Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
powerpc: Don't export cvt_fd & _df when CONFIG_PPC_FPU is not set
powerpc/44x: icon: select SM502 and frame buffer console support
powerpc/85xx: Add P1021MDS board support
powerpc/85xx: Change MPC8572DS camp dtses for MSI sharing
powerpc/fsl_msi: add removal path and probe failing path
powerpc/fsl_msi: enable msi sharing through AMP OSes
powerpc/fsl_msi: enable msi allocation in all banks
powerpc/fsl_msi: fix the conflict of virt_msir's chip_data
powerpc/fsl_msi: Add multiple MSI bank support
powerpc/kexec: Add support for FSL-BookE
powerpc/fsl-booke: Move the entry setup code into a seperate file
powerpc/fsl-booke: fix the case where we are not in the first page
powerpc/85xx: Enable support for ports 3 and 4 on 8548 CDS
powerpc/fsl-booke: Add hibernation support for FSL BookE processors
powerpc/e500mc: Implement machine check handler.
powerpc/44x: Add basic ICON PPC440SPe board support
powerpc/44x: Fix UART clocks on 440SPe
powerpc/44x: Add reset-type to katmai.dts
powerpc/44x: Adding PCI-E support for PowerPC 460SX based SOC.
diff --git a/.gitignore b/.gitignore
index a2939fc..8faa6c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,7 @@
*.gz
*.bz2
*.lzma
+*.lzo
*.patch
*.gcno
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
new file mode 100644
index 0000000..bcd907b
--- /dev/null
+++ b/Documentation/.gitignore
@@ -0,0 +1,7 @@
+filesystems/dnotify_test
+laptops/dslm
+timers/hpet_example
+vm/hugepage-mmap
+vm/hugepage-shm
+vm/map_hugetlb
+
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
index 6f8c1ca..634c625 100644
--- a/Documentation/kbuild/kbuild.txt
+++ b/Documentation/kbuild/kbuild.txt
@@ -65,7 +65,7 @@
Specify an optional fixed part of the binutils filename.
CROSS_COMPILE can be a part of the filename or the full path.
-CROSS_COMPILE is also used for ccache is some setups.
+CROSS_COMPILE is also used for ccache in some setups.
CF
--------------------------------------------------
@@ -162,3 +162,7 @@
to be included in the databases, separated by blank space. E.g.:
$ make ALLSOURCE_ARCHS="x86 mips arm" tags
+
+To get all available archs you can also specify all. E.g.:
+
+ $ make ALLSOURCE_ARCHS=all tags
diff --git a/Documentation/mutex-design.txt b/Documentation/mutex-design.txt
index aa60d1f..c91ccc0 100644
--- a/Documentation/mutex-design.txt
+++ b/Documentation/mutex-design.txt
@@ -66,14 +66,14 @@
c0377ccb <mutex_lock>:
c0377ccb: f0 ff 08 lock decl (%eax)
- c0377cce: 78 0e js c0377cde <.text.lock.mutex>
+ c0377cce: 78 0e js c0377cde <.text..lock.mutex>
c0377cd0: c3 ret
the unlocking fastpath is equally tight:
c0377cd1 <mutex_unlock>:
c0377cd1: f0 ff 00 lock incl (%eax)
- c0377cd4: 7e 0f jle c0377ce5 <.text.lock.mutex+0x7>
+ c0377cd4: 7e 0f jle c0377ce5 <.text..lock.mutex+0x7>
c0377cd6: c3 ret
- 'struct mutex' semantics are well-defined and are enforced if
diff --git a/Documentation/timers/Makefile b/Documentation/timers/Makefile
index c85625f..73f75f8 100644
--- a/Documentation/timers/Makefile
+++ b/Documentation/timers/Makefile
@@ -2,7 +2,7 @@
obj- := dummy.o
# List of programs to build
-hostprogs-y := hpet_example
+hostprogs-$(CONFIG_X86) := hpet_example
# Tell kbuild to always build the programs
always := $(hostprogs-y)
diff --git a/MAINTAINERS b/MAINTAINERS
index 13608bd..2652ebc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3242,7 +3242,7 @@
S: Maintained
F: fs/autofs4/
-KERNEL BUILD
+KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
M: Michal Marek <mmarek@suse.cz>
T: git git://repo.or.cz/linux-kbuild.git for-next
T: git git://repo.or.cz/linux-kbuild.git for-linus
@@ -3251,6 +3251,9 @@
F: Documentation/kbuild/
F: Makefile
F: scripts/Makefile.*
+F: scripts/basic/
+F: scripts/mk*
+F: scripts/package/
KERNEL JANITORS
L: kernel-janitors@vger.kernel.org
diff --git a/Makefile b/Makefile
index 6e39ec7..efdc3d0 100644
--- a/Makefile
+++ b/Makefile
@@ -183,11 +183,14 @@
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
+# A third alternative is to store a setting in .config so that plain
+# "make" in the configured kernel build directory always uses that.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
+CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
@@ -576,9 +579,6 @@
# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
-# revert to pre-gcc-4.4 behaviour of .eh_frame
-KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
-
# conserve stack if available
KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)
@@ -882,9 +882,6 @@
PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
-ifdef CONFIG_MODULES
- $(Q)$(MAKE) $(modbuiltin)=$@
-endif
# Build the kernel release string
#
@@ -907,14 +904,19 @@
# $(localver)
# localversion* (files without backups, containing '~')
# $(CONFIG_LOCALVERSION) (from kernel config setting)
-# $(localver-auto) (only if CONFIG_LOCALVERSION_AUTO is set)
-# ./scripts/setlocalversion (SCM tag, if one exists)
-# $(LOCALVERSION) (from make command line if provided)
+# $(LOCALVERSION) (from make command line, if provided)
+# $(localver-extra)
+# $(scm-identifier) (unique SCM tag, if one exists)
+# ./scripts/setlocalversion (only with CONFIG_LOCALVERSION_AUTO)
+# .scmversion (only with CONFIG_LOCALVERSION_AUTO)
+# + (only without CONFIG_LOCALVERSION_AUTO
+# and without LOCALVERSION= and
+# repository is at non-tagged commit)
#
-# Note how the final $(localver-auto) string is included *only* if the
-# kernel config option CONFIG_LOCALVERSION_AUTO is selected. Also, at the
-# moment, only git is supported but other SCMs can edit the script
-# scripts/setlocalversion and add the appropriate checks as needed.
+# For kernels without CONFIG_LOCALVERSION_AUTO compiled from an SCM that has
+# been revised beyond a tagged commit, `+' is appended to the version string
+# when not overridden by using "make LOCALVERSION=". This indicates that the
+# kernel is not a vanilla release version and has been modified.
pattern = ".*/localversion[^~]*"
string = $(shell cat /dev/null \
@@ -923,26 +925,32 @@
localver = $(subst $(space),, $(string) \
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
-# and if the SCM is know a tag from the SCM is appended.
-# The appended tag is determined by the SCM used.
+# scripts/setlocalversion is called to create a unique identifier if the source
+# is managed by a known SCM and the repository has been revised since the last
+# tagged (release) commit. The format of the identifier is determined by the
+# SCM's implementation.
#
# .scmversion is used when generating rpm packages so we do not loose
# the version information from the SCM when we do the build of the kernel
# from the copied source
-ifdef CONFIG_LOCALVERSION_AUTO
-
ifeq ($(wildcard .scmversion),)
- _localver-auto = $(shell $(CONFIG_SHELL) \
+ scm-identifier = $(shell $(CONFIG_SHELL) \
$(srctree)/scripts/setlocalversion $(srctree))
else
- _localver-auto = $(shell cat .scmversion 2> /dev/null)
+ scm-identifier = $(shell cat .scmversion 2> /dev/null)
endif
- localver-auto = $(LOCALVERSION)$(_localver-auto)
+ifdef CONFIG_LOCALVERSION_AUTO
+ localver-extra = $(scm-identifier)
+else
+ ifneq ($(scm-identifier),)
+ ifeq ($(LOCALVERSION),)
+ localver-extra = +
+ endif
+ endif
endif
-localver-full = $(localver)$(localver-auto)
+localver-full = $(localver)$(LOCALVERSION)$(localver-extra)
# Store (new) KERNELRELASE string in include/config/kernel.release
kernelrelease = $(KERNELVERSION)$(localver-full)
@@ -1089,11 +1097,16 @@
PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
- $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.builtin) > $(objtree)/modules.builtin
@$(kecho) ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
+modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
+ $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin
+
+%/modules.builtin: include/config/auto.conf
+ $(Q)$(MAKE) $(modbuiltin)=$*
+
# Target to prepare building external modules
PHONY += modules_prepare
@@ -1104,7 +1117,7 @@
modules_install: _modinst_ _modinst_post
PHONY += _modinst_
-_modinst_:
+_modinst_: modules.builtin
@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
echo "Warning: you may need to install module-init-tools"; \
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
@@ -1247,7 +1260,9 @@
@echo ' firmware_install- Install all firmware to INSTALL_FW_PATH'
@echo ' (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
@echo ' dir/ - Build all files in dir and below'
- @echo ' dir/file.[ois] - Build specified target only'
+ @echo ' dir/file.[oisS] - Build specified target only'
+ @echo ' dir/file.lst - Build specified mixed source/assembly target only'
+ @echo ' (requires a recent binutils and recent build (System.map))'
@echo ' dir/file.ko - Build module including final link'
@echo ' modules_prepare - Set up for building external modules'
@echo ' tags/TAGS - Generate tags file for editors'
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 77630df..8842756 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
+#include <linux/smp_lock.h>
#include <linux/bcd.h>
#include <linux/capability.h>
@@ -238,9 +239,7 @@
/* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */
-static int
-rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static int rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long flags;
@@ -354,6 +353,17 @@
}
}
+static long rtc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ lock_kernel();
+ ret = rtc_ioctl(file, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
+
static void
print_rtc_status(void)
{
@@ -375,8 +385,8 @@
/* The various file operations we support. */
static const struct file_operations rtc_fops = {
- .owner = THIS_MODULE,
- .ioctl = rtc_ioctl,
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = rtc_unlocked_ioctl,
};
/* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 1e90c1a..7dcb1f8 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -27,6 +27,7 @@
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -53,7 +54,7 @@
static const unsigned char days_in_month[] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static long pcf8563_unlocked_ioctl(struct file *, unsigned int, unsigned long);
/* Cache VL bit value read at driver init since writing the RTC_SECOND
* register clears the VL status.
@@ -62,7 +63,7 @@
static const struct file_operations pcf8563_fops = {
.owner = THIS_MODULE,
- .ioctl = pcf8563_ioctl,
+ .unlocked_ioctl = pcf8563_unlocked_ioctl,
};
unsigned char
@@ -212,8 +213,7 @@
* ioctl calls for this driver. Why return -ENOTTY upon error? Because
* POSIX says so!
*/
-int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
/* Some sanity checks. */
if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -339,6 +339,17 @@
return 0;
}
+static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ lock_kernel();
+ return pcf8563_ioctl(filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
+
static int __init pcf8563_register(void)
{
if (pcf8563_init() < 0) {
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index 1a61efc..a0c0df8 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -17,8 +17,8 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
-#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
+#define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
+#define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
* global just so that the kernel gdb can use it.
@@ -116,12 +116,12 @@
static void enable_crisv10_irq(unsigned int irq)
{
- unmask_irq(irq);
+ crisv10_unmask_irq(irq);
}
static void disable_crisv10_irq(unsigned int irq)
{
- mask_irq(irq);
+ crisv10_mask_irq(irq);
}
static void ack_crisv10_irq(unsigned int irq)
diff --git a/arch/cris/arch-v10/lib/dmacopy.c b/arch/cris/arch-v10/lib/dmacopy.c
index e5fb44f..49f5b8c 100644
--- a/arch/cris/arch-v10/lib/dmacopy.c
+++ b/arch/cris/arch-v10/lib/dmacopy.c
@@ -1,5 +1,4 @@
-/* $Id: dmacopy.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $
- *
+/*
* memcpy for large blocks, using memory-memory DMA channels 6 and 7 in Etrax
*/
@@ -13,11 +12,11 @@
unsigned int pn)
{
static etrax_dma_descr indma, outdma;
-
- D(printk("dma_memcpy %d bytes... ", pn));
+
+ D(printk(KERN_DEBUG "dma_memcpy %d bytes... ", pn));
#if 0
- *R_GEN_CONFIG = genconfig_shadow =
+ *R_GEN_CONFIG = genconfig_shadow =
(genconfig_shadow & ~0x3c0000) |
IO_STATE(R_GEN_CONFIG, dma6, intdma7) |
IO_STATE(R_GEN_CONFIG, dma7, intdma6);
@@ -32,11 +31,11 @@
*R_DMA_CH7_FIRST = &outdma;
*R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, start);
*R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, start);
-
- while(*R_DMA_CH7_CMD == 1) /* wait for completion */ ;
- D(printk("done\n"));
+ while (*R_DMA_CH7_CMD == 1)
+ /* wait for completion */;
+ D(printk(KERN_DEBUG "done\n"));
}
diff --git a/arch/cris/arch-v10/lib/hw_settings.S b/arch/cris/arch-v10/lib/hw_settings.S
index 56905aa..c09f19f 100644
--- a/arch/cris/arch-v10/lib/hw_settings.S
+++ b/arch/cris/arch-v10/lib/hw_settings.S
@@ -1,13 +1,11 @@
/*
- * $Id: hw_settings.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
- *
* This table is used by some tools to extract hardware parameters.
* The table should be included in the kernel and the decompressor.
* Don't forget to update the tools if you change this table.
*
* Copyright (C) 2001 Axis Communications AB
*
- * Authors: Mikael Starvik (starvik@axis.com)
+ * Authors: Mikael Starvik (starvik@axis.com)
*/
#define PA_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PA_DIR << 8) | \
@@ -15,13 +13,13 @@
#define PB_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG << 16) | \
(CONFIG_ETRAX_DEF_R_PORT_PB_DIR << 8) | \
(CONFIG_ETRAX_DEF_R_PORT_PB_DATA))
-
+
.ascii "HW_PARAM_MAGIC" ; Magic number
.dword 0xc0004000 ; Kernel start address
; Debug port
#ifdef CONFIG_ETRAX_DEBUG_PORT0
- .dword 0
+ .dword 0
#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
.dword 1
#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
@@ -30,7 +28,7 @@
.dword 3
#else
.dword 4 ; No debug
-#endif
+#endif
; SDRAM or EDO DRAM?
#ifdef CONFIG_ETRAX_SDRAM
@@ -39,7 +37,7 @@
.dword 0
#endif
- ; Register values
+ ; Register values
.dword R_WAITSTATES
.dword CONFIG_ETRAX_DEF_R_WAITSTATES
.dword R_BUS_CONFIG
@@ -56,7 +54,7 @@
.dword CONFIG_ETRAX_DEF_R_DRAM_TIMING
#endif
.dword R_PORT_PA_SET
- .dword PA_SET_VALUE
+ .dword PA_SET_VALUE
.dword R_PORT_PB_SET
.dword PB_SET_VALUE
.dword 0 ; No more register values
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index b9e328e..a2dd740 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -360,24 +360,10 @@
string "Ser 4 DSR bit (empty = not used)"
depends on ETRAX_SERIAL_PORT4
-config ETRAX_SER3_CD_BIT
+config ETRAX_SER4_CD_BIT
string "Ser 4 CD bit (empty = not used)"
depends on ETRAX_SERIAL_PORT4
-config ETRAX_RS485
- bool "RS-485 support"
- depends on ETRAXFS_SERIAL
- help
- Enables support for RS-485 serial communication. For a primer on
- RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>.
-
-config ETRAX_RS485_DISABLE_RECEIVER
- bool "Disable serial receiver"
- depends on ETRAX_RS485
- help
- It is necessary to disable the serial receiver to avoid serial
- loopback. Not all products are able to do this in software only.
-
config ETRAX_SYNCHRONOUS_SERIAL
bool "Synchronous serial-port support"
depends on ETRAX_ARCH_V32
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5068263..2fd6a74 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -649,10 +649,10 @@
/* Main device API. ioctl's to write or read to/from i2c registers.
*/
-static int
-i2c_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long
+i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
+ int ret;
if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) {
return -ENOTTY;
}
@@ -665,9 +665,13 @@
I2C_ARGREG(arg),
I2C_ARGVALUE(arg)));
- return i2c_writereg(I2C_ARGSLAVE(arg),
+ lock_kernel();
+ ret = i2c_writereg(I2C_ARGSLAVE(arg),
I2C_ARGREG(arg),
I2C_ARGVALUE(arg));
+ unlock_kernel();
+ return ret;
+
case I2C_READREG:
{
unsigned char val;
@@ -675,7 +679,9 @@
D(printk("i2cr %d %d ",
I2C_ARGSLAVE(arg),
I2C_ARGREG(arg)));
+ lock_kernel();
val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg));
+ unlock_kernel();
D(printk("= %d\n", val));
return val;
}
@@ -688,10 +694,10 @@
}
static const struct file_operations i2c_fops = {
- .owner = THIS_MODULE,
- .ioctl = i2c_ioctl,
- .open = i2c_open,
- .release = i2c_release,
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = i2c_ioctl,
+ .open = i2c_open,
+ .release = i2c_release,
};
static int __init i2c_init(void)
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index f447850..bef6eb5 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
+#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
@@ -49,7 +50,7 @@
static const unsigned char days_in_month[] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
/* Cache VL bit value read at driver init since writing the RTC_SECOND
* register clears the VL status.
@@ -57,8 +58,8 @@
static int voltage_low;
static const struct file_operations pcf8563_fops = {
- .owner = THIS_MODULE,
- .ioctl = pcf8563_ioctl
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pcf8563_unlocked_ioctl,
};
unsigned char
@@ -208,8 +209,7 @@
* ioctl calls for this driver. Why return -ENOTTY upon error? Because
* POSIX says so!
*/
-int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
/* Some sanity checks. */
if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -335,6 +335,17 @@
return 0;
}
+static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ lock_kernel();
+ return pcf8563_ioctl(filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
+
static int __init pcf8563_register(void)
{
if (pcf8563_init() < 0) {
diff --git a/arch/cris/arch-v32/kernel/crisksyms.c b/arch/cris/arch-v32/kernel/crisksyms.c
index 64933e2..bde8d1a 100644
--- a/arch/cris/arch-v32/kernel/crisksyms.c
+++ b/arch/cris/arch-v32/kernel/crisksyms.c
@@ -24,5 +24,5 @@
EXPORT_SYMBOL(crisv32_io_get);
/* Functions masking/unmasking interrupts */
-EXPORT_SYMBOL(mask_irq);
-EXPORT_SYMBOL(unmask_irq);
+EXPORT_SYMBOL(crisv32_mask_irq);
+EXPORT_SYMBOL(crisv32_unmask_irq);
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index b624119..0b1febe 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -280,8 +280,7 @@
return cpu;
}
-void
-mask_irq(int irq)
+void crisv32_mask_irq(int irq)
{
int cpu;
@@ -289,8 +288,7 @@
block_irq(irq, cpu);
}
-void
-unmask_irq(int irq)
+void crisv32_unmask_irq(int irq)
{
unblock_irq(irq, irq_cpu(irq));
}
@@ -298,23 +296,23 @@
static unsigned int startup_crisv32_irq(unsigned int irq)
{
- unmask_irq(irq);
+ crisv32_unmask_irq(irq);
return 0;
}
static void shutdown_crisv32_irq(unsigned int irq)
{
- mask_irq(irq);
+ crisv32_mask_irq(irq);
}
static void enable_crisv32_irq(unsigned int irq)
{
- unmask_irq(irq);
+ crisv32_unmask_irq(irq);
}
static void disable_crisv32_irq(unsigned int irq)
{
- mask_irq(irq);
+ crisv32_mask_irq(irq);
}
static void ack_crisv32_irq(unsigned int irq)
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 058addd..84fed3b 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -168,8 +168,8 @@
/* Enable IRQ and idle */
REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask);
- unmask_irq(IPI_INTR_VECT);
- unmask_irq(TIMER0_INTR_VECT);
+ crisv32_unmask_irq(IPI_INTR_VECT);
+ crisv32_unmask_irq(TIMER0_INTR_VECT);
preempt_disable();
notify_cpu_starting(cpu);
local_irq_enable();
diff --git a/arch/cris/include/arch-v10/arch/irq.h b/arch/cris/include/arch-v10/arch/irq.h
index 6248004..7d34594 100644
--- a/arch/cris/include/arch-v10/arch/irq.h
+++ b/arch/cris/include/arch-v10/arch/irq.h
@@ -93,15 +93,16 @@
"push $r10\n\t" /* push orig_r10 */ \
"clear.d [$sp=$sp-4]\n\t" /* frametype - this is a normal stackframe */
- /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq */
+/* BLOCK_IRQ and UNBLOCK_IRQ do the same as
+ * crisv10_mask_irq and crisv10_unmask_irq */
#define BLOCK_IRQ(mask,nr) \
"move.d " #mask ",$r0\n\t" \
- "move.d $r0,[0xb00000d8]\n\t"
-
+ "move.d $r0,[0xb00000d8]\n\t"
+
#define UNBLOCK_IRQ(mask) \
"move.d " #mask ",$r0\n\t" \
- "move.d $r0,[0xb00000dc]\n\t"
+ "move.d $r0,[0xb00000dc]\n\t"
#define IRQ_NAME2(nr) nr##_interrupt(void)
#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
diff --git a/arch/cris/include/arch-v32/arch/irq.h b/arch/cris/include/arch-v32/arch/irq.h
index 9e4c9fb..b31e998 100644
--- a/arch/cris/include/arch-v32/arch/irq.h
+++ b/arch/cris/include/arch-v32/arch/irq.h
@@ -23,8 +23,8 @@
extern struct etrax_interrupt_vector *etrax_irv; /* head.S */
-void mask_irq(int irq);
-void unmask_irq(int irq);
+void crisv32_mask_irq(int irq);
+void crisv32_unmask_irq(int irq);
void set_exception_vector(int n, irqvectptr addr);
diff --git a/arch/cris/include/asm/param.h b/arch/cris/include/asm/param.h
index 0e47994..484fcf8 100644
--- a/arch/cris/include/asm/param.h
+++ b/arch/cris/include/asm/param.h
@@ -2,22 +2,9 @@
#define _ASMCRIS_PARAM_H
/* Currently we assume that HZ=100 is good for CRIS. */
-#ifdef __KERNEL__
-# define HZ CONFIG_HZ /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
#define EXEC_PAGESIZE 8192
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
+#include <asm-generic/param.h>
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#endif
+#endif /* _ASMCRIS_PARAM_H */
diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S
index bd0bdf9..cbb6958 100644
--- a/arch/frv/kernel/break.S
+++ b/arch/frv/kernel/break.S
@@ -21,7 +21,7 @@
#
# the break handler has its own stack
#
- .section .bss.stack
+ .section .bss..stack
.globl __break_user_context
.balign THREAD_SIZE
__break_stack:
@@ -63,7 +63,7 @@
# entry point for Break Exceptions/Interrupts
#
###############################################################################
- .section .text.break
+ .section .text..break
.balign 4
.globl __entry_break
__entry_break:
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 189397e..63d579b 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -38,7 +38,7 @@
#define nr_syscalls ((syscall_table_size)/4)
- .section .text.entry
+ .section .text..entry
.balign 4
.macro LEDS val
diff --git a/arch/frv/kernel/head.S b/arch/frv/kernel/head.S
index b825ef3..e9a8cc6 100644
--- a/arch/frv/kernel/head.S
+++ b/arch/frv/kernel/head.S
@@ -542,7 +542,7 @@
.size _boot, .-_boot
# provide a point for GDB to place a break
- .section .text.start,"ax"
+ .section .text..start,"ax"
.globl _start
.balign 4
_start:
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index cbe811f..8b973f3 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -57,10 +57,10 @@
_text = .;
_stext = .;
.text : {
- *(.text.start)
- *(.text.entry)
- *(.text.break)
- *(.text.tlbmiss)
+ *(.text..start)
+ *(.text..entry)
+ *(.text..break)
+ *(.text..tlbmiss)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
@@ -114,7 +114,7 @@
.sbss : { *(.sbss .sbss.*) }
.bss : { *(.bss .bss.*) }
- .bss.stack : { *(.bss) }
+ .bss..stack : { *(.bss) }
__bss_stop = .;
_end = . ;
diff --git a/arch/frv/mm/tlb-miss.S b/arch/frv/mm/tlb-miss.S
index 7f392bc..f3ac019 100644
--- a/arch/frv/mm/tlb-miss.S
+++ b/arch/frv/mm/tlb-miss.S
@@ -15,7 +15,7 @@
#include <asm/pgtable.h>
#include <asm/spr-regs.h>
- .section .text.tlbmiss
+ .section .text..tlbmiss
.balign 4
.globl __entry_insn_mmu_miss
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
index 985a81a..10e9a2d 100644
--- a/arch/h8300/boot/compressed/head.S
+++ b/arch/h8300/boot/compressed/head.S
@@ -9,7 +9,7 @@
#define SRAM_START 0xff4000
- .section .text.startup
+ .section .text..startup
.global startup
startup:
mov.l #SRAM_START+0x8000, sp
diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
index 65e2a0d..a0a3a0e 100644
--- a/arch/h8300/boot/compressed/vmlinux.lds
+++ b/arch/h8300/boot/compressed/vmlinux.lds
@@ -4,7 +4,7 @@
{
__stext = . ;
__text = .;
- *(.text.startup)
+ *(.text..startup)
*(.text)
__etext = . ;
}
diff --git a/arch/ia64/include/asm/asmmacro.h b/arch/ia64/include/asm/asmmacro.h
index c1642fd..3ab6d75 100644
--- a/arch/ia64/include/asm/asmmacro.h
+++ b/arch/ia64/include/asm/asmmacro.h
@@ -70,12 +70,12 @@
* path (ivt.S - TLB miss processing) or in places where it might not be
* safe to use a "tpa" instruction (mca_asm.S - error recovery).
*/
- .section ".data.patch.vtop", "a" // declare section & section attributes
+ .section ".data..patch.vtop", "a" // declare section & section attributes
.previous
#define LOAD_PHYSICAL(pr, reg, obj) \
[1:](pr)movl reg = obj; \
- .xdata4 ".data.patch.vtop", 1b-.
+ .xdata4 ".data..patch.vtop", 1b-.
/*
* For now, we always put in the McKinley E9 workaround. On CPUs that don't need it,
@@ -84,11 +84,11 @@
#define DO_MCKINLEY_E9_WORKAROUND
#ifdef DO_MCKINLEY_E9_WORKAROUND
- .section ".data.patch.mckinley_e9", "a"
+ .section ".data..patch.mckinley_e9", "a"
.previous
/* workaround for Itanium 2 Errata 9: */
# define FSYS_RETURN \
- .xdata4 ".data.patch.mckinley_e9", 1f-.; \
+ .xdata4 ".data..patch.mckinley_e9", 1f-.; \
1:{ .mib; \
nop.m 0; \
mov r16=ar.pfs; \
@@ -107,11 +107,11 @@
* If physical stack register size is different from DEF_NUM_STACK_REG,
* dynamically patch the kernel for correct size.
*/
- .section ".data.patch.phys_stack_reg", "a"
+ .section ".data..patch.phys_stack_reg", "a"
.previous
#define LOAD_PHYS_STACK_REG_SIZE(reg) \
[1:] adds reg=IA64_NUM_PHYS_STACK_REG*8+8,r0; \
- .xdata4 ".data.patch.phys_stack_reg", 1b-.
+ .xdata4 ".data..patch.phys_stack_reg", 1b-.
/*
* Up until early 2004, use of .align within a function caused bad unwind info.
diff --git a/arch/ia64/include/asm/cache.h b/arch/ia64/include/asm/cache.h
index e7482bd..988254a 100644
--- a/arch/ia64/include/asm/cache.h
+++ b/arch/ia64/include/asm/cache.h
@@ -24,6 +24,6 @@
# define SMP_CACHE_BYTES (1 << 3)
#endif
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#endif /* _ASM_IA64_CACHE_H */
diff --git a/arch/ia64/include/asm/percpu.h b/arch/ia64/include/asm/percpu.h
index 1bd4082..14aa1c5 100644
--- a/arch/ia64/include/asm/percpu.h
+++ b/arch/ia64/include/asm/percpu.h
@@ -31,7 +31,7 @@
#endif /* SMP */
-#define PER_CPU_BASE_SECTION ".data.percpu"
+#define PER_CPU_BASE_SECTION ".data..percpu"
/*
* Be extremely careful when taking the address of this variable! Due to virtual
diff --git a/arch/ia64/kernel/Makefile.gate b/arch/ia64/kernel/Makefile.gate
index ab9b03a..ceeffc5 100644
--- a/arch/ia64/kernel/Makefile.gate
+++ b/arch/ia64/kernel/Makefile.gate
@@ -21,7 +21,7 @@
$(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
$(call if_changed,gate)
-# gate-data.o contains the gate DSO image as data in section .data.gate.
+# gate-data.o contains the gate DSO image as data in section .data..gate.
# We must build gate.so before we can assemble it.
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/gate-data.o: $(obj)/gate.so
diff --git a/arch/ia64/kernel/gate-data.S b/arch/ia64/kernel/gate-data.S
index 258c0a3..b3ef1c7 100644
--- a/arch/ia64/kernel/gate-data.S
+++ b/arch/ia64/kernel/gate-data.S
@@ -1,3 +1,3 @@
- .section .data.gate, "aw"
+ .section .data..gate, "aw"
.incbin "arch/ia64/kernel/gate.so"
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
index cf5e0a1..245d3e1 100644
--- a/arch/ia64/kernel/gate.S
+++ b/arch/ia64/kernel/gate.S
@@ -21,18 +21,18 @@
* to targets outside the shared object) and to avoid multi-phase kernel builds, we
* simply create minimalistic "patch lists" in special ELF sections.
*/
- .section ".data.patch.fsyscall_table", "a"
+ .section ".data..patch.fsyscall_table", "a"
.previous
#define LOAD_FSYSCALL_TABLE(reg) \
[1:] movl reg=0; \
- .xdata4 ".data.patch.fsyscall_table", 1b-.
+ .xdata4 ".data..patch.fsyscall_table", 1b-.
- .section ".data.patch.brl_fsys_bubble_down", "a"
+ .section ".data..patch.brl_fsys_bubble_down", "a"
.previous
#define BRL_COND_FSYS_BUBBLE_DOWN(pr) \
[1:](pr)brl.cond.sptk 0; \
;; \
- .xdata4 ".data.patch.brl_fsys_bubble_down", 1b-.
+ .xdata4 ".data..patch.brl_fsys_bubble_down", 1b-.
GLOBAL_ENTRY(__kernel_syscall_via_break)
.prologue
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index 88c64ed..d32b085 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -33,21 +33,21 @@
*/
. = GATE_ADDR + 0x600;
- .data.patch : {
+ .data..patch : {
__paravirt_start_gate_mckinley_e9_patchlist = .;
- *(.data.patch.mckinley_e9)
+ *(.data..patch.mckinley_e9)
__paravirt_end_gate_mckinley_e9_patchlist = .;
__paravirt_start_gate_vtop_patchlist = .;
- *(.data.patch.vtop)
+ *(.data..patch.vtop)
__paravirt_end_gate_vtop_patchlist = .;
__paravirt_start_gate_fsyscall_patchlist = .;
- *(.data.patch.fsyscall_table)
+ *(.data..patch.fsyscall_table)
__paravirt_end_gate_fsyscall_patchlist = .;
__paravirt_start_gate_brl_fsys_bubble_down_patchlist = .;
- *(.data.patch.brl_fsys_bubble_down)
+ *(.data..patch.brl_fsys_bubble_down)
__paravirt_end_gate_brl_fsys_bubble_down_patchlist = .;
} :readable
diff --git a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
index e253ab8..f9efe97 100644
--- a/arch/ia64/kernel/init_task.c
+++ b/arch/ia64/kernel/init_task.c
@@ -23,7 +23,7 @@
* Initial task structure.
*
* We need to make sure that this is properly aligned due to the way process stacks are
- * handled. This is done by having a special ".data.init_task" section...
+ * handled. This is done by having a special ".data..init_task" section...
*/
#define init_thread_info init_task_mem.s.thread_info
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 179fd12..d93e396 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -82,7 +82,7 @@
mov r19=n;; /* prepare to save predicates */ \
br.sptk.many dispatch_to_fault_handler
- .section .text.ivt,"ax"
+ .section .text..ivt,"ax"
.align 32768 // align on 32KB boundary
.global ia64_ivt
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index 292e214..d56753a1 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -16,7 +16,7 @@
#define ACCOUNT_SYS_ENTER
#endif
-.section ".data.patch.rse", "a"
+.section ".data..patch.rse", "a"
.previous
/*
@@ -215,7 +215,7 @@
(pUStk) extr.u r17=r18,3,6; \
(pUStk) sub r16=r18,r22; \
[1:](pKStk) br.cond.sptk.many 1f; \
- .xdata4 ".data.patch.rse",1b-. \
+ .xdata4 ".data..patch.rse",1b-. \
;; \
cmp.ge p6,p7 = 33,r17; \
;; \
diff --git a/arch/ia64/kernel/paravirtentry.S b/arch/ia64/kernel/paravirtentry.S
index 6158560..92d880c 100644
--- a/arch/ia64/kernel/paravirtentry.S
+++ b/arch/ia64/kernel/paravirtentry.S
@@ -28,7 +28,7 @@
#include "entry.h"
#define DATA8(sym, init_value) \
- .pushsection .data.read_mostly ; \
+ .pushsection .data..read_mostly ; \
.align 8 ; \
.global sym ; \
sym: ; \
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 1295ba3..e07218a 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -8,7 +8,7 @@
#define IVT_TEXT \
VMLINUX_SYMBOL(__start_ivt_text) = .; \
- *(.text.ivt) \
+ *(.text..ivt) \
VMLINUX_SYMBOL(__end_ivt_text) = .;
OUTPUT_FORMAT("elf64-ia64-little")
@@ -54,8 +54,8 @@
.text2 : AT(ADDR(.text2) - LOAD_OFFSET)
{ *(.text2) }
#ifdef CONFIG_SMP
- .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET)
- { *(.text.lock) }
+ .text..lock : AT(ADDR(.text..lock) - LOAD_OFFSET)
+ { *(.text..lock) }
#endif
_etext = .;
@@ -75,10 +75,10 @@
__stop___mca_table = .;
}
- .data.patch.phys_stack_reg : AT(ADDR(.data.patch.phys_stack_reg) - LOAD_OFFSET)
+ .data..patch.phys_stack_reg : AT(ADDR(.data..patch.phys_stack_reg) - LOAD_OFFSET)
{
__start___phys_stack_reg_patchlist = .;
- *(.data.patch.phys_stack_reg)
+ *(.data..patch.phys_stack_reg)
__end___phys_stack_reg_patchlist = .;
}
@@ -110,24 +110,24 @@
INIT_TEXT_SECTION(PAGE_SIZE)
INIT_DATA_SECTION(16)
- .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET)
+ .data..patch.vtop : AT(ADDR(.data..patch.vtop) - LOAD_OFFSET)
{
__start___vtop_patchlist = .;
- *(.data.patch.vtop)
+ *(.data..patch.vtop)
__end___vtop_patchlist = .;
}
- .data.patch.rse : AT(ADDR(.data.patch.rse) - LOAD_OFFSET)
+ .data..patch.rse : AT(ADDR(.data..patch.rse) - LOAD_OFFSET)
{
__start___rse_patchlist = .;
- *(.data.patch.rse)
+ *(.data..patch.rse)
__end___rse_patchlist = .;
}
- .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET)
+ .data..patch.mckinley_e9 : AT(ADDR(.data..patch.mckinley_e9) - LOAD_OFFSET)
{
__start___mckinley_e9_bundles = .;
- *(.data.patch.mckinley_e9)
+ *(.data..patch.mckinley_e9)
__end___mckinley_e9_bundles = .;
}
@@ -175,17 +175,17 @@
. = ALIGN(PAGE_SIZE);
__init_end = .;
- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET)
+ .data..page_aligned : AT(ADDR(.data..page_aligned) - LOAD_OFFSET)
{
PAGE_ALIGNED_DATA(PAGE_SIZE)
. = ALIGN(PAGE_SIZE);
__start_gate_section = .;
- *(.data.gate)
+ *(.data..gate)
__stop_gate_section = .;
#ifdef CONFIG_XEN
. = ALIGN(PAGE_SIZE);
__xen_start_gate_section = .;
- *(.data.gate.xen)
+ *(.data..gate.xen)
__xen_stop_gate_section = .;
#endif
}
diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
index 40920c6..2401848 100644
--- a/arch/ia64/kvm/vmm_ivt.S
+++ b/arch/ia64/kvm/vmm_ivt.S
@@ -104,7 +104,7 @@
br.call.sptk.many b6=vmm_panic_handler;
END(kvm_vmm_panic)
- .section .text.ivt,"ax"
+ .section .text..ivt,"ax"
.align 32768 // align on 32KB boundary
.global kvm_ia64_ivt
diff --git a/arch/ia64/scripts/unwcheck.py b/arch/ia64/scripts/unwcheck.py
index c278498..2bfd941 100644
--- a/arch/ia64/scripts/unwcheck.py
+++ b/arch/ia64/scripts/unwcheck.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
#
# Usage: unwcheck.py FILE
#
diff --git a/arch/ia64/xen/gate-data.S b/arch/ia64/xen/gate-data.S
index 7d4830a..6f95b6b 100644
--- a/arch/ia64/xen/gate-data.S
+++ b/arch/ia64/xen/gate-data.S
@@ -1,3 +1,3 @@
- .section .data.gate.xen, "aw"
+ .section .data..gate.xen, "aw"
.incbin "arch/ia64/xen/gate.so"
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S
index aff8346..b820ed0 100644
--- a/arch/ia64/xen/xensetup.S
+++ b/arch/ia64/xen/xensetup.S
@@ -14,7 +14,7 @@
#include <linux/init.h>
#include <xen/interface/elfnote.h>
- .section .data.read_mostly
+ .section .data..read_mostly
.align 8
.global xen_domain_type
xen_domain_type:
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 9f1784f..a91b271 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -57,7 +57,7 @@
.romvec : {
__rom_start = . ;
_romvec = .;
- *(.data.initvect)
+ *(.data..initvect)
} > romvec
#endif
@@ -68,7 +68,7 @@
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
- *(.text.lock)
+ *(.text..lock)
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
index 2ef0624..8eb94fb 100644
--- a/arch/m68knommu/platform/68360/head-ram.S
+++ b/arch/m68knommu/platform/68360/head-ram.S
@@ -280,7 +280,7 @@
* and then overwritten as needed.
*/
-.section ".data.initvect","awx"
+.section ".data..initvect","awx"
.long RAMEND /* Reset: Initial Stack Pointer - 0. */
.long _start /* Reset: Initial Program Counter - 1. */
.long buserr /* Bus Error - 2. */
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68knommu/platform/68360/head-rom.S
index 62ecf41..97510e5 100644
--- a/arch/m68knommu/platform/68360/head-rom.S
+++ b/arch/m68knommu/platform/68360/head-rom.S
@@ -291,7 +291,7 @@
* and then overwritten as needed.
*/
-.section ".data.initvect","awx"
+.section ".data..initvect","awx"
.long RAMEND /* Reset: Initial Stack Pointer - 0. */
.long _start /* Reset: Initial Program Counter - 1. */
.long buserr /* Bus Error - 2. */
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
index efb95f2..e0ecda9 100644
--- a/arch/mips/lasat/image/head.S
+++ b/arch/mips/lasat/image/head.S
@@ -1,7 +1,7 @@
#include <asm/lasat/head.h>
.text
- .section .text.start, "ax"
+ .section .text..start, "ax"
.set noreorder
.set mips3
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
index 988f8ad..0864c96 100644
--- a/arch/mips/lasat/image/romscript.normal
+++ b/arch/mips/lasat/image/romscript.normal
@@ -4,7 +4,7 @@
{
.text :
{
- *(.text.start)
+ *(.text..start)
}
/* Data in ROM */
diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h
index 32c2cca..45effe6 100644
--- a/arch/parisc/include/asm/cache.h
+++ b/arch/parisc/include/asm/cache.h
@@ -28,7 +28,7 @@
#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
void parisc_cache_init(void); /* initializes cache-flushing */
void disable_sr_hashing_asm(int); /* low level support for above */
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
index 4653c77..2ab4af5 100644
--- a/arch/parisc/include/asm/system.h
+++ b/arch/parisc/include/asm/system.h
@@ -174,7 +174,7 @@
})
#ifdef CONFIG_SMP
-# define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
+# define __lock_aligned __attribute__((__section__(".data..lock_aligned")))
#endif
#define arch_align_stack(x) (x)
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 0e3d9f9..4dbdf0e 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -345,7 +345,7 @@
ENDPROC(stext)
#ifndef CONFIG_64BIT
- .section .data.read_mostly
+ .section .data..read_mostly
.align 4
.export $global$,data
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index d020eae..4a91e4334 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -53,11 +53,11 @@
* guarantee that global objects will be laid out in memory in the same order
* as the order of declaration, so put these in different sections and use
* the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data.vm0.pmd"), aligned(PAGE_SIZE)));
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data..vm0.pmd"), aligned(PAGE_SIZE)));
#endif
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data.vm0.pgd"), aligned(PAGE_SIZE)));
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data.vm0.pte"), aligned(PAGE_SIZE)));
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE)));
/*
* Initial task structure.
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 9dab4a4..d64a6bb 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -94,8 +94,8 @@
/* PA-RISC locks requires 16-byte alignment */
. = ALIGN(16);
- .data.lock_aligned : {
- *(.data.lock_aligned)
+ .data..lock_aligned : {
+ *(.data..lock_aligned)
}
/* End of data section */
@@ -105,10 +105,10 @@
__bss_start = .;
/* page table entries need to be PAGE_SIZE aligned */
. = ALIGN(PAGE_SIZE);
- .data.vmpages : {
- *(.data.vm0.pmd)
- *(.data.vm0.pgd)
- *(.data.vm0.pte)
+ .data..vmpages : {
+ *(.data..vm0.pmd)
+ *(.data..vm0.pgd)
+ *(.data..vm0.pte)
}
.bss : {
*(.bss)
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 1a54a3b..42dcd3f4 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -112,6 +112,11 @@
# kernel considerably.
KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
+# FIXME: the module load should be taught about the additional relocs
+# generated by this.
+# revert to pre-gcc-4.4 behaviour of .eh_frame
+KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
+
# Never use string load/store instructions as they are
# often slow when they are implemented at all
KBUILD_CFLAGS += -mno-string
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index 725634f..4b50941 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -42,7 +42,7 @@
#endif /* __powerpc64__ && ! __ASSEMBLY__ */
#if !defined(__ASSEMBLY__)
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#endif
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index bfc4e02..358ff14 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -162,14 +162,6 @@
#endif /* !CONFIG_HUGETLB_PAGE */
-#ifdef MODULE
-#define __page_aligned __attribute__((__aligned__(PAGE_SIZE)))
-#else
-#define __page_aligned \
- __attribute__((__aligned__(PAGE_SIZE), \
- __section__(".data.page_aligned")))
-#endif
-
#define VM_DATA_DEFAULT_FLAGS \
(test_thread_flag(TIF_32BIT) ? \
VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64)
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index dcd01c8..8a0deef 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -223,19 +223,17 @@
#endif
/* The initial task and kernel stack */
- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
- INIT_TASK_DATA(THREAD_SIZE)
- }
+ INIT_TASK_DATA_SECTION(THREAD_SIZE)
- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ .data..page_aligned : AT(ADDR(.data..page_aligned) - LOAD_OFFSET) {
PAGE_ALIGNED_DATA(PAGE_SIZE)
}
- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+ .data..cacheline_aligned : AT(ADDR(.data..cacheline_aligned) - LOAD_OFFSET) {
CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
}
- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+ .data..read_mostly : AT(ADDR(.data..read_mostly) - LOAD_OFFSET) {
READ_MOSTLY_DATA(L1_CACHE_BYTES)
}
diff --git a/arch/s390/include/asm/cache.h b/arch/s390/include/asm/cache.h
index 9b86681..24aafa6 100644
--- a/arch/s390/include/asm/cache.h
+++ b/arch/s390/include/asm/cache.h
@@ -14,6 +14,6 @@
#define L1_CACHE_BYTES 256
#define L1_CACHE_SHIFT 8
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#endif
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index c56d3f5..1f066e4 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -264,7 +264,7 @@
lghi %r2,0
br %r14
- .section .data.nosave,"aw",@progbits
+ .section .data..nosave,"aw",@progbits
.align 8
.Ldisabled_wait_31:
.long 0x000a0000,0x00000000
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
index f02382a..862d748 100644
--- a/arch/sh/boot/compressed/vmlinux.scr
+++ b/arch/sh/boot/compressed/vmlinux.scr
@@ -1,6 +1,6 @@
SECTIONS
{
- .rodata.compressed : {
+ .rodata..compressed : {
input_len = .;
LONG(input_data_end - input_data) input_data = .;
*(.data)
diff --git a/arch/sh/include/asm/cache.h b/arch/sh/include/asm/cache.h
index e461d67..ef9e555 100644
--- a/arch/sh/include/asm/cache.h
+++ b/arch/sh/include/asm/cache.h
@@ -14,7 +14,7 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#ifndef __ASSEMBLY__
struct cache_info {
diff --git a/arch/sparc/boot/btfixupprep.c b/arch/sparc/boot/btfixupprep.c
index bbf91b9..e7f2940 100644
--- a/arch/sparc/boot/btfixupprep.c
+++ b/arch/sparc/boot/btfixupprep.c
@@ -325,7 +325,7 @@
(*rr)->next = NULL;
}
printf("! Generated by btfixupprep. Do not edit.\n\n");
- printf("\t.section\t\".data.init\",#alloc,#write\n\t.align\t4\n\n");
+ printf("\t.section\t\".data..init\",#alloc,#write\n\t.align\t4\n\n");
printf("\t.global\t___btfixup_start\n___btfixup_start:\n\n");
for (i = 0; i < last; i++) {
f = array + i;
diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h
index 78b0700..0588b8c 100644
--- a/arch/sparc/include/asm/cache.h
+++ b/arch/sparc/include/asm/cache.h
@@ -21,7 +21,7 @@
#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT)
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#ifdef CONFIG_SPARC32
#include <asm/asi.h>
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 7fcad58..6926801 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -94,7 +94,7 @@
.data : {
INIT_TASK_DATA(KERNEL_STACK_SIZE)
. = ALIGN(KERNEL_STACK_SIZE);
- *(.data.init_irqstack)
+ *(.data..init_irqstack)
DATA_DATA
*(.data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index 8aa77b6..ddc9698 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -34,5 +34,5 @@
{ INIT_THREAD_INFO(init_task) };
union thread_union cpu0_irqstack
- __attribute__((__section__(".data.init_irqstack"))) =
+ __attribute__((__section__(".data..init_irqstack"))) =
{ INIT_THREAD_INFO(init_task) };
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index e7a6cca..ec63785 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -50,7 +50,7 @@
{
INIT_TASK_DATA(KERNEL_STACK_SIZE)
. = ALIGN(KERNEL_STACK_SIZE);
- *(.data.init_irqstack)
+ *(.data..init_irqstack)
DATA_DATA
*(.gnu.linkonce.d*)
CONSTRUCTORS
diff --git a/arch/x86/.gitignore b/arch/x86/.gitignore
new file mode 100644
index 0000000..0280790
--- /dev/null
+++ b/arch/x86/.gitignore
@@ -0,0 +1,3 @@
+boot/compressed/vmlinux
+tools/test_get_len
+
diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c
index bcbd36c..5c22812 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -77,7 +77,7 @@
offs += 32*1024 + 18; /* Add 32K + 18 bytes slack */
offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
- printf(".section \".rodata.compressed\",\"a\",@progbits\n");
+ printf(".section \".rodata..compressed\",\"a\",@progbits\n");
printf(".globl z_input_len\n");
printf("z_input_len = %lu\n", ilen);
printf(".globl z_output_len\n");
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index a6f1a59..5ddabce 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -26,8 +26,8 @@
HEAD_TEXT
_ehead = . ;
}
- .rodata.compressed : {
- *(.rodata.compressed)
+ .rodata..compressed : {
+ *(.rodata..compressed)
}
.text : {
_text = .; /* Text */
diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h
index 2f9047c..48f99f1 100644
--- a/arch/x86/include/asm/cache.h
+++ b/arch/x86/include/asm/cache.h
@@ -7,7 +7,7 @@
#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#define INTERNODE_CACHE_SHIFT CONFIG_X86_INTERNODE_CACHE_SHIFT
#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
index 8ded418..13ab7205 100644
--- a/arch/x86/kernel/acpi/wakeup_32.S
+++ b/arch/x86/kernel/acpi/wakeup_32.S
@@ -1,4 +1,4 @@
- .section .text.page_aligned
+ .section .text..page_aligned
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page_types.h>
diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c
index 3a54dcb..43e9ccf 100644
--- a/arch/x86/kernel/init_task.c
+++ b/arch/x86/kernel/init_task.c
@@ -34,7 +34,7 @@
/*
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
* no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data.cacheline_aligned
+ * so they are allowed to end up in the .data..cacheline_aligned
* section. Since TSS's are completely CPU-local, we want them
* on exact cacheline boundaries, to eliminate cacheline ping-pong.
*/
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index a867940..cf59276 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -247,7 +247,7 @@
#endif
#endif
/*
- * Up to this point, the boot CPU has been using .data.init
+ * Up to this point, the boot CPU has been using .init.data
* area. Reload any changed state for the boot CPU.
*/
if (cpu == boot_cpu_id)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 2cc2497..d0bb522 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -97,7 +97,7 @@
HEAD_TEXT
#ifdef CONFIG_X86_32
. = ALIGN(PAGE_SIZE);
- *(.text.page_aligned)
+ *(.text..page_aligned)
#endif
. = ALIGN(8);
_stext = .;
@@ -305,7 +305,7 @@
. = ALIGN(PAGE_SIZE);
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
__bss_start = .;
- *(.bss.page_aligned)
+ *(.bss..page_aligned)
*(.bss)
. = ALIGN(4);
__bss_stop = .;
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index e8ea682..9344216 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1059,7 +1059,7 @@
}
}
-static int intel_i915_configure(void)
+static int intel_i9xx_configure(void)
{
struct aper_size_info_fixed *current_size;
u32 temp;
@@ -1207,6 +1207,38 @@
return 0;
}
+static int intel_i915_get_gtt_size(void)
+{
+ int size;
+
+ if (IS_G33) {
+ u16 gmch_ctrl;
+
+ /* G33's GTT size defined in gmch_ctrl */
+ pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+ switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
+ case G33_PGETBL_SIZE_1M:
+ size = 1024;
+ break;
+ case G33_PGETBL_SIZE_2M:
+ size = 2048;
+ break;
+ default:
+ dev_info(&agp_bridge->dev->dev,
+ "unknown page table size 0x%x, assuming 512KB\n",
+ (gmch_ctrl & G33_PGETBL_SIZE_MASK));
+ size = 512;
+ }
+ } else {
+ /* On previous hardware, the GTT size was just what was
+ * required to map the aperture.
+ */
+ size = agp_bridge->driver->fetch_size();
+ }
+
+ return KB(size);
+}
+
/* The intel i915 automatically initializes the agp aperture during POST.
* Use the memory already set aside for in the GTT.
*/
@@ -1216,7 +1248,7 @@
struct aper_size_info_fixed *size;
int num_entries;
u32 temp, temp2;
- int gtt_map_size = 256 * 1024;
+ int gtt_map_size;
size = agp_bridge->current_size;
page_order = size->page_order;
@@ -1226,8 +1258,8 @@
pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
- if (IS_G33)
- gtt_map_size = 1024 * 1024; /* 1M on G33 */
+ gtt_map_size = intel_i915_get_gtt_size();
+
intel_private.gtt = ioremap(temp2, gtt_map_size);
if (!intel_private.gtt)
return -ENOMEM;
@@ -1422,7 +1454,7 @@
.size_type = FIXED_APER_SIZE,
.num_aperture_sizes = 4,
.needs_scratch_page = true,
- .configure = intel_i915_configure,
+ .configure = intel_i9xx_configure,
.fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.mask_memory = intel_i810_mask_memory,
@@ -1455,7 +1487,7 @@
.size_type = FIXED_APER_SIZE,
.num_aperture_sizes = 4,
.needs_scratch_page = true,
- .configure = intel_i915_configure,
+ .configure = intel_i9xx_configure,
.fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.mask_memory = intel_i965_mask_memory,
@@ -1488,7 +1520,7 @@
.size_type = FIXED_APER_SIZE,
.num_aperture_sizes = 4,
.needs_scratch_page = true,
- .configure = intel_i915_configure,
+ .configure = intel_i9xx_configure,
.fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.mask_memory = intel_i965_mask_memory,
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 9563901..da78f2c 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -22,6 +22,7 @@
intel_fb.o \
intel_tv.o \
intel_dvo.o \
+ intel_ringbuffer.o \
intel_overlay.o \
dvo_ch7xxx.o \
dvo_ch7017.o \
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 322070c..52510ad 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -77,7 +77,7 @@
case ACTIVE_LIST:
seq_printf(m, "Active:\n");
lock = &dev_priv->mm.active_list_lock;
- head = &dev_priv->mm.active_list;
+ head = &dev_priv->render_ring.active_list;
break;
case INACTIVE_LIST:
seq_printf(m, "Inactive:\n");
@@ -129,7 +129,8 @@
struct drm_i915_gem_request *gem_request;
seq_printf(m, "Request:\n");
- list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) {
+ list_for_each_entry(gem_request, &dev_priv->render_ring.request_list,
+ list) {
seq_printf(m, " %d @ %d\n",
gem_request->seqno,
(int) (jiffies - gem_request->emitted_jiffies));
@@ -143,9 +144,9 @@
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- if (dev_priv->hw_status_page != NULL) {
+ if (dev_priv->render_ring.status_page.page_addr != NULL) {
seq_printf(m, "Current sequence: %d\n",
- i915_get_gem_seqno(dev));
+ i915_get_gem_seqno(dev, &dev_priv->render_ring));
} else {
seq_printf(m, "Current sequence: hws uninitialized\n");
}
@@ -195,9 +196,9 @@
}
seq_printf(m, "Interrupts received: %d\n",
atomic_read(&dev_priv->irq_received));
- if (dev_priv->hw_status_page != NULL) {
+ if (dev_priv->render_ring.status_page.page_addr != NULL) {
seq_printf(m, "Current sequence: %d\n",
- i915_get_gem_seqno(dev));
+ i915_get_gem_seqno(dev, &dev_priv->render_ring));
} else {
seq_printf(m, "Current sequence: hws uninitialized\n");
}
@@ -251,7 +252,7 @@
int i;
volatile u32 *hws;
- hws = (volatile u32 *)dev_priv->hw_status_page;
+ hws = (volatile u32 *)dev_priv->render_ring.status_page.page_addr;
if (hws == NULL)
return 0;
@@ -287,7 +288,8 @@
spin_lock(&dev_priv->mm.active_list_lock);
- list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+ list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list,
+ list) {
obj = &obj_priv->base;
if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
ret = i915_gem_object_get_pages(obj, 0);
@@ -317,14 +319,14 @@
u8 *virt;
uint32_t *ptr, off;
- if (!dev_priv->ring.ring_obj) {
+ if (!dev_priv->render_ring.gem_object) {
seq_printf(m, "No ringbuffer setup\n");
return 0;
}
- virt = dev_priv->ring.virtual_start;
+ virt = dev_priv->render_ring.virtual_start;
- for (off = 0; off < dev_priv->ring.Size; off += 4) {
+ for (off = 0; off < dev_priv->render_ring.size; off += 4) {
ptr = (uint32_t *)(virt + off);
seq_printf(m, "%08x : %08x\n", off, *ptr);
}
@@ -344,7 +346,7 @@
seq_printf(m, "RingHead : %08x\n", head);
seq_printf(m, "RingTail : %08x\n", tail);
- seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size);
+ seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size);
seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
return 0;
@@ -489,11 +491,14 @@
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
u16 rgvswctl = I915_READ16(MEMSWCTL);
+ u16 rgvstat = I915_READ16(MEMSTAT_ILK);
- seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3);
- seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1);
- seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf,
- rgvswctl & 0x3f);
+ seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
+ seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
+ seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
+ MEMSTAT_VID_SHIFT);
+ seq_printf(m, "Current P-state: %d\n",
+ (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
return 0;
}
@@ -508,7 +513,8 @@
for (i = 0; i < 16; i++) {
delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
- seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq);
+ seq_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
+ (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
}
return 0;
@@ -541,6 +547,8 @@
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
u32 rgvmodectl = I915_READ(MEMMODECTL);
+ u32 rstdbyctl = I915_READ(MCHBAR_RENDER_STANDBY);
+ u16 crstandvid = I915_READ16(CRSTANDVID);
seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
"yes" : "no");
@@ -555,9 +563,13 @@
rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
seq_printf(m, "Starting frequency: P%d\n",
(rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
- seq_printf(m, "Max frequency: P%d\n",
+ seq_printf(m, "Max P-state: P%d\n",
(rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
- seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
+ seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
+ seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
+ seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
+ seq_printf(m, "Render standby enabled: %s\n",
+ (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
return 0;
}
@@ -621,6 +633,36 @@
return 0;
}
+static int i915_emon_status(struct seq_file *m, void *unused)
+{
+ 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 long temp, chipset, gfx;
+
+ temp = i915_mch_val(dev_priv);
+ chipset = i915_chipset_val(dev_priv);
+ gfx = i915_gfx_val(dev_priv);
+
+ seq_printf(m, "GMCH temp: %ld\n", temp);
+ seq_printf(m, "Chipset power: %ld\n", chipset);
+ seq_printf(m, "GFX power: %ld\n", gfx);
+ seq_printf(m, "Total power: %ld\n", chipset + gfx);
+
+ return 0;
+}
+
+static int i915_gfxec(struct seq_file *m, void *unused)
+{
+ 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;
+
+ seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+
+ return 0;
+}
+
static int
i915_wedged_open(struct inode *inode,
struct file *filp)
@@ -743,6 +785,8 @@
{"i915_delayfreq_table", i915_delayfreq_table, 0},
{"i915_inttoext_table", i915_inttoext_table, 0},
{"i915_drpc_info", i915_drpc_info, 0},
+ {"i915_emon_status", i915_emon_status, 0},
+ {"i915_gfxec", i915_gfxec, 0},
{"i915_fbc_status", i915_fbc_status, 0},
{"i915_sr_status", i915_sr_status, 0},
};
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2a6b5de..84ce956 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -40,84 +40,6 @@
#include <linux/vga_switcheroo.h>
#include <linux/slab.h>
-/* Really want an OS-independent resettable timer. Would like to have
- * this loop run for (eg) 3 sec, but have the timer reset every time
- * the head pointer changes, so that EBUSY only happens if the ring
- * actually stalls for (eg) 3 seconds.
- */
-int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
- u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
- u32 last_acthd = I915_READ(acthd_reg);
- u32 acthd;
- u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
- int i;
-
- trace_i915_ring_wait_begin (dev);
-
- for (i = 0; i < 100000; i++) {
- ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
- acthd = I915_READ(acthd_reg);
- ring->space = ring->head - (ring->tail + 8);
- if (ring->space < 0)
- ring->space += ring->Size;
- if (ring->space >= n) {
- trace_i915_ring_wait_end (dev);
- return 0;
- }
-
- if (dev->primary->master) {
- struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
- if (master_priv->sarea_priv)
- master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
- }
-
-
- if (ring->head != last_head)
- i = 0;
- if (acthd != last_acthd)
- i = 0;
-
- last_head = ring->head;
- last_acthd = acthd;
- msleep_interruptible(10);
-
- }
-
- trace_i915_ring_wait_end (dev);
- 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.
@@ -133,10 +55,11 @@
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->render_ring.status_page.page_addr
+ = dev_priv->status_page_dmah->vaddr;
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE);
if (IS_I965G(dev))
dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
@@ -159,8 +82,8 @@
dev_priv->status_page_dmah = NULL;
}
- if (dev_priv->status_gfx_addr) {
- dev_priv->status_gfx_addr = 0;
+ if (dev_priv->render_ring.status_page.gfx_addr) {
+ dev_priv->render_ring.status_page.gfx_addr = 0;
drm_core_ioremapfree(&dev_priv->hws_map, dev);
}
@@ -172,7 +95,7 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv;
- drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+ struct intel_ring_buffer *ring = &dev_priv->render_ring;
/*
* We should never lose context on the ring with modesetting
@@ -185,7 +108,7 @@
ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0)
- ring->space += ring->Size;
+ ring->space += ring->size;
if (!dev->primary->master)
return;
@@ -205,12 +128,9 @@
if (dev->irq_enabled)
drm_irq_uninstall(dev);
- if (dev_priv->ring.virtual_start) {
- drm_core_ioremapfree(&dev_priv->ring.map, dev);
- dev_priv->ring.virtual_start = NULL;
- dev_priv->ring.map.handle = NULL;
- dev_priv->ring.map.size = 0;
- }
+ intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
+ if (HAS_BSD(dev))
+ intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
/* Clear the HWS virtual address at teardown */
if (I915_NEED_GFX_HWS(dev))
@@ -233,24 +153,24 @@
}
if (init->ring_size != 0) {
- if (dev_priv->ring.ring_obj != NULL) {
+ if (dev_priv->render_ring.gem_object != NULL) {
i915_dma_cleanup(dev);
DRM_ERROR("Client tried to initialize ringbuffer in "
"GEM mode\n");
return -EINVAL;
}
- dev_priv->ring.Size = init->ring_size;
+ dev_priv->render_ring.size = init->ring_size;
- dev_priv->ring.map.offset = init->ring_start;
- dev_priv->ring.map.size = init->ring_size;
- dev_priv->ring.map.type = 0;
- dev_priv->ring.map.flags = 0;
- dev_priv->ring.map.mtrr = 0;
+ dev_priv->render_ring.map.offset = init->ring_start;
+ dev_priv->render_ring.map.size = init->ring_size;
+ dev_priv->render_ring.map.type = 0;
+ dev_priv->render_ring.map.flags = 0;
+ dev_priv->render_ring.map.mtrr = 0;
- drm_core_ioremap_wc(&dev_priv->ring.map, dev);
+ drm_core_ioremap_wc(&dev_priv->render_ring.map, dev);
- if (dev_priv->ring.map.handle == NULL) {
+ if (dev_priv->render_ring.map.handle == NULL) {
i915_dma_cleanup(dev);
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
@@ -258,7 +178,7 @@
}
}
- dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+ dev_priv->render_ring.virtual_start = dev_priv->render_ring.map.handle;
dev_priv->cpp = init->cpp;
dev_priv->back_offset = init->back_offset;
@@ -278,26 +198,29 @@
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct intel_ring_buffer *ring;
DRM_DEBUG_DRIVER("%s\n", __func__);
- if (dev_priv->ring.map.handle == NULL) {
+ ring = &dev_priv->render_ring;
+
+ if (ring->map.handle == NULL) {
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
return -ENOMEM;
}
/* Program Hardware Status Page */
- if (!dev_priv->hw_status_page) {
+ if (!ring->status_page.page_addr) {
DRM_ERROR("Can not find hardware status page\n");
return -EINVAL;
}
DRM_DEBUG_DRIVER("hw status page @ %p\n",
- dev_priv->hw_status_page);
-
- if (dev_priv->status_gfx_addr != 0)
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+ ring->status_page.page_addr);
+ if (ring->status_page.gfx_addr != 0)
+ ring->setup_status_page(dev, ring);
else
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
+
DRM_DEBUG_DRIVER("Enabled hardware status page\n");
return 0;
@@ -407,9 +330,8 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;
- RING_LOCALS;
- if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
+ if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8)
return -EINVAL;
BEGIN_LP_RING((dwords+1)&~1);
@@ -442,9 +364,7 @@
struct drm_clip_rect *boxes,
int i, int DR1, int DR4)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_clip_rect box = boxes[i];
- RING_LOCALS;
if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
DRM_ERROR("Bad box %d,%d..%d,%d\n",
@@ -481,7 +401,6 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
- RING_LOCALS;
dev_priv->counter++;
if (dev_priv->counter > 0x7FFFFFFFUL)
@@ -535,10 +454,8 @@
drm_i915_batchbuffer_t * batch,
struct drm_clip_rect *cliprects)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
int nbox = batch->num_cliprects;
int i = 0, count;
- RING_LOCALS;
if ((batch->start | batch->used) & 0x7) {
DRM_ERROR("alignment");
@@ -587,7 +504,6 @@
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv =
dev->primary->master->driver_priv;
- RING_LOCALS;
if (!master_priv->sarea_priv)
return -EINVAL;
@@ -640,7 +556,8 @@
drm_i915_private_t *dev_priv = dev->dev_private;
i915_kernel_lost_context(dev);
- return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+ return intel_wait_ring_buffer(dev, &dev_priv->render_ring,
+ dev_priv->render_ring.size - 8);
}
static int i915_flush_ioctl(struct drm_device *dev, void *data,
@@ -827,6 +744,9 @@
/* depends on GEM */
value = dev_priv->has_gem;
break;
+ case I915_PARAM_HAS_BSD:
+ value = HAS_BSD(dev);
+ break;
default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param);
@@ -882,6 +802,7 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_hws_addr_t *hws = data;
+ struct intel_ring_buffer *ring = &dev_priv->render_ring;
if (!I915_NEED_GFX_HWS(dev))
return -EINVAL;
@@ -898,7 +819,7 @@
DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
- dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
+ ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);
dev_priv->hws_map.offset = dev->agp->base + hws->addr;
dev_priv->hws_map.size = 4*1024;
@@ -909,19 +830,19 @@
drm_core_ioremap_wc(&dev_priv->hws_map, dev);
if (dev_priv->hws_map.handle == NULL) {
i915_dma_cleanup(dev);
- dev_priv->status_gfx_addr = 0;
+ ring->status_page.gfx_addr = 0;
DRM_ERROR("can not ioremap virtual address for"
" G33 hw status page\n");
return -ENOMEM;
}
- dev_priv->hw_status_page = dev_priv->hws_map.handle;
+ ring->status_page.page_addr = dev_priv->hws_map.handle;
+ memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+ I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
- dev_priv->status_gfx_addr);
+ ring->status_page.gfx_addr);
DRM_DEBUG_DRIVER("load hws at %p\n",
- dev_priv->hw_status_page);
+ ring->status_page.page_addr);
return 0;
}
@@ -1539,14 +1460,11 @@
master->driver_priv = NULL;
}
-static void i915_get_mem_freq(struct drm_device *dev)
+static void i915_pineview_get_mem_freq(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 tmp;
- if (!IS_PINEVIEW(dev))
- return;
-
tmp = I915_READ(CLKCFG);
switch (tmp & CLKCFG_FSB_MASK) {
@@ -1575,8 +1493,525 @@
dev_priv->mem_freq = 800;
break;
}
+
+ /* detect pineview DDR3 setting */
+ tmp = I915_READ(CSHRDDR3CTL);
+ dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
}
+static void i915_ironlake_get_mem_freq(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ u16 ddrpll, csipll;
+
+ ddrpll = I915_READ16(DDRMPLL1);
+ csipll = I915_READ16(CSIPLL0);
+
+ switch (ddrpll & 0xff) {
+ case 0xc:
+ dev_priv->mem_freq = 800;
+ break;
+ case 0x10:
+ dev_priv->mem_freq = 1066;
+ break;
+ case 0x14:
+ dev_priv->mem_freq = 1333;
+ break;
+ case 0x18:
+ dev_priv->mem_freq = 1600;
+ break;
+ default:
+ DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
+ ddrpll & 0xff);
+ dev_priv->mem_freq = 0;
+ break;
+ }
+
+ dev_priv->r_t = dev_priv->mem_freq;
+
+ switch (csipll & 0x3ff) {
+ case 0x00c:
+ dev_priv->fsb_freq = 3200;
+ break;
+ case 0x00e:
+ dev_priv->fsb_freq = 3733;
+ break;
+ case 0x010:
+ dev_priv->fsb_freq = 4266;
+ break;
+ case 0x012:
+ dev_priv->fsb_freq = 4800;
+ break;
+ case 0x014:
+ dev_priv->fsb_freq = 5333;
+ break;
+ case 0x016:
+ dev_priv->fsb_freq = 5866;
+ break;
+ case 0x018:
+ dev_priv->fsb_freq = 6400;
+ break;
+ default:
+ DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
+ csipll & 0x3ff);
+ dev_priv->fsb_freq = 0;
+ break;
+ }
+
+ if (dev_priv->fsb_freq == 3200) {
+ dev_priv->c_m = 0;
+ } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
+ dev_priv->c_m = 1;
+ } else {
+ dev_priv->c_m = 2;
+ }
+}
+
+struct v_table {
+ u8 vid;
+ unsigned long vd; /* in .1 mil */
+ unsigned long vm; /* in .1 mil */
+ u8 pvid;
+};
+
+static struct v_table v_table[] = {
+ { 0, 16125, 15000, 0x7f, },
+ { 1, 16000, 14875, 0x7e, },
+ { 2, 15875, 14750, 0x7d, },
+ { 3, 15750, 14625, 0x7c, },
+ { 4, 15625, 14500, 0x7b, },
+ { 5, 15500, 14375, 0x7a, },
+ { 6, 15375, 14250, 0x79, },
+ { 7, 15250, 14125, 0x78, },
+ { 8, 15125, 14000, 0x77, },
+ { 9, 15000, 13875, 0x76, },
+ { 10, 14875, 13750, 0x75, },
+ { 11, 14750, 13625, 0x74, },
+ { 12, 14625, 13500, 0x73, },
+ { 13, 14500, 13375, 0x72, },
+ { 14, 14375, 13250, 0x71, },
+ { 15, 14250, 13125, 0x70, },
+ { 16, 14125, 13000, 0x6f, },
+ { 17, 14000, 12875, 0x6e, },
+ { 18, 13875, 12750, 0x6d, },
+ { 19, 13750, 12625, 0x6c, },
+ { 20, 13625, 12500, 0x6b, },
+ { 21, 13500, 12375, 0x6a, },
+ { 22, 13375, 12250, 0x69, },
+ { 23, 13250, 12125, 0x68, },
+ { 24, 13125, 12000, 0x67, },
+ { 25, 13000, 11875, 0x66, },
+ { 26, 12875, 11750, 0x65, },
+ { 27, 12750, 11625, 0x64, },
+ { 28, 12625, 11500, 0x63, },
+ { 29, 12500, 11375, 0x62, },
+ { 30, 12375, 11250, 0x61, },
+ { 31, 12250, 11125, 0x60, },
+ { 32, 12125, 11000, 0x5f, },
+ { 33, 12000, 10875, 0x5e, },
+ { 34, 11875, 10750, 0x5d, },
+ { 35, 11750, 10625, 0x5c, },
+ { 36, 11625, 10500, 0x5b, },
+ { 37, 11500, 10375, 0x5a, },
+ { 38, 11375, 10250, 0x59, },
+ { 39, 11250, 10125, 0x58, },
+ { 40, 11125, 10000, 0x57, },
+ { 41, 11000, 9875, 0x56, },
+ { 42, 10875, 9750, 0x55, },
+ { 43, 10750, 9625, 0x54, },
+ { 44, 10625, 9500, 0x53, },
+ { 45, 10500, 9375, 0x52, },
+ { 46, 10375, 9250, 0x51, },
+ { 47, 10250, 9125, 0x50, },
+ { 48, 10125, 9000, 0x4f, },
+ { 49, 10000, 8875, 0x4e, },
+ { 50, 9875, 8750, 0x4d, },
+ { 51, 9750, 8625, 0x4c, },
+ { 52, 9625, 8500, 0x4b, },
+ { 53, 9500, 8375, 0x4a, },
+ { 54, 9375, 8250, 0x49, },
+ { 55, 9250, 8125, 0x48, },
+ { 56, 9125, 8000, 0x47, },
+ { 57, 9000, 7875, 0x46, },
+ { 58, 8875, 7750, 0x45, },
+ { 59, 8750, 7625, 0x44, },
+ { 60, 8625, 7500, 0x43, },
+ { 61, 8500, 7375, 0x42, },
+ { 62, 8375, 7250, 0x41, },
+ { 63, 8250, 7125, 0x40, },
+ { 64, 8125, 7000, 0x3f, },
+ { 65, 8000, 6875, 0x3e, },
+ { 66, 7875, 6750, 0x3d, },
+ { 67, 7750, 6625, 0x3c, },
+ { 68, 7625, 6500, 0x3b, },
+ { 69, 7500, 6375, 0x3a, },
+ { 70, 7375, 6250, 0x39, },
+ { 71, 7250, 6125, 0x38, },
+ { 72, 7125, 6000, 0x37, },
+ { 73, 7000, 5875, 0x36, },
+ { 74, 6875, 5750, 0x35, },
+ { 75, 6750, 5625, 0x34, },
+ { 76, 6625, 5500, 0x33, },
+ { 77, 6500, 5375, 0x32, },
+ { 78, 6375, 5250, 0x31, },
+ { 79, 6250, 5125, 0x30, },
+ { 80, 6125, 5000, 0x2f, },
+ { 81, 6000, 4875, 0x2e, },
+ { 82, 5875, 4750, 0x2d, },
+ { 83, 5750, 4625, 0x2c, },
+ { 84, 5625, 4500, 0x2b, },
+ { 85, 5500, 4375, 0x2a, },
+ { 86, 5375, 4250, 0x29, },
+ { 87, 5250, 4125, 0x28, },
+ { 88, 5125, 4000, 0x27, },
+ { 89, 5000, 3875, 0x26, },
+ { 90, 4875, 3750, 0x25, },
+ { 91, 4750, 3625, 0x24, },
+ { 92, 4625, 3500, 0x23, },
+ { 93, 4500, 3375, 0x22, },
+ { 94, 4375, 3250, 0x21, },
+ { 95, 4250, 3125, 0x20, },
+ { 96, 4125, 3000, 0x1f, },
+ { 97, 4125, 3000, 0x1e, },
+ { 98, 4125, 3000, 0x1d, },
+ { 99, 4125, 3000, 0x1c, },
+ { 100, 4125, 3000, 0x1b, },
+ { 101, 4125, 3000, 0x1a, },
+ { 102, 4125, 3000, 0x19, },
+ { 103, 4125, 3000, 0x18, },
+ { 104, 4125, 3000, 0x17, },
+ { 105, 4125, 3000, 0x16, },
+ { 106, 4125, 3000, 0x15, },
+ { 107, 4125, 3000, 0x14, },
+ { 108, 4125, 3000, 0x13, },
+ { 109, 4125, 3000, 0x12, },
+ { 110, 4125, 3000, 0x11, },
+ { 111, 4125, 3000, 0x10, },
+ { 112, 4125, 3000, 0x0f, },
+ { 113, 4125, 3000, 0x0e, },
+ { 114, 4125, 3000, 0x0d, },
+ { 115, 4125, 3000, 0x0c, },
+ { 116, 4125, 3000, 0x0b, },
+ { 117, 4125, 3000, 0x0a, },
+ { 118, 4125, 3000, 0x09, },
+ { 119, 4125, 3000, 0x08, },
+ { 120, 1125, 0, 0x07, },
+ { 121, 1000, 0, 0x06, },
+ { 122, 875, 0, 0x05, },
+ { 123, 750, 0, 0x04, },
+ { 124, 625, 0, 0x03, },
+ { 125, 500, 0, 0x02, },
+ { 126, 375, 0, 0x01, },
+ { 127, 0, 0, 0x00, },
+};
+
+struct cparams {
+ int i;
+ int t;
+ int m;
+ int c;
+};
+
+static struct cparams cparams[] = {
+ { 1, 1333, 301, 28664 },
+ { 1, 1066, 294, 24460 },
+ { 1, 800, 294, 25192 },
+ { 0, 1333, 276, 27605 },
+ { 0, 1066, 276, 27605 },
+ { 0, 800, 231, 23784 },
+};
+
+unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
+{
+ u64 total_count, diff, ret;
+ u32 count1, count2, count3, m = 0, c = 0;
+ unsigned long now = jiffies_to_msecs(jiffies), diff1;
+ int i;
+
+ diff1 = now - dev_priv->last_time1;
+
+ count1 = I915_READ(DMIEC);
+ count2 = I915_READ(DDREC);
+ count3 = I915_READ(CSIEC);
+
+ total_count = count1 + count2 + count3;
+
+ /* FIXME: handle per-counter overflow */
+ if (total_count < dev_priv->last_count1) {
+ diff = ~0UL - dev_priv->last_count1;
+ diff += total_count;
+ } else {
+ diff = total_count - dev_priv->last_count1;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cparams); i++) {
+ if (cparams[i].i == dev_priv->c_m &&
+ cparams[i].t == dev_priv->r_t) {
+ m = cparams[i].m;
+ c = cparams[i].c;
+ break;
+ }
+ }
+
+ div_u64(diff, diff1);
+ ret = ((m * diff) + c);
+ div_u64(ret, 10);
+
+ dev_priv->last_count1 = total_count;
+ dev_priv->last_time1 = now;
+
+ return ret;
+}
+
+unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
+{
+ unsigned long m, x, b;
+ u32 tsfs;
+
+ tsfs = I915_READ(TSFS);
+
+ m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
+ x = I915_READ8(TR1);
+
+ b = tsfs & TSFS_INTR_MASK;
+
+ return ((m * x) / 127) - b;
+}
+
+static unsigned long pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
+{
+ unsigned long val = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(v_table); i++) {
+ if (v_table[i].pvid == pxvid) {
+ if (IS_MOBILE(dev_priv->dev))
+ val = v_table[i].vm;
+ else
+ val = v_table[i].vd;
+ }
+ }
+
+ return val;
+}
+
+void i915_update_gfx_val(struct drm_i915_private *dev_priv)
+{
+ struct timespec now, diff1;
+ u64 diff;
+ unsigned long diffms;
+ u32 count;
+
+ getrawmonotonic(&now);
+ diff1 = timespec_sub(now, dev_priv->last_time2);
+
+ /* Don't divide by 0 */
+ diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
+ if (!diffms)
+ return;
+
+ count = I915_READ(GFXEC);
+
+ if (count < dev_priv->last_count2) {
+ diff = ~0UL - dev_priv->last_count2;
+ diff += count;
+ } else {
+ diff = count - dev_priv->last_count2;
+ }
+
+ dev_priv->last_count2 = count;
+ dev_priv->last_time2 = now;
+
+ /* More magic constants... */
+ diff = diff * 1181;
+ div_u64(diff, diffms * 10);
+ dev_priv->gfx_power = diff;
+}
+
+unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
+{
+ unsigned long t, corr, state1, corr2, state2;
+ u32 pxvid, ext_v;
+
+ pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
+ pxvid = (pxvid >> 24) & 0x7f;
+ ext_v = pvid_to_extvid(dev_priv, pxvid);
+
+ state1 = ext_v;
+
+ t = i915_mch_val(dev_priv);
+
+ /* Revel in the empirically derived constants */
+
+ /* Correction factor in 1/100000 units */
+ if (t > 80)
+ corr = ((t * 2349) + 135940);
+ else if (t >= 50)
+ corr = ((t * 964) + 29317);
+ else /* < 50 */
+ corr = ((t * 301) + 1004);
+
+ corr = corr * ((150142 * state1) / 10000 - 78642);
+ corr /= 100000;
+ corr2 = (corr * dev_priv->corr);
+
+ state2 = (corr2 * state1) / 10000;
+ state2 /= 100; /* convert to mW */
+
+ i915_update_gfx_val(dev_priv);
+
+ return dev_priv->gfx_power + state2;
+}
+
+/* Global for IPS driver to get at the current i915 device */
+static struct drm_i915_private *i915_mch_dev;
+/*
+ * Lock protecting IPS related data structures
+ * - i915_mch_dev
+ * - dev_priv->max_delay
+ * - dev_priv->min_delay
+ * - dev_priv->fmax
+ * - dev_priv->gpu_busy
+ */
+DEFINE_SPINLOCK(mchdev_lock);
+
+/**
+ * i915_read_mch_val - return value for IPS use
+ *
+ * Calculate and return a value for the IPS driver to use when deciding whether
+ * we have thermal and power headroom to increase CPU or GPU power budget.
+ */
+unsigned long i915_read_mch_val(void)
+{
+ struct drm_i915_private *dev_priv;
+ unsigned long chipset_val, graphics_val, ret = 0;
+
+ spin_lock(&mchdev_lock);
+ if (!i915_mch_dev)
+ goto out_unlock;
+ dev_priv = i915_mch_dev;
+
+ chipset_val = i915_chipset_val(dev_priv);
+ graphics_val = i915_gfx_val(dev_priv);
+
+ ret = chipset_val + graphics_val;
+
+out_unlock:
+ spin_unlock(&mchdev_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i915_read_mch_val);
+
+/**
+ * i915_gpu_raise - raise GPU frequency limit
+ *
+ * Raise the limit; IPS indicates we have thermal headroom.
+ */
+bool i915_gpu_raise(void)
+{
+ struct drm_i915_private *dev_priv;
+ bool ret = true;
+
+ spin_lock(&mchdev_lock);
+ if (!i915_mch_dev) {
+ ret = false;
+ goto out_unlock;
+ }
+ dev_priv = i915_mch_dev;
+
+ if (dev_priv->max_delay > dev_priv->fmax)
+ dev_priv->max_delay--;
+
+out_unlock:
+ spin_unlock(&mchdev_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_raise);
+
+/**
+ * i915_gpu_lower - lower GPU frequency limit
+ *
+ * IPS indicates we're close to a thermal limit, so throttle back the GPU
+ * frequency maximum.
+ */
+bool i915_gpu_lower(void)
+{
+ struct drm_i915_private *dev_priv;
+ bool ret = true;
+
+ spin_lock(&mchdev_lock);
+ if (!i915_mch_dev) {
+ ret = false;
+ goto out_unlock;
+ }
+ dev_priv = i915_mch_dev;
+
+ if (dev_priv->max_delay < dev_priv->min_delay)
+ dev_priv->max_delay++;
+
+out_unlock:
+ spin_unlock(&mchdev_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_lower);
+
+/**
+ * i915_gpu_busy - indicate GPU business to IPS
+ *
+ * Tell the IPS driver whether or not the GPU is busy.
+ */
+bool i915_gpu_busy(void)
+{
+ struct drm_i915_private *dev_priv;
+ bool ret = false;
+
+ spin_lock(&mchdev_lock);
+ if (!i915_mch_dev)
+ goto out_unlock;
+ dev_priv = i915_mch_dev;
+
+ ret = dev_priv->busy;
+
+out_unlock:
+ spin_unlock(&mchdev_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_busy);
+
+/**
+ * i915_gpu_turbo_disable - disable graphics turbo
+ *
+ * Disable graphics turbo by resetting the max frequency and setting the
+ * current frequency to the default.
+ */
+bool i915_gpu_turbo_disable(void)
+{
+ struct drm_i915_private *dev_priv;
+ bool ret = true;
+
+ spin_lock(&mchdev_lock);
+ if (!i915_mch_dev) {
+ ret = false;
+ goto out_unlock;
+ }
+ dev_priv = i915_mch_dev;
+
+ dev_priv->max_delay = dev_priv->fstart;
+
+ if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
+ ret = false;
+
+out_unlock:
+ spin_unlock(&mchdev_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
+
/**
* i915_driver_load - setup chip and create an initial config
* @dev: DRM device
@@ -1594,7 +2029,6 @@
resource_size_t base, size;
int ret = 0, mmio_bar;
uint32_t agp_size, prealloc_size, prealloc_start;
-
/* i915 has 4 more counters */
dev->counters += 4;
dev->types[6] = _DRM_STAT_IRQ;
@@ -1672,6 +2106,13 @@
dev_priv->has_gem = 0;
}
+ if (dev_priv->has_gem == 0 &&
+ drm_core_check_feature(dev, DRIVER_MODESET)) {
+ DRM_ERROR("kernel modesetting requires GEM, disabling driver.\n");
+ ret = -ENODEV;
+ goto out_iomapfree;
+ }
+
dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
@@ -1691,7 +2132,10 @@
goto out_workqueue_free;
}
- i915_get_mem_freq(dev);
+ if (IS_PINEVIEW(dev))
+ i915_pineview_get_mem_freq(dev);
+ else if (IS_IRONLAKE(dev))
+ i915_ironlake_get_mem_freq(dev);
/* On the 945G/GM, the chipset reports the MSI capability on the
* integrated graphics even though the support isn't actually there
@@ -1709,7 +2153,6 @@
spin_lock_init(&dev_priv->user_irq_lock);
spin_lock_init(&dev_priv->error_lock);
- dev_priv->user_irq_refcount = 0;
dev_priv->trace_irq_seqno = 0;
ret = drm_vblank_init(dev, I915_NUM_PIPE);
@@ -1738,6 +2181,12 @@
setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev);
+
+ spin_lock(&mchdev_lock);
+ i915_mch_dev = dev_priv;
+ dev_priv->mchdev_lock = &mchdev_lock;
+ spin_unlock(&mchdev_lock);
+
return 0;
out_workqueue_free:
@@ -1759,6 +2208,10 @@
i915_destroy_error_state(dev);
+ spin_lock(&mchdev_lock);
+ i915_mch_dev = NULL;
+ spin_unlock(&mchdev_lock);
+
destroy_workqueue(dev_priv->wq);
del_timer_sync(&dev_priv->hangcheck_timer);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 5c51e45..423dc90 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -60,95 +60,95 @@
.subdevice = PCI_ANY_ID, \
.driver_data = (unsigned long) info }
-const static struct intel_device_info intel_i830_info = {
+static const struct intel_device_info intel_i830_info = {
.is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
};
-const static struct intel_device_info intel_845g_info = {
+static const struct intel_device_info intel_845g_info = {
.is_i8xx = 1,
};
-const static struct intel_device_info intel_i85x_info = {
+static const struct intel_device_info intel_i85x_info = {
.is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
.cursor_needs_physical = 1,
};
-const static struct intel_device_info intel_i865g_info = {
+static const struct intel_device_info intel_i865g_info = {
.is_i8xx = 1,
};
-const static struct intel_device_info intel_i915g_info = {
+static const struct intel_device_info intel_i915g_info = {
.is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
};
-const static struct intel_device_info intel_i915gm_info = {
+static const struct intel_device_info intel_i915gm_info = {
.is_i9xx = 1, .is_mobile = 1,
.cursor_needs_physical = 1,
};
-const static struct intel_device_info intel_i945g_info = {
+static const struct intel_device_info intel_i945g_info = {
.is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
};
-const static struct intel_device_info intel_i945gm_info = {
+static const struct intel_device_info intel_i945gm_info = {
.is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
.has_hotplug = 1, .cursor_needs_physical = 1,
};
-const static struct intel_device_info intel_i965g_info = {
+static const struct intel_device_info intel_i965g_info = {
.is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
};
-const static struct intel_device_info intel_i965gm_info = {
+static const struct intel_device_info intel_i965gm_info = {
.is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_g33_info = {
+static const struct intel_device_info intel_g33_info = {
.is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_g45_info = {
+static const struct intel_device_info intel_g45_info = {
.is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
.has_pipe_cxsr = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_gm45_info = {
+static const struct intel_device_info intel_gm45_info = {
.is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
.has_pipe_cxsr = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_pineview_info = {
+static const struct intel_device_info intel_pineview_info = {
.is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
.need_gfx_hws = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_ironlake_d_info = {
+static const struct intel_device_info intel_ironlake_d_info = {
.is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
.has_pipe_cxsr = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_ironlake_m_info = {
+static const struct intel_device_info intel_ironlake_m_info = {
.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
.need_gfx_hws = 1, .has_rc6 = 1,
.has_hotplug = 1,
};
-const static struct intel_device_info intel_sandybridge_d_info = {
+static const struct intel_device_info intel_sandybridge_d_info = {
.is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
.has_hotplug = 1, .is_gen6 = 1,
};
-const static struct intel_device_info intel_sandybridge_m_info = {
+static const struct intel_device_info intel_sandybridge_m_info = {
.is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
.has_hotplug = 1, .is_gen6 = 1,
};
-const static struct pci_device_id pciidlist[] = {
+static const struct pci_device_id pciidlist[] = {
INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
@@ -340,7 +340,7 @@
/*
* Clear request list
*/
- i915_gem_retire_requests(dev);
+ i915_gem_retire_requests(dev, &dev_priv->render_ring);
if (need_display)
i915_save_display(dev);
@@ -370,6 +370,7 @@
}
} else {
DRM_ERROR("Error occurred. Don't know how to reset this chip.\n");
+ mutex_unlock(&dev->struct_mutex);
return -ENODEV;
}
@@ -388,33 +389,10 @@
* switched away).
*/
if (drm_core_check_feature(dev, DRIVER_MODESET) ||
- !dev_priv->mm.suspended) {
- drm_i915_ring_buffer_t *ring = &dev_priv->ring;
- struct drm_gem_object *obj = ring->ring_obj;
- struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+ !dev_priv->mm.suspended) {
+ struct intel_ring_buffer *ring = &dev_priv->render_ring;
dev_priv->mm.suspended = 0;
-
- /* Stop the ring if it's running. */
- I915_WRITE(PRB0_CTL, 0);
- I915_WRITE(PRB0_TAIL, 0);
- I915_WRITE(PRB0_HEAD, 0);
-
- /* Initialize the ring. */
- I915_WRITE(PRB0_START, obj_priv->gtt_offset);
- I915_WRITE(PRB0_CTL,
- ((obj->size - 4096) & RING_NR_PAGES) |
- RING_NO_REPORT |
- RING_VALID);
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- i915_kernel_lost_context(dev);
- else {
- ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
- ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
- ring->space = ring->head - (ring->tail + 8);
- if (ring->space < 0)
- ring->space += ring->Size;
- }
-
+ ring->init(dev, ring);
mutex_unlock(&dev->struct_mutex);
drm_irq_uninstall(dev);
drm_irq_install(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7f797ef..9ed8ecd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -32,6 +32,7 @@
#include "i915_reg.h"
#include "intel_bios.h"
+#include "intel_ringbuffer.h"
#include <linux/io-mapping.h>
/* General customization:
@@ -55,6 +56,8 @@
#define I915_NUM_PIPE 2
+#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+
/* Interface history:
*
* 1.1: Original.
@@ -89,16 +92,6 @@
struct drm_gem_object *cur_obj;
};
-typedef struct _drm_i915_ring_buffer {
- unsigned long Size;
- u8 *virtual_start;
- int head;
- int tail;
- int space;
- drm_local_map_t map;
- struct drm_gem_object *ring_obj;
-} drm_i915_ring_buffer_t;
-
struct mem_block {
struct mem_block *next;
struct mem_block *prev;
@@ -241,17 +234,15 @@
void __iomem *regs;
struct pci_dev *bridge_dev;
- drm_i915_ring_buffer_t ring;
+ struct intel_ring_buffer render_ring;
+ struct intel_ring_buffer bsd_ring;
drm_dma_handle_t *status_page_dmah;
- void *hw_status_page;
void *seqno_page;
dma_addr_t dma_status_page;
uint32_t counter;
- unsigned int status_gfx_addr;
unsigned int seqno_gfx_addr;
drm_local_map_t hws_map;
- struct drm_gem_object *hws_obj;
struct drm_gem_object *seqno_obj;
struct drm_gem_object *pwrctx;
@@ -267,8 +258,6 @@
atomic_t irq_received;
/** Protects user_irq_refcount and irq_mask_reg */
spinlock_t user_irq_lock;
- /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
- int user_irq_refcount;
u32 trace_irq_seqno;
/** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg;
@@ -334,7 +323,7 @@
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
- unsigned int fsb_freq, mem_freq;
+ unsigned int fsb_freq, mem_freq, is_ddr3;
spinlock_t error_lock;
struct drm_i915_error_state *first_error;
@@ -514,18 +503,7 @@
*/
struct list_head shrink_list;
- /**
- * List of objects currently involved in rendering from the
- * ringbuffer.
- *
- * Includes buffers having the contents of their GPU caches
- * flushed, not necessarily primitives. last_rendering_seqno
- * represents when the rendering involved will be completed.
- *
- * A reference is held on the buffer while on this list.
- */
spinlock_t active_list_lock;
- struct list_head active_list;
/**
* List of objects which are not in the ringbuffer but which
@@ -563,12 +541,6 @@
struct list_head fence_list;
/**
- * List of breadcrumbs associated with GPU requests currently
- * outstanding.
- */
- struct list_head request_list;
-
- /**
* We leave the user IRQ off as much as possible,
* but this means that requests will finish and never
* be retired once the system goes idle. Set a timer to
@@ -644,6 +616,18 @@
u8 cur_delay;
u8 min_delay;
u8 max_delay;
+ u8 fmax;
+ u8 fstart;
+
+ u64 last_count1;
+ unsigned long last_time1;
+ u64 last_count2;
+ struct timespec last_time2;
+ unsigned long gfx_power;
+ int c_m;
+ int r_t;
+ u8 corr;
+ spinlock_t *mchdev_lock;
enum no_fbc_reason no_fbc_reason;
@@ -671,19 +655,64 @@
* (has pending rendering), and is not set if it's on inactive (ready
* to be unbound).
*/
- int active;
+ unsigned int active : 1;
/**
* This is set if the object has been written to since last bound
* to the GTT
*/
- int dirty;
+ unsigned int dirty : 1;
+
+ /**
+ * Fence register bits (if any) for this object. Will be set
+ * as needed when mapped into the GTT.
+ * Protected by dev->struct_mutex.
+ *
+ * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
+ */
+ int fence_reg : 5;
+
+ /**
+ * Used for checking the object doesn't appear more than once
+ * in an execbuffer object list.
+ */
+ unsigned int in_execbuffer : 1;
+
+ /**
+ * Advice: are the backing pages purgeable?
+ */
+ unsigned int madv : 2;
+
+ /**
+ * Refcount for the pages array. With the current locking scheme, there
+ * are at most two concurrent users: Binding a bo to the gtt and
+ * pwrite/pread using physical addresses. So two bits for a maximum
+ * of two users are enough.
+ */
+ unsigned int pages_refcount : 2;
+#define DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT 0x3
+
+ /**
+ * Current tiling mode for the object.
+ */
+ unsigned int tiling_mode : 2;
+
+ /** How many users have pinned this object in GTT space. The following
+ * users can each hold at most one reference: pwrite/pread, pin_ioctl
+ * (via user_pin_count), execbuffer (objects are not allowed multiple
+ * times for the same batchbuffer), and the framebuffer code. When
+ * switching/pageflipping, the framebuffer code has at most two buffers
+ * pinned per crtc.
+ *
+ * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
+ * bits with absolutely no headroom. So use 4 bits. */
+ int pin_count : 4;
+#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
/** AGP memory structure for our GTT binding. */
DRM_AGP_MEM *agp_mem;
struct page **pages;
- int pages_refcount;
/**
* Current offset of the object in GTT space.
@@ -692,26 +721,18 @@
*/
uint32_t gtt_offset;
+ /* Which ring is refering to is this object */
+ struct intel_ring_buffer *ring;
+
/**
* Fake offset for use by mmap(2)
*/
uint64_t mmap_offset;
- /**
- * Fence register bits (if any) for this object. Will be set
- * as needed when mapped into the GTT.
- * Protected by dev->struct_mutex.
- */
- int fence_reg;
-
- /** How many users have pinned this object in GTT space */
- int pin_count;
-
/** Breadcrumb of last rendering to the buffer. */
uint32_t last_rendering_seqno;
- /** Current tiling mode for the object. */
- uint32_t tiling_mode;
+ /** Current tiling stride for the object, if it's tiled. */
uint32_t stride;
/** Record of address bit 17 of each page at last unbind. */
@@ -734,17 +755,6 @@
struct drm_i915_gem_phys_object *phys_obj;
/**
- * Used for checking the object doesn't appear more than once
- * in an execbuffer object list.
- */
- int in_execbuffer;
-
- /**
- * Advice: are the backing pages purgeable?
- */
- int madv;
-
- /**
* Number of crtcs where this object is currently the fb, but
* will be page flipped away on the next vblank. When it
* reaches 0, dev_priv->pending_flip_queue will be woken up.
@@ -765,6 +775,9 @@
* an emission time with seqnos for tracking how far ahead of the GPU we are.
*/
struct drm_i915_gem_request {
+ /** On Which ring this request was generated */
+ struct intel_ring_buffer *ring;
+
/** GEM sequence number associated with this request. */
uint32_t seqno;
@@ -821,6 +834,11 @@
struct drm_clip_rect *boxes,
int i, int DR1, int DR4);
extern int i965_reset(struct drm_device *dev, u8 flags);
+extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
+extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
+extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
+extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
+
/* i915_irq.c */
void i915_hangcheck_elapsed(unsigned long data);
@@ -829,9 +847,7 @@
struct drm_file *file_priv);
extern int i915_irq_wait(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-void i915_user_irq_get(struct drm_device *dev);
void i915_trace_irq_get(struct drm_device *dev, u32 seqno);
-void i915_user_irq_put(struct drm_device *dev);
extern void i915_enable_interrupt (struct drm_device *dev);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
@@ -849,6 +865,11 @@
extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
+extern void i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask);
+extern void ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv,
+ u32 mask);
+extern void ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv,
+ u32 mask);
void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -922,11 +943,13 @@
int i915_gem_object_unbind(struct drm_gem_object *obj);
void i915_gem_release_mmap(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev);
-uint32_t i915_get_gem_seqno(struct drm_device *dev);
+uint32_t i915_get_gem_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
-void i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_requests(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
void i915_gem_retire_work_handler(struct work_struct *work);
void i915_gem_clflush_object(struct drm_gem_object *obj);
int i915_gem_object_set_domain(struct drm_gem_object *obj,
@@ -937,9 +960,13 @@
int i915_gem_do_init(struct drm_device *dev, unsigned long start,
unsigned long end);
int i915_gem_idle(struct drm_device *dev);
-uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
- uint32_t flush_domains);
-int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible);
+uint32_t i915_add_request(struct drm_device *dev,
+ struct drm_file *file_priv,
+ uint32_t flush_domains,
+ struct intel_ring_buffer *ring);
+int i915_do_wait_request(struct drm_device *dev,
+ uint32_t seqno, int interruptible,
+ struct intel_ring_buffer *ring);
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
int write);
@@ -1015,7 +1042,7 @@
extern void intel_disable_fbc(struct drm_device *dev);
extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
extern bool intel_fbc_enabled(struct drm_device *dev);
-
+extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
extern void intel_detect_pch (struct drm_device *dev);
extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
@@ -1026,7 +1053,8 @@
* has access to the ring.
*/
#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \
- if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
+ if (((drm_i915_private_t *)dev->dev_private)->render_ring.gem_object \
+ == NULL) \
LOCK_TEST_WITH_RETURN(dev, file_priv); \
} while (0)
@@ -1039,35 +1067,31 @@
#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg))
#define I915_READ64(reg) readq(dev_priv->regs + (reg))
#define POSTING_READ(reg) (void)I915_READ(reg)
+#define POSTING_READ16(reg) (void)I915_READ16(reg)
#define I915_VERBOSE 0
-#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__; \
+#define BEGIN_LP_RING(n) do { \
+ drm_i915_private_t *dev_priv = dev->dev_private; \
+ if (I915_VERBOSE) \
+ DRM_DEBUG(" BEGIN_LP_RING %x\n", (int)(n)); \
+ intel_ring_begin(dev, &dev_priv->render_ring, 4*(n)); \
} while (0)
-#define OUT_RING(n) do { \
- if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
- *ring_virt__++ = (n); \
+
+#define OUT_RING(x) do { \
+ drm_i915_private_t *dev_priv = dev->dev_private; \
+ if (I915_VERBOSE) \
+ DRM_DEBUG(" OUT_RING %x\n", (int)(x)); \
+ intel_ring_emit(dev, &dev_priv->render_ring, x); \
} while (0)
#define ADVANCE_LP_RING() do { \
+ drm_i915_private_t *dev_priv = dev->dev_private; \
if (I915_VERBOSE) \
- DRM_DEBUG("ADVANCE_LP_RING %x\n", dev_priv->ring.tail); \
- I915_WRITE(PRB0_TAIL, dev_priv->ring.tail); \
+ DRM_DEBUG("ADVANCE_LP_RING %x\n", \
+ dev_priv->render_ring.tail); \
+ intel_ring_advance(dev, &dev_priv->render_ring); \
} while(0)
/**
@@ -1085,14 +1109,12 @@
*
* The area from dword 0x20 to 0x3ff is available for driver usage.
*/
-#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#define READ_HWSP(dev_priv, reg) (((volatile u32 *)\
+ (dev_priv->render_ring.status_page.page_addr))[reg])
#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
#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 INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info)
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
@@ -1138,6 +1160,7 @@
(dev)->pci_device == 0x2A42 || \
(dev)->pci_device == 0x2E42)
+#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev))
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 112699f..9ded3da 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -35,8 +35,6 @@
#include <linux/swap.h>
#include <linux/pci.h>
-#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
-
static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
@@ -169,7 +167,7 @@
obj_priv->tiling_mode != I915_TILING_NONE;
}
-static inline int
+static inline void
slow_shmem_copy(struct page *dst_page,
int dst_offset,
struct page *src_page,
@@ -178,25 +176,16 @@
{
char *dst_vaddr, *src_vaddr;
- dst_vaddr = kmap_atomic(dst_page, KM_USER0);
- if (dst_vaddr == NULL)
- return -ENOMEM;
-
- src_vaddr = kmap_atomic(src_page, KM_USER1);
- if (src_vaddr == NULL) {
- kunmap_atomic(dst_vaddr, KM_USER0);
- return -ENOMEM;
- }
+ dst_vaddr = kmap(dst_page);
+ src_vaddr = kmap(src_page);
memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length);
- kunmap_atomic(src_vaddr, KM_USER1);
- kunmap_atomic(dst_vaddr, KM_USER0);
-
- return 0;
+ kunmap(src_page);
+ kunmap(dst_page);
}
-static inline int
+static inline void
slow_shmem_bit17_copy(struct page *gpu_page,
int gpu_offset,
struct page *cpu_page,
@@ -216,15 +205,8 @@
cpu_page, cpu_offset, length);
}
- gpu_vaddr = kmap_atomic(gpu_page, KM_USER0);
- if (gpu_vaddr == NULL)
- return -ENOMEM;
-
- cpu_vaddr = kmap_atomic(cpu_page, KM_USER1);
- if (cpu_vaddr == NULL) {
- kunmap_atomic(gpu_vaddr, KM_USER0);
- return -ENOMEM;
- }
+ gpu_vaddr = kmap(gpu_page);
+ cpu_vaddr = kmap(cpu_page);
/* Copy the data, XORing A6 with A17 (1). The user already knows he's
* XORing with the other bits (A9 for Y, A9 and A10 for X)
@@ -248,10 +230,8 @@
length -= this_length;
}
- kunmap_atomic(cpu_vaddr, KM_USER1);
- kunmap_atomic(gpu_vaddr, KM_USER0);
-
- return 0;
+ kunmap(cpu_page);
+ kunmap(gpu_page);
}
/**
@@ -427,21 +407,19 @@
page_length = PAGE_SIZE - data_page_offset;
if (do_bit17_swizzling) {
- ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
- shmem_page_offset,
- user_pages[data_page_index],
- data_page_offset,
- page_length,
- 1);
- } else {
- ret = slow_shmem_copy(user_pages[data_page_index],
- data_page_offset,
- obj_priv->pages[shmem_page_index],
+ slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
shmem_page_offset,
- page_length);
+ user_pages[data_page_index],
+ data_page_offset,
+ page_length,
+ 1);
+ } else {
+ slow_shmem_copy(user_pages[data_page_index],
+ data_page_offset,
+ obj_priv->pages[shmem_page_index],
+ shmem_page_offset,
+ page_length);
}
- if (ret)
- goto fail_put_pages;
remain -= page_length;
data_ptr += page_length;
@@ -531,25 +509,24 @@
* page faults
*/
-static inline int
+static inline void
slow_kernel_write(struct io_mapping *mapping,
loff_t gtt_base, int gtt_offset,
struct page *user_page, int user_offset,
int length)
{
- char *src_vaddr, *dst_vaddr;
- unsigned long unwritten;
+ char __iomem *dst_vaddr;
+ char *src_vaddr;
- dst_vaddr = io_mapping_map_atomic_wc(mapping, gtt_base);
- src_vaddr = kmap_atomic(user_page, KM_USER1);
- unwritten = __copy_from_user_inatomic_nocache(dst_vaddr + gtt_offset,
- src_vaddr + user_offset,
- length);
- kunmap_atomic(src_vaddr, KM_USER1);
- io_mapping_unmap_atomic(dst_vaddr);
- if (unwritten)
- return -EFAULT;
- return 0;
+ dst_vaddr = io_mapping_map_wc(mapping, gtt_base);
+ src_vaddr = kmap(user_page);
+
+ memcpy_toio(dst_vaddr + gtt_offset,
+ src_vaddr + user_offset,
+ length);
+
+ kunmap(user_page);
+ io_mapping_unmap(dst_vaddr);
}
static inline int
@@ -722,18 +699,11 @@
if ((data_page_offset + page_length) > PAGE_SIZE)
page_length = PAGE_SIZE - data_page_offset;
- ret = slow_kernel_write(dev_priv->mm.gtt_mapping,
- gtt_page_base, gtt_page_offset,
- user_pages[data_page_index],
- data_page_offset,
- page_length);
-
- /* If we get a fault while copying data, then (presumably) our
- * source page isn't available. Return the error and we'll
- * retry in the slow path.
- */
- if (ret)
- goto out_unpin_object;
+ slow_kernel_write(dev_priv->mm.gtt_mapping,
+ gtt_page_base, gtt_page_offset,
+ user_pages[data_page_index],
+ data_page_offset,
+ page_length);
remain -= page_length;
offset += page_length;
@@ -902,21 +872,19 @@
page_length = PAGE_SIZE - data_page_offset;
if (do_bit17_swizzling) {
- ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
- shmem_page_offset,
- user_pages[data_page_index],
- data_page_offset,
- page_length,
- 0);
- } else {
- ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
+ slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
shmem_page_offset,
user_pages[data_page_index],
data_page_offset,
- page_length);
+ page_length,
+ 0);
+ } else {
+ slow_shmem_copy(obj_priv->pages[shmem_page_index],
+ shmem_page_offset,
+ user_pages[data_page_index],
+ data_page_offset,
+ page_length);
}
- if (ret)
- goto fail_put_pages;
remain -= page_length;
data_ptr += page_length;
@@ -973,7 +941,8 @@
if (obj_priv->phys_obj)
ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
else if (obj_priv->tiling_mode == I915_TILING_NONE &&
- dev->gtt_total != 0) {
+ dev->gtt_total != 0 &&
+ obj->write_domain != I915_GEM_DOMAIN_CPU) {
ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv);
if (ret == -EFAULT) {
ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
@@ -1484,11 +1453,14 @@
}
static void
-i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
+i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno,
+ struct intel_ring_buffer *ring)
{
struct drm_device *dev = obj->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+ BUG_ON(ring == NULL);
+ obj_priv->ring = ring;
/* Add a reference if we're newly entering the active list. */
if (!obj_priv->active) {
@@ -1497,8 +1469,7 @@
}
/* Move from whatever list we were on to the tail of execution. */
spin_lock(&dev_priv->mm.active_list_lock);
- list_move_tail(&obj_priv->list,
- &dev_priv->mm.active_list);
+ list_move_tail(&obj_priv->list, &ring->active_list);
spin_unlock(&dev_priv->mm.active_list_lock);
obj_priv->last_rendering_seqno = seqno;
}
@@ -1551,6 +1522,7 @@
BUG_ON(!list_empty(&obj_priv->gpu_write_list));
obj_priv->last_rendering_seqno = 0;
+ obj_priv->ring = NULL;
if (obj_priv->active) {
obj_priv->active = 0;
drm_gem_object_unreference(obj);
@@ -1560,7 +1532,8 @@
static void
i915_gem_process_flushing_list(struct drm_device *dev,
- uint32_t flush_domains, uint32_t seqno)
+ uint32_t flush_domains, uint32_t seqno,
+ struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj_priv, *next;
@@ -1571,12 +1544,13 @@
struct drm_gem_object *obj = &obj_priv->base;
if ((obj->write_domain & flush_domains) ==
- obj->write_domain) {
+ obj->write_domain &&
+ obj_priv->ring->ring_flag == ring->ring_flag) {
uint32_t old_write_domain = obj->write_domain;
obj->write_domain = 0;
list_del_init(&obj_priv->gpu_write_list);
- i915_gem_object_move_to_active(obj, seqno);
+ i915_gem_object_move_to_active(obj, seqno, ring);
/* update the fence lru list */
if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
@@ -1593,31 +1567,15 @@
}
}
-#define PIPE_CONTROL_FLUSH(addr) \
- OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
- PIPE_CONTROL_DEPTH_STALL); \
- OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT); \
- OUT_RING(0); \
- OUT_RING(0); \
-
-/**
- * Creates a new sequence number, emitting a write of it to the status page
- * plus an interrupt, which will trigger i915_user_interrupt_handler.
- *
- * Must be called with struct_lock held.
- *
- * Returned sequence numbers are nonzero on success.
- */
uint32_t
i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
- uint32_t flush_domains)
+ uint32_t flush_domains, struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_file_private *i915_file_priv = NULL;
struct drm_i915_gem_request *request;
uint32_t seqno;
int was_empty;
- RING_LOCALS;
if (file_priv != NULL)
i915_file_priv = file_priv->driver_priv;
@@ -1626,62 +1584,14 @@
if (request == NULL)
return 0;
- /* Grab the seqno we're going to make this request be, and bump the
- * next (skipping 0 so it can be the reserved no-seqno value).
- */
- seqno = dev_priv->mm.next_gem_seqno;
- dev_priv->mm.next_gem_seqno++;
- if (dev_priv->mm.next_gem_seqno == 0)
- dev_priv->mm.next_gem_seqno++;
-
- if (HAS_PIPE_CONTROL(dev)) {
- u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
-
- /*
- * Workaround qword write incoherence by flushing the
- * PIPE_NOTIFY buffers out to memory before requesting
- * an interrupt.
- */
- BEGIN_LP_RING(32);
- OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
- PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
- OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
- OUT_RING(seqno);
- OUT_RING(0);
- PIPE_CONTROL_FLUSH(scratch_addr);
- scratch_addr += 128; /* write to separate cachelines */
- PIPE_CONTROL_FLUSH(scratch_addr);
- scratch_addr += 128;
- PIPE_CONTROL_FLUSH(scratch_addr);
- scratch_addr += 128;
- PIPE_CONTROL_FLUSH(scratch_addr);
- scratch_addr += 128;
- PIPE_CONTROL_FLUSH(scratch_addr);
- scratch_addr += 128;
- PIPE_CONTROL_FLUSH(scratch_addr);
- OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
- PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
- PIPE_CONTROL_NOTIFY);
- OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
- OUT_RING(seqno);
- OUT_RING(0);
- ADVANCE_LP_RING();
- } else {
- BEGIN_LP_RING(4);
- OUT_RING(MI_STORE_DWORD_INDEX);
- OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
- OUT_RING(seqno);
-
- OUT_RING(MI_USER_INTERRUPT);
- ADVANCE_LP_RING();
- }
-
- DRM_DEBUG_DRIVER("%d\n", seqno);
+ seqno = ring->add_request(dev, ring, file_priv, flush_domains);
request->seqno = seqno;
+ request->ring = ring;
request->emitted_jiffies = jiffies;
- was_empty = list_empty(&dev_priv->mm.request_list);
- list_add_tail(&request->list, &dev_priv->mm.request_list);
+ was_empty = list_empty(&ring->request_list);
+ list_add_tail(&request->list, &ring->request_list);
+
if (i915_file_priv) {
list_add_tail(&request->client_list,
&i915_file_priv->mm.request_list);
@@ -1693,7 +1603,7 @@
* domain we're flushing with our flush.
*/
if (flush_domains != 0)
- i915_gem_process_flushing_list(dev, flush_domains, seqno);
+ i915_gem_process_flushing_list(dev, flush_domains, seqno, ring);
if (!dev_priv->mm.suspended) {
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
@@ -1710,20 +1620,16 @@
* before signalling the CPU
*/
static uint32_t
-i915_retire_commands(struct drm_device *dev)
+i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
uint32_t flush_domains = 0;
- RING_LOCALS;
/* The sampler always gets flushed on i965 (sigh) */
if (IS_I965G(dev))
flush_domains |= I915_GEM_DOMAIN_SAMPLER;
- BEGIN_LP_RING(2);
- OUT_RING(cmd);
- OUT_RING(0); /* noop */
- ADVANCE_LP_RING();
+
+ ring->flush(dev, ring,
+ I915_GEM_DOMAIN_COMMAND, flush_domains);
return flush_domains;
}
@@ -1743,11 +1649,11 @@
* by the ringbuffer to the flushing/inactive lists as appropriate.
*/
spin_lock(&dev_priv->mm.active_list_lock);
- while (!list_empty(&dev_priv->mm.active_list)) {
+ while (!list_empty(&request->ring->active_list)) {
struct drm_gem_object *obj;
struct drm_i915_gem_object *obj_priv;
- obj_priv = list_first_entry(&dev_priv->mm.active_list,
+ obj_priv = list_first_entry(&request->ring->active_list,
struct drm_i915_gem_object,
list);
obj = &obj_priv->base;
@@ -1794,35 +1700,33 @@
}
uint32_t
-i915_get_gem_seqno(struct drm_device *dev)
+i915_get_gem_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- if (HAS_PIPE_CONTROL(dev))
- return ((volatile u32 *)(dev_priv->seqno_page))[0];
- else
- return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
+ return ring->get_gem_seqno(dev, ring);
}
/**
* This function clears the request list as sequence numbers are passed.
*/
void
-i915_gem_retire_requests(struct drm_device *dev)
+i915_gem_retire_requests(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t seqno;
- if (!dev_priv->hw_status_page || list_empty(&dev_priv->mm.request_list))
+ if (!ring->status_page.page_addr
+ || list_empty(&ring->request_list))
return;
- seqno = i915_get_gem_seqno(dev);
+ seqno = i915_get_gem_seqno(dev, ring);
- while (!list_empty(&dev_priv->mm.request_list)) {
+ while (!list_empty(&ring->request_list)) {
struct drm_i915_gem_request *request;
uint32_t retiring_seqno;
- request = list_first_entry(&dev_priv->mm.request_list,
+ request = list_first_entry(&ring->request_list,
struct drm_i915_gem_request,
list);
retiring_seqno = request->seqno;
@@ -1840,7 +1744,8 @@
if (unlikely (dev_priv->trace_irq_seqno &&
i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
- i915_user_irq_put(dev);
+
+ ring->user_irq_put(dev, ring);
dev_priv->trace_irq_seqno = 0;
}
}
@@ -1856,15 +1761,22 @@
dev = dev_priv->dev;
mutex_lock(&dev->struct_mutex);
- i915_gem_retire_requests(dev);
+ i915_gem_retire_requests(dev, &dev_priv->render_ring);
+
+ if (HAS_BSD(dev))
+ i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
+
if (!dev_priv->mm.suspended &&
- !list_empty(&dev_priv->mm.request_list))
+ (!list_empty(&dev_priv->render_ring.request_list) ||
+ (HAS_BSD(dev) &&
+ !list_empty(&dev_priv->bsd_ring.request_list))))
queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
mutex_unlock(&dev->struct_mutex);
}
int
-i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
+i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
+ int interruptible, struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 ier;
@@ -1875,7 +1787,7 @@
if (atomic_read(&dev_priv->mm.wedged))
return -EIO;
- if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
+ if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) {
if (HAS_PCH_SPLIT(dev))
ier = I915_READ(DEIER) | I915_READ(GTIER);
else
@@ -1889,19 +1801,21 @@
trace_i915_gem_request_wait_begin(dev, seqno);
- dev_priv->mm.waiting_gem_seqno = seqno;
- i915_user_irq_get(dev);
+ ring->waiting_gem_seqno = seqno;
+ ring->user_irq_get(dev, ring);
if (interruptible)
- ret = wait_event_interruptible(dev_priv->irq_queue,
- i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
- atomic_read(&dev_priv->mm.wedged));
+ ret = wait_event_interruptible(ring->irq_queue,
+ i915_seqno_passed(
+ ring->get_gem_seqno(dev, ring), seqno)
+ || atomic_read(&dev_priv->mm.wedged));
else
- wait_event(dev_priv->irq_queue,
- i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
- atomic_read(&dev_priv->mm.wedged));
+ wait_event(ring->irq_queue,
+ i915_seqno_passed(
+ ring->get_gem_seqno(dev, ring), seqno)
+ || atomic_read(&dev_priv->mm.wedged));
- i915_user_irq_put(dev);
- dev_priv->mm.waiting_gem_seqno = 0;
+ ring->user_irq_put(dev, ring);
+ ring->waiting_gem_seqno = 0;
trace_i915_gem_request_wait_end(dev, seqno);
}
@@ -1910,7 +1824,7 @@
if (ret && ret != -ERESTARTSYS)
DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
- __func__, ret, seqno, i915_get_gem_seqno(dev));
+ __func__, ret, seqno, ring->get_gem_seqno(dev, ring));
/* Directly dispatch request retiring. While we have the work queue
* to handle this, the waiter on a request often wants an associated
@@ -1918,7 +1832,7 @@
* a separate wait queue to handle that.
*/
if (ret == 0)
- i915_gem_retire_requests(dev);
+ i915_gem_retire_requests(dev, ring);
return ret;
}
@@ -1928,9 +1842,10 @@
* request and object lists appropriately for that event.
*/
static int
-i915_wait_request(struct drm_device *dev, uint32_t seqno)
+i915_wait_request(struct drm_device *dev, uint32_t seqno,
+ struct intel_ring_buffer *ring)
{
- return i915_do_wait_request(dev, seqno, 1);
+ return i915_do_wait_request(dev, seqno, 1, ring);
}
static void
@@ -1939,71 +1854,29 @@
uint32_t flush_domains)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- uint32_t cmd;
- RING_LOCALS;
-
-#if WATCH_EXEC
- DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
- invalidate_domains, flush_domains);
-#endif
- trace_i915_gem_request_flush(dev, dev_priv->mm.next_gem_seqno,
- invalidate_domains, flush_domains);
-
if (flush_domains & I915_GEM_DOMAIN_CPU)
drm_agp_chipset_flush(dev);
+ dev_priv->render_ring.flush(dev, &dev_priv->render_ring,
+ invalidate_domains,
+ flush_domains);
- if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
- /*
- * read/write caches:
- *
- * I915_GEM_DOMAIN_RENDER is always invalidated, but is
- * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is
- * also flushed at 2d versus 3d pipeline switches.
- *
- * read-only caches:
- *
- * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
- * MI_READ_FLUSH is set, and is always flushed on 965.
- *
- * I915_GEM_DOMAIN_COMMAND may not exist?
- *
- * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
- * invalidated when MI_EXE_FLUSH is set.
- *
- * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
- * invalidated with every MI_FLUSH.
- *
- * TLBs:
- *
- * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
- * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
- * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
- * are flushed at any MI_FLUSH.
- */
+ if (HAS_BSD(dev))
+ dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring,
+ invalidate_domains,
+ flush_domains);
+}
- cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
- if ((invalidate_domains|flush_domains) &
- I915_GEM_DOMAIN_RENDER)
- cmd &= ~MI_NO_WRITE_FLUSH;
- if (!IS_I965G(dev)) {
- /*
- * On the 965, the sampler cache always gets flushed
- * and this bit is reserved.
- */
- if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
- cmd |= MI_READ_FLUSH;
- }
- if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
- cmd |= MI_EXE_FLUSH;
-
-#if WATCH_EXEC
- DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
-#endif
- BEGIN_LP_RING(2);
- OUT_RING(cmd);
- OUT_RING(MI_NOOP);
- ADVANCE_LP_RING();
- }
+static void
+i915_gem_flush_ring(struct drm_device *dev,
+ uint32_t invalidate_domains,
+ uint32_t flush_domains,
+ struct intel_ring_buffer *ring)
+{
+ if (flush_domains & I915_GEM_DOMAIN_CPU)
+ drm_agp_chipset_flush(dev);
+ ring->flush(dev, ring,
+ invalidate_domains,
+ flush_domains);
}
/**
@@ -2030,7 +1903,8 @@
DRM_INFO("%s: object %p wait for seqno %08x\n",
__func__, obj, obj_priv->last_rendering_seqno);
#endif
- ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
+ ret = i915_wait_request(dev,
+ obj_priv->last_rendering_seqno, obj_priv->ring);
if (ret != 0)
return ret;
}
@@ -2146,11 +2020,14 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
bool lists_empty;
- uint32_t seqno;
+ uint32_t seqno1, seqno2;
+ int ret;
spin_lock(&dev_priv->mm.active_list_lock);
- lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
- list_empty(&dev_priv->mm.active_list);
+ lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
+ list_empty(&dev_priv->render_ring.active_list) &&
+ (!HAS_BSD(dev) ||
+ list_empty(&dev_priv->bsd_ring.active_list)));
spin_unlock(&dev_priv->mm.active_list_lock);
if (lists_empty)
@@ -2158,11 +2035,25 @@
/* Flush everything onto the inactive list. */
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)
+ seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
+ &dev_priv->render_ring);
+ if (seqno1 == 0)
return -ENOMEM;
+ ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring);
- return i915_wait_request(dev, seqno);
+ if (HAS_BSD(dev)) {
+ seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
+ &dev_priv->bsd_ring);
+ if (seqno2 == 0)
+ return -ENOMEM;
+
+ ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring);
+ if (ret)
+ return ret;
+ }
+
+
+ return ret;
}
static int
@@ -2175,7 +2066,9 @@
spin_lock(&dev_priv->mm.active_list_lock);
lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
list_empty(&dev_priv->mm.flushing_list) &&
- list_empty(&dev_priv->mm.active_list));
+ list_empty(&dev_priv->render_ring.active_list) &&
+ (!HAS_BSD(dev)
+ || list_empty(&dev_priv->bsd_ring.active_list)));
spin_unlock(&dev_priv->mm.active_list_lock);
if (lists_empty)
@@ -2195,7 +2088,9 @@
spin_lock(&dev_priv->mm.active_list_lock);
lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
list_empty(&dev_priv->mm.flushing_list) &&
- list_empty(&dev_priv->mm.active_list));
+ list_empty(&dev_priv->render_ring.active_list) &&
+ (!HAS_BSD(dev)
+ || list_empty(&dev_priv->bsd_ring.active_list)));
spin_unlock(&dev_priv->mm.active_list_lock);
BUG_ON(!lists_empty);
@@ -2209,8 +2104,13 @@
struct drm_gem_object *obj;
int ret;
+ struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
+ struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
for (;;) {
- i915_gem_retire_requests(dev);
+ i915_gem_retire_requests(dev, render_ring);
+
+ if (HAS_BSD(dev))
+ i915_gem_retire_requests(dev, bsd_ring);
/* If there's an inactive buffer available now, grab it
* and be done.
@@ -2234,14 +2134,30 @@
* things, wait for the next to finish and hopefully leave us
* a buffer to evict.
*/
- if (!list_empty(&dev_priv->mm.request_list)) {
+ if (!list_empty(&render_ring->request_list)) {
struct drm_i915_gem_request *request;
- request = list_first_entry(&dev_priv->mm.request_list,
+ request = list_first_entry(&render_ring->request_list,
struct drm_i915_gem_request,
list);
- ret = i915_wait_request(dev, request->seqno);
+ ret = i915_wait_request(dev,
+ request->seqno, request->ring);
+ if (ret)
+ return ret;
+
+ continue;
+ }
+
+ if (HAS_BSD(dev) && !list_empty(&bsd_ring->request_list)) {
+ struct drm_i915_gem_request *request;
+
+ request = list_first_entry(&bsd_ring->request_list,
+ struct drm_i915_gem_request,
+ list);
+
+ ret = i915_wait_request(dev,
+ request->seqno, request->ring);
if (ret)
return ret;
@@ -2268,10 +2184,13 @@
if (obj != NULL) {
uint32_t seqno;
- i915_gem_flush(dev,
+ i915_gem_flush_ring(dev,
obj->write_domain,
- obj->write_domain);
- seqno = i915_add_request(dev, NULL, obj->write_domain);
+ obj->write_domain,
+ obj_priv->ring);
+ seqno = i915_add_request(dev, NULL,
+ obj->write_domain,
+ obj_priv->ring);
if (seqno == 0)
return -ENOMEM;
continue;
@@ -2299,6 +2218,9 @@
struct inode *inode;
struct page *page;
+ BUG_ON(obj_priv->pages_refcount
+ == DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT);
+
if (obj_priv->pages_refcount++ != 0)
return 0;
@@ -2697,6 +2619,14 @@
return -EINVAL;
}
+ /* If the object is bigger than the entire aperture, reject it early
+ * before evicting everything in a vain attempt to find space.
+ */
+ if (obj->size > dev->gtt_total) {
+ DRM_ERROR("Attempting to bind an object larger than the aperture\n");
+ return -E2BIG;
+ }
+
search_free:
free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
obj->size, alignment, 0);
@@ -2807,6 +2737,7 @@
{
struct drm_device *dev = obj->dev;
uint32_t old_write_domain;
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
return;
@@ -2814,7 +2745,7 @@
/* Queue the GPU write cache flushing we need. */
old_write_domain = obj->write_domain;
i915_gem_flush(dev, 0, obj->write_domain);
- (void) i915_add_request(dev, NULL, obj->write_domain);
+ (void) i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring);
BUG_ON(obj->write_domain);
trace_i915_gem_object_change_domain(obj,
@@ -2954,23 +2885,24 @@
DRM_INFO("%s: object %p wait for seqno %08x\n",
__func__, obj, obj_priv->last_rendering_seqno);
#endif
- ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0);
+ ret = i915_do_wait_request(dev,
+ obj_priv->last_rendering_seqno,
+ 0,
+ obj_priv->ring);
if (ret != 0)
return ret;
}
+ i915_gem_object_flush_cpu_write_domain(obj);
+
old_write_domain = obj->write_domain;
old_read_domains = obj->read_domains;
- obj->read_domains &= I915_GEM_DOMAIN_GTT;
-
- i915_gem_object_flush_cpu_write_domain(obj);
-
/* It should now be out of any other write domains, and we can update
* the domain values for our changes.
*/
BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
- obj->read_domains |= I915_GEM_DOMAIN_GTT;
+ obj->read_domains = I915_GEM_DOMAIN_GTT;
obj->write_domain = I915_GEM_DOMAIN_GTT;
obj_priv->dirty = 1;
@@ -3354,9 +3286,13 @@
obj_priv->tiling_mode != I915_TILING_NONE;
/* Check fence reg constraints and rebind if necessary */
- if (need_fence && !i915_gem_object_fence_offset_ok(obj,
- obj_priv->tiling_mode))
- i915_gem_object_unbind(obj);
+ if (need_fence &&
+ !i915_gem_object_fence_offset_ok(obj,
+ obj_priv->tiling_mode)) {
+ ret = i915_gem_object_unbind(obj);
+ if (ret)
+ return ret;
+ }
/* Choose the GTT offset for our buffer and put it there. */
ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
@@ -3370,9 +3306,6 @@
if (need_fence) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret != 0) {
- if (ret != -EBUSY && ret != -ERESTARTSYS)
- DRM_ERROR("Failure to install fence: %d\n",
- ret);
i915_gem_object_unpin(obj);
return ret;
}
@@ -3545,62 +3478,6 @@
return 0;
}
-/** Dispatch a batchbuffer to the ring
- */
-static int
-i915_dispatch_gem_execbuffer(struct drm_device *dev,
- struct drm_i915_gem_execbuffer2 *exec,
- struct drm_clip_rect *cliprects,
- uint64_t exec_offset)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- int nbox = exec->num_cliprects;
- int i = 0, count;
- uint32_t exec_start, exec_len;
- RING_LOCALS;
-
- exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
- exec_len = (uint32_t) exec->batch_len;
-
- trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
-
- count = nbox ? nbox : 1;
-
- for (i = 0; i < count; i++) {
- if (i < nbox) {
- int ret = i915_emit_box(dev, cliprects, i,
- exec->DR1, exec->DR4);
- if (ret)
- return ret;
- }
-
- if (IS_I830(dev) || IS_845G(dev)) {
- BEGIN_LP_RING(4);
- OUT_RING(MI_BATCH_BUFFER);
- OUT_RING(exec_start | MI_BATCH_NON_SECURE);
- OUT_RING(exec_start + exec_len - 4);
- OUT_RING(0);
- ADVANCE_LP_RING();
- } else {
- BEGIN_LP_RING(2);
- if (IS_I965G(dev)) {
- OUT_RING(MI_BATCH_BUFFER_START |
- (2 << 6) |
- MI_BATCH_NON_SECURE_I965);
- OUT_RING(exec_start);
- } else {
- OUT_RING(MI_BATCH_BUFFER_START |
- (2 << 6));
- OUT_RING(exec_start | MI_BATCH_NON_SECURE);
- }
- ADVANCE_LP_RING();
- }
- }
-
- /* XXX breadcrumb */
- return 0;
-}
-
/* Throttle our rendering by waiting until the ring has completed our requests
* emitted over 20 msec ago.
*
@@ -3629,7 +3506,7 @@
if (time_after_eq(request->emitted_jiffies, recent_enough))
break;
- ret = i915_wait_request(dev, request->seqno);
+ ret = i915_wait_request(dev, request->seqno, request->ring);
if (ret != 0)
break;
}
@@ -3786,10 +3663,22 @@
uint32_t seqno, flush_domains, reloc_index;
int pin_tries, flips;
+ struct intel_ring_buffer *ring = NULL;
+
#if WATCH_EXEC
DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
(int) args->buffers_ptr, args->buffer_count, args->batch_len);
#endif
+ if (args->flags & I915_EXEC_BSD) {
+ if (!HAS_BSD(dev)) {
+ DRM_ERROR("execbuf with wrong flag\n");
+ return -EINVAL;
+ }
+ ring = &dev_priv->bsd_ring;
+ } else {
+ ring = &dev_priv->render_ring;
+ }
+
if (args->buffer_count < 1) {
DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
@@ -3902,11 +3791,19 @@
if (ret != -ENOSPC || pin_tries >= 1) {
if (ret != -ERESTARTSYS) {
unsigned long long total_size = 0;
- for (i = 0; i < args->buffer_count; i++)
+ int num_fences = 0;
+ for (i = 0; i < args->buffer_count; i++) {
+ obj_priv = object_list[i]->driver_private;
+
total_size += object_list[i]->size;
- DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes: %d\n",
+ num_fences +=
+ exec_list[i].flags & EXEC_OBJECT_NEEDS_FENCE &&
+ obj_priv->tiling_mode != I915_TILING_NONE;
+ }
+ DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes, %d fences: %d\n",
pinned+1, args->buffer_count,
- total_size, ret);
+ total_size, num_fences,
+ ret);
DRM_ERROR("%d objects [%d pinned], "
"%d object bytes [%d pinned], "
"%d/%d gtt bytes\n",
@@ -3976,9 +3873,16 @@
i915_gem_flush(dev,
dev->invalidate_domains,
dev->flush_domains);
- if (dev->flush_domains & I915_GEM_GPU_DOMAINS)
+ if (dev->flush_domains & I915_GEM_GPU_DOMAINS) {
(void)i915_add_request(dev, file_priv,
- dev->flush_domains);
+ dev->flush_domains,
+ &dev_priv->render_ring);
+
+ if (HAS_BSD(dev))
+ (void)i915_add_request(dev, file_priv,
+ dev->flush_domains,
+ &dev_priv->bsd_ring);
+ }
}
for (i = 0; i < args->buffer_count; i++) {
@@ -4015,7 +3919,8 @@
#endif
/* Exec the batchbuffer */
- ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset);
+ ret = ring->dispatch_gem_execbuffer(dev, ring, args,
+ cliprects, exec_offset);
if (ret) {
DRM_ERROR("dispatch failed %d\n", ret);
goto err;
@@ -4025,7 +3930,7 @@
* Ensure that the commands in the batch buffer are
* finished before the interrupt fires
*/
- flush_domains = i915_retire_commands(dev);
+ flush_domains = i915_retire_commands(dev, ring);
i915_verify_inactive(dev, __FILE__, __LINE__);
@@ -4036,12 +3941,13 @@
* *some* interrupts representing completion of buffers that we can
* wait on when trying to clear up gtt space).
*/
- seqno = i915_add_request(dev, file_priv, flush_domains);
+ seqno = i915_add_request(dev, file_priv, flush_domains, ring);
BUG_ON(seqno == 0);
for (i = 0; i < args->buffer_count; i++) {
struct drm_gem_object *obj = object_list[i];
+ obj_priv = to_intel_bo(obj);
- i915_gem_object_move_to_active(obj, seqno);
+ i915_gem_object_move_to_active(obj, seqno, ring);
#if WATCH_LRU
DRM_INFO("%s: move to exec list %p\n", __func__, obj);
#endif
@@ -4153,7 +4059,7 @@
exec2.DR4 = args->DR4;
exec2.num_cliprects = args->num_cliprects;
exec2.cliprects_ptr = args->cliprects_ptr;
- exec2.flags = 0;
+ exec2.flags = I915_EXEC_RENDER;
ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
if (!ret) {
@@ -4239,7 +4145,20 @@
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
int ret;
+ BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
+
i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ if (obj_priv->gtt_space != NULL) {
+ if (alignment == 0)
+ alignment = i915_gem_get_gtt_alignment(obj);
+ if (obj_priv->gtt_offset & (alignment - 1)) {
+ ret = i915_gem_object_unbind(obj);
+ if (ret)
+ return ret;
+ }
+ }
+
if (obj_priv->gtt_space == NULL) {
ret = i915_gem_object_bind_to_gtt(obj, alignment);
if (ret)
@@ -4392,6 +4311,7 @@
struct drm_i915_gem_busy *args = data;
struct drm_gem_object *obj;
struct drm_i915_gem_object *obj_priv;
+ drm_i915_private_t *dev_priv = dev->dev_private;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL) {
@@ -4406,7 +4326,10 @@
* actually unmasked, and our working set ends up being larger than
* required.
*/
- i915_gem_retire_requests(dev);
+ i915_gem_retire_requests(dev, &dev_priv->render_ring);
+
+ if (HAS_BSD(dev))
+ i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
obj_priv = to_intel_bo(obj);
/* Don't count being on the flushing list against the object being
@@ -4573,7 +4496,10 @@
mutex_lock(&dev->struct_mutex);
- if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
+ if (dev_priv->mm.suspended ||
+ (dev_priv->render_ring.gem_object == NULL) ||
+ (HAS_BSD(dev) &&
+ dev_priv->bsd_ring.gem_object == NULL)) {
mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -4654,71 +4580,6 @@
return ret;
}
-static int
-i915_gem_init_hws(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- struct drm_gem_object *obj;
- struct drm_i915_gem_object *obj_priv;
- int ret;
-
- /* If we need a physical address for the status page, it's already
- * initialized at driver load time.
- */
- if (!I915_NEED_GFX_HWS(dev))
- return 0;
-
- obj = i915_gem_alloc_object(dev, 4096);
- if (obj == NULL) {
- DRM_ERROR("Failed to allocate status page\n");
- ret = -ENOMEM;
- goto err;
- }
- obj_priv = to_intel_bo(obj);
- obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
-
- ret = i915_gem_object_pin(obj, 4096);
- if (ret != 0) {
- drm_gem_object_unreference(obj);
- goto err_unref;
- }
-
- dev_priv->status_gfx_addr = obj_priv->gtt_offset;
-
- dev_priv->hw_status_page = kmap(obj_priv->pages[0]);
- if (dev_priv->hw_status_page == NULL) {
- DRM_ERROR("Failed to map status page.\n");
- memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
- ret = -EINVAL;
- goto err_unpin;
- }
-
- if (HAS_PIPE_CONTROL(dev)) {
- ret = i915_gem_init_pipe_control(dev);
- if (ret)
- goto err_unpin;
- }
-
- dev_priv->hws_obj = obj;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- if (IS_GEN6(dev)) {
- I915_WRITE(HWS_PGA_GEN6, dev_priv->status_gfx_addr);
- I915_READ(HWS_PGA_GEN6); /* posting read */
- } else {
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
- I915_READ(HWS_PGA); /* posting read */
- }
- DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
-
- return 0;
-
-err_unpin:
- i915_gem_object_unpin(obj);
-err_unref:
- drm_gem_object_unreference(obj);
-err:
- return 0;
-}
static void
i915_gem_cleanup_pipe_control(struct drm_device *dev)
@@ -4737,146 +4598,46 @@
dev_priv->seqno_page = NULL;
}
-static void
-i915_gem_cleanup_hws(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- struct drm_gem_object *obj;
- struct drm_i915_gem_object *obj_priv;
-
- if (dev_priv->hws_obj == NULL)
- return;
-
- obj = dev_priv->hws_obj;
- obj_priv = to_intel_bo(obj);
-
- kunmap(obj_priv->pages[0]);
- i915_gem_object_unpin(obj);
- drm_gem_object_unreference(obj);
- dev_priv->hws_obj = NULL;
-
- memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
- dev_priv->hw_status_page = NULL;
-
- if (HAS_PIPE_CONTROL(dev))
- i915_gem_cleanup_pipe_control(dev);
-
- /* Write high address into HWS_PGA when disabling. */
- I915_WRITE(HWS_PGA, 0x1ffff000);
-}
-
int
i915_gem_init_ringbuffer(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- struct drm_gem_object *obj;
- struct drm_i915_gem_object *obj_priv;
- drm_i915_ring_buffer_t *ring = &dev_priv->ring;
int ret;
- u32 head;
- ret = i915_gem_init_hws(dev);
- if (ret != 0)
- return ret;
+ dev_priv->render_ring = render_ring;
- obj = i915_gem_alloc_object(dev, 128 * 1024);
- if (obj == NULL) {
- DRM_ERROR("Failed to allocate ringbuffer\n");
- i915_gem_cleanup_hws(dev);
- return -ENOMEM;
- }
- obj_priv = to_intel_bo(obj);
-
- ret = i915_gem_object_pin(obj, 4096);
- if (ret != 0) {
- drm_gem_object_unreference(obj);
- i915_gem_cleanup_hws(dev);
- return ret;
+ if (!I915_NEED_GFX_HWS(dev)) {
+ dev_priv->render_ring.status_page.page_addr
+ = dev_priv->status_page_dmah->vaddr;
+ memset(dev_priv->render_ring.status_page.page_addr,
+ 0, PAGE_SIZE);
}
- /* Set up the kernel mapping for the ring. */
- ring->Size = obj->size;
-
- ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
- ring->map.size = obj->size;
- ring->map.type = 0;
- ring->map.flags = 0;
- ring->map.mtrr = 0;
-
- drm_core_ioremap_wc(&ring->map, dev);
- if (ring->map.handle == NULL) {
- DRM_ERROR("Failed to map ringbuffer.\n");
- memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
- i915_gem_object_unpin(obj);
- drm_gem_object_unreference(obj);
- i915_gem_cleanup_hws(dev);
- return -EINVAL;
- }
- ring->ring_obj = obj;
- ring->virtual_start = ring->map.handle;
-
- /* Stop the ring if it's running. */
- I915_WRITE(PRB0_CTL, 0);
- I915_WRITE(PRB0_TAIL, 0);
- I915_WRITE(PRB0_HEAD, 0);
-
- /* Initialize the ring. */
- I915_WRITE(PRB0_START, obj_priv->gtt_offset);
- head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-
- /* G45 ring initialization fails to reset head to zero */
- if (head != 0) {
- DRM_ERROR("Ring head not reset to zero "
- "ctl %08x head %08x tail %08x start %08x\n",
- I915_READ(PRB0_CTL),
- I915_READ(PRB0_HEAD),
- I915_READ(PRB0_TAIL),
- I915_READ(PRB0_START));
- I915_WRITE(PRB0_HEAD, 0);
-
- DRM_ERROR("Ring head forced to zero "
- "ctl %08x head %08x tail %08x start %08x\n",
- I915_READ(PRB0_CTL),
- I915_READ(PRB0_HEAD),
- I915_READ(PRB0_TAIL),
- I915_READ(PRB0_START));
+ if (HAS_PIPE_CONTROL(dev)) {
+ ret = i915_gem_init_pipe_control(dev);
+ if (ret)
+ return ret;
}
- I915_WRITE(PRB0_CTL,
- ((obj->size - 4096) & RING_NR_PAGES) |
- RING_NO_REPORT |
- RING_VALID);
+ ret = intel_init_ring_buffer(dev, &dev_priv->render_ring);
+ if (ret)
+ goto cleanup_pipe_control;
- head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-
- /* If the head is still not zero, the ring is dead */
- if (head != 0) {
- DRM_ERROR("Ring initialization failed "
- "ctl %08x head %08x tail %08x start %08x\n",
- I915_READ(PRB0_CTL),
- I915_READ(PRB0_HEAD),
- I915_READ(PRB0_TAIL),
- I915_READ(PRB0_START));
- return -EIO;
- }
-
- /* Update our cache of the ring state */
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- i915_kernel_lost_context(dev);
- else {
- ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
- ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
- ring->space = ring->head - (ring->tail + 8);
- if (ring->space < 0)
- ring->space += ring->Size;
- }
-
- if (IS_I9XX(dev) && !IS_GEN3(dev)) {
- I915_WRITE(MI_MODE,
- (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
+ if (HAS_BSD(dev)) {
+ dev_priv->bsd_ring = bsd_ring;
+ ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
+ if (ret)
+ goto cleanup_render_ring;
}
return 0;
+
+cleanup_render_ring:
+ intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
+cleanup_pipe_control:
+ if (HAS_PIPE_CONTROL(dev))
+ i915_gem_cleanup_pipe_control(dev);
+ return ret;
}
void
@@ -4884,17 +4645,11 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
- if (dev_priv->ring.ring_obj == NULL)
- return;
-
- drm_core_ioremapfree(&dev_priv->ring.map, dev);
-
- i915_gem_object_unpin(dev_priv->ring.ring_obj);
- drm_gem_object_unreference(dev_priv->ring.ring_obj);
- dev_priv->ring.ring_obj = NULL;
- memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-
- i915_gem_cleanup_hws(dev);
+ intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
+ if (HAS_BSD(dev))
+ intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+ if (HAS_PIPE_CONTROL(dev))
+ i915_gem_cleanup_pipe_control(dev);
}
int
@@ -4922,12 +4677,14 @@
}
spin_lock(&dev_priv->mm.active_list_lock);
- BUG_ON(!list_empty(&dev_priv->mm.active_list));
+ BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
+ BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list));
spin_unlock(&dev_priv->mm.active_list_lock);
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
- BUG_ON(!list_empty(&dev_priv->mm.request_list));
+ BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
+ BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
mutex_unlock(&dev->struct_mutex);
drm_irq_install(dev);
@@ -4966,18 +4723,20 @@
drm_i915_private_t *dev_priv = dev->dev_private;
spin_lock_init(&dev_priv->mm.active_list_lock);
- INIT_LIST_HEAD(&dev_priv->mm.active_list);
INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
INIT_LIST_HEAD(&dev_priv->mm.gpu_write_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_LIST_HEAD(&dev_priv->render_ring.active_list);
+ INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
+ if (HAS_BSD(dev)) {
+ INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list);
+ INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list);
+ }
for (i = 0; i < 16; i++)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler);
- dev_priv->mm.next_gem_seqno = 1;
-
spin_lock(&shrink_list_lock);
list_add(&dev_priv->mm.shrink_list, &shrink_list);
spin_unlock(&shrink_list_lock);
@@ -5209,7 +4968,9 @@
spin_lock(&dev_priv->mm.active_list_lock);
lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
- list_empty(&dev_priv->mm.active_list);
+ list_empty(&dev_priv->render_ring.active_list);
+ if (HAS_BSD(dev))
+ lists_empty &= list_empty(&dev_priv->bsd_ring.active_list);
spin_unlock(&dev_priv->mm.active_list_lock);
return !lists_empty;
@@ -5254,8 +5015,10 @@
continue;
spin_unlock(&shrink_list_lock);
+ i915_gem_retire_requests(dev, &dev_priv->render_ring);
- i915_gem_retire_requests(dev);
+ if (HAS_BSD(dev))
+ i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
list_for_each_entry_safe(obj_priv, next_obj,
&dev_priv->mm.inactive_list,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8c3f080..2479be0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -53,7 +53,7 @@
I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
/** Interrupts that we mask and unmask at runtime. */
-#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT)
#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\
PIPE_VBLANK_INTERRUPT_STATUS)
@@ -74,7 +74,7 @@
}
}
-static inline void
+void
ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
@@ -115,7 +115,7 @@
}
}
-static inline void
+void
i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->irq_mask_reg & mask) != mask) {
@@ -278,10 +278,9 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 busy_up, busy_down, max_avg, min_avg;
- u16 rgvswctl;
u8 new_delay = dev_priv->cur_delay;
- I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG);
+ I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
busy_up = I915_READ(RCPREVBSYTUPAVG);
busy_down = I915_READ(RCPREVBSYTDNAVG);
max_avg = I915_READ(RCBMAXAVG);
@@ -300,27 +299,8 @@
new_delay = dev_priv->min_delay;
}
- DRM_DEBUG("rps change requested: %d -> %d\n",
- dev_priv->cur_delay, new_delay);
-
- rgvswctl = I915_READ(MEMSWCTL);
- if (rgvswctl & MEMCTL_CMD_STS) {
- DRM_ERROR("gpu busy, RCS change rejected\n");
- return; /* still busy with another command */
- }
-
- /* Program the new state */
- rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
- (new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
- I915_WRITE(MEMSWCTL, rgvswctl);
- POSTING_READ(MEMSWCTL);
-
- rgvswctl |= MEMCTL_CMD_STS;
- I915_WRITE(MEMSWCTL, rgvswctl);
-
- dev_priv->cur_delay = new_delay;
-
- DRM_DEBUG("rps changed\n");
+ if (ironlake_set_drps(dev, new_delay))
+ dev_priv->cur_delay = new_delay;
return;
}
@@ -331,6 +311,7 @@
int ret = IRQ_NONE;
u32 de_iir, gt_iir, de_ier, pch_iir;
struct drm_i915_master_private *master_priv;
+ struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
/* disable master interrupt before clearing iir */
de_ier = I915_READ(DEIER);
@@ -354,13 +335,16 @@
}
if (gt_iir & GT_PIPE_NOTIFY) {
- u32 seqno = i915_get_gem_seqno(dev);
- dev_priv->mm.irq_gem_seqno = seqno;
+ u32 seqno = render_ring->get_gem_seqno(dev, render_ring);
+ render_ring->irq_gem_seqno = seqno;
trace_i915_gem_request_complete(dev, seqno);
- DRM_WAKEUP(&dev_priv->irq_queue);
+ DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
dev_priv->hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
}
+ if (gt_iir & GT_BSD_USER_INTERRUPT)
+ DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+
if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev);
@@ -388,7 +372,7 @@
}
if (de_iir & DE_PCU_EVENT) {
- I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS));
+ I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
i915_handle_rps_change(dev);
}
@@ -536,17 +520,18 @@
*/
bbaddr = 0;
head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
- ring = (u32 *)(dev_priv->ring.virtual_start + head);
+ ring = (u32 *)(dev_priv->render_ring.virtual_start + head);
- while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
+ while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
bbaddr = i915_get_bbaddr(dev, ring);
if (bbaddr)
break;
}
if (bbaddr == 0) {
- ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size);
- while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
+ ring = (u32 *)(dev_priv->render_ring.virtual_start
+ + dev_priv->render_ring.size);
+ while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
bbaddr = i915_get_bbaddr(dev, ring);
if (bbaddr)
break;
@@ -587,7 +572,7 @@
return;
}
- error->seqno = i915_get_gem_seqno(dev);
+ error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring);
error->eir = I915_READ(EIR);
error->pgtbl_er = I915_READ(PGTBL_ER);
error->pipeastat = I915_READ(PIPEASTAT);
@@ -615,7 +600,9 @@
batchbuffer[0] = NULL;
batchbuffer[1] = NULL;
count = 0;
- list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+ list_for_each_entry(obj_priv,
+ &dev_priv->render_ring.active_list, list) {
+
struct drm_gem_object *obj = &obj_priv->base;
if (batchbuffer[0] == NULL &&
@@ -639,7 +626,8 @@
error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
/* Record the ringbuffer */
- error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj);
+ error->ringbuffer = i915_error_object_create(dev,
+ dev_priv->render_ring.gem_object);
/* Record buffers on the active list. */
error->active_bo = NULL;
@@ -651,7 +639,8 @@
if (error->active_bo) {
int i = 0;
- list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+ list_for_each_entry(obj_priv,
+ &dev_priv->render_ring.active_list, list) {
struct drm_gem_object *obj = &obj_priv->base;
error->active_bo[i].size = obj->size;
@@ -703,24 +692,13 @@
i915_error_state_free(dev, error);
}
-/**
- * i915_handle_error - handle an error interrupt
- * @dev: drm device
- *
- * Do some basic checking of regsiter state at error interrupt time and
- * dump it to the syslog. Also call i915_capture_error_state() to make
- * sure we get a record and make it available in debugfs. Fire a uevent
- * so userspace knows something bad happened (should trigger collection
- * of a ring dump etc.).
- */
-static void i915_handle_error(struct drm_device *dev, bool wedged)
+static void i915_report_and_clear_eir(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 eir = I915_READ(EIR);
- u32 pipea_stats = I915_READ(PIPEASTAT);
- u32 pipeb_stats = I915_READ(PIPEBSTAT);
- i915_capture_error_state(dev);
+ if (!eir)
+ return;
printk(KERN_ERR "render error detected, EIR: 0x%08x\n",
eir);
@@ -766,6 +744,9 @@
}
if (eir & I915_ERROR_MEMORY_REFRESH) {
+ u32 pipea_stats = I915_READ(PIPEASTAT);
+ u32 pipeb_stats = I915_READ(PIPEBSTAT);
+
printk(KERN_ERR "memory refresh error\n");
printk(KERN_ERR "PIPEASTAT: 0x%08x\n",
pipea_stats);
@@ -822,6 +803,24 @@
I915_WRITE(EMR, I915_READ(EMR) | eir);
I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
}
+}
+
+/**
+ * i915_handle_error - handle an error interrupt
+ * @dev: drm device
+ *
+ * Do some basic checking of regsiter state at error interrupt time and
+ * dump it to the syslog. Also call i915_capture_error_state() to make
+ * sure we get a record and make it available in debugfs. Fire a uevent
+ * so userspace knows something bad happened (should trigger collection
+ * of a ring dump etc.).
+ */
+static void i915_handle_error(struct drm_device *dev, bool wedged)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ i915_capture_error_state(dev);
+ i915_report_and_clear_eir(dev);
if (wedged) {
atomic_set(&dev_priv->mm.wedged, 1);
@@ -829,7 +828,7 @@
/*
* Wakeup waiting processes so they don't hang
*/
- DRM_WAKEUP(&dev_priv->irq_queue);
+ DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
}
queue_work(dev_priv->wq, &dev_priv->error_work);
@@ -848,6 +847,7 @@
unsigned long irqflags;
int irq_received;
int ret = IRQ_NONE;
+ struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
atomic_inc(&dev_priv->irq_received);
@@ -928,14 +928,18 @@
}
if (iir & I915_USER_INTERRUPT) {
- u32 seqno = i915_get_gem_seqno(dev);
- dev_priv->mm.irq_gem_seqno = seqno;
+ u32 seqno =
+ render_ring->get_gem_seqno(dev, render_ring);
+ render_ring->irq_gem_seqno = seqno;
trace_i915_gem_request_complete(dev, seqno);
- DRM_WAKEUP(&dev_priv->irq_queue);
+ DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
dev_priv->hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
}
+ if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
+ DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+
if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
intel_prepare_page_flip(dev, 0);
@@ -984,7 +988,6 @@
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
- RING_LOCALS;
i915_kernel_lost_context(dev);
@@ -1006,43 +1009,13 @@
return dev_priv->counter;
}
-void i915_user_irq_get(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
- if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
- if (HAS_PCH_SPLIT(dev))
- ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
- else
- i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
- }
- spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
-}
-
-void i915_user_irq_put(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
- BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
- if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
- if (HAS_PCH_SPLIT(dev))
- ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
- else
- i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
- }
- spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
-}
-
void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
if (dev_priv->trace_irq_seqno == 0)
- i915_user_irq_get(dev);
+ render_ring->user_irq_get(dev, render_ring);
dev_priv->trace_irq_seqno = seqno;
}
@@ -1052,6 +1025,7 @@
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
int ret = 0;
+ struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
READ_BREADCRUMB(dev_priv));
@@ -1065,10 +1039,10 @@
if (master_priv->sarea_priv)
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
- i915_user_irq_get(dev);
- DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+ render_ring->user_irq_get(dev, render_ring);
+ DRM_WAIT_ON(ret, dev_priv->render_ring.irq_queue, 3 * DRM_HZ,
READ_BREADCRUMB(dev_priv) >= irq_nr);
- i915_user_irq_put(dev);
+ render_ring->user_irq_put(dev, render_ring);
if (ret == -EBUSY) {
DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
@@ -1087,7 +1061,7 @@
drm_i915_irq_emit_t *emit = data;
int result;
- if (!dev_priv || !dev_priv->ring.virtual_start) {
+ if (!dev_priv || !dev_priv->render_ring.virtual_start) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
@@ -1233,9 +1207,12 @@
return -EINVAL;
}
-struct drm_i915_gem_request *i915_get_tail_request(struct drm_device *dev) {
+struct drm_i915_gem_request *
+i915_get_tail_request(struct drm_device *dev)
+{
drm_i915_private_t *dev_priv = dev->dev_private;
- return list_entry(dev_priv->mm.request_list.prev, struct drm_i915_gem_request, list);
+ return list_entry(dev_priv->render_ring.request_list.prev,
+ struct drm_i915_gem_request, list);
}
/**
@@ -1260,8 +1237,10 @@
acthd = I915_READ(ACTHD_I965);
/* If all work is done then ACTHD clearly hasn't advanced. */
- if (list_empty(&dev_priv->mm.request_list) ||
- i915_seqno_passed(i915_get_gem_seqno(dev), i915_get_tail_request(dev)->seqno)) {
+ if (list_empty(&dev_priv->render_ring.request_list) ||
+ i915_seqno_passed(i915_get_gem_seqno(dev,
+ &dev_priv->render_ring),
+ i915_get_tail_request(dev)->seqno)) {
dev_priv->hangcheck_count = 0;
return;
}
@@ -1314,7 +1293,7 @@
/* enable kind of interrupts always enabled */
u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
- u32 render_mask = GT_PIPE_NOTIFY;
+ u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT;
u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
@@ -1328,7 +1307,7 @@
(void) I915_READ(DEIER);
/* user interrupt should be enabled, but masked initial */
- dev_priv->gt_irq_mask_reg = 0xffffffff;
+ dev_priv->gt_irq_mask_reg = ~render_mask;
dev_priv->gt_irq_enable_reg = render_mask;
I915_WRITE(GTIIR, I915_READ(GTIIR));
@@ -1391,7 +1370,10 @@
u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
u32 error_mask;
- DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+ DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue);
+
+ if (HAS_BSD(dev))
+ DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f3e39cc..64b0a3a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -334,6 +334,7 @@
#define I915_DEBUG_INTERRUPT (1<<2)
#define I915_USER_INTERRUPT (1<<1)
#define I915_ASLE_INTERRUPT (1<<0)
+#define I915_BSD_USER_INTERRUPT (1<<25)
#define EIR 0x020b0
#define EMR 0x020b4
#define ESR 0x020b8
@@ -368,6 +369,36 @@
#define BB_ADDR 0x02140 /* 8 bytes */
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
+/* GEN6 interrupt control */
+#define GEN6_RENDER_HWSTAM 0x2098
+#define GEN6_RENDER_IMR 0x20a8
+#define GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT (1 << 8)
+#define GEN6_RENDER_PPGTT_PAGE_FAULT (1 << 7)
+#define GEN6_RENDER TIMEOUT_COUNTER_EXPIRED (1 << 6)
+#define GEN6_RENDER_L3_PARITY_ERROR (1 << 5)
+#define GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT (1 << 4)
+#define GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR (1 << 3)
+#define GEN6_RENDER_SYNC_STATUS (1 << 2)
+#define GEN6_RENDER_DEBUG_INTERRUPT (1 << 1)
+#define GEN6_RENDER_USER_INTERRUPT (1 << 0)
+
+#define GEN6_BLITTER_HWSTAM 0x22098
+#define GEN6_BLITTER_IMR 0x220a8
+#define GEN6_BLITTER_MI_FLUSH_DW_NOTIFY_INTERRUPT (1 << 26)
+#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25)
+#define GEN6_BLITTER_SYNC_STATUS (1 << 24)
+#define GEN6_BLITTER_USER_INTERRUPT (1 << 22)
+/*
+ * BSD (bit stream decoder instruction and interrupt control register defines
+ * (G4X and Ironlake only)
+ */
+
+#define BSD_RING_TAIL 0x04030
+#define BSD_RING_HEAD 0x04034
+#define BSD_RING_START 0x04038
+#define BSD_RING_CTL 0x0403c
+#define BSD_RING_ACTHD 0x04074
+#define BSD_HWS_PGA 0x04080
/*
* Framebuffer compression (915+ only)
@@ -805,6 +836,10 @@
#define DCC_CHANNEL_XOR_DISABLE (1 << 10)
#define DCC_CHANNEL_XOR_BIT_17 (1 << 9)
+/** Pineview MCH register contains DDR3 setting */
+#define CSHRDDR3CTL 0x101a8
+#define CSHRDDR3CTL_DDR3 (1 << 2)
+
/** 965 MCH register controlling DRAM channel configuration */
#define C0DRB3 0x10206
#define C1DRB3 0x10606
@@ -826,6 +861,12 @@
#define CLKCFG_MEM_800 (3 << 4)
#define CLKCFG_MEM_MASK (7 << 4)
+#define TR1 0x11006
+#define TSFS 0x11020
+#define TSFS_SLOPE_MASK 0x0000ff00
+#define TSFS_SLOPE_SHIFT 8
+#define TSFS_INTR_MASK 0x000000ff
+
#define CRSTANDVID 0x11100
#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
#define PXVFREQ_PX_MASK 0x7f000000
@@ -964,6 +1005,41 @@
#define MEMSTAT_SRC_CTL_STDBY 3
#define RCPREVBSYTUPAVG 0x113b8
#define RCPREVBSYTDNAVG 0x113bc
+#define SDEW 0x1124c
+#define CSIEW0 0x11250
+#define CSIEW1 0x11254
+#define CSIEW2 0x11258
+#define PEW 0x1125c
+#define DEW 0x11270
+#define MCHAFE 0x112c0
+#define CSIEC 0x112e0
+#define DMIEC 0x112e4
+#define DDREC 0x112e8
+#define PEG0EC 0x112ec
+#define PEG1EC 0x112f0
+#define GFXEC 0x112f4
+#define RPPREVBSYTUPAVG 0x113b8
+#define RPPREVBSYTDNAVG 0x113bc
+#define ECR 0x11600
+#define ECR_GPFE (1<<31)
+#define ECR_IMONE (1<<30)
+#define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */
+#define OGW0 0x11608
+#define OGW1 0x1160c
+#define EG0 0x11610
+#define EG1 0x11614
+#define EG2 0x11618
+#define EG3 0x1161c
+#define EG4 0x11620
+#define EG5 0x11624
+#define EG6 0x11628
+#define EG7 0x1162c
+#define PXW 0x11664
+#define PXWL 0x11680
+#define LCFUSE02 0x116c0
+#define LCFUSE_HIV_MASK 0x000000ff
+#define CSIPLL0 0x12c10
+#define DDRMPLL1 0X12c20
#define PEG_BAND_GAP_DATA 0x14d68
/*
@@ -1055,7 +1131,6 @@
#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
-#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
#define PORT_HOTPLUG_STAT 0x61114
#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
@@ -2355,6 +2430,8 @@
#define GT_PIPE_NOTIFY (1 << 4)
#define GT_SYNC_STATUS (1 << 2)
#define GT_USER_INTERRUPT (1 << 0)
+#define GT_BSD_USER_INTERRUPT (1 << 5)
+
#define GTISR 0x44010
#define GTIMR 0x44014
@@ -2690,6 +2767,9 @@
#define SDVO_ENCODING (0)
#define TMDS_ENCODING (2 << 10)
#define NULL_PACKET_VSYNC_ENABLE (1 << 9)
+/* CPT */
+#define HDMI_MODE_SELECT (1 << 9)
+#define DVI_MODE_SELECT (0)
#define SDVOB_BORDER_ENABLE (1 << 7)
#define AUDIO_ENABLE (1 << 6)
#define VSYNC_ACTIVE_HIGH (1 << 4)
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 9e4c45f..fab2176 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -53,23 +53,6 @@
__entry->obj, __entry->gtt_offset)
);
-TRACE_EVENT(i915_gem_object_clflush,
-
- TP_PROTO(struct drm_gem_object *obj),
-
- TP_ARGS(obj),
-
- TP_STRUCT__entry(
- __field(struct drm_gem_object *, obj)
- ),
-
- TP_fast_assign(
- __entry->obj = obj;
- ),
-
- TP_printk("obj=%p", __entry->obj)
-);
-
TRACE_EVENT(i915_gem_object_change_domain,
TP_PROTO(struct drm_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain),
@@ -132,6 +115,13 @@
TP_printk("obj=%p", __entry->obj)
);
+DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
+
+ TP_PROTO(struct drm_gem_object *obj),
+
+ TP_ARGS(obj)
+);
+
DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
TP_PROTO(struct drm_gem_object *obj),
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 4c748d8..96f75d7 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -95,6 +95,16 @@
panel_fixed_mode->clock = dvo_timing->clock * 10;
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
+ if (dvo_timing->hsync_positive)
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+ if (dvo_timing->vsync_positive)
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
/* Some VBTs have bogus h/vtotal values */
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index e16ac5a..22ff384 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -217,7 +217,8 @@
{
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 hotplug_en;
+ u32 hotplug_en, orig, stat;
+ bool ret = false;
int i, tries = 0;
if (HAS_PCH_SPLIT(dev))
@@ -232,8 +233,8 @@
tries = 2;
else
tries = 1;
- hotplug_en = I915_READ(PORT_HOTPLUG_EN);
- hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
+ hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
+ hotplug_en &= CRT_HOTPLUG_MASK;
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
if (IS_G4X(dev))
@@ -255,11 +256,17 @@
} while (time_after(timeout, jiffies));
}
- if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
- CRT_HOTPLUG_MONITOR_NONE)
- return true;
+ stat = I915_READ(PORT_HOTPLUG_STAT);
+ if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
+ ret = true;
- return false;
+ /* clear the interrupt we just generated, if any */
+ I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
+
+ /* and put the bits back */
+ I915_WRITE(PORT_HOTPLUG_EN, orig);
+
+ return ret;
}
static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
@@ -569,7 +576,7 @@
(1 << INTEL_ANALOG_CLONE_BIT) |
(1 << INTEL_SDVO_LVDS_CLONE_BIT);
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
- connector->interlace_allowed = 0;
+ connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f469a84..88a1ab7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1029,19 +1029,28 @@
void i8xx_disable_fbc(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1);
u32 fbc_ctl;
if (!I915_HAS_FBC(dev))
return;
+ if (!(I915_READ(FBC_CONTROL) & FBC_CTL_EN))
+ return; /* Already off, just return */
+
/* Disable compression */
fbc_ctl = I915_READ(FBC_CONTROL);
fbc_ctl &= ~FBC_CTL_EN;
I915_WRITE(FBC_CONTROL, fbc_ctl);
/* Wait for compressing bit to clear */
- while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING)
- ; /* nothing */
+ while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) {
+ if (time_after(jiffies, timeout)) {
+ DRM_DEBUG_DRIVER("FBC idle timed out\n");
+ break;
+ }
+ ; /* do nothing */
+ }
intel_wait_for_vblank(dev);
@@ -1239,10 +1248,11 @@
return;
out_disable:
- DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
/* Multiple disables should be harmless */
- if (intel_fbc_enabled(dev))
+ if (intel_fbc_enabled(dev)) {
+ DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
intel_disable_fbc(dev);
+ }
}
static int
@@ -1386,7 +1396,8 @@
Start = obj_priv->gtt_offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
- DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+ DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+ Start, Offset, x, y, crtc->fb->pitch);
I915_WRITE(dspstride, crtc->fb->pitch);
if (IS_I965G(dev)) {
I915_WRITE(dspbase, Offset);
@@ -2345,6 +2356,8 @@
if (mode->clock * 3 > 27000 * 4)
return MODE_CLOCK_HIGH;
}
+
+ drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
@@ -2629,6 +2642,7 @@
struct cxsr_latency {
int is_desktop;
+ int is_ddr3;
unsigned long fsb_freq;
unsigned long mem_freq;
unsigned long display_sr;
@@ -2638,33 +2652,45 @@
};
static struct cxsr_latency cxsr_latency_table[] = {
- {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */
- {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */
- {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */
+ {1, 0, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */
+ {1, 0, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */
+ {1, 0, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */
+ {1, 1, 800, 667, 6420, 36420, 6873, 36873}, /* DDR3-667 SC */
+ {1, 1, 800, 800, 5902, 35902, 6318, 36318}, /* DDR3-800 SC */
- {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */
- {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */
- {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */
+ {1, 0, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */
+ {1, 0, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */
+ {1, 0, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */
+ {1, 1, 667, 667, 6438, 36438, 6911, 36911}, /* DDR3-667 SC */
+ {1, 1, 667, 800, 5941, 35941, 6377, 36377}, /* DDR3-800 SC */
- {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */
- {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */
- {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */
+ {1, 0, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */
+ {1, 0, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */
+ {1, 0, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */
+ {1, 1, 400, 667, 6509, 36509, 7062, 37062}, /* DDR3-667 SC */
+ {1, 1, 400, 800, 5985, 35985, 6501, 36501}, /* DDR3-800 SC */
- {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */
- {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */
- {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */
+ {0, 0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */
+ {0, 0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */
+ {0, 0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */
+ {0, 1, 800, 667, 6476, 36476, 6955, 36955}, /* DDR3-667 SC */
+ {0, 1, 800, 800, 5958, 35958, 6400, 36400}, /* DDR3-800 SC */
- {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */
- {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */
- {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */
+ {0, 0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */
+ {0, 0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */
+ {0, 0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */
+ {0, 1, 667, 667, 6494, 36494, 6993, 36993}, /* DDR3-667 SC */
+ {0, 1, 667, 800, 5998, 35998, 6460, 36460}, /* DDR3-800 SC */
- {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */
- {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */
- {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */
+ {0, 0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */
+ {0, 0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */
+ {0, 0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */
+ {0, 1, 400, 667, 6566, 36566, 7145, 37145}, /* DDR3-667 SC */
+ {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */
};
-static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
- int mem)
+static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int is_ddr3,
+ int fsb, int mem)
{
int i;
struct cxsr_latency *latency;
@@ -2675,6 +2701,7 @@
for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
latency = &cxsr_latency_table[i];
if (is_desktop == latency->is_desktop &&
+ is_ddr3 == latency->is_ddr3 &&
fsb == latency->fsb_freq && mem == latency->mem_freq)
return latency;
}
@@ -2789,8 +2816,8 @@
struct cxsr_latency *latency;
int sr_clock;
- latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq,
- dev_priv->mem_freq);
+ latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
+ dev_priv->fsb_freq, dev_priv->mem_freq);
if (!latency) {
DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
pineview_disable_cxsr(dev);
@@ -3772,6 +3799,18 @@
}
}
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+ pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+ /* the chip adds 2 halflines automatically */
+ adjusted_mode->crtc_vdisplay -= 1;
+ adjusted_mode->crtc_vtotal -= 1;
+ adjusted_mode->crtc_vblank_start -= 1;
+ adjusted_mode->crtc_vblank_end -= 1;
+ adjusted_mode->crtc_vsync_end -= 1;
+ adjusted_mode->crtc_vsync_start -= 1;
+ } else
+ pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
+
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) |
@@ -4436,6 +4475,8 @@
mutex_lock(&dev->struct_mutex);
+ i915_update_gfx_val(dev_priv);
+
if (IS_I945G(dev) || IS_I945GM(dev)) {
DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
@@ -4564,12 +4605,6 @@
spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
if (work == NULL || !work->pending) {
- if (work && !work->pending) {
- obj_priv = to_intel_bo(work->pending_flip_obj);
- DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
- obj_priv,
- atomic_read(&obj_priv->pending_flip));
- }
spin_unlock_irqrestore(&dev->event_lock, flags);
return;
}
@@ -4629,14 +4664,11 @@
unsigned long flags;
int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
int ret, pipesrc;
- RING_LOCALS;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
return -ENOMEM;
- mutex_lock(&dev->struct_mutex);
-
work->event = event;
work->dev = crtc->dev;
intel_fb = to_intel_framebuffer(crtc->fb);
@@ -4646,10 +4678,10 @@
/* We borrow the event spin lock for protecting unpin_work */
spin_lock_irqsave(&dev->event_lock, flags);
if (intel_crtc->unpin_work) {
- DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(work);
- mutex_unlock(&dev->struct_mutex);
+
+ DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
return -EBUSY;
}
intel_crtc->unpin_work = work;
@@ -4658,13 +4690,19 @@
intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;
+ mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(dev, obj);
if (ret != 0) {
- DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
- to_intel_bo(obj));
- kfree(work);
- intel_crtc->unpin_work = NULL;
mutex_unlock(&dev->struct_mutex);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ intel_crtc->unpin_work = NULL;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ kfree(work);
+
+ DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
+ to_intel_bo(obj));
return ret;
}
@@ -5023,10 +5061,32 @@
return NULL;
}
+bool ironlake_set_drps(struct drm_device *dev, u8 val)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u16 rgvswctl;
+
+ rgvswctl = I915_READ16(MEMSWCTL);
+ if (rgvswctl & MEMCTL_CMD_STS) {
+ DRM_DEBUG("gpu busy, RCS change rejected\n");
+ return false; /* still busy with another command */
+ }
+
+ rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+ (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+ I915_WRITE16(MEMSWCTL, rgvswctl);
+ POSTING_READ16(MEMSWCTL);
+
+ rgvswctl |= MEMCTL_CMD_STS;
+ I915_WRITE16(MEMSWCTL, rgvswctl);
+
+ return true;
+}
+
void ironlake_enable_drps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl;
+ u32 rgvmodectl = I915_READ(MEMMODECTL);
u8 fmax, fmin, fstart, vstart;
int i = 0;
@@ -5045,13 +5105,21 @@
fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
MEMMODE_FSTART_SHIFT;
+ fstart = fmax;
+
vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
PXVFREQ_PX_SHIFT;
- dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */
+ dev_priv->fmax = fstart; /* IPS callback will increase this */
+ dev_priv->fstart = fstart;
+
+ dev_priv->max_delay = fmax;
dev_priv->min_delay = fmin;
dev_priv->cur_delay = fstart;
+ DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin,
+ fstart);
+
I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
/*
@@ -5073,20 +5141,19 @@
}
msleep(1);
- rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
- (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
- I915_WRITE(MEMSWCTL, rgvswctl);
- POSTING_READ(MEMSWCTL);
+ ironlake_set_drps(dev, fstart);
- rgvswctl |= MEMCTL_CMD_STS;
- I915_WRITE(MEMSWCTL, rgvswctl);
+ dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
+ I915_READ(0x112e0);
+ dev_priv->last_time1 = jiffies_to_msecs(jiffies);
+ dev_priv->last_count2 = I915_READ(0x112f4);
+ getrawmonotonic(&dev_priv->last_time2);
}
void ironlake_disable_drps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 rgvswctl;
- u8 fstart;
+ u16 rgvswctl = I915_READ16(MEMSWCTL);
/* Ack interrupts, disable EFC interrupt */
I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -5096,11 +5163,7 @@
I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
/* Go back to the starting frequency */
- fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >>
- MEMMODE_FSTART_SHIFT;
- rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
- (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
- I915_WRITE(MEMSWCTL, rgvswctl);
+ ironlake_set_drps(dev, dev_priv->fstart);
msleep(1);
rgvswctl |= MEMCTL_CMD_STS;
I915_WRITE(MEMSWCTL, rgvswctl);
@@ -5108,6 +5171,92 @@
}
+static unsigned long intel_pxfreq(u32 vidfreq)
+{
+ unsigned long freq;
+ int div = (vidfreq & 0x3f0000) >> 16;
+ int post = (vidfreq & 0x3000) >> 12;
+ int pre = (vidfreq & 0x7);
+
+ if (!pre)
+ return 0;
+
+ freq = ((div * 133333) / ((1<<post) * pre));
+
+ return freq;
+}
+
+void intel_init_emon(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 lcfuse;
+ u8 pxw[16];
+ int i;
+
+ /* Disable to program */
+ I915_WRITE(ECR, 0);
+ POSTING_READ(ECR);
+
+ /* Program energy weights for various events */
+ I915_WRITE(SDEW, 0x15040d00);
+ I915_WRITE(CSIEW0, 0x007f0000);
+ I915_WRITE(CSIEW1, 0x1e220004);
+ I915_WRITE(CSIEW2, 0x04000004);
+
+ for (i = 0; i < 5; i++)
+ I915_WRITE(PEW + (i * 4), 0);
+ for (i = 0; i < 3; i++)
+ I915_WRITE(DEW + (i * 4), 0);
+
+ /* Program P-state weights to account for frequency power adjustment */
+ for (i = 0; i < 16; i++) {
+ u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
+ unsigned long freq = intel_pxfreq(pxvidfreq);
+ unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
+ PXVFREQ_PX_SHIFT;
+ unsigned long val;
+
+ val = vid * vid;
+ val *= (freq / 1000);
+ val *= 255;
+ val /= (127*127*900);
+ if (val > 0xff)
+ DRM_ERROR("bad pxval: %ld\n", val);
+ pxw[i] = val;
+ }
+ /* Render standby states get 0 weight */
+ pxw[14] = 0;
+ pxw[15] = 0;
+
+ for (i = 0; i < 4; i++) {
+ u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
+ (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
+ I915_WRITE(PXW + (i * 4), val);
+ }
+
+ /* Adjust magic regs to magic values (more experimental results) */
+ I915_WRITE(OGW0, 0);
+ I915_WRITE(OGW1, 0);
+ I915_WRITE(EG0, 0x00007f00);
+ I915_WRITE(EG1, 0x0000000e);
+ I915_WRITE(EG2, 0x000e0000);
+ I915_WRITE(EG3, 0x68000300);
+ I915_WRITE(EG4, 0x42000000);
+ I915_WRITE(EG5, 0x00140031);
+ I915_WRITE(EG6, 0);
+ I915_WRITE(EG7, 0);
+
+ for (i = 0; i < 8; i++)
+ I915_WRITE(PXWL + (i * 4), 0);
+
+ /* Enable PMON + select events */
+ I915_WRITE(ECR, 0x80000019);
+
+ lcfuse = I915_READ(LCFUSE02);
+
+ dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
+}
+
void intel_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5277,11 +5426,13 @@
dev_priv->display.update_wm = NULL;
} else if (IS_PINEVIEW(dev)) {
if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+ dev_priv->is_ddr3,
dev_priv->fsb_freq,
dev_priv->mem_freq)) {
DRM_INFO("failed to find known CxSR latency "
- "(found fsb freq %d, mem freq %d), "
+ "(found ddr%s fsb freq %d, mem freq %d), "
"disabling CxSR\n",
+ (dev_priv->is_ddr3 == 1) ? "3": "2",
dev_priv->fsb_freq, dev_priv->mem_freq);
/* Disable CxSR and never update its watermark again */
pineview_disable_cxsr(dev);
@@ -5354,8 +5505,10 @@
intel_init_clock_gating(dev);
- if (IS_IRONLAKE_M(dev))
+ if (IS_IRONLAKE_M(dev)) {
ironlake_enable_drps(dev);
+ intel_init_emon(dev);
+ }
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6b1c9a2..49b54f0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -576,7 +576,7 @@
struct intel_encoder *intel_encoder;
struct intel_dp_priv *dp_priv;
- if (!encoder || encoder->crtc != crtc)
+ if (encoder->crtc != crtc)
continue;
intel_encoder = enc_to_intel_encoder(encoder);
@@ -675,10 +675,9 @@
dp_priv->link_configuration[1] = dp_priv->lane_count;
/*
- * Check for DPCD version > 1.1,
- * enable enahanced frame stuff in that case
+ * Check for DPCD version > 1.1 and enhanced framing support
*/
- if (dp_priv->dpcd[0] >= 0x11) {
+ if (dp_priv->dpcd[0] >= 0x11 && (dp_priv->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
dp_priv->DP |= DP_ENHANCED_FRAMING;
}
@@ -1208,6 +1207,8 @@
if (dp_priv->dpcd[0] != 0)
status = connector_status_connected;
}
+ DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", dp_priv->dpcd[0],
+ dp_priv->dpcd[1], dp_priv->dpcd[2], dp_priv->dpcd[3]);
return status;
}
@@ -1352,7 +1353,7 @@
struct intel_encoder *intel_encoder = NULL;
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
- if (!encoder || encoder->crtc != crtc)
+ if (encoder->crtc != crtc)
continue;
intel_encoder = enc_to_intel_encoder(encoder);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 6f53cf7..f8c76e6 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -105,7 +105,11 @@
}
/* Flush everything out, we'll be doing GTT only from now on */
- i915_gem_object_set_to_gtt_domain(fbo, 1);
+ ret = i915_gem_object_set_to_gtt_domain(fbo, 1);
+ if (ret) {
+ DRM_ERROR("failed to bind fb: %d.\n", ret);
+ goto out_unpin;
+ }
info = framebuffer_alloc(0, device);
if (!info) {
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 65727f0..83bd764 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -59,8 +59,11 @@
SDVO_VSYNC_ACTIVE_HIGH |
SDVO_HSYNC_ACTIVE_HIGH;
- if (hdmi_priv->has_hdmi_sink)
+ if (hdmi_priv->has_hdmi_sink) {
sdvox |= SDVO_AUDIO_ENABLE;
+ if (HAS_PCH_CPT(dev))
+ sdvox |= HDMI_MODE_SELECT;
+ }
if (intel_crtc->pipe == 1) {
if (HAS_PCH_CPT(dev))
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index b0e17b0..d7ad513 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -211,9 +211,8 @@
static int intel_overlay_on(struct intel_overlay *overlay)
{
struct drm_device *dev = overlay->dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
- RING_LOCALS;
+ drm_i915_private_t *dev_priv = dev->dev_private;
BUG_ON(overlay->active);
@@ -227,11 +226,13 @@
OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req =
+ i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
if (overlay->last_flip_req == 0)
return -ENOMEM;
- ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+ ret = i915_do_wait_request(dev,
+ overlay->last_flip_req, 1, &dev_priv->render_ring);
if (ret != 0)
return ret;
@@ -248,7 +249,6 @@
drm_i915_private_t *dev_priv = dev->dev_private;
u32 flip_addr = overlay->flip_addr;
u32 tmp;
- RING_LOCALS;
BUG_ON(!overlay->active);
@@ -265,7 +265,8 @@
OUT_RING(flip_addr);
ADVANCE_LP_RING();
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req =
+ i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
}
static int intel_overlay_wait_flip(struct intel_overlay *overlay)
@@ -274,10 +275,10 @@
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
u32 tmp;
- RING_LOCALS;
if (overlay->last_flip_req != 0) {
- ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+ ret = i915_do_wait_request(dev, overlay->last_flip_req,
+ 1, &dev_priv->render_ring);
if (ret == 0) {
overlay->last_flip_req = 0;
@@ -296,11 +297,13 @@
OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req =
+ i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
if (overlay->last_flip_req == 0)
return -ENOMEM;
- ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+ ret = i915_do_wait_request(dev, overlay->last_flip_req,
+ 1, &dev_priv->render_ring);
if (ret != 0)
return ret;
@@ -314,9 +317,8 @@
{
u32 flip_addr = overlay->flip_addr;
struct drm_device *dev = overlay->dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
- RING_LOCALS;
BUG_ON(!overlay->active);
@@ -336,11 +338,13 @@
OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req =
+ i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
if (overlay->last_flip_req == 0)
return -ENOMEM;
- ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+ ret = i915_do_wait_request(dev, overlay->last_flip_req,
+ 1, &dev_priv->render_ring);
if (ret != 0)
return ret;
@@ -354,11 +358,13 @@
OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req =
+ i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
if (overlay->last_flip_req == 0)
return -ENOMEM;
- ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+ ret = i915_do_wait_request(dev, overlay->last_flip_req,
+ 1, &dev_priv->render_ring);
if (ret != 0)
return ret;
@@ -390,22 +396,23 @@
int interruptible)
{
struct drm_device *dev = overlay->dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj;
+ drm_i915_private_t *dev_priv = dev->dev_private;
u32 flip_addr;
int ret;
- RING_LOCALS;
if (overlay->hw_wedged == HW_WEDGED)
return -EIO;
if (overlay->last_flip_req == 0) {
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req =
+ i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
if (overlay->last_flip_req == 0)
return -ENOMEM;
}
- ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible);
+ ret = i915_do_wait_request(dev, overlay->last_flip_req,
+ interruptible, &dev_priv->render_ring);
if (ret != 0)
return ret;
@@ -429,12 +436,13 @@
OUT_RING(MI_NOOP);
ADVANCE_LP_RING();
- overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+ overlay->last_flip_req = i915_add_request(dev, NULL,
+ 0, &dev_priv->render_ring);
if (overlay->last_flip_req == 0)
return -ENOMEM;
ret = i915_do_wait_request(dev, overlay->last_flip_req,
- interruptible);
+ interruptible, &dev_priv->render_ring);
if (ret != 0)
return ret;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
new file mode 100644
index 0000000..cea4f1a
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -0,0 +1,849 @@
+/*
+ * Copyright © 2008-2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Zou Nan hai <nanhai.zou@intel.com>
+ * Xiang Hai hao<haihao.xiang@intel.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drv.h"
+#include "i915_drm.h"
+#include "i915_trace.h"
+
+static void
+render_ring_flush(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ u32 invalidate_domains,
+ u32 flush_domains)
+{
+#if WATCH_EXEC
+ DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
+ invalidate_domains, flush_domains);
+#endif
+ u32 cmd;
+ trace_i915_gem_request_flush(dev, ring->next_seqno,
+ invalidate_domains, flush_domains);
+
+ if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
+ /*
+ * read/write caches:
+ *
+ * I915_GEM_DOMAIN_RENDER is always invalidated, but is
+ * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is
+ * also flushed at 2d versus 3d pipeline switches.
+ *
+ * read-only caches:
+ *
+ * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
+ * MI_READ_FLUSH is set, and is always flushed on 965.
+ *
+ * I915_GEM_DOMAIN_COMMAND may not exist?
+ *
+ * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
+ * invalidated when MI_EXE_FLUSH is set.
+ *
+ * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
+ * invalidated with every MI_FLUSH.
+ *
+ * TLBs:
+ *
+ * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
+ * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
+ * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
+ * are flushed at any MI_FLUSH.
+ */
+
+ cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+ if ((invalidate_domains|flush_domains) &
+ I915_GEM_DOMAIN_RENDER)
+ cmd &= ~MI_NO_WRITE_FLUSH;
+ if (!IS_I965G(dev)) {
+ /*
+ * On the 965, the sampler cache always gets flushed
+ * and this bit is reserved.
+ */
+ if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+ cmd |= MI_READ_FLUSH;
+ }
+ if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+ cmd |= MI_EXE_FLUSH;
+
+#if WATCH_EXEC
+ DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
+#endif
+ intel_ring_begin(dev, ring, 8);
+ intel_ring_emit(dev, ring, cmd);
+ intel_ring_emit(dev, ring, MI_NOOP);
+ intel_ring_advance(dev, ring);
+ }
+}
+
+static unsigned int render_ring_get_head(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(PRB0_HEAD) & HEAD_ADDR;
+}
+
+static unsigned int render_ring_get_tail(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(PRB0_TAIL) & TAIL_ADDR;
+}
+
+static unsigned int render_ring_get_active_head(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
+
+ return I915_READ(acthd_reg);
+}
+
+static void render_ring_advance_ring(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ I915_WRITE(PRB0_TAIL, ring->tail);
+}
+
+static int init_ring_common(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ u32 head;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv;
+ obj_priv = to_intel_bo(ring->gem_object);
+
+ /* Stop the ring if it's running. */
+ I915_WRITE(ring->regs.ctl, 0);
+ I915_WRITE(ring->regs.head, 0);
+ I915_WRITE(ring->regs.tail, 0);
+
+ /* Initialize the ring. */
+ I915_WRITE(ring->regs.start, obj_priv->gtt_offset);
+ head = ring->get_head(dev, ring);
+
+ /* G45 ring initialization fails to reset head to zero */
+ if (head != 0) {
+ DRM_ERROR("%s head not reset to zero "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ ring->name,
+ I915_READ(ring->regs.ctl),
+ I915_READ(ring->regs.head),
+ I915_READ(ring->regs.tail),
+ I915_READ(ring->regs.start));
+
+ I915_WRITE(ring->regs.head, 0);
+
+ DRM_ERROR("%s head forced to zero "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ ring->name,
+ I915_READ(ring->regs.ctl),
+ I915_READ(ring->regs.head),
+ I915_READ(ring->regs.tail),
+ I915_READ(ring->regs.start));
+ }
+
+ I915_WRITE(ring->regs.ctl,
+ ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
+ | RING_NO_REPORT | RING_VALID);
+
+ head = I915_READ(ring->regs.head) & HEAD_ADDR;
+ /* If the head is still not zero, the ring is dead */
+ if (head != 0) {
+ DRM_ERROR("%s initialization failed "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ ring->name,
+ I915_READ(ring->regs.ctl),
+ I915_READ(ring->regs.head),
+ I915_READ(ring->regs.tail),
+ I915_READ(ring->regs.start));
+ return -EIO;
+ }
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ i915_kernel_lost_context(dev);
+ else {
+ ring->head = ring->get_head(dev, ring);
+ ring->tail = ring->get_tail(dev, ring);
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->size;
+ }
+ return 0;
+}
+
+static int init_render_ring(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret = init_ring_common(dev, ring);
+ if (IS_I9XX(dev) && !IS_GEN3(dev)) {
+ I915_WRITE(MI_MODE,
+ (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
+ }
+ return ret;
+}
+
+#define PIPE_CONTROL_FLUSH(addr) \
+do { \
+ OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
+ PIPE_CONTROL_DEPTH_STALL | 2); \
+ OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT); \
+ OUT_RING(0); \
+ OUT_RING(0); \
+} while (0)
+
+/**
+ * Creates a new sequence number, emitting a write of it to the status page
+ * plus an interrupt, which will trigger i915_user_interrupt_handler.
+ *
+ * Must be called with struct_lock held.
+ *
+ * Returned sequence numbers are nonzero on success.
+ */
+static u32
+render_ring_add_request(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_file *file_priv,
+ u32 flush_domains)
+{
+ u32 seqno;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ seqno = intel_ring_get_seqno(dev, ring);
+
+ if (IS_GEN6(dev)) {
+ BEGIN_LP_RING(6);
+ OUT_RING(GFX_OP_PIPE_CONTROL | 3);
+ OUT_RING(PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
+ PIPE_CONTROL_NOTIFY);
+ OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+ OUT_RING(seqno);
+ OUT_RING(0);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ } else if (HAS_PIPE_CONTROL(dev)) {
+ u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
+
+ /*
+ * Workaround qword write incoherence by flushing the
+ * PIPE_NOTIFY buffers out to memory before requesting
+ * an interrupt.
+ */
+ BEGIN_LP_RING(32);
+ OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+ OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+ OUT_RING(seqno);
+ OUT_RING(0);
+ PIPE_CONTROL_FLUSH(scratch_addr);
+ scratch_addr += 128; /* write to separate cachelines */
+ PIPE_CONTROL_FLUSH(scratch_addr);
+ scratch_addr += 128;
+ PIPE_CONTROL_FLUSH(scratch_addr);
+ scratch_addr += 128;
+ PIPE_CONTROL_FLUSH(scratch_addr);
+ scratch_addr += 128;
+ PIPE_CONTROL_FLUSH(scratch_addr);
+ scratch_addr += 128;
+ PIPE_CONTROL_FLUSH(scratch_addr);
+ OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+ PIPE_CONTROL_NOTIFY);
+ OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+ OUT_RING(seqno);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ } else {
+ BEGIN_LP_RING(4);
+ OUT_RING(MI_STORE_DWORD_INDEX);
+ OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+ OUT_RING(seqno);
+
+ OUT_RING(MI_USER_INTERRUPT);
+ ADVANCE_LP_RING();
+ }
+ return seqno;
+}
+
+static u32
+render_ring_get_gem_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ if (HAS_PIPE_CONTROL(dev))
+ return ((volatile u32 *)(dev_priv->seqno_page))[0];
+ else
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static void
+render_ring_get_user_irq(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ if (dev->irq_enabled && (++ring->user_irq_refcount == 1)) {
+ if (HAS_PCH_SPLIT(dev))
+ ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
+ else
+ i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+ }
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+}
+
+static void
+render_ring_put_user_irq(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ BUG_ON(dev->irq_enabled && ring->user_irq_refcount <= 0);
+ if (dev->irq_enabled && (--ring->user_irq_refcount == 0)) {
+ if (HAS_PCH_SPLIT(dev))
+ ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
+ else
+ i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+ }
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+}
+
+static void render_setup_status_page(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ if (IS_GEN6(dev)) {
+ I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr);
+ I915_READ(HWS_PGA_GEN6); /* posting read */
+ } else {
+ I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
+ I915_READ(HWS_PGA); /* posting read */
+ }
+
+}
+
+void
+bsd_ring_flush(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ u32 invalidate_domains,
+ u32 flush_domains)
+{
+ intel_ring_begin(dev, ring, 8);
+ intel_ring_emit(dev, ring, MI_FLUSH);
+ intel_ring_emit(dev, ring, MI_NOOP);
+ intel_ring_advance(dev, ring);
+}
+
+static inline unsigned int bsd_ring_get_head(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(BSD_RING_HEAD) & HEAD_ADDR;
+}
+
+static inline unsigned int bsd_ring_get_tail(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(BSD_RING_TAIL) & TAIL_ADDR;
+}
+
+static inline unsigned int bsd_ring_get_active_head(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(BSD_RING_ACTHD);
+}
+
+static inline void bsd_ring_advance_ring(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ I915_WRITE(BSD_RING_TAIL, ring->tail);
+}
+
+static int init_bsd_ring(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ return init_ring_common(dev, ring);
+}
+
+static u32
+bsd_ring_add_request(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_file *file_priv,
+ u32 flush_domains)
+{
+ u32 seqno;
+ seqno = intel_ring_get_seqno(dev, ring);
+ intel_ring_begin(dev, ring, 4);
+ intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
+ intel_ring_emit(dev, ring,
+ I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+ intel_ring_emit(dev, ring, seqno);
+ intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
+ intel_ring_advance(dev, ring);
+
+ DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
+
+ return seqno;
+}
+
+static void bsd_setup_status_page(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr);
+ I915_READ(BSD_HWS_PGA);
+}
+
+static void
+bsd_ring_get_user_irq(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ /* do nothing */
+}
+static void
+bsd_ring_put_user_irq(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ /* do nothing */
+}
+
+static u32
+bsd_ring_get_gem_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static int
+bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_i915_gem_execbuffer2 *exec,
+ struct drm_clip_rect *cliprects,
+ uint64_t exec_offset)
+{
+ uint32_t exec_start;
+ exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+ intel_ring_begin(dev, ring, 2);
+ intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START |
+ (2 << 6) | MI_BATCH_NON_SECURE_I965);
+ intel_ring_emit(dev, ring, exec_start);
+ intel_ring_advance(dev, ring);
+ return 0;
+}
+
+
+static int
+render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_i915_gem_execbuffer2 *exec,
+ struct drm_clip_rect *cliprects,
+ uint64_t exec_offset)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int nbox = exec->num_cliprects;
+ int i = 0, count;
+ uint32_t exec_start, exec_len;
+ exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+ exec_len = (uint32_t) exec->batch_len;
+
+ trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
+
+ count = nbox ? nbox : 1;
+
+ for (i = 0; i < count; i++) {
+ if (i < nbox) {
+ int ret = i915_emit_box(dev, cliprects, i,
+ exec->DR1, exec->DR4);
+ if (ret)
+ return ret;
+ }
+
+ if (IS_I830(dev) || IS_845G(dev)) {
+ intel_ring_begin(dev, ring, 4);
+ intel_ring_emit(dev, ring, MI_BATCH_BUFFER);
+ intel_ring_emit(dev, ring,
+ exec_start | MI_BATCH_NON_SECURE);
+ intel_ring_emit(dev, ring, exec_start + exec_len - 4);
+ intel_ring_emit(dev, ring, 0);
+ } else {
+ intel_ring_begin(dev, ring, 4);
+ if (IS_I965G(dev)) {
+ intel_ring_emit(dev, ring,
+ MI_BATCH_BUFFER_START | (2 << 6)
+ | MI_BATCH_NON_SECURE_I965);
+ intel_ring_emit(dev, ring, exec_start);
+ } else {
+ intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START
+ | (2 << 6));
+ intel_ring_emit(dev, ring, exec_start |
+ MI_BATCH_NON_SECURE);
+ }
+ }
+ intel_ring_advance(dev, ring);
+ }
+
+ /* XXX breadcrumb */
+ return 0;
+}
+
+static void cleanup_status_page(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ obj = ring->status_page.obj;
+ if (obj == NULL)
+ return;
+ obj_priv = to_intel_bo(obj);
+
+ kunmap(obj_priv->pages[0]);
+ i915_gem_object_unpin(obj);
+ drm_gem_object_unreference(obj);
+ ring->status_page.obj = NULL;
+
+ memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+}
+
+static int init_status_page(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret;
+
+ obj = i915_gem_alloc_object(dev, 4096);
+ if (obj == NULL) {
+ DRM_ERROR("Failed to allocate status page\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ obj_priv = to_intel_bo(obj);
+ obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+
+ ret = i915_gem_object_pin(obj, 4096);
+ if (ret != 0) {
+ goto err_unref;
+ }
+
+ ring->status_page.gfx_addr = obj_priv->gtt_offset;
+ ring->status_page.page_addr = kmap(obj_priv->pages[0]);
+ if (ring->status_page.page_addr == NULL) {
+ memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+ goto err_unpin;
+ }
+ ring->status_page.obj = obj;
+ memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+
+ ring->setup_status_page(dev, ring);
+ DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
+ ring->name, ring->status_page.gfx_addr);
+
+ return 0;
+
+err_unpin:
+ i915_gem_object_unpin(obj);
+err_unref:
+ drm_gem_object_unreference(obj);
+err:
+ return ret;
+}
+
+
+int intel_init_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ int ret;
+ struct drm_i915_gem_object *obj_priv;
+ struct drm_gem_object *obj;
+ ring->dev = dev;
+
+ if (I915_NEED_GFX_HWS(dev)) {
+ ret = init_status_page(dev, ring);
+ if (ret)
+ return ret;
+ }
+
+ obj = i915_gem_alloc_object(dev, ring->size);
+ if (obj == NULL) {
+ DRM_ERROR("Failed to allocate ringbuffer\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ ring->gem_object = obj;
+
+ ret = i915_gem_object_pin(obj, ring->alignment);
+ if (ret != 0) {
+ drm_gem_object_unreference(obj);
+ goto cleanup;
+ }
+
+ obj_priv = to_intel_bo(obj);
+ ring->map.size = ring->size;
+ ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
+ ring->map.type = 0;
+ ring->map.flags = 0;
+ ring->map.mtrr = 0;
+
+ drm_core_ioremap_wc(&ring->map, dev);
+ if (ring->map.handle == NULL) {
+ DRM_ERROR("Failed to map ringbuffer.\n");
+ i915_gem_object_unpin(obj);
+ drm_gem_object_unreference(obj);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ ring->virtual_start = ring->map.handle;
+ ret = ring->init(dev, ring);
+ if (ret != 0) {
+ intel_cleanup_ring_buffer(dev, ring);
+ return ret;
+ }
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ i915_kernel_lost_context(dev);
+ else {
+ ring->head = ring->get_head(dev, ring);
+ ring->tail = ring->get_tail(dev, ring);
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->size;
+ }
+ INIT_LIST_HEAD(&ring->active_list);
+ INIT_LIST_HEAD(&ring->request_list);
+ return ret;
+cleanup:
+ cleanup_status_page(dev, ring);
+ return ret;
+}
+
+void intel_cleanup_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ if (ring->gem_object == NULL)
+ return;
+
+ drm_core_ioremapfree(&ring->map, dev);
+
+ i915_gem_object_unpin(ring->gem_object);
+ drm_gem_object_unreference(ring->gem_object);
+ ring->gem_object = NULL;
+ cleanup_status_page(dev, ring);
+}
+
+int intel_wrap_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ unsigned int *virt;
+ int rem;
+ rem = ring->size - ring->tail;
+
+ if (ring->space < rem) {
+ int ret = intel_wait_ring_buffer(dev, ring, rem);
+ if (ret)
+ return ret;
+ }
+
+ virt = (unsigned int *)(ring->virtual_start + ring->tail);
+ rem /= 4;
+ while (rem--)
+ *virt++ = MI_NOOP;
+
+ ring->tail = 0;
+
+ return 0;
+}
+
+int intel_wait_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring, int n)
+{
+ unsigned long end;
+
+ trace_i915_ring_wait_begin (dev);
+ end = jiffies + 3 * HZ;
+ do {
+ ring->head = ring->get_head(dev, ring);
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->size;
+ if (ring->space >= n) {
+ trace_i915_ring_wait_end (dev);
+ return 0;
+ }
+
+ if (dev->primary->master) {
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+ }
+
+ yield();
+ } while (!time_after(jiffies, end));
+ trace_i915_ring_wait_end (dev);
+ return -EBUSY;
+}
+
+void intel_ring_begin(struct drm_device *dev,
+ struct intel_ring_buffer *ring, int n)
+{
+ if (unlikely(ring->tail + n > ring->size))
+ intel_wrap_ring_buffer(dev, ring);
+ if (unlikely(ring->space < n))
+ intel_wait_ring_buffer(dev, ring, n);
+}
+
+void intel_ring_emit(struct drm_device *dev,
+ struct intel_ring_buffer *ring, unsigned int data)
+{
+ unsigned int *virt = ring->virtual_start + ring->tail;
+ *virt = data;
+ ring->tail += 4;
+ ring->tail &= ring->size - 1;
+ ring->space -= 4;
+}
+
+void intel_ring_advance(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ ring->advance_ring(dev, ring);
+}
+
+void intel_fill_struct(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ void *data,
+ unsigned int len)
+{
+ unsigned int *virt = ring->virtual_start + ring->tail;
+ BUG_ON((len&~(4-1)) != 0);
+ intel_ring_begin(dev, ring, len);
+ memcpy(virt, data, len);
+ ring->tail += len;
+ ring->tail &= ring->size - 1;
+ ring->space -= len;
+ intel_ring_advance(dev, ring);
+}
+
+u32 intel_ring_get_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ u32 seqno;
+ seqno = ring->next_seqno;
+
+ /* reserve 0 for non-seqno */
+ if (++ring->next_seqno == 0)
+ ring->next_seqno = 1;
+ return seqno;
+}
+
+struct intel_ring_buffer render_ring = {
+ .name = "render ring",
+ .regs = {
+ .ctl = PRB0_CTL,
+ .head = PRB0_HEAD,
+ .tail = PRB0_TAIL,
+ .start = PRB0_START
+ },
+ .ring_flag = I915_EXEC_RENDER,
+ .size = 32 * PAGE_SIZE,
+ .alignment = PAGE_SIZE,
+ .virtual_start = NULL,
+ .dev = NULL,
+ .gem_object = NULL,
+ .head = 0,
+ .tail = 0,
+ .space = 0,
+ .next_seqno = 1,
+ .user_irq_refcount = 0,
+ .irq_gem_seqno = 0,
+ .waiting_gem_seqno = 0,
+ .setup_status_page = render_setup_status_page,
+ .init = init_render_ring,
+ .get_head = render_ring_get_head,
+ .get_tail = render_ring_get_tail,
+ .get_active_head = render_ring_get_active_head,
+ .advance_ring = render_ring_advance_ring,
+ .flush = render_ring_flush,
+ .add_request = render_ring_add_request,
+ .get_gem_seqno = render_ring_get_gem_seqno,
+ .user_irq_get = render_ring_get_user_irq,
+ .user_irq_put = render_ring_put_user_irq,
+ .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer,
+ .status_page = {NULL, 0, NULL},
+ .map = {0,}
+};
+
+/* ring buffer for bit-stream decoder */
+
+struct intel_ring_buffer bsd_ring = {
+ .name = "bsd ring",
+ .regs = {
+ .ctl = BSD_RING_CTL,
+ .head = BSD_RING_HEAD,
+ .tail = BSD_RING_TAIL,
+ .start = BSD_RING_START
+ },
+ .ring_flag = I915_EXEC_BSD,
+ .size = 32 * PAGE_SIZE,
+ .alignment = PAGE_SIZE,
+ .virtual_start = NULL,
+ .dev = NULL,
+ .gem_object = NULL,
+ .head = 0,
+ .tail = 0,
+ .space = 0,
+ .next_seqno = 1,
+ .user_irq_refcount = 0,
+ .irq_gem_seqno = 0,
+ .waiting_gem_seqno = 0,
+ .setup_status_page = bsd_setup_status_page,
+ .init = init_bsd_ring,
+ .get_head = bsd_ring_get_head,
+ .get_tail = bsd_ring_get_tail,
+ .get_active_head = bsd_ring_get_active_head,
+ .advance_ring = bsd_ring_advance_ring,
+ .flush = bsd_ring_flush,
+ .add_request = bsd_ring_add_request,
+ .get_gem_seqno = bsd_ring_get_gem_seqno,
+ .user_irq_get = bsd_ring_get_user_irq,
+ .user_irq_put = bsd_ring_put_user_irq,
+ .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer,
+ .status_page = {NULL, 0, NULL},
+ .map = {0,}
+};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
new file mode 100644
index 0000000..d5568d3
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -0,0 +1,124 @@
+#ifndef _INTEL_RINGBUFFER_H_
+#define _INTEL_RINGBUFFER_H_
+
+struct intel_hw_status_page {
+ void *page_addr;
+ unsigned int gfx_addr;
+ struct drm_gem_object *obj;
+};
+
+struct drm_i915_gem_execbuffer2;
+struct intel_ring_buffer {
+ const char *name;
+ struct ring_regs {
+ u32 ctl;
+ u32 head;
+ u32 tail;
+ u32 start;
+ } regs;
+ unsigned int ring_flag;
+ unsigned long size;
+ unsigned int alignment;
+ void *virtual_start;
+ struct drm_device *dev;
+ struct drm_gem_object *gem_object;
+
+ unsigned int head;
+ unsigned int tail;
+ unsigned int space;
+ u32 next_seqno;
+ struct intel_hw_status_page status_page;
+
+ u32 irq_gem_seqno; /* last seq seem at irq time */
+ u32 waiting_gem_seqno;
+ int user_irq_refcount;
+ void (*user_irq_get)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ void (*user_irq_put)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ void (*setup_status_page)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+
+ int (*init)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+
+ unsigned int (*get_head)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ unsigned int (*get_tail)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ unsigned int (*get_active_head)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ void (*advance_ring)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ void (*flush)(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ u32 invalidate_domains,
+ u32 flush_domains);
+ u32 (*add_request)(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_file *file_priv,
+ u32 flush_domains);
+ u32 (*get_gem_seqno)(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+ int (*dispatch_gem_execbuffer)(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_i915_gem_execbuffer2 *exec,
+ struct drm_clip_rect *cliprects,
+ uint64_t exec_offset);
+
+ /**
+ * List of objects currently involved in rendering from the
+ * ringbuffer.
+ *
+ * Includes buffers having the contents of their GPU caches
+ * flushed, not necessarily primitives. last_rendering_seqno
+ * represents when the rendering involved will be completed.
+ *
+ * A reference is held on the buffer while on this list.
+ */
+ struct list_head active_list;
+
+ /**
+ * List of breadcrumbs associated with GPU requests currently
+ * outstanding.
+ */
+ struct list_head request_list;
+
+ wait_queue_head_t irq_queue;
+ drm_local_map_t map;
+};
+
+static inline u32
+intel_read_status_page(struct intel_ring_buffer *ring,
+ int reg)
+{
+ u32 *regs = ring->status_page.page_addr;
+ return regs[reg];
+}
+
+int intel_init_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+void intel_cleanup_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+int intel_wait_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring, int n);
+int intel_wrap_ring_buffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+void intel_ring_begin(struct drm_device *dev,
+ struct intel_ring_buffer *ring, int n);
+void intel_ring_emit(struct drm_device *dev,
+ struct intel_ring_buffer *ring, u32 data);
+void intel_fill_struct(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ void *data,
+ unsigned int len);
+void intel_ring_advance(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+
+u32 intel_ring_get_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring);
+
+extern struct intel_ring_buffer render_ring;
+extern struct intel_ring_buffer bsd_ring;
+
+#endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index aba72c4..76993ac 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1479,7 +1479,7 @@
intel_encoder = enc_to_intel_encoder(encoder);
if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector && encoder == intel_attached_encoder(connector))
+ if (encoder == intel_attached_encoder(connector))
return connector;
}
}
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index b3b7e28..8700474 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -97,8 +97,10 @@
hw->name, __func__, reg, val);
spin_lock(&hw->ctrl_lock);
- if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+ if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE) {
+ spin_unlock(&hw->ctrl_lock);
return 1;
+ }
buf = &hw->ctrl_buff[hw->ctrl_in_idx];
buf->hfcs_reg = reg;
buf->reg_val = val;
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index 0a3553d..54ae71a 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -320,12 +320,12 @@
return -ENOMEM;
}
for (i = 0; i < 2; i++) {
- card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL);
+ card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_ATOMIC);
if (!card->bc[i].hsbuf) {
pr_info("%s: no B%d send buffer\n", card->name, i + 1);
return -ENOMEM;
}
- card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL);
+ card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_ATOMIC);
if (!card->bc[i].hrbuf) {
pr_info("%s: no B%d recv buffer\n", card->name, i + 1);
return -ENOMEM;
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 9d11dbf..b9ad799 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1429,7 +1429,7 @@
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
- goto err;
+ goto err_unlock;
}
req = cmd->va;
sge = nonembedded_sgl(wrb);
@@ -1457,7 +1457,10 @@
else
status = adapter->flash_status;
-err:
+ return status;
+
+err_unlock:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1497,7 +1500,7 @@
return status;
}
-extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
+int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
struct be_dma_mem *nonemb_cmd)
{
struct be_mcc_wrb *wrb;
@@ -1590,7 +1593,7 @@
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
- req->hdr.timeout = 4;
+ req->hdr.timeout = cpu_to_le32(4);
req->pattern = cpu_to_le64(pattern);
req->src_port = cpu_to_le32(port_num);
@@ -1662,7 +1665,7 @@
return status;
}
-extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
+int be_cmd_get_seeprom_data(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd)
{
struct be_mcc_wrb *wrb;
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 8af8442..af75393 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -73,7 +73,7 @@
else
*mscan_clksrc = MSCAN_CLKSRC_XTAL;
- freq = mpc5xxx_get_bus_frequency(ofdev->node);
+ freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
if (!freq)
return 0;
@@ -152,7 +152,7 @@
}
/* Determine the MSCAN device index from the physical address */
- pval = of_get_property(ofdev->node, "reg", &plen);
+ pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
BUG_ON(!pval || plen < sizeof(*pval));
clockidx = (*pval & 0x80) ? 1 : 0;
if (*pval & 0x2000)
@@ -168,11 +168,11 @@
*/
if (clock_name && !strcmp(clock_name, "ip")) {
*mscan_clksrc = MSCAN_CLKSRC_IPS;
- freq = mpc5xxx_get_bus_frequency(ofdev->node);
+ freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
} else {
*mscan_clksrc = MSCAN_CLKSRC_BUS;
- pval = of_get_property(ofdev->node,
+ pval = of_get_property(ofdev->dev.of_node,
"fsl,mscan-clock-divider", &plen);
if (pval && plen == sizeof(*pval))
clockdiv = *pval;
@@ -251,7 +251,7 @@
const struct of_device_id *id)
{
struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
struct net_device *dev;
struct mscan_priv *priv;
void __iomem *base;
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 5d45084..48e91b6 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -504,17 +504,54 @@
}
/* Some transmit errors cause the transmitter to shut
- * down. We now issue a restart transmit. Since the
- * errors close the BD and update the pointers, the restart
- * _should_ pick up without having to reset any of our
- * pointers either. Also, To workaround 8260 device erratum
- * CPM37, we must disable and then re-enable the transmitter
- * following a Late Collision, Underrun, or Retry Limit error.
+ * down. We now issue a restart transmit.
+ * Also, to workaround 8260 device erratum CPM37, we must
+ * disable and then re-enable the transmitterfollowing a
+ * Late Collision, Underrun, or Retry Limit error.
+ * In addition, tbptr may point beyond BDs beyond still marked
+ * as ready due to internal pipelining, so we need to look back
+ * through the BDs and adjust tbptr to point to the last BD
+ * marked as ready. This may result in some buffers being
+ * retransmitted.
*/
static void tx_restart(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
fcc_t __iomem *fccp = fep->fcc.fccp;
+ const struct fs_platform_info *fpi = fep->fpi;
+ fcc_enet_t __iomem *ep = fep->fcc.ep;
+ cbd_t __iomem *curr_tbptr;
+ cbd_t __iomem *recheck_bd;
+ cbd_t __iomem *prev_bd;
+ cbd_t __iomem *last_tx_bd;
+
+ last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
+
+ /* get the current bd held in TBPTR and scan back from this point */
+ recheck_bd = curr_tbptr = (cbd_t __iomem *)
+ ((R32(ep, fen_genfcc.fcc_tbptr) - fep->ring_mem_addr) +
+ fep->ring_base);
+
+ prev_bd = (recheck_bd == fep->tx_bd_base) ? last_tx_bd : recheck_bd - 1;
+
+ /* Move through the bds in reverse, look for the earliest buffer
+ * that is not ready. Adjust TBPTR to the following buffer */
+ while ((CBDR_SC(prev_bd) & BD_ENET_TX_READY) != 0) {
+ /* Go back one buffer */
+ recheck_bd = prev_bd;
+
+ /* update the previous buffer */
+ prev_bd = (prev_bd == fep->tx_bd_base) ? last_tx_bd : prev_bd - 1;
+
+ /* We should never see all bds marked as ready, check anyway */
+ if (recheck_bd == curr_tbptr)
+ break;
+ }
+ /* Now update the TBPTR and dirty flag to the current buffer */
+ W32(ep, fen_genfcc.fcc_tbptr,
+ (uint) (((void *)recheck_bd - fep->ring_base) +
+ fep->ring_mem_addr));
+ fep->dirty_tx = recheck_bd;
C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
udelay(10);
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index f37a4c1..3a029d0 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -1607,14 +1607,13 @@
MODULE_DEVICE_TABLE(of, greth_of_match);
static struct of_platform_driver greth_of_driver = {
- .name = "grlib-greth",
- .match_table = greth_of_match,
+ .driver = {
+ .name = "grlib-greth",
+ .owner = THIS_MODULE,
+ .of_match_table = greth_of_match,
+ },
.probe = greth_of_probe,
.remove = __devexit_p(greth_of_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "grlib-greth",
- },
};
static int __init greth_init(void)
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index c80ca64..7805bbf 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -4854,7 +4854,7 @@
*
* Return 0 if successful; otherwise an error code indicating failure.
*/
-static int netdev_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
{
struct dev_priv *priv = netdev_priv(dev);
struct dev_info *hw_priv = priv->adapter;
@@ -6863,6 +6863,7 @@
.ndo_tx_timeout = netdev_tx_timeout,
.ndo_change_mtu = netdev_change_mtu,
.ndo_set_mac_address = netdev_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = netdev_ioctl,
.ndo_set_rx_mode = netdev_set_rx_mode,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 78eb319..1edb7a6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -340,7 +340,7 @@
skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
- err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb);
+ err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
if (err < 0)
dev_kfree_skb(skb);
@@ -385,8 +385,8 @@
/* chain first in list head */
first->private = (unsigned long)list;
- err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
- first);
+ err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+ first, gfp);
if (err < 0)
give_pages(vi, first);
@@ -404,7 +404,7 @@
sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
- err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page);
+ err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
if (err < 0)
give_pages(vi, page);
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 82ab532..a93dc18 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -739,17 +739,27 @@
static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)
{
struct device *parent = aru->udev->dev.parent;
+ struct usb_device *udev;
+
+ /*
+ * Store a copy of the usb_device pointer locally.
+ * This is because device_release_driver initiates
+ * ar9170_usb_disconnect, which in turn frees our
+ * driver context (aru).
+ */
+ udev = aru->udev;
complete(&aru->firmware_loading_complete);
/* unbind anything failed */
if (parent)
device_lock(parent);
- device_release_driver(&aru->udev->dev);
+
+ device_release_driver(&udev->dev);
if (parent)
device_unlock(parent);
- usb_put_dev(aru->udev);
+ usb_put_dev(udev);
}
static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3db1917..859aa4a 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1198,7 +1198,7 @@
int r;
ath_print(common, ATH_DBG_FATAL,
- "Unable to stop TxDMA. Reset HAL!\n");
+ "Failed to stop TX DMA. Resetting hardware!\n");
spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
@@ -1728,6 +1728,8 @@
} else
bf->bf_isnullfunc = false;
+ bf->bf_tx_aborted = false;
+
return 0;
}
@@ -1989,7 +1991,7 @@
int nbad = 0;
int isaggr = 0;
- if (bf->bf_tx_aborted)
+ if (bf->bf_lastbf->bf_tx_aborted)
return 0;
isaggr = bf_isaggr(bf);
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index a115bfa..7a377f5 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -329,9 +329,8 @@
/* create the exported radio header */
/* radiotap header */
- radiotap_hdr.hdr.it_version = 0;
- /* XXX must check this value for pad */
- radiotap_hdr.hdr.it_pad = 0;
+ memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
+ /* XXX must check radiotap_hdr.hdr.it_pad for pad */
radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6991613..0f8b84b 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -413,7 +413,7 @@
*/
rt2x00_desc_read(txi, 0, &word);
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
- skb->len - TXINFO_DESC_SIZE);
+ skb->len + TXWI_DESC_SIZE);
rt2x00_set_field32(&word, TXINFO_W0_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 576c3ed..40658e3 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -524,7 +524,7 @@
for (i = 0; i < inlen; i++)
ipc_data_writel(*in++, 4 * i);
- ipc_command(cmd << 12 | sub);
+ ipc_command((cmd << 12) | sub | (inlen << 18));
err = busy_loop();
for (i = 0; i < outlen; i++)
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 989e275..6dcda86 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -625,9 +625,12 @@
ssb_printk(KERN_ERR PFX "No SPROM available!\n");
return -ENODEV;
}
-
- bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
- SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+ if (bus->chipco.dev) { /* can be unavailible! */
+ bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
+ SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+ } else {
+ bus->sprom_offset = SSB_SPROM_BASE1;
+ }
buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
if (!buf)
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 007bc3a..4f7cc8d 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -185,6 +185,7 @@
/* this routine differs from specs as we do not access SPROM directly
on PCMCIA */
if (bus->bustype == SSB_BUSTYPE_PCI &&
+ bus->chipco.dev && /* can be unavailible! */
bus->chipco.dev->id.revision >= 31)
return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
diff --git a/fs/afs/server.c b/fs/afs/server.c
index f490995..9fdc7fe 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -91,9 +91,10 @@
memcpy(&server->addr, addr, sizeof(struct in_addr));
server->addr.s_addr = addr->s_addr;
+ _leave(" = %p{%d}", server, atomic_read(&server->usage));
+ } else {
+ _leave(" = NULL [nomem]");
}
-
- _leave(" = %p{%d}", server, atomic_read(&server->usage));
return server;
}
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 2c5f9a0..63039ed 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -990,10 +990,9 @@
/* clear any space allocated but not loaded */
if (phdr->p_filesz < phdr->p_memsz) {
- ret = clear_user((void *) (seg->addr + phdr->p_filesz),
- phdr->p_memsz - phdr->p_filesz);
- if (ret)
- return ret;
+ if (clear_user((void *) (seg->addr + phdr->p_filesz),
+ phdr->p_memsz - phdr->p_filesz))
+ return -EFAULT;
}
if (mm) {
@@ -1027,7 +1026,7 @@
struct elf32_fdpic_loadseg *seg;
struct elf32_phdr *phdr;
unsigned long load_addr, delta_vaddr;
- int loop, dvset, ret;
+ int loop, dvset;
load_addr = params->load_addr;
delta_vaddr = 0;
@@ -1127,9 +1126,8 @@
* PT_LOAD */
if (prot & PROT_WRITE && disp > 0) {
kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
- ret = clear_user((void __user *) maddr, disp);
- if (ret)
- return ret;
+ if (clear_user((void __user *) maddr, disp))
+ return -EFAULT;
maddr += disp;
}
@@ -1164,19 +1162,17 @@
if (prot & PROT_WRITE && excess1 > 0) {
kdebug("clear[%d] ad=%lx sz=%lx",
loop, maddr + phdr->p_filesz, excess1);
- ret = clear_user((void __user *) maddr + phdr->p_filesz,
- excess1);
- if (ret)
- return ret;
+ if (clear_user((void __user *) maddr + phdr->p_filesz,
+ excess1))
+ return -EFAULT;
}
#else
if (excess > 0) {
kdebug("clear[%d] ad=%lx sz=%lx",
loop, maddr + phdr->p_filesz, excess);
- ret = clear_user((void *) maddr + phdr->p_filesz, excess);
- if (ret)
- return ret;
+ if (clear_user((void *) maddr + phdr->p_filesz, excess))
+ return -EFAULT;
}
#endif
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 47aefd3..723b889 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -710,30 +710,26 @@
goto superseded;
}
- if (page) {
- radix_tree_tag_set(&cookie->stores, page->index,
- FSCACHE_COOKIE_STORING_TAG);
- radix_tree_tag_clear(&cookie->stores, page->index,
- FSCACHE_COOKIE_PENDING_TAG);
- }
+ radix_tree_tag_set(&cookie->stores, page->index,
+ FSCACHE_COOKIE_STORING_TAG);
+ radix_tree_tag_clear(&cookie->stores, page->index,
+ FSCACHE_COOKIE_PENDING_TAG);
spin_unlock(&cookie->stores_lock);
spin_unlock(&object->lock);
- if (page) {
- fscache_set_op_state(&op->op, "Store");
- fscache_stat(&fscache_n_store_pages);
- fscache_stat(&fscache_n_cop_write_page);
- ret = object->cache->ops->write_page(op, page);
- fscache_stat_d(&fscache_n_cop_write_page);
- fscache_set_op_state(&op->op, "EndWrite");
- fscache_end_page_write(object, page);
- if (ret < 0) {
- fscache_set_op_state(&op->op, "Abort");
- fscache_abort_object(object);
- } else {
- fscache_enqueue_operation(&op->op);
- }
+ fscache_set_op_state(&op->op, "Store");
+ fscache_stat(&fscache_n_store_pages);
+ fscache_stat(&fscache_n_cop_write_page);
+ ret = object->cache->ops->write_page(op, page);
+ fscache_stat_d(&fscache_n_cop_write_page);
+ fscache_set_op_state(&op->op, "EndWrite");
+ fscache_end_page_write(object, page);
+ if (ret < 0) {
+ fscache_set_op_state(&op->op, "Abort");
+ fscache_abort_object(object);
+ } else {
+ fscache_enqueue_operation(&op->op);
}
_leave("");
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 04f91c2..b5043a9 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -80,7 +80,7 @@
#ifndef PER_CPU_BASE_SECTION
#ifdef CONFIG_SMP
-#define PER_CPU_BASE_SECTION ".data.percpu"
+#define PER_CPU_BASE_SECTION ".data..percpu"
#else
#define PER_CPU_BASE_SECTION ".data"
#endif
@@ -92,15 +92,15 @@
#define PER_CPU_SHARED_ALIGNED_SECTION ""
#define PER_CPU_ALIGNED_SECTION ""
#else
-#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned"
-#define PER_CPU_ALIGNED_SECTION ".shared_aligned"
+#define PER_CPU_SHARED_ALIGNED_SECTION "..shared_aligned"
+#define PER_CPU_ALIGNED_SECTION "..shared_aligned"
#endif
-#define PER_CPU_FIRST_SECTION ".first"
+#define PER_CPU_FIRST_SECTION "..first"
#else
#define PER_CPU_SHARED_ALIGNED_SECTION ""
-#define PER_CPU_ALIGNED_SECTION ".shared_aligned"
+#define PER_CPU_ALIGNED_SECTION "..shared_aligned"
#define PER_CPU_FIRST_SECTION ""
#endif
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ef779c6..48c5299 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -175,25 +175,25 @@
#define NOSAVE_DATA \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__nosave_begin) = .; \
- *(.data.nosave) \
+ *(.data..nosave) \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__nosave_end) = .;
#define PAGE_ALIGNED_DATA(page_align) \
. = ALIGN(page_align); \
- *(.data.page_aligned)
+ *(.data..page_aligned)
#define READ_MOSTLY_DATA(align) \
. = ALIGN(align); \
- *(.data.read_mostly)
+ *(.data..read_mostly)
#define CACHELINE_ALIGNED_DATA(align) \
. = ALIGN(align); \
- *(.data.cacheline_aligned)
+ *(.data..cacheline_aligned)
#define INIT_TASK_DATA(align) \
. = ALIGN(align); \
- *(.data.init_task)
+ *(.data..init_task)
/*
* Read only Data
@@ -435,7 +435,7 @@
*/
#define INIT_TASK_DATA_SECTION(align) \
. = ALIGN(align); \
- .data.init_task : { \
+ .data..init_task : { \
INIT_TASK_DATA(align) \
}
@@ -499,7 +499,7 @@
#define BSS(bss_align) \
. = ALIGN(bss_align); \
.bss : AT(ADDR(.bss) - LOAD_OFFSET) { \
- *(.bss.page_aligned) \
+ *(.bss..page_aligned) \
*(.dynbss) \
*(.bss) \
*(COMMON) \
@@ -666,16 +666,16 @@
*/
#define PERCPU_VADDR(vaddr, phdr) \
VMLINUX_SYMBOL(__per_cpu_load) = .; \
- .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \
+ .data..percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \
- LOAD_OFFSET) { \
VMLINUX_SYMBOL(__per_cpu_start) = .; \
- *(.data.percpu.first) \
- *(.data.percpu.page_aligned) \
- *(.data.percpu) \
- *(.data.percpu.shared_aligned) \
+ *(.data..percpu..first) \
+ *(.data..percpu..page_aligned) \
+ *(.data..percpu) \
+ *(.data..percpu..shared_aligned) \
VMLINUX_SYMBOL(__per_cpu_end) = .; \
} phdr \
- . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu);
+ . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data..percpu);
/**
* PERCPU - define output section for percpu area, simple version
@@ -687,18 +687,18 @@
*
* This macro is equivalent to ALIGN(align); PERCPU_VADDR( , ) except
* that __per_cpu_load is defined as a relative symbol against
- * .data.percpu which is required for relocatable x86_32
+ * .data..percpu which is required for relocatable x86_32
* configuration.
*/
#define PERCPU(align) \
. = ALIGN(align); \
- .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { \
+ .data..percpu : AT(ADDR(.data..percpu) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__per_cpu_load) = .; \
VMLINUX_SYMBOL(__per_cpu_start) = .; \
- *(.data.percpu.first) \
- *(.data.percpu.page_aligned) \
- *(.data.percpu) \
- *(.data.percpu.shared_aligned) \
+ *(.data..percpu..first) \
+ *(.data..percpu..page_aligned) \
+ *(.data..percpu) \
+ *(.data..percpu..shared_aligned) \
VMLINUX_SYMBOL(__per_cpu_end) = .; \
}
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index b64a8d7..7f0028e 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -275,6 +275,7 @@
#define I915_PARAM_HAS_OVERLAY 7
#define I915_PARAM_HAS_PAGEFLIPPING 8
#define I915_PARAM_HAS_EXECBUF2 9
+#define I915_PARAM_HAS_BSD 10
typedef struct drm_i915_getparam {
int param;
@@ -616,7 +617,9 @@
__u32 num_cliprects;
/** This is a struct drm_clip_rect *cliprects */
__u64 cliprects_ptr;
- __u64 flags; /* currently unused */
+#define I915_EXEC_RENDER (1<<0)
+#define I915_EXEC_BSD (1<<1)
+ __u64 flags;
__u64 rsvd1;
__u64 rsvd2;
};
diff --git a/include/linux/cache.h b/include/linux/cache.h
index 97e2488..4c570653 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -31,7 +31,7 @@
#ifndef __cacheline_aligned
#define __cacheline_aligned \
__attribute__((__aligned__(SMP_CACHE_BYTES), \
- __section__(".data.cacheline_aligned")))
+ __section__(".data..cacheline_aligned")))
#endif /* __cacheline_aligned */
#ifndef __cacheline_aligned_in_smp
diff --git a/include/linux/init.h b/include/linux/init.h
index ab1d31f..de99430 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -301,7 +301,7 @@
#endif
/* Data marked not to be saved by software suspend */
-#define __nosavedata __section(.data.nosave)
+#define __nosavedata __section(.data..nosave)
/* This means "can be init if no module support, otherwise module load
may call it." */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 2beaa13..1f43fa5 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -183,7 +183,7 @@
}
/* Attach to the init_task data structure for proper alignment */
-#define __init_task_data __attribute__((__section__(".data.init_task")))
+#define __init_task_data __attribute__((__section__(".data..init_task")))
#endif
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 5126cce..7135ebc 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -18,8 +18,8 @@
# define asmregparm
#endif
-#define __page_aligned_data __section(.data.page_aligned) __aligned(PAGE_SIZE)
-#define __page_aligned_bss __section(.bss.page_aligned) __aligned(PAGE_SIZE)
+#define __page_aligned_data __section(.data..page_aligned) __aligned(PAGE_SIZE)
+#define __page_aligned_bss __section(.bss..page_aligned) __aligned(PAGE_SIZE)
/*
* For assembly routines.
@@ -27,8 +27,8 @@
* Note when using these that you must specify the appropriate
* alignment directives yourself
*/
-#define __PAGE_ALIGNED_DATA .section ".data.page_aligned", "aw"
-#define __PAGE_ALIGNED_BSS .section ".bss.page_aligned", "aw"
+#define __PAGE_ALIGNED_DATA .section ".data..page_aligned", "aw"
+#define __PAGE_ALIGNED_BSS .section ".bss..page_aligned", "aw"
/*
* This is used by architectures to keep arguments on the stack
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index c00cc0c..24e5d01 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -397,7 +397,7 @@
* @stacksize jumps (number of user chains) can possibly be made.
*/
unsigned int stacksize;
- unsigned int *stackptr;
+ unsigned int __percpu *stackptr;
void ***jumpstack;
/* ipt_entry tables: one per CPU */
/* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 68567c0..ce2dc65 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -131,11 +131,11 @@
* Declaration/definition used for per-CPU variables that must be page aligned.
*/
#define DECLARE_PER_CPU_PAGE_ALIGNED(type, name) \
- DECLARE_PER_CPU_SECTION(type, name, ".page_aligned") \
+ DECLARE_PER_CPU_SECTION(type, name, "..page_aligned") \
__aligned(PAGE_SIZE)
#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \
- DEFINE_PER_CPU_SECTION(type, name, ".page_aligned") \
+ DEFINE_PER_CPU_SECTION(type, name, "..page_aligned") \
__aligned(PAGE_SIZE)
/*
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7cdfb4d..bf243fc 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -501,7 +501,7 @@
return __alloc_skb(size, priority, 1, -1);
}
-extern int skb_recycle_check(struct sk_buff *skb, int skb_size);
+extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
extern struct sk_buff *skb_clone(struct sk_buff *skb,
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 89fac6a..f885465 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -60,7 +60,7 @@
/*
* Must define these before including other files, inline functions need them
*/
-#define LOCK_SECTION_NAME ".text.lock."KBUILD_BASENAME
+#define LOCK_SECTION_NAME ".text..lock."KBUILD_BASENAME
#define LOCK_SECTION_START(extra) \
".subsection 1\n\t" \
diff --git a/include/net/sock.h b/include/net/sock.h
index ca241ea..731150d5 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1524,20 +1524,7 @@
extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
-static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
-{
- /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
- number of warnings when compiling with -W --ANK
- */
- if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
- (unsigned)sk->sk_rcvbuf)
- return -ENOMEM;
- skb_set_owner_r(skb, sk);
- skb_queue_tail(&sk->sk_error_queue, skb);
- if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_data_ready(sk, skb->len);
- return 0;
-}
+extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
/*
* Recover an error report and clear atomically
diff --git a/init/Kconfig b/init/Kconfig
index 2cce9f3..5cff9a9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -76,6 +76,14 @@
variables passed to init from the kernel command line.
+config CROSS_COMPILE
+ string "Cross-compiler tool prefix"
+ help
+ Same as running 'make CROSS_COMPILE=prefix-' but stored for
+ default make runs in this kernel build directory. You don't
+ need to set this unless you want the configured kernel build
+ directory to select the cross-compiler automatically.
+
config LOCALVERSION
string "Local version - append to kernel release"
help
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 8b92539..97d1b42 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -34,7 +34,7 @@
mutex_unlock(&cpu_add_remove_lock);
}
-static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
+static RAW_NOTIFIER_HEAD(cpu_chain);
/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
* Should always be manipulated under cpu_add_remove_lock
diff --git a/kernel/module.c b/kernel/module.c
index 333fbcc..0129769 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -403,7 +403,7 @@
Elf_Shdr *sechdrs,
const char *secstrings)
{
- return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
+ return find_sec(hdr, sechdrs, secstrings, ".data..percpu");
}
static void percpu_modcopy(struct module *mod,
@@ -2014,6 +2014,7 @@
long err = 0;
void *ptr = NULL; /* Stops spurious gcc warning */
unsigned long symoffs, stroffs, *strmap;
+ void __percpu *percpu;
mm_segment_t old_fs;
@@ -2158,6 +2159,8 @@
goto free_mod;
sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
}
+ /* Keep this around for failure path. */
+ percpu = mod_percpu(mod);
/* Determine total sizes, and put offsets in sh_entsize. For now
this is done generically; there doesn't appear to be any
@@ -2463,7 +2466,7 @@
module_free(mod, mod->module_core);
/* mod will be freed with core. Don't access it beyond this line! */
free_percpu:
- percpu_modfree(mod);
+ free_percpu(percpu);
free_mod:
kfree(args);
kfree(strmap);
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
index cb4325a..965c5ba 100644
--- a/net/caif/cfserl.c
+++ b/net/caif/cfserl.c
@@ -59,16 +59,18 @@
u8 stx = CFSERL_STX;
int ret;
u16 expectlen = 0;
+
caif_assert(newpkt != NULL);
spin_lock(&layr->sync);
if (layr->incomplete_frm != NULL) {
-
layr->incomplete_frm =
cfpkt_append(layr->incomplete_frm, newpkt, expectlen);
pkt = layr->incomplete_frm;
- if (pkt == NULL)
+ if (pkt == NULL) {
+ spin_unlock(&layr->sync);
return -ENOMEM;
+ }
} else {
pkt = newpkt;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f8abf68..9f07e74 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -482,22 +482,22 @@
* reference count dropping and cleans up the skbuff as if it
* just came from __alloc_skb().
*/
-int skb_recycle_check(struct sk_buff *skb, int skb_size)
+bool skb_recycle_check(struct sk_buff *skb, int skb_size)
{
struct skb_shared_info *shinfo;
if (irqs_disabled())
- return 0;
+ return false;
if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
- return 0;
+ return false;
skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
if (skb_end_pointer(skb) - skb->head < skb_size)
- return 0;
+ return false;
if (skb_shared(skb) || skb_cloned(skb))
- return 0;
+ return false;
skb_release_head_state(skb);
@@ -509,7 +509,7 @@
skb->data = skb->head + NET_SKB_PAD;
skb_reset_tail_pointer(skb);
- return 1;
+ return true;
}
EXPORT_SYMBOL(skb_recycle_check);
@@ -2965,6 +2965,34 @@
}
EXPORT_SYMBOL_GPL(skb_cow_data);
+static void sock_rmem_free(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+}
+
+/*
+ * Note: We dont mem charge error packets (no sk_forward_alloc changes)
+ */
+int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
+{
+ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+ (unsigned)sk->sk_rcvbuf)
+ return -ENOMEM;
+
+ skb_orphan(skb);
+ skb->sk = sk;
+ skb->destructor = sock_rmem_free;
+ atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+
+ skb_queue_tail(&sk->sk_error_queue, skb);
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb->len);
+ return 0;
+}
+EXPORT_SYMBOL(sock_queue_err_skb);
+
void skb_tstamp_tx(struct sk_buff *orig_skb,
struct skb_shared_hwtstamps *hwtstamps)
{
@@ -2996,7 +3024,9 @@
memset(serr, 0, sizeof(*serr));
serr->ee.ee_errno = ENOMSG;
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
+
err = sock_queue_err_skb(sk, skb);
+
if (err)
kfree_skb(skb);
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 63958f3..4b6c5ca 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -336,7 +336,7 @@
cpu = smp_processor_id();
table_base = private->entries[cpu];
jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
- stackptr = &private->stackptr[cpu];
+ stackptr = per_cpu_ptr(private->stackptr, cpu);
origptr = *stackptr;
e = get_entry(table_base, private->hook_entry[hook]);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3e6dafc..548d575 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2639,7 +2639,7 @@
if (sk->sk_family == AF_INET) {
printk(KERN_DEBUG "Undo %s %pI4/%u c%u l%u ss%u/%u p%u\n",
msg,
- &inet->daddr, ntohs(inet->dport),
+ &inet->inet_daddr, ntohs(inet->inet_dport),
tp->snd_cwnd, tcp_left_out(tp),
tp->snd_ssthresh, tp->prior_ssthresh,
tp->packets_out);
@@ -2649,7 +2649,7 @@
struct ipv6_pinfo *np = inet6_sk(sk);
printk(KERN_DEBUG "Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n",
msg,
- &np->daddr, ntohs(inet->dport),
+ &np->daddr, ntohs(inet->inet_dport),
tp->snd_cwnd, tcp_left_out(tp),
tp->snd_ssthresh, tp->prior_ssthresh,
tp->packets_out);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5858574..eec4ff4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -633,9 +633,9 @@
if (!inet->recverr) {
if (!harderr || sk->sk_state != TCP_ESTABLISHED)
goto out;
- } else {
+ } else
ip_icmp_error(sk, skb, err, uh->dest, info, (u8 *)(uh+1));
- }
+
sk->sk_err = err;
sk->sk_error_report(sk);
out:
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 6f517bd..9d2d68f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -363,7 +363,7 @@
cpu = smp_processor_id();
table_base = private->entries[cpu];
jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
- stackptr = &private->stackptr[cpu];
+ stackptr = per_cpu_ptr(private->stackptr, cpu);
origptr = *stackptr;
e = get_entry(table_base, private->hook_entry[hook]);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 294cbe8..252d761 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -814,7 +814,7 @@
{
int flags = 0;
- if (fl->oif || rt6_need_strict(&fl->fl6_dst))
+ if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst))
flags |= RT6_LOOKUP_F_IFACE;
if (!ipv6_addr_any(&fl->fl6_src))
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5d218c5..32be11e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -5,7 +5,7 @@
#include <linux/nl80211.h>
#include "ieee80211_i.h"
-enum ieee80211_chan_mode
+static enum ieee80211_chan_mode
__ieee80211_get_channel_mode(struct ieee80211_local *local,
struct ieee80211_sub_if_data *ignore)
{
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 445de70..e34622f 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -699,10 +699,8 @@
vfree(info->jumpstack);
else
kfree(info->jumpstack);
- if (sizeof(unsigned int) * nr_cpu_ids > PAGE_SIZE)
- vfree(info->stackptr);
- else
- kfree(info->stackptr);
+
+ free_percpu(info->stackptr);
kfree(info);
}
@@ -753,14 +751,9 @@
unsigned int size;
int cpu;
- size = sizeof(unsigned int) * nr_cpu_ids;
- if (size > PAGE_SIZE)
- i->stackptr = vmalloc(size);
- else
- i->stackptr = kmalloc(size, GFP_KERNEL);
+ i->stackptr = alloc_percpu(unsigned int);
if (i->stackptr == NULL)
return -ENOMEM;
- memset(i->stackptr, 0, size);
size = sizeof(void **) * nr_cpu_ids;
if (size > PAGE_SIZE)
@@ -844,10 +837,6 @@
struct xt_table_info *private;
struct xt_table *t, *table;
- ret = xt_jumpstack_alloc(newinfo);
- if (ret < 0)
- return ERR_PTR(ret);
-
/* Don't add one object to multiple lists. */
table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);
if (!table) {
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 7b048a3..94d72e8 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1045,12 +1045,12 @@
lock_sock(sk);
if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
skparent = pn->listener;
- sk_del_node_init(sk);
release_sock(sk);
- sk = skparent;
pn = pep_sk(skparent);
- lock_sock(sk);
+ lock_sock(skparent);
+ sk_del_node_init(sk);
+ sk = skparent;
}
/* Unhash a listening sock only when it is closed
* and all of its active connected pipes are closed. */
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index 10ed0d5..f688327 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -475,6 +475,7 @@
err = rds_ib_setup_qp(conn);
if (err) {
rds_ib_conn_error(conn, "rds_ib_setup_qp failed (%d)\n", err);
+ mutex_unlock(&conn->c_cm_lock);
goto out;
}
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c
index a9d951b..b5dd6ac 100644
--- a/net/rds/iw_cm.c
+++ b/net/rds/iw_cm.c
@@ -452,6 +452,7 @@
err = rds_iw_setup_qp(conn);
if (err) {
rds_iw_conn_error(conn, "rds_iw_setup_qp failed (%d)\n", err);
+ mutex_unlock(&conn->c_cm_lock);
goto out;
}
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 0b94d2f..e4deb73 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -82,7 +82,7 @@
lib-target := $(obj)/lib.a
endif
-ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
+ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index cbcd654..54fd1b7 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -241,7 +241,7 @@
lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
-quiet_cmd_lzo = LZO $@
+quiet_cmd_lzo = LZO $@
cmd_lzo = (cat $(filter-out FORCE,$^) | \
lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
diff --git a/scripts/checkincludes.pl b/scripts/checkincludes.pl
index 676ddc0..97b2c61 100755
--- a/scripts/checkincludes.pl
+++ b/scripts/checkincludes.pl
@@ -11,6 +11,8 @@
# you do have real dups and do not have them under #ifdef's. You
# could also just review the results.
+use strict;
+
sub usage {
print "Usage: checkincludes.pl [-r]\n";
print "By default we just warn of duplicates\n";
@@ -35,23 +37,24 @@
}
}
-foreach $file (@ARGV) {
- open(FILE, $file) or die "Cannot open $file: $!.\n";
+foreach my $file (@ARGV) {
+ open(my $f, '<', $file)
+ or die "Cannot open $file: $!.\n";
my %includedfiles = ();
my @file_lines = ();
- while (<FILE>) {
+ while (<$f>) {
if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
++$includedfiles{$1};
}
push(@file_lines, $_);
}
- close(FILE);
+ close($f);
if (!$remove) {
- foreach $filename (keys %includedfiles) {
+ foreach my $filename (keys %includedfiles) {
if ($includedfiles{$filename} > 1) {
print "$file: $filename is included more than once.\n";
}
@@ -59,27 +62,28 @@
next;
}
- open(FILE,">$file") || die("Cannot write to $file: $!");
+ open($f, '>', $file)
+ or die("Cannot write to $file: $!");
my $dups = 0;
foreach (@file_lines) {
if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
- foreach $filename (keys %includedfiles) {
+ foreach my $filename (keys %includedfiles) {
if ($1 eq $filename) {
if ($includedfiles{$filename} > 1) {
$includedfiles{$filename}--;
$dups++;
} else {
- print FILE $_;
+ print {$f} $_;
}
}
}
} else {
- print FILE $_;
+ print {$f} $_;
}
}
if ($dups > 0) {
print "$file: removed $dups duplicate includes\n";
}
- close(FILE);
+ close($f);
}
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 14ee68e..1afff66 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -21,6 +21,8 @@
#
# TODO : Port to all architectures (one regex per arch)
+use strict;
+
# check for arch
#
# $re is used for two matches:
@@ -104,19 +106,11 @@
}
}
-sub bysize($) {
- my ($asize, $bsize);
- ($asize = $a) =~ s/.*: *(.*)$/$1/;
- ($bsize = $b) =~ s/.*: *(.*)$/$1/;
- $bsize <=> $asize
-}
-
#
# main()
#
my $funcre = qr/^$x* <(.*)>:$/;
-my $func;
-my $file, $lastslash;
+my ($func, $file, $lastslash);
while (my $line = <STDIN>) {
if ($line =~ m/$funcre/) {
@@ -173,4 +167,6 @@
}
}
-print sort bysize @stack;
+# Sort output by size (last field)
+print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack;
+
diff --git a/scripts/checkversion.pl b/scripts/checkversion.pl
index ec7d211..b444e89 100755
--- a/scripts/checkversion.pl
+++ b/scripts/checkversion.pl
@@ -5,23 +5,22 @@
# including <linux/version.h> that don't need it.
# Copyright (C) 2003, Randy Dunlap <rdunlap@xenotime.net>
+use strict;
+
$| = 1;
-my $debugging = 0;
+my $debugging;
-foreach $file (@ARGV)
-{
+foreach my $file (@ARGV) {
# Open this file.
- open(FILE, $file) || die "Can't open $file: $!\n";
+ open( my $f, '<', $file )
+ or die "Can't open $file: $!\n";
# Initialize variables.
- my $fInComment = 0;
- my $fInString = 0;
- my $fUseVersion = 0;
+ my ($fInComment, $fInString, $fUseVersion);
my $iLinuxVersion = 0;
- LINE: while ( <FILE> )
- {
+ while (<$f>) {
# Strip comments.
$fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next);
m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
@@ -43,8 +42,8 @@
# Look for uses: LINUX_VERSION_CODE, KERNEL_VERSION, UTS_RELEASE
if (($_ =~ /LINUX_VERSION_CODE/) || ($_ =~ /\WKERNEL_VERSION/)) {
$fUseVersion = 1;
- last LINE if $iLinuxVersion;
- }
+ last if $iLinuxVersion;
+ }
}
# Report used version IDs without include?
@@ -67,5 +66,5 @@
}
}
- close(FILE);
+ close($f);
}
diff --git a/scripts/decodecode b/scripts/decodecode
index 4b00647..8b30cc3 100755
--- a/scripts/decodecode
+++ b/scripts/decodecode
@@ -7,7 +7,7 @@
# AFLAGS=--32 decodecode < 386.oops
cleanup() {
- rm -f $T $T.s $T.o $T.oo $T.aa $T.aaa
+ rm -f $T $T.s $T.o $T.oo $T.aa $T.dis
exit 1
}
@@ -39,6 +39,29 @@
echo $code
code=`echo $code | sed -e 's/.*Code: //'`
+width=`expr index "$code" ' '`
+width=$[($width-1)/2]
+case $width in
+1) type=byte ;;
+2) type=2byte ;;
+4) type=4byte ;;
+esac
+
+disas() {
+ ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s &> /dev/null
+
+ if [ "$ARCH" == "arm" ]; then
+ if [ $width == 2 ]; then
+ OBJDUMPFLAGS="-M force-thumb"
+ fi
+
+ ${CROSS_COMPILE}strip $1.o
+ fi
+
+ ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \
+ grep -v "/tmp\|Disassembly\|\.text\|^$" &> $1.dis
+}
+
marker=`expr index "$code" "\<"`
if [ $marker -eq 0 ]; then
marker=`expr index "$code" "\("`
@@ -49,26 +72,25 @@
echo All code >> $T.oo
echo ======== >> $T.oo
beforemark=`echo "$code"`
- echo -n " .byte 0x" > $T.s
- echo $beforemark | sed -e 's/ /,0x/g' | sed -e 's/<//g' | sed -e 's/>//g' >> $T.s
- as $AFLAGS -o $T.o $T.s &> /dev/null
- objdump -S $T.o | grep -v "/tmp" | grep -v "Disassembly" | grep -v "\.text" | grep -v "^$" &> $T.ooo
- cat $T.ooo >> $T.oo
- rm -f $T.o $T.s $T.ooo
+ echo -n " .$type 0x" > $T.s
+ echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s
+ disas $T
+ cat $T.dis >> $T.oo
+ rm -f $T.o $T.s $T.dis
# and fix code at-and-after marker
code=`echo "$code" | cut -c$((${marker} + 1))-`
fi
echo Code starting with the faulting instruction > $T.aa
echo =========================================== >> $T.aa
-code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'`
-echo -n " .byte 0x" > $T.s
+code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
+echo -n " .$type 0x" > $T.s
echo $code >> $T.s
-as $AFLAGS -o $T.o $T.s &> /dev/null
-objdump -S $T.o | grep -v "Disassembly" | grep -v "/tmp" | grep -v "\.text" | grep -v "^$" &> $T.aaa
-cat $T.aaa >> $T.aa
+disas $T
+cat $T.dis >> $T.aa
-faultline=`cat $T.aaa | head -1 | cut -d":" -f2`
+faultline=`cat $T.dis | head -1 | cut -d":" -f2`
+faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
cat $T.oo | sed -e "s/\($faultline\)/\*\1 <-- trapping instruction/g"
echo
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index 705b5ba..04dce7c 100644
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -49,10 +49,10 @@
}
sub collectcfiles {
- my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`;
- @file = grep {s/\.ko/.mod.c/} @file;
- chomp @file;
- return @file;
+ my @file
+ = `cat .tmp_versions/*.mod | grep '.*\.ko\$' | sed s/\.ko$/.mod.c/`;
+ chomp @file;
+ return @file;
}
my (%SYMBOL, %MODULE, %opt, @allcfiles);
@@ -71,37 +71,40 @@
$opt{'k'} = "Module.symvers";
}
-unless (open(MODULE_SYMVERS, $opt{'k'})) {
- die "Sorry, cannot open $opt{'k'}: $!\n";
-}
+open (my $module_symvers, '<', $opt{'k'})
+ or die "Sorry, cannot open $opt{'k'}: $!\n";
if (defined $opt{'o'}) {
- unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) {
- die "Sorry, cannot open $opt{'o'} $!\n";
- }
- select OUTPUT_HANDLE;
+ open (my $out, '>', $opt{'o'})
+ or die "Sorry, cannot open $opt{'o'} $!\n";
+
+ select $out;
}
+
#
# collect all the symbols and their attributes from the
# Module.symvers file
#
-while ( <MODULE_SYMVERS> ) {
+while ( <$module_symvers> ) {
chomp;
my (undef, $symbol, $module, $gpl) = split;
$SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl];
}
-close(MODULE_SYMVERS);
+close($module_symvers);
#
# collect the usage count of each symbol.
#
foreach my $thismod (@allcfiles) {
- unless (open(MODULE_MODULE, $thismod)) {
- print "Sorry, cannot open $thismod: $!\n";
+ my $module;
+
+ unless (open ($module, '<', $thismod)) {
+ warn "Sorry, cannot open $thismod: $!\n";
next;
}
+
my $state=0;
- while ( <MODULE_MODULE> ) {
+ while ( <$module> ) {
chomp;
if ($state == 0) {
$state = 1 if ($_ =~ /static const struct modversion_info/);
@@ -124,7 +127,7 @@
if ($state != 2) {
print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n";
}
- close(MODULE_MODULE);
+ close($module);
}
print "\tThis file reports the exported symbols usage patterns by in-tree\n",
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index a932ae5..5958fff 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -202,6 +202,7 @@
print_mtime "$1" >> ${output}
cat "$1" >> ${output}
else
+ echo "$1 \\"
cat "$1" | while read type dir file perm ; do
if [ "$type" == "file" ]; then
echo "$file \\";
@@ -231,7 +232,7 @@
case "$arg" in
"-l") # files included in initramfs - used by kbuild
dep_list="list_"
- echo "deps_initramfs := \\"
+ echo "deps_initramfs := $0 \\"
shift
;;
"-o") # generate compressed cpio image named $1
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index af6b836..f99115e 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -758,8 +758,10 @@
/* setlinebuf(debugfile); */
}
- if (flag_reference)
+ if (flag_reference) {
read_reference(ref_file);
+ fclose(ref_file);
+ }
yyparse();
diff --git a/scripts/headerdep.pl b/scripts/headerdep.pl
index b7f6c56..8dd019b 100755
--- a/scripts/headerdep.pl
+++ b/scripts/headerdep.pl
@@ -80,8 +80,7 @@
my $path = "$i/$filename";
return $path if -f $path;
}
-
- return undef;
+ return;
}
sub parse_all {
diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl
index db1dd7a..50d6cfd 100644
--- a/scripts/headers_check.pl
+++ b/scripts/headers_check.pl
@@ -28,11 +28,12 @@
my $filename;
foreach my $file (@files) {
- local *FH;
$filename = $file;
- open(FH, "<$filename") or die "$filename: $!\n";
+
+ open(my $fh, '<', $filename)
+ or die "$filename: $!\n";
$lineno = 0;
- while ($line = <FH>) {
+ while ($line = <$fh>) {
$lineno++;
&check_include();
&check_asm_types();
@@ -40,7 +41,7 @@
&check_declarations();
# Dropped for now. Too much noise &check_config();
}
- close FH;
+ close $fh;
}
exit $ret;
@@ -78,7 +79,7 @@
}
my $linux_asm_types;
-sub check_asm_types()
+sub check_asm_types
{
if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
return;
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
index b89ca2c..4ca3be3 100644
--- a/scripts/headers_install.pl
+++ b/scripts/headers_install.pl
@@ -23,13 +23,13 @@
my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__";
foreach my $file (@files) {
- local *INFILE;
- local *OUTFILE;
my $tmpfile = "$installdir/$file.tmp";
- open(INFILE, "<$readdir/$file")
- or die "$readdir/$file: $!\n";
- open(OUTFILE, ">$tmpfile") or die "$tmpfile: $!\n";
- while (my $line = <INFILE>) {
+
+ open(my $in, '<', "$readdir/$file")
+ or die "$readdir/$file: $!\n";
+ open(my $out, '>', $tmpfile)
+ or die "$tmpfile: $!\n";
+ while (my $line = <$in>) {
$line =~ s/([\s(])__user\s/$1/g;
$line =~ s/([\s(])__force\s/$1/g;
$line =~ s/([\s(])__iomem\s/$1/g;
@@ -39,10 +39,11 @@
$line =~ s/(^|\s)(inline)\b/$1__$2__/g;
$line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
$line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
- printf OUTFILE "%s", $line;
+ printf {$out} "%s", $line;
}
- close OUTFILE;
- close INFILE;
+ close $out;
+ close $in;
+
system $unifdef . " $tmpfile > $installdir/$file";
unlink $tmpfile;
}
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 86c3896..e3902fb 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -108,8 +108,10 @@
rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
if (rc != 3) {
if (rc != EOF) {
- /* skip line */
- fgets(str, 500, in);
+ /* skip line. sym is used as dummy to
+ * shut of "warn_unused_result" warning.
+ */
+ sym = fgets(str, 500, in);
}
return -1;
}
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 186c466..7cdae39 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -23,6 +23,9 @@
config: $(obj)/conf
$< $(Kconfig)
+nconfig: $(obj)/nconf
+ $< $(Kconfig)
+
oldconfig: $(obj)/conf
$< -o $(Kconfig)
@@ -120,6 +123,7 @@
# Help text used by make help
help:
@echo ' config - Update current config utilising a line-oriented program'
+ @echo ' nconfig - Update current config utilising a ncurses menu based program'
@echo ' menuconfig - Update current config utilising a menu based program'
@echo ' xconfig - Update current config utilising a QT based front-end'
@echo ' gconfig - Update current config utilising a GTK based front-end'
@@ -147,6 +151,8 @@
# ===========================================================================
# Shared Makefile for the various kconfig executables:
# conf: Used for defconfig, oldconfig and related targets
+# nconf: Used for the nconfig target.
+# Utilizes ncurses
# mconf: Used for the menuconfig target
# Utilizes the lxdialog package
# qconf: Used for the xconfig target
@@ -159,11 +165,16 @@
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
conf-objs := conf.o zconf.tab.o
-mconf-objs := mconf.o zconf.tab.o $(lxdialog)
+mconf-objs := mconf.o zconf.tab.o $(lxdialog)
+nconf-objs := nconf.o zconf.tab.o nconf.gui.o
kxgettext-objs := kxgettext.o zconf.tab.o
hostprogs-y := conf qconf gconf kxgettext
+ifeq ($(MAKECMDGOALS),nconfig)
+ hostprogs-y += nconf
+endif
+
ifeq ($(MAKECMDGOALS),menuconfig)
hostprogs-y += mconf
endif
@@ -187,7 +198,7 @@
clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
.tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h
-clean-files += mconf qconf gconf
+clean-files += mconf qconf gconf nconf
clean-files += config.pot linux.pot
# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
@@ -212,6 +223,7 @@
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-D LKC_DIRECT_LINK
+HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
ifeq ($(qconf-target),1)
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index edd3f39..d83f232 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1097,9 +1097,32 @@
static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
{
- str_append((struct gstr*)data, str);
+ struct gstr *gs = (struct gstr*)data;
+ const char *sym_str = NULL;
+
if (sym)
- str_printf((struct gstr*)data, " [=%s]", sym_get_string_value(sym));
+ sym_str = sym_get_string_value(sym);
+
+ if (gs->max_width) {
+ unsigned extra_length = strlen(str);
+ const char *last_cr = strrchr(gs->s, '\n');
+ unsigned last_line_length;
+
+ if (sym_str)
+ extra_length += 4 + strlen(sym_str);
+
+ if (!last_cr)
+ last_cr = gs->s;
+
+ last_line_length = strlen(gs->s) - (last_cr - gs->s);
+
+ if ((last_line_length + extra_length) > gs->max_width)
+ str_append(gs, "\\\n");
+ }
+
+ str_append(gs, str);
+ if (sym)
+ str_printf(gs, " [=%s]", sym_str);
}
void expr_gstr_print(struct expr *e, struct gstr *gs)
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 6408fef..891cd9c 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -86,7 +86,7 @@
struct expr_value rev_dep;
};
-#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
@@ -108,8 +108,7 @@
#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
#define SYMBOL_MAXLENGTH 256
-#define SYMBOL_HASHSIZE 257
-#define SYMBOL_HASHMASK 0xff
+#define SYMBOL_HASHSIZE 9973
/* A property represent the config options that can be associated
* with a config "symbol".
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 6546436..bef1041 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -30,13 +30,16 @@
SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
};
+enum {
+ OPT_NORMAL, OPT_ALL, OPT_PROMPT
+};
+
static gint view_mode = FULL_VIEW;
static gboolean show_name = TRUE;
static gboolean show_range = TRUE;
static gboolean show_value = TRUE;
-static gboolean show_all = FALSE;
-static gboolean show_debug = FALSE;
static gboolean resizeable = FALSE;
+static int opt_mode = OPT_NORMAL;
GtkWidget *main_wnd = NULL;
GtkWidget *tree1_w = NULL; // left frame
@@ -76,36 +79,7 @@
/* Helping/Debugging Functions */
-
-const char *dbg_print_stype(int val)
-{
- static char buf[256];
-
- bzero(buf, 256);
-
- if (val == S_UNKNOWN)
- strcpy(buf, "unknown");
- if (val == S_BOOLEAN)
- strcpy(buf, "boolean");
- if (val == S_TRISTATE)
- strcpy(buf, "tristate");
- if (val == S_INT)
- strcpy(buf, "int");
- if (val == S_HEX)
- strcpy(buf, "hex");
- if (val == S_STRING)
- strcpy(buf, "string");
- if (val == S_OTHER)
- strcpy(buf, "other");
-
-#ifdef DEBUG
- printf("%s", buf);
-#endif
-
- return buf;
-}
-
-const char *dbg_print_flags(int val)
+const char *dbg_sym_flags(int val)
{
static char buf[256];
@@ -131,40 +105,10 @@
strcat(buf, "auto/");
buf[strlen(buf) - 1] = '\0';
-#ifdef DEBUG
- printf("%s", buf);
-#endif
return buf;
}
-const char *dbg_print_ptype(int val)
-{
- static char buf[256];
-
- bzero(buf, 256);
-
- if (val == P_UNKNOWN)
- strcpy(buf, "unknown");
- if (val == P_PROMPT)
- strcpy(buf, "prompt");
- if (val == P_COMMENT)
- strcpy(buf, "comment");
- if (val == P_MENU)
- strcpy(buf, "menu");
- if (val == P_DEFAULT)
- strcpy(buf, "default");
- if (val == P_CHOICE)
- strcpy(buf, "choice");
-
-#ifdef DEBUG
- printf("%s", buf);
-#endif
-
- return buf;
-}
-
-
void replace_button_icon(GladeXML * xml, GdkDrawable * window,
GtkStyle * style, gchar * btn_name, gchar ** xpm)
{
@@ -697,20 +641,29 @@
void
-on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
+on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
- show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
-
+ opt_mode = OPT_NORMAL;
gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); // instead of update_tree to speed-up
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
}
void
-on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
+on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
{
- show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
- update_tree(&rootmenu, NULL);
+ opt_mode = OPT_ALL;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void
+on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_PROMPT;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
}
@@ -1163,7 +1116,10 @@
g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
sym && sym_has_value(sym) ? "(NEW)" : "");
- if (show_all && !menu_is_visible(menu))
+ if (opt_mode == OPT_ALL && !menu_is_visible(menu))
+ row[COL_COLOR] = g_strdup("DarkGray");
+ else if (opt_mode == OPT_PROMPT &&
+ menu_has_prompt(menu) && !menu_is_visible(menu))
row[COL_COLOR] = g_strdup("DarkGray");
else
row[COL_COLOR] = g_strdup("Black");
@@ -1386,16 +1342,19 @@
menu2 ? menu_get_prompt(menu2) : "nil");
#endif
- if (!menu_is_visible(child1) && !show_all) { // remove node
+ if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
+ (opt_mode == OPT_PROMPT && !menu_has_prompt(child1))) {
+
+ /* remove node */
if (gtktree_iter_find_node(dst, menu1) != NULL) {
memcpy(&tmp, child2, sizeof(GtkTreeIter));
valid = gtk_tree_model_iter_next(model2,
child2);
gtk_tree_store_remove(tree2, &tmp);
if (!valid)
- return; // next parent
+ return; /* next parent */
else
- goto reparse; // next child
+ goto reparse; /* next child */
} else
continue;
}
@@ -1464,17 +1423,19 @@
&& (tree == tree2))
continue;
- if (menu_is_visible(child) || show_all)
+ if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
+ (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
+ (opt_mode == OPT_ALL))
place_node(child, fill_row(child));
#ifdef DEBUG
printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
- dbg_print_ptype(ptype);
+ printf("%s", prop_get_type_name(ptype));
printf(" | ");
if (sym) {
- dbg_print_stype(sym->type);
+ printf("%s", sym_type_name(sym->type));
printf(" | ");
- dbg_print_flags(sym->flags);
+ printf("%s", dbg_sym_flags(sym->flags));
printf("\n");
} else
printf("\n");
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index b1c86c1..d52b0a7 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -190,26 +190,40 @@
</child>
<child>
- <widget class="GtkCheckMenuItem" id="show_all_options1">
+ <widget class="GtkRadioMenuItem" id="set_option_mode1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show normal options</property>
+ <property name="label" translatable="yes">Show normal options</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <signal name="activate" handler="on_set_option_mode1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode2">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Show all options</property>
<property name="label" translatable="yes">Show all _options</property>
<property name="use_underline">True</property>
<property name="active">False</property>
- <signal name="activate" handler="on_show_all_options1_activate"/>
+ <property name="group">set_option_mode1</property>
+ <signal name="activate" handler="on_set_option_mode2_activate"/>
</widget>
</child>
<child>
- <widget class="GtkCheckMenuItem" id="show_debug_info1">
+ <widget class="GtkRadioMenuItem" id="set_option_mode3">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show masked options</property>
- <property name="label" translatable="yes">Show _debug info</property>
+ <property name="tooltip" translatable="yes">Show all options with prompts</property>
+ <property name="label" translatable="yes">Show all prompt options</property>
<property name="use_underline">True</property>
<property name="active">False</property>
- <signal name="activate" handler="on_show_debug_info1_activate"/>
+ <property name="group">set_option_mode1</property>
+ <signal name="activate" handler="on_set_option_mode3_activate"/>
</widget>
</child>
+
</widget>
</child>
</widget>
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index f379b0b..ce6549c 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -84,7 +84,7 @@
void kconfig_load(void);
/* menu.c */
-void menu_init(void);
+void _menu_init(void);
void menu_warn(struct menu *menu, const char *fmt, ...);
struct menu *menu_add_menu(void);
void menu_end_menu(void);
@@ -106,6 +106,11 @@
struct gstr {
size_t len;
char *s;
+ /*
+ * when max_width is not zero long lines in string s (if any) get
+ * wrapped not to exceed the max_width value
+ */
+ int max_width;
};
struct gstr str_new(void);
struct gstr str_assign(const char *s);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index ffeb532..7cadcad 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -11,13 +11,15 @@
/* menu.c */
P(rootmenu,struct menu,);
-P(menu_is_visible,bool,(struct menu *menu));
+P(menu_is_visible, bool, (struct menu *menu));
+P(menu_has_prompt, bool, (struct menu *menu));
P(menu_get_prompt,const char *,(struct menu *menu));
P(menu_get_root_menu,struct menu *,(struct menu *menu));
P(menu_get_parent_menu,struct menu *,(struct menu *menu));
P(menu_has_help,bool,(struct menu *menu));
P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str,void,(struct gstr *r, struct symbol *sym));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr));
P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
/* symbol.c */
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index 616c601..dd8e587 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -180,7 +180,7 @@
case KEY_LEFT:
switch (button) {
case -1:
- button = 1; /* Indicates "Cancel" button is selected */
+ button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 0:
@@ -204,7 +204,7 @@
print_buttons(dialog, height, width, 0);
break;
case 0:
- button = 1; /* Indicates "Cancel" button is selected */
+ button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 1:
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index fa9d633..1d60473 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -383,6 +383,10 @@
case 'n':
case 'm':
case '/':
+ case 'h':
+ case '?':
+ case 'z':
+ case '\n':
/* save scroll info */
*s_scroll = scroll;
delwin(menu);
@@ -390,8 +394,10 @@
item_set(scroll + choice);
item_set_selected(1);
switch (key) {
+ case 'h':
+ case '?':
+ return 2;
case 's':
- return 3;
case 'y':
return 3;
case 'n':
@@ -402,18 +408,12 @@
return 6;
case '/':
return 7;
+ case 'z':
+ return 8;
+ case '\n':
+ return button;
}
return 0;
- case 'h':
- case '?':
- button = 2;
- case '\n':
- *s_scroll = scroll;
- delwin(menu);
- delwin(dialog);
- item_set(scroll + choice);
- item_set_selected(1);
- return button;
case 'e':
case 'x':
key = KEY_ESC;
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 8413cf3..2c83d32 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -67,13 +67,15 @@
" there is a delayed response which you may find annoying.\n"
"\n"
" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
-" <Exit> and <Help>\n"
+" <Exit> and <Help>.\n"
"\n"
"o To get help with an item, use the cursor keys to highlight <Help>\n"
-" and Press <ENTER>.\n"
+" and press <ENTER>.\n"
"\n"
" Shortcut: Press <H> or <?>.\n"
"\n"
+"o To show hidden options, press <Z>.\n"
+"\n"
"\n"
"Radiolists (Choice lists)\n"
"-----------\n"
@@ -272,6 +274,7 @@
static struct menu *current_menu;
static int child_count;
static int single_menu_mode;
+static int show_all_options;
static void conf(struct menu *menu);
static void conf_choice(struct menu *menu);
@@ -282,19 +285,6 @@
static void show_helptext(const char *title, const char *text);
static void show_help(struct menu *menu);
-static struct gstr get_relations_str(struct symbol **sym_arr)
-{
- struct symbol *sym;
- struct gstr res = str_new();
- int i;
-
- for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
- get_symbol_str(&res, sym);
- if (!i)
- str_append(&res, _("No matches found.\n"));
- return res;
-}
-
static char filename[PATH_MAX+1];
static void set_config_filename(const char *config_filename)
{
@@ -359,8 +349,16 @@
int type, tmp, doint = 2;
tristate val;
char ch;
+ bool visible;
- if (!menu_is_visible(menu))
+ /*
+ * note: menu_is_visible() has side effect that it will
+ * recalc the value of the symbol.
+ */
+ visible = menu_is_visible(menu);
+ if (show_all_options && !menu_has_prompt(menu))
+ return;
+ else if (!show_all_options && !visible)
return;
sym = menu->sym;
@@ -619,6 +617,9 @@
case 7:
search_conf();
break;
+ case 8:
+ show_all_options = !show_all_options;
+ break;
}
}
}
@@ -638,6 +639,7 @@
{
struct gstr help = str_new();
+ help.max_width = getmaxx(stdscr) - 10;
menu_get_ext_help(menu, &help);
show_helptext(_(menu_get_prompt(menu)), str_get(&help));
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 059a246..203632c 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -38,7 +38,7 @@
va_end(ap);
}
-void menu_init(void)
+void _menu_init(void)
{
current_entry = current_menu = &rootmenu;
last_entry_ptr = &rootmenu.list;
@@ -197,7 +197,7 @@
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
prop->expr->type != E_SYMBOL)
prop_warn(prop,
- "default for config symbol '%'"
+ "default for config symbol '%s'"
" must be a single symbol", sym->name);
break;
case P_SELECT:
@@ -390,6 +390,13 @@
}
}
+bool menu_has_prompt(struct menu *menu)
+{
+ if (!menu->prompt)
+ return false;
+ return true;
+}
+
bool menu_is_visible(struct menu *menu)
{
struct menu *child;
@@ -398,6 +405,7 @@
if (!menu->prompt)
return false;
+
sym = menu->sym;
if (sym) {
sym_calc_value(sym);
@@ -407,12 +415,14 @@
if (visible != no)
return true;
+
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
for (child = menu->list; child; child = child->next)
if (menu_is_visible(child))
return true;
+
return false;
}
@@ -515,6 +525,20 @@
str_append(r, "\n\n");
}
+struct gstr get_relations_str(struct symbol **sym_arr)
+{
+ struct symbol *sym;
+ struct gstr res = str_new();
+ int i;
+
+ for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+ get_symbol_str(&res, sym);
+ if (!i)
+ str_append(&res, _("No matches found.\n"));
+ return res;
+}
+
+
void menu_get_ext_help(struct menu *menu, struct gstr *help)
{
struct symbol *sym = menu->sym;
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
new file mode 100644
index 0000000..762caf8
--- /dev/null
+++ b/scripts/kconfig/nconf.c
@@ -0,0 +1,1568 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+#include "nconf.h"
+
+static const char nconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"Some kernel features may be built directly into the kernel.\n"
+"Some may be made into loadable runtime modules. Some features\n"
+"may be completely removed altogether. There are also certain\n"
+"kernel parameters which are not really features, but must be\n"
+"entered in as decimal or hexadecimal numbers or possibly text.\n"
+"\n"
+"Menu items beginning with following braces represent features that\n"
+" [ ] can be built in or removed\n"
+" < > can be built in, modularized or removed\n"
+" { } can be built in or modularized (selected by other feature)\n"
+" - - are selected by other feature,\n"
+" XXX cannot be selected. use Symbol Info to find out why,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in, <M> to make it a module or\n"
+"<N> to removed it. You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+" you wish to change use <Enter> or <Space>. Goto submenu by \n"
+" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
+" Submenus are designated by \"--->\".\n"
+"\n"
+" Shortcut: Press the option's highlighted letter (hotkey).\n"
+" Pressing a hotkey more than once will sequence\n"
+" through all visible items which use that hotkey.\n"
+"\n"
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+" unseen options into view.\n"
+"\n"
+"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
+"\n"
+"o To get help with an item, press <F1>\n"
+" Shortcut: Press <h> or <?>.\n"
+"\n"
+"\n"
+"Radiolists (Choice lists)\n"
+"-----------\n"
+"o Use the cursor keys to select the option you wish to set and press\n"
+" <S> or the <SPACE BAR>.\n"
+"\n"
+" Shortcut: Press the first letter of the option you wish to set then\n"
+" press <S> or <SPACE BAR>.\n"
+"\n"
+"o To see available help for the item, press <F1>\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o Enter the requested information and press <ENTER>\n"
+" If you are entering hexadecimal values, it is not necessary to\n"
+" add the '0x' prefix to the entry.\n"
+"\n"
+"o For help, press <F1>.\n"
+"\n"
+"\n"
+"Text Box (Help Window)\n"
+"--------\n"
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
+" keys h,j,k,l function here as do <SPACE BAR> for those\n"
+" who are familiar with less and lynx.\n"
+"\n"
+"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"nconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different kernel configurations.\n"
+"\n"
+"At the end of the main menu you will find two options. One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a nconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting nconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use nconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, nconfig will look rather bad. nconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"nconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry. I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment. Some distributions\n"
+"export those variables via /etc/profile. Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the kernel options listed in a single\n"
+"menu, rather than the default multimenu hierarchy, run the nconfig\n"
+"with NCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make NCONFIG_MODE=single_menu nconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"
+"\n"),
+menu_no_f_instructions[] = N_(
+" You do not have function keys support. Please follow the\n"
+" following instructions:\n"
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options\n"
+" Press <Esc> or <left-arrow> to go back one menu, \n"
+" <?> or <h> for Help, </> for Search.\n"
+" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
+" <Esc> always leaves the current window\n"),
+menu_instructions[] = N_(
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options\n"
+" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n"
+" <?>, <F1> or <h> for Help, </> for Search.\n"
+" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
+" <Esc> always leaves the current window\n"),
+radiolist_instructions[] = N_(
+" Use the arrow keys to navigate this window or\n"
+" press the hotkey of the item you wish to select\n"
+" followed by the <SPACE BAR>.\n"
+" Press <?>, <F1> or <h> for additional information about this option.\n"),
+inputbox_instructions_int[] = N_(
+"Please enter a decimal value.\n"
+"Fractions will not be accepted.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_hex[] = N_(
+"Please enter a hexadecimal value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_string[] = N_(
+"Please enter a string value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+setmod_text[] = N_(
+"This feature depends on another which\n"
+"has been configured as a module.\n"
+"As a result, this feature will be built as a module."),
+nohelp_text[] = N_(
+"There is no help available for this kernel option.\n"),
+load_config_text[] = N_(
+"Enter the name of the configuration file you wish to load.\n"
+"Accept the name shown to restore the configuration you\n"
+"last retrieved. Leave blank to abort."),
+load_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep several different kernel\n"
+"configurations available on a single machine.\n"
+"\n"
+"If you have saved a previous configuration in a file other than the\n"
+"kernel's default, entering the name of the file here will allow you\n"
+"to modify that configuration.\n"
+"\n"
+"If you are uncertain, then you have probably never used alternate\n"
+"configuration files. You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
+"Enter a filename to which this configuration should be saved\n"
+"as an alternate. Leave blank to abort."),
+save_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep different kernel\n"
+"configurations available on a single machine.\n"
+"\n"
+"Entering a file name here will allow you to later retrieve, modify\n"
+"and use the current configuration as an alternate to whatever\n"
+"configuration options you have selected at that time.\n"
+"\n"
+"If you are uncertain what all this means then you should probably\n"
+"leave this blank.\n"),
+search_help[] = N_(
+"\n"
+"Search for CONFIG_ symbols and display their relations.\n"
+"Regular expressions are allowed.\n"
+"Example: search for \"^FOO\"\n"
+"Result:\n"
+"-----------------------------------------------------------------\n"
+"Symbol: FOO [ = m]\n"
+"Prompt: Foo bus is used to drive the bar HW\n"
+"Defined at drivers/pci/Kconfig:47\n"
+"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+"Location:\n"
+" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+" -> PCI support (PCI [ = y])\n"
+" -> PCI access mode (<choice> [ = y])\n"
+"Selects: LIBCRC32\n"
+"Selected by: BAR\n"
+"-----------------------------------------------------------------\n"
+"o The line 'Prompt:' shows the text used in the menu structure for\n"
+" this CONFIG_ symbol\n"
+"o The 'Defined at' line tell at what file / line number the symbol\n"
+" is defined\n"
+"o The 'Depends on:' line tell what symbols needs to be defined for\n"
+" this symbol to be visible in the menu (selectable)\n"
+"o The 'Location:' lines tell where in the menu structure this symbol\n"
+" is located\n"
+" A location followed by a [ = y] indicate that this is a selectable\n"
+" menu item - and current value is displayed inside brackets.\n"
+"o The 'Selects:' line tell what symbol will be automatically\n"
+" selected if this symbol is selected (y or m)\n"
+"o The 'Selected by' line tell what symbol has selected this symbol\n"
+"\n"
+"Only relevant lines are shown.\n"
+"\n\n"
+"Search examples:\n"
+"Examples: USB = > find all CONFIG_ symbols containing USB\n"
+" ^USB => find all CONFIG_ symbols starting with USB\n"
+" USB$ => find all CONFIG_ symbols ending with USB\n"
+"\n");
+
+struct mitem {
+ char str[256];
+ char tag;
+ void *usrptr;
+ int is_hot;
+ int is_visible;
+};
+
+#define MAX_MENU_ITEMS 4096
+static int show_all_items;
+static int indent;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+/* the window in which all information appears */
+static WINDOW *main_window;
+/* the largest size of the menu window */
+static int mwin_max_lines;
+static int mwin_max_cols;
+/* the window in which we show option buttons */
+static MENU *curses_menu;
+static ITEM *curses_menu_items[MAX_MENU_ITEMS];
+static struct mitem k_menu_items[MAX_MENU_ITEMS];
+static int items_num;
+static int global_exit;
+/* the currently selected button */
+const char *current_instructions = menu_instructions;
+/* this array is used to implement hot keys. it is updated in item_make and
+ * resetted in clean_items. It would be better to use a hash, but lets keep it
+ * simple... */
+#define MAX_SAME_KEY MAX_MENU_ITEMS
+struct {
+ int count;
+ int ptrs[MAX_MENU_ITEMS];
+} hotkeys[1<<(sizeof(char)*8)];
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_help(struct menu *menu);
+static int do_exit(void);
+static void setup_windows(void);
+
+typedef void (*function_key_handler_t)(int *key, struct menu *menu);
+static void handle_f1(int *key, struct menu *current_item);
+static void handle_f2(int *key, struct menu *current_item);
+static void handle_f3(int *key, struct menu *current_item);
+static void handle_f4(int *key, struct menu *current_item);
+static void handle_f5(int *key, struct menu *current_item);
+static void handle_f6(int *key, struct menu *current_item);
+static void handle_f7(int *key, struct menu *current_item);
+static void handle_f8(int *key, struct menu *current_item);
+
+struct function_keys {
+ const char *key_str;
+ const char *func;
+ function_key key;
+ function_key_handler_t handler;
+};
+
+static const int function_keys_num = 8;
+struct function_keys function_keys[] = {
+ {
+ .key_str = "F1",
+ .func = "Help",
+ .key = F_HELP,
+ .handler = handle_f1,
+ },
+ {
+ .key_str = "F2",
+ .func = "Symbol Info",
+ .key = F_SYMBOL,
+ .handler = handle_f2,
+ },
+ {
+ .key_str = "F3",
+ .func = "Instructions",
+ .key = F_INSTS,
+ .handler = handle_f3,
+ },
+ {
+ .key_str = "F4",
+ .func = "Config",
+ .key = F_CONF,
+ .handler = handle_f4,
+ },
+ {
+ .key_str = "F5",
+ .func = "Back",
+ .key = F_BACK,
+ .handler = handle_f5,
+ },
+ {
+ .key_str = "F6",
+ .func = "Save",
+ .key = F_SAVE,
+ .handler = handle_f6,
+ },
+ {
+ .key_str = "F7",
+ .func = "Load",
+ .key = F_LOAD,
+ .handler = handle_f7,
+ },
+ {
+ .key_str = "F8",
+ .func = "Exit",
+ .key = F_EXIT,
+ .handler = handle_f8,
+ },
+};
+
+static void print_function_line(void)
+{
+ int i;
+ int offset = 1;
+ const int skip = 1;
+
+ for (i = 0; i < function_keys_num; i++) {
+ wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
+ mvwprintw(main_window, LINES-3, offset,
+ "%s",
+ function_keys[i].key_str);
+ wattrset(main_window, attributes[FUNCTION_TEXT]);
+ offset += strlen(function_keys[i].key_str);
+ mvwprintw(main_window, LINES-3,
+ offset, "%s",
+ function_keys[i].func);
+ offset += strlen(function_keys[i].func) + skip;
+ }
+ wattrset(main_window, attributes[NORMAL]);
+}
+
+/* help */
+static void handle_f1(int *key, struct menu *current_item)
+{
+ show_scroll_win(main_window,
+ _("README"), _(nconf_readme));
+ return;
+}
+
+/* symbole help */
+static void handle_f2(int *key, struct menu *current_item)
+{
+ show_help(current_item);
+ return;
+}
+
+/* instructions */
+static void handle_f3(int *key, struct menu *current_item)
+{
+ show_scroll_win(main_window,
+ _("Instructions"),
+ _(current_instructions));
+ return;
+}
+
+/* config */
+static void handle_f4(int *key, struct menu *current_item)
+{
+ int res = btn_dialog(main_window,
+ _("Show all symbols?"),
+ 2,
+ " <Show All> ",
+ "<Don't show all>");
+ if (res == 0)
+ show_all_items = 1;
+ else if (res == 1)
+ show_all_items = 0;
+
+ return;
+}
+
+/* back */
+static void handle_f5(int *key, struct menu *current_item)
+{
+ *key = KEY_LEFT;
+ return;
+}
+
+/* save */
+static void handle_f6(int *key, struct menu *current_item)
+{
+ conf_save();
+ return;
+}
+
+/* load */
+static void handle_f7(int *key, struct menu *current_item)
+{
+ conf_load();
+ return;
+}
+
+/* exit */
+static void handle_f8(int *key, struct menu *current_item)
+{
+ do_exit();
+ return;
+}
+
+/* return != 0 to indicate the key was handles */
+static int process_special_keys(int *key, struct menu *menu)
+{
+ int i;
+
+ if (*key == KEY_RESIZE) {
+ setup_windows();
+ return 1;
+ }
+
+ for (i = 0; i < function_keys_num; i++) {
+ if (*key == KEY_F(function_keys[i].key) ||
+ *key == '0' + function_keys[i].key){
+ function_keys[i].handler(key, menu);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void clean_items(void)
+{
+ int i;
+ for (i = 0; curses_menu_items[i]; i++)
+ free_item(curses_menu_items[i]);
+ bzero(curses_menu_items, sizeof(curses_menu_items));
+ bzero(k_menu_items, sizeof(k_menu_items));
+ bzero(hotkeys, sizeof(hotkeys));
+ items_num = 0;
+}
+
+/* return the index of the next hot item, or -1 if no such item exists */
+static int get_next_hot(int c)
+{
+ static int hot_index;
+ static int hot_char;
+
+ if (c < 0 || c > 255 || hotkeys[c].count <= 0)
+ return -1;
+
+ if (hot_char == c) {
+ hot_index = (hot_index+1)%hotkeys[c].count;
+ return hotkeys[c].ptrs[hot_index];
+ } else {
+ hot_char = c;
+ hot_index = 0;
+ return hotkeys[c].ptrs[0];
+ }
+}
+
+/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */
+static int canbhot(char c)
+{
+ c = tolower(c);
+ return isalnum(c) && c != 'y' && c != 'm' && c != 'h' &&
+ c != 'n' && c != '?';
+}
+
+/* check if str already contains a hot key. */
+static int is_hot(int index)
+{
+ return k_menu_items[index].is_hot;
+}
+
+/* find the first possible hot key, and mark it.
+ * index is the index of the item in the menu
+ * return 0 on success*/
+static int make_hot(char *dest, int len, const char *org, int index)
+{
+ int position = -1;
+ int i;
+ int tmp;
+ int c;
+ int org_len = strlen(org);
+
+ if (org == NULL || is_hot(index))
+ return 1;
+
+ /* make sure not to make hot keys out of markers.
+ * find where to start looking for a hot key
+ */
+ i = 0;
+ /* skip white space */
+ while (i < org_len && org[i] == ' ')
+ i++;
+ if (i == org_len)
+ return -1;
+ /* if encountering '(' or '<' or '[', find the match and look from there
+ **/
+ if (org[i] == '[' || org[i] == '<' || org[i] == '(') {
+ i++;
+ for (; i < org_len; i++)
+ if (org[i] == ']' || org[i] == '>' || org[i] == ')')
+ break;
+ }
+ if (i == org_len)
+ return -1;
+ for (; i < org_len; i++) {
+ if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') {
+ position = i;
+ break;
+ }
+ }
+ if (position == -1)
+ return 1;
+
+ /* ok, char at org[position] should be a hot key to this item */
+ c = tolower(org[position]);
+ tmp = hotkeys[c].count;
+ hotkeys[c].ptrs[tmp] = index;
+ hotkeys[c].count++;
+ /*
+ snprintf(dest, len, "%.*s(%c)%s", position, org, org[position],
+ &org[position+1]);
+ */
+ /* make org[position] uppercase, and all leading letter small case */
+ strncpy(dest, org, len);
+ for (i = 0; i < position; i++)
+ dest[i] = tolower(dest[i]);
+ dest[position] = toupper(dest[position]);
+ k_menu_items[index].is_hot = 1;
+ return 0;
+}
+
+/* Make a new item. Add a hotkey mark in the first possible letter.
+ * As ncurses does not allow any attributes inside menue item, we mark the
+ * hot key as the first capitalized letter in the string */
+static void item_make(struct menu *menu, char tag, const char *fmt, ...)
+{
+ va_list ap;
+ char tmp_str[256];
+
+ if (items_num > MAX_MENU_ITEMS-1)
+ return;
+
+ bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
+ k_menu_items[items_num].tag = tag;
+ k_menu_items[items_num].usrptr = menu;
+ if (menu != NULL)
+ k_menu_items[items_num].is_visible =
+ menu_is_visible(menu);
+ else
+ k_menu_items[items_num].is_visible = 1;
+
+ va_start(ap, fmt);
+ vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap);
+ if (!k_menu_items[items_num].is_visible)
+ memcpy(tmp_str, "XXX", 3);
+ va_end(ap);
+ if (make_hot(
+ k_menu_items[items_num].str,
+ sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0)
+ strncpy(k_menu_items[items_num].str,
+ tmp_str,
+ sizeof(k_menu_items[items_num].str));
+
+ curses_menu_items[items_num] = new_item(
+ k_menu_items[items_num].str,
+ k_menu_items[items_num].str);
+ set_item_userptr(curses_menu_items[items_num],
+ &k_menu_items[items_num]);
+ /*
+ if (!k_menu_items[items_num].is_visible)
+ item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
+ */
+
+ items_num++;
+ curses_menu_items[items_num] = NULL;
+}
+
+/* very hackish. adds a string to the last item added */
+static void item_add_str(const char *fmt, ...)
+{
+ va_list ap;
+ int index = items_num-1;
+ char new_str[256];
+ char tmp_str[256];
+
+ if (index < 0)
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(new_str, sizeof(new_str), fmt, ap);
+ va_end(ap);
+ snprintf(tmp_str, sizeof(tmp_str), "%s%s",
+ k_menu_items[index].str, new_str);
+ if (make_hot(k_menu_items[index].str,
+ sizeof(k_menu_items[index].str), tmp_str, index) != 0)
+ strncpy(k_menu_items[index].str,
+ tmp_str,
+ sizeof(k_menu_items[index].str));
+
+ free_item(curses_menu_items[index]);
+ curses_menu_items[index] = new_item(
+ k_menu_items[index].str,
+ k_menu_items[index].str);
+ set_item_userptr(curses_menu_items[index],
+ &k_menu_items[index]);
+}
+
+/* get the tag of the currently selected item */
+static char item_tag(void)
+{
+ ITEM *cur;
+ struct mitem *mcur;
+
+ cur = current_item(curses_menu);
+ if (cur == NULL)
+ return 0;
+ mcur = (struct mitem *) item_userptr(cur);
+ return mcur->tag;
+}
+
+static int curses_item_index(void)
+{
+ return item_index(current_item(curses_menu));
+}
+
+static void *item_data(void)
+{
+ ITEM *cur;
+ struct mitem *mcur;
+
+ cur = current_item(curses_menu);
+ mcur = (struct mitem *) item_userptr(cur);
+ return mcur->usrptr;
+
+}
+
+static int item_is_tag(char tag)
+{
+ return item_tag() == tag;
+}
+
+static char filename[PATH_MAX+1];
+static char menu_backtitle[PATH_MAX+128];
+static const char *set_config_filename(const char *config_filename)
+{
+ int size;
+ struct symbol *sym;
+
+ sym = sym_lookup("KERNELVERSION", 0);
+ sym_calc_value(sym);
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+ _("%s - Linux Kernel v%s Configuration"),
+ config_filename, sym_get_string_value(sym));
+ if (size >= sizeof(menu_backtitle))
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
+ if (size >= sizeof(filename))
+ filename[sizeof(filename)-1] = '\0';
+ return menu_backtitle;
+}
+
+/* command = 0 is supress, 1 is restore */
+static void supress_stdout(int command)
+{
+ static FILE *org_stdout;
+ static FILE *org_stderr;
+
+ if (command == 0) {
+ org_stdout = stdout;
+ org_stderr = stderr;
+ stdout = fopen("/dev/null", "a");
+ stderr = fopen("/dev/null", "a");
+ } else {
+ fclose(stdout);
+ fclose(stderr);
+ stdout = org_stdout;
+ stderr = org_stderr;
+ }
+}
+
+/* return = 0 means we are successful.
+ * -1 means go on doing what you were doing
+ */
+static int do_exit(void)
+{
+ int res;
+ if (!conf_get_changed()) {
+ global_exit = 1;
+ return 0;
+ }
+ res = btn_dialog(main_window,
+ _("Do you wish to save your "
+ "new kernel configuration?\n"
+ "<ESC> to cancel and resume nconfig."),
+ 2,
+ " <save> ",
+ "<don't save>");
+ if (res == KEY_EXIT) {
+ global_exit = 0;
+ return -1;
+ }
+
+ /* if we got here, the user really wants to exit */
+ switch (res) {
+ case 0:
+ supress_stdout(0);
+ res = conf_write(filename);
+ supress_stdout(1);
+ if (res)
+ btn_dialog(
+ main_window,
+ _("Error during writing of the kernel "
+ "configuration.\n"
+ "Your kernel configuration "
+ "changes were NOT saved."),
+ 1,
+ "<OK>");
+ else {
+ char buf[1024];
+ snprintf(buf, 1024,
+ _("Configuration written to %s\n"
+ "End of Linux kernel configuration.\n"
+ "Execute 'make' to build the kernel or try"
+ " 'make help'."), filename);
+ btn_dialog(
+ main_window,
+ buf,
+ 1,
+ "<OK>");
+ }
+ break;
+ default:
+ btn_dialog(
+ main_window,
+ _("Your kernel configuration changes were NOT saved."),
+ 1,
+ "<OK>");
+ break;
+ }
+ global_exit = 1;
+ return 0;
+}
+
+
+static void search_conf(void)
+{
+ struct symbol **sym_arr;
+ struct gstr res;
+ char dialog_input_result[100];
+ char *dialog_input;
+ int dres;
+again:
+ dres = dialog_inputbox(main_window,
+ _("Search Configuration Parameter"),
+ _("Enter CONFIG_ (sub)string to search for "
+ "(with or without \"CONFIG\")"),
+ "", dialog_input_result, 99);
+ switch (dres) {
+ case 0:
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Search Configuration"), search_help);
+ goto again;
+ default:
+ return;
+ }
+
+ /* strip CONFIG_ if necessary */
+ dialog_input = dialog_input_result;
+ if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
+ dialog_input += 7;
+
+ sym_arr = sym_re_search(dialog_input);
+ res = get_relations_str(sym_arr);
+ free(sym_arr);
+ show_scroll_win(main_window,
+ _("Search Results"), str_get(&res));
+ str_free(&res);
+}
+
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+
+ if (!menu || (!show_all_items && !menu_is_visible(menu)))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ enum prop_type ptype;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ switch (ptype) {
+ case P_MENU:
+ child_count++;
+ prompt = _(prompt);
+ if (single_menu_mode) {
+ item_make(menu, 'm',
+ "%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
+ } else
+ item_make(menu, 'm',
+ " %*c%s --->",
+ indent + 1,
+ ' ', prompt);
+
+ if (single_menu_mode && menu->data)
+ goto conf_childs;
+ return;
+ case P_COMMENT:
+ if (prompt) {
+ child_count++;
+ item_make(menu, ':',
+ " %*c*** %s ***",
+ indent + 1, ' ',
+ _(prompt));
+ }
+ break;
+ default:
+ if (prompt) {
+ child_count++;
+ item_make(menu, ':', "---%*c%s",
+ indent + 1, ' ',
+ _(prompt));
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ switch (type) {
+ case S_BOOLEAN:
+ item_make(menu, 't', "[%c]",
+ val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes:
+ ch = '*';
+ break;
+ case mod:
+ ch = 'M';
+ break;
+ default:
+ ch = ' ';
+ break;
+ }
+ item_make(menu, 't', "<%c>", ch);
+ break;
+ }
+ } else {
+ item_make(menu, def_menu ? 't' : ':', " ");
+ }
+
+ item_add_str("%*c%s", indent + 1,
+ ' ', _(menu_get_prompt(menu)));
+ if (val == yes) {
+ if (def_menu) {
+ item_add_str(" (%s)",
+ _(menu_get_prompt(def_menu)));
+ item_add_str(" --->");
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ }
+ return;
+ }
+ } else {
+ if (menu == current_menu) {
+ item_make(menu, ':',
+ "---%*c%s", indent + 1,
+ ' ', _(menu_get_prompt(menu)));
+ goto conf_childs;
+ }
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ item_make(menu, ':', " ");
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ if (sym_is_changable(sym))
+ item_make(menu, 't', "[%c]",
+ val == no ? ' ' : '*');
+ else
+ item_make(menu, 't', "-%c-",
+ val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes:
+ ch = '*';
+ break;
+ case mod:
+ ch = 'M';
+ break;
+ default:
+ ch = ' ';
+ break;
+ }
+ if (sym_is_changable(sym)) {
+ if (sym->rev_dep.tri == mod)
+ item_make(menu,
+ 't', "{%c}", ch);
+ else
+ item_make(menu,
+ 't', "<%c>", ch);
+ } else
+ item_make(menu, 't', "-%c-", ch);
+ break;
+ default:
+ tmp = 2 + strlen(sym_get_string_value(sym));
+ item_make(menu, 's', " (%s)",
+ sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ item_add_str("%*c%s%s", tmp, ' ',
+ _(menu_get_prompt(menu)),
+ (sym_has_value(sym) ||
+ !sym_is_changable(sym)) ? "" :
+ _(" (NEW)"));
+ goto conf_childs;
+ }
+ }
+ item_add_str("%*c%s%s", indent + 1, ' ',
+ _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ if (menu->prompt && menu->prompt->type == P_MENU) {
+ item_add_str(" --->");
+ return;
+ }
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void reset_menu(void)
+{
+ unpost_menu(curses_menu);
+ clean_items();
+}
+
+/* adjust the menu to show this item.
+ * prefer not to scroll the menu if possible*/
+static void center_item(int selected_index, int *last_top_row)
+{
+ int toprow;
+ int maxy, maxx;
+
+ scale_menu(curses_menu, &maxy, &maxx);
+ set_top_row(curses_menu, *last_top_row);
+ toprow = top_row(curses_menu);
+ if (selected_index >= toprow && selected_index < toprow+maxy) {
+ /* we can only move the selected item. no need to scroll */
+ set_current_item(curses_menu,
+ curses_menu_items[selected_index]);
+ } else {
+ toprow = max(selected_index-maxy/2, 0);
+ if (toprow >= item_count(curses_menu)-maxy)
+ toprow = item_count(curses_menu)-mwin_max_lines;
+ set_top_row(curses_menu, toprow);
+ set_current_item(curses_menu,
+ curses_menu_items[selected_index]);
+ }
+ *last_top_row = toprow;
+ post_menu(curses_menu);
+ refresh_all_windows(main_window);
+}
+
+/* this function assumes reset_menu has been called before */
+static void show_menu(const char *prompt, const char *instructions,
+ int selected_index, int *last_top_row)
+{
+ int maxx, maxy;
+ WINDOW *menu_window;
+
+ current_instructions = instructions;
+
+ clear();
+ wattrset(main_window, attributes[NORMAL]);
+ print_in_middle(stdscr, 1, 0, COLS,
+ menu_backtitle,
+ attributes[MAIN_HEADING]);
+
+ wattrset(main_window, attributes[MAIN_MENU_BOX]);
+ box(main_window, 0, 0);
+ wattrset(main_window, attributes[MAIN_MENU_HEADING]);
+ mvwprintw(main_window, 0, 3, " %s ", prompt);
+ wattrset(main_window, attributes[NORMAL]);
+
+ set_menu_items(curses_menu, curses_menu_items);
+
+ /* position the menu at the middle of the screen */
+ scale_menu(curses_menu, &maxy, &maxx);
+ maxx = min(maxx, mwin_max_cols-2);
+ maxy = mwin_max_lines-2;
+ menu_window = derwin(main_window,
+ maxy,
+ maxx,
+ 2,
+ (mwin_max_cols-maxx)/2);
+ keypad(menu_window, TRUE);
+ set_menu_win(curses_menu, menu_window);
+ set_menu_sub(curses_menu, menu_window);
+
+ /* must reassert this after changing items, otherwise returns to a
+ * default of 16
+ */
+ set_menu_format(curses_menu, maxy, 1);
+ center_item(selected_index, last_top_row);
+ set_menu_format(curses_menu, maxy, 1);
+
+ print_function_line();
+
+ /* Post the menu */
+ post_menu(curses_menu);
+ refresh_all_windows(main_window);
+}
+
+
+static void conf(struct menu *menu)
+{
+ char pattern[256];
+ struct menu *submenu = 0;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ struct menu *active_menu = NULL;
+ int res;
+ int current_index = 0;
+ int last_top_row = 0;
+
+ bzero(pattern, sizeof(pattern));
+
+ while (!global_exit) {
+ reset_menu();
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+
+ show_menu(prompt ? _(prompt) : _("Main Menu"),
+ _(menu_instructions),
+ current_index, &last_top_row);
+ keypad((menu_win(curses_menu)), TRUE);
+ while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
+ if (process_special_keys(&res,
+ (struct menu *) item_data()))
+ break;
+ switch (res) {
+ case KEY_DOWN:
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
+ break;
+ case KEY_UP:
+ menu_driver(curses_menu, REQ_UP_ITEM);
+ break;
+ case KEY_NPAGE:
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
+ break;
+ case KEY_PPAGE:
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
+ break;
+ case KEY_HOME:
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
+ break;
+ case KEY_END:
+ menu_driver(curses_menu, REQ_LAST_ITEM);
+ break;
+ case 'h':
+ case '?':
+ show_help((struct menu *) item_data());
+ break;
+ }
+ if (res == 10 || res == 27 ||
+ res == 32 || res == 'n' || res == 'y' ||
+ res == KEY_LEFT || res == KEY_RIGHT ||
+ res == 'm' || res == '/')
+ break;
+ else if (canbhot(res)) {
+ /* check for hot keys: */
+ int tmp = get_next_hot(res);
+ if (tmp != -1)
+ center_item(tmp, &last_top_row);
+ }
+ refresh_all_windows(main_window);
+ }
+
+ refresh_all_windows(main_window);
+ /* if ESC or left*/
+ if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
+ break;
+
+ /* remember location in the menu */
+ last_top_row = top_row(curses_menu);
+ current_index = curses_item_index();
+
+ if (!item_tag())
+ continue;
+
+ submenu = (struct menu *) item_data();
+ active_menu = (struct menu *)item_data();
+ if (!submenu || !menu_is_visible(submenu))
+ continue;
+ if (submenu)
+ sym = submenu->sym;
+ else
+ sym = NULL;
+
+ switch (res) {
+ case ' ':
+ if (item_is_tag('t'))
+ sym_toggle_tristate_value(sym);
+ else if (item_is_tag('m'))
+ conf(submenu);
+ break;
+ case KEY_RIGHT:
+ case 10: /* ENTER WAS PRESSED */
+ switch (item_tag()) {
+ case 'm':
+ if (single_menu_mode)
+ submenu->data =
+ (void *) (long) !submenu->data;
+ else
+ conf(submenu);
+ break;
+ case 't':
+ if (sym_is_choice(sym) &&
+ sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ else if (submenu->prompt &&
+ submenu->prompt->type == P_MENU)
+ conf(submenu);
+ else if (res == 10)
+ sym_toggle_tristate_value(sym);
+ break;
+ case 's':
+ conf_string(submenu);
+ break;
+ }
+ break;
+ case 'y':
+ if (item_is_tag('t')) {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ btn_dialog(main_window, setmod_text, 0);
+ }
+ break;
+ case 'n':
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, no);
+ break;
+ case 'm':
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, mod);
+ break;
+ case '/':
+ search_conf();
+ break;
+ }
+ }
+}
+
+static void show_help(struct menu *menu)
+{
+ struct gstr help = str_new();
+
+ if (menu && menu->sym && menu_has_help(menu)) {
+ if (menu->sym->name) {
+ str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name);
+ str_append(&help, _(menu_get_help(menu)));
+ str_append(&help, "\n");
+ get_symbol_str(&help, menu->sym);
+ }
+ } else {
+ str_append(&help, nohelp_text);
+ }
+ show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
+ str_free(&help);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = _(menu_get_prompt(menu));
+ struct menu *child = 0;
+ struct symbol *active;
+ int selected_index = 0;
+ int last_top_row = 0;
+ int res, i = 0;
+
+ active = sym_get_choice_value(menu->sym);
+ /* this is mostly duplicated from the conf() function. */
+ while (!global_exit) {
+ reset_menu();
+
+ for (i = 0, child = menu->list; child; child = child->next) {
+ if (!show_all_items && !menu_is_visible(child))
+ continue;
+
+ if (child->sym == sym_get_choice_value(menu->sym))
+ item_make(child, ':', "<X> %s",
+ _(menu_get_prompt(child)));
+ else
+ item_make(child, ':', " %s",
+ _(menu_get_prompt(child)));
+ if (child->sym == active){
+ last_top_row = top_row(curses_menu);
+ selected_index = i;
+ }
+ i++;
+ }
+ show_menu(prompt ? _(prompt) : _("Choice Menu"),
+ _(radiolist_instructions),
+ selected_index,
+ &last_top_row);
+ while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
+ if (process_special_keys(
+ &res,
+ (struct menu *) item_data()))
+ break;
+ switch (res) {
+ case KEY_DOWN:
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
+ break;
+ case KEY_UP:
+ menu_driver(curses_menu, REQ_UP_ITEM);
+ break;
+ case KEY_NPAGE:
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
+ break;
+ case KEY_PPAGE:
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
+ break;
+ case KEY_HOME:
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
+ break;
+ case KEY_END:
+ menu_driver(curses_menu, REQ_LAST_ITEM);
+ break;
+ case 'h':
+ case '?':
+ show_help((struct menu *) item_data());
+ break;
+ }
+ if (res == 10 || res == 27 || res == ' ' ||
+ res == KEY_LEFT)
+ break;
+ else if (canbhot(res)) {
+ /* check for hot keys: */
+ int tmp = get_next_hot(res);
+ if (tmp != -1)
+ center_item(tmp, &last_top_row);
+ }
+ refresh_all_windows(main_window);
+ }
+ /* if ESC or left */
+ if (res == 27 || res == KEY_LEFT)
+ break;
+
+ child = item_data();
+ if (!child || !menu_is_visible(child))
+ continue;
+ switch (res) {
+ case ' ':
+ case 10:
+ case KEY_RIGHT:
+ sym_set_tristate_value(child->sym, yes);
+ return;
+ case 'h':
+ case '?':
+ show_help(child);
+ active = child->sym;
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+ char dialog_input_result[256];
+
+ while (1) {
+ int res;
+ const char *heading;
+
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ heading = _(inputbox_instructions_int);
+ break;
+ case S_HEX:
+ heading = _(inputbox_instructions_hex);
+ break;
+ case S_STRING:
+ heading = _(inputbox_instructions_string);
+ break;
+ default:
+ heading = _("Internal nconf error!");
+ }
+ res = dialog_inputbox(main_window,
+ prompt ? _(prompt) : _("Main Menu"),
+ heading,
+ sym_get_string_value(menu->sym),
+ dialog_input_result,
+ sizeof(dialog_input_result));
+ switch (res) {
+ case 0:
+ if (sym_set_string_value(menu->sym,
+ dialog_input_result))
+ return;
+ btn_dialog(main_window,
+ _("You have made an invalid entry."), 0);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+ char dialog_input_result[256];
+ while (1) {
+ int res;
+ res = dialog_inputbox(main_window,
+ NULL, load_config_text,
+ filename,
+ dialog_input_result,
+ sizeof(dialog_input_result));
+ switch (res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_read(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ sym_set_change_count(1);
+ return;
+ }
+ btn_dialog(main_window, _("File does not exist!"), 0);
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Load Alternate Configuration"),
+ load_config_help);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ char dialog_input_result[256];
+ while (1) {
+ int res;
+ res = dialog_inputbox(main_window,
+ NULL, save_config_text,
+ filename,
+ dialog_input_result,
+ sizeof(dialog_input_result));
+ switch (res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ supress_stdout(0);
+ res = conf_write(dialog_input_result);
+ supress_stdout(1);
+ if (!res) {
+ char buf[1024];
+ sprintf(buf, "%s %s",
+ _("configuration file saved to: "),
+ dialog_input_result);
+ btn_dialog(main_window,
+ buf, 1, "<OK>");
+ set_config_filename(dialog_input_result);
+ return;
+ }
+ btn_dialog(main_window, _("Can't create file! "
+ "Probably a nonexistent directory."),
+ 1, "<OK>");
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Save Alternate Configuration"),
+ save_config_help);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+void setup_windows(void)
+{
+ if (main_window != NULL)
+ delwin(main_window);
+
+ /* set up the menu and menu window */
+ main_window = newwin(LINES-2, COLS-2, 2, 1);
+ keypad(main_window, TRUE);
+ mwin_max_lines = LINES-6;
+ mwin_max_cols = COLS-6;
+
+ /* panels order is from bottom to top */
+ new_panel(main_window);
+}
+
+int main(int ac, char **av)
+{
+ char *mode;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ mode = getenv("NCONFIG_MODE");
+ if (mode) {
+ if (!strcasecmp(mode, "single_menu"))
+ single_menu_mode = 1;
+ }
+
+ /* Initialize curses */
+ initscr();
+ /* set color theme */
+ set_colors();
+
+ cbreak();
+ noecho();
+ keypad(stdscr, TRUE);
+ curs_set(0);
+
+ if (COLS < 75 || LINES < 20) {
+ endwin();
+ printf("Your terminal should have at "
+ "least 20 lines and 75 columns\n");
+ return 1;
+ }
+
+ notimeout(stdscr, FALSE);
+ ESCDELAY = 1;
+
+ /* set btns menu */
+ curses_menu = new_menu(curses_menu_items);
+ menu_opts_off(curses_menu, O_SHOWDESC);
+ menu_opts_off(curses_menu, O_SHOWMATCH);
+ menu_opts_on(curses_menu, O_ONEVALUE);
+ menu_opts_on(curses_menu, O_NONCYCLIC);
+ set_menu_mark(curses_menu, " ");
+ set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
+ set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
+ set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
+
+ set_config_filename(conf_get_configname());
+ setup_windows();
+
+ /* check for KEY_FUNC(1) */
+ if (has_key(KEY_F(1)) == FALSE) {
+ show_scroll_win(main_window,
+ _("Instructions"),
+ _(menu_no_f_instructions));
+ }
+
+
+
+ /* do the work */
+ while (!global_exit) {
+ conf(&rootmenu);
+ if (!global_exit && do_exit() == 0)
+ break;
+ }
+ /* ok, we are done */
+ unpost_menu(curses_menu);
+ free_menu(curses_menu);
+ delwin(main_window);
+ clear();
+ refresh();
+ endwin();
+ return 0;
+}
+
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
new file mode 100644
index 0000000..115edb4
--- /dev/null
+++ b/scripts/kconfig/nconf.gui.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#include "nconf.h"
+
+/* a list of all the different widgets we use */
+attributes_t attributes[ATTR_MAX+1] = {0};
+
+/* available colors:
+ COLOR_BLACK 0
+ COLOR_RED 1
+ COLOR_GREEN 2
+ COLOR_YELLOW 3
+ COLOR_BLUE 4
+ COLOR_MAGENTA 5
+ COLOR_CYAN 6
+ COLOR_WHITE 7
+ */
+static void set_normal_colors(void)
+{
+ init_pair(NORMAL, -1, -1);
+ init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
+
+ /* FORE is for the selected item */
+ init_pair(MAIN_MENU_FORE, -1, -1);
+ /* BACK for all the rest */
+ init_pair(MAIN_MENU_BACK, -1, -1);
+ init_pair(MAIN_MENU_GREY, -1, -1);
+ init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
+ init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
+
+ init_pair(SCROLLWIN_TEXT, -1, -1);
+ init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
+ init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
+
+ init_pair(DIALOG_TEXT, -1, -1);
+ init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
+ init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
+ init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
+
+ init_pair(INPUT_BOX, COLOR_YELLOW, -1);
+ init_pair(INPUT_HEADING, COLOR_GREEN, -1);
+ init_pair(INPUT_TEXT, -1, -1);
+ init_pair(INPUT_FIELD, -1, -1);
+
+ init_pair(FUNCTION_HIGHLIGHT, -1, -1);
+ init_pair(FUNCTION_TEXT, COLOR_BLUE, -1);
+}
+
+/* available attributes:
+ A_NORMAL Normal display (no highlight)
+ A_STANDOUT Best highlighting mode of the terminal.
+ A_UNDERLINE Underlining
+ A_REVERSE Reverse video
+ A_BLINK Blinking
+ A_DIM Half bright
+ A_BOLD Extra bright or bold
+ A_PROTECT Protected mode
+ A_INVIS Invisible or blank mode
+ A_ALTCHARSET Alternate character set
+ A_CHARTEXT Bit-mask to extract a character
+ COLOR_PAIR(n) Color-pair number n
+ */
+static void normal_color_theme(void)
+{
+ /* automatically add color... */
+#define mkattr(name, attr) do { \
+attributes[name] = attr | COLOR_PAIR(name); } while (0)
+ mkattr(NORMAL, NORMAL);
+ mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+ mkattr(MAIN_MENU_FORE, A_REVERSE);
+ mkattr(MAIN_MENU_BACK, A_NORMAL);
+ mkattr(MAIN_MENU_GREY, A_NORMAL);
+ mkattr(MAIN_MENU_HEADING, A_BOLD);
+ mkattr(MAIN_MENU_BOX, A_NORMAL);
+
+ mkattr(SCROLLWIN_TEXT, A_NORMAL);
+ mkattr(SCROLLWIN_HEADING, A_BOLD);
+ mkattr(SCROLLWIN_BOX, A_BOLD);
+
+ mkattr(DIALOG_TEXT, A_BOLD);
+ mkattr(DIALOG_BOX, A_BOLD);
+ mkattr(DIALOG_MENU_FORE, A_STANDOUT);
+ mkattr(DIALOG_MENU_BACK, A_NORMAL);
+
+ mkattr(INPUT_BOX, A_NORMAL);
+ mkattr(INPUT_HEADING, A_BOLD);
+ mkattr(INPUT_TEXT, A_NORMAL);
+ mkattr(INPUT_FIELD, A_UNDERLINE);
+
+ mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
+ mkattr(FUNCTION_TEXT, A_REVERSE);
+}
+
+static void no_colors_theme(void)
+{
+ /* automatically add highlight, no color */
+#define mkattrn(name, attr) { attributes[name] = attr; }
+
+ mkattrn(NORMAL, NORMAL);
+ mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+ mkattrn(MAIN_MENU_FORE, A_STANDOUT);
+ mkattrn(MAIN_MENU_BACK, A_NORMAL);
+ mkattrn(MAIN_MENU_GREY, A_NORMAL);
+ mkattrn(MAIN_MENU_HEADING, A_BOLD);
+ mkattrn(MAIN_MENU_BOX, A_NORMAL);
+
+ mkattrn(SCROLLWIN_TEXT, A_NORMAL);
+ mkattrn(SCROLLWIN_HEADING, A_BOLD);
+ mkattrn(SCROLLWIN_BOX, A_BOLD);
+
+ mkattrn(DIALOG_TEXT, A_NORMAL);
+ mkattrn(DIALOG_BOX, A_BOLD);
+ mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
+ mkattrn(DIALOG_MENU_BACK, A_NORMAL);
+
+ mkattrn(INPUT_BOX, A_BOLD);
+ mkattrn(INPUT_HEADING, A_BOLD);
+ mkattrn(INPUT_TEXT, A_NORMAL);
+ mkattrn(INPUT_FIELD, A_UNDERLINE);
+
+ mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
+ mkattrn(FUNCTION_TEXT, A_REVERSE);
+}
+
+void set_colors()
+{
+ start_color();
+ use_default_colors();
+ set_normal_colors();
+ if (has_colors()) {
+ normal_color_theme();
+ } else {
+ /* give deafults */
+ no_colors_theme();
+ }
+}
+
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+ int starty,
+ int startx,
+ int width,
+ const char *string,
+ chtype color)
+{ int length, x, y;
+ float temp;
+
+
+ if (win == NULL)
+ win = stdscr;
+ getyx(win, y, x);
+ if (startx != 0)
+ x = startx;
+ if (starty != 0)
+ y = starty;
+ if (width == 0)
+ width = 80;
+
+ length = strlen(string);
+ temp = (width - length) / 2;
+ x = startx + (int)temp;
+ wattrset(win, color);
+ mvwprintw(win, y, x, "%s", string);
+ refresh();
+}
+
+int get_line_no(const char *text)
+{
+ int i;
+ int total = 1;
+
+ if (!text)
+ return 0;
+
+ for (i = 0; text[i] != '\0'; i++)
+ if (text[i] == '\n')
+ total++;
+ return total;
+}
+
+const char *get_line(const char *text, int line_no)
+{
+ int i;
+ int lines = 0;
+
+ if (!text)
+ return 0;
+
+ for (i = 0; text[i] != '\0' && lines < line_no; i++)
+ if (text[i] == '\n')
+ lines++;
+ return text+i;
+}
+
+int get_line_length(const char *line)
+{
+ int res = 0;
+ while (*line != '\0' && *line != '\n') {
+ line++;
+ res++;
+ }
+ return res;
+}
+
+/* print all lines to the window. */
+void fill_window(WINDOW *win, const char *text)
+{
+ int x, y;
+ int total_lines = get_line_no(text);
+ int i;
+
+ getmaxyx(win, y, x);
+ /* do not go over end of line */
+ total_lines = min(total_lines, y);
+ for (i = 0; i < total_lines; i++) {
+ char tmp[x+10];
+ const char *line = get_line(text, i);
+ int len = get_line_length(line);
+ strncpy(tmp, line, min(len, x));
+ tmp[len] = '\0';
+ mvwprintw(win, i, 0, tmp);
+ }
+}
+
+/* get the message, and buttons.
+ * each button must be a char*
+ * return the selected button
+ *
+ * this dialog is used for 2 different things:
+ * 1) show a text box, no buttons.
+ * 2) show a dialog, with horizontal buttons
+ */
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
+{
+ va_list ap;
+ char *btn;
+ int btns_width = 0;
+ int msg_lines = 0;
+ int msg_width = 0;
+ int total_width;
+ int win_rows = 0;
+ WINDOW *win;
+ WINDOW *msg_win;
+ WINDOW *menu_win;
+ MENU *menu;
+ ITEM *btns[btn_num+1];
+ int i, x, y;
+ int res = -1;
+
+
+ va_start(ap, btn_num);
+ for (i = 0; i < btn_num; i++) {
+ btn = va_arg(ap, char *);
+ btns[i] = new_item(btn, "");
+ btns_width += strlen(btn)+1;
+ }
+ va_end(ap);
+ btns[btn_num] = NULL;
+
+ /* find the widest line of msg: */
+ msg_lines = get_line_no(msg);
+ for (i = 0; i < msg_lines; i++) {
+ const char *line = get_line(msg, i);
+ int len = get_line_length(line);
+ if (msg_width < len)
+ msg_width = len;
+ }
+
+ total_width = max(msg_width, btns_width);
+ /* place dialog in middle of screen */
+ y = (LINES-(msg_lines+4))/2;
+ x = (COLS-(total_width+4))/2;
+
+
+ /* create the windows */
+ if (btn_num > 0)
+ win_rows = msg_lines+4;
+ else
+ win_rows = msg_lines+2;
+
+ win = newwin(win_rows, total_width+4, y, x);
+ keypad(win, TRUE);
+ menu_win = derwin(win, 1, btns_width, win_rows-2,
+ 1+(total_width+2-btns_width)/2);
+ menu = new_menu(btns);
+ msg_win = derwin(win, win_rows-2, msg_width, 1,
+ 1+(total_width+2-msg_width)/2);
+
+ set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
+ set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
+
+ wattrset(win, attributes[DIALOG_BOX]);
+ box(win, 0, 0);
+
+ /* print message */
+ wattrset(msg_win, attributes[DIALOG_TEXT]);
+ fill_window(msg_win, msg);
+
+ set_menu_win(menu, win);
+ set_menu_sub(menu, menu_win);
+ set_menu_format(menu, 1, btn_num);
+ menu_opts_off(menu, O_SHOWDESC);
+ menu_opts_off(menu, O_SHOWMATCH);
+ menu_opts_on(menu, O_ONEVALUE);
+ menu_opts_on(menu, O_NONCYCLIC);
+ set_menu_mark(menu, "");
+ post_menu(menu);
+
+
+ touchwin(win);
+ refresh_all_windows(main_window);
+ while ((res = wgetch(win))) {
+ switch (res) {
+ case KEY_LEFT:
+ menu_driver(menu, REQ_LEFT_ITEM);
+ break;
+ case KEY_RIGHT:
+ menu_driver(menu, REQ_RIGHT_ITEM);
+ break;
+ case 10: /* ENTER */
+ case 27: /* ESCAPE */
+ case ' ':
+ case KEY_F(F_BACK):
+ case KEY_F(F_EXIT):
+ break;
+ }
+ touchwin(win);
+ refresh_all_windows(main_window);
+
+ if (res == 10 || res == ' ') {
+ res = item_index(current_item(menu));
+ break;
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT)) {
+ res = KEY_EXIT;
+ break;
+ }
+ }
+
+ unpost_menu(menu);
+ free_menu(menu);
+ for (i = 0; i < btn_num; i++)
+ free_item(btns[i]);
+
+ delwin(win);
+ return res;
+}
+
+int dialog_inputbox(WINDOW *main_window,
+ const char *title, const char *prompt,
+ const char *init, char *result, int result_len)
+{
+ int prompt_lines = 0;
+ int prompt_width = 0;
+ WINDOW *win;
+ WINDOW *prompt_win;
+ WINDOW *form_win;
+ PANEL *panel;
+ int i, x, y;
+ int res = -1;
+ int cursor_position = strlen(init);
+
+
+ /* find the widest line of msg: */
+ prompt_lines = get_line_no(prompt);
+ for (i = 0; i < prompt_lines; i++) {
+ const char *line = get_line(prompt, i);
+ int len = get_line_length(line);
+ prompt_width = max(prompt_width, len);
+ }
+
+ if (title)
+ prompt_width = max(prompt_width, strlen(title));
+
+ /* place dialog in middle of screen */
+ y = (LINES-(prompt_lines+4))/2;
+ x = (COLS-(prompt_width+4))/2;
+
+ strncpy(result, init, result_len);
+
+ /* create the windows */
+ win = newwin(prompt_lines+6, prompt_width+7, y, x);
+ prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
+ form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
+ keypad(form_win, TRUE);
+
+ wattrset(form_win, attributes[INPUT_FIELD]);
+
+ wattrset(win, attributes[INPUT_BOX]);
+ box(win, 0, 0);
+ wattrset(win, attributes[INPUT_HEADING]);
+ if (title)
+ mvwprintw(win, 0, 3, "%s", title);
+
+ /* print message */
+ wattrset(prompt_win, attributes[INPUT_TEXT]);
+ fill_window(prompt_win, prompt);
+
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+ mvwprintw(form_win, 0, 0, "%s", result);
+
+ /* create panels */
+ panel = new_panel(win);
+
+ /* show the cursor */
+ curs_set(1);
+
+ touchwin(win);
+ refresh_all_windows(main_window);
+ while ((res = wgetch(form_win))) {
+ int len = strlen(result);
+ switch (res) {
+ case 10: /* ENTER */
+ case 27: /* ESCAPE */
+ case KEY_F(F_HELP):
+ case KEY_F(F_EXIT):
+ case KEY_F(F_BACK):
+ break;
+ case 127:
+ case KEY_BACKSPACE:
+ if (cursor_position > 0) {
+ memmove(&result[cursor_position-1],
+ &result[cursor_position],
+ len-cursor_position+1);
+ cursor_position--;
+ }
+ break;
+ case KEY_DC:
+ if (cursor_position >= 0 && cursor_position < len) {
+ memmove(&result[cursor_position],
+ &result[cursor_position+1],
+ len-cursor_position+1);
+ }
+ break;
+ case KEY_UP:
+ case KEY_RIGHT:
+ if (cursor_position < len &&
+ cursor_position < min(result_len, prompt_width))
+ cursor_position++;
+ break;
+ case KEY_DOWN:
+ case KEY_LEFT:
+ if (cursor_position > 0)
+ cursor_position--;
+ break;
+ default:
+ if ((isgraph(res) || isspace(res)) &&
+ len-2 < result_len) {
+ /* insert the char at the proper position */
+ memmove(&result[cursor_position+1],
+ &result[cursor_position],
+ len+1);
+ result[cursor_position] = res;
+ cursor_position++;
+ } else {
+ mvprintw(0, 0, "unknow key: %d\n", res);
+ }
+ break;
+ }
+ wmove(form_win, 0, 0);
+ wclrtoeol(form_win);
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+ mvwprintw(form_win, 0, 0, "%s", result);
+ wmove(form_win, 0, cursor_position);
+ touchwin(win);
+ refresh_all_windows(main_window);
+
+ if (res == 10) {
+ res = 0;
+ break;
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT)) {
+ res = KEY_EXIT;
+ break;
+ } else if (res == KEY_F(F_HELP)) {
+ res = 1;
+ break;
+ }
+ }
+
+ /* hide the cursor */
+ curs_set(0);
+ del_panel(panel);
+ delwin(prompt_win);
+ delwin(form_win);
+ delwin(win);
+ return res;
+}
+
+/* refresh all windows in the correct order */
+void refresh_all_windows(WINDOW *main_window)
+{
+ update_panels();
+ touchwin(main_window);
+ refresh();
+}
+
+/* layman's scrollable window... */
+void show_scroll_win(WINDOW *main_window,
+ const char *title,
+ const char *text)
+{
+ int res;
+ int total_lines = get_line_no(text);
+ int x, y;
+ int start_x = 0, start_y = 0;
+ int text_lines = 0, text_cols = 0;
+ int total_cols = 0;
+ int win_cols = 0;
+ int win_lines = 0;
+ int i = 0;
+ WINDOW *win;
+ WINDOW *pad;
+ PANEL *panel;
+
+ /* find the widest line of msg: */
+ total_lines = get_line_no(text);
+ for (i = 0; i < total_lines; i++) {
+ const char *line = get_line(text, i);
+ int len = get_line_length(line);
+ total_cols = max(total_cols, len+2);
+ }
+
+ /* create the pad */
+ pad = newpad(total_lines+10, total_cols+10);
+ wattrset(pad, attributes[SCROLLWIN_TEXT]);
+ fill_window(pad, text);
+
+ win_lines = min(total_lines+4, LINES-2);
+ win_cols = min(total_cols+2, COLS-2);
+ text_lines = max(win_lines-4, 0);
+ text_cols = max(win_cols-2, 0);
+
+ /* place window in middle of screen */
+ y = (LINES-win_lines)/2;
+ x = (COLS-win_cols)/2;
+
+ win = newwin(win_lines, win_cols, y, x);
+ keypad(win, TRUE);
+ /* show the help in the help window, and show the help panel */
+ wattrset(win, attributes[SCROLLWIN_BOX]);
+ box(win, 0, 0);
+ wattrset(win, attributes[SCROLLWIN_HEADING]);
+ mvwprintw(win, 0, 3, " %s ", title);
+ panel = new_panel(win);
+
+ /* handle scrolling */
+ do {
+
+ copywin(pad, win, start_y, start_x, 2, 2, text_lines,
+ text_cols, 0);
+ print_in_middle(win,
+ text_lines+2,
+ 0,
+ text_cols,
+ "<OK>",
+ attributes[DIALOG_MENU_FORE]);
+ wrefresh(win);
+
+ res = wgetch(win);
+ switch (res) {
+ case KEY_NPAGE:
+ case ' ':
+ start_y += text_lines-2;
+ break;
+ case KEY_PPAGE:
+ start_y -= text_lines+2;
+ break;
+ case KEY_HOME:
+ start_y = 0;
+ break;
+ case KEY_END:
+ start_y = total_lines-text_lines;
+ break;
+ case KEY_DOWN:
+ case 'j':
+ start_y++;
+ break;
+ case KEY_UP:
+ case 'k':
+ start_y--;
+ break;
+ case KEY_LEFT:
+ case 'h':
+ start_x--;
+ break;
+ case KEY_RIGHT:
+ case 'l':
+ start_x++;
+ break;
+ }
+ if (res == 10 || res == 27 || res == 'q'
+ || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
+ break;
+ }
+ if (start_y < 0)
+ start_y = 0;
+ if (start_y >= total_lines-text_lines)
+ start_y = total_lines-text_lines;
+ if (start_x < 0)
+ start_x = 0;
+ if (start_x >= total_cols-text_cols)
+ start_x = total_cols-text_cols;
+ } while (res);
+
+ del_panel(panel);
+ delwin(win);
+ refresh_all_windows(main_window);
+}
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
new file mode 100644
index 0000000..fb42966
--- /dev/null
+++ b/scripts/kconfig/nconf.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <locale.h>
+#include <curses.h>
+#include <menu.h>
+#include <panel.h>
+#include <form.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "ncurses.h"
+
+#define max(a, b) ({\
+ typeof(a) _a = a;\
+ typeof(b) _b = b;\
+ _a > _b ? _a : _b; })
+
+#define min(a, b) ({\
+ typeof(a) _a = a;\
+ typeof(b) _b = b;\
+ _a < _b ? _a : _b; })
+
+typedef enum {
+ NORMAL = 1,
+ MAIN_HEADING,
+ MAIN_MENU_BOX,
+ MAIN_MENU_FORE,
+ MAIN_MENU_BACK,
+ MAIN_MENU_GREY,
+ MAIN_MENU_HEADING,
+ SCROLLWIN_TEXT,
+ SCROLLWIN_HEADING,
+ SCROLLWIN_BOX,
+ DIALOG_TEXT,
+ DIALOG_MENU_FORE,
+ DIALOG_MENU_BACK,
+ DIALOG_BOX,
+ INPUT_BOX,
+ INPUT_HEADING,
+ INPUT_TEXT,
+ INPUT_FIELD,
+ FUNCTION_TEXT,
+ FUNCTION_HIGHLIGHT,
+ ATTR_MAX
+} attributes_t;
+extern attributes_t attributes[];
+
+typedef enum {
+ F_HELP = 1,
+ F_SYMBOL = 2,
+ F_INSTS = 3,
+ F_CONF = 4,
+ F_BACK = 5,
+ F_SAVE = 6,
+ F_LOAD = 7,
+ F_EXIT = 8
+} function_key;
+
+void set_colors(void);
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+ int starty,
+ int startx,
+ int width,
+ const char *string,
+ chtype color);
+int get_line_length(const char *line);
+int get_line_no(const char *text);
+const char *get_line(const char *text, int line_no);
+void fill_window(WINDOW *win, const char *text);
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
+int dialog_inputbox(WINDOW *main_window,
+ const char *title, const char *prompt,
+ const char *init, char *result, int result_len);
+void refresh_all_windows(WINDOW *main_window);
+void show_scroll_win(WINDOW *main_window,
+ const char *title,
+ const char *text);
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 6c8fbbb..2e7a048 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -651,12 +651,20 @@
return sym->visible > sym->rev_dep.tri;
}
+static unsigned strhash(const char *s)
+{
+ /* fnv32 hash */
+ unsigned hash = 2166136261U;
+ for (; *s; s++)
+ hash = (hash ^ *s) * 0x01000193;
+ return hash;
+}
+
struct symbol *sym_lookup(const char *name, int flags)
{
struct symbol *symbol;
- const char *ptr;
char *new_name;
- int hash = 0;
+ int hash;
if (name) {
if (name[0] && !name[1]) {
@@ -666,12 +674,11 @@
case 'n': return &symbol_no;
}
}
- for (ptr = name; *ptr; ptr++)
- hash += *ptr;
- hash &= 0xff;
+ hash = strhash(name) % SYMBOL_HASHSIZE;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
- if (!strcmp(symbol->name, name) &&
+ if (symbol->name &&
+ !strcmp(symbol->name, name) &&
(flags ? symbol->flags & flags
: !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
return symbol;
@@ -679,7 +686,7 @@
new_name = strdup(name);
} else {
new_name = NULL;
- hash = 256;
+ hash = 0;
}
symbol = malloc(sizeof(*symbol));
@@ -697,7 +704,6 @@
struct symbol *sym_find(const char *name)
{
struct symbol *symbol = NULL;
- const char *ptr;
int hash = 0;
if (!name)
@@ -710,12 +716,11 @@
case 'n': return &symbol_no;
}
}
- for (ptr = name; *ptr; ptr++)
- hash += *ptr;
- hash &= 0xff;
+ hash = strhash(name) % SYMBOL_HASHSIZE;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
- if (!strcmp(symbol->name, name) &&
+ if (symbol->name &&
+ !strcmp(symbol->name, name) &&
!(symbol->flags & SYMBOL_CONST))
break;
}
@@ -750,6 +755,7 @@
return NULL;
}
}
+ sym_calc_value(sym);
sym_arr[cnt++] = sym;
}
if (sym_arr)
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 25d1ec4..78b5c04 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -78,6 +78,7 @@
struct gstr gs;
gs.s = malloc(sizeof(char) * 64);
gs.len = 64;
+ gs.max_width = 0;
strcpy(gs.s, "\0");
return gs;
}
@@ -88,6 +89,7 @@
struct gstr gs;
gs.s = strdup(s);
gs.len = strlen(s) + 1;
+ gs.max_width = 0;
return gs;
}
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 6e9dcd5..32a9eef 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -104,7 +104,7 @@
static void zconferror(const char *err);
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
@@ -2220,7 +2220,7 @@
zconf_initscan(name);
sym_init();
- menu_init();
+ _menu_init();
modules_sym = sym_lookup(NULL, 0);
modules_sym->type = S_BOOLEAN;
modules_sym->flags |= SYMBOL_AUTO;
@@ -2336,9 +2336,9 @@
struct property *prop;
if (sym_is_choice(sym))
- fprintf(out, "choice\n");
+ fprintf(out, "\nchoice\n");
else
- fprintf(out, "config %s\n", sym->name);
+ fprintf(out, "\nconfig %s\n", sym->name);
switch (sym->type) {
case S_BOOLEAN:
fputs(" boolean\n", out);
@@ -2384,6 +2384,21 @@
case P_CHOICE:
fputs(" #choice value\n", out);
break;
+ case P_SELECT:
+ fputs( " select ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_RANGE:
+ fputs( " range ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_MENU:
+ fputs( " menu ", out);
+ print_quoted_string(out, prop->text);
+ fputc('\n', out);
+ break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
@@ -2395,7 +2410,6 @@
menu->help[len] = 0;
fprintf(out, " help\n%s\n", menu->help);
}
- fputc('\n', out);
}
void zconfdump(FILE *out)
@@ -2428,7 +2442,6 @@
expr_fprint(prop->visible.expr, out);
fputc('\n', out);
}
- fputs("\n", out);
}
if (menu->list)
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 8c43491..23dfd3b 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -27,7 +27,7 @@
static void zconferror(const char *err);
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
@@ -475,7 +475,7 @@
zconf_initscan(name);
sym_init();
- menu_init();
+ _menu_init();
modules_sym = sym_lookup(NULL, 0);
modules_sym->type = S_BOOLEAN;
modules_sym->flags |= SYMBOL_AUTO;
@@ -591,9 +591,9 @@
struct property *prop;
if (sym_is_choice(sym))
- fprintf(out, "choice\n");
+ fprintf(out, "\nchoice\n");
else
- fprintf(out, "config %s\n", sym->name);
+ fprintf(out, "\nconfig %s\n", sym->name);
switch (sym->type) {
case S_BOOLEAN:
fputs(" boolean\n", out);
@@ -639,6 +639,21 @@
case P_CHOICE:
fputs(" #choice value\n", out);
break;
+ case P_SELECT:
+ fputs( " select ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_RANGE:
+ fputs( " range ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_MENU:
+ fputs( " menu ", out);
+ print_quoted_string(out, prop->text);
+ fputc('\n', out);
+ break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
@@ -650,7 +665,6 @@
menu->help[len] = 0;
fprintf(out, " help\n%s\n", menu->help);
}
- fputc('\n', out);
}
void zconfdump(FILE *out)
@@ -683,7 +697,6 @@
expr_fprint(prop->visible.expr, out);
fputc('\n', out);
}
- fputs("\n", out);
}
if (menu->list)
diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl
index e950f9c..827896f 100644
--- a/scripts/markup_oops.pl
+++ b/scripts/markup_oops.pl
@@ -2,6 +2,7 @@
use File::Basename;
use Math::BigInt;
+use Getopt::Long;
# Copyright 2008, Intel Corporation
#
@@ -15,6 +16,16 @@
# Arjan van de Ven <arjan@linux.intel.com>
+my $cross_compile = "";
+my $vmlinux_name = "";
+my $modulefile = "";
+
+# Get options
+Getopt::Long::GetOptions(
+ 'cross-compile|c=s' => \$cross_compile,
+ 'module|m=s' => \$modulefile,
+ 'help|h' => \&usage,
+) || usage ();
my $vmlinux_name = $ARGV[0];
if (!defined($vmlinux_name)) {
my $kerver = `uname -r`;
@@ -23,9 +34,8 @@
print "No vmlinux specified, assuming $vmlinux_name\n";
}
my $filename = $vmlinux_name;
-#
-# Step 1: Parse the oops to find the EIP value
-#
+
+# Parse the oops to find the EIP value
my $target = "0";
my $function;
@@ -177,26 +187,26 @@
my $decodestop = Math::BigInt->from_hex("0x$target") + 8192;
if ($target eq "0") {
print "No oops found!\n";
- print "Usage: \n";
- print " dmesg | perl scripts/markup_oops.pl vmlinux\n";
- exit;
+ usage();
}
# if it's a module, we need to find the .ko file and calculate a load offset
if ($module ne "") {
- my $modulefile = `modinfo $module | grep '^filename:' | awk '{ print \$2 }'`;
- chomp($modulefile);
+ if ($modulefile eq "") {
+ $modulefile = `modinfo -F filename $module`;
+ chomp($modulefile);
+ }
$filename = $modulefile;
if ($filename eq "") {
print "Module .ko file for $module not found. Aborting\n";
exit;
}
# ok so we found the module, now we need to calculate the vma offset
- open(FILE, "objdump -dS $filename |") || die "Cannot start objdump";
+ open(FILE, $cross_compile."objdump -dS $filename |") || die "Cannot start objdump";
while (<FILE>) {
if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) {
my $fu = $1;
- $vmaoffset = hex($target) - hex($fu) - hex($func_offset);
+ $vmaoffset = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$fu") - Math::BigInt->from_hex("0x$func_offset");
}
}
close(FILE);
@@ -204,7 +214,7 @@
my $counter = 0;
my $state = 0;
-my $center = 0;
+my $center = -1;
my @lines;
my @reglines;
@@ -212,7 +222,7 @@
my ($address, $target) = @_;
my $ad = "0x".$address;
my $ta = "0x".$target;
- my $delta = hex($ad) - hex($ta);
+ my $delta = Math::BigInt->from_hex($ad) - Math::BigInt->from_hex($ta);
if (($delta > -4096) && ($delta < 4096)) {
return 1;
@@ -225,7 +235,7 @@
# first, parse the input into the lines array, but to keep size down,
# we only do this for 4Kb around the sweet spot
-open(FILE, "objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump";
+open(FILE, $cross_compile."objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump";
while (<FILE>) {
my $line = $_;
@@ -236,7 +246,8 @@
$state = 1;
}
}
- } else {
+ }
+ if ($state == 1) {
if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) {
my $val = $1;
if (!InRange($val, $target)) {
@@ -259,7 +270,7 @@
exit;
}
-if ($center == 0) {
+if ($center == -1) {
print "No matching code found \n";
exit;
}
@@ -344,3 +355,16 @@
$i = $i +1;
}
+sub usage {
+ print <<EOT;
+Usage:
+ dmesg | perl $0 [OPTION] [VMLINUX]
+
+OPTION:
+ -c, --cross-compile CROSS_COMPILE Specify the prefix used for toolchain.
+ -m, --module MODULE_DIRNAME Specify the module filename.
+ -h, --help Help.
+EOT
+ exit;
+}
+
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index 23dbad8..50ad317 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -67,9 +67,8 @@
echo \#define LINUX_COMPILE_BY \"`whoami`\"
echo \#define LINUX_COMPILE_HOST \"`hostname | $UTS_TRUNCATE`\"
- if [ -x /bin/dnsdomainname ]; then
- domain=`dnsdomainname 2> /dev/null`
- elif [ -x /bin/domainname ]; then
+ domain=`dnsdomainname 2> /dev/null`
+ if [ -z "$domain" ]; then
domain=`domainname 2> /dev/null`
fi
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 2092361..3318692 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -781,10 +781,13 @@
#define ALL_EXIT_TEXT_SECTIONS \
".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$"
-#define ALL_INIT_SECTIONS INIT_SECTIONS, DEV_INIT_SECTIONS, \
- CPU_INIT_SECTIONS, MEM_INIT_SECTIONS
-#define ALL_EXIT_SECTIONS EXIT_SECTIONS, DEV_EXIT_SECTIONS, \
- CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS
+#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \
+ MEM_INIT_SECTIONS
+#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \
+ MEM_EXIT_SECTIONS
+
+#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
+#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
#define DATA_SECTIONS ".data$", ".data.rel$"
#define TEXT_SECTIONS ".text$"
@@ -814,33 +817,29 @@
/* symbols in .data that may refer to init/exit sections */
-static const char *symbol_white_list[] =
-{
- "*driver",
- "*_template", /* scsi uses *_template a lot */
- "*_timer", /* arm uses ops structures named _timer a lot */
- "*_sht", /* scsi also used *_sht to some extent */
- "*_ops",
- "*_probe",
- "*_probe_one",
- "*_console",
- NULL
-};
+#define DEFAULT_SYMBOL_WHITE_LIST \
+ "*driver", \
+ "*_template", /* scsi uses *_template a lot */ \
+ "*_timer", /* arm uses ops structures named _timer a lot */ \
+ "*_sht", /* scsi also used *_sht to some extent */ \
+ "*_ops", \
+ "*_probe", \
+ "*_probe_one", \
+ "*_console"
static const char *head_sections[] = { ".head.text*", NULL };
static const char *linker_symbols[] =
{ "__init_begin", "_sinittext", "_einittext", NULL };
enum mismatch {
- NO_MISMATCH,
- TEXT_TO_INIT,
- DATA_TO_INIT,
- TEXT_TO_EXIT,
- DATA_TO_EXIT,
- XXXINIT_TO_INIT,
- XXXEXIT_TO_EXIT,
- INIT_TO_EXIT,
- EXIT_TO_INIT,
+ TEXT_TO_ANY_INIT,
+ DATA_TO_ANY_INIT,
+ TEXT_TO_ANY_EXIT,
+ DATA_TO_ANY_EXIT,
+ XXXINIT_TO_SOME_INIT,
+ XXXEXIT_TO_SOME_EXIT,
+ ANY_INIT_TO_ANY_EXIT,
+ ANY_EXIT_TO_ANY_INIT,
EXPORT_TO_INIT_EXIT,
};
@@ -848,6 +847,7 @@
const char *fromsec[20];
const char *tosec[20];
enum mismatch mismatch;
+ const char *symbol_white_list[20];
};
const struct sectioncheck sectioncheck[] = {
@@ -857,80 +857,103 @@
{
.fromsec = { TEXT_SECTIONS, NULL },
.tosec = { ALL_INIT_SECTIONS, NULL },
- .mismatch = TEXT_TO_INIT,
+ .mismatch = TEXT_TO_ANY_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
{
.fromsec = { DATA_SECTIONS, NULL },
- .tosec = { ALL_INIT_SECTIONS, NULL },
- .mismatch = DATA_TO_INIT,
+ .tosec = { ALL_XXXINIT_SECTIONS, NULL },
+ .mismatch = DATA_TO_ANY_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+ .fromsec = { DATA_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, NULL },
+ .mismatch = DATA_TO_ANY_INIT,
+ .symbol_white_list = {
+ "*_template", "*_timer", "*_sht", "*_ops",
+ "*_probe", "*_probe_one", "*_console", NULL
+ },
},
{
.fromsec = { TEXT_SECTIONS, NULL },
.tosec = { ALL_EXIT_SECTIONS, NULL },
- .mismatch = TEXT_TO_EXIT,
+ .mismatch = TEXT_TO_ANY_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
{
.fromsec = { DATA_SECTIONS, NULL },
.tosec = { ALL_EXIT_SECTIONS, NULL },
- .mismatch = DATA_TO_EXIT,
+ .mismatch = DATA_TO_ANY_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not reference init code/data from devinit/cpuinit/meminit code/data */
{
- .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL },
+ .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
.tosec = { INIT_SECTIONS, NULL },
- .mismatch = XXXINIT_TO_INIT,
+ .mismatch = XXXINIT_TO_SOME_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not reference cpuinit code/data from meminit code/data */
{
.fromsec = { MEM_INIT_SECTIONS, NULL },
.tosec = { CPU_INIT_SECTIONS, NULL },
- .mismatch = XXXINIT_TO_INIT,
+ .mismatch = XXXINIT_TO_SOME_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not reference meminit code/data from cpuinit code/data */
{
.fromsec = { CPU_INIT_SECTIONS, NULL },
.tosec = { MEM_INIT_SECTIONS, NULL },
- .mismatch = XXXINIT_TO_INIT,
+ .mismatch = XXXINIT_TO_SOME_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
{
- .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL },
+ .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
.tosec = { EXIT_SECTIONS, NULL },
- .mismatch = XXXEXIT_TO_EXIT,
+ .mismatch = XXXEXIT_TO_SOME_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not reference cpuexit code/data from memexit code/data */
{
.fromsec = { MEM_EXIT_SECTIONS, NULL },
.tosec = { CPU_EXIT_SECTIONS, NULL },
- .mismatch = XXXEXIT_TO_EXIT,
+ .mismatch = XXXEXIT_TO_SOME_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not reference memexit code/data from cpuexit code/data */
{
.fromsec = { CPU_EXIT_SECTIONS, NULL },
.tosec = { MEM_EXIT_SECTIONS, NULL },
- .mismatch = XXXEXIT_TO_EXIT,
+ .mismatch = XXXEXIT_TO_SOME_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not use exit code/data from init code */
{
.fromsec = { ALL_INIT_SECTIONS, NULL },
.tosec = { ALL_EXIT_SECTIONS, NULL },
- .mismatch = INIT_TO_EXIT,
+ .mismatch = ANY_INIT_TO_ANY_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not use init code/data from exit code */
{
.fromsec = { ALL_EXIT_SECTIONS, NULL },
.tosec = { ALL_INIT_SECTIONS, NULL },
- .mismatch = EXIT_TO_INIT,
+ .mismatch = ANY_EXIT_TO_ANY_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
/* Do not export init/exit functions or data */
{
.fromsec = { "__ksymtab*", NULL },
.tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
- .mismatch = EXPORT_TO_INIT_EXIT
+ .mismatch = EXPORT_TO_INIT_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
}
};
-static int section_mismatch(const char *fromsec, const char *tosec)
+static const struct sectioncheck *section_mismatch(
+ const char *fromsec, const char *tosec)
{
int i;
int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
@@ -939,10 +962,10 @@
for (i = 0; i < elems; i++) {
if (match(fromsec, check->fromsec) &&
match(tosec, check->tosec))
- return check->mismatch;
+ return check;
check++;
}
- return NO_MISMATCH;
+ return NULL;
}
/**
@@ -961,7 +984,7 @@
* Pattern 2:
* Many drivers utilise a *driver container with references to
* add, remove, probe functions etc.
- * These functions may often be marked __init and we do not want to
+ * These functions may often be marked __devinit and we do not want to
* warn here.
* the pattern is identified by:
* tosec = init or exit section
@@ -982,7 +1005,8 @@
* refsymname = __init_begin, _sinittext, _einittext
*
**/
-static int secref_whitelist(const char *fromsec, const char *fromsym,
+static int secref_whitelist(const struct sectioncheck *mismatch,
+ const char *fromsec, const char *fromsym,
const char *tosec, const char *tosym)
{
/* Check for pattern 1 */
@@ -994,7 +1018,7 @@
/* Check for pattern 2 */
if (match(tosec, init_exit_sections) &&
match(fromsec, data_sections) &&
- match(fromsym, symbol_white_list))
+ match(fromsym, mismatch->symbol_white_list))
return 0;
/* Check for pattern 3 */
@@ -1155,7 +1179,8 @@
* Try to find symbols near it so user can find it.
* Check whitelist before warning - it may be a false positive.
*/
-static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
+static void report_sec_mismatch(const char *modname,
+ const struct sectioncheck *mismatch,
const char *fromsec,
unsigned long long fromaddr,
const char *fromsym,
@@ -1186,8 +1211,8 @@
modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
tosym, to_p);
- switch (mismatch) {
- case TEXT_TO_INIT:
+ switch (mismatch->mismatch) {
+ case TEXT_TO_ANY_INIT:
fprintf(stderr,
"The function %s%s() references\n"
"the %s %s%s%s.\n"
@@ -1197,8 +1222,8 @@
to, sec2annotation(tosec), tosym, to_p,
fromsym, sec2annotation(tosec), tosym);
break;
- case DATA_TO_INIT: {
- const char **s = symbol_white_list;
+ case DATA_TO_ANY_INIT: {
+ const char *const *s = mismatch->symbol_white_list;
fprintf(stderr,
"The variable %s references\n"
"the %s %s%s%s\n"
@@ -1211,15 +1236,15 @@
fprintf(stderr, "\n");
break;
}
- case TEXT_TO_EXIT:
+ case TEXT_TO_ANY_EXIT:
fprintf(stderr,
"The function %s() references a %s in an exit section.\n"
"Often the %s %s%s has valid usage outside the exit section\n"
"and the fix is to remove the %sannotation of %s.\n",
fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
break;
- case DATA_TO_EXIT: {
- const char **s = symbol_white_list;
+ case DATA_TO_ANY_EXIT: {
+ const char *const *s = mismatch->symbol_white_list;
fprintf(stderr,
"The variable %s references\n"
"the %s %s%s%s\n"
@@ -1232,8 +1257,8 @@
fprintf(stderr, "\n");
break;
}
- case XXXINIT_TO_INIT:
- case XXXEXIT_TO_EXIT:
+ case XXXINIT_TO_SOME_INIT:
+ case XXXEXIT_TO_SOME_EXIT:
fprintf(stderr,
"The %s %s%s%s references\n"
"a %s %s%s%s.\n"
@@ -1243,7 +1268,7 @@
to, sec2annotation(tosec), tosym, to_p,
tosym, fromsym, tosym);
break;
- case INIT_TO_EXIT:
+ case ANY_INIT_TO_ANY_EXIT:
fprintf(stderr,
"The %s %s%s%s references\n"
"a %s %s%s%s.\n"
@@ -1256,7 +1281,7 @@
to, sec2annotation(tosec), tosym, to_p,
sec2annotation(tosec), tosym, to_p);
break;
- case EXIT_TO_INIT:
+ case ANY_EXIT_TO_ANY_INIT:
fprintf(stderr,
"The %s %s%s%s references\n"
"a %s %s%s%s.\n"
@@ -1275,8 +1300,6 @@
"Fix this by removing the %sannotation of %s "
"or drop the export.\n",
tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
- case NO_MISMATCH:
- /* To get warnings on missing members */
break;
}
fprintf(stderr, "\n");
@@ -1286,11 +1309,11 @@
Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
{
const char *tosec;
- enum mismatch mismatch;
+ const struct sectioncheck *mismatch;
tosec = sec_name(elf, sym->st_shndx);
mismatch = section_mismatch(fromsec, tosec);
- if (mismatch != NO_MISMATCH) {
+ if (mismatch) {
Elf_Sym *to;
Elf_Sym *from;
const char *tosym;
@@ -1302,7 +1325,8 @@
tosym = sym_name(elf, to);
/* check whitelist - we may ignore it */
- if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {
+ if (secref_whitelist(mismatch,
+ fromsec, fromsym, tosec, tosym)) {
report_sec_mismatch(modname, mismatch,
fromsec, r->r_offset, fromsym,
is_function(from), tosec, tosym,
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index c6e88c6..361d0f71 100755
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
@@ -175,12 +175,11 @@
}
if (! -e "$source.c" && ! -e "$source.S") {
# No obvious source, exclude the object if it is conglomerate
- if (! open(OBJDUMPDATA, "$objdump $basename|")) {
- printf STDERR "$objdump $fullname failed $!\n";
- return;
- }
+ open(my $objdumpdata, "$objdump $basename|")
+ or die "$objdump $fullname failed $!\n";
+
my $comment;
- while (<OBJDUMPDATA>) {
+ while (<$objdumpdata>) {
chomp();
if (/^In archive/) {
# Archives are always conglomerate
@@ -190,18 +189,18 @@
next if (! /^[ 0-9a-f]{5,} /);
$comment .= substr($_, 43);
}
- close(OBJDUMPDATA);
+ close($objdumpdata);
+
if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) {
printf STDERR "No source file found for $fullname\n";
}
return;
}
- if (! open(NMDATA, "$nm $basename|")) {
- printf STDERR "$nm $fullname failed $!\n";
- return;
- }
+ open (my $nmdata, "$nm $basename|")
+ or die "$nm $fullname failed $!\n";
+
my @nmdata;
- while (<NMDATA>) {
+ while (<$nmdata>) {
chop;
($type, $name) = (split(/ +/, $_, 3))[1..2];
# Expected types
@@ -268,7 +267,8 @@
}
}
}
- close(NMDATA);
+ close($nmdata);
+
if ($#nmdata < 0) {
if (
$fullname ne "lib/brlock.o"
@@ -316,8 +316,7 @@
sub list_multiply_defined
{
- my ($name, $module);
- foreach $name (keys(%def)) {
+ foreach my $name (keys(%def)) {
if ($#{$def{$name}} > 0) {
# Special case for cond_syscall
if ($#{$def{$name}} == 1 && $name =~ /^sys_/ &&
@@ -333,8 +332,9 @@
&drop_def("arch/x86/kernel/vsyscall-sysenter_32.o", $name);
next;
}
+
printf "$name is multiply defined in :-\n";
- foreach $module (@{$def{$name}}) {
+ foreach my $module (@{$def{$name}}) {
printf "\t$module\n";
}
}
@@ -343,12 +343,13 @@
sub resolve_external_references
{
- my ($object, $type, $name, $i, $j, $kstrtab, $ksymtab, $export);
+ my ($kstrtab, $ksymtab, $export);
+
printf "\n";
- foreach $object (keys(%nmdata)) {
+ foreach my $object (keys(%nmdata)) {
my $nmdata = $nmdata{$object};
- for ($i = 0; $i <= $#{$nmdata}; ++$i) {
- ($type, $name) = split(' ', $nmdata->[$i], 2);
+ for (my $i = 0; $i <= $#{$nmdata}; ++$i) {
+ my ($type, $name) = split(' ', $nmdata->[$i], 2);
if ($type eq "U" || $type eq "w") {
if (exists($def{$name}) || exists($ksymtab{$name})) {
# add the owning object to the nmdata
@@ -357,7 +358,7 @@
$kstrtab = "R __kstrtab_$name";
$ksymtab = "R __ksymtab_$name";
$export = 0;
- for ($j = 0; $j <= $#{$nmdata}; ++$j) {
+ for (my $j = 0; $j <= $#{$nmdata}; ++$j) {
if ($nmdata->[$j] eq $kstrtab ||
$nmdata->[$j] eq $ksymtab) {
$export = 1;
@@ -424,11 +425,11 @@
sub list_extra_externals
{
my %noref = ();
- my ($name, @module, $module, $export);
- foreach $name (keys(%def)) {
+
+ foreach my $name (keys(%def)) {
if (! exists($ref{$name})) {
- @module = @{$def{$name}};
- foreach $module (@module) {
+ my @module = @{$def{$name}};
+ foreach my $module (@module) {
if (! exists($noref{$module})) {
$noref{$module} = [];
}
@@ -438,16 +439,16 @@
}
if (%noref) {
printf "\nExternally defined symbols with no external references\n";
- foreach $module (sort(keys(%noref))) {
+ foreach my $module (sort(keys(%noref))) {
printf " $module\n";
foreach (sort(@{$noref{$module}})) {
- if (exists($export{$_})) {
- $export = " (export only)";
- }
- else {
- $export = "";
- }
- printf " $_$export\n";
+ my $export;
+ if (exists($export{$_})) {
+ $export = " (export only)";
+ } else {
+ $export = "";
+ }
+ printf " $_$export\n";
}
}
}
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 8b357b0..07f2fbd 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -18,6 +18,8 @@
cp debian/copyright "$pdir/usr/share/doc/$pname/"
cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
+ sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
+ | xargs -r0 md5sum > DEBIAN/md5sums"
# Fix ownership and permissions
chown -R root:root "$pdir"
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index fa27f3d..15440f5 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -39,7 +39,7 @@
echo "Source: kernel-$__KERNELRELEASE.tar.gz"
fi
-echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
+echo "BuildRoot: %{_tmppath}/%{name}-%{PACKAGE_VERSION}-root"
echo "Provides: $PROVIDES"
echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
echo "%define debug_package %{nil}"
diff --git a/scripts/profile2linkerlist.pl b/scripts/profile2linkerlist.pl
index cb4260e..6943fa7 100644
--- a/scripts/profile2linkerlist.pl
+++ b/scripts/profile2linkerlist.pl
@@ -7,15 +7,13 @@
# usage:
# readprofile | sort -rn | perl profile2linkerlist.pl > functionlist
#
+use strict;
while (<>) {
my $line = $_;
$_ =~ /\W*[0-9]+\W*([a-zA-Z\_0-9]+)\W*[0-9]+/;
- if ( ($line =~ /unknown/) || ($line =~ /total/)) {
-
- } else {
- print "*(.text.$1)\n";
- }
+ print "*(.text.$1)\n"
+ unless ($line =~ /unknown/) || ($line =~ /total/);
}
diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py
index 4c79660..44423b4 100644
--- a/scripts/rt-tester/rt-tester.py
+++ b/scripts/rt-tester/rt-tester.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
#
# rt-mutex tester
#
diff --git a/scripts/show_delta b/scripts/show_delta
index 48a706a..17df305 100755
--- a/scripts/show_delta
+++ b/scripts/show_delta
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
#
# show_deltas: Read list of printk messages instrumented with
# time data, and format with time deltas.
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 1a0c44d..8509bb5 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -5,7 +5,7 @@
# mode may be any of: tags, TAGS, cscope
#
# Uses the following environment variables:
-# ARCH, SUBARCH, srctree, src, obj
+# ARCH, SUBARCH, SRCARCH, srctree, src, obj
if [ "$KBUILD_VERBOSE" = "1" ]; then
set -x
@@ -17,28 +17,48 @@
-name .git ) \
-prune -o"
-# Do not use full path is we do not use O=.. builds
+# Do not use full path if we do not use O=.. builds
+# Use make O=. {tags|cscope}
+# to force full paths for a non-O= build
if [ "${KBUILD_SRC}" = "" ]; then
tree=
else
tree=${srctree}/
fi
+# Find all available archs
+find_all_archs()
+{
+ ALLSOURCE_ARCHS=""
+ for arch in `ls ${tree}arch`; do
+ ALLSOURCE_ARCHS="${ALLSOURCE_ARCHS} "${arch##\/}
+ done
+}
+
# Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH
if [ "${ALLSOURCE_ARCHS}" = "" ]; then
ALLSOURCE_ARCHS=${SRCARCH}
+elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then
+ find_all_archs
fi
# find sources in arch/$ARCH
find_arch_sources()
{
- find ${tree}arch/$1 $ignore -name "$2" -print;
+ for i in $archincludedir; do
+ prune="$prune -wholename $i -prune -o"
+ done
+ find ${tree}arch/$1 $ignore $prune -name "$2" -print;
}
# find sources in arch/$1/include
find_arch_include_sources()
{
- find ${tree}arch/$1/include $ignore -name "$2" -print;
+ include=$(find ${tree}arch/$1/ -name include -type d);
+ if [ -n "$include" ]; then
+ archincludedir="$archincludedir $include"
+ find $include $ignore -name "$2" -print;
+ fi
}
# find sources in include/
@@ -63,14 +83,15 @@
all_sources()
{
- for arch in $ALLSOURCE_ARCHS
- do
- find_sources $arch '*.[chS]'
- done
+ find_arch_include_sources ${SRCARCH} '*.[chS]'
if [ ! -z "$archinclude" ]; then
find_arch_include_sources $archinclude '*.[chS]'
fi
find_include_sources '*.[chS]'
+ for arch in $ALLSOURCE_ARCHS
+ do
+ find_sources $arch '*.[chS]'
+ done
find_other_sources '*.[chS]'
}
@@ -89,13 +110,7 @@
docscope()
{
- # always use absolute paths for cscope, as recommended by cscope
- # upstream
- case "$tree" in
- /*) ;;
- *) tree=$PWD/$tree ;;
- esac
- (cd /; echo \-k; echo \-q; all_sources) > cscope.files
+ (echo \-k; echo \-q; all_sources) > cscope.files
cscope -b -f cscope.out
}