summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-09-07 20:27:20 +1000
committerDave Airlie <airlied@redhat.com>2009-09-07 20:27:20 +1000
commit11670d3c93210793562748d83502ecbef4034765 (patch)
tree9e2c33c6249e26b05a2b5db87d4f4840e9049840
parent575dc34ee0de867ba83abf25998e0963bff451fa (diff)
parent01dfba93d9dfcf6d7abfc55ff5d9d6e76fa01ba0 (diff)
Merge intel drm-intel-next branch
Merge remote branch 'anholt/drm-intel-next' of ../anholt-2.6 into drm-next Conflicts: drivers/gpu/drm/i915/intel_display.c drivers/gpu/drm/i915/intel_drv.h drivers/gpu/drm/i915/intel_sdvo.c
-rw-r--r--Documentation/filesystems/9p.txt3
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile2
-rw-r--r--arch/arm/configs/kirkwood_defconfig2
-rw-r--r--arch/arm/mach-kirkwood/ts219-setup.c9
-rw-r--r--arch/arm/plat-orion/include/plat/gpio.h2
-rw-r--r--arch/avr32/boards/favr-32/setup.c4
-rw-r--r--arch/avr32/lib/memcpy.S16
-rw-r--r--arch/m68k/amiga/config.c6
-rw-r--r--arch/m68k/include/asm/motorola_pgalloc.h10
-rw-r--r--arch/m68k/include/asm/pgtable_mm.h3
-rw-r--r--arch/m68k/include/asm/unistd.h4
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68knommu/kernel/syscalltable.S2
-rw-r--r--arch/parisc/kernel/traps.c2
-rw-r--r--arch/powerpc/configs/ps3_defconfig211
-rw-r--r--arch/powerpc/platforms/ps3/time.c4
-rw-r--r--arch/s390/kernel/setup.c25
-rw-r--r--arch/sparc/configs/sparc32_defconfig74
-rw-r--r--arch/sparc/configs/sparc64_defconfig59
-rw-r--r--arch/sparc/include/asm/pgtable_64.h12
-rw-r--r--arch/sparc/kernel/ktlb.S42
-rw-r--r--arch/sparc/kernel/sun4d_smp.c22
-rw-r--r--arch/sparc/kernel/sun4m_smp.c26
-rw-r--r--arch/sparc/kernel/sys32.S4
-rw-r--r--arch/sparc/kernel/systbls_64.S4
-rw-r--r--arch/sparc/mm/fault_32.c7
-rw-r--r--arch/sparc/mm/fault_64.c7
-rw-r--r--arch/sparc/mm/init_64.c43
-rw-r--r--arch/sparc/mm/init_64.h7
-rw-r--r--arch/x86/boot/compressed/Makefile2
-rw-r--r--arch/x86/include/asm/pgtable.h12
-rw-r--r--arch/x86/kernel/apic/ipi.c3
-rw-r--r--arch/x86/kernel/apic/probe_64.c10
-rw-r--r--arch/x86/kernel/cpu/Makefile4
-rw-r--r--arch/x86/kernel/head_32.S8
-rw-r--r--arch/x86/kernel/process.c6
-rw-r--r--arch/x86/kernel/vmlinux.lds.S126
-rw-r--r--arch/x86/mm/init_64.c2
-rw-r--r--arch/x86/mm/pat.c3
-rw-r--r--arch/x86/mm/tlb.c21
-rw-r--r--arch/x86/xen/Makefile4
-rw-r--r--arch/x86/xen/enlighten.c24
-rw-r--r--drivers/acpi/acpica/exstorob.c12
-rw-r--r--drivers/acpi/processor_core.c6
-rw-r--r--drivers/acpi/processor_idle.c6
-rw-r--r--drivers/acpi/processor_thermal.c6
-rw-r--r--drivers/acpi/processor_throttling.c30
-rw-r--r--drivers/acpi/video.c7
-rw-r--r--drivers/ata/ata_piix.c14
-rw-r--r--drivers/char/agp/intel-agp.c8
-rw-r--r--drivers/char/tty_ldisc.c10
-rw-r--r--drivers/gpu/drm/drm_sysfs.c51
-rw-r--r--drivers/gpu/drm/i915/Makefile2
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c (renamed from drivers/gpu/drm/i915/i915_gem_debugfs.c)91
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c29
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c9
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h68
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c100
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c15
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c21
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h143
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c4
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c59
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c39
-rw-r--r--drivers/gpu/drm/i915/intel_display.c686
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c12
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h24
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c6
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c18
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c2
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c307
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c32
-rw-r--r--drivers/gpu/drm/radeon/r100.c10
-rw-r--r--drivers/gpu/drm/radeon/r300.c4
-rw-r--r--drivers/gpu/drm/radeon/r420.c13
-rw-r--r--drivers/gpu/drm/radeon/r520.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h5
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_reg.h5
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c3
-rw-r--r--drivers/i2c/busses/i2c-omap.c14
-rw-r--r--drivers/i2c/busses/i2c-stu300.c157
-rw-r--r--drivers/input/joydev.c68
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c1
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/tablet/wacom_sys.c43
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c17
-rw-r--r--drivers/leds/ledtrig-gpio.c24
-rw-r--r--drivers/macintosh/via-maciisi.c2
-rw-r--r--drivers/media/dvb/siano/Kconfig40
-rw-r--r--drivers/media/dvb/siano/Makefile9
-rw-r--r--drivers/media/dvb/siano/smsdvb.c44
-rw-r--r--drivers/media/dvb/siano/smssdio.c54
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c44
-rw-r--r--drivers/media/video/em28xx/em28xx.h1
-rw-r--r--drivers/media/video/gspca/Kconfig2
-rw-r--r--drivers/media/video/zr364xx.c2
-rw-r--r--drivers/mtd/nand/orion_nand.c2
-rw-r--r--drivers/net/Kconfig4
-rw-r--r--drivers/net/arm/w90p910_ether.c4
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/fec_mpc52xx.c5
-rw-r--r--drivers/net/ibm_newemac/core.c2
-rw-r--r--drivers/net/irda/au1k_ir.c4
-rw-r--r--drivers/net/irda/pxaficp_ir.c4
-rw-r--r--drivers/net/irda/sa1100_ir.c4
-rw-r--r--drivers/net/ixp2000/ixpdev.c5
-rw-r--r--drivers/net/macb.c7
-rw-r--r--drivers/net/mlx4/en_tx.c5
-rw-r--r--drivers/net/smc91x.c40
-rw-r--r--drivers/net/virtio_net.c61
-rw-r--r--drivers/net/wireless/orinoco/hw.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c14
-rw-r--r--drivers/net/yellowfin.c28
-rw-r--r--drivers/pci/pci-driver.c2
-rw-r--r--drivers/pci/pci.c2
-rw-r--r--drivers/platform/x86/toshiba_acpi.c1
-rw-r--r--drivers/platform/x86/wmi.c8
-rw-r--r--drivers/pps/pps.c2
-rw-r--r--drivers/s390/block/dasd.c2
-rw-r--r--drivers/s390/cio/device.c4
-rw-r--r--drivers/sbus/char/bbc_envctrl.c11
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c98
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h6
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c91
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c124
-rw-r--r--drivers/thermal/thermal_sys.c9
-rw-r--r--drivers/video/xen-fbfront.c8
-rw-r--r--drivers/watchdog/ar7_wdt.c2
-rw-r--r--fs/9p/v9fs.c21
-rw-r--r--fs/9p/v9fs.h1
-rw-r--r--fs/9p/vfs_inode.c126
-rw-r--r--fs/9p/vfs_super.c39
-rw-r--r--fs/afs/file.c18
-rw-r--r--fs/autofs4/expire.c2
-rw-r--r--fs/btrfs/inode.c21
-rw-r--r--fs/buffer.c7
-rw-r--r--fs/exec.c4
-rw-r--r--fs/ext3/Kconfig32
-rw-r--r--fs/ext3/super.c40
-rw-r--r--fs/hugetlbfs/inode.c20
-rw-r--r--fs/nfs/nfs4state.c4
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c33
-rw-r--r--fs/notify/inotify/inotify_user.c245
-rw-r--r--fs/ocfs2/alloc.c2
-rw-r--r--fs/ocfs2/dlm/dlmunlock.c4
-rw-r--r--fs/ocfs2/ocfs2_lockid.h1
-rw-r--r--fs/ocfs2/quota_global.c10
-rw-r--r--fs/ocfs2/super.c6
-rw-r--r--include/acpi/processor.h5
-rw-r--r--include/drm/radeon_drm.h4
-rw-r--r--include/linux/bitmap.h18
-rw-r--r--include/linux/cpumask.h20
-rw-r--r--include/linux/flex_array.h12
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/hugetlb.h6
-rw-r--r--include/linux/lmb.h2
-rw-r--r--include/linux/ucb1400.h4
-rw-r--r--include/net/pkt_sched.h4
-rw-r--r--init/main.c7
-rw-r--r--ipc/shm.c8
-rw-r--r--kernel/fork.c20
-rw-r--r--kernel/module.c10
-rw-r--r--kernel/perf_counter.c2
-rw-r--r--kernel/time/clockevents.c16
-rw-r--r--kernel/time/tick-broadcast.c7
-rw-r--r--kernel/time/timer_list.c2
-rw-r--r--kernel/trace/ftrace.c17
-rw-r--r--kernel/trace/trace.c12
-rw-r--r--lib/bitmap.c12
-rw-r--r--lib/dma-debug.c28
-rw-r--r--lib/flex_array.c41
-rw-r--r--lib/lmb.c2
-rw-r--r--mm/rmap.c1
-rw-r--r--mm/vmscan.c9
-rw-r--r--net/9p/client.c21
-rw-r--r--net/9p/error.c2
-rw-r--r--net/9p/trans_fd.c8
-rw-r--r--net/9p/trans_rdma.c9
-rw-r--r--net/9p/trans_virtio.c11
-rw-r--r--net/core/netpoll.c5
-rw-r--r--net/ipv4/ip_output.c2
-rw-r--r--net/ipv6/af_inet6.c4
-rw-r--r--net/llc/af_llc.c1
-rw-r--r--net/mac80211/key.c28
-rw-r--r--net/netfilter/xt_quota.c2
-rw-r--r--net/sched/sch_api.c10
-rw-r--r--net/sched/sch_cbq.c25
-rw-r--r--net/sunrpc/clnt.c1
-rw-r--r--security/integrity/ima/ima_crypto.c6
-rw-r--r--security/integrity/ima/ima_main.c4
-rw-r--r--sound/core/pcm_lib.c39
-rw-r--r--sound/pci/ali5451/ali5451.c18
-rw-r--r--sound/pci/hda/patch_analog.c6
-rw-r--r--sound/pci/hda/patch_realtek.c49
-rw-r--r--sound/pci/hda/patch_sigmatel.c6
-rw-r--r--sound/pci/hda/patch_via.c1
-rw-r--r--sound/pci/vx222/vx222_ops.c4
-rw-r--r--tools/perf/builtin-annotate.c7
-rw-r--r--tools/perf/builtin-report.c7
205 files changed, 3349 insertions, 1656 deletions
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index bf8080640eba..6208f55c44c3 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -123,6 +123,9 @@ available from the same CVS repository.
There are user and developer mailing lists available through the v9fs project
on sourceforge (http://sourceforge.net/projects/v9fs).
+A stand-alone version of the module (which should build for any 2.6 kernel)
+is available via (http://github.com/ericvh/9p-sac/tree/master)
+
News and other information is maintained on SWiK (http://swik.net/v9fs).
Bug reports may be issued through the kernel.org bugzilla
diff --git a/MAINTAINERS b/MAINTAINERS
index 60299a9a7adb..8dca9d89c6c1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2239,8 +2239,7 @@ S: Maintained
F: drivers/media/video/gspca/pac207.c
GSPCA SN9C20X SUBDRIVER
-P: Brian Johnson
-M: brijohn@gmail.com
+M: Brian Johnson <brijohn@gmail.com>
L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
diff --git a/Makefile b/Makefile
index abcfa85f8f82..25c615e57302 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 31
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc8
NAME = Man-Eating Seals of Antiquity
# *DOCUMENTATION*
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 0a1abb978d7e..af74cc2de8b6 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -629,7 +629,7 @@ CONFIG_SCSI_LOWLEVEL=y
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
-# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_AHCI=y
# CONFIG_SATA_SIL24 is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index 01aa213c0a6f..ec1a64f263d2 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -206,6 +206,15 @@ static void __init qnap_ts219_init(void)
}
+static int __init ts219_pci_init(void)
+{
+ if (machine_is_ts219())
+ kirkwood_pcie_init();
+
+ return 0;
+}
+subsys_initcall(ts219_pci_init);
+
MACHINE_START(TS219, "QNAP TS-119/TS-219")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
.phys_io = KIRKWOOD_REGS_PHYS_BASE,
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index 9646a94ed3d0..07c430fdc9ef 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -11,6 +11,8 @@
#ifndef __PLAT_GPIO_H
#define __PLAT_GPIO_H
+#include <linux/init.h>
+
/*
* GENERIC_GPIO primitives.
*/
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 46c9b0a224cf..75f19f47fb2f 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -72,6 +72,10 @@ static struct ads7846_platform_data ads7843_data = {
.debounce_max = 20,
.debounce_rep = 4,
.debounce_tol = 5,
+
+ .keep_vref_on = true,
+ .settle_delay_usecs = 500,
+ .penirq_recheck_delay_usecs = 100,
};
static struct spi_board_info __initdata spi1_board_info[] = {
diff --git a/arch/avr32/lib/memcpy.S b/arch/avr32/lib/memcpy.S
index 0abb26142b64..c2ca49d705af 100644
--- a/arch/avr32/lib/memcpy.S
+++ b/arch/avr32/lib/memcpy.S
@@ -24,8 +24,8 @@ memcpy:
brne 1f
/* At this point, "from" is word-aligned */
-2: sub r10, 4
- mov r9, r12
+2: mov r9, r12
+5: sub r10, 4
brlt 4f
3: ld.w r8, r11++
@@ -49,6 +49,7 @@ memcpy:
/* Handle unaligned "from" pointer */
1: sub r10, 4
+ movlt r9, r12
brlt 4b
add r10, r9
lsl r9, 2
@@ -59,4 +60,13 @@ memcpy:
st.b r12++, r8
ld.ub r8, r11++
st.b r12++, r8
- rjmp 2b
+ mov r8, r12
+ add pc, pc, r9
+ sub r8, 1
+ nop
+ sub r8, 1
+ nop
+ sub r8, 1
+ nop
+ mov r9, r8
+ rjmp 5b
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 6e562751ad51..6c74751c7b82 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -574,10 +574,11 @@ static int a2000_hwclk(int op, struct rtc_time *t)
tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
- while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+ while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt) {
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
udelay(70);
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+ --cnt;
}
if (!cnt)
@@ -649,10 +650,11 @@ static int amiga_set_clock_mmss(unsigned long nowtime)
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
- while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+ while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt) {
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
udelay(70);
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+ --cnt;
}
if (!cnt)
diff --git a/arch/m68k/include/asm/motorola_pgalloc.h b/arch/m68k/include/asm/motorola_pgalloc.h
index 15ee4c74a9f0..2f02f264e694 100644
--- a/arch/m68k/include/asm/motorola_pgalloc.h
+++ b/arch/m68k/include/asm/motorola_pgalloc.h
@@ -36,12 +36,10 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addres
return NULL;
pte = kmap(page);
- if (pte) {
- __flush_page_to_ram(pte);
- flush_tlb_kernel_page(pte);
- nocache_page(pte);
- }
- kunmap(pte);
+ __flush_page_to_ram(pte);
+ flush_tlb_kernel_page(pte);
+ nocache_page(pte);
+ kunmap(page);
pgtable_page_ctor(page);
return page;
}
diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h
index 0b604f0f192d..fe60e1abaee8 100644
--- a/arch/m68k/include/asm/pgtable_mm.h
+++ b/arch/m68k/include/asm/pgtable_mm.h
@@ -135,8 +135,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#endif
#ifndef __ASSEMBLY__
-#include <asm-generic/pgtable.h>
-
/*
* Macro to mark a page protection value as "uncacheable".
*/
@@ -154,6 +152,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
? (__pgprot((pgprot_val(prot) & _CACHEMASK040) | _PAGE_NOCACHE_S)) \
: (prot)))
+#include <asm-generic/pgtable.h>
#endif /* !__ASSEMBLY__ */
/*
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index aa29a8640f74..946d8691f2b0 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -334,10 +334,12 @@
#define __NR_inotify_init1 328
#define __NR_preadv 329
#define __NR_pwritev 330
+#define __NR_rt_tgsigqueueinfo 331
+#define __NR_perf_counter_open 332
#ifdef __KERNEL__
-#define NR_syscalls 331
+#define NR_syscalls 333
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 8744f60c07a9..c3735cd6207e 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -755,4 +755,6 @@ sys_call_table:
.long sys_inotify_init1
.long sys_preadv
.long sys_pwritev /* 330 */
+ .long sys_rt_tgsigqueueinfo
+ .long sys_perf_counter_open
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index c0b8782832fd..0ae123e08985 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -349,6 +349,8 @@ ENTRY(sys_call_table)
.long sys_inotify_init1
.long sys_preadv
.long sys_pwritev /* 330 */
+ .long sys_rt_tgsigqueueinfo
+ .long sys_perf_counter_open
.rept NR_syscalls-(.-sys_call_table)/4
.long sys_ni_syscall
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 528f0ff9b273..8b58bf0b7d5a 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -532,7 +532,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
/* Kill the user process later */
regs->iaoq[0] = 0 | 3;
regs->iaoq[1] = regs->iaoq[0] + 4;
- regs->iasq[0] = regs->iasq[0] = regs->sr[7];
+ regs->iasq[0] = regs->iasq[1] = regs->sr[7];
regs->gr[0] &= ~PSW_B;
return;
}
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index e28e65e7a0e1..7de127e4ceef 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,13 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc5
-# Fri May 15 10:37:00 2009
+# Linux kernel version: 2.6.31-rc7
+# Mon Aug 24 17:38:50 2009
#
CONFIG_PPC64=y
#
# Processor support
#
+CONFIG_PPC_BOOK3S_64=y
CONFIG_PPC_BOOK3S=y
# CONFIG_POWER4_ONLY is not set
CONFIG_POWER3=y
@@ -20,6 +21,7 @@ CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_64=y
CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_64BIT=y
@@ -31,6 +33,7 @@ CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -41,7 +44,6 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_PPC=y
@@ -62,6 +64,7 @@ CONFIG_DTC=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
#
# General setup
@@ -113,7 +116,6 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -126,7 +128,14 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
@@ -145,6 +154,11 @@ CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
@@ -210,7 +224,7 @@ CONFIG_PPC_CELL=y
#
# Cell Broadband Engine options
#
-CONFIG_SPU_FS=y
+CONFIG_SPU_FS=m
CONFIG_SPU_FS_64K_LS=y
# CONFIG_SPU_TRACE is not set
CONFIG_SPU_BASE=y
@@ -255,6 +269,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
# CONFIG_IOMMU_VMERGE is not set
CONFIG_IOMMU_HELPER=y
+# CONFIG_SWIOTLB is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -285,9 +300,9 @@ CONFIG_MIGRATION=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
-CONFIG_UNEVICTABLE_LRU=y
CONFIG_HAVE_MLOCK=y
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_ARCH_MEMORY_PROBE=y
CONFIG_PPC_HAS_HASH_64K=y
CONFIG_PPC_4K_PAGES=y
@@ -399,6 +414,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -433,11 +449,14 @@ CONFIG_BT_HCIBTUSB=m
CONFIG_WIRELESS=y
CONFIG_CFG80211=m
# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
# CONFIG_WIRELESS_EXT_SYSFS is not set
# CONFIG_LIB80211 is not set
CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
#
# Rate control algorithm selection
@@ -447,7 +466,6 @@ CONFIG_MAC80211_RC_PID=y
CONFIG_MAC80211_RC_DEFAULT_PID=y
# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
CONFIG_MAC80211_RC_DEFAULT="pid"
-# CONFIG_MAC80211_MESH is not set
# CONFIG_MAC80211_LEDS is not set
# CONFIG_MAC80211_DEBUGFS is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
@@ -472,77 +490,7 @@ CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=0
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_TESTS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# LPDDR flash memory drivers
-#
-# CONFIG_MTD_LPDDR is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
+# CONFIG_MTD is not set
CONFIG_OF_DEVICE=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
@@ -590,10 +538,6 @@ CONFIG_BLK_DEV_SR=y
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_CHR_DEV_SG=m
# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
@@ -626,7 +570,6 @@ CONFIG_BLK_DEV_DM=m
# CONFIG_DM_UEVENT is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -646,10 +589,11 @@ CONFIG_MII=m
# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
CONFIG_NETDEV_1000=y
CONFIG_GELIC_NET=y
CONFIG_GELIC_WIRELESS=y
-CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE=y
+# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
# CONFIG_NETDEV_10000 is not set
#
@@ -669,8 +613,7 @@ CONFIG_WLAN_80211=y
# CONFIG_HOSTAP is not set
# CONFIG_B43 is not set
# CONFIG_B43LEGACY is not set
-CONFIG_ZD1211RW=m
-# CONFIG_ZD1211RW_DEBUG is not set
+# CONFIG_ZD1211RW is not set
# CONFIG_RT2X00 is not set
#
@@ -682,7 +625,7 @@ CONFIG_ZD1211RW=m
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=m
+# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
@@ -693,10 +636,11 @@ CONFIG_USB_NET_AX8817X=m
# CONFIG_USB_NET_GL620A is not set
# CONFIG_USB_NET_NET1080 is not set
# CONFIG_USB_NET_PLUSB is not set
-CONFIG_USB_NET_MCS7830=m
+# CONFIG_USB_NET_MCS7830 is not set
# CONFIG_USB_NET_RNDIS_HOST is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
# CONFIG_WAN is not set
CONFIG_PPP=m
CONFIG_PPP_MULTILINK=y
@@ -771,8 +715,7 @@ CONFIG_DEVKMEM=y
#
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_LEGACY_PTYS is not set
# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
@@ -782,6 +725,11 @@ CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
@@ -805,22 +753,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
#
# Graphics support
@@ -898,6 +831,11 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
# CONFIG_SND_DRIVERS is not set
CONFIG_SND_PPC=y
CONFIG_SND_PS3=m
@@ -930,29 +868,34 @@ CONFIG_USB_HIDDEV=y
# Special HID drivers
#
# CONFIG_HID_A4TECH is not set
-# CONFIG_HID_APPLE is not set
-# CONFIG_HID_BELKIN is not set
-# CONFIG_HID_CHERRY is not set
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
# CONFIG_HID_CHICONY is not set
# CONFIG_HID_CYPRESS is not set
-# CONFIG_DRAGONRISE_FF is not set
-# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_DRAGONRISE is not set
+CONFIG_HID_EZKEY=m
# CONFIG_HID_KYE is not set
# CONFIG_HID_GYRATION is not set
# CONFIG_HID_KENSINGTON is not set
-# CONFIG_HID_LOGITECH is not set
-# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
# CONFIG_HID_MONTEREY is not set
# CONFIG_HID_NTRIG is not set
# CONFIG_HID_PANTHERLORD is not set
# CONFIG_HID_PETALYNX is not set
# CONFIG_HID_SAMSUNG is not set
CONFIG_HID_SONY=m
-# CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SUNPLUS=m
+# CONFIG_HID_GREENASIA is not set
+CONFIG_HID_SMARTJOYPLUS=m
+# CONFIG_SMARTJOYPLUS_FF is not set
# CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -988,6 +931,8 @@ CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
# CONFIG_USB_OHCI_HCD_PPC_OF is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1115,6 +1060,10 @@ CONFIG_RTC_DRV_PS3=m
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
# CONFIG_STAGING is not set
#
@@ -1141,11 +1090,12 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -1205,7 +1155,6 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
@@ -1222,6 +1171,7 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
@@ -1359,7 +1309,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1374,31 +1323,21 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_TRACING=y
CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FTRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
CONFIG_PRINT_STACK_DEPTH=64
CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index b178a1e66c91..40b5cb433005 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <asm/firmware.h>
#include <asm/rtc.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
@@ -84,6 +85,9 @@ static int __init ps3_rtc_init(void)
{
struct platform_device *pdev;
+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return -ENODEV;
+
pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 9717717c6fea..cbb897bc50bd 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -154,6 +154,20 @@ static int __init condev_setup(char *str)
__setup("condev=", condev_setup);
+static void __init set_preferred_console(void)
+{
+ if (MACHINE_IS_KVM) {
+ add_preferred_console("hvc", 0, NULL);
+ s390_virtio_console_init();
+ return;
+ }
+
+ if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
+ add_preferred_console("ttyS", 0, NULL);
+ if (CONSOLE_IS_3270)
+ add_preferred_console("tty3270", 0, NULL);
+}
+
static int __init conmode_setup(char *str)
{
#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
@@ -168,6 +182,7 @@ static int __init conmode_setup(char *str)
if (strncmp(str, "3270", 5) == 0)
SET_CONSOLE_3270;
#endif
+ set_preferred_console();
return 1;
}
@@ -780,9 +795,6 @@ static void __init setup_hwcaps(void)
void __init
setup_arch(char **cmdline_p)
{
- /* set up preferred console */
- add_preferred_console("ttyS", 0, NULL);
-
/*
* print what head.S has found out about the machine
*/
@@ -802,11 +814,9 @@ setup_arch(char **cmdline_p)
if (MACHINE_IS_VM)
pr_info("Linux is running as a z/VM "
"guest operating system in 64-bit mode\n");
- else if (MACHINE_IS_KVM) {
+ else if (MACHINE_IS_KVM)
pr_info("Linux is running under KVM in 64-bit mode\n");
- add_preferred_console("hvc", 0, NULL);
- s390_virtio_console_init();
- } else
+ else
pr_info("Linux is running natively in 64-bit mode\n");
#endif /* CONFIG_64BIT */
@@ -851,6 +861,7 @@ setup_arch(char **cmdline_p)
/* Setup default console */
conmode_default();
+ set_preferred_console();
/* Setup zfcpdump support */
setup_zfcpdump(console_devno);
diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig
index 8bcd27af724b..a0f62a808edb 100644
--- a/arch/sparc/configs/sparc32_defconfig
+++ b/arch/sparc/configs/sparc32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Fri Apr 17 04:04:46 2009
+# Linux kernel version: 2.6.31-rc1
+# Tue Aug 18 23:45:52 2009
#
# CONFIG_64BIT is not set
CONFIG_SPARC=y
@@ -17,6 +17,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
#
# General setup
@@ -74,7 +75,6 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -87,8 +87,13 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
+
+#
+# Performance Counters
+#
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
@@ -97,6 +102,10 @@ CONFIG_SLAB=y
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
@@ -109,7 +118,7 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,9 +163,9 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
-CONFIG_UNEVICTABLE_LRU=y
CONFIG_HAVE_MLOCK=y
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_SUN_PM=y
# CONFIG_SPARC_LED is not set
CONFIG_SERIAL_CONSOLE=y
@@ -264,6 +273,7 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -281,7 +291,11 @@ CONFIG_WIRELESS=y
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -335,6 +349,7 @@ CONFIG_MISC_DEVICES=y
# EEPROM support
#
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -358,10 +373,6 @@ CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_CHR_DEV_SG=m
# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
@@ -379,6 +390,7 @@ CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -387,6 +399,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
@@ -401,7 +414,6 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -426,13 +438,16 @@ CONFIG_SCSI_SUNESP=y
#
#
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -463,6 +478,7 @@ CONFIG_SUNQE=m
# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
@@ -482,6 +498,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
@@ -629,6 +646,11 @@ CONFIG_HW_RANDOM=m
CONFIG_DEVPORT=y
# CONFIG_I2C is not set
# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
@@ -668,22 +690,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
#
# Graphics support
@@ -776,6 +783,10 @@ CONFIG_RTC_DRV_M48T59=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
# CONFIG_STAGING is not set
#
@@ -799,10 +810,12 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -985,6 +998,7 @@ CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_TESTS=y
# CONFIG_KGDB_TESTS_ON_BOOT is not set
+# CONFIG_KMEMCHECK is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_STACK_DEBUG is not set
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 0123a4c596ce..fdddf7a6f725 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30
-# Tue Jun 16 04:59:36 2009
+# Linux kernel version: 2.6.31-rc1
+# Tue Aug 18 23:56:02 2009
#
CONFIG_64BIT=y
CONFIG_SPARC=y
@@ -26,6 +26,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
#
# General setup
@@ -119,6 +120,11 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
@@ -204,7 +210,6 @@ CONFIG_MIGRATION=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1
-CONFIG_UNEVICTABLE_LRU=y
CONFIG_HAVE_MLOCK=y
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=8192
@@ -410,6 +415,7 @@ CONFIG_MISC_DEVICES=y
#
# CONFIG_EEPROM_AT24 is not set
# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_CB710_CORE is not set
CONFIG_HAVE_IDE=y
@@ -562,6 +568,7 @@ CONFIG_BLK_DEV_DM=m
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
+# CONFIG_DM_LOG_USERSPACE is not set
CONFIG_DM_ZERO=m
# CONFIG_DM_MULTIPATH is not set
# CONFIG_DM_DELAY is not set
@@ -573,7 +580,11 @@ CONFIG_DM_ZERO=m
#
#
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
@@ -667,6 +678,7 @@ CONFIG_E1000E=m
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
CONFIG_BNX2=m
+# CONFIG_CNIC is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
@@ -773,6 +785,7 @@ CONFIG_MOUSE_SERIAL=y
# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_BCM5974 is not set
# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
@@ -870,6 +883,7 @@ CONFIG_I2C_ALGOBIT=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
+# CONFIG_I2C_DESIGNWARE is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set
@@ -898,13 +912,17 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
@@ -959,6 +977,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
@@ -994,23 +1013,9 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
# CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
#
# Graphics support
@@ -1284,7 +1289,6 @@ CONFIG_USB=y
#
# Miscellaneous USB options
#
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -1296,6 +1300,7 @@ CONFIG_USB_DEVICEFS=y
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1374,7 +1379,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
@@ -1420,6 +1424,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
#
# SPI RTC drivers
@@ -1448,6 +1453,10 @@ CONFIG_RTC_DRV_STARFIRE=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
# CONFIG_STAGING is not set
#
@@ -1480,11 +1489,11 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
@@ -1560,7 +1569,7 @@ CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
CONFIG_SUN_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index b049abf9902f..0ff92fa22064 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -726,11 +726,17 @@ extern unsigned long pte_file(pte_t);
extern pte_t pgoff_to_pte(unsigned long);
#define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL)
-extern unsigned long *sparc64_valid_addr_bitmap;
+extern unsigned long sparc64_valid_addr_bitmap[];
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr) \
- (test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
+static inline bool kern_addr_valid(unsigned long addr)
+{
+ unsigned long paddr = __pa(addr);
+
+ if ((paddr >> 41UL) != 0UL)
+ return false;
+ return test_bit(paddr >> 22, sparc64_valid_addr_bitmap);
+}
extern int page_in_phys_avail(unsigned long paddr);
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index cef8defcd7a9..3ea6e8cde8c5 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -151,12 +151,46 @@ kvmap_dtlb_4v:
* Must preserve %g1 and %g6 (TAG).
*/
kvmap_dtlb_tsb4m_miss:
- sethi %hi(kpte_linear_bitmap), %g2
- or %g2, %lo(kpte_linear_bitmap), %g2
+ /* Clear the PAGE_OFFSET top virtual bits, shift
+ * down to get PFN, and make sure PFN is in range.
+ */
+ sllx %g4, 21, %g5
- /* Clear the PAGE_OFFSET top virtual bits, then shift
- * down to get a 256MB physical address index.
+ /* Check to see if we know about valid memory at the 4MB
+ * chunk this physical address will reside within.
*/
+ srlx %g5, 21 + 41, %g2
+ brnz,pn %g2, kvmap_dtlb_longpath
+ nop
+
+ /* This unconditional branch and delay-slot nop gets patched
+ * by the sethi sequence once the bitmap is properly setup.
+ */
+ .globl valid_addr_bitmap_insn
+valid_addr_bitmap_insn:
+ ba,pt %xcc, 2f
+ nop
+ .subsection 2
+ .globl valid_addr_bitmap_patch
+valid_addr_bitmap_patch:
+ sethi %hi(sparc64_valid_addr_bitmap), %g7
+ or %g7, %lo(sparc64_valid_addr_bitmap), %g7
+ .previous
+
+ srlx %g5, 21 + 22, %g2
+ srlx %g2, 6, %g5
+ and %g2, 63, %g2
+ sllx %g5, 3, %g5
+ ldx [%g7 + %g5], %g5
+ mov 1, %g7
+ sllx %g7, %g2, %g7
+ andcc %g5, %g7, %g0
+ be,pn %xcc, kvmap_dtlb_longpath
+
+2: sethi %hi(kpte_linear_bitmap), %g2
+ or %g2, %lo(kpte_linear_bitmap), %g2
+
+ /* Get the 256MB physical address index. */
sllx %g4, 21, %g5
mov 1, %g7
srlx %g5, 21 + 28, %g5
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 54fb02468f0d..68791cad7b74 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -162,9 +162,6 @@ extern void cpu_panic(void);
*/
extern struct linux_prom_registers smp_penguin_ctable;
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
void __init smp4d_boot_cpus(void)
{
@@ -235,25 +232,6 @@ void __init smp4d_smp_done(void)
*prev = first;
local_flush_cache_all();
- /* Free unneeded trap tables */
- ClearPageReserved(virt_to_page(trapbase_cpu1));
- init_page_count(virt_to_page(trapbase_cpu1));
- free_page((unsigned long)trapbase_cpu1);
- totalram_pages++;
- num_physpages++;
-
- ClearPageReserved(virt_to_page(trapbase_cpu2));
- init_page_count(virt_to_page(trapbase_cpu2));
- free_page((unsigned long)trapbase_cpu2);
- totalram_pages++;
- num_physpages++;
-
- ClearPageReserved(virt_to_page(trapbase_cpu3));
- init_page_count(virt_to_page(trapbase_cpu3));
- free_page((unsigned long)trapbase_cpu3);
- totalram_pages++;
- num_physpages++;
-
/* Ok, they are spinning and ready to go. */
smp_processors_ready = 1;
sun4d_distribute_irqs();
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 960b113d0006..762d6eedd944 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -121,9 +121,6 @@ void __cpuinit smp4m_callin(void)
*/
extern struct linux_prom_registers smp_penguin_ctable;
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
void __init smp4m_boot_cpus(void)
{
@@ -193,29 +190,6 @@ void __init smp4m_smp_done(void)
*prev = first;
local_flush_cache_all();
- /* Free unneeded trap tables */
- if (!cpu_isset(1, cpu_present_map)) {
- ClearPageReserved(virt_to_page(trapbase_cpu1));
- init_page_count(virt_to_page(trapbase_cpu1));
- free_page((unsigned long)trapbase_cpu1);
- totalram_pages++;
- num_physpages++;
- }
- if (!cpu_isset(2, cpu_present_map)) {
- ClearPageReserved(virt_to_page(trapbase_cpu2));
- init_page_count(virt_to_page(trapbase_cpu2));
- free_page((unsigned long)trapbase_cpu2);
- totalram_pages++;
- num_physpages++;
- }
- if (!cpu_isset(3, cpu_present_map)) {
- ClearPageReserved(virt_to_page(trapbase_cpu3));
- init_page_count(virt_to_page(trapbase_cpu3));
- free_page((unsigned long)trapbase_cpu3);
- totalram_pages++;
- num_physpages++;
- }
-
/* Ok, they are spinning and ready to go. */
}
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index f061c4dda9ef..aed94869ad6a 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -134,10 +134,12 @@ SIGN1(sys32_getpeername, sys_getpeername, %o0)
SIGN1(sys32_getsockname, sys_getsockname, %o0)
SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
-SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_splice, sys_splice, %o0, %o2)
SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
SIGN2(sys32_tee, sys_tee, %o0, %o1)
SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
+SIGN1(sys32_truncate, sys_truncate, %o1)
+SIGN1(sys32_ftruncate, sys_ftruncate, %o1)
.globl sys32_mmap2
sys32_mmap2:
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 6b3ee88e253c..2ee7250ba7ae 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -43,8 +43,8 @@ sys_call_table32:
/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
.word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
- .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
-/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
+ .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys32_truncate
+/*130*/ .word sys32_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
.word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index a5e30c642ee3..b99f81c4906f 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -319,9 +319,10 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- printk("VM: killing process %s\n", tsk->comm);
- if (from_user)
- do_group_exit(SIGKILL);
+ if (from_user) {
+ pagefault_out_of_memory();
+ return;
+ }
goto no_context;
do_sigbus:
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index e5620b27c8bf..43b0da96a4fb 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -447,9 +447,10 @@ handle_kernel_fault:
out_of_memory:
insn = get_fault_insn(regs, insn);
up_read(&mm->mmap_sem);
- printk("VM: killing process %s\n", current->comm);
- if (!(regs->tstate & TSTATE_PRIV))
- do_group_exit(SIGKILL);
+ if (!(regs->tstate & TSTATE_PRIV)) {
+ pagefault_out_of_memory();
+ return;
+ }
goto handle_kernel_fault;
intr_or_no_mm:
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index ed6be6ba2f4e..a70a5e1904d9 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -145,7 +145,8 @@ static void __init read_obp_memory(const char *property,
cmp_p64, NULL);
}
-unsigned long *sparc64_valid_addr_bitmap __read_mostly;
+unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES /
+ sizeof(unsigned long)];
EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
/* Kernel physical address base and size in bytes. */
@@ -1874,7 +1875,7 @@ static int pavail_rescan_ents __initdata;
* memory list again, and make sure it provides at least as much
* memory as 'pavail' does.
*/
-static void __init setup_valid_addr_bitmap_from_pavail(void)
+static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap)
{
int i;
@@ -1897,8 +1898,7 @@ static void __init setup_valid_addr_bitmap_from_pavail(void)
if (new_start <= old_start &&
new_end >= (old_start + PAGE_SIZE)) {
- set_bit(old_start >> 22,
- sparc64_valid_addr_bitmap);
+ set_bit(old_start >> 22, bitmap);
goto do_next_page;
}
}
@@ -1919,20 +1919,21 @@ static void __init setup_valid_addr_bitmap_from_pavail(void)
}
}
+static void __init patch_tlb_miss_handler_bitmap(void)
+{
+ extern unsigned int valid_addr_bitmap_insn[];
+ extern unsigned int valid_addr_bitmap_patch[];
+
+ valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1];
+ mb();
+ valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0];
+ flushi(&valid_addr_bitmap_insn[0]);
+}
+
void __init mem_init(void)
{
unsigned long codepages, datapages, initpages;
unsigned long addr, last;
- int i;
-
- i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
- i += 1;
- sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3);
- if (sparc64_valid_addr_bitmap == NULL) {
- prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
- prom_halt();
- }
- memset(sparc64_valid_addr_bitmap, 0, i << 3);
addr = PAGE_OFFSET + kern_base;
last = PAGE_ALIGN(kern_size) + addr;
@@ -1941,15 +1942,19 @@ void __init mem_init(void)
addr += PAGE_SIZE;
}
- setup_valid_addr_bitmap_from_pavail();
+ setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap);
+ patch_tlb_miss_handler_bitmap();
high_memory = __va(last_valid_pfn << PAGE_SHIFT);
#ifdef CONFIG_NEED_MULTIPLE_NODES
- for_each_online_node(i) {
- if (NODE_DATA(i)->node_spanned_pages != 0) {
- totalram_pages +=
- free_all_bootmem_node(NODE_DATA(i));
+ {
+ int i;
+ for_each_online_node(i) {
+ if (NODE_DATA(i)->node_spanned_pages != 0) {
+ totalram_pages +=
+ free_all_bootmem_node(NODE_DATA(i));
+ }
}
}
#else
diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h
index 16063870a489..c2f772dbd556 100644
--- a/arch/sparc/mm/init_64.h
+++ b/arch/sparc/mm/init_64.h
@@ -5,10 +5,13 @@
* marked non-static so that assembler code can get at them.
*/
-#define MAX_PHYS_ADDRESS (1UL << 42UL)
-#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL)
+#define MAX_PHYS_ADDRESS (1UL << 41UL)
+#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL)
#define KPTE_BITMAP_BYTES \
((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8)
+#define VALID_ADDR_BITMAP_CHUNK_SZ (4UL * 1024UL * 1024UL)
+#define VALID_ADDR_BITMAP_BYTES \
+ ((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
extern unsigned long kern_linear_pte_xor[2];
extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index e2ff504b4ddc..f8ed0658404c 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -4,7 +4,7 @@
# create a compressed vmlinux image from the original vmlinux
#
-targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 3cc06e3fceb8..16748077559a 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -2,6 +2,7 @@
#define _ASM_X86_PGTABLE_H
#include <asm/page.h>
+#include <asm/e820.h>
#include <asm/pgtable_types.h>
@@ -269,10 +270,17 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
#define canon_pgprot(p) __pgprot(massage_pgprot(p))
-static inline int is_new_memtype_allowed(unsigned long flags,
- unsigned long new_flags)
+static inline int is_new_memtype_allowed(u64 paddr, unsigned long size,
+ unsigned long flags,
+ unsigned long new_flags)
{
/*
+ * PAT type is always WB for ISA. So no need to check.
+ */
+ if (is_ISA_range(paddr, paddr + size - 1))
+ return 1;
+
+ /*
* Certain new memtypes are not allowed with certain
* requested memtype:
* - request is uncached, return cannot be write-back
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c
index dbf5445727a9..6ef00ba4c886 100644
--- a/arch/x86/kernel/apic/ipi.c
+++ b/arch/x86/kernel/apic/ipi.c
@@ -106,6 +106,9 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
unsigned long mask = cpumask_bits(cpumask)[0];
unsigned long flags;
+ if (WARN_ONCE(!mask, "empty IPI mask"))
+ return;
+
local_irq_save(flags);
WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
__default_send_IPI_dest_field(mask, vector, apic->dest_logical);
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c
index bc3e880f9b82..fcec2f1d34a1 100644
--- a/arch/x86/kernel/apic/probe_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -44,6 +44,11 @@ static struct apic *apic_probe[] __initdata = {
NULL,
};
+static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
+{
+ return hard_smp_processor_id() >> index_msb;
+}
+
/*
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
*/
@@ -69,6 +74,11 @@ void __init default_setup_apic_routing(void)
printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
}
+ if (is_vsmp_box()) {
+ /* need to update phys_pkg_id */
+ apic->phys_pkg_id = apicid_phys_pkg_id;
+ }
+
/*
* Now that apic routing model is selected, configure the
* fault handling for intr remapping.
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 3efcb2b96a15..c1f253dac155 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -7,6 +7,10 @@ ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_common.o = -pg
endif
+# Make sure load_percpu_segment has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_common.o := $(nostackp)
+
obj-y := intel_cacheinfo.o addon_cpuid_features.o
obj-y += proc.o capflags.o powerflags.o common.o
obj-y += vmware.o hypervisor.o
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 0d98a01cbdb2..cc827ac9e8d3 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -261,9 +261,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
* which will be freed later
*/
-#ifndef CONFIG_HOTPLUG_CPU
-.section .init.text,"ax",@progbits
-#endif
+__CPUINIT
#ifdef CONFIG_SMP
ENTRY(startup_32_smp)
@@ -602,11 +600,7 @@ ignore_int:
#endif
iret
-#ifndef CONFIG_HOTPLUG_CPU
- __CPUINITDATA
-#else
__REFDATA
-#endif
.align 4
ENTRY(initial_code)
.long i386_start_kernel
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 994dd6a4a2a0..071166a4ba83 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -519,16 +519,12 @@ static void c1e_idle(void)
if (!cpumask_test_cpu(cpu, c1e_mask)) {
cpumask_set_cpu(cpu, c1e_mask);
/*
- * Force broadcast so ACPI can not interfere. Needs
- * to run with interrupts enabled as it uses
- * smp_function_call.
+ * Force broadcast so ACPI can not interfere.
*/
- local_irq_enable();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
&cpu);
printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
cpu);
- local_irq_disable();
}
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 78d185d797de..9fc178255c04 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -46,11 +46,10 @@ PHDRS {
data PT_LOAD FLAGS(7); /* RWE */
#ifdef CONFIG_X86_64
user PT_LOAD FLAGS(7); /* RWE */
- data.init PT_LOAD FLAGS(7); /* RWE */
#ifdef CONFIG_SMP
percpu PT_LOAD FLAGS(7); /* RWE */
#endif
- data.init2 PT_LOAD FLAGS(7); /* RWE */
+ init PT_LOAD FLAGS(7); /* RWE */
#endif
note PT_NOTE FLAGS(0); /* ___ */
}
@@ -103,65 +102,43 @@ SECTIONS
__stop___ex_table = .;
} :text = 0x9090
- RODATA
+ RO_DATA(PAGE_SIZE)
/* Data */
- . = ALIGN(PAGE_SIZE);
.data : AT(ADDR(.data) - LOAD_OFFSET) {
/* Start of data section */
_sdata = .;
- DATA_DATA
- CONSTRUCTORS
- } :data
+
+ /* init_task */
+ INIT_TASK_DATA(THREAD_SIZE)
#ifdef CONFIG_X86_32
- /* 32 bit has nosave before _edata */
- . = ALIGN(PAGE_SIZE);
- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
- }
+ /* 32 bit has nosave before _edata */
+ NOSAVE_DATA
#endif
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
- *(.data.page_aligned)
+ PAGE_ALIGNED_DATA(PAGE_SIZE)
*(.data.idt)
- }
-#ifdef CONFIG_X86_32
- . = ALIGN(32);
-#else
- . = ALIGN(PAGE_SIZE);
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-#endif
- .data.cacheline_aligned :
- AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
- *(.data.cacheline_aligned)
- }
+ CACHELINE_ALIGNED_DATA(CONFIG_X86_L1_CACHE_BYTES)
- /* rarely changed data like cpu maps */
-#ifdef CONFIG_X86_32
- . = ALIGN(32);
-#else
- . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
-#endif
- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
- *(.data.read_mostly)
+ DATA_DATA
+ CONSTRUCTORS
+
+ /* rarely changed data like cpu maps */
+ READ_MOSTLY_DATA(CONFIG_X86_INTERNODE_CACHE_BYTES)
/* End of data section */
_edata = .;
- }
+ } :data
#ifdef CONFIG_X86_64
#define VSYSCALL_ADDR (-10*1024*1024)
-#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + \
- SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + \
- SIZEOF(.data.read_mostly) + 4095) & ~(4095))
+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data) + SIZEOF(.data) + \
+ PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
+#define VSYSCALL_VIRT_ADDR ((ADDR(.data) + SIZEOF(.data) + \
+ PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
@@ -227,35 +204,29 @@ SECTIONS
#endif /* CONFIG_X86_64 */
- /* init_task */
- . = ALIGN(THREAD_SIZE);
- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
- *(.data.init_task)
+ /* Init code and data - will be freed after init */
+ . = ALIGN(PAGE_SIZE);
+ .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
+ __init_begin = .; /* paired with __init_end */
}
-#ifdef CONFIG_X86_64
- :data.init
-#endif
+#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
/*
- * smp_locks might be freed after init
- * start/end must be page aligned
+ * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the
+ * output PHDR, so the next output section - .init.text - should
+ * start another segment - init.
*/
- . = ALIGN(PAGE_SIZE);
- .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
- __smp_locks = .;
- *(.smp_locks)
- __smp_locks_end = .;
- . = ALIGN(PAGE_SIZE);
- }
+ PERCPU_VADDR(0, :percpu)
+#endif
- /* Init code and data - will be freed after init */
- . = ALIGN(PAGE_SIZE);
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
- __init_begin = .; /* paired with __init_end */
_sinittext = .;
INIT_TEXT
_einittext = .;
}
+#ifdef CONFIG_X86_64
+ :init
+#endif
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
INIT_DATA
@@ -326,17 +297,7 @@ SECTIONS
}
#endif
-#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
- /*
- * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the
- * output PHDR, so the next output section - __data_nosave - should
- * start another section data.init2. Also, pda should be at the head of
- * percpu area. Preallocate it and define the percpu offset symbol
- * so that it can be accessed as a percpu variable.
- */
- . = ALIGN(PAGE_SIZE);
- PERCPU_VADDR(0, :percpu)
-#else
+#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
PERCPU(PAGE_SIZE)
#endif
@@ -347,15 +308,22 @@ SECTIONS
__init_end = .;
}
+ /*
+ * smp_locks might be freed after init
+ * start/end must be page aligned
+ */
+ . = ALIGN(PAGE_SIZE);
+ .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+ __smp_locks = .;
+ *(.smp_locks)
+ __smp_locks_end = .;
+ . = ALIGN(PAGE_SIZE);
+ }
+
#ifdef CONFIG_X86_64
.data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
- } :data.init2
- /* use another section data.init2, see PERCPU_VADDR() above */
+ NOSAVE_DATA
+ }
#endif
/* BSS */
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 6176fe8f29e0..ea56b8cbb6a6 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -796,7 +796,7 @@ int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
return ret;
#else
- reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ reserve_bootmem(phys, len, flags);
#endif
if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index e6718bb28065..352aa9e927e2 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -623,7 +623,8 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
return ret;
if (flags != want_flags) {
- if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
+ if (strict_prot ||
+ !is_new_memtype_allowed(paddr, size, want_flags, flags)) {
free_memtype(paddr, paddr + size);
printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
" for %Lx-%Lx, got %s\n",
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 821e97017e95..c814e144a3f0 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -183,18 +183,17 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask,
f->flush_mm = mm;
f->flush_va = va;
- cpumask_andnot(to_cpumask(f->flush_cpumask),
- cpumask, cpumask_of(smp_processor_id()));
-
- /*
- * We have to send the IPI only to
- * CPUs affected.
- */
- apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
- INVALIDATE_TLB_VECTOR_START + sender);
+ if (cpumask_andnot(to_cpumask(f->flush_cpumask), cpumask, cpumask_of(smp_processor_id()))) {
+ /*
+ * We have to send the IPI only to
+ * CPUs affected.
+ */
+ apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
+ INVALIDATE_TLB_VECTOR_START + sender);
- while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
- cpu_relax();
+ while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
+ cpu_relax();
+ }
f->flush_mm = NULL;
f->flush_va = 0;
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 172438f86a02..7410640db173 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -5,6 +5,10 @@ CFLAGS_REMOVE_time.o = -pg
CFLAGS_REMOVE_irq.o = -pg
endif
+# Make sure early boot has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_enlighten.o := $(nostackp)
+
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
time.o xen-asm.o xen-asm_$(BITS).o \
grant-table.o suspend.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 0a1700a2be9c..eb33aaa8415d 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -215,6 +215,7 @@ static __init void xen_init_cpuid_mask(void)
(1 << X86_FEATURE_ACPI)); /* disable ACPI */
ax = 1;
+ cx = 0;
xen_cpuid(&ax, &bx, &cx, &dx);
/* cpuid claims we support xsave; try enabling it to see what happens */
@@ -974,10 +975,6 @@ asmlinkage void __init xen_start_kernel(void)
xen_domain_type = XEN_PV_DOMAIN;
- BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0);
-
- xen_setup_features();
-
/* Install Xen paravirt ops */
pv_info = xen_info;
pv_init_ops = xen_init_ops;
@@ -986,8 +983,15 @@ asmlinkage void __init xen_start_kernel(void)
pv_apic_ops = xen_apic_ops;
pv_mmu_ops = xen_mmu_ops;
- xen_init_irq_ops();
+#ifdef CONFIG_X86_64
+ /*
+ * Setup percpu state. We only need to do this for 64-bit
+ * because 32-bit already has %fs set properly.
+ */
+ load_percpu_segment(0);
+#endif
+ xen_init_irq_ops();
xen_init_cpuid_mask();
#ifdef CONFIG_X86_LOCAL_APIC
@@ -997,6 +1001,8 @@ asmlinkage void __init xen_start_kernel(void)
set_xen_basic_apic_ops();
#endif
+ xen_setup_features();
+
if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
@@ -1004,13 +1010,6 @@ asmlinkage void __init xen_start_kernel(void)
machine_ops = xen_machine_ops;
-#ifdef CONFIG_X86_64
- /*
- * Setup percpu state. We only need to do this for 64-bit
- * because 32-bit already has %fs set properly.
- */
- load_percpu_segment(0);
-#endif
/*
* The only reliable way to retain the initial address of the
* percpu gdt_page is to remember it here, so we can go and
@@ -1061,6 +1060,7 @@ asmlinkage void __init xen_start_kernel(void)
/* set up basic CPUID stuff */
cpu_detect(&new_cpu_data);
new_cpu_data.hard_math = 1;
+ new_cpu_data.wp_works_ok = 1;
new_cpu_data.x86_capability[0] = cpuid_edx(1);
#endif
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c
index 67340cc70142..257706e7734f 100644
--- a/drivers/acpi/acpica/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -70,6 +70,12 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
+ /* If Source and Target are the same, just return */
+
+ if (source_desc == target_desc) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/* We know that source_desc is a buffer by now */
buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
@@ -161,6 +167,12 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
+ /* If Source and Target are the same, just return */
+
+ if (source_desc == target_desc) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/* We know that source_desc is a string by now */
buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 84e0f3c07442..2cc4b3033872 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -1151,6 +1151,9 @@ static int __init acpi_processor_init(void)
{
int result = 0;
+ if (acpi_disabled)
+ return 0;
+
memset(&errata, 0, sizeof(errata));
#ifdef CONFIG_SMP
@@ -1197,6 +1200,9 @@ out_proc:
static void __exit acpi_processor_exit(void)
{
+ if (acpi_disabled)
+ return;
+
acpi_processor_ppc_exit();
acpi_thermal_cpufreq_exit();
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 0efa59e7e3af..66393d5c4c7c 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -162,8 +162,9 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
pr->power.timer_broadcast_on_state = state;
}
-static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
+static void lapic_timer_propagate_broadcast(void *arg)
{
+ struct acpi_processor *pr = (struct acpi_processor *) arg;
unsigned long reason;
reason = pr->power.timer_broadcast_on_state < INT_MAX ?
@@ -635,7 +636,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
working++;
}
- lapic_timer_propagate_broadcast(pr);
+ smp_call_function_single(pr->id, lapic_timer_propagate_broadcast,
+ pr, 1);
return (working);
}
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 39838c666032..31adda1099e0 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -66,7 +66,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
if (pr->limit.thermal.tx > tx)
tx = pr->limit.thermal.tx;
- result = acpi_processor_set_throttling(pr, tx);
+ result = acpi_processor_set_throttling(pr, tx, false);
if (result)
goto end;
}
@@ -421,12 +421,12 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
if (state <= max_pstate) {
if (pr->flags.throttling && pr->throttling.state)
- result = acpi_processor_set_throttling(pr, 0);
+ result = acpi_processor_set_throttling(pr, 0, false);
cpufreq_set_cur_state(pr->id, state);
} else {
cpufreq_set_cur_state(pr->id, max_pstate);
result = acpi_processor_set_throttling(pr,
- state - max_pstate);
+ state - max_pstate, false);
}
return result;
}
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 227543789ba9..ae39797aab55 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -62,7 +62,8 @@ struct throttling_tstate {
#define THROTTLING_POSTCHANGE (2)
static int acpi_processor_get_throttling(struct acpi_processor *pr);
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force);
static int acpi_processor_update_tsd_coord(void)
{
@@ -361,7 +362,7 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
*/
target_state = throttling_limit;
}
- return acpi_processor_set_throttling(pr, target_state);
+ return acpi_processor_set_throttling(pr, target_state, false);
}
/*
@@ -839,10 +840,10 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
if (ret >= 0) {
state = acpi_get_throttling_state(pr, value);
if (state == -1) {
- ACPI_WARNING((AE_INFO,
- "Invalid throttling state, reset"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Invalid throttling state, reset\n"));
state = 0;
- ret = acpi_processor_set_throttling(pr, state);
+ ret = acpi_processor_set_throttling(pr, state, true);
if (ret)
return ret;
}
@@ -915,7 +916,7 @@ static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
}
static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
- int state)
+ int state, bool force)
{
u32 value = 0;
u32 duty_mask = 0;
@@ -930,7 +931,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
if (!pr->flags.throttling)
return -ENODEV;
- if (state == pr->throttling.state)
+ if (!force && (state == pr->throttling.state))
return 0;
if (state < pr->throttling_platform_limit)
@@ -988,7 +989,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
}
static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
- int state)
+ int state, bool force)
{
int ret;
acpi_integer value;
@@ -1002,7 +1003,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
if (!pr->flags.throttling)
return -ENODEV;
- if (state == pr->throttling.state)
+ if (!force && (state == pr->throttling.state))
return 0;
if (state < pr->throttling_platform_limit)
@@ -1018,7 +1019,8 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
return 0;
}
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force)
{
cpumask_var_t saved_mask;
int ret = 0;
@@ -1070,7 +1072,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
/* FIXME: use work_on_cpu() */
set_cpus_allowed_ptr(current, cpumask_of(pr->id));
ret = p_throttling->acpi_processor_set_throttling(pr,
- t_state.target_state);
+ t_state.target_state, force);
} else {
/*
* When the T-state coordination is SW_ALL or HW_ALL,
@@ -1103,7 +1105,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
set_cpus_allowed_ptr(current, cpumask_of(i));
ret = match_pr->throttling.
acpi_processor_set_throttling(
- match_pr, t_state.target_state);
+ match_pr, t_state.target_state, force);
}
}
/*
@@ -1201,7 +1203,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Disabling throttling (was T%d)\n",
pr->throttling.state));
- result = acpi_processor_set_throttling(pr, 0);
+ result = acpi_processor_set_throttling(pr, 0, false);
if (result)
goto end;
}
@@ -1307,7 +1309,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
if (strcmp(tmpbuf, charp) != 0)
return -EINVAL;
- result = acpi_processor_set_throttling(pr, state_val);
+ result = acpi_processor_set_throttling(pr, state_val, false);
if (result)
return result;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 8851315ce858..60ea984c84a0 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -2004,8 +2004,11 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
status = acpi_remove_notify_handler(device->dev->handle,
ACPI_DEVICE_NOTIFY,
acpi_video_device_notify);
- sysfs_remove_link(&device->backlight->dev.kobj, "device");
- backlight_device_unregister(device->backlight);
+ if (device->backlight) {
+ sysfs_remove_link(&device->backlight->dev.kobj, "device");
+ backlight_device_unregister(device->backlight);
+ device->backlight = NULL;
+ }
if (device->cdev) {
sysfs_remove_link(&device->dev->dev.kobj,
"thermal_cooling");
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 56b8a3ff1286..9ac4e378992e 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -664,6 +664,8 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
return ata_sff_prereset(link, deadline);
}
+static DEFINE_SPINLOCK(piix_lock);
+
/**
* piix_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
@@ -677,8 +679,9 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
- unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ unsigned long flags;
+ unsigned int pio = adev->pio_mode - XFER_PIO_0;
unsigned int is_slave = (adev->devno != 0);
unsigned int master_port= ap->port_no ? 0x42 : 0x40;
unsigned int slave_port = 0x44;
@@ -708,6 +711,8 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
if (adev->class == ATA_DEV_ATA)
control |= 4; /* PPE enable */
+ spin_lock_irqsave(&piix_lock, flags);
+
/* PIO configuration clears DTE unconditionally. It will be
* programmed in set_dmamode which is guaranteed to be called
* after set_piomode if any DMA mode is available.
@@ -747,6 +752,8 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
pci_write_config_byte(dev, 0x48, udma_enable);
}
+
+ spin_unlock_irqrestore(&piix_lock, flags);
}
/**
@@ -764,6 +771,7 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ unsigned long flags;
u8 master_port = ap->port_no ? 0x42 : 0x40;
u16 master_data;
u8 speed = adev->dma_mode;
@@ -777,6 +785,8 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
{ 2, 1 },
{ 2, 3 }, };
+ spin_lock_irqsave(&piix_lock, flags);
+
pci_read_config_word(dev, master_port, &master_data);
if (ap->udma_mask)
pci_read_config_byte(dev, 0x48, &udma_enable);
@@ -867,6 +877,8 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
/* Don't scribble on 0x48 if the controller does not support UDMA */
if (ap->udma_mask)
pci_write_config_byte(dev, 0x48, udma_enable);
+
+ spin_unlock_irqrestore(&piix_lock, flags);
}
/**
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 8c9d50db5c3a..c58557790585 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -49,6 +49,7 @@
#define PCI_DEVICE_ID_INTEL_IGDNG_D_HB 0x0040
#define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042
#define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044
+#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB 0x0062
#define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046
/* cover 915 and 945 variants */
@@ -81,7 +82,8 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB)
extern int agp_memory_reserved;
@@ -1216,6 +1218,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
case PCI_DEVICE_ID_INTEL_G41_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_D_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_M_HB:
+ case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB:
*gtt_offset = *gtt_size = MB(2);
break;
default:
@@ -2195,6 +2198,8 @@ static const struct intel_driver_description {
"IGDNG/D", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
"IGDNG/M", NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
+ "IGDNG/MA", NULL, &intel_i965_driver },
{ 0, 0, 0, NULL, NULL, NULL }
};
@@ -2398,6 +2403,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_G41_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB),
+ ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB),
{ }
};
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 1733d3439ad2..e48af9f79219 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -508,8 +508,9 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
* be obtained while the delayed work queue halt ensures that no more
* data is fed to the ldisc.
*
- * In order to wait for any existing references to complete see
- * tty_ldisc_wait_idle.
+ * You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
+ * in order to make sure any currently executing ldisc work is also
+ * flushed.
*/
static int tty_ldisc_halt(struct tty_struct *tty)
@@ -753,11 +754,14 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* N_TTY.
*/
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
+ /* Make sure the old ldisc is quiescent */
+ tty_ldisc_halt(tty);
+ flush_scheduled_work();
+
/* Avoid racing set_ldisc or tty_ldisc_release */
mutex_lock(&tty->ldisc_mutex);
if (tty->ldisc) { /* Not yet closed */
/* Switch back to N_TTY */
- tty_ldisc_halt(tty);
tty_ldisc_reinit(tty);
/* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index de154556c405..51611722aa02 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -23,44 +23,50 @@
#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
#define to_drm_connector(d) container_of(d, struct drm_connector, kdev)
+static struct device_type drm_sysfs_device_minor = {
+ .name = "drm_minor"
+};
+
/**
- * drm_sysfs_suspend - DRM class suspend hook
+ * drm_class_suspend - DRM class suspend hook
* @dev: Linux device to suspend
* @state: power state to enter
*
* Just figures out what the actual struct drm_device associated with
* @dev is and calls its suspend hook, if present.
*/
-static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+static int drm_class_suspend(struct device *dev, pm_message_t state)
{
- struct drm_minor *drm_minor = to_drm_minor(dev);
- struct drm_device *drm_dev = drm_minor->dev;
-
- if (drm_minor->type == DRM_MINOR_LEGACY &&
- !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
- drm_dev->driver->suspend)
- return drm_dev->driver->suspend(drm_dev, state);
-
+ if (dev->type == &drm_sysfs_device_minor) {
+ struct drm_minor *drm_minor = to_drm_minor(dev);
+ struct drm_device *drm_dev = drm_minor->dev;
+
+ if (drm_minor->type == DRM_MINOR_LEGACY &&
+ !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
+ drm_dev->driver->suspend)
+ return drm_dev->driver->suspend(drm_dev, state);
+ }
return 0;
}
/**
- * drm_sysfs_resume - DRM class resume hook
+ * drm_class_resume - DRM class resume hook
* @dev: Linux device to resume
*
* Just figures out what the actual struct drm_device associated with
* @dev is and calls its resume hook, if present.
*/
-static int drm_sysfs_resume(struct device *dev)
+static int drm_class_resume(struct device *dev)
{
- struct drm_minor *drm_minor = to_drm_minor(dev);
- struct drm_device *drm_dev = drm_minor->dev;
-
- if (drm_minor->type == DRM_MINOR_LEGACY &&
- !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
- drm_dev->driver->resume)
- return drm_dev->driver->resume(drm_dev);
-
+ if (dev->type == &drm_sysfs_device_minor) {
+ struct drm_minor *drm_minor = to_drm_minor(dev);
+ struct drm_device *drm_dev = drm_minor->dev;
+
+ if (drm_minor->type == DRM_MINOR_LEGACY &&
+ !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
+ drm_dev->driver->resume)
+ return drm_dev->driver->resume(drm_dev);
+ }
return 0;
}
@@ -100,8 +106,8 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
goto err_out;
}
- class->suspend = drm_sysfs_suspend;
- class->resume = drm_sysfs_resume;
+ class->suspend = drm_class_suspend;
+ class->resume = drm_class_resume;
err = class_create_file(class, &class_attr_version);
if (err)
@@ -484,6 +490,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
minor->kdev.class = drm_class;
minor->kdev.release = drm_sysfs_device_release;
minor->kdev.devt = minor->device;
+ minor->kdev.type = &drm_sysfs_device_minor;
if (minor->type == DRM_MINOR_CONTROL)
minor_str = "controlD%d";
else if (minor->type == DRM_MINOR_RENDER)
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 30d6b99fb302..5269dfa5f620 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -4,10 +4,10 @@
ccflags-y := -Iinclude/drm
i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
+ i915_debugfs.o \
i915_suspend.o \
i915_gem.o \
i915_gem_debug.o \
- i915_gem_debugfs.o \
i915_gem_tiling.o \
intel_display.o \
intel_crt.o \
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index cb3b97405fbf..1e3bdcee863c 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -158,16 +158,37 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- seq_printf(m, "Interrupt enable: %08x\n",
- I915_READ(IER));
- seq_printf(m, "Interrupt identity: %08x\n",
- I915_READ(IIR));
- seq_printf(m, "Interrupt mask: %08x\n",
- I915_READ(IMR));
- seq_printf(m, "Pipe A stat: %08x\n",
- I915_READ(PIPEASTAT));
- seq_printf(m, "Pipe B stat: %08x\n",
- I915_READ(PIPEBSTAT));
+ if (!IS_IGDNG(dev)) {
+ seq_printf(m, "Interrupt enable: %08x\n",
+ I915_READ(IER));
+ seq_printf(m, "Interrupt identity: %08x\n",
+ I915_READ(IIR));
+ seq_printf(m, "Interrupt mask: %08x\n",
+ I915_READ(IMR));
+ seq_printf(m, "Pipe A stat: %08x\n",
+ I915_READ(PIPEASTAT));
+ seq_printf(m, "Pipe B stat: %08x\n",
+ I915_READ(PIPEBSTAT));
+ } else {
+ seq_printf(m, "North Display Interrupt enable: %08x\n",
+ I915_READ(DEIER));
+ seq_printf(m, "North Display Interrupt identity: %08x\n",
+ I915_READ(DEIIR));
+ seq_printf(m, "North Display Interrupt mask: %08x\n",
+ I915_READ(DEIMR));
+ seq_printf(m, "South Display Interrupt enable: %08x\n",
+ I915_READ(SDEIER));
+ seq_printf(m, "South Display Interrupt identity: %08x\n",
+ I915_READ(SDEIIR));
+ seq_printf(m, "South Display Interrupt mask: %08x\n",
+ I915_READ(SDEIMR));
+ seq_printf(m, "Graphics Interrupt enable: %08x\n",
+ I915_READ(GTIER));
+ seq_printf(m, "Graphics Interrupt identity: %08x\n",
+ I915_READ(GTIIR));
+ seq_printf(m, "Graphics Interrupt mask: %08x\n",
+ I915_READ(GTIMR));
+ }
seq_printf(m, "Interrupts received: %d\n",
atomic_read(&dev_priv->irq_received));
if (dev_priv->hw_status_page != NULL) {
@@ -312,15 +333,13 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- unsigned int head, tail, mask;
+ unsigned int head, tail;
head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
- mask = dev_priv->ring.tail_mask;
seq_printf(m, "RingHead : %08x\n", head);
seq_printf(m, "RingTail : %08x\n", tail);
- seq_printf(m, "RingMask : %08x\n", mask);
seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size);
seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
@@ -363,7 +382,37 @@ out:
return 0;
}
-static struct drm_info_list i915_gem_debugfs_list[] = {
+static int i915_registers_info(struct seq_file *m, void *data) {
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t reg;
+
+#define DUMP_RANGE(start, end) \
+ for (reg=start; reg < end; reg += 4) \
+ seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
+
+ DUMP_RANGE(0x00000, 0x00fff); /* VGA registers */
+ DUMP_RANGE(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */
+ DUMP_RANGE(0x03000, 0x031ff); /* FENCE and PPGTT control registers */
+ DUMP_RANGE(0x03200, 0x03fff); /* frame buffer compression registers */
+ DUMP_RANGE(0x05000, 0x05fff); /* I/O control registers */
+ DUMP_RANGE(0x06000, 0x06fff); /* clock control registers */
+ DUMP_RANGE(0x07000, 0x07fff); /* 3D internal debug registers */
+ DUMP_RANGE(0x07400, 0x088ff); /* GPE debug registers */
+ DUMP_RANGE(0x0a000, 0x0afff); /* display palette registers */
+ DUMP_RANGE(0x10000, 0x13fff); /* MMIO MCHBAR */
+ DUMP_RANGE(0x30000, 0x3ffff); /* overlay registers */
+ DUMP_RANGE(0x60000, 0x6ffff); /* display engine pipeline registers */
+ DUMP_RANGE(0x70000, 0x72fff); /* display and cursor registers */
+ DUMP_RANGE(0x73000, 0x73fff); /* performance counters */
+
+ return 0;
+}
+
+
+static struct drm_info_list i915_debugfs_list[] = {
+ {"i915_regs", i915_registers_info, 0},
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
@@ -377,19 +426,19 @@ static struct drm_info_list i915_gem_debugfs_list[] = {
{"i915_batchbuffers", i915_batchbuffer_info, 0},
{"i915_error_state", i915_error_state, 0},
};
-#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
+#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
-int i915_gem_debugfs_init(struct drm_minor *minor)
+int i915_debugfs_init(struct drm_minor *minor)
{
- return drm_debugfs_create_files(i915_gem_debugfs_list,
- I915_GEM_DEBUGFS_ENTRIES,
+ return drm_debugfs_create_files(i915_debugfs_list,
+ I915_DEBUGFS_ENTRIES,
minor->debugfs_root, minor);
}
-void i915_gem_debugfs_cleanup(struct drm_minor *minor)
+void i915_debugfs_cleanup(struct drm_minor *minor)
{
- drm_debugfs_remove_files(i915_gem_debugfs_list,
- I915_GEM_DEBUGFS_ENTRIES, minor);
+ drm_debugfs_remove_files(i915_debugfs_list,
+ I915_DEBUGFS_ENTRIES, minor);
}
#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index c628c3671394..91ef4c150193 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -79,6 +79,34 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
return -EBUSY;
}
+/* As a ringbuffer is only allowed to wrap between instructions, fill
+ * the tail with NOOPs.
+ */
+int i915_wrap_ring(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ volatile unsigned int *virt;
+ int rem;
+
+ rem = dev_priv->ring.Size - dev_priv->ring.tail;
+ if (dev_priv->ring.space < rem) {
+ int ret = i915_wait_ring(dev, rem, __func__);
+ if (ret)
+ return ret;
+ }
+ dev_priv->ring.space -= rem;
+
+ virt = (unsigned int *)
+ (dev_priv->ring.virtual_start + dev_priv->ring.tail);
+ rem /= 4;
+ while (rem--)
+ *virt++ = MI_NOOP;
+
+ dev_priv->ring.tail = 0;
+
+ return 0;
+}
+
/**
* Sets up the hardware status page for devices that need a physical address
* in the register.
@@ -198,7 +226,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
}
dev_priv->ring.Size = init->ring_size;
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
dev_priv->ring.map.offset = init->ring_start;
dev_priv->ring.map.size = init->ring_size;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fc4b68aa2d05..dbe568c9327b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -37,12 +37,15 @@
#include <linux/console.h>
#include "drm_crtc_helper.h"
-static unsigned int i915_modeset = -1;
+static int i915_modeset = -1;
module_param_named(modeset, i915_modeset, int, 0400);
unsigned int i915_fbpercrtc = 0;
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
+unsigned int i915_powersave = 1;
+module_param_named(powersave, i915_powersave, int, 0400);
+
static struct drm_driver driver;
static struct pci_device_id pciidlist[] = {
@@ -188,8 +191,8 @@ static struct drm_driver driver = {
.master_create = i915_master_create,
.master_destroy = i915_master_destroy,
#if defined(CONFIG_DEBUG_FS)
- .debugfs_init = i915_gem_debugfs_init,
- .debugfs_cleanup = i915_gem_debugfs_cleanup,
+ .debugfs_init = i915_debugfs_init,
+ .debugfs_cleanup = i915_debugfs_cleanup,
#endif
.gem_init_object = i915_gem_init_object,
.gem_free_object = i915_gem_free_object,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7537f57d8a87..2d5bce643e6a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -85,7 +85,6 @@ struct drm_i915_gem_phys_object {
};
typedef struct _drm_i915_ring_buffer {
- int tail_mask;
unsigned long Size;
u8 *virtual_start;
int head;
@@ -222,6 +221,7 @@ typedef struct drm_i915_private {
unsigned int edp_support:1;
int lvds_ssc_freq;
+ int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@@ -310,7 +310,7 @@ typedef struct drm_i915_private {
u32 saveIMR;
u32 saveCACHE_MODE_0;
u32 saveD_STATE;
- u32 saveCG_2D_DIS;
+ u32 saveDSPCLK_GATE_D;
u32 saveMI_ARB_STATE;
u32 saveSWF0[16];
u32 saveSWF1[16];
@@ -384,6 +384,9 @@ typedef struct drm_i915_private {
*/
struct list_head inactive_list;
+ /** LRU list of objects with fence regs on them. */
+ struct list_head fence_list;
+
/**
* List of breadcrumbs associated with GPU requests currently
* outstanding.
@@ -439,6 +442,14 @@ typedef struct drm_i915_private {
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
} mm;
struct sdvo_device_mapping sdvo_mappings[2];
+
+ /* Reclocking support */
+ bool render_reclock_avail;
+ bool lvds_downclock_avail;
+ struct work_struct idle_work;
+ struct timer_list idle_timer;
+ bool busy;
+ u16 orig_clock;
} drm_i915_private_t;
/** driver private structure attached to each drm_gem_object */
@@ -451,6 +462,9 @@ struct drm_i915_gem_object {
/** This object's place on the active/flushing/inactive lists */
struct list_head list;
+ /** This object's place on the fenced object LRU */
+ struct list_head fence_list;
+
/**
* This is set if the object is on the active or flushing lists
* (has pending rendering), and is not set if it's on inactive (ready
@@ -568,6 +582,7 @@ enum intel_chip_family {
extern struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl;
extern unsigned int i915_fbpercrtc;
+extern unsigned int i915_powersave;
extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
@@ -723,8 +738,8 @@ void i915_gem_dump_object(struct drm_gem_object *obj, int len,
void i915_dump_lru(struct drm_device *dev, const char *where);
/* i915_debugfs.c */
-int i915_gem_debugfs_init(struct drm_minor *minor);
-void i915_gem_debugfs_cleanup(struct drm_minor *minor);
+int i915_debugfs_init(struct drm_minor *minor);
+void i915_debugfs_cleanup(struct drm_minor *minor);
/* i915_suspend.c */
extern int i915_save_state(struct drm_device *dev);
@@ -774,33 +789,32 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
#define I915_VERBOSE 0
-#define RING_LOCALS unsigned int outring, ringmask, outcount; \
- volatile char *virt;
-
-#define BEGIN_LP_RING(n) do { \
- if (I915_VERBOSE) \
- DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
- if (dev_priv->ring.space < (n)*4) \
- i915_wait_ring(dev, (n)*4, __func__); \
- outcount = 0; \
- outring = dev_priv->ring.tail; \
- ringmask = dev_priv->ring.tail_mask; \
- virt = dev_priv->ring.virtual_start; \
+#define RING_LOCALS volatile unsigned int *ring_virt__;
+
+#define BEGIN_LP_RING(n) do { \
+ int bytes__ = 4*(n); \
+ if (I915_VERBOSE) DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
+ /* a wrap must occur between instructions so pad beforehand */ \
+ if (unlikely (dev_priv->ring.tail + bytes__ > dev_priv->ring.Size)) \
+ i915_wrap_ring(dev); \
+ if (unlikely (dev_priv->ring.space < bytes__)) \
+ i915_wait_ring(dev, bytes__, __func__); \
+ ring_virt__ = (unsigned int *) \
+ (dev_priv->ring.virtual_start + dev_priv->ring.tail); \
+ dev_priv->ring.tail += bytes__; \
+ dev_priv->ring.tail &= dev_priv->ring.Size - 1; \
+ dev_priv->ring.space -= bytes__; \
} while (0)
-#define OUT_RING(n) do { \
+#define OUT_RING(n) do { \
if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
- *(volatile unsigned int *)(virt + outring) = (n); \
- outcount++; \
- outring += 4; \
- outring &= ringmask; \
+ *ring_virt__++ = (n); \
} while (0)
#define ADVANCE_LP_RING() do { \
- if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \
- dev_priv->ring.tail = outring; \
- dev_priv->ring.space -= outcount * 4; \
- I915_WRITE(PRB0_TAIL, outring); \
+ if (I915_VERBOSE) \
+ DRM_DEBUG("ADVANCE_LP_RING %x\n", dev_priv->ring.tail); \
+ I915_WRITE(PRB0_TAIL, dev_priv->ring.tail); \
} while(0)
/**
@@ -823,6 +837,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
#define I915_GEM_HWS_INDEX 0x20
#define I915_BREADCRUMB_INDEX 0x21
+extern int i915_wrap_ring(struct drm_device * dev);
extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
@@ -896,6 +911,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
/* dsparb controlled by hw only */
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
+#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev))
+#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev))
+
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
#endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0e6c9cca897c..954fb699131b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -29,6 +29,7 @@
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
+#include "intel_drv.h"
#include <linux/swap.h>
#include <linux/pci.h>
@@ -979,8 +980,10 @@ int
i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_set_domain *args = data;
struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
uint32_t read_domains = args->read_domains;
uint32_t write_domain = args->write_domain;
int ret;
@@ -1004,8 +1007,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EBADF;
+ obj_priv = obj->driver_private;
mutex_lock(&dev->struct_mutex);
+
+ intel_mark_busy(dev, obj);
+
#if WATCH_BUF
DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
obj, obj->size, read_domains, write_domain);
@@ -1013,6 +1020,14 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
if (read_domains & I915_GEM_DOMAIN_GTT) {
ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
+ /* Update the LRU on the fence for the CPU access that's
+ * about to occur.
+ */
+ if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+ list_move_tail(&obj_priv->fence_list,
+ &dev_priv->mm.fence_list);
+ }
+
/* Silently promote "you're not bound, there was nothing to do"
* to success, since the client was just asking us to
* make sure everything was done.
@@ -1156,8 +1171,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
/* Need a new fence register? */
- if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
- obj_priv->tiling_mode != I915_TILING_NONE) {
+ if (obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret) {
mutex_unlock(&dev->struct_mutex);
@@ -2209,6 +2223,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
struct drm_i915_gem_object *old_obj_priv = NULL;
int i, ret, avail;
+ /* Just update our place in the LRU if our fence is getting used. */
+ if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+ list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+ return 0;
+ }
+
switch (obj_priv->tiling_mode) {
case I915_TILING_NONE:
WARN(1, "allocating a fence for non-tiled object?\n");
@@ -2230,7 +2250,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
}
/* First try to find a free reg */
-try_again:
avail = 0;
for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
reg = &dev_priv->fence_regs[i];
@@ -2244,63 +2263,62 @@ try_again:
/* None available, try to steal one or wait for a user to finish */
if (i == dev_priv->num_fence_regs) {
- uint32_t seqno = dev_priv->mm.next_gem_seqno;
+ struct drm_gem_object *old_obj = NULL;
if (avail == 0)
return -ENOSPC;
- for (i = dev_priv->fence_reg_start;
- i < dev_priv->num_fence_regs; i++) {
- uint32_t this_seqno;
-
- reg = &dev_priv->fence_regs[i];
- old_obj_priv = reg->obj->driver_private;
+ list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
+ fence_list) {
+ old_obj = old_obj_priv->obj;
if (old_obj_priv->pin_count)
continue;
+ /* Take a reference, as otherwise the wait_rendering
+ * below may cause the object to get freed out from
+ * under us.
+ */
+ drm_gem_object_reference(old_obj);
+
/* i915 uses fences for GPU access to tiled buffers */
if (IS_I965G(dev) || !old_obj_priv->active)
break;
- /* find the seqno of the first available fence */
- this_seqno = old_obj_priv->last_rendering_seqno;
- if (this_seqno != 0 &&
- reg->obj->write_domain == 0 &&
- i915_seqno_passed(seqno, this_seqno))
- seqno = this_seqno;
- }
-
- /*
- * Now things get ugly... we have to wait for one of the
- * objects to finish before trying again.
- */
- if (i == dev_priv->num_fence_regs) {
- if (seqno == dev_priv->mm.next_gem_seqno) {
- i915_gem_flush(dev,
- I915_GEM_GPU_DOMAINS,
- I915_GEM_GPU_DOMAINS);
- seqno = i915_add_request(dev, NULL,
- I915_GEM_GPU_DOMAINS);
- if (seqno == 0)
- return -ENOMEM;
+ /* This brings the object to the head of the LRU if it
+ * had been written to. The only way this should
+ * result in us waiting longer than the expected
+ * optimal amount of time is if there was a
+ * fence-using buffer later that was read-only.
+ */
+ i915_gem_object_flush_gpu_write_domain(old_obj);
+ ret = i915_gem_object_wait_rendering(old_obj);
+ if (ret != 0) {
+ drm_gem_object_unreference(old_obj);
+ return ret;
}
- ret = i915_wait_request(dev, seqno);
- if (ret)
- return ret;
- goto try_again;
+ break;
}
/*
* Zap this virtual mapping so we can set up a fence again
* for this object next time we need it.
*/
- i915_gem_release_mmap(reg->obj);
+ i915_gem_release_mmap(old_obj);
+
+ i = old_obj_priv->fence_reg;
+ reg = &dev_priv->fence_regs[i];
+
old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
+ list_del_init(&old_obj_priv->fence_list);
+
+ drm_gem_object_unreference(old_obj);
}
obj_priv->fence_reg = i;
+ list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+
reg->obj = obj;
if (IS_I965G(dev))
@@ -2343,6 +2361,7 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
obj_priv->fence_reg = I915_FENCE_REG_NONE;
+ list_del_init(&obj_priv->fence_list);
}
/**
@@ -2762,6 +2781,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
+ intel_mark_busy(dev, obj);
+
#if WATCH_BUF
DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
__func__, obj,
@@ -3596,9 +3617,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
* Pre-965 chips need a fence register set up in order to
* properly handle tiled surfaces.
*/
- if (!IS_I965G(dev) &&
- obj_priv->fence_reg == I915_FENCE_REG_NONE &&
- obj_priv->tiling_mode != I915_TILING_NONE) {
+ if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret != 0) {
if (ret != -EBUSY && ret != -ERESTARTSYS)
@@ -3807,6 +3826,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
obj_priv->obj = obj;
obj_priv->fence_reg = I915_FENCE_REG_NONE;
INIT_LIST_HEAD(&obj_priv->list);
+ INIT_LIST_HEAD(&obj_priv->fence_list);
return 0;
}
@@ -4080,7 +4100,6 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
/* Set up the kernel mapping for the ring. */
ring->Size = obj->size;
- ring->tail_mask = obj->size - 1;
ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
ring->map.size = obj->size;
@@ -4254,6 +4273,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
INIT_LIST_HEAD(&dev_priv->mm.request_list);
+ INIT_LIST_HEAD(&dev_priv->mm.fence_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler);
dev_priv->mm.next_gem_seqno = 1;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index a2d527b22ec4..e774a4a1a503 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -234,7 +234,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
bool need_disable;
- if (!IS_I9XX(dev)) {
+ if (IS_IGDNG(dev)) {
+ /* On IGDNG whatever DRAM config, GPU always do
+ * same swizzling setup.
+ */
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+ swizzle_y = I915_BIT_6_SWIZZLE_9;
+ } else if (!IS_I9XX(dev)) {
/* As far as we know, the 865 doesn't have these bit 6
* swizzling issues.
*/
@@ -317,13 +323,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
}
}
- /* FIXME: check with memory config on IGDNG */
- if (IS_IGDNG(dev)) {
- DRM_ERROR("disable tiling on IGDNG...\n");
- swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
- swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- }
-
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7ebc84c2881e..6c89f2ff2495 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -565,6 +565,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
+
+ /* EOS interrupts occurs */
+ if (IS_IGD(dev) &&
+ (hotplug_status & CRT_EOS_INT_STATUS)) {
+ u32 temp;
+
+ DRM_DEBUG("EOS interrupt occurs\n");
+ /* status is already cleared */
+ temp = I915_READ(ADPA);
+ temp &= ~ADPA_DAC_ENABLE;
+ I915_WRITE(ADPA, temp);
+
+ temp = I915_READ(PORT_HOTPLUG_EN);
+ temp &= ~CRT_EOS_INT_EN;
+ I915_WRITE(PORT_HOTPLUG_EN, temp);
+
+ temp = I915_READ(PORT_HOTPLUG_STAT);
+ if (temp & CRT_EOS_INT_STATUS)
+ I915_WRITE(PORT_HOTPLUG_STAT,
+ CRT_EOS_INT_STATUS);
+ }
}
I915_WRITE(IIR, iir);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2955083aa471..e38cd21161c8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -55,7 +55,7 @@
/* PCI config space */
#define HPLLCC 0xc0 /* 855 only */
-#define GC_CLOCK_CONTROL_MASK (3 << 0)
+#define GC_CLOCK_CONTROL_MASK (0xf << 0)
#define GC_CLOCK_133_200 (0 << 0)
#define GC_CLOCK_100_200 (1 << 0)
#define GC_CLOCK_100_133 (2 << 0)
@@ -65,6 +65,25 @@
#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
#define GC_DISPLAY_CLOCK_333_MHZ (4 << 4)
#define GC_DISPLAY_CLOCK_MASK (7 << 4)
+#define GM45_GC_RENDER_CLOCK_MASK (0xf << 0)
+#define GM45_GC_RENDER_CLOCK_266_MHZ (8 << 0)
+#define GM45_GC_RENDER_CLOCK_320_MHZ (9 << 0)
+#define GM45_GC_RENDER_CLOCK_400_MHZ (0xb << 0)
+#define GM45_GC_RENDER_CLOCK_533_MHZ (0xc << 0)
+#define I965_GC_RENDER_CLOCK_MASK (0xf << 0)
+#define I965_GC_RENDER_CLOCK_267_MHZ (2 << 0)
+#define I965_GC_RENDER_CLOCK_333_MHZ (3 << 0)
+#define I965_GC_RENDER_CLOCK_444_MHZ (4 << 0)
+#define I965_GC_RENDER_CLOCK_533_MHZ (5 << 0)
+#define I945_GC_RENDER_CLOCK_MASK (7 << 0)
+#define I945_GC_RENDER_CLOCK_166_MHZ (0 << 0)
+#define I945_GC_RENDER_CLOCK_200_MHZ (1 << 0)
+#define I945_GC_RENDER_CLOCK_250_MHZ (3 << 0)
+#define I945_GC_RENDER_CLOCK_400_MHZ (5 << 0)
+#define I915_GC_RENDER_CLOCK_MASK (7 << 0)
+#define I915_GC_RENDER_CLOCK_166_MHZ (0 << 0)
+#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0)
+#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0)
#define LBB 0xf4
/* VGA stuff */
@@ -553,9 +572,118 @@
#define DPLLA_TEST_M_BYPASS (1 << 2)
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
#define D_STATE 0x6104
-#define CG_2D_DIS 0x6200
-#define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24)
-#define CG_3D_DIS 0x6204
+#define DSTATE_PLL_D3_OFF (1<<3)
+#define DSTATE_GFX_CLOCK_GATING (1<<1)
+#define DSTATE_DOT_CLOCK_GATING (1<<0)
+#define DSPCLK_GATE_D 0x6200
+# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */
+# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */
+# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */
+# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */
+# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */
+# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */
+# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */
+# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */
+# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */
+# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */
+# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */
+# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */
+# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */
+# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */
+# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */
+# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */
+# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */
+# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */
+# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */
+# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11)
+# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10)
+# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9)
+# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8)
+# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */
+# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */
+# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */
+# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5)
+# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4)
+/**
+ * This bit must be set on the 830 to prevent hangs when turning off the
+ * overlay scaler.
+ */
+# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3)
+# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2)
+# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1)
+# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */
+# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */
+
+#define RENCLK_GATE_D1 0x6204
+# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */
+# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */
+# define PC_FE_CLOCK_GATE_DISABLE (1 << 11)
+# define PC_BE_CLOCK_GATE_DISABLE (1 << 10)
+# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9)
+# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8)
+# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7)
+# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6)
+# define MAG_CLOCK_GATE_DISABLE (1 << 5)
+/** This bit must be unset on 855,865 */
+# define MECI_CLOCK_GATE_DISABLE (1 << 4)
+# define DCMP_CLOCK_GATE_DISABLE (1 << 3)
+# define MEC_CLOCK_GATE_DISABLE (1 << 2)
+# define MECO_CLOCK_GATE_DISABLE (1 << 1)
+/** This bit must be set on 855,865. */
+# define SV_CLOCK_GATE_DISABLE (1 << 0)
+# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16)
+# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15)
+# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14)
+# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13)
+# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12)
+# define I915_WM_CLOCK_GATE_DISABLE (1 << 11)
+# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10)
+# define I915_PI_CLOCK_GATE_DISABLE (1 << 9)
+# define I915_DI_CLOCK_GATE_DISABLE (1 << 8)
+# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7)
+# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6)
+# define I915_SC_CLOCK_GATE_DISABLE (1 << 5)
+# define I915_FL_CLOCK_GATE_DISABLE (1 << 4)
+# define I915_DM_CLOCK_GATE_DISABLE (1 << 3)
+# define I915_PS_CLOCK_GATE_DISABLE (1 << 2)
+# define I915_CC_CLOCK_GATE_DISABLE (1 << 1)
+# define I915_BY_CLOCK_GATE_DISABLE (1 << 0)
+
+# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30)
+/** This bit must always be set on 965G/965GM */
+# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29)
+# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28)
+# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27)
+# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26)
+# define I965_GW_CLOCK_GATE_DISABLE (1 << 25)
+# define I965_TD_CLOCK_GATE_DISABLE (1 << 24)
+/** This bit must always be set on 965G */
+# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23)
+# define I965_IC_CLOCK_GATE_DISABLE (1 << 22)
+# define I965_EU_CLOCK_GATE_DISABLE (1 << 21)
+# define I965_IF_CLOCK_GATE_DISABLE (1 << 20)
+# define I965_TC_CLOCK_GATE_DISABLE (1 << 19)
+# define I965_SO_CLOCK_GATE_DISABLE (1 << 17)
+# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16)
+# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15)
+# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14)
+# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13)
+# define I965_EM_CLOCK_GATE_DISABLE (1 << 12)
+# define I965_UC_CLOCK_GATE_DISABLE (1 << 11)
+# define I965_SI_CLOCK_GATE_DISABLE (1 << 6)
+# define I965_MT_CLOCK_GATE_DISABLE (1 << 5)
+# define I965_PL_CLOCK_GATE_DISABLE (1 << 4)
+# define I965_DG_CLOCK_GATE_DISABLE (1 << 3)
+# define I965_QC_CLOCK_GATE_DISABLE (1 << 2)
+# define I965_FT_CLOCK_GATE_DISABLE (1 << 1)
+# define I965_DM_CLOCK_GATE_DISABLE (1 << 0)
+
+#define RENCLK_GATE_D2 0x6208
+#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9)
+#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7)
+#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6)
+#define RAMCLK_GATE_D 0x6210 /* CRL only */
+#define DEUC 0x6214 /* CRL only */
/*
* Palette regs
@@ -683,6 +811,7 @@
#define SDVOB_HOTPLUG_INT_EN (1 << 26)
#define SDVOC_HOTPLUG_INT_EN (1 << 25)
#define TV_HOTPLUG_INT_EN (1 << 18)
+#define CRT_EOS_INT_EN (1 << 10)
#define CRT_HOTPLUG_INT_EN (1 << 9)
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
@@ -717,6 +846,7 @@
#define DPC_HOTPLUG_INT_STATUS (1 << 28)
#define HDMID_HOTPLUG_INT_STATUS (1 << 27)
#define DPD_HOTPLUG_INT_STATUS (1 << 27)
+#define CRT_EOS_INT_STATUS (1 << 12)
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
#define TV_HOTPLUG_INT_STATUS (1 << 10)
#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
@@ -1586,6 +1716,7 @@
#define PIPECONF_PROGRESSIVE (0 << 21)
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPEASTAT 0x70024
#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31)
#define PIPE_CRC_ERROR_ENABLE (1UL<<29)
@@ -1733,6 +1864,7 @@
#define DISPPLANE_NO_LINE_DOUBLE 0
#define DISPPLANE_STEREO_POLARITY_FIRST 0
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* IGDNG */
#define DISPPLANE_TILED (1<<10)
#define DSPAADDR 0x70184
#define DSPASTRIDE 0x70188
@@ -1913,6 +2045,9 @@
#define GTIIR 0x44018
#define GTIER 0x4401c
+#define DISP_ARB_CTL 0x45000
+#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
+
/* PCH */
/* south display engine interrupt */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 1d04e1904ac6..20d4d19f5568 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -461,7 +461,7 @@ int i915_save_state(struct drm_device *dev)
/* Clock gating state */
dev_priv->saveD_STATE = I915_READ(D_STATE);
- dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
+ dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
/* Cache mode state */
dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
@@ -588,7 +588,7 @@ int i915_restore_state(struct drm_device *dev)
/* Clock gating state */
I915_WRITE (D_STATE, dev_priv->saveD_STATE);
- I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
+ I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
/* Cache mode state */
I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 300aee3296c2..1e28c1652fd0 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -59,6 +59,16 @@ find_section(struct bdb_header *bdb, int section_id)
return NULL;
}
+static u16
+get_blocksize(void *p)
+{
+ u16 *block_ptr, block_size;
+
+ block_ptr = (u16 *)((char *)p - 2);
+ block_size = *block_ptr;
+ return block_size;
+}
+
static void
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
struct lvds_dvo_timing *dvo_timing)
@@ -215,6 +225,41 @@ parse_general_features(struct drm_i915_private *dev_priv,
}
static void
+parse_general_definitions(struct drm_i915_private *dev_priv,
+ struct bdb_header *bdb)
+{
+ struct bdb_general_definitions *general;
+ const int crt_bus_map_table[] = {
+ GPIOB,
+ GPIOA,
+ GPIOC,
+ GPIOD,
+ GPIOE,
+ GPIOF,
+ };
+
+ /* Set sensible defaults in case we can't find the general block
+ or it is the wrong chipset */
+ dev_priv->crt_ddc_bus = -1;
+
+ general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+ if (general) {
+ u16 block_size = get_blocksize(general);
+ if (block_size >= sizeof(*general)) {
+ int bus_pin = general->crt_ddc_gmbus_pin;
+ DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
+ if ((bus_pin >= 1) && (bus_pin <= 6)) {
+ dev_priv->crt_ddc_bus =
+ crt_bus_map_table[bus_pin-1];
+ }
+ } else {
+ DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
+ block_size);
+ }
+ }
+}
+
+static void
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
@@ -222,7 +267,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
struct bdb_general_definitions *p_defs;
struct child_device_config *p_child;
int i, child_device_num, count;
- u16 block_size, *block_ptr;
+ u16 block_size;
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (!p_defs) {
@@ -240,8 +285,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
return;
}
/* get the block size of general definitions */
- block_ptr = (u16 *)((char *)p_defs - 2);
- block_size = *block_ptr;
+ block_size = get_blocksize(p_defs);
/* get the number of child device */
child_device_num = (block_size - sizeof(*p_defs)) /
sizeof(*p_child);
@@ -311,8 +355,14 @@ parse_driver_features(struct drm_i915_private *dev_priv,
}
driver = find_section(bdb, BDB_DRIVER_FEATURES);
- if (driver && driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
+ if (!driver)
+ return;
+
+ if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
dev_priv->edp_support = 1;
+
+ if (driver->dual_frequency)
+ dev_priv->render_reclock_avail = true;
}
/**
@@ -362,6 +412,7 @@ intel_init_bios(struct drm_device *dev)
/* Grab useful general definitions */
parse_general_features(dev_priv, bdb);
+ parse_general_definitions(dev_priv, bdb);
parse_lfp_panel_data(dev_priv, bdb);
parse_sdvo_panel_data(dev_priv, bdb);
parse_sdvo_device_mapping(dev_priv, bdb);
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 4cf8e2e88a40..88814fa2dfd2 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -64,6 +64,34 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
}
I915_WRITE(reg, temp);
+
+ if (IS_IGD(dev)) {
+ if (mode == DRM_MODE_DPMS_OFF) {
+ /* turn off DAC */
+ temp = I915_READ(PORT_HOTPLUG_EN);
+ temp &= ~CRT_EOS_INT_EN;
+ I915_WRITE(PORT_HOTPLUG_EN, temp);
+
+ temp = I915_READ(PORT_HOTPLUG_STAT);
+ if (temp & CRT_EOS_INT_STATUS)
+ I915_WRITE(PORT_HOTPLUG_STAT,
+ CRT_EOS_INT_STATUS);
+ } else {
+ /* turn on DAC. EOS interrupt must be enabled after DAC
+ * is enabled, so it sounds not good to enable it in
+ * i915_driver_irq_postinstall()
+ * wait 12.5ms after DAC is enabled
+ */
+ msleep(13);
+ temp = I915_READ(PORT_HOTPLUG_STAT);
+ if (temp & CRT_EOS_INT_STATUS)
+ I915_WRITE(PORT_HOTPLUG_STAT,
+ CRT_EOS_INT_STATUS);
+ temp = I915_READ(PORT_HOTPLUG_EN);
+ temp |= CRT_EOS_INT_EN;
+ I915_WRITE(PORT_HOTPLUG_EN, temp);
+ }
+ }
}
static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -508,6 +536,7 @@ void intel_crt_init(struct drm_device *dev)
{
struct drm_connector *connector;
struct intel_output *intel_output;
+ struct drm_i915_private *dev_priv = dev->dev_private;
u32 i2c_reg;
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
@@ -527,8 +556,12 @@ void intel_crt_init(struct drm_device *dev)
/* Set up the DDC bus. */
if (IS_IGDNG(dev))
i2c_reg = PCH_GPIOA;
- else
+ else {
i2c_reg = GPIOA;
+ /* Use VBT information for CRT DDC if available */
+ if (dev_priv->crt_ddc_bus != -1)
+ i2c_reg = dev_priv->crt_ddc_bus;
+ }
intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
if (!intel_output->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
@@ -537,6 +570,10 @@ void intel_crt_init(struct drm_device *dev)
}
intel_output->type = INTEL_OUTPUT_ANALOG;
+ intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+ (1 << INTEL_ANALOG_CLONE_BIT) |
+ (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+ intel_output->crtc_mask = (1 << 0) | (1 << 1);
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5fb7a4f4a427..155719ff99d1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -38,6 +38,7 @@
bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
static void intel_update_watermarks(struct drm_device *dev);
+static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule);
typedef struct {
/* given values */
@@ -67,6 +68,8 @@ struct intel_limit {
intel_p2_t p2;
bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
int, int, intel_clock_t *);
+ bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *,
+ int, int, intel_clock_t *);
};
#define I8XX_DOT_MIN 25000
@@ -261,6 +264,9 @@ static bool
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
int target, int refclk, intel_clock_t *best_clock);
static bool
+intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
+ int target, int refclk, intel_clock_t *best_clock);
+static bool
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
int target, int refclk, intel_clock_t *best_clock);
static bool
@@ -286,6 +292,7 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
.find_pll = intel_find_best_PLL,
+ .find_reduced_pll = intel_find_best_reduced_PLL,
};
static const intel_limit_t intel_limits_i8xx_lvds = {
@@ -300,6 +307,7 @@ static const intel_limit_t intel_limits_i8xx_lvds = {
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
.find_pll = intel_find_best_PLL,
+ .find_reduced_pll = intel_find_best_reduced_PLL,
};
static const intel_limit_t intel_limits_i9xx_sdvo = {
@@ -314,6 +322,7 @@ static const intel_limit_t intel_limits_i9xx_sdvo = {
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
.find_pll = intel_find_best_PLL,
+ .find_reduced_pll = intel_find_best_reduced_PLL,
};
static const intel_limit_t intel_limits_i9xx_lvds = {
@@ -331,6 +340,7 @@ static const intel_limit_t intel_limits_i9xx_lvds = {
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
.find_pll = intel_find_best_PLL,
+ .find_reduced_pll = intel_find_best_reduced_PLL,
};
/* below parameter and function is for G4X Chipset Family*/
@@ -348,6 +358,7 @@ static const intel_limit_t intel_limits_g4x_sdvo = {
.p2_fast = G4X_P2_SDVO_FAST
},
.find_pll = intel_g4x_find_best_PLL,
+ .find_reduced_pll = intel_g4x_find_best_PLL,
};
static const intel_limit_t intel_limits_g4x_hdmi = {
@@ -364,6 +375,7 @@ static const intel_limit_t intel_limits_g4x_hdmi = {
.p2_fast = G4X_P2_HDMI_DAC_FAST
},
.find_pll = intel_g4x_find_best_PLL,
+ .find_reduced_pll = intel_g4x_find_best_PLL,
};
static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
@@ -388,6 +400,7 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
.p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
},
.find_pll = intel_g4x_find_best_PLL,
+ .find_reduced_pll = intel_g4x_find_best_PLL,
};
static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
@@ -412,6 +425,7 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
.p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
},
.find_pll = intel_g4x_find_best_PLL,
+ .find_reduced_pll = intel_g4x_find_best_PLL,
};
static const intel_limit_t intel_limits_g4x_display_port = {
@@ -449,6 +463,7 @@ static const intel_limit_t intel_limits_igd_sdvo = {
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
.find_pll = intel_find_best_PLL,
+ .find_reduced_pll = intel_find_best_reduced_PLL,
};
static const intel_limit_t intel_limits_igd_lvds = {
@@ -464,6 +479,7 @@ static const intel_limit_t intel_limits_igd_lvds = {
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
.find_pll = intel_find_best_PLL,
+ .find_reduced_pll = intel_find_best_reduced_PLL,
};
static const intel_limit_t intel_limits_igdng_sdvo = {
@@ -666,7 +682,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
intel_clock_t clock;
int err = target;
- if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
(I915_READ(LVDS)) != 0) {
/*
* For LVDS, if the panel is on, just rely on its current
@@ -688,15 +704,16 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
memset (best_clock, 0, sizeof (*best_clock));
- for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
- for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
- /* m1 is always 0 in IGD */
- if (clock.m2 >= clock.m1 && !IS_IGD(dev))
- break;
- for (clock.n = limit->n.min; clock.n <= limit->n.max;
- clock.n++) {
- for (clock.p1 = limit->p1.min;
- clock.p1 <= limit->p1.max; clock.p1++) {
+ for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
+ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+ clock.m1++) {
+ for (clock.m2 = limit->m2.min;
+ clock.m2 <= limit->m2.max; clock.m2++) {
+ /* m1 is always 0 in IGD */
+ if (clock.m2 >= clock.m1 && !IS_IGD(dev))
+ break;
+ for (clock.n = limit->n.min;
+ clock.n <= limit->n.max; clock.n++) {
int this_err;
intel_clock(dev, refclk, &clock);
@@ -717,6 +734,46 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
return (err != target);
}
+
+static bool
+intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
+ int target, int refclk, intel_clock_t *best_clock)
+
+{
+ struct drm_device *dev = crtc->dev;
+ intel_clock_t clock;
+ int err = target;
+ bool found = false;
+
+ memcpy(&clock, best_clock, sizeof(intel_clock_t));
+
+ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
+ for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
+ /* m1 is always 0 in IGD */
+ if (clock.m2 >= clock.m1 && !IS_IGD(dev))
+ break;
+ for (clock.n = limit->n.min; clock.n <= limit->n.max;
+ clock.n++) {
+ int this_err;
+
+ intel_clock(dev, refclk, &clock);
+
+ if (!intel_PLL_is_valid(crtc, &clock))
+ continue;
+
+ this_err = abs(clock.dot - target);
+ if (this_err < err) {
+ *best_clock = clock;
+ err = this_err;
+ found = true;
+ }
+ }
+ }
+ }
+
+ return found;
+}
+
static bool
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
int target, int refclk, intel_clock_t *best_clock)
@@ -747,7 +804,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
max_n = limit->n.max;
/* based on hardware requriment prefer smaller n to precision */
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
- /* based on hardware requirment prefere larger m1,m2, p1 */
+ /* based on hardware requirment prefere larger m1,m2 */
for (clock.m1 = limit->m1.max;
clock.m1 >= limit->m1.min; clock.m1--) {
for (clock.m2 = limit->m2.max;
@@ -832,15 +889,14 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
memset(best_clock, 0, sizeof(*best_clock));
max_n = limit->n.max;
- /* based on hardware requriment prefer smaller n to precision */
- for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
- /* based on hardware requirment prefere larger m1,m2, p1 */
- for (clock.m1 = limit->m1.max;
- clock.m1 >= limit->m1.min; clock.m1--) {
- for (clock.m2 = limit->m2.max;
- clock.m2 >= limit->m2.min; clock.m2--) {
- for (clock.p1 = limit->p1.max;
- clock.p1 >= limit->p1.min; clock.p1--) {
+ for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
+ /* based on hardware requriment prefer smaller n to precision */
+ for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
+ /* based on hardware requirment prefere larger m1,m2 */
+ for (clock.m1 = limit->m1.max;
+ clock.m1 >= limit->m1.min; clock.m1--) {
+ for (clock.m2 = limit->m2.max;
+ clock.m2 >= limit->m2.min; clock.m2--) {
int this_err;
intel_clock(dev, refclk, &clock);
@@ -1008,6 +1064,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
dspcntr &= ~DISPPLANE_TILED;
}
+ if (IS_IGDNG(dev))
+ /* must disable */
+ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
@@ -1030,8 +1090,11 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
if (old_fb) {
intel_fb = to_intel_framebuffer(old_fb);
+ obj_priv = intel_fb->obj->driver_private;
i915_gem_object_unpin(intel_fb->obj);
}
+ intel_increase_pllclock(crtc, true);
+
mutex_unlock(&dev->struct_mutex);
if (!dev->primary->master)
@@ -1581,6 +1644,8 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
else
i9xx_crtc_dpms(crtc, mode);
+ intel_crtc->dpms_mode = mode;
+
if (!dev->primary->master)
return;
@@ -1603,8 +1668,6 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
break;
}
-
- intel_crtc->dpms_mode = mode;
}
static void intel_crtc_prepare (struct drm_crtc *crtc)
@@ -2005,7 +2068,21 @@ static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock,
return;
}
-const static int latency_ns = 3000; /* default for non-igd platforms */
+/*
+ * Latency for FIFO fetches is dependent on several factors:
+ * - memory configuration (speed, channels)
+ * - chipset
+ * - current MCH state
+ * It can be fairly high in some situations, so here we assume a fairly
+ * pessimal value. It's a tradeoff between extra memory fetches (if we
+ * set this value too high, the FIFO will fetch frequently to stay full)
+ * and power consumption (set it too low to save power and we might see
+ * FIFO underruns and display "flicker").
+ *
+ * A value of 5us seems to be a good balance; safe for very low end
+ * platforms but not overly aggressive on lower latency configs.
+ */
+const static int latency_ns = 5000;
static int intel_get_fifo_size(struct drm_device *dev, int plane)
{
@@ -2040,6 +2117,18 @@ static int intel_get_fifo_size(struct drm_device *dev, int plane)
return size;
}
+static void g4x_update_wm(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 fw_blc_self = I915_READ(FW_BLC_SELF);
+
+ if (i915_powersave)
+ fw_blc_self |= FW_BLC_SELF_EN;
+ else
+ fw_blc_self &= ~FW_BLC_SELF_EN;
+ I915_WRITE(FW_BLC_SELF, fw_blc_self);
+}
+
static void i965_update_wm(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2091,7 +2180,8 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
cwm = 2;
/* Calc sr entries for one plane configs */
- if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+ if (HAS_FW_BLC(dev) && sr_hdisplay &&
+ (!planea_clock || !planeb_clock)) {
/* self-refresh has much higher latency */
const static int sr_latency_ns = 6000;
@@ -2106,8 +2196,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
srwm = total_size - sr_entries;
if (srwm < 0)
srwm = 1;
- if (IS_I9XX(dev))
- I915_WRITE(FW_BLC_SELF, (srwm & 0x3f));
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
}
DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
@@ -2181,9 +2270,6 @@ static void intel_update_watermarks(struct drm_device *dev)
unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
int enabled = 0, pixel_size = 0;
- if (DSPARB_HWCONTROL(dev))
- return;
-
/* Get the clock config from both planes */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
intel_crtc = to_intel_crtc(crtc);
@@ -2216,7 +2302,9 @@ static void intel_update_watermarks(struct drm_device *dev)
else if (IS_IGD(dev))
igd_disable_cxsr(dev);
- if (IS_I965G(dev))
+ if (IS_G4X(dev))
+ g4x_update_wm(dev);
+ else if (IS_I965G(dev))
i965_update_wm(dev);
else if (IS_I9XX(dev) || IS_MOBILE(dev))
i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
@@ -2250,9 +2338,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
int refclk, num_outputs = 0;
- intel_clock_t clock;
- u32 dpll = 0, fp = 0, dspcntr, pipeconf;
- bool ok, is_sdvo = false, is_dvo = false;
+ intel_clock_t clock, reduced_clock;
+ u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
+ bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
bool is_edp = false;
struct drm_mode_config *mode_config = &dev->mode_config;
@@ -2335,6 +2423,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
return -EINVAL;
}
+ if (limit->find_reduced_pll && dev_priv->lvds_downclock_avail) {
+ memcpy(&reduced_clock, &clock, sizeof(intel_clock_t));
+ has_reduced_clock = limit->find_reduced_pll(limit, crtc,
+ (adjusted_mode->clock*3/4),
+ refclk,
+ &reduced_clock);
+ }
+
/* SDVO TV has fixed PLL values depend on its clock range,
this mirrors vbios setting. */
if (is_sdvo && is_tv) {
@@ -2380,10 +2476,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
link_bw, &m_n);
}
- if (IS_IGD(dev))
+ if (IS_IGD(dev)) {
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
- else
+ if (has_reduced_clock)
+ fp2 = (1 << reduced_clock.n) << 16 |
+ reduced_clock.m1 << 8 | reduced_clock.m2;
+ } else {
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+ if (has_reduced_clock)
+ fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+ reduced_clock.m2;
+ }
if (!IS_IGDNG(dev))
dpll = DPLL_VGA_MODE_DIS;
@@ -2396,7 +2499,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
if (is_sdvo) {
dpll |= DPLL_DVO_HIGH_SPEED;
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
- if (IS_I945G(dev) || IS_I945GM(dev))
+ if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
else if (IS_IGDNG(dev))
dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
@@ -2412,6 +2515,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* also FPA1 */
if (IS_IGDNG(dev))
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+ if (IS_G4X(dev) && has_reduced_clock)
+ dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
}
switch (clock.p2) {
case 5:
@@ -2559,6 +2664,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
udelay(150);
}
+ if (is_lvds && has_reduced_clock && i915_powersave) {
+ I915_WRITE(fp_reg + 4, fp2);
+ intel_crtc->lowfreq_avail = true;
+ if (HAS_PIPE_CXSR(dev)) {
+ DRM_DEBUG("enabling CxSR downclocking\n");
+ pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+ }
+ } else {
+ I915_WRITE(fp_reg + 4, fp);
+ intel_crtc->lowfreq_avail = false;
+ if (HAS_PIPE_CXSR(dev)) {
+ DRM_DEBUG("disabling CxSR downclocking\n");
+ pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+ }
+ }
+
I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
((adjusted_mode->crtc_htotal - 1) << 16));
I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
@@ -2602,6 +2723,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
intel_wait_for_vblank(dev);
+ if (IS_IGDNG(dev)) {
+ /* enable address swizzle for tiling buffer */
+ temp = I915_READ(DISP_ARB_CTL);
+ I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
+ }
+
I915_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */
@@ -2755,10 +2882,16 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_framebuffer *intel_fb;
int pipe = intel_crtc->pipe;
uint32_t temp = 0;
uint32_t adder;
+ if (crtc->fb) {
+ intel_fb = to_intel_framebuffer(crtc->fb);
+ intel_mark_busy(dev, intel_fb->obj);
+ }
+
if (x < 0) {
temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
x = -x;
@@ -3056,6 +3189,315 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
return mode;
}
+#define GPU_IDLE_TIMEOUT 500 /* ms */
+
+/* When this timer fires, we've been idle for awhile */
+static void intel_gpu_idle_timer(unsigned long arg)
+{
+ struct drm_device *dev = (struct drm_device *)arg;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("idle timer fired, downclocking\n");
+
+ dev_priv->busy = false;
+
+ queue_work(dev_priv->wq, &dev_priv->idle_work);
+}
+
+void intel_increase_renderclock(struct drm_device *dev, bool schedule)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ if (IS_IGDNG(dev))
+ return;
+
+ if (!dev_priv->render_reclock_avail) {
+ DRM_DEBUG("not reclocking render clock\n");
+ return;
+ }
+
+ /* Restore render clock frequency to original value */
+ if (IS_G4X(dev) || IS_I9XX(dev))
+ pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
+ else if (IS_I85X(dev))
+ pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
+ DRM_DEBUG("increasing render clock frequency\n");
+
+ /* Schedule downclock */
+ if (schedule)
+ mod_timer(&dev_priv->idle_timer, jiffies +
+ msecs_to_jiffies(GPU_IDLE_TIMEOUT));
+}
+
+void intel_decrease_renderclock(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ if (IS_IGDNG(dev))
+ return;
+
+ if (!dev_priv->render_reclock_avail) {
+ DRM_DEBUG("not reclocking render clock\n");
+ return;
+ }
+
+ if (IS_G4X(dev)) {
+ u16 gcfgc;
+
+ /* Adjust render clock... */
+ pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
+
+ /* Down to minimum... */
+ gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
+ gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
+
+ pci_write_config_word(dev->pdev, GCFGC, gcfgc);
+ } else if (IS_I965G(dev)) {
+ u16 gcfgc;
+
+ /* Adjust render clock... */
+ pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
+
+ /* Down to minimum... */
+ gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
+ gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
+
+ pci_write_config_word(dev->pdev, GCFGC, gcfgc);
+ } else if (IS_I945G(dev) || IS_I945GM(dev)) {
+ u16 gcfgc;
+
+ /* Adjust render clock... */
+ pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
+
+ /* Down to minimum... */
+ gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
+ gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
+
+ pci_write_config_word(dev->pdev, GCFGC, gcfgc);
+ } else if (IS_I915G(dev)) {
+ u16 gcfgc;
+
+ /* Adjust render clock... */
+ pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
+
+ /* Down to minimum... */
+ gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
+ gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
+
+ pci_write_config_word(dev->pdev, GCFGC, gcfgc);
+ } else if (IS_I85X(dev)) {
+ u16 hpllcc;
+
+ /* Adjust render clock... */
+ pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
+
+ /* Up to maximum... */
+ hpllcc &= ~GC_CLOCK_CONTROL_MASK;
+ hpllcc |= GC_CLOCK_133_200;
+
+ pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
+ }
+ DRM_DEBUG("decreasing render clock frequency\n");
+}
+
+/* Note that no increase function is needed for this - increase_renderclock()
+ * will also rewrite these bits
+ */
+void intel_decrease_displayclock(struct drm_device *dev)
+{
+ if (IS_IGDNG(dev))
+ return;
+
+ if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
+ IS_I915GM(dev)) {
+ u16 gcfgc;
+
+ /* Adjust render clock... */
+ pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
+
+ /* Down to minimum... */
+ gcfgc &= ~0xf0;
+ gcfgc |= 0x80;
+
+ pci_write_config_word(dev->pdev, GCFGC, gcfgc);
+ }
+}
+
+#define CRTC_IDLE_TIMEOUT 1000 /* ms */
+
+static void intel_crtc_idle_timer(unsigned long arg)
+{
+ struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
+ struct drm_crtc *crtc = &intel_crtc->base;
+ drm_i915_private_t *dev_priv = crtc->dev->dev_private;
+
+ DRM_DEBUG("idle timer fired, downclocking\n");
+
+ intel_crtc->busy = false;
+
+ queue_work(dev_priv->wq, &dev_priv->idle_work);
+}
+
+static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)
+{
+ struct drm_device *dev = crtc->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int pipe = intel_crtc->pipe;
+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+ int dpll = I915_READ(dpll_reg);
+
+ if (IS_IGDNG(dev))
+ return;
+
+ if (!dev_priv->lvds_downclock_avail)
+ return;
+
+ if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
+ DRM_DEBUG("upclocking LVDS\n");
+
+ /* Unlock panel regs */
+ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
+
+ dpll &= ~DISPLAY_RATE_SELECT_FPA1;
+ I915_WRITE(dpll_reg, dpll);
+ dpll = I915_READ(dpll_reg);
+ intel_wait_for_vblank(dev);
+ dpll = I915_READ(dpll_reg);
+ if (dpll & DISPLAY_RATE_SELECT_FPA1)
+ DRM_DEBUG("failed to upclock LVDS!\n");
+
+ /* ...and lock them again */
+ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
+ }
+
+ /* Schedule downclock */
+ if (schedule)
+ mod_timer(&intel_crtc->idle_timer, jiffies +
+ msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+}
+
+static void intel_decrease_pllclock(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int pipe = intel_crtc->pipe;
+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+ int dpll = I915_READ(dpll_reg);
+
+ if (IS_IGDNG(dev))
+ return;
+
+ if (!dev_priv->lvds_downclock_avail)
+ return;
+
+ /*
+ * Since this is called by a timer, we should never get here in
+ * the manual case.
+ */
+ if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
+ DRM_DEBUG("downclocking LVDS\n");
+
+ /* Unlock panel regs */
+ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
+
+ dpll |= DISPLAY_RATE_SELECT_FPA1;
+ I915_WRITE(dpll_reg, dpll);
+ dpll = I915_READ(dpll_reg);
+ intel_wait_for_vblank(dev);
+ dpll = I915_READ(dpll_reg);
+ if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
+ DRM_DEBUG("failed to downclock LVDS!\n");
+
+ /* ...and lock them again */
+ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
+ }
+
+}
+
+/**
+ * intel_idle_update - adjust clocks for idleness
+ * @work: work struct
+ *
+ * Either the GPU or display (or both) went idle. Check the busy status
+ * here and adjust the CRTC and GPU clocks as necessary.
+ */
+static void intel_idle_update(struct work_struct *work)
+{
+ drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+ idle_work);
+ struct drm_device *dev = dev_priv->dev;
+ struct drm_crtc *crtc;
+ struct intel_crtc *intel_crtc;
+
+ if (!i915_powersave)
+ return;
+
+ mutex_lock(&dev->struct_mutex);
+
+ /* GPU isn't processing, downclock it. */
+ if (!dev_priv->busy) {
+ intel_decrease_renderclock(dev);
+ intel_decrease_displayclock(dev);
+ }
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ /* Skip inactive CRTCs */
+ if (!crtc->fb)
+ continue;
+
+ intel_crtc = to_intel_crtc(crtc);
+ if (!intel_crtc->busy)
+ intel_decrease_pllclock(crtc);
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * intel_mark_busy - mark the GPU and possibly the display busy
+ * @dev: drm device
+ * @obj: object we're operating on
+ *
+ * Callers can use this function to indicate that the GPU is busy processing
+ * commands. If @obj matches one of the CRTC objects (i.e. it's a scanout
+ * buffer), we'll also mark the display as busy, so we know to increase its
+ * clock frequency.
+ */
+void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc = NULL;
+ struct intel_framebuffer *intel_fb;
+ struct intel_crtc *intel_crtc;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
+ dev_priv->busy = true;
+ intel_increase_renderclock(dev, true);
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (!crtc->fb)
+ continue;
+
+ intel_crtc = to_intel_crtc(crtc);
+ intel_fb = to_intel_framebuffer(crtc->fb);
+ if (intel_fb->obj == obj) {
+ if (!intel_crtc->busy) {
+ /* Non-busy -> busy, upclock */
+ intel_increase_pllclock(crtc, true);
+ intel_crtc->busy = true;
+ } else {
+ /* Busy -> busy, put off timer */
+ mod_timer(&intel_crtc->idle_timer, jiffies +
+ msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+ }
+ }
+ }
+}
+
static void intel_crtc_destroy(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -3105,6 +3547,11 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
intel_crtc->cursor_addr = 0;
intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
+
+ intel_crtc->busy = false;
+
+ setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
+ (unsigned long)intel_crtc);
}
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -3112,30 +3559,26 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
- struct drm_crtc *crtc = NULL;
- int pipe = -1;
+ struct drm_mode_object *drmmode_obj;
+ struct intel_crtc *crtc;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- if (crtc->base.id == pipe_from_crtc_id->crtc_id) {
- pipe = intel_crtc->pipe;
- break;
- }
- }
+ drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
+ DRM_MODE_OBJECT_CRTC);
- if (pipe == -1) {
+ if (!drmmode_obj) {
DRM_ERROR("no such CRTC id\n");
return -EINVAL;
}
- pipe_from_crtc_id->pipe = pipe;
+ crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+ pipe_from_crtc_id->pipe = crtc->pipe;
- return 0;
+ return 0;
}
struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
@@ -3158,7 +3601,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct intel_output *intel_output = to_intel_output(connector);
- if (type_mask & (1 << intel_output->type))
+ if (type_mask & intel_output->clone_mask)
index_mask |= (1 << entry);
entry++;
}
@@ -3206,30 +3649,30 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_dp_init(dev, PCH_DP_D);
} else if (IS_I9XX(dev)) {
- int found;
- u32 reg;
+ bool found = false;
if (I915_READ(SDVOB) & SDVO_DETECTED) {
found = intel_sdvo_init(dev, SDVOB);
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
intel_hdmi_init(dev, SDVOB);
+
if (!found && SUPPORTS_INTEGRATED_DP(dev))
intel_dp_init(dev, DP_B);
}
/* Before G4X SDVOC doesn't have its own detect register */
- if (IS_G4X(dev))
- reg = SDVOC;
- else
- reg = SDVOB;
- if (I915_READ(reg) & SDVO_DETECTED) {
+ if (I915_READ(SDVOB) & SDVO_DETECTED)
found = intel_sdvo_init(dev, SDVOC);
- if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+
+ if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
+
+ if (SUPPORTS_INTEGRATED_HDMI(dev))
intel_hdmi_init(dev, SDVOC);
- if (!found && SUPPORTS_INTEGRATED_DP(dev))
+ if (SUPPORTS_INTEGRATED_DP(dev))
intel_dp_init(dev, DP_C);
}
+
if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
intel_dp_init(dev, DP_D);
} else
@@ -3241,51 +3684,10 @@ static void intel_setup_outputs(struct drm_device *dev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct intel_output *intel_output = to_intel_output(connector);
struct drm_encoder *encoder = &intel_output->enc;
- int crtc_mask = 0, clone_mask = 0;
- /* valid crtcs */
- switch(intel_output->type) {
- case INTEL_OUTPUT_HDMI:
- crtc_mask = ((1 << 0)|
- (1 << 1));
- clone_mask = ((1 << INTEL_OUTPUT_HDMI));
- break;
- case INTEL_OUTPUT_DVO:
- case INTEL_OUTPUT_SDVO:
- crtc_mask = ((1 << 0)|
- (1 << 1));
- clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
- (1 << INTEL_OUTPUT_DVO) |
- (1 << INTEL_OUTPUT_SDVO));
- break;
- case INTEL_OUTPUT_ANALOG:
- crtc_mask = ((1 << 0)|
- (1 << 1));
- clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
- (1 << INTEL_OUTPUT_DVO) |
- (1 << INTEL_OUTPUT_SDVO));
- break;
- case INTEL_OUTPUT_LVDS:
- crtc_mask = (1 << 1);
- clone_mask = (1 << INTEL_OUTPUT_LVDS);
- break;
- case INTEL_OUTPUT_TVOUT:
- crtc_mask = ((1 << 0) |
- (1 << 1));
- clone_mask = (1 << INTEL_OUTPUT_TVOUT);
- break;
- case INTEL_OUTPUT_DISPLAYPORT:
- crtc_mask = ((1 << 0) |
- (1 << 1));
- clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
- break;
- case INTEL_OUTPUT_EDP:
- crtc_mask = (1 << 1);
- clone_mask = (1 << INTEL_OUTPUT_EDP);
- break;
- }
- encoder->possible_crtcs = crtc_mask;
- encoder->possible_clones = intel_connector_clones(dev, clone_mask);
+ encoder->possible_crtcs = intel_output->crtc_mask;
+ encoder->possible_clones = intel_connector_clones(dev,
+ intel_output->clone_mask);
}
}
@@ -3377,8 +3779,56 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
.fb_changed = intelfb_probe,
};
+void intel_init_clock_gating(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /*
+ * Disable clock gating reported to work incorrectly according to the
+ * specs, but enable as much else as we can.
+ */
+ if (IS_G4X(dev)) {
+ uint32_t dspclk_gate;
+ I915_WRITE(RENCLK_GATE_D1, 0);
+ I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
+ GS_UNIT_CLOCK_GATE_DISABLE |
+ CL_UNIT_CLOCK_GATE_DISABLE);
+ I915_WRITE(RAMCLK_GATE_D, 0);
+ dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
+ OVRUNIT_CLOCK_GATE_DISABLE |
+ OVCUNIT_CLOCK_GATE_DISABLE;
+ if (IS_GM45(dev))
+ dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
+ I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
+ } else if (IS_I965GM(dev)) {
+ I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
+ I915_WRITE(RENCLK_GATE_D2, 0);
+ I915_WRITE(DSPCLK_GATE_D, 0);
+ I915_WRITE(RAMCLK_GATE_D, 0);
+ I915_WRITE16(DEUC, 0);
+ } else if (IS_I965G(dev)) {
+ I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
+ I965_RCC_CLOCK_GATE_DISABLE |
+ I965_RCPB_CLOCK_GATE_DISABLE |
+ I965_ISC_CLOCK_GATE_DISABLE |
+ I965_FBC_CLOCK_GATE_DISABLE);
+ I915_WRITE(RENCLK_GATE_D2, 0);
+ } else if (IS_I9XX(dev)) {
+ u32 dstate = I915_READ(D_STATE);
+
+ dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
+ DSTATE_DOT_CLOCK_GATING;
+ I915_WRITE(D_STATE, dstate);
+ } else if (IS_I855(dev) || IS_I865G(dev)) {
+ I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
+ } else if (IS_I830(dev)) {
+ I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
+ }
+}
+
void intel_modeset_init(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
int num_pipe;
int i;
@@ -3413,15 +3863,47 @@ void intel_modeset_init(struct drm_device *dev)
DRM_DEBUG("%d display pipe%s available.\n",
num_pipe, num_pipe > 1 ? "s" : "");
+ if (IS_I85X(dev))
+ pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
+ else if (IS_I9XX(dev) || IS_G4X(dev))
+ pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
+
for (i = 0; i < num_pipe; i++) {
intel_crtc_init(dev, i);
}
intel_setup_outputs(dev);
+
+ intel_init_clock_gating(dev);
+
+ INIT_WORK(&dev_priv->idle_work, intel_idle_update);
+ setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
+ (unsigned long)dev);
}
void intel_modeset_cleanup(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc;
+ struct intel_crtc *intel_crtc;
+
+ mutex_lock(&dev->struct_mutex);
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ /* Skip inactive CRTCs */
+ if (!crtc->fb)
+ continue;
+
+ intel_crtc = to_intel_crtc(crtc);
+ intel_increase_pllclock(crtc, false);
+ del_timer_sync(&intel_crtc->idle_timer);
+ }
+
+ intel_increase_renderclock(dev, false);
+ del_timer_sync(&dev_priv->idle_timer);
+
+ mutex_unlock(&dev->struct_mutex);
+
drm_mode_config_cleanup(dev);
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a6ff15ac548a..f2afc4af4bc9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1254,6 +1254,18 @@ intel_dp_init(struct drm_device *dev, int output_reg)
else
intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
+ if (output_reg == DP_B)
+ intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
+ else if (output_reg == DP_C)
+ intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
+ else if (output_reg == DP_D)
+ intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+
+ if (IS_eDP(intel_output)) {
+ intel_output->crtc_mask = (1 << 1);
+ intel_output->clone_mask = (1 << INTEL_OUTPUT_EDP);
+ } else
+ intel_output->crtc_mask = (1 << 0) | (1 << 1);
connector->interlace_allowed = true;
connector->doublescan_allowed = 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 38910f8f30ed..b9e47f1e1cc0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -57,6 +57,24 @@
#define INTEL_OUTPUT_DISPLAYPORT 7
#define INTEL_OUTPUT_EDP 8
+/* Intel Pipe Clone Bit */
+#define INTEL_HDMIB_CLONE_BIT 1
+#define INTEL_HDMIC_CLONE_BIT 2
+#define INTEL_HDMID_CLONE_BIT 3
+#define INTEL_HDMIE_CLONE_BIT 4
+#define INTEL_HDMIF_CLONE_BIT 5
+#define INTEL_SDVO_NON_TV_CLONE_BIT 6
+#define INTEL_SDVO_TV_CLONE_BIT 7
+#define INTEL_SDVO_LVDS_CLONE_BIT 8
+#define INTEL_ANALOG_CLONE_BIT 9
+#define INTEL_TV_CLONE_BIT 10
+#define INTEL_DP_B_CLONE_BIT 11
+#define INTEL_DP_C_CLONE_BIT 12
+#define INTEL_DP_D_CLONE_BIT 13
+#define INTEL_LVDS_CLONE_BIT 14
+#define INTEL_DVO_TMDS_CLONE_BIT 15
+#define INTEL_DVO_LVDS_CLONE_BIT 16
+
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
#define INTEL_DVO_CHIP_TMDS 2
@@ -86,6 +104,8 @@ struct intel_output {
bool needs_tv_clock;
void *dev_priv;
void (*hot_plug)(struct intel_output *);
+ int crtc_mask;
+ int clone_mask;
};
struct intel_crtc {
@@ -96,6 +116,9 @@ struct intel_crtc {
uint32_t cursor_addr;
u8 lut_r[256], lut_g[256], lut_b[256];
int dpms_mode;
+ bool busy; /* is scanout buffer being updated frequently? */
+ struct timer_list idle_timer;
+ bool lowfreq_avail;
};
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -114,6 +137,7 @@ extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
extern void intel_dvo_init(struct drm_device *dev);
extern void intel_tv_init(struct drm_device *dev);
+extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj);
extern void intel_lvds_init(struct drm_device *dev);
extern void intel_dp_init(struct drm_device *dev, int dp_reg);
void
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 13bff20930e8..a4d2606de778 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -435,14 +435,20 @@ void intel_dvo_init(struct drm_device *dev)
continue;
intel_output->type = INTEL_OUTPUT_DVO;
+ intel_output->crtc_mask = (1 << 0) | (1 << 1);
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
+ intel_output->clone_mask =
+ (1 << INTEL_DVO_TMDS_CLONE_BIT) |
+ (1 << INTEL_ANALOG_CLONE_BIT);
drm_connector_init(dev, connector,
&intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_DVII);
encoder_type = DRM_MODE_ENCODER_TMDS;
break;
case INTEL_DVO_CHIP_LVDS:
+ intel_output->clone_mask =
+ (1 << INTEL_DVO_LVDS_CLONE_BIT);
drm_connector_init(dev, connector,
&intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 1842290cded3..fa304e136010 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -230,22 +230,28 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
+ intel_output->crtc_mask = (1 << 0) | (1 << 1);
/* Set up the DDC bus. */
- if (sdvox_reg == SDVOB)
+ if (sdvox_reg == SDVOB) {
+ intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
- else if (sdvox_reg == SDVOC)
+ } else if (sdvox_reg == SDVOC) {
+ intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
- else if (sdvox_reg == HDMIB)
+ } else if (sdvox_reg == HDMIB) {
+ intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
"HDMIB");
- else if (sdvox_reg == HDMIC)
+ } else if (sdvox_reg == HDMIC) {
+ intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
"HDMIC");
- else if (sdvox_reg == HDMID)
+ } else if (sdvox_reg == HDMID) {
+ intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
"HDMID");
-
+ }
if (!intel_output->ddc_bus)
goto err_connector;
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 62b8bead7652..c7eab724c418 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -42,11 +42,11 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
if (!IS_IGD(dev))
return;
if (enable)
- I915_WRITE(CG_2D_DIS,
- I915_READ(CG_2D_DIS) | DPCUNIT_CLOCK_GATE_DISABLE);
+ I915_WRITE(DSPCLK_GATE_D,
+ I915_READ(DSPCLK_GATE_D) | DPCUNIT_CLOCK_GATE_DISABLE);
else
- I915_WRITE(CG_2D_DIS,
- I915_READ(CG_2D_DIS) & (~DPCUNIT_CLOCK_GATE_DISABLE));
+ I915_WRITE(DSPCLK_GATE_D,
+ I915_READ(DSPCLK_GATE_D) & (~DPCUNIT_CLOCK_GATE_DISABLE));
}
/*
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index b78c550ae866..dafc0da1c256 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -904,6 +904,8 @@ void intel_lvds_init(struct drm_device *dev)
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
intel_output->type = INTEL_OUTPUT_LVDS;
+ intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+ intel_output->crtc_mask = (1 << 1);
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 91238f0c39a5..0bf28efcf2c1 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -37,6 +37,19 @@
#include "intel_sdvo_regs.h"
#undef SDVO_DEBUG
+
+static char *tv_format_names[] = {
+ "NTSC_M" , "NTSC_J" , "NTSC_443",
+ "PAL_B" , "PAL_D" , "PAL_G" ,
+ "PAL_H" , "PAL_I" , "PAL_M" ,
+ "PAL_N" , "PAL_NC" , "PAL_60" ,
+ "SECAM_B" , "SECAM_D" , "SECAM_G" ,
+ "SECAM_K" , "SECAM_K1", "SECAM_L" ,
+ "SECAM_60"
+};
+
+#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
+
struct intel_sdvo_priv {
u8 slave_addr;
@@ -70,6 +83,15 @@ struct intel_sdvo_priv {
*/
bool is_tv;
+ /* This is for current tv format name */
+ char *tv_format_name;
+
+ /* This contains all current supported TV format */
+ char *tv_format_supported[TV_FORMAT_NUM];
+ int format_supported_num;
+ struct drm_property *tv_format_property;
+ struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
+
/**
* This is set if we treat the device as HDMI, instead of DVI.
*/
@@ -96,14 +118,6 @@ struct intel_sdvo_priv {
*/
struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
- /**
- * Current selected TV format.
- *
- * This is stored in the same structure that's passed to the device, for
- * convenience.
- */
- struct intel_sdvo_tv_format tv_format;
-
/*
* supported encoding mode, used to determine whether HDMI is
* supported
@@ -113,6 +127,9 @@ struct intel_sdvo_priv {
/* DDC bus used by this SDVO output */
uint8_t ddc_bus;
+ /* Mac mini hack -- use the same DDC as the analog connector */
+ struct i2c_adapter *analog_ddc_bus;
+
int save_sdvo_mult;
u16 save_active_outputs;
struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
@@ -944,23 +961,28 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
static void intel_sdvo_set_tv_format(struct intel_output *output)
{
+
+ struct intel_sdvo_tv_format format;
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
- struct intel_sdvo_tv_format *format, unset;
- u8 status;
+ uint32_t format_map, i;
+ uint8_t status;
- format = &sdvo_priv->tv_format;
- memset(&unset, 0, sizeof(unset));
- if (memcmp(format, &unset, sizeof(*format))) {
- DRM_DEBUG_KMS("%s: Choosing default TV format of NTSC-M\n",
- SDVO_NAME(sdvo_priv));
- format->ntsc_m = 1;
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
- sizeof(*format));
- status = intel_sdvo_read_response(output, NULL, 0);
- if (status != SDVO_CMD_STATUS_SUCCESS)
- DRM_DEBUG_KMS("%s: Failed to set TV format\n",
- SDVO_NAME(sdvo_priv));
- }
+ for (i = 0; i < TV_FORMAT_NUM; i++)
+ if (tv_format_names[i] == sdvo_priv->tv_format_name)
+ break;
+
+ format_map = 1 << i;
+ memset(&format, 0, sizeof(format));
+ memcpy(&format, &format_map, sizeof(format_map) > sizeof(format) ?
+ sizeof(format) : sizeof(format_map));
+
+ intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format_map,
+ sizeof(format));
+
+ status = intel_sdvo_read_response(output, NULL, 0);
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ DRM_DEBUG("%s: Failed to set TV format\n",
+ SDVO_NAME(sdvo_priv));
}
static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
@@ -1457,7 +1479,7 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
(SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
caps++;
if (sdvo_priv->caps.output_flags &
- (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID0))
+ (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
caps++;
if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
@@ -1477,6 +1499,36 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
return (caps > 1);
}
+static struct drm_connector *
+intel_find_analog_connector(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+ struct intel_output *intel_output;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ intel_output = to_intel_output(connector);
+ if (intel_output->type == INTEL_OUTPUT_ANALOG)
+ return connector;
+ }
+ return NULL;
+}
+
+static int
+intel_analog_is_connected(struct drm_device *dev)
+{
+ struct drm_connector *analog_connector;
+ analog_connector = intel_find_analog_connector(dev);
+
+ if (!analog_connector)
+ return false;
+
+ if (analog_connector->funcs->detect(analog_connector) ==
+ connector_status_disconnected)
+ return false;
+
+ return true;
+}
+
enum drm_connector_status
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
{
@@ -1487,6 +1539,15 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
edid = drm_get_edid(&intel_output->base,
intel_output->ddc_bus);
+
+ /* when there is no edid and no monitor is connected with VGA
+ * port, try to use the CRT ddc to read the EDID for DVI-connector
+ */
+ if (edid == NULL &&
+ sdvo_priv->analog_ddc_bus &&
+ !intel_analog_is_connected(intel_output->base.dev))
+ edid = drm_get_edid(&intel_output->base,
+ sdvo_priv->analog_ddc_bus);
if (edid != NULL) {
/* Don't report the output as connected if it's a DVI-I
* connector with a non-digital EDID coming out.
@@ -1515,7 +1576,8 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+ intel_sdvo_write_cmd(intel_output,
+ SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, 2);
DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8);
@@ -1539,50 +1601,32 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ int num_modes;
/* set the bus switch and get the modes */
- intel_ddc_get_modes(intel_output);
+ num_modes = intel_ddc_get_modes(intel_output);
-#if 0
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- /* Mac mini hack. On this device, I get DDC through the analog, which
- * load-detects as disconnected. I fail to DDC through the SDVO DDC,
- * but it does load-detect as connected. So, just steal the DDC bits
- * from analog when we fail at finding it the right way.
+ /*
+ * Mac mini hack. On this device, the DVI-I connector shares one DDC
+ * link between analog and digital outputs. So, if the regular SDVO
+ * DDC fails, check to see if the analog output is disconnected, in
+ * which case we'll look there for the digital DDC data.
*/
- crt = xf86_config->output[0];
- intel_output = crt->driver_private;
- if (intel_output->type == I830_OUTPUT_ANALOG &&
- crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
- I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A");
- edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus);
- xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true);
- }
- if (edid_mon) {
- xf86OutputSetEDID(output, edid_mon);
- modes = xf86OutputGetEDIDModes(output);
- }
-#endif
-}
+ if (num_modes == 0 &&
+ sdvo_priv->analog_ddc_bus &&
+ !intel_analog_is_connected(intel_output->base.dev)) {
+ struct i2c_adapter *digital_ddc_bus;
-/**
- * This function checks the current TV format, and chooses a default if
- * it hasn't been set.
- */
-static void
-intel_sdvo_check_tv_format(struct intel_output *output)
-{
- struct intel_sdvo_priv *dev_priv = output->dev_priv;
- struct intel_sdvo_tv_format format;
- uint8_t status;
+ /* Switch to the analog ddc bus and try that
+ */
+ digital_ddc_bus = intel_output->ddc_bus;
+ intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
- status = intel_sdvo_read_response(output, &format, sizeof(format));
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return;
+ (void) intel_ddc_get_modes(intel_output);
- memcpy(&dev_priv->tv_format, &format, sizeof(format));
+ intel_output->ddc_bus = digital_ddc_bus;
+ }
}
/*
@@ -1655,17 +1699,26 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
struct intel_output *output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
struct intel_sdvo_sdtv_resolution_request tv_res;
- uint32_t reply = 0;
+ uint32_t reply = 0, format_map = 0;
+ int i;
uint8_t status;
- int i = 0;
- intel_sdvo_check_tv_format(output);
/* Read the list of supported input resolutions for the selected TV
* format.
*/
- memset(&tv_res, 0, sizeof(tv_res));
- memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
+ for (i = 0; i < TV_FORMAT_NUM; i++)
+ if (tv_format_names[i] == sdvo_priv->tv_format_name)
+ break;
+
+ format_map = (1 << i);
+ memcpy(&tv_res, &format_map,
+ sizeof(struct intel_sdvo_sdtv_resolution_request) >
+ sizeof(format_map) ? sizeof(format_map) :
+ sizeof(struct intel_sdvo_sdtv_resolution_request));
+
+ intel_sdvo_set_target_output(output, sdvo_priv->controlled_output);
+
intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
&tv_res, sizeof(tv_res));
status = intel_sdvo_read_response(output, &reply, 3);
@@ -1680,6 +1733,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
if (nmode)
drm_mode_probed_add(connector, nmode);
}
+
}
static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
@@ -1747,17 +1801,62 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
intel_i2c_destroy(intel_output->i2c_bus);
if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus);
+ if (sdvo_priv->analog_ddc_bus)
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
drm_mode_destroy(connector->dev,
sdvo_priv->sdvo_lvds_fixed_mode);
+ if (sdvo_priv->tv_format_property)
+ drm_property_destroy(connector->dev,
+ sdvo_priv->tv_format_property);
+
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
kfree(intel_output);
}
+static int
+intel_sdvo_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ struct drm_encoder *encoder = &intel_output->enc;
+ struct drm_crtc *crtc = encoder->crtc;
+ int ret = 0;
+ bool changed = false;
+
+ ret = drm_connector_property_set_value(connector, property, val);
+ if (ret < 0)
+ goto out;
+
+ if (property == sdvo_priv->tv_format_property) {
+ if (val >= TV_FORMAT_NUM) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (sdvo_priv->tv_format_name ==
+ sdvo_priv->tv_format_supported[val])
+ goto out;
+
+ sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
+ changed = true;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (changed && crtc)
+ drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
+ crtc->y, crtc->fb);
+out:
+ return ret;
+}
+
static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
.dpms = intel_sdvo_dpms,
.mode_fixup = intel_sdvo_mode_fixup,
@@ -1772,6 +1871,7 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
.restore = intel_sdvo_restore,
.detect = intel_sdvo_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = intel_sdvo_set_property,
.destroy = intel_sdvo_destroy,
};
@@ -1966,6 +2066,9 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
intel_sdvo_set_colorimetry(intel_output,
SDVO_COLORIMETRY_RGB256);
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ intel_output->clone_mask =
+ (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+ (1 << INTEL_ANALOG_CLONE_BIT);
}
} else if (flags & SDVO_OUTPUT_SVID0) {
@@ -1974,11 +2077,14 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
sdvo_priv->is_tv = true;
intel_output->needs_tv_clock = true;
+ intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
} else if (flags & SDVO_OUTPUT_RGB0) {
sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
encoder->encoder_type = DRM_MODE_ENCODER_DAC;
connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+ intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+ (1 << INTEL_ANALOG_CLONE_BIT);
} else if (flags & SDVO_OUTPUT_RGB1) {
sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
@@ -1990,12 +2096,16 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
sdvo_priv->is_lvds = true;
+ intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+ (1 << INTEL_SDVO_LVDS_CLONE_BIT);
} else if (flags & SDVO_OUTPUT_LVDS1) {
sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
sdvo_priv->is_lvds = true;
+ intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+ (1 << INTEL_SDVO_LVDS_CLONE_BIT);
} else {
unsigned char bytes[2];
@@ -2007,6 +2117,7 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
bytes[0], bytes[1]);
ret = false;
}
+ intel_output->crtc_mask = (1 << 0) | (1 << 1);
if (ret && registered)
ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
@@ -2016,6 +2127,55 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
}
+static void intel_sdvo_tv_create_property(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ struct intel_sdvo_tv_format format;
+ uint32_t format_map, i;
+ uint8_t status;
+
+ intel_sdvo_set_target_output(intel_output,
+ sdvo_priv->controlled_output);
+
+ intel_sdvo_write_cmd(intel_output,
+ SDVO_CMD_GET_SUPPORTED_TV_FORMATS, NULL, 0);
+ status = intel_sdvo_read_response(intel_output,
+ &format, sizeof(format));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return;
+
+ memcpy(&format_map, &format, sizeof(format) > sizeof(format_map) ?
+ sizeof(format_map) : sizeof(format));
+
+ if (format_map == 0)
+ return;
+
+ sdvo_priv->format_supported_num = 0;
+ for (i = 0 ; i < TV_FORMAT_NUM; i++)
+ if (format_map & (1 << i)) {
+ sdvo_priv->tv_format_supported
+ [sdvo_priv->format_supported_num++] =
+ tv_format_names[i];
+ }
+
+
+ sdvo_priv->tv_format_property =
+ drm_property_create(
+ connector->dev, DRM_MODE_PROP_ENUM,
+ "mode", sdvo_priv->format_supported_num);
+
+ for (i = 0; i < sdvo_priv->format_supported_num; i++)
+ drm_property_add_enum(
+ sdvo_priv->tv_format_property, i,
+ i, sdvo_priv->tv_format_supported[i]);
+
+ sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[0];
+ drm_connector_attach_property(
+ connector, sdvo_priv->tv_format_property, 0);
+
+}
+
bool intel_sdvo_init(struct drm_device *dev, int output_device)
{
struct drm_connector *connector;
@@ -2060,10 +2220,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
}
/* setup the DDC bus. */
- if (output_device == SDVOB)
+ if (output_device == SDVOB) {
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
- else
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVOB/VGA DDC BUS");
+ } else {
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVOC/VGA DDC BUS");
+ }
if (intel_output->ddc_bus == NULL)
goto err_i2c;
@@ -2097,6 +2262,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
+ if (sdvo_priv->is_tv)
+ intel_sdvo_tv_create_property(connector);
drm_sysfs_connector_add(connector);
intel_sdvo_select_ddc_bus(sdvo_priv);
@@ -2129,6 +2296,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
return true;
err_i2c:
+ if (sdvo_priv->analog_ddc_bus != NULL)
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
if (intel_output->ddc_bus != NULL)
intel_i2c_destroy(intel_output->ddc_bus);
if (intel_output->i2c_bus != NULL)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index da4ab4dc1630..a6c686cded54 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1437,6 +1437,35 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
return type;
}
+/*
+ * Here we set accurate tv format according to connector type
+ * i.e Component TV should not be assigned by NTSC or PAL
+ */
+static void intel_tv_find_better_format(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_tv_priv *tv_priv = intel_output->dev_priv;
+ const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
+ int i;
+
+ if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
+ tv_mode->component_only)
+ return;
+
+
+ for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
+ tv_mode = tv_modes + i;
+
+ if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
+ tv_mode->component_only)
+ break;
+ }
+
+ tv_priv->tv_format = tv_mode->name;
+ drm_connector_property_set_value(connector,
+ connector->dev->mode_config.tv_mode_property, i);
+}
+
/**
* Detect the TV connection.
*
@@ -1473,6 +1502,7 @@ intel_tv_detect(struct drm_connector *connector)
if (type < 0)
return connector_status_disconnected;
+ intel_tv_find_better_format(connector);
return connector_status_connected;
}
@@ -1718,6 +1748,7 @@ intel_tv_init(struct drm_device *dev)
if (!intel_output) {
return;
}
+
connector = &intel_output->base;
drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@@ -1729,6 +1760,7 @@ intel_tv_init(struct drm_device *dev)
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
tv_priv = (struct intel_tv_priv *)(intel_output + 1);
intel_output->type = INTEL_OUTPUT_TVOUT;
+ intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT);
intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_output->dev_priv = tv_priv;
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 639d5b216eed..44f34f8e2b32 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1140,6 +1140,16 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
tmp |= tile_flags;
ib[idx] = tmp;
break;
+ case RADEON_RB3D_ZPASS_ADDR:
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+ idx, reg);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ break;
default:
/* FIXME: we don't want to allow anyothers packet */
break;
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 482d6b296b74..9f2460cf9dbc 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -450,6 +450,7 @@ void r300_gpu_init(struct radeon_device *rdev)
/* rv350,rv370,rv380 */
rdev->num_gb_pipes = 1;
}
+ rdev->num_z_pipes = 1;
gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
switch (rdev->num_gb_pipes) {
case 2:
@@ -488,7 +489,8 @@ void r300_gpu_init(struct radeon_device *rdev)
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
}
- DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes);
+ DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n",
+ rdev->num_gb_pipes, rdev->num_z_pipes);
}
int r300_ga_reset(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index dea497a979f2..97426a6f370f 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -165,7 +165,18 @@ void r420_pipes_init(struct radeon_device *rdev)
printk(KERN_WARNING "Failed to wait GUI idle while "
"programming pipes. Bad things might happen.\n");
}
- DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes);
+
+ if (rdev->family == CHIP_RV530) {
+ tmp = RREG32(RV530_GB_PIPE_SELECT2);
+ if ((tmp & 3) == 3)
+ rdev->num_z_pipes = 2;
+ else
+ rdev->num_z_pipes = 1;
+ } else
+ rdev->num_z_pipes = 1;
+
+ DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n",
+ rdev->num_gb_pipes, rdev->num_z_pipes);
}
void r420_gpu_init(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
index 09fb0b6ec7dd..ebd6b0f7bdff 100644
--- a/drivers/gpu/drm/radeon/r520.c
+++ b/drivers/gpu/drm/radeon/r520.c
@@ -177,7 +177,6 @@ void r520_gpu_init(struct radeon_device *rdev)
*/
/* workaround for RV530 */
if (rdev->family == CHIP_RV530) {
- WREG32(0x4124, 1);
WREG32(0x4128, 0xFF);
}
r420_pipes_init(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 1041a7c28051..149974d13aa2 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -655,6 +655,7 @@ struct radeon_device {
int usec_timeout;
enum radeon_pll_errata pll_errata;
int num_gb_pipes;
+ int num_z_pipes;
int disp_priority;
/* BIOS */
uint8_t *bios;
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 6b6cc8434d3c..fa063d0cfb63 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -421,6 +421,15 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
{
uint32_t gb_tile_config, gb_pipe_sel = 0;
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
+ uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
+ if ((z_pipe_sel & 3) == 3)
+ dev_priv->num_z_pipes = 2;
+ else
+ dev_priv->num_z_pipes = 1;
+ } else
+ dev_priv->num_z_pipes = 1;
+
/* RS4xx/RS6xx/R4xx/R5xx */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 45a6ad997f5f..40294a07976f 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -103,9 +103,10 @@
* 1.28- Add support for VBL on CRTC2
* 1.29- R500 3D cmd buffer support
* 1.30- Add support for occlusion queries
+ * 1.31- Add support for num Z pipes from GET_PARAM
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 30
+#define DRIVER_MINOR 31
#define DRIVER_PATCHLEVEL 0
/*
@@ -332,6 +333,7 @@ typedef struct drm_radeon_private {
resource_size_t fb_aper_offset;
int num_gb_pipes;
+ int num_z_pipes;
int track_flush;
drm_local_map_t *mmio;
@@ -694,6 +696,7 @@ extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pciga
/* pipe config regs */
#define R400_GB_PIPE_SELECT 0x402c
+#define RV530_GB_PIPE_SELECT2 0x4124
#define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */
#define R300_GB_TILE_CONFIG 0x4018
# define R300_ENABLE_TILING (1 << 0)
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index d4ceff13bbb1..d880edf254db 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -274,16 +274,22 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
}
robj = gobj->driver_private;
r = radeon_object_busy_domain(robj, &cur_placement);
- if (cur_placement == TTM_PL_VRAM)
+ switch (cur_placement) {
+ case TTM_PL_VRAM:
args->domain = RADEON_GEM_DOMAIN_VRAM;
- if (cur_placement == TTM_PL_FLAG_TT)
+ break;
+ case TTM_PL_TT:
args->domain = RADEON_GEM_DOMAIN_GTT;
- if (cur_placement == TTM_PL_FLAG_SYSTEM)
+ break;
+ case TTM_PL_SYSTEM:
args->domain = RADEON_GEM_DOMAIN_CPU;
+ default:
+ break;
+ }
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
- return 0;
+ return r;
}
int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index d2764bf6b2a2..dce09ada32bc 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -95,6 +95,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
case RADEON_INFO_NUM_GB_PIPES:
value = rdev->num_gb_pipes;
break;
+ case RADEON_INFO_NUM_Z_PIPES:
+ value = rdev->num_z_pipes;
+ break;
default:
DRM_DEBUG("Invalid request %d\n", info->request);
return -EINVAL;
@@ -318,5 +321,6 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH),
};
int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index 5a098f304edb..4df43f62c678 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -2337,6 +2337,9 @@
# define RADEON_RE_WIDTH_SHIFT 0
# define RADEON_RE_HEIGHT_SHIFT 16
+#define RADEON_RB3D_ZPASS_DATA 0x3290
+#define RADEON_RB3D_ZPASS_ADDR 0x3294
+
#define RADEON_SE_CNTL 0x1c4c
# define RADEON_FFACE_CULL_CW (0 << 0)
# define RADEON_FFACE_CULL_CCW (1 << 0)
@@ -3571,4 +3574,6 @@
#define RADEON_SCRATCH_REG4 0x15f0
#define RADEON_SCRATCH_REG5 0x15f4
+#define RV530_GB_PIPE_SELECT2 0x4124
+
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 46645f3e0328..2882f40d5ec5 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -3081,6 +3081,9 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
case RADEON_PARAM_NUM_GB_PIPES:
value = dev_priv->num_gb_pipes;
break;
+ case RADEON_PARAM_NUM_Z_PIPES:
+ value = dev_priv->num_z_pipes;
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", param->param);
return -EINVAL;
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index d258b02aef44..827da0858136 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -674,7 +674,14 @@ omap_i2c_isr(int this_irq, void *dev_id)
err = 0;
complete:
- omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+ /*
+ * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
+ * acked after the data operation is complete.
+ * Ref: TRM SWPU114Q Figure 18-31
+ */
+ omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+ ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+ OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
if (stat & OMAP_I2C_STAT_NACK) {
err |= OMAP_I2C_STAT_NACK;
@@ -687,6 +694,9 @@ complete:
}
if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
OMAP_I2C_STAT_AL)) {
+ omap_i2c_ack_stat(dev, stat &
+ (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+ OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
omap_i2c_complete_cmd(dev, err);
return IRQ_HANDLED;
}
@@ -774,7 +784,7 @@ complete:
* memory to the I2C interface.
*/
- if (cpu_is_omap34xx()) {
+ if (dev->rev <= OMAP_I2C_REV_ON_3430) {
while (!(stat & OMAP_I2C_STAT_XUDF)) {
if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 182e711318ba..d2728a28a8db 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -117,7 +117,8 @@ enum stu300_error {
STU300_ERROR_NONE = 0,
STU300_ERROR_ACKNOWLEDGE_FAILURE,
STU300_ERROR_BUS_ERROR,
- STU300_ERROR_ARBITRATION_LOST
+ STU300_ERROR_ARBITRATION_LOST,
+ STU300_ERROR_UNKNOWN
};
/* timeout waiting for the controller to respond */
@@ -127,7 +128,7 @@ enum stu300_error {
* The number of address send athemps tried before giving up.
* If the first one failes it seems like 5 to 8 attempts are required.
*/
-#define NUM_ADDR_RESEND_ATTEMPTS 10
+#define NUM_ADDR_RESEND_ATTEMPTS 12
/* I2C clock speed, in Hz 0-400kHz*/
static unsigned int scl_frequency = 100000;
@@ -149,6 +150,7 @@ module_param(scl_frequency, uint, 0644);
* @msg_index: index of current message
* @msg_len: length of current message
*/
+
struct stu300_dev {
struct platform_device *pdev;
struct i2c_adapter adapter;
@@ -188,6 +190,27 @@ static inline u32 stu300_r8(void __iomem *address)
return readl(address) & 0x000000FFU;
}
+static void stu300_irq_enable(struct stu300_dev *dev)
+{
+ u32 val;
+ val = stu300_r8(dev->virtbase + I2C_CR);
+ val |= I2C_CR_INTERRUPT_ENABLE;
+ /* Twice paranoia (possible HW glitch) */
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+static void stu300_irq_disable(struct stu300_dev *dev)
+{
+ u32 val;
+ val = stu300_r8(dev->virtbase + I2C_CR);
+ val &= ~I2C_CR_INTERRUPT_ENABLE;
+ /* Twice paranoia (possible HW glitch) */
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+
/*
* Tells whether a certain event or events occurred in
* response to a command. The events represent states in
@@ -196,9 +219,10 @@ static inline u32 stu300_r8(void __iomem *address)
* documentation and can only be treated as abstract state
* machine states.
*
- * @ret 0 = event has not occurred, any other value means
- * the event occurred.
+ * @ret 0 = event has not occurred or unknown error, any
+ * other value means the correct event occurred or an error.
*/
+
static int stu300_event_occurred(struct stu300_dev *dev,
enum stu300_event mr_event) {
u32 status1;
@@ -206,11 +230,28 @@ static int stu300_event_occurred(struct stu300_dev *dev,
/* What event happened? */
status1 = stu300_r8(dev->virtbase + I2C_SR1);
+
if (!(status1 & I2C_SR1_EVF_IND))
/* No event at all */
return 0;
+
status2 = stu300_r8(dev->virtbase + I2C_SR2);
+ /* Block any multiple interrupts */
+ stu300_irq_disable(dev);
+
+ /* Check for errors first */
+ if (status2 & I2C_SR2_AF_IND) {
+ dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
+ return 1;
+ } else if (status2 & I2C_SR2_BERR_IND) {
+ dev->cmd_err = STU300_ERROR_BUS_ERROR;
+ return 1;
+ } else if (status2 & I2C_SR2_ARLO_IND) {
+ dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+ return 1;
+ }
+
switch (mr_event) {
case STU300_EVENT_1:
if (status1 & I2C_SR1_ADSL_IND)
@@ -221,10 +262,6 @@ static int stu300_event_occurred(struct stu300_dev *dev,
case STU300_EVENT_7:
case STU300_EVENT_8:
if (status1 & I2C_SR1_BTF_IND) {
- if (status2 & I2C_SR2_AF_IND)
- dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
- else if (status2 & I2C_SR2_BERR_IND)
- dev->cmd_err = STU300_ERROR_BUS_ERROR;
return 1;
}
break;
@@ -240,8 +277,6 @@ static int stu300_event_occurred(struct stu300_dev *dev,
case STU300_EVENT_6:
if (status2 & I2C_SR2_ENDAD_IND) {
/* First check for any errors */
- if (status2 & I2C_SR2_AF_IND)
- dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
return 1;
}
break;
@@ -252,8 +287,15 @@ static int stu300_event_occurred(struct stu300_dev *dev,
default:
break;
}
- if (status2 & I2C_SR2_ARLO_IND)
- dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+ /* If we get here, we're on thin ice.
+ * Here we are in a status where we have
+ * gotten a response that does not match
+ * what we requested.
+ */
+ dev->cmd_err = STU300_ERROR_UNKNOWN;
+ dev_err(&dev->pdev->dev,
+ "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n",
+ mr_event, status1, status2);
return 0;
}
@@ -262,21 +304,20 @@ static irqreturn_t stu300_irh(int irq, void *data)
struct stu300_dev *dev = data;
int res;
+ /* Just make sure that the block is clocked */
+ clk_enable(dev->clk);
+
/* See if this was what we were waiting for */
spin_lock(&dev->cmd_issue_lock);
- if (dev->cmd_event != STU300_EVENT_NONE) {
- res = stu300_event_occurred(dev, dev->cmd_event);
- if (res || dev->cmd_err != STU300_ERROR_NONE) {
- u32 val;
-
- complete(&dev->cmd_complete);
- /* Block any multiple interrupts */
- val = stu300_r8(dev->virtbase + I2C_CR);
- val &= ~I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
- }
- }
+
+ res = stu300_event_occurred(dev, dev->cmd_event);
+ if (res || dev->cmd_err != STU300_ERROR_NONE)
+ complete(&dev->cmd_complete);
+
spin_unlock(&dev->cmd_issue_lock);
+
+ clk_disable(dev->clk);
+
return IRQ_HANDLED;
}
@@ -308,7 +349,6 @@ static int stu300_start_and_await_event(struct stu300_dev *dev,
stu300_wr8(cr_value, dev->virtbase + I2C_CR);
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
STU300_TIMEOUT);
-
if (ret < 0) {
dev_err(&dev->pdev->dev,
"wait_for_completion_interruptible_timeout() "
@@ -342,7 +382,6 @@ static int stu300_await_event(struct stu300_dev *dev,
enum stu300_event mr_event)
{
int ret;
- u32 val;
if (unlikely(irqs_disabled())) {
/* TODO: implement polling for this case if need be. */
@@ -354,36 +393,18 @@ static int stu300_await_event(struct stu300_dev *dev,
/* Is it already here? */
spin_lock_irq(&dev->cmd_issue_lock);
dev->cmd_err = STU300_ERROR_NONE;
- if (stu300_event_occurred(dev, mr_event)) {
- spin_unlock_irq(&dev->cmd_issue_lock);
- goto exit_await_check_err;
- }
- init_completion(&dev->cmd_complete);
- dev->cmd_err = STU300_ERROR_NONE;
dev->cmd_event = mr_event;
- /* Turn on the I2C interrupt for current operation */
- val = stu300_r8(dev->virtbase + I2C_CR);
- val |= I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
-
- /* Twice paranoia (possible HW glitch) */
- stu300_wr8(val, dev->virtbase + I2C_CR);
+ init_completion(&dev->cmd_complete);
- /* Check again: is it already here? */
- if (unlikely(stu300_event_occurred(dev, mr_event))) {
- /* Disable IRQ again. */
- val &= ~I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
- spin_unlock_irq(&dev->cmd_issue_lock);
- goto exit_await_check_err;
- }
+ /* Turn on the I2C interrupt for current operation */
+ stu300_irq_enable(dev);
/* Unlock the command block and wait for the event to occur */
spin_unlock_irq(&dev->cmd_issue_lock);
+
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
STU300_TIMEOUT);
-
if (ret < 0) {
dev_err(&dev->pdev->dev,
"wait_for_completion_interruptible_timeout()"
@@ -401,7 +422,6 @@ static int stu300_await_event(struct stu300_dev *dev,
return -ETIMEDOUT;
}
- exit_await_check_err:
if (dev->cmd_err != STU300_ERROR_NONE) {
if (mr_event != STU300_EVENT_6) {
dev_err(&dev->pdev->dev, "controller "
@@ -457,18 +477,19 @@ struct stu300_clkset {
};
static const struct stu300_clkset stu300_clktable[] = {
- { 0, 0xFFU },
- { 2500000, I2C_OAR2_FR_25_10MHZ },
- { 10000000, I2C_OAR2_FR_10_1667MHZ },
- { 16670000, I2C_OAR2_FR_1667_2667MHZ },
- { 26670000, I2C_OAR2_FR_2667_40MHZ },
- { 40000000, I2C_OAR2_FR_40_5333MHZ },
- { 53330000, I2C_OAR2_FR_5333_66MHZ },
- { 66000000, I2C_OAR2_FR_66_80MHZ },
- { 80000000, I2C_OAR2_FR_80_100MHZ },
+ { 0, 0xFFU },
+ { 2500000, I2C_OAR2_FR_25_10MHZ },
+ { 10000000, I2C_OAR2_FR_10_1667MHZ },
+ { 16670000, I2C_OAR2_FR_1667_2667MHZ },
+ { 26670000, I2C_OAR2_FR_2667_40MHZ },
+ { 40000000, I2C_OAR2_FR_40_5333MHZ },
+ { 53330000, I2C_OAR2_FR_5333_66MHZ },
+ { 66000000, I2C_OAR2_FR_66_80MHZ },
+ { 80000000, I2C_OAR2_FR_80_100MHZ },
{ 100000000, 0xFFU },
};
+
static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
{
@@ -494,10 +515,10 @@ static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
if (dev->speed > 100000)
/* Fast Mode I2C */
- val = ((clkrate/dev->speed)-9)/3;
+ val = ((clkrate/dev->speed) - 9)/3 + 1;
else
/* Standard Mode I2C */
- val = ((clkrate/dev->speed)-7)/2;
+ val = ((clkrate/dev->speed) - 7)/2 + 1;
/* According to spec the divider must be > 2 */
if (val < 0x002) {
@@ -557,6 +578,7 @@ static int stu300_init_hw(struct stu300_dev *dev)
*/
clkrate = clk_get_rate(dev->clk);
ret = stu300_set_clk(dev, clkrate);
+
if (ret)
return ret;
/*
@@ -641,7 +663,6 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
int attempts = 0;
struct stu300_dev *dev = i2c_get_adapdata(adap);
-
clk_enable(dev->clk);
/* Remove this if (0) to trace each and every message. */
@@ -715,14 +736,15 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) {
dev_dbg(&dev->pdev->dev, "managed to get address "
- "through after %d attempts\n", attempts);
+ "through after %d attempts\n", attempts);
} else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) {
dev_dbg(&dev->pdev->dev, "I give up, tried %d times "
- "to resend address.\n",
- NUM_ADDR_RESEND_ATTEMPTS);
+ "to resend address.\n",
+ NUM_ADDR_RESEND_ATTEMPTS);
goto exit_disable;
}
+
if (msg->flags & I2C_M_RD) {
/* READ: we read the actual bytes one at a time */
for (i = 0; i < msg->len; i++) {
@@ -804,8 +826,10 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
{
int ret = -1;
int i;
+
struct stu300_dev *dev = i2c_get_adapdata(adap);
dev->msg_len = num;
+
for (i = 0; i < num; i++) {
/*
* Another driver appears to send stop for each message,
@@ -817,6 +841,7 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
dev->msg_index = i;
ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+
if (ret != 0) {
num = ret;
break;
@@ -845,6 +870,7 @@ stu300_probe(struct platform_device *pdev)
struct resource *res;
int bus_nr;
int ret = 0;
+ char clk_name[] = "I2C0";
dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL);
if (!dev) {
@@ -854,7 +880,8 @@ stu300_probe(struct platform_device *pdev)
}
bus_nr = pdev->id;
- dev->clk = clk_get(&pdev->dev, NULL);
+ clk_name[3] += (char)bus_nr;
+ dev->clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 4cfd084fa897..9a1d55b74d7a 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -456,8 +456,11 @@ static int joydev_ioctl_common(struct joydev *joydev,
unsigned int cmd, void __user *argp)
{
struct input_dev *dev = joydev->handle.dev;
+ size_t len;
int i, j;
+ const char *name;
+ /* Process fixed-sized commands. */
switch (cmd) {
case JS_SET_CAL:
@@ -499,9 +502,22 @@ static int joydev_ioctl_common(struct joydev *joydev,
return copy_to_user(argp, joydev->corr,
sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
- case JSIOCSAXMAP:
- if (copy_from_user(joydev->abspam, argp,
- sizeof(__u8) * (ABS_MAX + 1)))
+ }
+
+ /*
+ * Process variable-sized commands (the axis and button map commands
+ * are considered variable-sized to decouple them from the values of
+ * ABS_MAX and KEY_MAX).
+ */
+ switch (cmd & ~IOCSIZE_MASK) {
+
+ case (JSIOCSAXMAP & ~IOCSIZE_MASK):
+ len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
+ /*
+ * FIXME: we should not copy into our axis map before
+ * validating the data.
+ */
+ if (copy_from_user(joydev->abspam, argp, len))
return -EFAULT;
for (i = 0; i < joydev->nabs; i++) {
@@ -511,13 +527,17 @@ static int joydev_ioctl_common(struct joydev *joydev,
}
return 0;
- case JSIOCGAXMAP:
- return copy_to_user(argp, joydev->abspam,
- sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
-
- case JSIOCSBTNMAP:
- if (copy_from_user(joydev->keypam, argp,
- sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
+ case (JSIOCGAXMAP & ~IOCSIZE_MASK):
+ len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
+ return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0;
+
+ case (JSIOCSBTNMAP & ~IOCSIZE_MASK):
+ len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
+ /*
+ * FIXME: we should not copy into our keymap before
+ * validating the data.
+ */
+ if (copy_from_user(joydev->keypam, argp, len))
return -EFAULT;
for (i = 0; i < joydev->nkey; i++) {
@@ -529,25 +549,19 @@ static int joydev_ioctl_common(struct joydev *joydev,
return 0;
- case JSIOCGBTNMAP:
- return copy_to_user(argp, joydev->keypam,
- sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
+ case (JSIOCGBTNMAP & ~IOCSIZE_MASK):
+ len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
+ return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0;
- default:
- if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
- int len;
- const char *name = dev->name;
-
- if (!name)
- return 0;
- len = strlen(name) + 1;
- if (len > _IOC_SIZE(cmd))
- len = _IOC_SIZE(cmd);
- if (copy_to_user(argp, name, len))
- return -EFAULT;
- return len;
- }
+ case JSIOCGNAME(0):
+ name = dev->name;
+ if (!name)
+ return 0;
+
+ len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1);
+ return copy_to_user(argp, name, len) ? -EFAULT : len;
}
+
return -EINVAL;
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index baabf8302645..f6c688cae334 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -74,6 +74,7 @@ static struct iforce_device iforce_device[] = {
{ 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce },
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
+ { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce },
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index f83185aeb511..9f289d8f52c6 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -223,6 +223,7 @@ static struct usb_device_id iforce_usb_ids [] = {
{ USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */
{ USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */
{ USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
+ { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
{ USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index a9d5031b855e..ea30c983a33e 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -388,6 +388,32 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
return result;
}
+static int wacom_query_tablet_data(struct usb_interface *intf)
+{
+ unsigned char *rep_data;
+ int limit = 0;
+ int error;
+
+ rep_data = kmalloc(2, GFP_KERNEL);
+ if (!rep_data)
+ return -ENOMEM;
+
+ do {
+ rep_data[0] = 2;
+ rep_data[1] = 2;
+ error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+ 2, rep_data, 2);
+ if (error >= 0)
+ error = usb_get_report(intf,
+ WAC_HID_FEATURE_REPORT, 2,
+ rep_data, 2);
+ } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+
+ kfree(rep_data);
+
+ return error < 0 ? error : 0;
+}
+
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -398,7 +424,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct wacom_features *features;
struct input_dev *input_dev;
int error = -ENOMEM;
- char rep_data[2], limit = 0;
struct hid_descriptor *hid_desc;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
@@ -489,20 +514,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
/*
* Ask the tablet to report tablet data if it is not a Tablet PC.
- * Repeat until it succeeds
+ * Note that if query fails it is not a hard failure.
*/
- if (wacom_wac->features->type != TABLETPC) {
- do {
- rep_data[0] = 2;
- rep_data[1] = 2;
- error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
- 2, rep_data, 2);
- if (error >= 0)
- error = usb_get_report(intf,
- WAC_HID_FEATURE_REPORT, 2,
- rep_data, 2);
- } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
- }
+ if (wacom_wac->features->type != TABLETPC)
+ wacom_query_tablet_data(intf);
usb_set_intfdata(intf, wacom);
return 0;
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 6954f5500108..3a7a58222f83 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -170,11 +170,11 @@ static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb)
ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr);
ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);
- if (isr & UCB_IE_TSPX) {
+ if (isr & UCB_IE_TSPX)
ucb1400_ts_irq_disable(ucb->ac97);
- enable_irq(ucb->irq);
- } else
- printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+ else
+ dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+ enable_irq(ucb->irq);
}
static int ucb1400_ts_thread(void *_ucb)
@@ -345,6 +345,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb)
static int ucb1400_ts_probe(struct platform_device *dev)
{
int error, x_res, y_res;
+ u16 fcsr;
struct ucb1400_ts *ucb = dev->dev.platform_data;
ucb->ts_idev = input_allocate_device();
@@ -382,6 +383,14 @@ static int ucb1400_ts_probe(struct platform_device *dev)
ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ /*
+ * Enable ADC filter to prevent horrible jitter on Colibri.
+ * This also further reduces jitter on boards where ADCSYNC
+ * pin is connected.
+ */
+ fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR);
+ ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE);
+
ucb1400_adc_enable(ucb->ac97);
x_res = ucb1400_ts_read_xres(ucb);
y_res = ucb1400_ts_read_yres(ucb);
diff --git a/drivers/leds/ledtrig-gpio.c b/drivers/leds/ledtrig-gpio.c
index a247ae63374f..1bc5db4ece0d 100644
--- a/drivers/leds/ledtrig-gpio.c
+++ b/drivers/leds/ledtrig-gpio.c
@@ -117,6 +117,9 @@ static ssize_t gpio_trig_inverted_store(struct device *dev,
gpio_data->inverted = !!inverted;
+ /* After inverting, we need to update the LED. */
+ schedule_work(&gpio_data->work);
+
return n;
}
static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
@@ -146,20 +149,26 @@ static ssize_t gpio_trig_gpio_store(struct device *dev,
return -EINVAL;
}
+ if (gpio_data->gpio == gpio)
+ return n;
+
if (!gpio) {
- free_irq(gpio_to_irq(gpio_data->gpio), led);
+ if (gpio_data->gpio != 0)
+ free_irq(gpio_to_irq(gpio_data->gpio), led);
+ gpio_data->gpio = 0;
return n;
}
- if (gpio_data->gpio > 0 && gpio_data->gpio != gpio)
- free_irq(gpio_to_irq(gpio_data->gpio), led);
-
- gpio_data->gpio = gpio;
ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq,
IRQF_SHARED | IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
- if (ret)
+ if (ret) {
dev_err(dev, "request_irq failed with error %d\n", ret);
+ } else {
+ if (gpio_data->gpio != 0)
+ free_irq(gpio_to_irq(gpio_data->gpio), led);
+ gpio_data->gpio = gpio;
+ }
return ret ? ret : n;
}
@@ -211,7 +220,8 @@ static void gpio_trig_deactivate(struct led_classdev *led)
device_remove_file(led->dev, &dev_attr_inverted);
device_remove_file(led->dev, &dev_attr_desired_brightness);
flush_work(&gpio_data->work);
- free_irq(gpio_to_irq(gpio_data->gpio),led);
+ if (gpio_data->gpio != 0)
+ free_irq(gpio_to_irq(gpio_data->gpio), led);
kfree(gpio_data);
}
}
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 4d686c0bdea0..9ab5b0c34f0d 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -288,7 +288,7 @@ static void maciisi_sync(struct adb_request *req)
}
/* This could be BAD... when the ADB controller doesn't respond
* for this long, it's probably not coming back :-( */
- if(count >= 50) /* Hopefully shouldn't happen */
+ if (count > 50) /* Hopefully shouldn't happen */
printk(KERN_ERR "maciisi_send_request: poll timed out!\n");
}
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
index 88847d1dcbb5..8c1aed77ea30 100644
--- a/drivers/media/dvb/siano/Kconfig
+++ b/drivers/media/dvb/siano/Kconfig
@@ -2,25 +2,33 @@
# Siano Mobile Silicon Digital TV device configuration
#
-config DVB_SIANO_SMS1XXX
- tristate "Siano SMS1XXX USB dongle support"
- depends on DVB_CORE && USB && INPUT
+config SMS_SIANO_MDTV
+ tristate "Siano SMS1xxx based MDTV receiver"
+ depends on DVB_CORE && INPUT
---help---
- Choose Y here if you have a USB dongle with a SMS1XXX chipset.
+ Choose Y or M here if you have MDTV receiver with a Siano chipset.
- To compile this driver as a module, choose M here: the
- module will be called sms1xxx.
+ To compile this driver as a module, choose M here
+ (The module will be called smsmdtv).
-config DVB_SIANO_SMS1XXX_SMS_IDS
- bool "Enable support for Siano Mobile Silicon default USB IDs"
- depends on DVB_SIANO_SMS1XXX
- default y
- ---help---
- Choose Y here if you have a USB dongle with a SMS1XXX chipset
- that uses Siano Mobile Silicon's default usb vid:pid.
+ Further documentation on this driver can be found on the WWW
+ at http://www.siano-ms.com/
+
+if SMS_SIANO_MDTV
+menu "Siano module components"
- Choose N here if you would prefer to use Siano's external driver.
+# Hardware interfaces support
- Further documentation on this driver can be found on the WWW at
- <http://www.siano-ms.com/>.
+config SMS_USB_DRV
+ tristate "USB interface support"
+ depends on DVB_CORE && USB
+ ---help---
+ Choose if you would like to have Siano's support for USB interface
+config SMS_SDIO_DRV
+ tristate "SDIO interface support"
+ depends on DVB_CORE && MMC
+ ---help---
+ Choose if you would like to have Siano's support for SDIO interface
+endmenu
+endif # SMS_SIANO_MDTV
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
index c6644d909433..c54140b5ab5a 100644
--- a/drivers/media/dvb/siano/Makefile
+++ b/drivers/media/dvb/siano/Makefile
@@ -1,8 +1,9 @@
-sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o
+smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
+
+obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
+obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
+obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index 3ee1c3902c56..266033ae2784 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -325,6 +325,16 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
0 : -ETIME;
}
+static inline int led_feedback(struct smsdvb_client_t *client)
+{
+ if (client->fe_status & FE_HAS_LOCK)
+ return sms_board_led_feedback(client->coredev,
+ (client->sms_stat_dvb.ReceptionData.BER
+ == 0) ? SMS_LED_HI : SMS_LED_LO);
+ else
+ return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+}
+
static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
{
struct smsdvb_client_t *client;
@@ -332,6 +342,8 @@ static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
*stat = client->fe_status;
+ led_feedback(client);
+
return 0;
}
@@ -342,6 +354,8 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
*ber = client->sms_stat_dvb.ReceptionData.BER;
+ led_feedback(client);
+
return 0;
}
@@ -359,6 +373,8 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
(client->sms_stat_dvb.ReceptionData.InBandPwr
+ 95) * 3 / 2;
+ led_feedback(client);
+
return 0;
}
@@ -369,6 +385,8 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
*snr = client->sms_stat_dvb.ReceptionData.SNR;
+ led_feedback(client);
+
return 0;
}
@@ -379,6 +397,8 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
+ led_feedback(client);
+
return 0;
}
@@ -404,6 +424,8 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
u32 Data[3];
} Msg;
+ int ret;
+
client->fe_status = FE_HAS_SIGNAL;
client->event_fe_state = -1;
client->event_unc_state = -1;
@@ -426,6 +448,23 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
case BANDWIDTH_AUTO: return -EOPNOTSUPP;
default: return -EINVAL;
}
+ /* Disable LNA, if any. An error is returned if no LNA is present */
+ ret = sms_board_lna_control(client->coredev, 0);
+ if (ret == 0) {
+ fe_status_t status;
+
+ /* tune with LNA off at first */
+ ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->tune_done);
+
+ smsdvb_read_status(fe, &status);
+
+ if (status & FE_HAS_LOCK)
+ return ret;
+
+ /* previous tune didnt lock - enable LNA and tune again */
+ sms_board_lna_control(client->coredev, 1);
+ }
return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
&client->tune_done);
@@ -451,6 +490,8 @@ static int smsdvb_init(struct dvb_frontend *fe)
struct smsdvb_client_t *client =
container_of(fe, struct smsdvb_client_t, frontend);
+ sms_board_power(client->coredev, 1);
+
sms_board_dvb3_event(client, DVB3_EVENT_INIT);
return 0;
}
@@ -460,6 +501,9 @@ static int smsdvb_sleep(struct dvb_frontend *fe)
struct smsdvb_client_t *client =
container_of(fe, struct smsdvb_client_t, frontend);
+ sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+ sms_board_power(client->coredev, 0);
+
sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
return 0;
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
index dfaa49a53f32..d1d652e7f890 100644
--- a/drivers/media/dvb/siano/smssdio.c
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -46,6 +46,7 @@
#define SMSSDIO_DATA 0x00
#define SMSSDIO_INT 0x04
+#define SMSSDIO_BLOCK_SIZE 128
static const struct sdio_device_id smssdio_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
@@ -85,7 +86,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size)
sdio_claim_host(smsdev->func);
while (size >= smsdev->func->cur_blksize) {
- ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1);
+ ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+ buffer, smsdev->func->cur_blksize);
if (ret)
goto out;
@@ -94,8 +96,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size)
}
if (size) {
- ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA,
- buffer, size);
+ ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+ buffer, size);
}
out:
@@ -125,23 +127,23 @@ static void smssdio_interrupt(struct sdio_func *func)
*/
isr = sdio_readb(func, SMSSDIO_INT, &ret);
if (ret) {
- dev_err(&smsdev->func->dev,
- "Unable to read interrupt register!\n");
+ sms_err("Unable to read interrupt register!\n");
return;
}
if (smsdev->split_cb == NULL) {
cb = smscore_getbuffer(smsdev->coredev);
if (!cb) {
- dev_err(&smsdev->func->dev,
- "Unable to allocate data buffer!\n");
+ sms_err("Unable to allocate data buffer!\n");
return;
}
- ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1);
+ ret = sdio_memcpy_fromio(smsdev->func,
+ cb->p,
+ SMSSDIO_DATA,
+ SMSSDIO_BLOCK_SIZE);
if (ret) {
- dev_err(&smsdev->func->dev,
- "Error %d reading initial block!\n", ret);
+ sms_err("Error %d reading initial block!\n", ret);
return;
}
@@ -152,7 +154,10 @@ static void smssdio_interrupt(struct sdio_func *func)
return;
}
- size = hdr->msgLength - smsdev->func->cur_blksize;
+ if (hdr->msgLength > smsdev->func->cur_blksize)
+ size = hdr->msgLength - smsdev->func->cur_blksize;
+ else
+ size = 0;
} else {
cb = smsdev->split_cb;
hdr = cb->p;
@@ -162,23 +167,24 @@ static void smssdio_interrupt(struct sdio_func *func)
smsdev->split_cb = NULL;
}
- if (hdr->msgLength > smsdev->func->cur_blksize) {
+ if (size) {
void *buffer;
- size = ALIGN(size, 128);
- buffer = cb->p + hdr->msgLength;
+ buffer = cb->p + (hdr->msgLength - size);
+ size = ALIGN(size, SMSSDIO_BLOCK_SIZE);
- BUG_ON(smsdev->func->cur_blksize != 128);
+ BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE);
/*
* First attempt to transfer all of it in one go...
*/
- ret = sdio_read_blocks(smsdev->func, buffer,
- SMSSDIO_DATA, size / 128);
+ ret = sdio_memcpy_fromio(smsdev->func,
+ buffer,
+ SMSSDIO_DATA,
+ size);
if (ret && ret != -EINVAL) {
smscore_putbuffer(smsdev->coredev, cb);
- dev_err(&smsdev->func->dev,
- "Error %d reading data from card!\n", ret);
+ sms_err("Error %d reading data from card!\n", ret);
return;
}
@@ -191,12 +197,12 @@ static void smssdio_interrupt(struct sdio_func *func)
*/
if (ret == -EINVAL) {
while (size) {
- ret = sdio_read_blocks(smsdev->func,
- buffer, SMSSDIO_DATA, 1);
+ ret = sdio_memcpy_fromio(smsdev->func,
+ buffer, SMSSDIO_DATA,
+ smsdev->func->cur_blksize);
if (ret) {
smscore_putbuffer(smsdev->coredev, cb);
- dev_err(&smsdev->func->dev,
- "Error %d reading "
+ sms_err("Error %d reading "
"data from card!\n", ret);
return;
}
@@ -269,7 +275,7 @@ static int smssdio_probe(struct sdio_func *func,
if (ret)
goto release;
- ret = sdio_set_block_size(func, 128);
+ ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE);
if (ret)
goto disable;
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index ed281f565945..1c2e544eda73 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -1730,6 +1730,25 @@ static inline void em28xx_set_model(struct em28xx *dev)
EM28XX_I2C_FREQ_100_KHZ;
}
+
+/* FIXME: Should be replaced by a proper mt9m111 driver */
+static int em28xx_initialize_mt9m111(struct em28xx *dev)
+{
+ int i;
+ unsigned char regs[][3] = {
+ { 0x0d, 0x00, 0x01, }, /* reset and use defaults */
+ { 0x0d, 0x00, 0x00, },
+ { 0x0a, 0x00, 0x21, },
+ { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */
+ };
+
+ for (i = 0; i < ARRAY_SIZE(regs); i++)
+ i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+ return 0;
+}
+
+
/* FIXME: Should be replaced by a proper mt9m001 driver */
static int em28xx_initialize_mt9m001(struct em28xx *dev)
{
@@ -1758,7 +1777,7 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev)
/* HINT method: webcam I2C chips
*
- * This method work for webcams with Micron sensors
+ * This method works for webcams with Micron sensors
*/
static int em28xx_hint_sensor(struct em28xx *dev)
{
@@ -1804,6 +1823,23 @@ static int em28xx_hint_sensor(struct em28xx *dev)
dev->vinctl = 0x00;
break;
+
+ case 0x143a: /* MT9M111 as found in the ECS G200 */
+ dev->model = EM2750_BOARD_UNKNOWN;
+ em28xx_set_model(dev);
+
+ sensor_name = "mt9m111";
+ dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
+ dev->em28xx_sensor = EM28XX_MT9M111;
+ em28xx_initialize_mt9m111(dev);
+ dev->sensor_xres = 640;
+ dev->sensor_yres = 512;
+
+ dev->vinmode = 0x0a;
+ dev->vinctl = 0x00;
+
+ break;
+
case 0x8431:
dev->model = EM2750_BOARD_UNKNOWN;
em28xx_set_model(dev);
@@ -1820,7 +1856,7 @@ static int em28xx_hint_sensor(struct em28xx *dev)
break;
default:
- printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version));
+ printk("Unknown Micron Sensor 0x%04x\n", version);
return -EINVAL;
}
@@ -2346,7 +2382,9 @@ void em28xx_card_setup(struct em28xx *dev)
}
em28xx_tuner_setup(dev);
- em28xx_ir_init(dev);
+
+ if(!disable_ir)
+ em28xx_ir_init(dev);
}
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 8c2dc38bca9f..a2add61f7d59 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -367,6 +367,7 @@ enum em28xx_sensor {
EM28XX_NOSENSOR = 0,
EM28XX_MT9V011,
EM28XX_MT9M001,
+ EM28XX_MT9M111,
};
enum em28xx_adecoder {
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 34f46f2bc040..e994dcac43ff 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -114,7 +114,7 @@ config USB_GSPCA_SN9C20X
config USB_GSPCA_SN9C20X_EVDEV
bool "Enable evdev support"
- depends on USB_GSPCA_SN9C20X
+ depends on USB_GSPCA_SN9C20X && INPUT
---help---
Say Y here in order to enable evdev support for sn9c20x webcam button.
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index fc976f42f432..2622a6e63da1 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -695,7 +695,7 @@ static int zr364xx_release(struct file *file)
for (i = 0; i < 2; i++) {
err =
send_control_msg(udev, 1, init[cam->method][i].value,
- 0, init[i][cam->method].bytes,
+ 0, init[cam->method][i].bytes,
init[cam->method][i].size);
if (err < 0) {
dev_err(&udev->dev, "error during release sequence\n");
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 7ad972229db4..0d9d4bc9c762 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -61,7 +61,7 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
buf64 = (uint64_t *)buf;
while (i < len/8) {
uint64_t x;
- asm ("ldrd\t%0, [%1]" : "=r" (x) : "r" (io_base));
+ asm volatile ("ldrd\t%0, [%1]" : "=&r" (x) : "r" (io_base));
buf64[i++] = x;
}
i *= 8;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f6509a5f640..5ce7cbabd7a7 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1727,12 +1727,14 @@ config KS8842
tristate "Micrel KSZ8842"
depends on HAS_IOMEM
help
- This platform driver is for Micrel KSZ8842 chip.
+ This platform driver is for Micrel KSZ8842 / KS8842
+ 2-port ethernet switch chip (managed, VLAN, QoS).
config KS8851
tristate "Micrel KS8851 SPI"
depends on SPI
select MII
+ select CRC32
help
SPI driver for Micrel KS8851 SPI attached network chip.
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
index 616fb7985a34..ddd231cb54b7 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/arm/w90p910_ether.c
@@ -1080,7 +1080,7 @@ static struct platform_driver w90p910_ether_driver = {
.probe = w90p910_ether_probe,
.remove = __devexit_p(w90p910_ether_remove),
.driver = {
- .name = "w90p910-emc",
+ .name = "nuc900-emc",
.owner = THIS_MODULE,
},
};
@@ -1101,5 +1101,5 @@ module_exit(w90p910_ether_exit);
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
MODULE_DESCRIPTION("w90p910 MAC driver!");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:w90p910-emc");
+MODULE_ALIAS("platform:nuc900-emc");
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 41b648a67fec..3a6735dc9f6a 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1899,7 +1899,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
nic->ru_running = RU_SUSPENDED;
pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
sizeof(struct rfd),
- PCI_DMA_BIDIRECTIONAL);
+ PCI_DMA_FROMDEVICE);
return -ENODATA;
}
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index cc786333d95c..c40113f58963 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -309,6 +309,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct mpc52xx_fec_priv *priv = netdev_priv(dev);
struct bcom_fec_bd *bd;
+ unsigned long flags;
if (bcom_queue_full(priv->tx_dmatsk)) {
if (net_ratelimit())
@@ -316,7 +317,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- spin_lock_irq(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
dev->trans_start = jiffies;
bd = (struct bcom_fec_bd *)
@@ -332,7 +333,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
- spin_unlock_irq(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index beb84213b671..f0f890803710 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -1305,6 +1305,8 @@ static int emac_close(struct net_device *ndev)
free_irq(dev->emac_irq, dev);
+ netif_carrier_off(ndev);
+
return 0;
}
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index c4361d466597..ee1cff5c9b21 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/interrupt.h>
@@ -205,9 +204,6 @@ static const struct net_device_ops au1k_irda_netdev_ops = {
.ndo_start_xmit = au1k_irda_hard_xmit,
.ndo_tx_timeout = au1k_tx_timeout,
.ndo_do_ioctl = au1k_irda_ioctl,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
};
static int au1k_irda_net_init(struct net_device *dev)
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 3376a4f39e0a..77d10edefd25 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -803,9 +803,6 @@ static const struct net_device_ops pxa_irda_netdev_ops = {
.ndo_stop = pxa_irda_stop,
.ndo_start_xmit = pxa_irda_hard_xmit,
.ndo_do_ioctl = pxa_irda_ioctl,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
};
static int pxa_irda_probe(struct platform_device *pdev)
@@ -830,6 +827,7 @@ static int pxa_irda_probe(struct platform_device *pdev)
if (!dev)
goto err_mem_3;
+ SET_NETDEV_DEV(dev, &pdev->dev);
si = netdev_priv(dev);
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 2aeb2e6aec1b..b039cb081e94 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -24,7 +24,6 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/interrupt.h>
@@ -881,9 +880,6 @@ static const struct net_device_ops sa1100_irda_netdev_ops = {
.ndo_stop = sa1100_irda_stop,
.ndo_start_xmit = sa1100_irda_hard_xmit,
.ndo_do_ioctl = sa1100_irda_ioctl,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
};
static int sa1100_irda_probe(struct platform_device *pdev)
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 2a0174b62e96..92fb8235c766 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -41,6 +41,7 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
struct ixpdev_priv *ip = netdev_priv(dev);
struct ixpdev_tx_desc *desc;
int entry;
+ unsigned long flags;
if (unlikely(skb->len > PAGE_SIZE)) {
/* @@@ Count drops. */
@@ -63,11 +64,11 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- local_irq_disable();
+ local_irq_save(flags);
ip->tx_queue_entries++;
if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
netif_stop_queue(dev);
- local_irq_enable();
+ local_irq_restore(flags);
return 0;
}
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 5b5c25368d1e..e3601cf3f931 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -620,6 +620,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
dma_addr_t mapping;
unsigned int len, entry;
u32 ctrl;
+ unsigned long flags;
#ifdef DEBUG
int i;
@@ -635,12 +636,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
len = skb->len;
- spin_lock_irq(&bp->lock);
+ spin_lock_irqsave(&bp->lock, flags);
/* This is a hard error, log it. */
if (TX_BUFFS_AVAIL(bp) < 1) {
netif_stop_queue(dev);
- spin_unlock_irq(&bp->lock);
+ spin_unlock_irqrestore(&bp->lock, flags);
dev_err(&bp->pdev->dev,
"BUG! Tx Ring full when queue awake!\n");
dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n",
@@ -674,7 +675,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (TX_BUFFS_AVAIL(bp) < 1)
netif_stop_queue(dev);
- spin_unlock_irq(&bp->lock);
+ spin_unlock_irqrestore(&bp->lock, flags);
dev->trans_start = jiffies;
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 5a88b3f57693..62208401c4df 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -437,6 +437,7 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
{
struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind];
struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind];
+ unsigned long flags;
/* If we don't have a pending timer, set one up to catch our recent
post in case the interface becomes idle */
@@ -445,9 +446,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
/* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
- if (spin_trylock_irq(&ring->comp_lock)) {
+ if (spin_trylock_irqsave(&ring->comp_lock, flags)) {
mlx4_en_process_tx_cq(priv->dev, cq);
- spin_unlock_irq(&ring->comp_lock);
+ spin_unlock_irqrestore(&ring->comp_lock, flags);
}
}
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 1c70e999cc50..7567f510eff5 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -196,21 +196,23 @@ static void PRINT_PKT(u_char *buf, int length)
/* this enables an interrupt in the interrupt mask register */
#define SMC_ENABLE_INT(lp, x) do { \
unsigned char mask; \
- spin_lock_irq(&lp->lock); \
+ unsigned long smc_enable_flags; \
+ spin_lock_irqsave(&lp->lock, smc_enable_flags); \
mask = SMC_GET_INT_MASK(lp); \
mask |= (x); \
SMC_SET_INT_MASK(lp, mask); \
- spin_unlock_irq(&lp->lock); \
+ spin_unlock_irqrestore(&lp->lock, smc_enable_flags); \
} while (0)
/* this disables an interrupt from the interrupt mask register */
#define SMC_DISABLE_INT(lp, x) do { \
unsigned char mask; \
- spin_lock_irq(&lp->lock); \
+ unsigned long smc_disable_flags; \
+ spin_lock_irqsave(&lp->lock, smc_disable_flags); \
mask = SMC_GET_INT_MASK(lp); \
mask &= ~(x); \
SMC_SET_INT_MASK(lp, mask); \
- spin_unlock_irq(&lp->lock); \
+ spin_unlock_irqrestore(&lp->lock, smc_disable_flags); \
} while (0)
/*
@@ -520,21 +522,21 @@ static inline void smc_rcv(struct net_device *dev)
* any other concurrent access and C would always interrupt B. But life
* isn't that easy in a SMP world...
*/
-#define smc_special_trylock(lock) \
+#define smc_special_trylock(lock, flags) \
({ \
int __ret; \
- local_irq_disable(); \
+ local_irq_save(flags); \
__ret = spin_trylock(lock); \
if (!__ret) \
- local_irq_enable(); \
+ local_irq_restore(flags); \
__ret; \
})
-#define smc_special_lock(lock) spin_lock_irq(lock)
-#define smc_special_unlock(lock) spin_unlock_irq(lock)
+#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags)
+#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags)
#else
-#define smc_special_trylock(lock) (1)
-#define smc_special_lock(lock) do { } while (0)
-#define smc_special_unlock(lock) do { } while (0)
+#define smc_special_trylock(lock, flags) (1)
+#define smc_special_lock(lock, flags) do { } while (0)
+#define smc_special_unlock(lock, flags) do { } while (0)
#endif
/*
@@ -548,10 +550,11 @@ static void smc_hardware_send_pkt(unsigned long data)
struct sk_buff *skb;
unsigned int packet_no, len;
unsigned char *buf;
+ unsigned long flags;
DBG(3, "%s: %s\n", dev->name, __func__);
- if (!smc_special_trylock(&lp->lock)) {
+ if (!smc_special_trylock(&lp->lock, flags)) {
netif_stop_queue(dev);
tasklet_schedule(&lp->tx_task);
return;
@@ -559,7 +562,7 @@ static void smc_hardware_send_pkt(unsigned long data)
skb = lp->pending_tx_skb;
if (unlikely(!skb)) {
- smc_special_unlock(&lp->lock);
+ smc_special_unlock(&lp->lock, flags);
return;
}
lp->pending_tx_skb = NULL;
@@ -569,7 +572,7 @@ static void smc_hardware_send_pkt(unsigned long data)
printk("%s: Memory allocation failed.\n", dev->name);
dev->stats.tx_errors++;
dev->stats.tx_fifo_errors++;
- smc_special_unlock(&lp->lock);
+ smc_special_unlock(&lp->lock, flags);
goto done;
}
@@ -608,7 +611,7 @@ static void smc_hardware_send_pkt(unsigned long data)
/* queue the packet for TX */
SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
- smc_special_unlock(&lp->lock);
+ smc_special_unlock(&lp->lock, flags);
dev->trans_start = jiffies;
dev->stats.tx_packets++;
@@ -633,6 +636,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
unsigned int numPages, poll_count, status;
+ unsigned long flags;
DBG(3, "%s: %s\n", dev->name, __func__);
@@ -658,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
- smc_special_lock(&lp->lock);
+ smc_special_lock(&lp->lock, flags);
/* now, try to allocate the memory */
SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
@@ -676,7 +680,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
} while (--poll_count);
- smc_special_unlock(&lp->lock);
+ smc_special_unlock(&lp->lock, flags);
lp->pending_tx_skb = skb;
if (!poll_count) {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 2a6e81d5b579..bbedf03a2124 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -70,6 +70,9 @@ struct virtnet_info
struct sk_buff_head recv;
struct sk_buff_head send;
+ /* Work struct for refilling if we run low on memory. */
+ struct delayed_work refill;
+
/* Chain pages by the private ptr. */
struct page *pages;
};
@@ -273,19 +276,22 @@ drop:
dev_kfree_skb(skb);
}
-static void try_fill_recv_maxbufs(struct virtnet_info *vi)
+static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp)
{
struct sk_buff *skb;
struct scatterlist sg[2+MAX_SKB_FRAGS];
int num, err, i;
+ bool oom = false;
sg_init_table(sg, 2+MAX_SKB_FRAGS);
for (;;) {
struct virtio_net_hdr *hdr;
skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN);
- if (unlikely(!skb))
+ if (unlikely(!skb)) {
+ oom = true;
break;
+ }
skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, MAX_PACKET_LEN);
@@ -296,7 +302,7 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi)
if (vi->big_packets) {
for (i = 0; i < MAX_SKB_FRAGS; i++) {
skb_frag_t *f = &skb_shinfo(skb)->frags[i];
- f->page = get_a_page(vi, GFP_ATOMIC);
+ f->page = get_a_page(vi, gfp);
if (!f->page)
break;
@@ -325,31 +331,35 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi)
if (unlikely(vi->num > vi->max))
vi->max = vi->num;
vi->rvq->vq_ops->kick(vi->rvq);
+ return !oom;
}
-static void try_fill_recv(struct virtnet_info *vi)
+/* Returns false if we couldn't fill entirely (OOM). */
+static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
{
struct sk_buff *skb;
struct scatterlist sg[1];
int err;
+ bool oom = false;
- if (!vi->mergeable_rx_bufs) {
- try_fill_recv_maxbufs(vi);
- return;
- }
+ if (!vi->mergeable_rx_bufs)
+ return try_fill_recv_maxbufs(vi, gfp);
for (;;) {
skb_frag_t *f;
skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
- if (unlikely(!skb))
+ if (unlikely(!skb)) {
+ oom = true;
break;
+ }
skb_reserve(skb, NET_IP_ALIGN);
f = &skb_shinfo(skb)->frags[0];
- f->page = get_a_page(vi, GFP_ATOMIC);
+ f->page = get_a_page(vi, gfp);
if (!f->page) {
+ oom = true;
kfree_skb(skb);
break;
}
@@ -373,6 +383,7 @@ static void try_fill_recv(struct virtnet_info *vi)
if (unlikely(vi->num > vi->max))
vi->max = vi->num;
vi->rvq->vq_ops->kick(vi->rvq);
+ return !oom;
}
static void skb_recv_done(struct virtqueue *rvq)
@@ -385,6 +396,23 @@ static void skb_recv_done(struct virtqueue *rvq)
}
}
+static void refill_work(struct work_struct *work)
+{
+ struct virtnet_info *vi;
+ bool still_empty;
+
+ vi = container_of(work, struct virtnet_info, refill.work);
+ napi_disable(&vi->napi);
+ try_fill_recv(vi, GFP_KERNEL);
+ still_empty = (vi->num == 0);
+ napi_enable(&vi->napi);
+
+ /* In theory, this can happen: if we don't get any buffers in
+ * we will *never* try to fill again. */
+ if (still_empty)
+ schedule_delayed_work(&vi->refill, HZ/2);
+}
+
static int virtnet_poll(struct napi_struct *napi, int budget)
{
struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
@@ -400,10 +428,10 @@ again:
received++;
}
- /* FIXME: If we oom and completely run out of inbufs, we need
- * to start a timer trying to fill more. */
- if (vi->num < vi->max / 2)
- try_fill_recv(vi);
+ if (vi->num < vi->max / 2) {
+ if (!try_fill_recv(vi, GFP_ATOMIC))
+ schedule_delayed_work(&vi->refill, 0);
+ }
/* Out of packets? */
if (received < budget) {
@@ -893,6 +921,7 @@ static int virtnet_probe(struct virtio_device *vdev)
vi->vdev = vdev;
vdev->priv = vi;
vi->pages = NULL;
+ INIT_DELAYED_WORK(&vi->refill, refill_work);
/* If they give us a callback when all buffers are done, we don't need
* the timer. */
@@ -941,7 +970,7 @@ static int virtnet_probe(struct virtio_device *vdev)
}
/* Last of all, set up some receive buffers. */
- try_fill_recv(vi);
+ try_fill_recv(vi, GFP_KERNEL);
/* If we didn't even get one input buffer, we're useless. */
if (vi->num == 0) {
@@ -958,6 +987,7 @@ static int virtnet_probe(struct virtio_device *vdev)
unregister:
unregister_netdev(dev);
+ cancel_delayed_work_sync(&vi->refill);
free_vqs:
vdev->config->del_vqs(vdev);
free:
@@ -986,6 +1016,7 @@ static void virtnet_remove(struct virtio_device *vdev)
BUG_ON(vi->num != 0);
unregister_netdev(vi->dev);
+ cancel_delayed_work_sync(&vi->refill);
vdev->config->del_vqs(vi->vdev);
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 632fac86a308..b3946272c72e 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -70,7 +70,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
int err = 0;
u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
- if ((key < 0) || (key > 4))
+ if ((key < 0) || (key >= 4))
return -EINVAL;
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 294250e294dd..87a95588a8e3 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -869,6 +869,9 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
priv->aifsn[3] = 3; /* AIFSN[AC_BE] */
rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
+ /* ENEDCA flag must always be set, transmit issues? */
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA);
+
return 0;
}
@@ -1173,13 +1176,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
rtl818x_iowrite8(priv, &priv->map->BSSID[i],
info->bssid[i]);
+ if (priv->is_rtl8187b)
+ reg = RTL818X_MSR_ENEDCA;
+ else
+ reg = 0;
+
if (is_valid_ether_addr(info->bssid)) {
- reg = RTL818X_MSR_INFRA;
- if (priv->is_rtl8187b)
- reg |= RTL818X_MSR_ENEDCA;
+ reg |= RTL818X_MSR_INFRA;
rtl818x_iowrite8(priv, &priv->map->MSR, reg);
} else {
- reg = RTL818X_MSR_NO_LINK;
+ reg |= RTL818X_MSR_NO_LINK;
rtl818x_iowrite8(priv, &priv->map->MSR, reg);
}
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index a07580138e81..c2fd6187773f 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -346,7 +346,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int yellowfin_open(struct net_device *dev);
static void yellowfin_timer(unsigned long data);
static void yellowfin_tx_timeout(struct net_device *dev);
-static void yellowfin_init_ring(struct net_device *dev);
+static int yellowfin_init_ring(struct net_device *dev);
static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance);
static int yellowfin_rx(struct net_device *dev);
@@ -573,19 +573,24 @@ static int yellowfin_open(struct net_device *dev)
{
struct yellowfin_private *yp = netdev_priv(dev);
void __iomem *ioaddr = yp->base;
- int i;
+ int i, ret;
/* Reset the chip. */
iowrite32(0x80000000, ioaddr + DMACtrl);
- i = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev);
- if (i) return i;
+ ret = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev);
+ if (ret)
+ return ret;
if (yellowfin_debug > 1)
printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n",
dev->name, dev->irq);
- yellowfin_init_ring(dev);
+ ret = yellowfin_init_ring(dev);
+ if (ret) {
+ free_irq(dev->irq, dev);
+ return ret;
+ }
iowrite32(yp->rx_ring_dma, ioaddr + RxPtr);
iowrite32(yp->tx_ring_dma, ioaddr + TxPtr);
@@ -725,10 +730,10 @@ static void yellowfin_tx_timeout(struct net_device *dev)
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void yellowfin_init_ring(struct net_device *dev)
+static int yellowfin_init_ring(struct net_device *dev)
{
struct yellowfin_private *yp = netdev_priv(dev);
- int i;
+ int i, j;
yp->tx_full = 0;
yp->cur_rx = yp->cur_tx = 0;
@@ -753,6 +758,11 @@ static void yellowfin_init_ring(struct net_device *dev)
yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
}
+ if (i != RX_RING_SIZE) {
+ for (j = 0; j < i; j++)
+ dev_kfree_skb(yp->rx_skbuff[j]);
+ return -ENOMEM;
+ }
yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP);
yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -769,8 +779,6 @@ static void yellowfin_init_ring(struct net_device *dev)
yp->tx_ring[--i].dbdma_cmd = cpu_to_le32(CMD_STOP | BRANCH_ALWAYS);
#else
{
- int j;
-
/* Tx ring needs a pair of descriptors, the second for the status. */
for (i = 0; i < TX_RING_SIZE; i++) {
j = 2*i;
@@ -805,7 +813,7 @@ static void yellowfin_init_ring(struct net_device *dev)
}
#endif
yp->tx_tail_desc = &yp->tx_status[0];
- return;
+ return 0;
}
static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index d76c4c85367e..f99bc7f089f1 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -508,7 +508,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)
return error;
}
- return pci_dev->state_saved ? pci_restore_state(pci_dev) : 0;
+ return pci_restore_state(pci_dev);
}
static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index dbd0f947f497..7b70312181d7 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -846,6 +846,8 @@ pci_restore_state(struct pci_dev *dev)
int i;
u32 val;
+ if (!dev->state_saved)
+ return 0;
/* PCI Express register must be restored first */
pci_restore_pcie_state(dev);
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 81d31ea507d1..51c0a8bee414 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -335,6 +335,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
if (hci_result != HCI_SUCCESS) {
/* Can't do anything useful */
mutex_unlock(&dev->mutex);
+ return;
}
new_rfk_state = value;
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 043b208d971d..f215a5919192 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -270,7 +270,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
acpi_status status;
struct acpi_object_list input;
union acpi_object params[3];
- char method[4] = "WM";
+ char method[5] = "WM";
if (!find_guid(guid_string, &wblock))
return AE_ERROR;
@@ -328,8 +328,8 @@ struct acpi_buffer *out)
acpi_status status, wc_status = AE_ERROR;
struct acpi_object_list input, wc_input;
union acpi_object wc_params[1], wq_params[1];
- char method[4];
- char wc_method[4] = "WC";
+ char method[5];
+ char wc_method[5] = "WC";
if (!guid_string || !out)
return AE_BAD_PARAMETER;
@@ -410,7 +410,7 @@ const struct acpi_buffer *in)
acpi_handle handle;
struct acpi_object_list input;
union acpi_object params[2];
- char method[4] = "WS";
+ char method[5] = "WS";
if (!guid_string || !in)
return AE_BAD_DATA;
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index ac8cc8cea1e3..fea17e7805e9 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -244,7 +244,7 @@ int pps_register_cdev(struct pps_device *pps)
}
pps->dev = device_create(pps_class, pps->info.dev, pps->devno, NULL,
"pps%d", pps->id);
- if (err)
+ if (IS_ERR(pps->dev))
goto del_cdev;
dev_set_drvdata(pps->dev, pps);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 749836668655..3f62dd50bbbe 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2135,9 +2135,9 @@ static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
struct dasd_device *base;
block = bdev->bd_disk->private_data;
- base = block->base;
if (!block)
return -ENODEV;
+ base = block->base;
if (!base->discipline ||
!base->discipline->fill_geometry)
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 3c57c1a18bb8..d593bc76afe3 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -772,10 +772,8 @@ static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
cdev = io_subchannel_allocate_dev(sch);
if (!IS_ERR(cdev)) {
ret = io_subchannel_initialize_dev(sch, cdev);
- if (ret) {
- kfree(cdev);
+ if (ret)
cdev = ERR_PTR(ret);
- }
}
return cdev;
}
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 15dab96d05e3..7c815d3327f7 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -537,8 +537,12 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
}
if (temp_index != 0 && fan_index != 0) {
kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
- if (IS_ERR(kenvctrld_task))
- return PTR_ERR(kenvctrld_task);
+ if (IS_ERR(kenvctrld_task)) {
+ int err = PTR_ERR(kenvctrld_task);
+
+ kenvctrld_task = NULL;
+ return err;
+ }
}
return 0;
@@ -561,7 +565,8 @@ void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
struct bbc_cpu_temperature *tp, *tpos;
struct bbc_fan_control *fp, *fpos;
- kthread_stop(kenvctrld_task);
+ if (kenvctrld_task)
+ kthread_stop(kenvctrld_task);
list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
list_del(&tp->bp_list);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index f3da592f7bcc..35a13867495e 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struct *work)
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
}
+/**
+ * mpt2sas_base_start_watchdog - start the fault_reset_work_q
+ * @ioc: pointer to scsi command object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+
+ if (ioc->fault_reset_work_q)
+ return;
+
+ /* initialize fault polling */
+ INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
+ snprintf(ioc->fault_reset_work_q_name,
+ sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+ ioc->fault_reset_work_q =
+ create_singlethread_workqueue(ioc->fault_reset_work_q_name);
+ if (!ioc->fault_reset_work_q) {
+ printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
+ ioc->name, __func__, __LINE__);
+ return;
+ }
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->fault_reset_work_q)
+ queue_delayed_work(ioc->fault_reset_work_q,
+ &ioc->fault_reset_work,
+ msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+}
+
+/**
+ * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
+ * @ioc: pointer to scsi command object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+ struct workqueue_struct *wq;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ wq = ioc->fault_reset_work_q;
+ ioc->fault_reset_work_q = NULL;
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (wq) {
+ if (!cancel_delayed_work(&ioc->fault_reset_work))
+ flush_workqueue(wq);
+ destroy_workqueue(wq);
+ }
+}
+
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _base_sas_ioc_info - verbose translation of the ioc status
@@ -440,6 +498,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
return;
+ /* each nexus loss loginfo */
+ if (log_info == 0x31170000)
+ return;
+
/* eat the loginfos associated with task aborts */
if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
0x31140000 || log_info == 0x31130000))
@@ -1109,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
}
}
- pci_set_drvdata(pdev, ioc->shost);
_base_mask_interrupts(ioc);
r = _base_enable_msix(ioc);
if (r)
@@ -1132,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
ioc->pci_irq = -1;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
return r;
}
@@ -3191,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
ioc->chip_phys = 0;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
return;
}
@@ -3205,7 +3264,6 @@ int
mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
{
int r, i;
- unsigned long flags;
dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));
@@ -3214,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
if (r)
return r;
+ pci_set_drvdata(ioc->pdev, ioc->shost);
r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
if (r)
goto out_free_resources;
@@ -3288,23 +3347,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
if (r)
goto out_free_resources;
- /* initialize fault polling */
- INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
- snprintf(ioc->fault_reset_work_q_name,
- sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
- ioc->fault_reset_work_q =
- create_singlethread_workqueue(ioc->fault_reset_work_q_name);
- if (!ioc->fault_reset_work_q) {
- printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
- ioc->name, __func__, __LINE__);
- goto out_free_resources;
- }
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->fault_reset_work_q)
- queue_delayed_work(ioc->fault_reset_work_q,
- &ioc->fault_reset_work,
- msecs_to_jiffies(FAULT_POLLING_INTERVAL));
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ mpt2sas_base_start_watchdog(ioc);
return 0;
out_free_resources:
@@ -3312,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
ioc->remove_host = 1;
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
+ pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
kfree(ioc->config_cmds.reply);
@@ -3337,22 +3381,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
void
mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
{
- unsigned long flags;
- struct workqueue_struct *wq;
dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- wq = ioc->fault_reset_work_q;
- ioc->fault_reset_work_q = NULL;
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
- if (!cancel_delayed_work(&ioc->fault_reset_work))
- flush_workqueue(wq);
- destroy_workqueue(wq);
-
+ mpt2sas_base_stop_watchdog(ioc);
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
+ pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply);
kfree(ioc->base_cmds.reply);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 286c185fa9e4..acdcff150a35 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,10 +69,10 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "01.100.03.00"
+#define MPT2SAS_DRIVER_VERSION "01.100.04.00"
#define MPT2SAS_MAJOR_VERSION 01
#define MPT2SAS_MINOR_VERSION 100
-#define MPT2SAS_BUILD_VERSION 03
+#define MPT2SAS_BUILD_VERSION 04
#define MPT2SAS_RELEASE_VERSION 00
/*
@@ -673,6 +673,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
/* base shared API */
extern struct list_head mpt2sas_ioc_list;
+void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc);
int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
index 58cfb97846f7..6ddee161beb3 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -236,17 +236,25 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
Mpi2ConfigRequest_t *config_request;
int r;
u8 retry_count;
- u8 issue_reset;
+ u8 issue_host_reset = 0;
u16 wait_state_count;
+ mutex_lock(&ioc->config_cmds.mutex);
if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
ioc->name, __func__);
+ mutex_unlock(&ioc->config_cmds.mutex);
return -EAGAIN;
}
retry_count = 0;
retry_config:
+ if (retry_count) {
+ if (retry_count > 2) /* attempt only 2 retries */
+ return -EFAULT;
+ printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
+ ioc->name, __func__, retry_count);
+ }
wait_state_count = 0;
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
@@ -254,8 +262,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
printk(MPT2SAS_ERR_FMT
"%s: failed due to ioc not operational\n",
ioc->name, __func__);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- return -EFAULT;
+ r = -EFAULT;
+ goto out;
}
ssleep(1);
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
@@ -271,8 +279,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
if (!smid) {
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- return -EAGAIN;
+ r = -EAGAIN;
+ goto out;
}
r = 0;
@@ -292,9 +300,15 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
ioc->name, __func__);
_debug_dump_mf(mpi_request,
sizeof(Mpi2ConfigRequest_t)/4);
- if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
+ retry_count++;
+ if (ioc->config_cmds.smid == smid)
+ mpt2sas_base_free_smid(ioc, smid);
+ if ((ioc->shost_recovery) ||
+ (ioc->config_cmds.status & MPT2_CMD_RESET))
+ goto retry_config;
+ issue_host_reset = 1;
+ r = -EFAULT;
+ goto out;
}
if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
memcpy(mpi_reply, ioc->config_cmds.reply,
@@ -302,21 +316,13 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
if (retry_count)
printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n",
ioc->name, __func__);
+out:
ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- return r;
-
- issue_host_reset:
- if (issue_reset)
+ mutex_unlock(&ioc->config_cmds.mutex);
+ if (issue_host_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- if (!retry_count) {
- printk(MPT2SAS_INFO_FMT "%s: attempting retry\n",
- ioc->name, __func__);
- retry_count++;
- goto retry_config;
- }
- return -EFAULT;
+ return r;
}
/**
@@ -375,7 +381,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -417,7 +422,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -438,7 +442,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2BiosPage2_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -480,7 +483,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -501,7 +503,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2BiosPage3_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -543,7 +544,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -564,7 +564,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -606,7 +605,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -627,7 +625,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -669,7 +666,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -690,7 +686,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
@@ -732,7 +727,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -753,7 +747,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2IOCPage8_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -795,7 +788,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -818,7 +810,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -863,7 +854,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -886,7 +876,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -931,7 +920,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -953,7 +941,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
Mpi2ConfigReply_t mpi_reply;
Mpi2SasIOUnitPage0_t config_page;
- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
@@ -1002,7 +989,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1026,8 +1012,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
Mpi2ConfigRequest_t mpi_request;
int r;
struct config_request mem;
-
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sz);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1070,7 +1054,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1095,7 +1078,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sz);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1138,7 +1120,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1161,7 +1142,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1206,7 +1186,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1230,7 +1209,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1277,7 +1255,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1300,7 +1277,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1345,7 +1321,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1367,7 +1342,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1413,7 +1387,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1435,7 +1408,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1481,7 +1453,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1505,7 +1476,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1548,7 +1518,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1572,7 +1541,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
struct config_request mem;
u16 ioc_status;
- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
*num_pds = 0;
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1620,7 +1588,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1645,7 +1612,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
memset(config_page, 0, sz);
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1687,7 +1653,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1711,7 +1676,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
int r;
struct config_request mem;
- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1754,7 +1718,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
@@ -1778,7 +1741,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
struct config_request mem;
u16 ioc_status;
- mutex_lock(&ioc->config_cmds.mutex);
*volume_handle = 0;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1842,7 +1804,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
_config_free_config_dma_memory(ioc, &mem);
out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 2a01a5f2a84d..2e9a4445596f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -2767,6 +2767,10 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
char *desc_ioc_state = NULL;
char *desc_scsi_status = NULL;
char *desc_scsi_state = ioc->tmp_string;
+ u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
+
+ if (log_info == 0x31170000)
+ return;
switch (ioc_status) {
case MPI2_IOCSTATUS_SUCCESS:
@@ -3426,7 +3430,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
__le64 sas_address;
int i;
unsigned long flags;
- struct _sas_port *mpt2sas_port;
+ struct _sas_port *mpt2sas_port = NULL;
int rc = 0;
if (!handle)
@@ -3518,12 +3522,20 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
&expander_pg1, i, handle))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
- continue;
+ rc = -1;
+ goto out_fail;
}
sas_expander->phy[i].handle = handle;
sas_expander->phy[i].phy_id = i;
- mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i],
- expander_pg1, sas_expander->parent_dev);
+
+ if ((mpt2sas_transport_add_expander_phy(ioc,
+ &sas_expander->phy[i], expander_pg1,
+ sas_expander->parent_dev))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -1;
+ goto out_fail;
+ }
}
if (sas_expander->enclosure_handle) {
@@ -3540,8 +3552,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
out_fail:
- if (sas_expander)
- kfree(sas_expander->phy);
+ if (mpt2sas_port)
+ mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
+ sas_expander->parent_handle);
kfree(sas_expander);
return rc;
}
@@ -3663,12 +3676,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
sas_device->hidden_raid_component = is_pd;
/* get enclosure_logical_id */
- if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0,
- MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- sas_device->enclosure_handle))) {
+ if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
+ ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+ sas_device->enclosure_handle)))
sas_device->enclosure_logical_id =
le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
- }
/* get device name */
sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
@@ -4250,12 +4262,6 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
u16 handle = le16_to_cpu(element->VolDevHandle);
int rc;
-#if 0 /* RAID_HACKS */
- if (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
- return;
-#endif
-
mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
if (!wwid) {
printk(MPT2SAS_ERR_FMT
@@ -4310,12 +4316,6 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc,
unsigned long flags;
struct MPT2SAS_TARGET *sas_target_priv_data;
-#if 0 /* RAID_HACKS */
- if (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
- return;
-#endif
-
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
@@ -4428,14 +4428,38 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
struct _sas_device *sas_device;
unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ u32 ioc_status;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
+ if (sas_device) {
sas_device->hidden_raid_component = 1;
- else
- _scsih_add_device(ioc, handle, 0, 1);
+ return;
+ }
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ _scsih_link_change(ioc,
+ le16_to_cpu(sas_device_pg0.ParentDevHandle),
+ handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+ _scsih_add_device(ioc, handle, 0, 1);
}
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
@@ -4535,12 +4559,15 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
{
Mpi2EventIrConfigElement_t *element;
int i;
+ u8 foreign_config;
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
_scsih_sas_ir_config_change_event_debug(ioc, event_data);
#endif
+ foreign_config = (le32_to_cpu(event_data->Flags) &
+ MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
for (i = 0; i < event_data->NumElements; i++, element++) {
@@ -4548,11 +4575,13 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
switch (element->ReasonCode) {
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
case MPI2_EVENT_IR_CHANGE_RC_ADDED:
- _scsih_sas_volume_add(ioc, element);
+ if (!foreign_config)
+ _scsih_sas_volume_add(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
- _scsih_sas_volume_delete(ioc, element);
+ if (!foreign_config)
+ _scsih_sas_volume_delete(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
_scsih_sas_pd_hide(ioc, element);
@@ -4671,6 +4700,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
u32 state;
struct _sas_device *sas_device;
unsigned long flags;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ u32 ioc_status;
if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
return;
@@ -4687,22 +4719,40 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
switch (state) {
-#if 0
- case MPI2_RAID_PD_STATE_OFFLINE:
- if (sas_device)
- _scsih_remove_device(ioc, handle);
- break;
-#endif
case MPI2_RAID_PD_STATE_ONLINE:
case MPI2_RAID_PD_STATE_DEGRADED:
case MPI2_RAID_PD_STATE_REBUILDING:
case MPI2_RAID_PD_STATE_OPTIMAL:
- if (sas_device)
+ if (sas_device) {
sas_device->hidden_raid_component = 1;
- else
- _scsih_add_device(ioc, handle, 0, 1);
+ return;
+ }
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+ &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+ handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ _scsih_link_change(ioc,
+ le16_to_cpu(sas_device_pg0.ParentDevHandle),
+ handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+ _scsih_add_device(ioc, handle, 0, 1);
+
break;
+ case MPI2_RAID_PD_STATE_OFFLINE:
case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
case MPI2_RAID_PD_STATE_HOT_SPARE:
@@ -5774,6 +5824,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
u32 device_state;
+ mpt2sas_base_stop_watchdog(ioc);
flush_scheduled_work();
scsi_block_requests(shost);
device_state = pci_choose_state(pdev, state);
@@ -5816,6 +5867,7 @@ _scsih_resume(struct pci_dev *pdev)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
scsi_unblock_requests(shost);
+ mpt2sas_base_start_watchdog(ioc);
return 0;
}
#endif /* CONFIG_PM */
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 0a69672097a8..4e83c297ec9e 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -953,7 +953,12 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
mutex_lock(&tz->lock);
- tz->ops->get_temp(tz, &temp);
+ if (tz->ops->get_temp(tz, &temp)) {
+ /* get_temp failed - retry it later */
+ printk(KERN_WARNING PREFIX "failed to read out thermal zone "
+ "%d\n", tz->id);
+ goto leave;
+ }
for (count = 0; count < tz->trips; count++) {
tz->ops->get_trip_type(tz, count, &trip_type);
@@ -1005,6 +1010,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
THERMAL_TRIPS_NONE);
tz->last_temperature = temp;
+
+ leave:
if (tz->passive)
thermal_zone_device_set_polling(tz, tz->passive_delay);
else if (tz->polling_delay)
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 15502d5e3641..54cd91610174 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -454,6 +454,10 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
xenfb_init_shared_page(info, fb_info);
+ ret = xenfb_connect_backend(dev, info);
+ if (ret < 0)
+ goto error;
+
ret = register_framebuffer(fb_info);
if (ret) {
fb_deferred_io_cleanup(fb_info);
@@ -464,10 +468,6 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
}
info->fb_info = fb_info;
- ret = xenfb_connect_backend(dev, info);
- if (ret < 0)
- goto error;
-
xenfb_make_preferred_console();
return 0;
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 3fe9742c23ca..2f8643efe92c 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -37,7 +37,7 @@
#include <linux/uaccess.h>
#include <asm/addrspace.h>
-#include <asm/ar7/ar7.h>
+#include <asm/mach-ar7/ar7.h>
#define DRVNAME "ar7_wdt"
#define LONGNAME "TI AR7 Watchdog Timer"
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 332b5ff02fec..f7003cfac63d 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -76,7 +76,7 @@ static const match_table_t tokens = {
* Return 0 upon success, -ERRNO upon failure.
*/
-static int v9fs_parse_options(struct v9fs_session_info *v9ses)
+static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
{
char *options;
substring_t args[MAX_OPT_ARGS];
@@ -90,10 +90,10 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses)
v9ses->debug = 0;
v9ses->cache = 0;
- if (!v9ses->options)
+ if (!opts)
return 0;
- options = kstrdup(v9ses->options, GFP_KERNEL);
+ options = kstrdup(opts, GFP_KERNEL);
if (!options) {
P9_DPRINTK(P9_DEBUG_ERROR,
"failed to allocate copy of option string\n");
@@ -206,24 +206,14 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
v9ses->uid = ~0;
v9ses->dfltuid = V9FS_DEFUID;
v9ses->dfltgid = V9FS_DEFGID;
- if (data) {
- v9ses->options = kstrdup(data, GFP_KERNEL);
- if (!v9ses->options) {
- P9_DPRINTK(P9_DEBUG_ERROR,
- "failed to allocate copy of option string\n");
- retval = -ENOMEM;
- goto error;
- }
- }
- rc = v9fs_parse_options(v9ses);
+ rc = v9fs_parse_options(v9ses, data);
if (rc < 0) {
retval = rc;
goto error;
}
- v9ses->clnt = p9_client_create(dev_name, v9ses->options);
-
+ v9ses->clnt = p9_client_create(dev_name, data);
if (IS_ERR(v9ses->clnt)) {
retval = PTR_ERR(v9ses->clnt);
v9ses->clnt = NULL;
@@ -280,7 +270,6 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
__putname(v9ses->uname);
__putname(v9ses->aname);
- kfree(v9ses->options);
}
/**
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index a7d567192998..38762bf102a9 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -85,7 +85,6 @@ struct v9fs_session_info {
unsigned int afid;
unsigned int cache;
- char *options; /* copy of mount options */
char *uname; /* user name to mount as */
char *aname; /* name of remote hierarchy being mounted */
unsigned int maxdata; /* max data for client interface */
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 81f8bbf12f9f..06a223d50a81 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -171,7 +171,6 @@ int v9fs_uflags2omode(int uflags, int extended)
/**
* v9fs_blank_wstat - helper function to setup a 9P stat structure
- * @v9ses: 9P session info (for determining extended mode)
* @wstat: structure to initialize
*
*/
@@ -207,65 +206,72 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
struct inode *v9fs_get_inode(struct super_block *sb, int mode)
{
+ int err;
struct inode *inode;
struct v9fs_session_info *v9ses = sb->s_fs_info;
P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
inode = new_inode(sb);
- if (inode) {
- inode->i_mode = mode;
- inode->i_uid = current_fsuid();
- inode->i_gid = current_fsgid();
- inode->i_blocks = 0;
- inode->i_rdev = 0;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_mapping->a_ops = &v9fs_addr_operations;
-
- switch (mode & S_IFMT) {
- case S_IFIFO:
- case S_IFBLK:
- case S_IFCHR:
- case S_IFSOCK:
- if (!v9fs_extended(v9ses)) {
- P9_DPRINTK(P9_DEBUG_ERROR,
- "special files without extended mode\n");
- return ERR_PTR(-EINVAL);
- }
- init_special_inode(inode, inode->i_mode,
- inode->i_rdev);
- break;
- case S_IFREG:
- inode->i_op = &v9fs_file_inode_operations;
- inode->i_fop = &v9fs_file_operations;
- break;
- case S_IFLNK:
- if (!v9fs_extended(v9ses)) {
- P9_DPRINTK(P9_DEBUG_ERROR,
- "extended modes used w/o 9P2000.u\n");
- return ERR_PTR(-EINVAL);
- }
- inode->i_op = &v9fs_symlink_inode_operations;
- break;
- case S_IFDIR:
- inc_nlink(inode);
- if (v9fs_extended(v9ses))
- inode->i_op = &v9fs_dir_inode_operations_ext;
- else
- inode->i_op = &v9fs_dir_inode_operations;
- inode->i_fop = &v9fs_dir_operations;
- break;
- default:
- P9_DPRINTK(P9_DEBUG_ERROR,
- "BAD mode 0x%x S_IFMT 0x%x\n",
- mode, mode & S_IFMT);
- return ERR_PTR(-EINVAL);
- }
- } else {
+ if (!inode) {
P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
return ERR_PTR(-ENOMEM);
}
+
+ inode->i_mode = mode;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
+ inode->i_blocks = 0;
+ inode->i_rdev = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mapping->a_ops = &v9fs_addr_operations;
+
+ switch (mode & S_IFMT) {
+ case S_IFIFO:
+ case S_IFBLK:
+ case S_IFCHR:
+ case S_IFSOCK:
+ if (!v9fs_extended(v9ses)) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "special files without extended mode\n");
+ err = -EINVAL;
+ goto error;
+ }
+ init_special_inode(inode, inode->i_mode, inode->i_rdev);
+ break;
+ case S_IFREG:
+ inode->i_op = &v9fs_file_inode_operations;
+ inode->i_fop = &v9fs_file_operations;
+ break;
+ case S_IFLNK:
+ if (!v9fs_extended(v9ses)) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "extended modes used w/o 9P2000.u\n");
+ err = -EINVAL;
+ goto error;
+ }
+ inode->i_op = &v9fs_symlink_inode_operations;
+ break;
+ case S_IFDIR:
+ inc_nlink(inode);
+ if (v9fs_extended(v9ses))
+ inode->i_op = &v9fs_dir_inode_operations_ext;
+ else
+ inode->i_op = &v9fs_dir_inode_operations;
+ inode->i_fop = &v9fs_dir_operations;
+ break;
+ default:
+ P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+ mode, mode & S_IFMT);
+ err = -EINVAL;
+ goto error;
+ }
+
return inode;
+
+error:
+ iput(inode);
+ return ERR_PTR(err);
}
/*
@@ -338,30 +344,25 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
ret = NULL;
st = p9_client_stat(fid);
- if (IS_ERR(st)) {
- err = PTR_ERR(st);
- st = NULL;
- goto error;
- }
+ if (IS_ERR(st))
+ return ERR_CAST(st);
umode = p9mode2unixmode(v9ses, st->mode);
ret = v9fs_get_inode(sb, umode);
if (IS_ERR(ret)) {
err = PTR_ERR(ret);
- ret = NULL;
goto error;
}
v9fs_stat2inode(st, ret, sb);
ret->i_ino = v9fs_qid2ino(&st->qid);
+ p9stat_free(st);
kfree(st);
return ret;
error:
+ p9stat_free(st);
kfree(st);
- if (ret)
- iput(ret);
-
return ERR_PTR(err);
}
@@ -403,9 +404,9 @@ v9fs_open_created(struct inode *inode, struct file *file)
* @v9ses: session information
* @dir: directory that dentry is being created in
* @dentry: dentry that is being created
+ * @extension: 9p2000.u extension string to support devices, etc.
* @perm: create permissions
* @mode: open mode
- * @extension: 9p2000.u extension string to support devices, etc.
*
*/
static struct p9_fid *
@@ -470,7 +471,10 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
- v9fs_fid_add(dentry, fid);
+ err = v9fs_fid_add(dentry, fid);
+ if (err < 0)
+ goto error;
+
return ofid;
error:
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 38d695d66a0b..8961f1a8f668 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -81,7 +81,7 @@ static int v9fs_set_super(struct super_block *s, void *data)
static void
v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
- int flags)
+ int flags, void *data)
{
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
@@ -91,6 +91,8 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
MS_NOATIME;
+
+ save_mount_options(sb, data);
}
/**
@@ -113,14 +115,11 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
struct v9fs_session_info *v9ses = NULL;
struct p9_wstat *st = NULL;
int mode = S_IRWXUGO | S_ISVTX;
- uid_t uid = current_fsuid();
- gid_t gid = current_fsgid();
struct p9_fid *fid;
int retval = 0;
P9_DPRINTK(P9_DEBUG_VFS, " \n");
- st = NULL;
v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
if (!v9ses)
return -ENOMEM;
@@ -142,7 +141,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
retval = PTR_ERR(sb);
goto free_stat;
}
- v9fs_fill_super(sb, v9ses, flags);
+ v9fs_fill_super(sb, v9ses, flags, data);
inode = v9fs_get_inode(sb, S_IFDIR | mode);
if (IS_ERR(inode)) {
@@ -150,9 +149,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
goto release_sb;
}
- inode->i_uid = uid;
- inode->i_gid = gid;
-
root = d_alloc_root(inode);
if (!root) {
iput(inode);
@@ -173,10 +169,8 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
simple_set_mnt(mnt, sb);
return 0;
-release_sb:
- deactivate_locked_super(sb);
-
free_stat:
+ p9stat_free(st);
kfree(st);
clunk_fid:
@@ -185,7 +179,12 @@ clunk_fid:
close_session:
v9fs_session_close(v9ses);
kfree(v9ses);
+ return retval;
+release_sb:
+ p9stat_free(st);
+ kfree(st);
+ deactivate_locked_super(sb);
return retval;
}
@@ -207,24 +206,10 @@ static void v9fs_kill_super(struct super_block *s)
v9fs_session_close(v9ses);
kfree(v9ses);
+ s->s_fs_info = NULL;
P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
}
-/**
- * v9fs_show_options - Show mount options in /proc/mounts
- * @m: seq_file to write to
- * @mnt: mount descriptor
- *
- */
-
-static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
-{
- struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
-
- seq_printf(m, "%s", v9ses->options);
- return 0;
-}
-
static void
v9fs_umount_begin(struct super_block *sb)
{
@@ -237,7 +222,7 @@ v9fs_umount_begin(struct super_block *sb)
static const struct super_operations v9fs_super_ops = {
.statfs = simple_statfs,
.clear_inode = v9fs_clear_inode,
- .show_options = v9fs_show_options,
+ .show_options = generic_show_options,
.umount_begin = v9fs_umount_begin,
};
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 0149dab365e7..681c2a7b013f 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -134,9 +134,16 @@ static int afs_readpage(struct file *file, struct page *page)
inode = page->mapping->host;
- ASSERT(file != NULL);
- key = file->private_data;
- ASSERT(key != NULL);
+ if (file) {
+ key = file->private_data;
+ ASSERT(key != NULL);
+ } else {
+ key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell);
+ if (IS_ERR(key)) {
+ ret = PTR_ERR(key);
+ goto error_nokey;
+ }
+ }
_enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
@@ -207,12 +214,17 @@ static int afs_readpage(struct file *file, struct page *page)
unlock_page(page);
}
+ if (!file)
+ key_put(key);
_leave(" = 0");
return 0;
error:
SetPageError(page);
unlock_page(page);
+ if (!file)
+ key_put(key);
+error_nokey:
_leave(" = %d", ret);
return ret;
}
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index aa39ae83f019..3da18d453488 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -77,7 +77,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
}
/* Update the expiry counter if fs is busy */
- if (!may_umount_tree(mnt)) {
+ if (!may_umount_tree(path.mnt)) {
struct autofs_info *ino = autofs4_dentry_ino(top);
ino->last_used = jiffies;
goto done;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 272b9b2bea86..59cba180fe83 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3099,8 +3099,12 @@ static void inode_tree_add(struct inode *inode)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_inode *entry;
- struct rb_node **p = &root->inode_tree.rb_node;
- struct rb_node *parent = NULL;
+ struct rb_node **p;
+ struct rb_node *parent;
+
+again:
+ p = &root->inode_tree.rb_node;
+ parent = NULL;
spin_lock(&root->inode_lock);
while (*p) {
@@ -3108,13 +3112,16 @@ static void inode_tree_add(struct inode *inode)
entry = rb_entry(parent, struct btrfs_inode, rb_node);
if (inode->i_ino < entry->vfs_inode.i_ino)
- p = &(*p)->rb_left;
+ p = &parent->rb_left;
else if (inode->i_ino > entry->vfs_inode.i_ino)
- p = &(*p)->rb_right;
+ p = &parent->rb_right;
else {
WARN_ON(!(entry->vfs_inode.i_state &
(I_WILL_FREE | I_FREEING | I_CLEAR)));
- break;
+ rb_erase(parent, &root->inode_tree);
+ RB_CLEAR_NODE(parent);
+ spin_unlock(&root->inode_lock);
+ goto again;
}
}
rb_link_node(&BTRFS_I(inode)->rb_node, parent, p);
@@ -3126,12 +3133,12 @@ static void inode_tree_del(struct inode *inode)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
+ spin_lock(&root->inode_lock);
if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) {
- spin_lock(&root->inode_lock);
rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree);
- spin_unlock(&root->inode_lock);
RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
}
+ spin_unlock(&root->inode_lock);
}
static noinline void init_btrfs_i(struct inode *inode)
diff --git a/fs/buffer.c b/fs/buffer.c
index a3ef091a45bd..28f320fac4d4 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1165,8 +1165,11 @@ void mark_buffer_dirty(struct buffer_head *bh)
if (!test_set_buffer_dirty(bh)) {
struct page *page = bh->b_page;
- if (!TestSetPageDirty(page))
- __set_page_dirty(page, page_mapping(page), 0);
+ if (!TestSetPageDirty(page)) {
+ struct address_space *mapping = page_mapping(page);
+ if (mapping)
+ __set_page_dirty(page, mapping, 0);
+ }
}
}
diff --git a/fs/exec.c b/fs/exec.c
index 4a8849e45b21..fb4f3cdda78c 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -678,8 +678,8 @@ exit:
}
EXPORT_SYMBOL(open_exec);
-int kernel_read(struct file *file, unsigned long offset,
- char *addr, unsigned long count)
+int kernel_read(struct file *file, loff_t offset,
+ char *addr, unsigned long count)
{
mm_segment_t old_fs;
loff_t pos = offset;
diff --git a/fs/ext3/Kconfig b/fs/ext3/Kconfig
index fb3c1a21b135..522b15498f45 100644
--- a/fs/ext3/Kconfig
+++ b/fs/ext3/Kconfig
@@ -29,23 +29,25 @@ config EXT3_FS
module will be called ext3.
config EXT3_DEFAULTS_TO_ORDERED
- bool "Default to 'data=ordered' in ext3 (legacy option)"
+ bool "Default to 'data=ordered' in ext3"
depends on EXT3_FS
help
- If a filesystem does not explicitly specify a data ordering
- mode, and the journal capability allowed it, ext3 used to
- historically default to 'data=ordered'.
-
- That was a rather unfortunate choice, because it leads to all
- kinds of latency problems, and the 'data=writeback' mode is more
- appropriate these days.
-
- You should probably always answer 'n' here, and if you really
- want to use 'data=ordered' mode, set it in the filesystem itself
- with 'tune2fs -o journal_data_ordered'.
-
- But if you really want to enable the legacy default, you can do
- so by answering 'y' to this question.
+ The journal mode options for ext3 have different tradeoffs
+ between when data is guaranteed to be on disk and
+ performance. The use of "data=writeback" can cause
+ unwritten data to appear in files after an system crash or
+ power failure, which can be a security issue. However,
+ "data=ordered" mode can also result in major performance
+ problems, including seconds-long delays before an fsync()
+ call returns. For details, see:
+
+ http://ext4.wiki.kernel.org/index.php/Ext3_data_mode_tradeoffs
+
+ If you have been historically happy with ext3's performance,
+ data=ordered mode will be a safe choice and you should
+ answer 'y' here. If you understand the reliability and data
+ privacy issues of data=writeback and are willing to make
+ that trade off, answer 'n'.
config EXT3_FS_XATTR
bool "Ext3 extended attributes"
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 524b349c6299..a8d80a7f1105 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -543,6 +543,19 @@ static inline void ext3_show_quota_options(struct seq_file *seq, struct super_bl
#endif
}
+static char *data_mode_string(unsigned long mode)
+{
+ switch (mode) {
+ case EXT3_MOUNT_JOURNAL_DATA:
+ return "journal";
+ case EXT3_MOUNT_ORDERED_DATA:
+ return "ordered";
+ case EXT3_MOUNT_WRITEBACK_DATA:
+ return "writeback";
+ }
+ return "unknown";
+}
+
/*
* Show an option if
* - it's set to a non-default value OR
@@ -616,13 +629,8 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
if (test_opt(sb, NOBH))
seq_puts(seq, ",nobh");
- if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
- seq_puts(seq, ",data=journal");
- else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
- seq_puts(seq, ",data=ordered");
- else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
- seq_puts(seq, ",data=writeback");
-
+ seq_printf(seq, ",data=%s", data_mode_string(sbi->s_mount_opt &
+ EXT3_MOUNT_DATA_FLAGS));
if (test_opt(sb, DATA_ERR_ABORT))
seq_puts(seq, ",data_err=abort");
@@ -1024,12 +1032,18 @@ static int parse_options (char *options, struct super_block *sb,
datacheck:
if (is_remount) {
if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS)
- != data_opt) {
- printk(KERN_ERR
- "EXT3-fs: cannot change data "
- "mode on remount\n");
- return 0;
- }
+ == data_opt)
+ break;
+ printk(KERN_ERR
+ "EXT3-fs (device %s): Cannot change "
+ "data mode on remount. The filesystem "
+ "is mounted in data=%s mode and you "
+ "try to remount it in data=%s mode.\n",
+ sb->s_id,
+ data_mode_string(sbi->s_mount_opt &
+ EXT3_MOUNT_DATA_FLAGS),
+ data_mode_string(data_opt));
+ return 0;
} else {
sbi->s_mount_opt &= ~EXT3_MOUNT_DATA_FLAGS;
sbi->s_mount_opt |= data_opt;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 941c8425c10b..cb88dac8ccaa 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -935,26 +935,28 @@ static int can_do_hugetlb_shm(void)
return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group);
}
-struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag)
+struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
+ struct user_struct **user)
{
int error = -ENOMEM;
- int unlock_shm = 0;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct qstr quick_string;
- struct user_struct *user = current_user();
+ *user = NULL;
if (!hugetlbfs_vfsmount)
return ERR_PTR(-ENOENT);
if (!can_do_hugetlb_shm()) {
- if (user_shm_lock(size, user)) {
- unlock_shm = 1;
+ *user = current_user();
+ if (user_shm_lock(size, *user)) {
WARN_ONCE(1,
"Using mlock ulimits for SHM_HUGETLB deprecated\n");
- } else
+ } else {
+ *user = NULL;
return ERR_PTR(-EPERM);
+ }
}
root = hugetlbfs_vfsmount->mnt_root;
@@ -996,8 +998,10 @@ out_inode:
out_dentry:
dput(dentry);
out_shm_unlock:
- if (unlock_shm)
- user_shm_unlock(size, user);
+ if (*user) {
+ user_shm_unlock(size, *user);
+ *user = NULL;
+ }
return ERR_PTR(error);
}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 65ca8c18476f..1434080aefeb 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1250,8 +1250,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
continue;
}
/* Initialize or reset the session */
- if (nfs4_has_session(clp) &&
- test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
+ if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
+ && nfs4_has_session(clp)) {
if (clp->cl_cons_state == NFS_CS_SESSION_INITING)
status = nfs4_initialize_session(clp);
else
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 5dcbafe72d71..c9ee67b442e1 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -105,16 +105,45 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode
return send;
}
+/*
+ * This is NEVER supposed to be called. Inotify marks should either have been
+ * removed from the idr when the watch was removed or in the
+ * fsnotify_destroy_mark_by_group() call when the inotify instance was being
+ * torn down. This is only called if the idr is about to be freed but there
+ * are still marks in it.
+ */
static int idr_callback(int id, void *p, void *data)
{
- BUG();
+ struct fsnotify_mark_entry *entry;
+ struct inotify_inode_mark_entry *ientry;
+ static bool warned = false;
+
+ if (warned)
+ return 0;
+
+ warned = false;
+ entry = p;
+ ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
+
+ WARN(1, "inotify closing but id=%d for entry=%p in group=%p still in "
+ "idr. Probably leaking memory\n", id, p, data);
+
+ /*
+ * I'm taking the liberty of assuming that the mark in question is a
+ * valid address and I'm dereferencing it. This might help to figure
+ * out why we got here and the panic is no worse than the original
+ * BUG() that was here.
+ */
+ if (entry)
+ printk(KERN_WARNING "entry->group=%p inode=%p wd=%d\n",
+ entry->group, entry->inode, ientry->wd);
return 0;
}
static void inotify_free_group_priv(struct fsnotify_group *group)
{
/* ideally the idr is empty and we won't hit the BUG in teh callback */
- idr_for_each(&group->inotify_data.idr, idr_callback, NULL);
+ idr_for_each(&group->inotify_data.idr, idr_callback, group);
idr_remove_all(&group->inotify_data.idr);
idr_destroy(&group->inotify_data.idr);
}
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index dc32ed8323ba..dcd2040d330c 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -47,9 +47,6 @@
static struct vfsmount *inotify_mnt __read_mostly;
-/* this just sits here and wastes global memory. used to just pad userspace messages with zeros */
-static struct inotify_event nul_inotify_event;
-
/* these are configurable via /proc/sys/fs/inotify/ */
static int inotify_max_user_instances __read_mostly;
static int inotify_max_queued_events __read_mostly;
@@ -157,7 +154,8 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
event = fsnotify_peek_notify_event(group);
- event_size += roundup(event->name_len, event_size);
+ if (event->name_len)
+ event_size += roundup(event->name_len + 1, event_size);
if (event_size > count)
return ERR_PTR(-EINVAL);
@@ -183,7 +181,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
struct fsnotify_event_private_data *fsn_priv;
struct inotify_event_private_data *priv;
size_t event_size = sizeof(struct inotify_event);
- size_t name_len;
+ size_t name_len = 0;
/* we get the inotify watch descriptor from the event private data */
spin_lock(&event->lock);
@@ -199,8 +197,12 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
inotify_free_event_priv(fsn_priv);
}
- /* round up event->name_len so it is a multiple of event_size */
- name_len = roundup(event->name_len, event_size);
+ /*
+ * round up event->name_len so it is a multiple of event_size
+ * plus an extra byte for the terminating '\0'.
+ */
+ if (event->name_len)
+ name_len = roundup(event->name_len + 1, event_size);
inotify_event.len = name_len;
inotify_event.mask = inotify_mask_to_arg(event->mask);
@@ -224,8 +226,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
return -EFAULT;
buf += event->name_len;
- /* fill userspace with 0's from nul_inotify_event */
- if (copy_to_user(buf, &nul_inotify_event, len_to_zero))
+ /* fill userspace with 0's */
+ if (clear_user(buf, len_to_zero))
return -EFAULT;
buf += len_to_zero;
event_size += name_len;
@@ -326,8 +328,9 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
list_for_each_entry(holder, &group->notification_list, event_list) {
event = holder->event;
send_len += sizeof(struct inotify_event);
- send_len += roundup(event->name_len,
- sizeof(struct inotify_event));
+ if (event->name_len)
+ send_len += roundup(event->name_len + 1,
+ sizeof(struct inotify_event));
}
mutex_unlock(&group->notification_mutex);
ret = put_user(send_len, (int __user *) p);
@@ -364,20 +367,53 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns
return error;
}
+/*
+ * Remove the mark from the idr (if present) and drop the reference
+ * on the mark because it was in the idr.
+ */
static void inotify_remove_from_idr(struct fsnotify_group *group,
struct inotify_inode_mark_entry *ientry)
{
struct idr *idr;
+ struct fsnotify_mark_entry *entry;
+ struct inotify_inode_mark_entry *found_ientry;
+ int wd;
spin_lock(&group->inotify_data.idr_lock);
idr = &group->inotify_data.idr;
- idr_remove(idr, ientry->wd);
- spin_unlock(&group->inotify_data.idr_lock);
+ wd = ientry->wd;
+
+ if (wd == -1)
+ goto out;
+
+ entry = idr_find(&group->inotify_data.idr, wd);
+ if (unlikely(!entry))
+ goto out;
+
+ found_ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
+ if (unlikely(found_ientry != ientry)) {
+ /* We found an entry in the idr with the right wd, but it's
+ * not the entry we were told to remove. eparis seriously
+ * fucked up somewhere. */
+ WARN_ON(1);
+ ientry->wd = -1;
+ goto out;
+ }
+
+ /* One ref for being in the idr, one ref held by the caller */
+ BUG_ON(atomic_read(&entry->refcnt) < 2);
+
+ idr_remove(idr, wd);
ientry->wd = -1;
+
+ /* removed from the idr, drop that ref */
+ fsnotify_put_mark(entry);
+out:
+ spin_unlock(&group->inotify_data.idr_lock);
}
+
/*
- * Send IN_IGNORED for this wd, remove this wd from the idr, and drop the
- * internal reference help on the mark because it is in the idr.
+ * Send IN_IGNORED for this wd, remove this wd from the idr.
*/
void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry,
struct fsnotify_group *group)
@@ -417,9 +453,6 @@ skip_send_ignore:
/* remove this entry from the idr */
inotify_remove_from_idr(group, ientry);
- /* removed from idr, drop that reference */
- fsnotify_put_mark(entry);
-
atomic_dec(&group->inotify_data.user->inotify_watches);
}
@@ -431,80 +464,29 @@ static void inotify_free_mark(struct fsnotify_mark_entry *entry)
kmem_cache_free(inotify_inode_mark_cachep, ientry);
}
-static int inotify_update_watch(struct fsnotify_group *group, struct inode *inode, u32 arg)
+static int inotify_update_existing_watch(struct fsnotify_group *group,
+ struct inode *inode,
+ u32 arg)
{
- struct fsnotify_mark_entry *entry = NULL;
+ struct fsnotify_mark_entry *entry;
struct inotify_inode_mark_entry *ientry;
- struct inotify_inode_mark_entry *tmp_ientry;
- int ret = 0;
- int add = (arg & IN_MASK_ADD);
- __u32 mask;
__u32 old_mask, new_mask;
+ __u32 mask;
+ int add = (arg & IN_MASK_ADD);
+ int ret;
/* don't allow invalid bits: we don't want flags set */
mask = inotify_arg_to_mask(arg);
if (unlikely(!mask))
return -EINVAL;
- tmp_ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
- if (unlikely(!tmp_ientry))
- return -ENOMEM;
- /* we set the mask at the end after attaching it */
- fsnotify_init_mark(&tmp_ientry->fsn_entry, inotify_free_mark);
- tmp_ientry->wd = -1;
-
-find_entry:
spin_lock(&inode->i_lock);
entry = fsnotify_find_mark_entry(group, inode);
spin_unlock(&inode->i_lock);
- if (entry) {
- ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
- } else {
- ret = -ENOSPC;
- if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches)
- goto out_err;
-retry:
- ret = -ENOMEM;
- if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
- goto out_err;
-
- spin_lock(&group->inotify_data.idr_lock);
- ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry,
- group->inotify_data.last_wd,
- &tmp_ientry->wd);
- spin_unlock(&group->inotify_data.idr_lock);
- if (ret) {
- if (ret == -EAGAIN)
- goto retry;
- goto out_err;
- }
-
- ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
- if (ret) {
- inotify_remove_from_idr(group, tmp_ientry);
- if (ret == -EEXIST)
- goto find_entry;
- goto out_err;
- }
-
- /* tmp_ientry has been added to the inode, so we are all set up.
- * now we just need to make sure tmp_ientry doesn't get freed and
- * we need to set up entry and ientry so the generic code can
- * do its thing. */
- ientry = tmp_ientry;
- entry = &ientry->fsn_entry;
- tmp_ientry = NULL;
-
- atomic_inc(&group->inotify_data.user->inotify_watches);
-
- /* update the idr hint */
- group->inotify_data.last_wd = ientry->wd;
-
- /* we put the mark on the idr, take a reference */
- fsnotify_get_mark(entry);
- }
+ if (!entry)
+ return -ENOENT;
- ret = ientry->wd;
+ ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
spin_lock(&entry->lock);
@@ -536,18 +518,107 @@ retry:
fsnotify_recalc_group_mask(group);
}
- /* this either matches fsnotify_find_mark_entry, or init_mark_entry
- * depending on which path we took... */
+ /* return the wd */
+ ret = ientry->wd;
+
+ /* match the get from fsnotify_find_mark_entry() */
fsnotify_put_mark(entry);
+ return ret;
+}
+
+static int inotify_new_watch(struct fsnotify_group *group,
+ struct inode *inode,
+ u32 arg)
+{
+ struct inotify_inode_mark_entry *tmp_ientry;
+ __u32 mask;
+ int ret;
+
+ /* don't allow invalid bits: we don't want flags set */
+ mask = inotify_arg_to_mask(arg);
+ if (unlikely(!mask))
+ return -EINVAL;
+
+ tmp_ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
+ if (unlikely(!tmp_ientry))
+ return -ENOMEM;
+
+ fsnotify_init_mark(&tmp_ientry->fsn_entry, inotify_free_mark);
+ tmp_ientry->fsn_entry.mask = mask;
+ tmp_ientry->wd = -1;
+
+ ret = -ENOSPC;
+ if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches)
+ goto out_err;
+retry:
+ ret = -ENOMEM;
+ if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
+ goto out_err;
+
+ spin_lock(&group->inotify_data.idr_lock);
+ ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry,
+ group->inotify_data.last_wd,
+ &tmp_ientry->wd);
+ spin_unlock(&group->inotify_data.idr_lock);
+ if (ret) {
+ /* idr was out of memory allocate and try again */
+ if (ret == -EAGAIN)
+ goto retry;
+ goto out_err;
+ }
+
+ /* we put the mark on the idr, take a reference */
+ fsnotify_get_mark(&tmp_ientry->fsn_entry);
+
+ /* we are on the idr, now get on the inode */
+ ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
+ if (ret) {
+ /* we failed to get on the inode, get off the idr */
+ inotify_remove_from_idr(group, tmp_ientry);
+ goto out_err;
+ }
+
+ /* update the idr hint, who cares about races, it's just a hint */
+ group->inotify_data.last_wd = tmp_ientry->wd;
+
+ /* increment the number of watches the user has */
+ atomic_inc(&group->inotify_data.user->inotify_watches);
+
+ /* return the watch descriptor for this new entry */
+ ret = tmp_ientry->wd;
+
+ /* match the ref from fsnotify_init_markentry() */
+ fsnotify_put_mark(&tmp_ientry->fsn_entry);
+
+ /* if this mark added a new event update the group mask */
+ if (mask & ~group->mask)
+ fsnotify_recalc_group_mask(group);
+
out_err:
- /* could be an error, could be that we found an existing mark */
- if (tmp_ientry) {
- /* on the idr but didn't make it on the inode */
- if (tmp_ientry->wd != -1)
- inotify_remove_from_idr(group, tmp_ientry);
+ if (ret < 0)
kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry);
- }
+
+ return ret;
+}
+
+static int inotify_update_watch(struct fsnotify_group *group, struct inode *inode, u32 arg)
+{
+ int ret = 0;
+
+retry:
+ /* try to update and existing watch with the new arg */
+ ret = inotify_update_existing_watch(group, inode, arg);
+ /* no mark present, try to add a new one */
+ if (ret == -ENOENT)
+ ret = inotify_new_watch(group, inode, arg);
+ /*
+ * inotify_new_watch could race with another thread which did an
+ * inotify_new_watch between the update_existing and the add watch
+ * here, go back and try to update an existing mark again.
+ */
+ if (ret == -EEXIST)
+ goto retry;
return ret;
}
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index f9a3e8942669..ab513ddaeff2 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -6851,7 +6851,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
}
status = 0;
bail:
-
+ brelse(last_eb_bh);
mlog_exit(status);
return status;
}
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index fcf879ed6930..756f5b0998e0 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -122,7 +122,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
* that still has AST's pending... */
in_use = !list_empty(&lock->ast_list);
spin_unlock(&dlm->ast_lock);
- if (in_use) {
+ if (in_use && !(flags & LKM_CANCEL)) {
mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock "
"while waiting for an ast!", res->lockname.len,
res->lockname.name);
@@ -131,7 +131,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
spin_lock(&res->spinlock);
if (res->state & DLM_LOCK_RES_IN_PROGRESS) {
- if (master_node) {
+ if (master_node && !(flags & LKM_CANCEL)) {
mlog(ML_ERROR, "lockres in progress!\n");
spin_unlock(&res->spinlock);
return DLM_FORWARD;
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
index fcdba091af3d..c212cf5a2bdf 100644
--- a/fs/ocfs2/ocfs2_lockid.h
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -108,6 +108,7 @@ static char *ocfs2_lock_type_strings[] = {
[OCFS2_LOCK_TYPE_OPEN] = "Open",
[OCFS2_LOCK_TYPE_FLOCK] = "Flock",
[OCFS2_LOCK_TYPE_QINFO] = "Quota",
+ [OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
[OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
};
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index bf7742d0ee3b..44f2a5e1d042 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -23,6 +23,7 @@
#include "sysfile.h"
#include "dlmglue.h"
#include "uptodate.h"
+#include "super.h"
#include "quota.h"
static struct workqueue_struct *ocfs2_quota_wq = NULL;
@@ -114,6 +115,15 @@ int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
int rc = 0;
struct buffer_head *tmp = *bh;
+ if (i_size_read(inode) >> inode->i_sb->s_blocksize_bits <= v_block) {
+ ocfs2_error(inode->i_sb,
+ "Quota file %llu is probably corrupted! Requested "
+ "to read block %Lu but file has size only %Lu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)v_block,
+ (unsigned long long)i_size_read(inode));
+ return -EIO;
+ }
rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, 0,
ocfs2_validate_quota_block);
if (rc)
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index b0ee0fdf799a..a3f8871d21fd 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1218,13 +1218,17 @@ static void ocfs2_kill_sb(struct super_block *sb)
{
struct ocfs2_super *osb = OCFS2_SB(sb);
+ /* Failed mount? */
+ if (!osb || atomic_read(&osb->vol_state) == VOLUME_DISABLED)
+ goto out;
+
/* Prevent further queueing of inode drop events */
spin_lock(&dentry_list_lock);
ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED);
spin_unlock(&dentry_list_lock);
/* Wait for work to finish and/or remove it */
cancel_work_sync(&osb->dentry_lock_work);
-
+out:
kill_block_super(sb);
}
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index baf1e0a9a7ee..740ac3ad8fd0 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -174,7 +174,7 @@ struct acpi_processor_throttling {
cpumask_var_t shared_cpu_map;
int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
- int state);
+ int state, bool force);
u32 address;
u8 duty_offset;
@@ -321,7 +321,8 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
/* in processor_throttling.c */
int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
int acpi_processor_get_throttling_info(struct acpi_processor *pr);
-extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+extern int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force);
extern const struct file_operations acpi_processor_throttling_fops;
extern void acpi_processor_throttling_init(void);
/* in processor_idle.c */
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index f81c3232accd..2ba61e18fc8b 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -508,6 +508,7 @@ typedef struct {
#define DRM_RADEON_INFO 0x27
#define DRM_RADEON_GEM_SET_TILING 0x28
#define DRM_RADEON_GEM_GET_TILING 0x29
+#define DRM_RADEON_GEM_BUSY 0x2a
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -548,6 +549,7 @@ typedef struct {
#define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info)
#define DRM_IOCTL_RADEON_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling)
#define DRM_IOCTL_RADEON_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling)
+#define DRM_IOCTL_RADEON_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy)
typedef struct drm_radeon_init {
enum {
@@ -707,6 +709,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_FB_LOCATION 14 /* FB location */
#define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */
#define RADEON_PARAM_DEVICE_ID 16
+#define RADEON_PARAM_NUM_Z_PIPES 17 /* num Z pipes */
typedef struct drm_radeon_getparam {
int param;
@@ -895,6 +898,7 @@ struct drm_radeon_cs {
#define RADEON_INFO_DEVICE_ID 0x00
#define RADEON_INFO_NUM_GB_PIPES 0x01
+#define RADEON_INFO_NUM_Z_PIPES 0x02
struct drm_radeon_info {
uint32_t request;
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 2878811c6134..756d78b8c1c5 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -94,13 +94,13 @@ extern void __bitmap_shift_right(unsigned long *dst,
const unsigned long *src, int shift, int bits);
extern void __bitmap_shift_left(unsigned long *dst,
const unsigned long *src, int shift, int bits);
-extern void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
-extern void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern int __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
@@ -171,13 +171,12 @@ static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
}
}
-static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
+static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, int nbits)
{
if (small_const_nbits(nbits))
- *dst = *src1 & *src2;
- else
- __bitmap_and(dst, src1, src2, nbits);
+ return (*dst = *src1 & *src2) != 0;
+ return __bitmap_and(dst, src1, src2, nbits);
}
static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
@@ -198,13 +197,12 @@ static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
__bitmap_xor(dst, src1, src2, nbits);
}
-static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, int nbits)
{
if (small_const_nbits(nbits))
- *dst = *src1 & ~(*src2);
- else
- __bitmap_andnot(dst, src1, src2, nbits);
+ return (*dst = *src1 & ~(*src2)) != 0;
+ return __bitmap_andnot(dst, src1, src2, nbits);
}
static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c5ac87ca7bc6..796df12091b7 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -43,10 +43,10 @@
* int cpu_isset(cpu, mask) true iff bit 'cpu' set in mask
* int cpu_test_and_set(cpu, mask) test and set bit 'cpu' in mask
*
- * void cpus_and(dst, src1, src2) dst = src1 & src2 [intersection]
+ * int cpus_and(dst, src1, src2) dst = src1 & src2 [intersection]
* void cpus_or(dst, src1, src2) dst = src1 | src2 [union]
* void cpus_xor(dst, src1, src2) dst = src1 ^ src2
- * void cpus_andnot(dst, src1, src2) dst = src1 & ~src2
+ * int cpus_andnot(dst, src1, src2) dst = src1 & ~src2
* void cpus_complement(dst, src) dst = ~src
*
* int cpus_equal(mask1, mask2) Does mask1 == mask2?
@@ -179,10 +179,10 @@ static inline int __cpu_test_and_set(int cpu, cpumask_t *addr)
}
#define cpus_and(dst, src1, src2) __cpus_and(&(dst), &(src1), &(src2), NR_CPUS)
-static inline void __cpus_and(cpumask_t *dstp, const cpumask_t *src1p,
+static inline int __cpus_and(cpumask_t *dstp, const cpumask_t *src1p,
const cpumask_t *src2p, int nbits)
{
- bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits);
+ return bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits);
}
#define cpus_or(dst, src1, src2) __cpus_or(&(dst), &(src1), &(src2), NR_CPUS)
@@ -201,10 +201,10 @@ static inline void __cpus_xor(cpumask_t *dstp, const cpumask_t *src1p,
#define cpus_andnot(dst, src1, src2) \
__cpus_andnot(&(dst), &(src1), &(src2), NR_CPUS)
-static inline void __cpus_andnot(cpumask_t *dstp, const cpumask_t *src1p,
+static inline int __cpus_andnot(cpumask_t *dstp, const cpumask_t *src1p,
const cpumask_t *src2p, int nbits)
{
- bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits);
+ return bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits);
}
#define cpus_complement(dst, src) __cpus_complement(&(dst), &(src), NR_CPUS)
@@ -738,11 +738,11 @@ static inline void cpumask_clear(struct cpumask *dstp)
* @src1p: the first input
* @src2p: the second input
*/
-static inline void cpumask_and(struct cpumask *dstp,
+static inline int cpumask_and(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
- bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
+ return bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}
@@ -779,11 +779,11 @@ static inline void cpumask_xor(struct cpumask *dstp,
* @src1p: the first input
* @src2p: the second input
*/
-static inline void cpumask_andnot(struct cpumask *dstp,
+static inline int cpumask_andnot(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
- bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
+ return bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}
diff --git a/include/linux/flex_array.h b/include/linux/flex_array.h
index 23c1ec79a31b..45ff18491514 100644
--- a/include/linux/flex_array.h
+++ b/include/linux/flex_array.h
@@ -21,7 +21,7 @@ struct flex_array {
struct {
int element_size;
int total_nr_elements;
- struct flex_array_part *parts[0];
+ struct flex_array_part *parts[];
};
/*
* This little trick makes sure that
@@ -36,12 +36,14 @@ struct flex_array {
.total_nr_elements = (total), \
} } }
-struct flex_array *flex_array_alloc(int element_size, int total, gfp_t flags);
-int flex_array_prealloc(struct flex_array *fa, int start, int end, gfp_t flags);
+struct flex_array *flex_array_alloc(int element_size, unsigned int total,
+ gfp_t flags);
+int flex_array_prealloc(struct flex_array *fa, unsigned int start,
+ unsigned int end, gfp_t flags);
void flex_array_free(struct flex_array *fa);
void flex_array_free_parts(struct flex_array *fa);
-int flex_array_put(struct flex_array *fa, int element_nr, void *src,
+int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
gfp_t flags);
-void *flex_array_get(struct flex_array *fa, int element_nr);
+void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
#endif /* _FLEX_ARRAY_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 67888a9e0655..73e9b643e455 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2123,7 +2123,7 @@ extern struct file *do_filp_open(int dfd, const char *pathname,
int open_flag, int mode, int acc_mode);
extern int may_open(struct path *, int, int);
-extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
+extern int kernel_read(struct file *, loff_t, char *, unsigned long);
extern struct file * open_exec(const char *);
/* fs/dcache.c -- generic fs support functions */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 2723513a5651..5cbc620bdfe0 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -10,6 +10,7 @@
#include <asm/tlbflush.h>
struct ctl_table;
+struct user_struct;
int PageHuge(struct page *page);
@@ -146,7 +147,8 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
-struct file *hugetlb_file_setup(const char *name, size_t, int);
+struct file *hugetlb_file_setup(const char *name, size_t size, int acct,
+ struct user_struct **user);
int hugetlb_get_quota(struct address_space *mapping, long delta);
void hugetlb_put_quota(struct address_space *mapping, long delta);
@@ -168,7 +170,7 @@ static inline void set_file_hugepages(struct file *file)
#define is_file_hugepages(file) 0
#define set_file_hugepages(file) BUG()
-#define hugetlb_file_setup(name,size,acctflag) ERR_PTR(-ENOSYS)
+#define hugetlb_file_setup(name,size,acct,user) ERR_PTR(-ENOSYS)
#endif /* !CONFIG_HUGETLBFS */
diff --git a/include/linux/lmb.h b/include/linux/lmb.h
index c46c89505dac..2442e3f3d033 100644
--- a/include/linux/lmb.h
+++ b/include/linux/lmb.h
@@ -51,7 +51,7 @@ extern u64 __init lmb_alloc_base(u64 size,
extern u64 __init __lmb_alloc_base(u64 size,
u64 align, u64 max_addr);
extern u64 __init lmb_phys_mem_size(void);
-extern u64 __init lmb_end_of_DRAM(void);
+extern u64 lmb_end_of_DRAM(void);
extern void __init lmb_enforce_memory_limit(u64 memory_limit);
extern int __init lmb_is_reserved(u64 addr);
extern int lmb_find(struct lmb_property *res);
diff --git a/include/linux/ucb1400.h b/include/linux/ucb1400.h
index ed889f4168f3..ae779bb8cc0f 100644
--- a/include/linux/ucb1400.h
+++ b/include/linux/ucb1400.h
@@ -73,6 +73,10 @@
#define UCB_ADC_DATA 0x68
#define UCB_ADC_DAT_VALID (1 << 15)
+
+#define UCB_FCSR 0x6c
+#define UCB_FCSR_AVE (1 << 12)
+
#define UCB_ADC_DAT_MASK 0x3ff
#define UCB_ID 0x7e
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 82a3191375f5..7eafb8d54470 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -61,8 +61,8 @@ psched_tdiff_bounded(psched_time_t tv1, psched_time_t tv2, psched_time_t bound)
}
struct qdisc_watchdog {
- struct hrtimer timer;
- struct Qdisc *qdisc;
+ struct tasklet_hrtimer timer;
+ struct Qdisc *qdisc;
};
extern void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc);
diff --git a/init/main.c b/init/main.c
index 2d9d6bdfe7c9..11f4f145be3f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -733,13 +733,14 @@ static void __init do_ctors(void)
int initcall_debug;
core_param(initcall_debug, initcall_debug, bool, 0644);
+static char msgbuf[64];
+static struct boot_trace_call call;
+static struct boot_trace_ret ret;
+
int do_one_initcall(initcall_t fn)
{
int count = preempt_count();
ktime_t calltime, delta, rettime;
- char msgbuf[64];
- struct boot_trace_call call;
- struct boot_trace_ret ret;
if (initcall_debug) {
call.caller = task_pid_nr(current);
diff --git a/ipc/shm.c b/ipc/shm.c
index 15dd238e5338..1bc4701ef4f0 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -174,7 +174,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
shm_unlock(shp);
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 0, shp->mlock_user);
- else
+ else if (shp->mlock_user)
user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
shp->mlock_user);
fput (shp->shm_file);
@@ -369,8 +369,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
/* hugetlb_file_setup applies strict accounting */
if (shmflg & SHM_NORESERVE)
acctflag = VM_NORESERVE;
- file = hugetlb_file_setup(name, size, acctflag);
- shp->mlock_user = current_user();
+ file = hugetlb_file_setup(name, size, acctflag,
+ &shp->mlock_user);
} else {
/*
* Do not allow no accounting for OVERCOMMIT_NEVER, even
@@ -410,6 +410,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
return error;
no_id:
+ if (shp->mlock_user) /* shmflg & SHM_HUGETLB case */
+ user_shm_unlock(size, shp->mlock_user);
fput(file);
no_file:
security_shm_free(shp);
diff --git a/kernel/fork.c b/kernel/fork.c
index 144326b7af50..e6c04d462ab2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -815,11 +815,8 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
{
struct signal_struct *sig;
- if (clone_flags & CLONE_THREAD) {
- atomic_inc(&current->signal->count);
- atomic_inc(&current->signal->live);
+ if (clone_flags & CLONE_THREAD)
return 0;
- }
sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
tsk->signal = sig;
@@ -877,16 +874,6 @@ void __cleanup_signal(struct signal_struct *sig)
kmem_cache_free(signal_cachep, sig);
}
-static void cleanup_signal(struct task_struct *tsk)
-{
- struct signal_struct *sig = tsk->signal;
-
- atomic_dec(&sig->live);
-
- if (atomic_dec_and_test(&sig->count))
- __cleanup_signal(sig);
-}
-
static void copy_flags(unsigned long clone_flags, struct task_struct *p)
{
unsigned long new_flags = p->flags;
@@ -1239,6 +1226,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
}
if (clone_flags & CLONE_THREAD) {
+ atomic_inc(&current->signal->count);
+ atomic_inc(&current->signal->live);
p->group_leader = current->group_leader;
list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
}
@@ -1282,7 +1271,8 @@ bad_fork_cleanup_mm:
if (p->mm)
mmput(p->mm);
bad_fork_cleanup_signal:
- cleanup_signal(p);
+ if (!(clone_flags & CLONE_THREAD))
+ __cleanup_signal(p->signal);
bad_fork_cleanup_sighand:
__cleanup_sighand(p->sighand);
bad_fork_cleanup_fs:
diff --git a/kernel/module.c b/kernel/module.c
index fd1411403558..2d537186191f 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -909,16 +909,18 @@ void __symbol_put(const char *symbol)
}
EXPORT_SYMBOL(__symbol_put);
+/* Note this assumes addr is a function, which it currently always is. */
void symbol_put_addr(void *addr)
{
struct module *modaddr;
+ unsigned long a = (unsigned long)dereference_function_descriptor(addr);
- if (core_kernel_text((unsigned long)addr))
+ if (core_kernel_text(a))
return;
/* module_text_address is safe here: we're supposed to have reference
* to module from symbol_get, so it can't go away. */
- modaddr = __module_text_address((unsigned long)addr);
+ modaddr = __module_text_address(a);
BUG_ON(!modaddr);
module_put(modaddr);
}
@@ -1272,6 +1274,10 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,
struct module_notes_attrs *notes_attrs;
struct bin_attribute *nattr;
+ /* failed to create section attributes, so can't create notes */
+ if (!mod->sect_attrs)
+ return;
+
/* Count notes sections and allocate structures. */
notes = 0;
for (i = 0; i < nsect; i++)
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 36f65e2b8b57..f274e1959885 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1791,7 +1791,7 @@ static int perf_counter_read_group(struct perf_counter *counter,
size += err;
list_for_each_entry(sub, &leader->sibling_list, list_entry) {
- err = perf_counter_read_entry(counter, read_format,
+ err = perf_counter_read_entry(sub, read_format,
buf + size);
if (err < 0)
return err;
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index a6dcd67b041d..620b58abdc32 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -137,11 +137,12 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
*/
int clockevents_register_notifier(struct notifier_block *nb)
{
+ unsigned long flags;
int ret;
- spin_lock(&clockevents_lock);
+ spin_lock_irqsave(&clockevents_lock, flags);
ret = raw_notifier_chain_register(&clockevents_chain, nb);
- spin_unlock(&clockevents_lock);
+ spin_unlock_irqrestore(&clockevents_lock, flags);
return ret;
}
@@ -178,16 +179,18 @@ static void clockevents_notify_released(void)
*/
void clockevents_register_device(struct clock_event_device *dev)
{
+ unsigned long flags;
+
BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
BUG_ON(!dev->cpumask);
- spin_lock(&clockevents_lock);
+ spin_lock_irqsave(&clockevents_lock, flags);
list_add(&dev->list, &clockevent_devices);
clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
clockevents_notify_released();
- spin_unlock(&clockevents_lock);
+ spin_unlock_irqrestore(&clockevents_lock, flags);
}
EXPORT_SYMBOL_GPL(clockevents_register_device);
@@ -235,8 +238,9 @@ void clockevents_exchange_device(struct clock_event_device *old,
void clockevents_notify(unsigned long reason, void *arg)
{
struct list_head *node, *tmp;
+ unsigned long flags;
- spin_lock(&clockevents_lock);
+ spin_lock_irqsave(&clockevents_lock, flags);
clockevents_do_notify(reason, arg);
switch (reason) {
@@ -251,7 +255,7 @@ void clockevents_notify(unsigned long reason, void *arg)
default:
break;
}
- spin_unlock(&clockevents_lock);
+ spin_unlock_irqrestore(&clockevents_lock, flags);
}
EXPORT_SYMBOL_GPL(clockevents_notify);
#endif
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 877dbedc3118..c2ec25087a35 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -205,11 +205,11 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
* Powerstate information: The system enters/leaves a state, where
* affected devices might stop
*/
-static void tick_do_broadcast_on_off(void *why)
+static void tick_do_broadcast_on_off(unsigned long *reason)
{
struct clock_event_device *bc, *dev;
struct tick_device *td;
- unsigned long flags, *reason = why;
+ unsigned long flags;
int cpu, bc_stopped;
spin_lock_irqsave(&tick_broadcast_lock, flags);
@@ -276,8 +276,7 @@ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
"offline CPU #%d\n", *oncpu);
else
- smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
- &reason, 1);
+ tick_do_broadcast_on_off(&reason);
}
/*
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index a999b92a1277..fddd69d16e03 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -286,7 +286,7 @@ static int __init init_timer_list_procfs(void)
{
struct proc_dir_entry *pe;
- pe = proc_create("timer_list", 0644, NULL, &timer_list_fops);
+ pe = proc_create("timer_list", 0444, NULL, &timer_list_fops);
if (!pe)
return -ENOMEM;
return 0;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1e1d23c26308..25edd5cc5935 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2278,7 +2278,11 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
read++;
cnt--;
- if (!(iter->flags & ~FTRACE_ITER_CONT)) {
+ /*
+ * If the parser haven't finished with the last write,
+ * continue reading the user input without skipping spaces.
+ */
+ if (!(iter->flags & FTRACE_ITER_CONT)) {
/* skip white space */
while (cnt && isspace(ch)) {
ret = get_user(ch, ubuf++);
@@ -2288,8 +2292,9 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
cnt--;
}
+ /* only spaces were written */
if (isspace(ch)) {
- file->f_pos += read;
+ *ppos += read;
ret = read;
goto out;
}
@@ -2319,12 +2324,12 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
if (ret)
goto out;
iter->buffer_idx = 0;
- } else
+ } else {
iter->flags |= FTRACE_ITER_CONT;
+ iter->buffer[iter->buffer_idx++] = ch;
+ }
-
- file->f_pos += read;
-
+ *ppos += read;
ret = read;
out:
mutex_unlock(&ftrace_regex_lock);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c22b40f8f576..8c358395d338 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3896,17 +3896,9 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
if (ret < 0)
return ret;
- switch (val) {
- case 0:
- trace_flags &= ~(1 << index);
- break;
- case 1:
- trace_flags |= 1 << index;
- break;
-
- default:
+ if (val != 0 && val != 1)
return -EINVAL;
- }
+ set_tracer_flags(1 << index, val);
*ppos += cnt;
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 35a1f7ff4149..702565821c99 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -179,14 +179,16 @@ void __bitmap_shift_left(unsigned long *dst,
}
EXPORT_SYMBOL(__bitmap_shift_left);
-void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits)
{
int k;
int nr = BITS_TO_LONGS(bits);
+ unsigned long result = 0;
for (k = 0; k < nr; k++)
- dst[k] = bitmap1[k] & bitmap2[k];
+ result |= (dst[k] = bitmap1[k] & bitmap2[k]);
+ return result != 0;
}
EXPORT_SYMBOL(__bitmap_and);
@@ -212,14 +214,16 @@ void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
}
EXPORT_SYMBOL(__bitmap_xor);
-void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits)
{
int k;
int nr = BITS_TO_LONGS(bits);
+ unsigned long result = 0;
for (k = 0; k < nr; k++)
- dst[k] = bitmap1[k] & ~bitmap2[k];
+ result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
+ return result != 0;
}
EXPORT_SYMBOL(__bitmap_andnot);
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 65b0d99b6d0a..58a9f9fc609a 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -156,9 +156,13 @@ static bool driver_filter(struct device *dev)
return true;
/* driver filter on and initialized */
- if (current_driver && dev->driver == current_driver)
+ if (current_driver && dev && dev->driver == current_driver)
return true;
+ /* driver filter on, but we can't filter on a NULL device... */
+ if (!dev)
+ return false;
+
if (current_driver || !current_driver_name[0])
return false;
@@ -183,17 +187,17 @@ static bool driver_filter(struct device *dev)
return ret;
}
-#define err_printk(dev, entry, format, arg...) do { \
- error_count += 1; \
- if (driver_filter(dev) && \
- (show_all_errors || show_num_errors > 0)) { \
- WARN(1, "%s %s: " format, \
- dev_driver_string(dev), \
- dev_name(dev) , ## arg); \
- dump_entry_trace(entry); \
- } \
- if (!show_all_errors && show_num_errors > 0) \
- show_num_errors -= 1; \
+#define err_printk(dev, entry, format, arg...) do { \
+ error_count += 1; \
+ if (driver_filter(dev) && \
+ (show_all_errors || show_num_errors > 0)) { \
+ WARN(1, "%s %s: " format, \
+ dev ? dev_driver_string(dev) : "NULL", \
+ dev ? dev_name(dev) : "NULL", ## arg); \
+ dump_entry_trace(entry); \
+ } \
+ if (!show_all_errors && show_num_errors > 0) \
+ show_num_errors -= 1; \
} while (0);
/*
diff --git a/lib/flex_array.c b/lib/flex_array.c
index 08f1636d296a..7baed2fc3bc8 100644
--- a/lib/flex_array.c
+++ b/lib/flex_array.c
@@ -99,7 +99,8 @@ static inline int elements_fit_in_base(struct flex_array *fa)
* capacity in the base structure. Also note that no effort is made
* to efficiently pack objects across page boundaries.
*/
-struct flex_array *flex_array_alloc(int element_size, int total, gfp_t flags)
+struct flex_array *flex_array_alloc(int element_size, unsigned int total,
+ gfp_t flags)
{
struct flex_array *ret;
int max_size = nr_base_part_ptrs() * __elements_per_part(element_size);
@@ -115,16 +116,14 @@ struct flex_array *flex_array_alloc(int element_size, int total, gfp_t flags)
return ret;
}
-static int fa_element_to_part_nr(struct flex_array *fa, int element_nr)
+static int fa_element_to_part_nr(struct flex_array *fa,
+ unsigned int element_nr)
{
return element_nr / __elements_per_part(fa->element_size);
}
/**
* flex_array_free_parts - just free the second-level pages
- * @src: address of data to copy into the array
- * @element_nr: index of the position in which to insert
- * the new element.
*
* This is to be used in cases where the base 'struct flex_array'
* has been statically allocated and should not be free.
@@ -146,14 +145,12 @@ void flex_array_free(struct flex_array *fa)
kfree(fa);
}
-static int fa_index_inside_part(struct flex_array *fa, int element_nr)
+static unsigned int index_inside_part(struct flex_array *fa,
+ unsigned int element_nr)
{
- return element_nr % __elements_per_part(fa->element_size);
-}
+ unsigned int part_offset;
-static int index_inside_part(struct flex_array *fa, int element_nr)
-{
- int part_offset = fa_index_inside_part(fa, element_nr);
+ part_offset = element_nr % __elements_per_part(fa->element_size);
return part_offset * fa->element_size;
}
@@ -188,7 +185,8 @@ __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags)
*
* Locking must be provided by the caller.
*/
-int flex_array_put(struct flex_array *fa, int element_nr, void *src, gfp_t flags)
+int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
+ gfp_t flags)
{
int part_nr = fa_element_to_part_nr(fa, element_nr);
struct flex_array_part *part;
@@ -198,10 +196,11 @@ int flex_array_put(struct flex_array *fa, int element_nr, void *src, gfp_t flags
return -ENOSPC;
if (elements_fit_in_base(fa))
part = (struct flex_array_part *)&fa->parts[0];
- else
+ else {
part = __fa_get_part(fa, part_nr, flags);
- if (!part)
- return -ENOMEM;
+ if (!part)
+ return -ENOMEM;
+ }
dst = &part->elements[index_inside_part(fa, element_nr)];
memcpy(dst, src, fa->element_size);
return 0;
@@ -219,7 +218,8 @@ int flex_array_put(struct flex_array *fa, int element_nr, void *src, gfp_t flags
*
* Locking must be provided by the caller.
*/
-int flex_array_prealloc(struct flex_array *fa, int start, int end, gfp_t flags)
+int flex_array_prealloc(struct flex_array *fa, unsigned int start,
+ unsigned int end, gfp_t flags)
{
int start_part;
int end_part;
@@ -250,18 +250,19 @@ int flex_array_prealloc(struct flex_array *fa, int start, int end, gfp_t flags)
*
* Locking must be provided by the caller.
*/
-void *flex_array_get(struct flex_array *fa, int element_nr)
+void *flex_array_get(struct flex_array *fa, unsigned int element_nr)
{
int part_nr = fa_element_to_part_nr(fa, element_nr);
struct flex_array_part *part;
if (element_nr >= fa->total_nr_elements)
return NULL;
- if (!fa->parts[part_nr])
- return NULL;
if (elements_fit_in_base(fa))
part = (struct flex_array_part *)&fa->parts[0];
- else
+ else {
part = fa->parts[part_nr];
+ if (!part)
+ return NULL;
+ }
return &part->elements[index_inside_part(fa, element_nr)];
}
diff --git a/lib/lmb.c b/lib/lmb.c
index e4a6482d8b26..0343c05609f0 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -429,7 +429,7 @@ u64 __init lmb_phys_mem_size(void)
return lmb.memory.size;
}
-u64 __init lmb_end_of_DRAM(void)
+u64 lmb_end_of_DRAM(void)
{
int idx = lmb.memory.cnt - 1;
diff --git a/mm/rmap.c b/mm/rmap.c
index 836c6c63e1f2..0895b5c7cbff 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -358,6 +358,7 @@ static int page_referenced_one(struct page *page,
*/
if (vma->vm_flags & VM_LOCKED) {
*mapcount = 1; /* break early from loop */
+ *vm_flags |= VM_LOCKED;
goto out_unmap;
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index dea7abd31098..94e86dd6954c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -630,9 +630,14 @@ static unsigned long shrink_page_list(struct list_head *page_list,
referenced = page_referenced(page, 1,
sc->mem_cgroup, &vm_flags);
- /* In active use or really unfreeable? Activate it. */
+ /*
+ * In active use or really unfreeable? Activate it.
+ * If page which have PG_mlocked lost isoltation race,
+ * try_to_unmap moves it to unevictable list
+ */
if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
- referenced && page_mapping_inuse(page))
+ referenced && page_mapping_inuse(page)
+ && !(vm_flags & VM_LOCKED))
goto activate_locked;
/*
diff --git a/net/9p/client.c b/net/9p/client.c
index 787ccddb85ea..5bf5f227dbe0 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -60,9 +60,9 @@ static struct p9_req_t *
p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
/**
- * v9fs_parse_options - parse mount options into session structure
- * @options: options string passed from mount
- * @v9ses: existing v9fs session information
+ * parse_options - parse mount options into client structure
+ * @opts: options string passed from mount
+ * @clnt: existing v9fs client information
*
* Return 0 upon success, -ERRNO upon failure
*/
@@ -232,7 +232,7 @@ EXPORT_SYMBOL(p9_tag_lookup);
/**
* p9_tag_init - setup tags structure and contents
- * @tags: tags structure from the client struct
+ * @c: v9fs client struct
*
* This initializes the tags structure for each client instance.
*
@@ -258,7 +258,7 @@ error:
/**
* p9_tag_cleanup - cleans up tags structure and reclaims resources
- * @tags: tags structure from the client struct
+ * @c: v9fs client struct
*
* This frees resources associated with the tags structure
*
@@ -411,14 +411,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
if (c->dotu)
err = -ecode;
- if (!err) {
+ if (!err || !IS_ERR_VALUE(err))
err = p9_errstr2errno(ename, strlen(ename));
- /* string match failed */
- if (!err)
- err = -ESERVERFAULT;
- }
-
P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
kfree(ename);
@@ -430,8 +425,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
/**
* p9_client_flush - flush (cancel) a request
- * c: client state
- * req: request to cancel
+ * @c: client state
+ * @oldreq: request to cancel
*
* This sents a flush for a particular requests and links
* the flush request to the original request. The current
diff --git a/net/9p/error.c b/net/9p/error.c
index fdebe4314062..52518512a93e 100644
--- a/net/9p/error.c
+++ b/net/9p/error.c
@@ -239,7 +239,7 @@ int p9_errstr2errno(char *errstr, int len)
errstr[len] = 0;
printk(KERN_ERR "%s: server reported unknown error %s\n",
__func__, errstr);
- errno = 1;
+ errno = ESERVERFAULT;
}
return -errno;
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 8c2588e4edc0..8d934dd7fd54 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -119,8 +119,8 @@ struct p9_poll_wait {
* @wpos: write position for current frame
* @wsize: amount of data to write for current frame
* @wbuf: current write buffer
+ * @poll_pending_link: pending links to be polled per conn
* @poll_wait: array of wait_q's for various worker threads
- * @poll_waddr: ????
* @pt: poll state
* @rq: current read work
* @wq: current write work
@@ -700,9 +700,9 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
}
/**
- * parse_options - parse mount options into session structure
- * @options: options string passed from mount
- * @opts: transport-specific structure to parse options into
+ * parse_opts - parse mount options into p9_fd_opts structure
+ * @params: options string passed from mount
+ * @opts: fd transport-specific structure to parse options into
*
* Returns 0 upon success, -ERRNO upon failure
*/
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index ac4990041ebb..65cb29db03f8 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -67,14 +67,15 @@
* @pd: Protection Domain pointer
* @qp: Queue Pair pointer
* @cq: Completion Queue pointer
+ * @dm_mr: DMA Memory Region pointer
* @lkey: The local access only memory region key
* @timeout: Number of uSecs to wait for connection management events
* @sq_depth: The depth of the Send Queue
* @sq_sem: Semaphore for the SQ
* @rq_depth: The depth of the Receive Queue.
+ * @rq_count: Count of requests in the Receive Queue.
* @addr: The remote peer's address
* @req_lock: Protects the active request list
- * @send_wait: Wait list when the SQ fills up
* @cm_done: Completion event for connection management tracking
*/
struct p9_trans_rdma {
@@ -154,9 +155,9 @@ static match_table_t tokens = {
};
/**
- * parse_options - parse mount options into session structure
- * @options: options string passed from mount
- * @opts: transport-specific structure to parse options into
+ * parse_opts - parse mount options into rdma options structure
+ * @params: options string passed from mount
+ * @opts: rdma transport-specific structure to parse options into
*
* Returns 0 upon success, -ERRNO upon failure
*/
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index a49484e67e1d..9bf0b737aa51 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -57,11 +57,9 @@ static int chan_index;
* @initialized: whether the channel is initialized
* @inuse: whether the channel is in use
* @lock: protects multiple elements within this structure
+ * @client: client instance
* @vdev: virtio dev associated with this channel
* @vq: virtio queue associated with this channel
- * @tagpool: accounting for tag ids (and request slots)
- * @reqs: array of request slots
- * @max_tag: current number of request_slots allocated
* @sg: scatter gather list which is used to pack a request (protected?)
*
* We keep all per-channel information in a structure.
@@ -92,7 +90,7 @@ static unsigned int rest_of_page(void *data)
/**
* p9_virtio_close - reclaim resources of a channel
- * @trans: transport state
+ * @client: client instance
*
* This reclaims a channel by freeing its resources and
* reseting its inuse flag.
@@ -181,9 +179,8 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
/**
* p9_virtio_request - issue a request
- * @t: transport state
- * @tc: &p9_fcall request to transmit
- * @rc: &p9_fcall to put reponse into
+ * @client: client instance issuing the request
+ * @req: request to be issued
*
*/
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index df30feb2fc72..1b76eb11deb4 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -319,6 +319,11 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
udelay(USEC_PER_POLL);
}
+
+ WARN_ONCE(!irqs_disabled(),
+ "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n",
+ dev->name, ops->ndo_start_xmit);
+
local_irq_restore(flags);
}
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 7d0821054729..7ffcd96fe591 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -813,6 +813,8 @@ int ip_append_data(struct sock *sk,
inet->cork.addr = ipc->addr;
}
rt = *rtp;
+ if (unlikely(!rt))
+ return -EFAULT;
/*
* We steal reference to this route, caller should not release it
*/
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index caa0278d30a9..45f9a2a42d56 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -306,8 +306,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
v4addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
- chk_addr_ret != RTN_BROADCAST)
+ chk_addr_ret != RTN_BROADCAST) {
+ err = -EADDRNOTAVAIL;
goto out;
+ }
} else {
if (addr_type != IPV6_ADDR_ANY) {
struct net_device *dev = NULL;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 9208cf5f2bd5..c45eee1c0e8d 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -914,6 +914,7 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
struct llc_sock *llc = llc_sk(sk);
int rc = 0;
+ memset(&sllc, 0, sizeof(sllc));
lock_sock(sk);
if (sock_flag(sk, SOCK_ZAPPED))
goto out;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ce267565e180..659a42d529e3 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -67,6 +67,8 @@ static DECLARE_WORK(todo_work, key_todo);
*
* @key: key to add to do item for
* @flag: todo flag(s)
+ *
+ * Must be called with IRQs or softirqs disabled.
*/
static void add_todo(struct ieee80211_key *key, u32 flag)
{
@@ -140,9 +142,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
if (!ret) {
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
@@ -164,12 +166,12 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
if (!key || !key->local->ops->set_key)
return;
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
return;
}
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
sta = get_sta_for_key(key);
sdata = key->sdata;
@@ -188,9 +190,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
wiphy_name(key->local->hw.wiphy),
key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
@@ -437,14 +439,14 @@ void ieee80211_key_link(struct ieee80211_key *key,
__ieee80211_key_replace(sdata, sta, old_key, key);
- spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-
/* free old key later */
add_todo(old_key, KEY_FLAG_TODO_DELETE);
add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
if (netif_running(sdata->dev))
add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
+
+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
}
static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -547,7 +549,7 @@ static void __ieee80211_key_todo(void)
*/
synchronize_rcu();
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
while (!list_empty(&todo_list)) {
key = list_first_entry(&todo_list, struct ieee80211_key, todo);
list_del_init(&key->todo);
@@ -558,7 +560,7 @@ static void __ieee80211_key_todo(void)
KEY_FLAG_TODO_HWACCEL_REMOVE |
KEY_FLAG_TODO_DELETE);
key->flags &= ~todoflags;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
work_done = false;
@@ -591,9 +593,9 @@ static void __ieee80211_key_todo(void)
WARN_ON(!work_done);
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
}
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
void ieee80211_key_todo(void)
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index 98fc190e8f0e..390b7d09fe51 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -52,7 +52,7 @@ static bool quota_mt_check(const struct xt_mtchk_param *par)
q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
if (q->master == NULL)
- return -ENOMEM;
+ return false;
q->master->quota = q->quota;
return true;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 24d17ce9c294..92e6f3a52c13 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -458,7 +458,7 @@ EXPORT_SYMBOL(qdisc_warn_nonwc);
static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
{
struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog,
- timer);
+ timer.timer);
wd->qdisc->flags &= ~TCQ_F_THROTTLED;
__netif_schedule(qdisc_root(wd->qdisc));
@@ -468,8 +468,8 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc)
{
- hrtimer_init(&wd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- wd->timer.function = qdisc_watchdog;
+ tasklet_hrtimer_init(&wd->timer, qdisc_watchdog,
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
wd->qdisc = qdisc;
}
EXPORT_SYMBOL(qdisc_watchdog_init);
@@ -485,13 +485,13 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
wd->qdisc->flags |= TCQ_F_THROTTLED;
time = ktime_set(0, 0);
time = ktime_add_ns(time, PSCHED_TICKS2NS(expires));
- hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
+ tasklet_hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
}
EXPORT_SYMBOL(qdisc_watchdog_schedule);
void qdisc_watchdog_cancel(struct qdisc_watchdog *wd)
{
- hrtimer_cancel(&wd->timer);
+ tasklet_hrtimer_cancel(&wd->timer);
wd->qdisc->flags &= ~TCQ_F_THROTTLED;
}
EXPORT_SYMBOL(qdisc_watchdog_cancel);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index d5798e17a832..149b0405c5ec 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -163,7 +163,7 @@ struct cbq_sched_data
psched_time_t now_rt; /* Cached real time */
unsigned pmask;
- struct hrtimer delay_timer;
+ struct tasklet_hrtimer delay_timer;
struct qdisc_watchdog watchdog; /* Watchdog timer,
started when CBQ has
backlog, but cannot
@@ -503,6 +503,8 @@ static void cbq_ovl_delay(struct cbq_class *cl)
cl->undertime = q->now + delay;
if (delay > 0) {
+ struct hrtimer *ht;
+
sched += delay + cl->penalty;
cl->penalized = sched;
cl->cpriority = TC_CBQ_MAXPRIO;
@@ -510,12 +512,12 @@ static void cbq_ovl_delay(struct cbq_class *cl)
expires = ktime_set(0, 0);
expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched));
- if (hrtimer_try_to_cancel(&q->delay_timer) &&
- ktime_to_ns(ktime_sub(
- hrtimer_get_expires(&q->delay_timer),
- expires)) > 0)
- hrtimer_set_expires(&q->delay_timer, expires);
- hrtimer_restart(&q->delay_timer);
+ ht = &q->delay_timer.timer;
+ if (hrtimer_try_to_cancel(ht) &&
+ ktime_to_ns(ktime_sub(hrtimer_get_expires(ht),
+ expires)) > 0)
+ hrtimer_set_expires(ht, expires);
+ hrtimer_restart(ht);
cl->delayed = 1;
cl->xstats.overactions++;
return;
@@ -591,7 +593,7 @@ static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio,
static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
{
struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data,
- delay_timer);
+ delay_timer.timer);
struct Qdisc *sch = q->watchdog.qdisc;
psched_time_t now;
psched_tdiff_t delay = 0;
@@ -621,7 +623,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
time = ktime_set(0, 0);
time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay));
- hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS);
+ tasklet_hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS);
}
sch->flags &= ~TCQ_F_THROTTLED;
@@ -1214,7 +1216,7 @@ cbq_reset(struct Qdisc* sch)
q->tx_class = NULL;
q->tx_borrowed = NULL;
qdisc_watchdog_cancel(&q->watchdog);
- hrtimer_cancel(&q->delay_timer);
+ tasklet_hrtimer_cancel(&q->delay_timer);
q->toplevel = TC_CBQ_MAXLEVEL;
q->now = psched_get_time();
q->now_rt = q->now;
@@ -1397,7 +1399,8 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
q->link.minidle = -0x7FFFFFFF;
qdisc_watchdog_init(&q->watchdog, sch);
- hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ tasklet_hrtimer_init(&q->delay_timer, cbq_undelay,
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
q->delay_timer.function = cbq_undelay;
q->toplevel = TC_CBQ_MAXLEVEL;
q->now = psched_get_time();
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ebfcf9b89909..df1039f077c2 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -937,6 +937,7 @@ static inline void
rpc_task_force_reencode(struct rpc_task *task)
{
task->tk_rqstp->rq_snd_buf.len = 0;
+ task->tk_rqstp->rq_bytes_sent = 0;
}
static inline void
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 63003a63aaee..46642a19bc78 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -45,9 +45,9 @@ int ima_calc_hash(struct file *file, char *digest)
{
struct hash_desc desc;
struct scatterlist sg[1];
- loff_t i_size;
+ loff_t i_size, offset = 0;
char *rbuf;
- int rc, offset = 0;
+ int rc;
rc = init_desc(&desc);
if (rc != 0)
@@ -67,6 +67,8 @@ int ima_calc_hash(struct file *file, char *digest)
rc = rbuf_len;
break;
}
+ if (rbuf_len == 0)
+ break;
offset += rbuf_len;
sg_init_one(sg, rbuf, rbuf_len);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 101c512564ec..4732f5e5d127 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -262,6 +262,8 @@ void ima_counts_put(struct path *path, int mask)
else if (mask & (MAY_READ | MAY_EXEC))
iint->readcount--;
mutex_unlock(&iint->mutex);
+
+ kref_put(&iint->refcount, iint_free);
}
/*
@@ -291,6 +293,8 @@ void ima_counts_get(struct file *file)
if (file->f_mode & FMODE_WRITE)
iint->writecount++;
mutex_unlock(&iint->mutex);
+
+ kref_put(&iint->refcount, iint_free);
}
EXPORT_SYMBOL_GPL(ima_counts_get);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 72cfd47af6b8..9db60d831bb2 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -943,47 +943,24 @@ static int snd_interval_ratden(struct snd_interval *i,
int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
{
unsigned int k;
- int changed = 0;
+ struct snd_interval list_range;
if (!count) {
i->empty = 1;
return -EINVAL;
}
+ snd_interval_any(&list_range);
+ list_range.min = UINT_MAX;
+ list_range.max = 0;
for (k = 0; k < count; k++) {
if (mask && !(mask & (1 << k)))
continue;
- if (i->min == list[k] && !i->openmin)
- goto _l1;
- if (i->min < list[k]) {
- i->min = list[k];
- i->openmin = 0;
- changed = 1;
- goto _l1;
- }
- }
- i->empty = 1;
- return -EINVAL;
- _l1:
- for (k = count; k-- > 0;) {
- if (mask && !(mask & (1 << k)))
+ if (!snd_interval_test(i, list[k]))
continue;
- if (i->max == list[k] && !i->openmax)
- goto _l2;
- if (i->max > list[k]) {
- i->max = list[k];
- i->openmax = 0;
- changed = 1;
- goto _l2;
- }
+ list_range.min = min(list_range.min, list[k]);
+ list_range.max = max(list_range.max, list[k]);
}
- i->empty = 1;
- return -EINVAL;
- _l2:
- if (snd_interval_checkempty(i)) {
- i->empty = 1;
- return -EINVAL;
- }
- return changed;
+ return snd_interval_refine(i, &list_range);
}
EXPORT_SYMBOL(snd_interval_list);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index c551006e2920..76d76c08339b 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -310,12 +310,16 @@ static int snd_ali_codec_ready(struct snd_ali *codec,
unsigned int res;
end_time = jiffies + msecs_to_jiffies(250);
- do {
+
+ for (;;) {
res = snd_ali_5451_peek(codec,port);
if (!(res & 0x8000))
return 0;
+ if (!time_after_eq(end_time, jiffies))
+ break;
schedule_timeout_uninterruptible(1);
- } while (time_after_eq(end_time, jiffies));
+ }
+
snd_ali_5451_poke(codec, port, res & ~0x8000);
snd_printdd("ali_codec_ready: codec is not ready.\n ");
return -EIO;
@@ -327,15 +331,17 @@ static int snd_ali_stimer_ready(struct snd_ali *codec)
unsigned long dwChk1,dwChk2;
dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);
- dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
-
end_time = jiffies + msecs_to_jiffies(250);
- do {
+
+ for (;;) {
dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
if (dwChk2 != dwChk1)
return 0;
+ if (!time_after_eq(end_time, jiffies))
+ break;
schedule_timeout_uninterruptible(1);
- } while (time_after_eq(end_time, jiffies));
+ }
+
snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n");
return -EIO;
}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 3da85caf8af1..403588c6e3f6 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3835,9 +3835,11 @@ static struct hda_verb ad1884a_laptop_verbs[] = {
/* Port-F (int speaker) mixer - route only from analog mixer */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* Port-F pin */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* Port-F (int speaker) pin */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* required for compaq 6530s/6531s speaker output */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
/* Port-C pin - internal mic-in */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index fea976793ae5..30eeb304351c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6423,9 +6423,9 @@ static struct hda_verb alc885_mbp_ch2_init[] = {
};
/*
- * 6ch mode
+ * 4ch mode
*/
-static struct hda_verb alc885_mbp_ch6_init[] = {
+static struct hda_verb alc885_mbp_ch4_init[] = {
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
@@ -6434,9 +6434,9 @@ static struct hda_verb alc885_mbp_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc885_mbp_6ch_modes[2] = {
+static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
{ 2, alc885_mbp_ch2_init },
- { 6, alc885_mbp_ch6_init },
+ { 4, alc885_mbp_ch4_init },
};
/*
@@ -6497,10 +6497,11 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
};
static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
@@ -6814,14 +6815,18 @@ static struct hda_verb alc885_mbp3_init_verbs[] = {
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* HP mixer */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Front Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: output 0 (0x0d) */
+ /* HP Pin: output 0 (0x0e) */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
/* Mic (rear) pin: input vref at 80% */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -7195,10 +7200,11 @@ static struct alc_config_preset alc882_presets[] = {
.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
.init_verbs = { alc885_mbp3_init_verbs,
alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .num_dacs = 2,
.dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mbp_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),
+ .hp_nid = 0x04,
+ .channel_mode = alc885_mbp_4ch_modes,
+ .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
.input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
@@ -12521,8 +12527,6 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
ALC268_TOSHIBA),
SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
- SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
- ALC268_TOSHIBA),
SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
@@ -12530,6 +12534,15 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
{}
};
+/* Toshiba laptops have no unique PCI SSID but only codec SSID */
+static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
+ SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
+ SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
+ ALC268_TOSHIBA),
+ {}
+};
+
static struct alc_config_preset alc268_presets[] = {
[ALC267_QUANTA_IL1] = {
.mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
@@ -12696,6 +12709,10 @@ static int patch_alc268(struct hda_codec *codec)
alc268_models,
alc268_cfg_tbl);
+ if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
+ board_config = snd_hda_check_board_codec_sid_config(codec,
+ ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
+
if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
printk(KERN_INFO "hda_codec: Unknown model for %s, "
"trying auto-probe from BIOS...\n", codec->chip_name);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 456ef6ac12e4..6990cfcb6a38 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -76,6 +76,7 @@ enum {
STAC_92HD73XX_AUTO,
STAC_92HD73XX_NO_JD, /* no jack-detection */
STAC_92HD73XX_REF,
+ STAC_92HD73XX_INTEL,
STAC_DELL_M6_AMIC,
STAC_DELL_M6_DMIC,
STAC_DELL_M6_BOTH,
@@ -1777,6 +1778,7 @@ static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_AUTO] = "auto",
[STAC_92HD73XX_NO_JD] = "no-jd",
[STAC_92HD73XX_REF] = "ref",
+ [STAC_92HD73XX_INTEL] = "intel",
[STAC_DELL_M6_AMIC] = "dell-m6-amic",
[STAC_DELL_M6_DMIC] = "dell-m6-dmic",
[STAC_DELL_M6_BOTH] = "dell-m6",
@@ -1789,6 +1791,10 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
"DFI LanParty", STAC_92HD73XX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
"DFI LanParty", STAC_92HD73XX_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002,
+ "Intel DG45ID", STAC_92HD73XX_INTEL),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003,
+ "Intel DG45FC", STAC_92HD73XX_INTEL),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
"Dell Studio 1535", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 9008b4b013aa..e8f10b10cceb 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1395,6 +1395,7 @@ static int patch_vt1708(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1708_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
spec->num_mixers++;
}
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 6416d3f0c7be..a69e774d0b13 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -885,10 +885,10 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
if (ucontrol->value.integer.value[0] < 0 ||
- ucontrol->value.integer.value[0] < MIC_LEVEL_MAX)
+ ucontrol->value.integer.value[0] > MIC_LEVEL_MAX)
return -EINVAL;
if (ucontrol->value.integer.value[1] < 0 ||
- ucontrol->value.integer.value[1] < MIC_LEVEL_MAX)
+ ucontrol->value.integer.value[1] > MIC_LEVEL_MAX)
return -EINVAL;
mutex_lock(&_chip->mixer_mutex);
if (chip->input_level[0] != ucontrol->value.integer.value[0] ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 343e7b14bf01..5e17de984dc8 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -31,6 +31,7 @@ static char *vmlinux = "vmlinux";
static char default_sort_order[] = "comm,symbol";
static char *sort_order = default_sort_order;
+static int force;
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -1334,6 +1335,11 @@ static int __cmd_annotate(void)
exit(-1);
}
+ if (!force && (stat.st_uid != geteuid())) {
+ fprintf(stderr, "file: %s not owned by current user\n", input_name);
+ exit(-1);
+ }
+
if (!stat.st_size) {
fprintf(stderr, "zero-sized file, nothing to do!\n");
exit(0);
@@ -1439,6 +1445,7 @@ static const struct option options[] = {
"input file name"),
OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
"symbol to annotate"),
+ OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b53a60fc12de..8b2ec882e6e0 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -38,6 +38,7 @@ static char *dso_list_str, *comm_list_str, *sym_list_str,
static struct strlist *dso_list, *comm_list, *sym_list;
static char *field_sep;
+static int force;
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -1856,6 +1857,11 @@ static int __cmd_report(void)
exit(-1);
}
+ if (!force && (stat.st_uid != geteuid())) {
+ fprintf(stderr, "file: %s not owned by current user\n", input_name);
+ exit(-1);
+ }
+
if (!stat.st_size) {
fprintf(stderr, "zero-sized file, nothing to do!\n");
exit(0);
@@ -2064,6 +2070,7 @@ static const struct option options[] = {
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
+ OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('m', "modules", &modules,
"load module symbols - WARNING: use only with -k and LIVE kernel"),
OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,