diff options
573 files changed, 5417 insertions, 3953 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index 428676cfa61e..25be3250f7d6 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -133,46 +133,6 @@ Description: The symbolic link points to the PCI device sysfs entry of the Physical Function this device associates with. - -What: /sys/bus/pci/slots/... -Date: April 2005 (possibly older) -KernelVersion: 2.6.12 (possibly older) -Contact: linux-pci@vger.kernel.org -Description: - When the appropriate driver is loaded, it will create a - directory per claimed physical PCI slot in - /sys/bus/pci/slots/. The names of these directories are - specific to the driver, which in turn, are specific to the - platform, but in general, should match the label on the - machine's physical chassis. - - The drivers that can create slot directories include the - PCI hotplug drivers, and as of 2.6.27, the pci_slot driver. - - The slot directories contain, at a minimum, a file named - 'address' which contains the PCI bus:device:function tuple. - Other files may appear as well, but are specific to the - driver. - -What: /sys/bus/pci/slots/.../function[0-7] -Date: March 2010 -KernelVersion: 2.6.35 -Contact: linux-pci@vger.kernel.org -Description: - If PCI slot directories (as described above) are created, - and the physical slot is actually populated with a device, - symbolic links in the slot directory pointing to the - device's PCI functions are created as well. - -What: /sys/bus/pci/devices/.../slot -Date: March 2010 -KernelVersion: 2.6.35 -Contact: linux-pci@vger.kernel.org -Description: - If PCI slot directories (as described above) are created, - a symbolic link pointing to the slot directory will be - created as well. - What: /sys/bus/pci/slots/.../module Date: June 2009 Contact: linux-pci@vger.kernel.org diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1808f1157f30..82d6aeb5228f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2048,7 +2048,9 @@ and is between 256 and 4096 characters. It is defined in the file WARNING: Forcing ASPM on may cause system lockups. pcie_pme= [PCIE,PM] Native PCIe PME signaling options: - off Do not use native PCIe PME signaling. + Format: {auto|force}[,nomsi] + auto Use native PCIe PME signaling if the BIOS allows the + kernel to control PCIe config registers of root ports. force Use native PCIe PME signaling even if the BIOS refuses to allow the kernel to control the relevant PCIe config registers. diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt index 41c95cc1dc1f..17ddd822b456 100644 --- a/Documentation/watchdog/watchdog-parameters.txt +++ b/Documentation/watchdog/watchdog-parameters.txt @@ -125,6 +125,11 @@ ibmasr: nowayout: Watchdog cannot be stopped once started (default=kernel config parameter) ------------------------------------------------- +imx2_wdt: +timeout: Watchdog timeout in seconds (default 60 s) +nowayout: Watchdog cannot be stopped once started + (default=kernel config parameter) +------------------------------------------------- indydog: nowayout: Watchdog cannot be stopped once started (default=kernel config parameter) diff --git a/MAINTAINERS b/MAINTAINERS index 67accd730ac9..a07a49deb47b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -896,11 +896,13 @@ S: Maintained ARM/SAMSUNG ARM ARCHITECTURES M: Ben Dooks <ben-linux@fluff.org> +M: Kukjin Kim <kgene.kim@samsung.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained -F: arch/arm/plat-s3c/ +F: arch/arm/plat-samsung/ F: arch/arm/plat-s3c24xx/ +F: arch/arm/plat-s5p/ ARM/S3C2410 ARM ARCHITECTURE M: Ben Dooks <ben-linux@fluff.org> @@ -1148,7 +1150,7 @@ F: drivers/mmc/host/atmel-mci.c F: drivers/mmc/host/atmel-mci-regs.h ATMEL AT91 / AT32 SERIAL DRIVER -M: Haavard Skinnemoen <hskinnemoen@atmel.com> +M: Nicolas Ferre <nicolas.ferre@atmel.com> S: Supported F: drivers/serial/atmel_serial.c @@ -1160,18 +1162,18 @@ F: drivers/video/atmel_lcdfb.c F: include/video/atmel_lcdc.h ATMEL MACB ETHERNET DRIVER -M: Haavard Skinnemoen <hskinnemoen@atmel.com> +M: Nicolas Ferre <nicolas.ferre@atmel.com> S: Supported F: drivers/net/macb.* ATMEL SPI DRIVER -M: Haavard Skinnemoen <hskinnemoen@atmel.com> +M: Nicolas Ferre <nicolas.ferre@atmel.com> S: Supported F: drivers/spi/atmel_spi.* ATMEL USBA UDC DRIVER -M: Haavard Skinnemoen <hskinnemoen@atmel.com> -L: kernel@avr32linux.org +M: Nicolas Ferre <nicolas.ferre@atmel.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver S: Supported F: drivers/usb/gadget/atmel_usba_udc.* @@ -1581,7 +1583,7 @@ F: include/linux/coda*.h COMMON INTERNET FILE SYSTEM (CIFS) M: Steve French <sfrench@samba.org> -L: linux-cifs-client@lists.samba.org (moderated for non-subscribers) +L: linux-cifs@vger.kernel.org L: samba-technical@lists.samba.org (moderated for non-subscribers) W: http://linux-cifs.samba.org/ Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/ @@ -2109,11 +2111,18 @@ F: drivers/edac/i5000_edac.c EDAC-I5400 M: Mauro Carvalho Chehab <mchehab@redhat.com> -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i5400_edac.c +EDAC-I7CORE +M: Mauro Carvalho Chehab <mchehab@redhat.com> +L: linux-edac@vger.kernel.org +W: bluesmoke.sourceforge.net +S: Maintained +F: drivers/edac/i7core_edac.c linux/edac_mce.h drivers/edac/edac_mce.c + EDAC-I82975X M: Ranganathan Desikan <ravi@jetztechnologies.com> M: "Arvind R." <arvind@jetztechnologies.com> @@ -2887,6 +2896,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git S: Maintained F: drivers/input/ +INPUT MULTITOUCH (MT) PROTOCOL +M: Henrik Rydberg <rydberg@euromail.se> +L: linux-input@vger.kernel.org +S: Maintained +F: Documentation/input/multi-touch-protocol.txt +K: \b(ABS|SYN)_MT_ + INTEL IDLE DRIVER M: Len Brown <lenb@kernel.org> L: linux-pm@lists.linux-foundation.org @@ -2978,22 +2994,14 @@ F: drivers/net/ixgb/ F: drivers/net/ixgbe/ INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT -M: Zhu Yi <yi.zhu@intel.com> -M: Reinette Chatre <reinette.chatre@intel.com> -M: Intel Linux Wireless <ilw@linux.intel.com> L: linux-wireless@vger.kernel.org -W: http://ipw2100.sourceforge.net -S: Odd Fixes +S: Orphan F: Documentation/networking/README.ipw2100 F: drivers/net/wireless/ipw2x00/ipw2100.* INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT -M: Zhu Yi <yi.zhu@intel.com> -M: Reinette Chatre <reinette.chatre@intel.com> -M: Intel Linux Wireless <ilw@linux.intel.com> L: linux-wireless@vger.kernel.org -W: http://ipw2200.sourceforge.net -S: Odd Fixes +S: Orphan F: Documentation/networking/README.ipw2200 F: drivers/net/wireless/ipw2x00/ipw2200.* @@ -3019,8 +3027,8 @@ F: drivers/net/wimax/i2400m/ F: include/linux/wimax/i2400m.h INTEL WIRELESS WIFI LINK (iwlwifi) -M: Zhu Yi <yi.zhu@intel.com> M: Reinette Chatre <reinette.chatre@intel.com> +M: Wey-Yi Guy <wey-yi.w.guy@intel.com> M: Intel Linux Wireless <ilw@linux.intel.com> L: linux-wireless@vger.kernel.org W: http://intellinuxwireless.org @@ -3030,7 +3038,6 @@ F: drivers/net/wireless/iwlwifi/ INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi) M: Samuel Ortiz <samuel.ortiz@intel.com> -M: Zhu Yi <yi.zhu@intel.com> M: Intel Linux Wireless <ilw@linux.intel.com> L: linux-wireless@vger.kernel.org S: Supported @@ -3382,7 +3389,7 @@ KPROBES M: Ananth N Mavinakayanahalli <ananth@in.ibm.com> M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> M: "David S. Miller" <davem@davemloft.net> -M: Masami Hiramatsu <mhiramat@redhat.com> +M: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> S: Maintained F: Documentation/kprobes.txt F: include/linux/kprobes.h @@ -4215,6 +4222,7 @@ OPEN FIRMWARE AND FLATTENED DEVICE TREE M: Grant Likely <grant.likely@secretlab.ca> L: devicetree-discuss@lists.ozlabs.org W: http://fdt.secretlab.ca +T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained F: drivers/of F: include/linux/of*.h @@ -4629,6 +4637,12 @@ M: Robert Jarzmik <robert.jarzmik@free.fr> L: rtc-linux@googlegroups.com S: Maintained +QLOGIC QLA1280 SCSI DRIVER +M: Michael Reed <mdr@sgi.com> +L: linux-scsi@vger.kernel.org +S: Maintained +F: drivers/scsi/qla1280.[ch] + QLOGIC QLA2XXX FC-SCSI DRIVER M: Andrew Vasquez <andrew.vasquez@qlogic.com> M: linux-driver@qlogic.com @@ -5387,6 +5401,7 @@ M: David Brownell <dbrownell@users.sourceforge.net> M: Grant Likely <grant.likely@secretlab.ca> L: spi-devel-general@lists.sourceforge.net Q: http://patchwork.kernel.org/project/spi-devel-general/list/ +T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained F: Documentation/spi/ F: drivers/spi/ @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc4 NAME = Sheep on Meth # *DOCUMENTATION* @@ -883,80 +883,10 @@ PHONY += $(vmlinux-dirs) $(vmlinux-dirs): prepare scripts $(Q)$(MAKE) $(build)=$@ -# Build the kernel release string -# -# The KERNELRELEASE value built here is stored in the file -# include/config/kernel.release, and is used when executing several -# make targets, such as "make install" or "make modules_install." -# -# The eventual kernel release string consists of the following fields, -# shown in a hierarchical format to show how smaller parts are concatenated -# to form the larger and final value, with values coming from places like -# the Makefile, kernel config options, make command line options and/or -# SCM tag information. -# -# $(KERNELVERSION) -# $(VERSION) eg, 2 -# $(PATCHLEVEL) eg, 6 -# $(SUBLEVEL) eg, 18 -# $(EXTRAVERSION) eg, -rc6 -# $(localver-full) -# $(localver) -# localversion* (files without backups, containing '~') -# $(CONFIG_LOCALVERSION) (from kernel config setting) -# $(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) -# -# 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 \ - `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`) - -localver = $(subst $(space),, $(string) \ - $(patsubst "%",%,$(CONFIG_LOCALVERSION))) - -# 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 -ifeq ($(wildcard .scmversion),) - scm-identifier = $(shell $(CONFIG_SHELL) \ - $(srctree)/scripts/setlocalversion $(srctree)) -else - scm-identifier = $(shell cat .scmversion 2> /dev/null) -endif - -ifdef CONFIG_LOCALVERSION_AUTO - localver-extra = $(scm-identifier) -else - ifneq ($(scm-identifier),) - ifeq ($(LOCALVERSION),) - localver-extra = + - endif - endif -endif - -localver-full = $(localver)$(LOCALVERSION)$(localver-extra) - # Store (new) KERNELRELASE string in include/config/kernel.release -kernelrelease = $(KERNELVERSION)$(localver-full) include/config/kernel.release: include/config/auto.conf FORCE $(Q)rm -f $@ - $(Q)echo $(kernelrelease) > $@ + $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) scripts/setlocalversion $(srctree))" > $@ # Things we need to do before we recursively start building the kernel @@ -1095,7 +1025,7 @@ all: modules # using awk while concatenating to the final file. PHONY += modules -modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) +modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order @$(kecho) ' Building modules, stage 2.'; $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost @@ -1117,7 +1047,7 @@ PHONY += modules_install modules_install: _modinst_ _modinst_post PHONY += _modinst_ -_modinst_: modules.builtin +_modinst_: @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";\ diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h index 1dce24bc455a..adfab8a21dfe 100644 --- a/arch/alpha/include/asm/bitops.h +++ b/arch/alpha/include/asm/bitops.h @@ -410,7 +410,7 @@ static inline unsigned long __arch_hweight64(unsigned long w) return __kernel_ctpop(w); } -static inline unsigned int __arch_weight32(unsigned int w) +static inline unsigned int __arch_hweight32(unsigned int w) { return __arch_hweight64(w); } diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index 7739a62440a7..5a62fb46ef20 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -35,7 +35,7 @@ endif obj-y += irq_pyxis.o irq_i8259.o irq_srm.o obj-y += err_ev6.o -obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o +obj-y += es1888.o smc37c669.o smc37c93x.o pc873xx.o gct.o obj-y += srmcons.o else @@ -63,11 +63,11 @@ obj-$(CONFIG_ALPHA_WILDFIRE) += core_wildfire.o # Board support obj-$(CONFIG_ALPHA_ALCOR) += sys_alcor.o irq_i8259.o irq_srm.o obj-$(CONFIG_ALPHA_CABRIOLET) += sys_cabriolet.o irq_i8259.o irq_srm.o \ - ns87312.o + pc873xx.o obj-$(CONFIG_ALPHA_EB164) += sys_cabriolet.o irq_i8259.o irq_srm.o \ - ns87312.o + pc873xx.o obj-$(CONFIG_ALPHA_EB66P) += sys_cabriolet.o irq_i8259.o irq_srm.o \ - ns87312.o + pc873xx.o obj-$(CONFIG_ALPHA_LX164) += sys_cabriolet.o irq_i8259.o irq_srm.o \ smc37c93x.o obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \ @@ -90,14 +90,14 @@ obj-$(CONFIG_ALPHA_RUFFIAN) += sys_ruffian.o irq_pyxis.o irq_i8259.o obj-$(CONFIG_ALPHA_RX164) += sys_rx164.o irq_i8259.o obj-$(CONFIG_ALPHA_SABLE) += sys_sable.o obj-$(CONFIG_ALPHA_LYNX) += sys_sable.o -obj-$(CONFIG_ALPHA_BOOK1) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o -obj-$(CONFIG_ALPHA_AVANTI) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o -obj-$(CONFIG_ALPHA_NONAME) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o -obj-$(CONFIG_ALPHA_P2K) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o -obj-$(CONFIG_ALPHA_XL) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o +obj-$(CONFIG_ALPHA_BOOK1) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o +obj-$(CONFIG_ALPHA_AVANTI) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o +obj-$(CONFIG_ALPHA_NONAME) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o +obj-$(CONFIG_ALPHA_P2K) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o +obj-$(CONFIG_ALPHA_XL) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o obj-$(CONFIG_ALPHA_SX164) += sys_sx164.o irq_pyxis.o irq_i8259.o \ irq_srm.o smc37c669.o -obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o ns87312.o +obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o pc873xx.o obj-$(CONFIG_ALPHA_WILDFIRE) += sys_wildfire.o irq_i8259.o # Error support diff --git a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c deleted file mode 100644 index 342b56d24c20..000000000000 --- a/arch/alpha/kernel/ns87312.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * linux/arch/alpha/kernel/ns87312.c - */ - -#include <linux/init.h> -#include <asm/io.h> -#include "proto.h" - - -/* - * The SRM console *disables* the IDE interface, this code ensures it's - * enabled. - * - * This code bangs on a control register of the 87312 Super I/O chip - * that implements parallel port/serial ports/IDE/FDI. Depending on - * the motherboard, the Super I/O chip can be configured through a - * pair of registers that are located either at I/O ports 0x26e/0x26f - * or 0x398/0x399. Unfortunately, autodetecting which base address is - * in use works only once (right after a reset). The Super I/O chip - * has the additional quirk that configuration register data must be - * written twice (I believe this is a safety feature to prevent - * accidental modification---fun, isn't it?). - */ - -void __init -ns87312_enable_ide(long ide_base) -{ - int data; - unsigned long flags; - - local_irq_save(flags); - outb(0, ide_base); /* set the index register for reg #0 */ - data = inb(ide_base+1); /* read the current contents */ - outb(0, ide_base); /* set the index register for reg #0 */ - outb(data | 0x40, ide_base+1); /* turn on IDE */ - outb(data | 0x40, ide_base+1); /* turn on IDE, really! */ - local_irq_restore(flags); -} diff --git a/arch/alpha/kernel/pc873xx.c b/arch/alpha/kernel/pc873xx.c new file mode 100644 index 000000000000..27dcbff85613 --- /dev/null +++ b/arch/alpha/kernel/pc873xx.c @@ -0,0 +1,88 @@ +#include <linux/ioport.h> +#include <asm/io.h> + +#include "pc873xx.h" + +static unsigned pc873xx_probelist[] = {0x398, 0x26e, 0}; + +static char *pc873xx_names[] = { + "PC87303", "PC87306", "PC87312", "PC87332", "PC87334" +}; + +static unsigned int base, model; + + +unsigned int __init pc873xx_get_base() +{ + return base; +} + +char *__init pc873xx_get_model() +{ + return pc873xx_names[model]; +} + +static unsigned char __init pc873xx_read(unsigned int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static void __init pc873xx_write(unsigned int base, int reg, unsigned char data) +{ + unsigned long flags; + + local_irq_save(flags); + outb(reg, base); + outb(data, base + 1); + outb(data, base + 1); /* Must be written twice */ + local_irq_restore(flags); +} + +int __init pc873xx_probe(void) +{ + int val, index = 0; + + while ((base = pc873xx_probelist[index++])) { + + if (request_region(base, 2, "Super IO PC873xx") == NULL) + continue; + + val = pc873xx_read(base, REG_SID); + if ((val & 0xf0) == 0x10) { + model = PC87332; + break; + } else if ((val & 0xf8) == 0x70) { + model = PC87306; + break; + } else if ((val & 0xf8) == 0x50) { + model = PC87334; + break; + } else if ((val & 0xf8) == 0x40) { + model = PC87303; + break; + } + + release_region(base, 2); + } + + return (base == 0) ? -1 : 1; +} + +void __init pc873xx_enable_epp19(void) +{ + unsigned char data; + + printk(KERN_INFO "PC873xx enabling EPP v1.9\n"); + data = pc873xx_read(base, REG_PCR); + pc873xx_write(base, REG_PCR, (data & 0xFC) | 0x02); +} + +void __init pc873xx_enable_ide(void) +{ + unsigned char data; + + printk(KERN_INFO "PC873xx enabling IDE interrupt\n"); + data = pc873xx_read(base, REG_FER); + pc873xx_write(base, REG_FER, data | 0x40); +} diff --git a/arch/alpha/kernel/pc873xx.h b/arch/alpha/kernel/pc873xx.h new file mode 100644 index 000000000000..25e16956fe3e --- /dev/null +++ b/arch/alpha/kernel/pc873xx.h @@ -0,0 +1,35 @@ + +#ifndef _PC873xx_H_ +#define _PC873xx_H_ + +/* + * Control Register Values + */ +#define REG_FER 0x00 +#define REG_FAR 0x01 +#define REG_PTR 0x02 +#define REG_FCR 0x03 +#define REG_PCR 0x04 +#define REG_KRR 0x05 +#define REG_PMC 0x06 +#define REG_TUP 0x07 +#define REG_SID 0x08 +#define REG_ASC 0x09 +#define REG_IRC 0x0e + +/* + * Model numbers + */ +#define PC87303 0 +#define PC87306 1 +#define PC87312 2 +#define PC87332 3 +#define PC87334 4 + +int pc873xx_probe(void); +unsigned int pc873xx_get_base(void); +char *pc873xx_get_model(void); +void pc873xx_enable_epp19(void); +void pc873xx_enable_ide(void); + +#endif diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index a5fffc882c72..738fc824e2ea 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -53,7 +53,6 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num, /** * pci_mmap_resource - map a PCI resource into user memory space - * @filp: open sysfs file * @kobj: kobject for mapping * @attr: struct bin_attribute for the file being mapped * @vma: struct vm_area_struct passed into the mmap @@ -61,7 +60,7 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num, * * Use the bus mapping routines to map a PCI resource into userspace. */ -static int pci_mmap_resource(struct file *filp, struct kobject *kobj, +static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, struct vm_area_struct *vma, int sparse) { diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c index d4327e461c22..85b4aea01ef8 100644 --- a/arch/alpha/kernel/sys_sio.c +++ b/arch/alpha/kernel/sys_sio.c @@ -34,6 +34,7 @@ #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" +#include "pc873xx.h" #if defined(ALPHA_RESTORE_SRM_SETUP) /* Save LCA configuration data as the console had it set up. */ @@ -208,7 +209,27 @@ noname_init_pci(void) common_init_pci(); sio_pci_route(); sio_fixup_irq_levels(sio_collect_irq_levels()); - ns87312_enable_ide(0x26e); + + if (pc873xx_probe() == -1) { + printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); + } else { + printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", + pc873xx_get_model(), pc873xx_get_base()); + + /* Enabling things in the Super IO chip doesn't actually + * configure and enable things, the legacy drivers still + * need to do the actual configuration and enabling. + * This only unblocks them. + */ + +#if !defined(CONFIG_ALPHA_AVANTI) + /* Don't bother on the Avanti family. + * None of them had on-board IDE. + */ + pc873xx_enable_ide(); +#endif + pc873xx_enable_epp19(); + } } static inline void __init diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1f254bd6c937..98922f7d2d12 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -955,7 +955,8 @@ config XSCALE_PMU default y config CPU_HAS_PMU - depends on CPU_V6 || CPU_V7 || XSCALE_PMU + depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \ + (!ARCH_OMAP3 || OMAP3_EMU) default y bool diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index a52a27c1d9be..6f80665f477e 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -951,8 +951,6 @@ static int sa1111_resume(struct platform_device *dev) if (!save) return 0; - spin_lock_irqsave(&sachip->lock, flags); - /* * Ensure that the SA1111 is still here. * FIXME: shouldn't do this here. @@ -969,6 +967,13 @@ static int sa1111_resume(struct platform_device *dev) * First of all, wake up the chip. */ sa1111_wake(sachip); + + /* + * Only lock for write ops. Also, sa1111_wake must be called with + * released spinlock! + */ + spin_lock_irqsave(&sachip->lock, flags); + sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0); sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1); diff --git a/arch/arm/include/asm/mach/udc_pxa2xx.h b/arch/arm/include/asm/mach/udc_pxa2xx.h index f3eabf1ecec3..833306ee9e7f 100644 --- a/arch/arm/include/asm/mach/udc_pxa2xx.h +++ b/arch/arm/include/asm/mach/udc_pxa2xx.h @@ -21,8 +21,8 @@ struct pxa2xx_udc_mach_info { * here. Note that sometimes the signals go through inverters... */ bool gpio_vbus_inverted; - u16 gpio_vbus; /* high == vbus present */ + int gpio_vbus; /* high == vbus present */ bool gpio_pullup_inverted; - u16 gpio_pullup; /* high == pullup activated */ + int gpio_pullup; /* high == pullup activated */ }; diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 6a89567ffc5b..7bed3daf83b8 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h @@ -91,7 +91,11 @@ extern void release_thread(struct task_struct *); unsigned long get_wchan(struct task_struct *p); +#if __LINUX_ARM_ARCH__ == 6 +#define cpu_relax() smp_mb() +#else #define cpu_relax() barrier() +#endif /* * Create a new kernel thread diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index c45768614c8a..de12536d687f 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -201,7 +201,7 @@ armpmu_event_update(struct perf_event *event, { int shift = 64 - 32; s64 prev_raw_count, new_raw_count; - s64 delta; + u64 delta; again: prev_raw_count = atomic64_read(&hwc->prev_count); diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c index d029d1f5f9e2..02cae5e2951c 100644 --- a/arch/arm/mach-msm/dma.c +++ b/arch/arm/mach-msm/dma.c @@ -17,6 +17,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/interrupt.h> +#include <linux/completion.h> #include <mach/dma.h> #define MSM_DMOV_CHANNEL_COUNT 16 diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c index d3d5877c750e..b2c7f512070f 100644 --- a/arch/arm/mach-mx3/mach-mx31lilly.c +++ b/arch/arm/mach-mx3/mach-mx31lilly.c @@ -115,6 +115,8 @@ static struct platform_device physmap_flash_device = { /* USB */ +#if defined(CONFIG_USB_ULPI) + #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \ PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU) @@ -244,10 +246,20 @@ static struct mxc_usbh_platform_data usbh2_pdata = { .flags = MXC_EHCI_POWER_PINS_ENABLED, }; -static struct platform_device *devices[] __initdata = { - &smsc91x_device, - &physmap_flash_device, -}; +static void lilly1131_usb_init(void) +{ + usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, + USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT); + usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, + USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT); + + mxc_register_device(&mxc_usbh1, &usbh1_pdata); + mxc_register_device(&mxc_usbh2, &usbh2_pdata); +} + +#else +static inline void lilly1131_usb_init(void) {} +#endif /* CONFIG_USB_ULPI */ /* SPI */ @@ -279,6 +291,11 @@ static struct spi_board_info mc13783_dev __initdata = { .platform_data = &mc13783_pdata, }; +static struct platform_device *devices[] __initdata = { + &smsc91x_device, + &physmap_flash_device, +}; + static int mx31lilly_baseboard; core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444); @@ -321,13 +338,7 @@ static void __init mx31lilly_board_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); /* USB */ - usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, - USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT); - usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops, - USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT); - - mxc_register_device(&mxc_usbh1, &usbh1_pdata); - mxc_register_device(&mxc_usbh2, &usbh2_pdata); + lilly1131_usb_init(); } static void __init mx31lilly_timer_init(void) diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c index 2c471fc451d7..f035f4185274 100644 --- a/arch/arm/mach-nomadik/clock.c +++ b/arch/arm/mach-nomadik/clock.c @@ -32,7 +32,10 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL(clk_disable); -/* We have a fixed clock alone, for now */ +static struct clk clk_24 = { + .rate = 2400000, +}; + static struct clk clk_48 = { .rate = 48 * 1000 * 1000, }; @@ -50,6 +53,8 @@ static struct clk clk_default; } static struct clk_lookup lookups[] = { + CLK(&clk_24, "mtu0"), + CLK(&clk_24, "mtu1"), CLK(&clk_48, "uart0"), CLK(&clk_48, "uart1"), CLK(&clk_default, "gpio.0"), @@ -59,10 +64,8 @@ static struct clk_lookup lookups[] = { CLK(&clk_default, "rng"), }; -static int __init clk_init(void) +int __init clk_init(void) { clkdev_add_table(lookups, ARRAY_SIZE(lookups)); return 0; } - -arch_initcall(clk_init); diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h index 5563985a2cc7..78da2e7c3985 100644 --- a/arch/arm/mach-nomadik/clock.h +++ b/arch/arm/mach-nomadik/clock.h @@ -11,3 +11,5 @@ struct clk { unsigned long rate; }; + +int __init clk_init(void); diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 91c3c901b469..ac58e3b03b1a 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -31,6 +31,8 @@ #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> +#include "clock.h" + #define __MEM_4K_RESOURCE(x) \ .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} @@ -143,6 +145,12 @@ void __init cpu8815_init_irq(void) /* This modified VIC cell has two register blocks, at 0 and 0x20 */ vic_init(io_p2v(NOMADIK_IC_BASE + 0x00), IRQ_VIC_START + 0, ~0, 0); vic_init(io_p2v(NOMADIK_IC_BASE + 0x20), IRQ_VIC_START + 32, ~0, 0); + + /* + * Init clocks here so that they are available for system timer + * initialization. + */ + clk_init(); } /* diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index f848ba8dbc16..a04cffd691c5 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -538,9 +538,7 @@ static void ads7846_dev_init(void) printk(KERN_ERR "can't get ads7846 pen down GPIO\n"); gpio_direction_input(OMAP3_STALKER_TS_GPIO); - - omap_set_gpio_debounce(OMAP3_STALKER_TS_GPIO, 1); - omap_set_gpio_debounce_time(OMAP3_STALKER_TS_GPIO, 0xa); + gpio_set_debounce(OMAP3_STALKER_TS_GPIO, 310); } static int ads7846_get_pendown_state(void) diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 02804224517b..e10db7a90cb2 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -1369,6 +1369,7 @@ static struct clk emif1_ick = { .ops = &clkops_omap2_dflt, .enable_reg = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .flags = ENABLE_ON_INIT, .clkdm_name = "l3_emif_clkdm", .parent = &ddrphy_ck, .recalc = &followparent_recalc, @@ -1379,6 +1380,7 @@ static struct clk emif2_ick = { .ops = &clkops_omap2_dflt, .enable_reg = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, + .flags = ENABLE_ON_INIT, .clkdm_name = "l3_emif_clkdm", .parent = &ddrphy_ck, .recalc = &followparent_recalc, diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 95c9a5f774e1..b7a4133267d8 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -409,10 +409,11 @@ static int _init_main_clk(struct omap_hwmod *oh) return 0; oh->_clk = omap_clk_get_by_name(oh->main_clk); - if (!oh->_clk) + if (!oh->_clk) { pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n", oh->name, oh->main_clk); return -EINVAL; + } if (!oh->_clk->clkdm) pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n", @@ -444,10 +445,11 @@ static int _init_interface_clks(struct omap_hwmod *oh) continue; c = omap_clk_get_by_name(os->clk); - if (!c) + if (!c) { pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n", oh->name, os->clk); ret = -EINVAL; + } os->_clk = c; } @@ -470,10 +472,11 @@ static int _init_opt_clks(struct omap_hwmod *oh) for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) { c = omap_clk_get_by_name(oc->clk); - if (!c) + if (!c) { pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n", oh->name, oc->clk); ret = -EINVAL; + } oc->_clk = c; } diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 2e967716cc3f..b88737fd6cfe 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -99,7 +99,7 @@ static void omap3_enable_io_chain(void) /* Do a readback to assure write has been done */ prm_read_mod_reg(WKUP_MOD, PM_WKEN); - while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) & + while (!(prm_read_mod_reg(WKUP_MOD, PM_WKEN) & OMAP3430_ST_IO_CHAIN_MASK)) { timeout++; if (timeout > 1000) { @@ -108,7 +108,7 @@ static void omap3_enable_io_chain(void) return; } prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, - WKUP_MOD, PM_WKST); + WKUP_MOD, PM_WKEN); } } } diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c index c68f799e83c5..d72d1ac30333 100644 --- a/arch/arm/mach-omap2/usb-ehci.c +++ b/arch/arm/mach-omap2/usb-ehci.c @@ -20,6 +20,8 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/dma-mapping.h> + #include <asm/io.h> #include <plat/mux.h> diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index d60db87dde08..fa6a708b4099 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -697,7 +697,7 @@ static struct i2c_board_info __initdata mioa701_pi2c_devices[] = { }; /* Board I2C devices. */ -static struct i2c_board_info __initdata mioa701_i2c_devices[] = { +static struct i2c_board_info mioa701_i2c_devices[] = { { I2C_BOARD_INFO("mt9m111", 0x5d), }, diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c index 033b567e50bb..ce1104d1bc17 100644 --- a/arch/arm/mach-pxa/palmtc.c +++ b/arch/arm/mach-pxa/palmtc.c @@ -263,11 +263,11 @@ const struct matrix_keymap_data palmtc_keymap_data = { .keymap_size = ARRAY_SIZE(palmtc_matrix_keys), }; -const static unsigned int palmtc_keypad_row_gpios[] = { +static const unsigned int palmtc_keypad_row_gpios[] = { 0, 9, 10, 11 }; -const static unsigned int palmtc_keypad_col_gpios[] = { +static const unsigned int palmtc_keypad_col_gpios[] = { 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 79, 80 }; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 4d2413ed0ffa..c1048a35f187 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -818,6 +818,9 @@ static struct i2c_board_info akita_i2c_board_info[] = { .type = "max7310", .addr = 0x18, .platform_data = &akita_ioexp, + }, { + .type = "wm8750", + .addr = 0x1b, }, }; diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index f5d1ae3db3a4..d303c6929d32 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -3,8 +3,9 @@ * * Support for the Zipit Z2 Handheld device. * - * Author: Ken McGuire - * Created: Jan 25, 2009 + * Copyright (C) 2009-2010 Marek Vasut <marek.vasut@gmail.com> + * + * Based on research and code by: Ken McGuire * Based on mainstone.c as modified for the Zipit Z2. * * This program is free software; you can redistribute it and/or modify @@ -157,21 +158,14 @@ static struct mtd_partition z2_flash_parts[] = { { .name = "U-Boot Bootloader", .offset = 0x0, - .size = 0x20000, - }, - { - .name = "Linux Kernel", - .offset = 0x20000, - .size = 0x220000, - }, - { - .name = "Filesystem", - .offset = 0x240000, - .size = 0x5b0000, - }, - { + .size = 0x40000, + }, { .name = "U-Boot Environment", - .offset = 0x7f0000, + .offset = 0x40000, + .size = 0x60000, + }, { + .name = "Flash", + .offset = 0x60000, .size = MTDPART_SIZ_FULL, }, }; diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index ee5e392430e8..b4575ae9648e 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -18,6 +18,7 @@ config REALVIEW_EB_ARM11MP bool "Support ARM11MPCore tile" depends on MACH_REALVIEW_EB select CPU_V6 + select ARCH_HAS_BARRIERS if SMP help Enable support for the ARM11MPCore tile on the Realview platform. @@ -35,6 +36,7 @@ config MACH_REALVIEW_PB11MP select CPU_V6 select ARM_GIC select HAVE_PATA_PLATFORM + select ARCH_HAS_BARRIERS if SMP help Include support for the ARM(R) RealView MPCore Platform Baseboard. PB11MPCore is a platform with an on-board ARM11MPCore and has diff --git a/arch/arm/mach-realview/include/mach/barriers.h b/arch/arm/mach-realview/include/mach/barriers.h new file mode 100644 index 000000000000..0c5d749d7b5f --- /dev/null +++ b/arch/arm/mach-realview/include/mach/barriers.h @@ -0,0 +1,8 @@ +/* + * Barriers redefined for RealView ARM11MPCore platforms with L220 cache + * controller to work around hardware errata causing the outer_sync() + * operation to deadlock the system. + */ +#define mb() dsb() +#define rmb() dmb() +#define wmb() mb() diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 422ccd70d5f5..4425018fab82 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -32,6 +32,7 @@ #include <asm/leds.h> #include <asm/mach-types.h> #include <asm/pmu.h> +#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/localtimer.h> @@ -457,7 +458,7 @@ static void __init realview_eb_init(void) MACHINE_START(REALVIEW_EB, "ARM-RealView EB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_io = REALVIEW_EB_UART0_BASE, + .phys_io = REALVIEW_EB_UART0_BASE & SECTION_MASK, .io_pg_offst = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index 96568ebfa2bb..099a1f125cf8 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -32,6 +32,7 @@ #include <asm/leds.h> #include <asm/mach-types.h> #include <asm/pmu.h> +#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> @@ -351,7 +352,7 @@ static void __init realview_pb1176_init(void) MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_io = REALVIEW_PB1176_UART0_BASE, + .phys_io = REALVIEW_PB1176_UART0_BASE & SECTION_MASK, .io_pg_offst = (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_pb1176_fixup, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 7fbefbbebaf0..0e07a5ccb75f 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -32,6 +32,7 @@ #include <asm/leds.h> #include <asm/mach-types.h> #include <asm/pmu.h> +#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/localtimer.h> @@ -373,7 +374,7 @@ static void __init realview_pb11mp_init(void) MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_io = REALVIEW_PB11MP_UART0_BASE, + .phys_io = REALVIEW_PB11MP_UART0_BASE & SECTION_MASK, .io_pg_offst = (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index d3c113b3dfce..ac2f06f1ca50 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -31,6 +31,7 @@ #include <asm/leds.h> #include <asm/mach-types.h> #include <asm/pmu.h> +#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/mach/arch.h> @@ -323,7 +324,7 @@ static void __init realview_pba8_init(void) MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_io = REALVIEW_PBA8_UART0_BASE, + .phys_io = REALVIEW_PBA8_UART0_BASE & SECTION_MASK, .io_pg_offst = (IO_ADDRESS(REALVIEW_PBA8_UART0_BASE) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index a235ba30996b..08fd683adc4c 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -31,6 +31,7 @@ #include <asm/mach-types.h> #include <asm/pmu.h> #include <asm/smp_twd.h> +#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> @@ -409,7 +410,7 @@ static void __init realview_pbx_init(void) MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_io = REALVIEW_PBX_UART0_BASE, + .phys_io = REALVIEW_PBX_UART0_BASE & SECTION_MASK, .io_pg_offst = (IO_ADDRESS(REALVIEW_PBX_UART0_BASE) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .fixup = realview_pbx_fixup, diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index c7bc4199e3a8..4556aea9c3c5 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o obj-$(CONFIG_MACH_U5500) += board-u5500.o -obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 6544855af2f1..fe84b9021c7a 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -16,6 +16,7 @@ #include <asm/clkdev.h> +#include <plat/mtu.h> #include <mach/hardware.h> #include "clock.h" @@ -59,6 +60,9 @@ #define PRCM_DMACLK_MGT 0x074 #define PRCM_B2R2CLK_MGT 0x078 #define PRCM_TVCLK_MGT 0x07C +#define PRCM_TCR 0x1C8 +#define PRCM_TCR_STOPPED (1 << 16) +#define PRCM_TCR_DOZE_MODE (1 << 17) #define PRCM_UNIPROCLK_MGT 0x278 #define PRCM_SSPCLK_MGT 0x280 #define PRCM_RNGCLK_MGT 0x284 @@ -120,10 +124,95 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL(clk_disable); +/* + * The MTU has a separate, rather complex muxing setup + * with alternative parents (peripheral cluster or + * ULP or fixed 32768 Hz) depending on settings + */ +static unsigned long clk_mtu_get_rate(struct clk *clk) +{ + void __iomem *addr = __io_address(U8500_PRCMU_BASE) + + PRCM_TCR; + u32 tcr = readl(addr); + int mtu = (int) clk->data; + /* + * One of these is selected eventually + * TODO: Replace the constant with a reference + * to the ULP source once this is modeled. + */ + unsigned long clk32k = 32768; + unsigned long mturate; + unsigned long retclk; + + /* Get the rate from the parent as a default */ + if (clk->parent_periph) + mturate = clk_get_rate(clk->parent_periph); + else if (clk->parent_cluster) + mturate = clk_get_rate(clk->parent_cluster); + else + /* We need to be connected SOMEWHERE */ + BUG(); + + /* + * Are we in doze mode? + * In this mode the parent peripheral or the fixed 32768 Hz + * clock is fed into the block. + */ + if (!(tcr & PRCM_TCR_DOZE_MODE)) { + /* + * Here we're using the clock input from the APE ULP + * clock domain. But first: are the timers stopped? + */ + if (tcr & PRCM_TCR_STOPPED) { + clk32k = 0; + mturate = 0; + } else { + /* Else default mode: 0 and 2.4 MHz */ + clk32k = 0; + if (cpu_is_u5500()) + /* DB5500 divides by 8 */ + mturate /= 8; + else if (cpu_is_u8500ed()) { + /* + * This clocking setting must not be used + * in the ED chip, it is simply not + * connected anywhere! + */ + mturate = 0; + BUG(); + } else + /* + * In this mode the ulp38m4 clock is divided + * by a factor 16, on the DB8500 typically + * 38400000 / 16 ~ 2.4 MHz. + * TODO: Replace the constant with a reference + * to the ULP source once this is modeled. + */ + mturate = 38400000 / 16; + } + } + + /* Return the clock selected for this MTU */ + if (tcr & (1 << mtu)) + retclk = clk32k; + else + retclk = mturate; + + pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk); + return retclk; +} + unsigned long clk_get_rate(struct clk *clk) { unsigned long rate; + /* + * If there is a custom getrate callback for this clock, + * it will take precedence. + */ + if (clk->get_rate) + return clk->get_rate(clk); + if (clk->ops && clk->ops->get_rate) return clk->ops->get_rate(clk); @@ -341,8 +430,9 @@ static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); /* Peripheral Cluster #6 */ -static DEFINE_PRCC_CLK(6, mtu1_v1, 8, -1, NULL); -static DEFINE_PRCC_CLK(6, mtu0_v1, 7, -1, NULL); +/* MTU ID in data */ +static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1); +static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0); static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); @@ -357,8 +447,9 @@ static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); /* Peripheral Cluster #7 */ static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); -static DEFINE_PRCC_CLK(7, mtu1_ed, 3, -1, NULL); -static DEFINE_PRCC_CLK(7, mtu0_ed, 2, -1, NULL); +/* MTU ID in data */ +static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1); +static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0); static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); @@ -503,15 +594,17 @@ static struct clk_lookup u8500_v1_clks[] = { CLK(uiccclk, "uicc", NULL), }; -static int __init clk_init(void) +int __init clk_init(void) { if (cpu_is_u8500ed()) { clk_prcmu_ops.enable = clk_prcmu_ed_enable; clk_prcmu_ops.disable = clk_prcmu_ed_disable; + clk_per6clk.rate = 100000000; } else if (cpu_is_u5500()) { /* Clock tree for U5500 not implemented yet */ clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; + clk_per6clk.rate = 26000000; } clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); @@ -522,4 +615,3 @@ static int __init clk_init(void) return 0; } -arch_initcall(clk_init); diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h index e4f99b65026f..a05802501527 100644 --- a/arch/arm/mach-ux500/clock.h +++ b/arch/arm/mach-ux500/clock.h @@ -28,6 +28,9 @@ struct clkops { * @ops: pointer to clkops struct used to control this clock * @name: name, for debugging * @enabled: refcount. positive if enabled, zero if disabled + * @get_rate: custom callback for getting the clock rate + * @data: custom per-clock data for example for the get_rate + * callback * @rate: fixed rate for clocks which don't implement * ops->getrate * @prcmu_cg_off: address offset of the combined enable/disable register @@ -67,6 +70,8 @@ struct clk { const struct clkops *ops; const char *name; unsigned int enabled; + unsigned long (*get_rate)(struct clk *); + void *data; unsigned long rate; struct list_head list; @@ -117,9 +122,26 @@ struct clk clk_##_name = { \ .parent_periph = _kernclk \ } +#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcc_ops, \ + .cluster = _pclust, \ + .prcc_bus = _bus_en, \ + .prcc_kernel = _kernel_en, \ + .parent_cluster = &clk_per##_pclust##clk, \ + .parent_periph = _kernclk, \ + .get_rate = _callback, \ + .data = (void *) _data \ + } + + #define CLK(_clk, _devname, _conname) \ { \ .clk = &clk_##_clk, \ .dev_id = _devname, \ .con_id = _conname, \ } + +int __init clk_db8500_ed_fixup(void); +int __init clk_init(void); diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index d81ad023963c..e0fd747e447a 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -62,6 +62,12 @@ void __init ux500_init_irq(void) { gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); + + /* + * Init clocks here so that they are available for system timer + * initialization. + */ + clk_init(); } #ifdef CONFIG_CACHE_L2X0 diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index e6f73030d5f0..6353459bb567 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -2,6 +2,7 @@ * Versatile Express Core Tile Cortex A9x4 Support */ #include <linux/init.h> +#include <linux/gfp.h> #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/platform_device.h> @@ -9,6 +10,7 @@ #include <linux/amba/clcd.h> #include <asm/clkdev.h> +#include <asm/pgtable.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/cache-l2x0.h> #include <asm/hardware/gic.h> @@ -235,7 +237,7 @@ static void ct_ca9x4_init(void) } MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") - .phys_io = V2M_UART0, + .phys_io = V2M_UART0 & SECTION_MASK, .io_pg_offst = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .map_io = ct_ca9x4_map_io, diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 346ae14824a5..101105e52610 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -735,6 +735,25 @@ config NEEDS_SYSCALL_FOR_CMPXCHG Forget about fast user space cmpxchg support. It is just not possible. +config DMA_CACHE_RWFO + bool "Enable read/write for ownership DMA cache maintenance" + depends on CPU_V6 && SMP + default y + help + The Snoop Control Unit on ARM11MPCore does not detect the + cache maintenance operations and the dma_{map,unmap}_area() + functions may leave stale cache entries on other CPUs. By + enabling this option, Read or Write For Ownership in the ARMv6 + DMA cache maintenance functions is performed. These LDR/STR + instructions change the cache line state to shared or modified + so that the cache operation has the desired effect. + + Note that the workaround is only valid on processors that do + not perform speculative loads into the D-cache. For such + processors, if cache maintenance operations are not broadcast + in hardware, other workarounds are needed (e.g. cache + maintenance broadcasting in software via FIQ). + config OUTER_CACHE bool @@ -794,6 +813,8 @@ config ARM_L1_CACHE_SHIFT config ARM_DMA_MEM_BUFFERABLE bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7 + depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \ + MACH_REALVIEW_PB11MP) default y if CPU_V6 || CPU_V7 help Historically, the kernel has used strongly ordered mappings to diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index e46ecd847138..86aa689ef1aa 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -211,8 +211,9 @@ v6_dma_inv_range: mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line #endif 1: -#ifdef CONFIG_SMP - str r0, [r0] @ write for ownership +#ifdef CONFIG_DMA_CACHE_RWFO + ldr r2, [r0] @ read for ownership + str r2, [r0] @ write for ownership #endif #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c6, 1 @ invalidate D line @@ -234,7 +235,7 @@ v6_dma_inv_range: v6_dma_clean_range: bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: -#ifdef CONFIG_SMP +#ifdef CONFIG_DMA_CACHE_RWFO ldr r2, [r0] @ read for ownership #endif #ifdef HARVARD_CACHE @@ -257,7 +258,7 @@ v6_dma_clean_range: ENTRY(v6_dma_flush_range) bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: -#ifdef CONFIG_SMP +#ifdef CONFIG_DMA_CACHE_RWFO ldr r2, [r0] @ read for ownership str r2, [r0] @ write for ownership #endif @@ -283,9 +284,13 @@ ENTRY(v6_dma_map_area) add r1, r1, r0 teq r2, #DMA_FROM_DEVICE beq v6_dma_inv_range +#ifndef CONFIG_DMA_CACHE_RWFO + b v6_dma_clean_range +#else teq r2, #DMA_TO_DEVICE beq v6_dma_clean_range b v6_dma_flush_range +#endif ENDPROC(v6_dma_map_area) /* @@ -295,6 +300,11 @@ ENDPROC(v6_dma_map_area) * - dir - DMA direction */ ENTRY(v6_dma_unmap_area) +#ifndef CONFIG_DMA_CACHE_RWFO + add r1, r1, r0 + teq r2, #DMA_TO_DEVICE + bne v6_dma_inv_range +#endif mov pc, lr ENDPROC(v6_dma_unmap_area) diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c index 5eb4fd93893d..ac163de7dc01 100644 --- a/arch/arm/mm/copypage-feroceon.c +++ b/arch/arm/mm/copypage-feroceon.c @@ -18,7 +18,7 @@ feroceon_copy_user_page(void *kto, const void *kfrom) { asm("\ stmfd sp!, {r4-r9, lr} \n\ - mov ip, %0 \n\ + mov ip, %2 \n\ 1: mov lr, r1 \n\ ldmia r1!, {r2 - r9} \n\ pld [lr, #32] \n\ @@ -64,7 +64,7 @@ feroceon_copy_user_page(void *kto, const void *kfrom) mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\ ldmfd sp!, {r4-r9, pc}" : - : "I" (PAGE_SIZE)); + : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE)); } void feroceon_copy_user_highpage(struct page *to, struct page *from, diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c index 7c2eb55cd4a9..cb589cbb2b6c 100644 --- a/arch/arm/mm/copypage-v4wb.c +++ b/arch/arm/mm/copypage-v4wb.c @@ -27,7 +27,7 @@ v4wb_copy_user_page(void *kto, const void *kfrom) { asm("\ stmfd sp!, {r4, lr} @ 2\n\ - mov r2, %0 @ 1\n\ + mov r2, %2 @ 1\n\ ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ stmia r0!, {r3, r4, ip, lr} @ 4\n\ @@ -44,7 +44,7 @@ v4wb_copy_user_page(void *kto, const void *kfrom) mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB\n\ ldmfd sp!, {r4, pc} @ 3" : - : "I" (PAGE_SIZE / 64)); + : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64)); } void v4wb_copy_user_highpage(struct page *to, struct page *from, diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c index 172e6a55458e..30c7d048a324 100644 --- a/arch/arm/mm/copypage-v4wt.c +++ b/arch/arm/mm/copypage-v4wt.c @@ -25,7 +25,7 @@ v4wt_copy_user_page(void *kto, const void *kfrom) { asm("\ stmfd sp!, {r4, lr} @ 2\n\ - mov r2, %0 @ 1\n\ + mov r2, %2 @ 1\n\ ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 1: stmia r0!, {r3, r4, ip, lr} @ 4\n\ ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ @@ -40,7 +40,7 @@ v4wt_copy_user_page(void *kto, const void *kfrom) mcr p15, 0, r2, c7, c7, 0 @ flush ID cache\n\ ldmfd sp!, {r4, pc} @ 3" : - : "I" (PAGE_SIZE / 64)); + : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64)); } void v4wt_copy_user_highpage(struct page *to, struct page *from, diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c index 747ad4140fc7..f9cde0702f1e 100644 --- a/arch/arm/mm/copypage-xsc3.c +++ b/arch/arm/mm/copypage-xsc3.c @@ -34,7 +34,7 @@ xsc3_mc_copy_user_page(void *kto, const void *kfrom) { asm("\ stmfd sp!, {r4, r5, lr} \n\ - mov lr, %0 \n\ + mov lr, %2 \n\ \n\ pld [r1, #0] \n\ pld [r1, #32] \n\ @@ -67,7 +67,7 @@ xsc3_mc_copy_user_page(void *kto, const void *kfrom) \n\ ldmfd sp!, {r4, r5, pc}" : - : "I" (PAGE_SIZE / 64 - 1)); + : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1)); } void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 13fa536d82e6..9e7742f0a102 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -24,15 +24,6 @@ #include <asm/tlbflush.h> #include <asm/sizes.h> -/* Sanity check size */ -#if (CONSISTENT_DMA_SIZE % SZ_2M) -#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB" -#endif - -#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) -#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) -#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) - static u64 get_coherent_dma_mask(struct device *dev) { u64 mask = ISA_DMA_THRESHOLD; @@ -123,6 +114,15 @@ static void __dma_free_buffer(struct page *page, size_t size) } #ifdef CONFIG_MMU +/* Sanity check size */ +#if (CONSISTENT_DMA_SIZE % SZ_2M) +#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB" +#endif + +#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) +#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) +#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) + /* * These are the page tables (2MB each) covering uncached, DMA consistent allocations */ diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 92f5801f99c1..cbfb2edcf7d1 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr, if (addr < TASK_SIZE) return do_page_fault(addr, fsr, regs); + if (user_mode(regs)) + goto bad_area; + index = pgd_index(addr); /* diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index 77b030f5ec09..086816b205b8 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -48,7 +48,16 @@ void *kmap_atomic(struct page *page, enum km_type type) debug_kmap_atomic(type); - kmap = kmap_high_get(page); +#ifdef CONFIG_DEBUG_HIGHMEM + /* + * There is no cache coherency issue when non VIVT, so force the + * dedicated kmap usage for better debugging purposes in that case. + */ + if (!cache_is_vivt()) + kmap = NULL; + else +#endif + kmap = kmap_high_get(page); if (kmap) return kmap; diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1ba6cf5a2c02..f6a999465323 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -678,10 +678,10 @@ void __init mem_init(void) void free_initmem(void) { #ifdef CONFIG_HAVE_TCM - extern char *__tcm_start, *__tcm_end; + extern char __tcm_start, __tcm_end; - totalram_pages += free_area(__phys_to_pfn(__pa(__tcm_start)), - __phys_to_pfn(__pa(__tcm_end)), + totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)), + __phys_to_pfn(__pa(&__tcm_end)), "TCM link"); #endif diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 0ff3798769ab..08aaa4a7f65f 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -13,7 +13,9 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/clockchips.h> +#include <linux/clk.h> #include <linux/jiffies.h> +#include <linux/err.h> #include <asm/mach/time.h> #include <plat/mtu.h> @@ -124,13 +126,25 @@ static struct irqaction nmdk_timer_irq = { void __init nmdk_timer_init(void) { unsigned long rate; - u32 cr = MTU_CRn_32BITS;; + struct clk *clk0; + struct clk *clk1; + u32 cr; + + clk0 = clk_get_sys("mtu0", NULL); + BUG_ON(IS_ERR(clk0)); + + clk1 = clk_get_sys("mtu1", NULL); + BUG_ON(IS_ERR(clk1)); + + clk_enable(clk0); + clk_enable(clk1); /* * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: * use a divide-by-16 counter if it's more than 16MHz */ - rate = CLOCK_TICK_RATE; + cr = MTU_CRn_32BITS;; + rate = clk_get_rate(clk0); if (rate > 16 << 20) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; @@ -153,6 +167,14 @@ void __init nmdk_timer_init(void) nmdk_clksrc.name); /* Timer 1 is used for events, fix according to rate */ + cr = MTU_CRn_32BITS; + rate = clk_get_rate(clk1); + if (rate > 16 << 20) { + rate /= 16; + cr |= MTU_CRn_PRESCALE_16; + } else { + cr |= MTU_CRn_PRESCALE_1; + } writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); nmdk_clkevt.max_delta_ns = diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index c64875f11fac..44bafdab2dce 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -541,11 +541,11 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer) * timer is stopped */ udelay(3500000 / clk_get_rate(timer->fclk) + 1); - /* Ack possibly pending interrupt */ - omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, - OMAP_TIMER_INT_OVERFLOW); #endif } + /* Ack possibly pending interrupt */ + omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, + OMAP_TIMER_INT_OVERFLOW); } EXPORT_SYMBOL_GPL(omap_dm_timer_stop); diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 393e9219a5b6..9b7e3545f325 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -673,6 +673,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, if (cpu_is_omap34xx() || cpu_is_omap44xx()) clk_disable(bank->dbck); } + bank->dbck_enable_mask = val; __raw_writel(val, reg); } diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index e43983ba59c5..8ce0de247c71 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -140,8 +140,10 @@ static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags) return ERR_PTR(-ENOMEM); err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL); - if (err) + if (err) { + kfree(sgt); return ERR_PTR(err); + } pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries); diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index 6187edfbcb77..a17cc0c6a6b0 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -2,8 +2,9 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o pmu.o +obj-y := dma.o +obj-$(CONFIG_ARCH_PXA) += pmu.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_PXA3xx) += mfp.o obj-$(CONFIG_ARCH_MMP) += mfp.o diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 66dc2d03b7fc..d66cead97d28 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -277,7 +277,7 @@ ENTRY(vfp_put_double) #ifdef CONFIG_VFPv3 @ d16 - d31 registers .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 -1: mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr +1: mcrr p11, 3, r0, r1, c\dr @ fmdrr r0, r1, d\dr mov pc, lr .org 1b + 8 .endr diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c index 84d103c33c9c..a4dba6b20bd0 100644 --- a/arch/frv/kernel/gdb-stub.c +++ b/arch/frv/kernel/gdb-stub.c @@ -1789,6 +1789,12 @@ void gdbstub(int sigval) flush_cache = 1; break; + /* pNN: Read value of reg N and return it */ + case 'p': + /* return no value, indicating that we don't support + * this command and that gdb should use 'g' instead */ + break; + /* PNN,=RRRRRRRR: Write value R to reg N return OK */ case 'P': ptr = &input_buffer[1]; diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index d5f4e9161201..21b701374f72 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -144,6 +144,7 @@ int kvm_arch_hardware_enable(void *garbage) VP_INIT_ENV : VP_INIT_ENV_INITALIZE, __pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base); if (status != 0) { + spin_unlock(&vp_lock); printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n"); return -EINVAL; } diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 5dfd916e9ea6..7b3cdc6c6d91 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -121,7 +121,7 @@ static inline void down_spin(struct spinaphore *ss) ia64_invala(); for (;;) { - asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory"); + asm volatile ("ld8.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory"); if (time_before(t, serve)) return; cpu_relax(); diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index de493f86d28f..464ff32bee3d 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -34,6 +34,8 @@ /* MS be sure that SLAB allocates aligned objects */ #define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES +#define ARCH_SLAB_MINALIGN L1_CACHE_BYTES + #define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1))) #define PAGE_DOWN(addr) ((addr)&(~((PAGE_SIZE)-1))) diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index 9dcd90b5df55..79c74659f204 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -90,7 +90,6 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, /* FIXME this part of code is untested */ for_each_sg(sgl, sg, nents, i) { sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); - sg->dma_length = sg->length; __dma_sync_page(page_to_phys(sg_page(sg)), sg->offset, sg->length, direction); } diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 9cb782b8e036..23be25fec4d6 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -1277,6 +1277,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) printk(KERN_WARNING "PCI: Cannot allocate resource region " "%d of PCI bridge %d, will remap\n", i, bus->number); clear_resource: + res->start = res->end = 0; res->flags = 0; } diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c index d6119b879a98..45b40ac6c464 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.c +++ b/arch/mn10300/unit-asb2305/pci-asb2305.c @@ -117,6 +117,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) * Invalidate the resource to prevent * child resource allocations in this * range. */ + r->start = r->end = 0; r->flags = 0; } } diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 53696da4518f..2d38a50e66ba 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -135,13 +135,6 @@ config DEBUGGER depends on KGDB || XMON default y -config IRQSTACKS - bool "Use separate kernel stacks when processing interrupts" - help - If you say Y here the kernel will use separate kernel stacks - for handling hard and soft interrupts. This can help avoid - overflowing the process kernel stacks. - config VIRQ_DEBUG bool "Expose hardware/virtual IRQ mapping via debugfs" depends on DEBUG_FS diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index ad0df7d0a643..fae8192c8fcc 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -141,7 +141,7 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE $(obj)/wrapper.a: $(obj-wlib) FORCE $(call if_changed,bootar) -hostprogs-y := addnote addRamDisk hack-coff mktree +hostprogs-y := addnote hack-coff mktree targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ diff --git a/arch/powerpc/boot/addRamDisk.c b/arch/powerpc/boot/addRamDisk.c deleted file mode 100644 index 893f446cbd22..000000000000 --- a/arch/powerpc/boot/addRamDisk.c +++ /dev/null @@ -1,311 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <netinet/in.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <string.h> -#include <elf.h> - -#define ElfHeaderSize (64 * 1024) -#define ElfPages (ElfHeaderSize / 4096) -#define KERNELBASE (0xc000000000000000) -#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) - -struct addr_range { - unsigned long long addr; - unsigned long memsize; - unsigned long offset; -}; - -static int check_elf64(void *p, int size, struct addr_range *r) -{ - Elf64_Ehdr *elf64 = p; - Elf64_Phdr *elf64ph; - - if (elf64->e_ident[EI_MAG0] != ELFMAG0 || - elf64->e_ident[EI_MAG1] != ELFMAG1 || - elf64->e_ident[EI_MAG2] != ELFMAG2 || - elf64->e_ident[EI_MAG3] != ELFMAG3 || - elf64->e_ident[EI_CLASS] != ELFCLASS64 || - elf64->e_ident[EI_DATA] != ELFDATA2MSB || - elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64) - return 0; - - if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size) - return 0; - - elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 + - (unsigned long)elf64->e_phoff); - - r->memsize = (unsigned long)elf64ph->p_memsz; - r->offset = (unsigned long)elf64ph->p_offset; - r->addr = (unsigned long long)elf64ph->p_vaddr; - -#ifdef DEBUG - printf("PPC64 ELF file, ph:\n"); - printf("p_type 0x%08x\n", elf64ph->p_type); - printf("p_flags 0x%08x\n", elf64ph->p_flags); - printf("p_offset 0x%016llx\n", elf64ph->p_offset); - printf("p_vaddr 0x%016llx\n", elf64ph->p_vaddr); - printf("p_paddr 0x%016llx\n", elf64ph->p_paddr); - printf("p_filesz 0x%016llx\n", elf64ph->p_filesz); - printf("p_memsz 0x%016llx\n", elf64ph->p_memsz); - printf("p_align 0x%016llx\n", elf64ph->p_align); - printf("... skipping 0x%08lx bytes of ELF header\n", - (unsigned long)elf64ph->p_offset); -#endif - - return 64; -} -static void get4k(FILE *file, char *buf ) -{ - unsigned j; - unsigned num = fread(buf, 1, 4096, file); - for ( j=num; j<4096; ++j ) - buf[j] = 0; -} - -static void put4k(FILE *file, char *buf ) -{ - fwrite(buf, 1, 4096, file); -} - -static void death(const char *msg, FILE *fdesc, const char *fname) -{ - fprintf(stderr, msg); - fclose(fdesc); - unlink(fname); - exit(1); -} - -int main(int argc, char **argv) -{ - char inbuf[4096]; - struct addr_range vmlinux; - FILE *ramDisk; - FILE *inputVmlinux; - FILE *outputVmlinux; - - char *rd_name, *lx_name, *out_name; - - size_t i; - unsigned long ramFileLen; - unsigned long ramLen; - unsigned long roundR; - unsigned long offset_end; - - unsigned long kernelLen; - unsigned long actualKernelLen; - unsigned long round; - unsigned long roundedKernelLen; - unsigned long ramStartOffs; - unsigned long ramPages; - unsigned long roundedKernelPages; - unsigned long hvReleaseData; - u_int32_t eyeCatcher = 0xc8a5d9c4; - unsigned long naca; - unsigned long xRamDisk; - unsigned long xRamDiskSize; - long padPages; - - - if (argc < 2) { - fprintf(stderr, "Name of RAM disk file missing.\n"); - exit(1); - } - rd_name = argv[1]; - - if (argc < 3) { - fprintf(stderr, "Name of vmlinux file missing.\n"); - exit(1); - } - lx_name = argv[2]; - - if (argc < 4) { - fprintf(stderr, "Name of vmlinux output file missing.\n"); - exit(1); - } - out_name = argv[3]; - - - ramDisk = fopen(rd_name, "r"); - if ( ! ramDisk ) { - fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name); - exit(1); - } - - inputVmlinux = fopen(lx_name, "r"); - if ( ! inputVmlinux ) { - fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name); - exit(1); - } - - outputVmlinux = fopen(out_name, "w+"); - if ( ! outputVmlinux ) { - fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name); - exit(1); - } - - i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux); - if (i != sizeof(inbuf)) { - fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i); - exit(1); - } - - i = check_elf64(inbuf, sizeof(inbuf), &vmlinux); - if (i == 0) { - fprintf(stderr, "You must have a linux kernel specified as argv[2]\n"); - exit(1); - } - - /* Input Vmlinux file */ - fseek(inputVmlinux, 0, SEEK_END); - kernelLen = ftell(inputVmlinux); - fseek(inputVmlinux, 0, SEEK_SET); - printf("kernel file size = %lu\n", kernelLen); - - actualKernelLen = kernelLen - ElfHeaderSize; - - printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen); - - round = actualKernelLen % 4096; - roundedKernelLen = actualKernelLen; - if ( round ) - roundedKernelLen += (4096 - round); - printf("Vmlinux length rounded up to a 4k multiple = %ld/0x%lx \n", roundedKernelLen, roundedKernelLen); - roundedKernelPages = roundedKernelLen / 4096; - printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); - - offset_end = _ALIGN_UP(vmlinux.memsize, 4096); - /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ - padPages = offset_end/4096 - roundedKernelPages; - - /* Check and see if the vmlinux is already larger than _end in System.map */ - if (padPages < 0) { - /* vmlinux is larger than _end - adjust the offset to the start of the embedded ram disk */ - offset_end = roundedKernelLen; - printf("vmlinux is larger than _end indicates it needs to be - offset_end = %lx \n", offset_end); - padPages = 0; - printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages); - } - else { - /* _end is larger than vmlinux - use the offset to _end that we calculated from the system map */ - printf("vmlinux is smaller than _end indicates is needed - offset_end = %lx \n", offset_end); - printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages); - } - - - - /* Input Ram Disk file */ - // Set the offset that the ram disk will be started at. - ramStartOffs = offset_end; /* determined from the input vmlinux file and the system map */ - printf("Ram Disk will start at offset = 0x%lx \n", ramStartOffs); - - fseek(ramDisk, 0, SEEK_END); - ramFileLen = ftell(ramDisk); - fseek(ramDisk, 0, SEEK_SET); - printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen); - - ramLen = ramFileLen; - - roundR = 4096 - (ramLen % 4096); - if ( roundR ) { - printf("Rounding RAM disk file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR); - ramLen += roundR; - } - - printf("Rounded RAM disk size is %ld/0x%lx \n", ramLen, ramLen); - ramPages = ramLen / 4096; - printf("RAM disk pages to copy = %ld/0x%lx\n", ramPages, ramPages); - - - - // Copy 64K ELF header - for (i=0; i<(ElfPages); ++i) { - get4k( inputVmlinux, inbuf ); - put4k( outputVmlinux, inbuf ); - } - - /* Copy the vmlinux (as full pages). */ - fseek(inputVmlinux, ElfHeaderSize, SEEK_SET); - for ( i=0; i<roundedKernelPages; ++i ) { - get4k( inputVmlinux, inbuf ); - put4k( outputVmlinux, inbuf ); - } - - /* Insert pad pages (if appropriate) that are needed between */ - /* | the end of the vmlinux and the ram disk. */ - for (i=0; i<padPages; ++i) { - memset(inbuf, 0, 4096); - put4k(outputVmlinux, inbuf); - } - - /* Copy the ram disk (as full pages). */ - for ( i=0; i<ramPages; ++i ) { - get4k( ramDisk, inbuf ); - put4k( outputVmlinux, inbuf ); - } - - /* Close the input files */ - fclose(ramDisk); - fclose(inputVmlinux); - /* And flush the written output file */ - fflush(outputVmlinux); - - - - /* Fixup the new vmlinux to contain the ram disk starting offset (xRamDisk) and the ram disk size (xRamDiskSize) */ - /* fseek to the hvReleaseData pointer */ - fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); - if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { - death("Could not read hvReleaseData pointer\n", outputVmlinux, out_name); - } - hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ - printf("hvReleaseData is at %08lx\n", hvReleaseData); - - /* fseek to the hvReleaseData */ - fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); - if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { - death("Could not read hvReleaseData\n", outputVmlinux, out_name); - } - /* Check hvReleaseData sanity */ - if (memcmp(inbuf, &eyeCatcher, 4) != 0) { - death("hvReleaseData is invalid\n", outputVmlinux, out_name); - } - /* Get the naca pointer */ - naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE; - printf("Naca is at offset 0x%lx \n", naca); - - /* fseek to the naca */ - fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); - if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { - death("Could not read naca\n", outputVmlinux, out_name); - } - xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); - xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); - /* Make sure a RAM disk isn't already present */ - if ((xRamDisk != 0) || (xRamDiskSize != 0)) { - death("RAM disk is already attached to this kernel\n", outputVmlinux, out_name); - } - /* Fill in the values */ - *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); - *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages); - - /* Write out the new naca */ - fflush(outputVmlinux); - fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); - if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { - death("Could not write naca\n", outputVmlinux, out_name); - } - printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08lx\n", - ramPages, ramStartOffs); - - /* Done */ - fclose(outputVmlinux); - /* Set permission to executable */ - chmod(out_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); - - return 0; -} - diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts index 82ff2b13bc37..179a1785d645 100644 --- a/arch/powerpc/boot/dts/lite5200.dts +++ b/arch/powerpc/boot/dts/lite5200.dts @@ -134,12 +134,16 @@ compatible = "fsl,mpc5200-gpio"; reg = <0xb00 0x40>; interrupts = <1 7 0>; + gpio-controller; + #gpio-cells = <2>; }; gpio@c00 { compatible = "fsl,mpc5200-gpio-wkup"; reg = <0xc00 0x40>; interrupts = <1 8 0 0 3 0>; + gpio-controller; + #gpio-cells = <2>; }; spi@f00 { @@ -230,8 +234,8 @@ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co. - phy0: ethernet-phy@1 { - reg = <1>; + phy0: ethernet-phy@0 { + reg = <0>; }; }; @@ -255,7 +259,13 @@ compatible = "fsl,mpc5200-i2c","fsl-i2c"; reg = <0x3d40 0x40>; interrupts = <2 16 0>; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; }; + sram@8000 { compatible = "fsl,mpc5200-sram"; reg = <0x8000 0x4000>; @@ -281,4 +291,18 @@ 0x02000000 0 0xa0000000 0xa0000000 0 0x10000000 0x01000000 0 0x00000000 0xb0000000 0 0x01000000>; }; + + localbus { + compatible = "fsl,mpc5200-lpb","simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + + ranges = <0 0 0xff000000 0x01000000>; + + flash@0,0 { + compatible = "amd,am29lv652d", "cfi-flash"; + reg = <0 0 0x01000000>; + bank-width = <1>; + }; + }; }; diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts index e45a63be3a86..59702ace900f 100644 --- a/arch/powerpc/boot/dts/lite5200b.dts +++ b/arch/powerpc/boot/dts/lite5200b.dts @@ -259,6 +259,11 @@ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c"; reg = <0x3d40 0x40>; interrupts = <2 16 0>; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; }; sram@8000 { diff --git a/arch/powerpc/configs/40x/acadia_defconfig b/arch/powerpc/configs/40x/acadia_defconfig index 8e95f8d227b9..4aa17b676a3f 100644 --- a/arch/powerpc/configs/40x/acadia_defconfig +++ b/arch/powerpc/configs/40x/acadia_defconfig @@ -98,8 +98,7 @@ CONFIG_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig index 918f23fd2b18..9a5f1ab777ed 100644 --- a/arch/powerpc/configs/40x/ep405_defconfig +++ b/arch/powerpc/configs/40x/ep405_defconfig @@ -98,8 +98,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig index f87ef0382280..0b452135d1d4 100644 --- a/arch/powerpc/configs/40x/hcu4_defconfig +++ b/arch/powerpc/configs/40x/hcu4_defconfig @@ -98,8 +98,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig index 19fbcb075376..4d2de0bed60e 100644 --- a/arch/powerpc/configs/40x/kilauea_defconfig +++ b/arch/powerpc/configs/40x/kilauea_defconfig @@ -98,8 +98,7 @@ CONFIG_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig index eb41cd695979..a1f3f505e4a7 100644 --- a/arch/powerpc/configs/40x/makalu_defconfig +++ b/arch/powerpc/configs/40x/makalu_defconfig @@ -98,8 +98,7 @@ CONFIG_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/40x/virtex_defconfig b/arch/powerpc/configs/40x/virtex_defconfig index 416e79ac0711..c76313577140 100644 --- a/arch/powerpc/configs/40x/virtex_defconfig +++ b/arch/powerpc/configs/40x/virtex_defconfig @@ -77,8 +77,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig index bfff0eae39d2..6597b2f1d1a8 100644 --- a/arch/powerpc/configs/40x/walnut_defconfig +++ b/arch/powerpc/configs/40x/walnut_defconfig @@ -98,8 +98,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig index 1f6d0490e28d..2d3dfb55fbed 100644 --- a/arch/powerpc/configs/44x/arches_defconfig +++ b/arch/powerpc/configs/44x/arches_defconfig @@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32 CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig index 788faac6c27a..51a00c46df19 100644 --- a/arch/powerpc/configs/44x/bamboo_defconfig +++ b/arch/powerpc/configs/44x/bamboo_defconfig @@ -102,8 +102,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig index 4ef8bcab61f8..1028b1bfb602 100644 --- a/arch/powerpc/configs/44x/canyonlands_defconfig +++ b/arch/powerpc/configs/44x/canyonlands_defconfig @@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32 CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig index ca17b1496e32..69f5633cbd4f 100644 --- a/arch/powerpc/configs/44x/ebony_defconfig +++ b/arch/powerpc/configs/44x/ebony_defconfig @@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/eiger_defconfig b/arch/powerpc/configs/44x/eiger_defconfig index e3149bade0b2..dcd859c8b4a6 100644 --- a/arch/powerpc/configs/44x/eiger_defconfig +++ b/arch/powerpc/configs/44x/eiger_defconfig @@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32 CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig index af244e1d255e..a2c24d1e051e 100644 --- a/arch/powerpc/configs/44x/katmai_defconfig +++ b/arch/powerpc/configs/44x/katmai_defconfig @@ -97,8 +97,7 @@ CONFIG_RCU_FANOUT=32 CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/rainier_defconfig b/arch/powerpc/configs/44x/rainier_defconfig index 8fed3b26af2e..3bb55b57077e 100644 --- a/arch/powerpc/configs/44x/rainier_defconfig +++ b/arch/powerpc/configs/44x/rainier_defconfig @@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/redwood_defconfig b/arch/powerpc/configs/44x/redwood_defconfig index a67ec91a28c3..684f40dc8a41 100644 --- a/arch/powerpc/configs/44x/redwood_defconfig +++ b/arch/powerpc/configs/44x/redwood_defconfig @@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32 CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig index 886cb6aa6432..e202924e6173 100644 --- a/arch/powerpc/configs/44x/sam440ep_defconfig +++ b/arch/powerpc/configs/44x/sam440ep_defconfig @@ -103,8 +103,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig index 1b2f41dbcafb..c348a4662a9e 100644 --- a/arch/powerpc/configs/44x/sequoia_defconfig +++ b/arch/powerpc/configs/44x/sequoia_defconfig @@ -102,8 +102,7 @@ CONFIG_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig index 12041d355b8c..f4cb7e84cb83 100644 --- a/arch/powerpc/configs/44x/taishan_defconfig +++ b/arch/powerpc/configs/44x/taishan_defconfig @@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/44x/virtex5_defconfig b/arch/powerpc/configs/44x/virtex5_defconfig index 2518b8568c70..c7ead0ec00bc 100644 --- a/arch/powerpc/configs/44x/virtex5_defconfig +++ b/arch/powerpc/configs/44x/virtex5_defconfig @@ -80,8 +80,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig index 218d49b36a0c..7664c83c17c2 100644 --- a/arch/powerpc/configs/52xx/cm5200_defconfig +++ b/arch/powerpc/configs/52xx/cm5200_defconfig @@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig index 90492ff25232..eac7c17eef34 100644 --- a/arch/powerpc/configs/52xx/lite5200b_defconfig +++ b/arch/powerpc/configs/52xx/lite5200b_defconfig @@ -96,8 +96,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig index dffc8cac825f..27afb6ecdf61 100644 --- a/arch/powerpc/configs/52xx/motionpro_defconfig +++ b/arch/powerpc/configs/52xx/motionpro_defconfig @@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig index 3cb2a522046a..5fe39ddb4e14 100644 --- a/arch/powerpc/configs/52xx/pcm030_defconfig +++ b/arch/powerpc/configs/52xx/pcm030_defconfig @@ -98,8 +98,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig index 96181c62abfa..a108b84c0074 100644 --- a/arch/powerpc/configs/52xx/tqm5200_defconfig +++ b/arch/powerpc/configs/52xx/tqm5200_defconfig @@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig index 183c59c6d896..b728a7d64250 100644 --- a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig +++ b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig @@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig index 1524d948a2ba..8e738de5f6a5 100644 --- a/arch/powerpc/configs/86xx/gef_sbc310_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc310_defconfig @@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig index 767c204c0603..59bf9e27d7f2 100644 --- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig @@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig index 55b9e4e867ac..4e8b01e73245 100644 --- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig +++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig @@ -98,8 +98,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig index 1be38eb05783..20fde6374aad 100644 --- a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig +++ b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig @@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/86xx/sbc8641d_defconfig b/arch/powerpc/configs/86xx/sbc8641d_defconfig index a63009457323..74f714d85936 100644 --- a/arch/powerpc/configs/86xx/sbc8641d_defconfig +++ b/arch/powerpc/configs/86xx/sbc8641d_defconfig @@ -102,8 +102,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/adder875_defconfig b/arch/powerpc/configs/adder875_defconfig index 9f89d5c9c0be..a670cee255b9 100644 --- a/arch/powerpc/configs/adder875_defconfig +++ b/arch/powerpc/configs/adder875_defconfig @@ -92,8 +92,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig index b63cc38df6b1..851287e78fc3 100644 --- a/arch/powerpc/configs/amigaone_defconfig +++ b/arch/powerpc/configs/amigaone_defconfig @@ -87,8 +87,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig index 4ab6074db3cf..b429a655b541 100644 --- a/arch/powerpc/configs/c2k_defconfig +++ b/arch/powerpc/configs/c2k_defconfig @@ -102,8 +102,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index c6d2baa7aaeb..943371954317 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -83,8 +83,7 @@ CONFIG_CPUSETS=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUP_CPUACCT is not set # CONFIG_RESOURCE_COUNTERS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_PROC_PID_CPUSET=y # CONFIG_RELAY is not set CONFIG_NAMESPACES=y diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig index d2123779512a..6be6c09eba6d 100644 --- a/arch/powerpc/configs/celleb_defconfig +++ b/arch/powerpc/configs/celleb_defconfig @@ -78,8 +78,7 @@ CONFIG_LOG_BUF_SHIFT=15 # CONFIG_GROUP_SCHED is not set # CONFIG_USER_SCHED is not set # CONFIG_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig index 5094a65a4493..2fdab660fce3 100644 --- a/arch/powerpc/configs/chrp32_defconfig +++ b/arch/powerpc/configs/chrp32_defconfig @@ -77,8 +77,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/ep8248e_defconfig b/arch/powerpc/configs/ep8248e_defconfig index 81e904e9f392..6b708395a7c6 100644 --- a/arch/powerpc/configs/ep8248e_defconfig +++ b/arch/powerpc/configs/ep8248e_defconfig @@ -96,8 +96,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set diff --git a/arch/powerpc/configs/ep88xc_defconfig b/arch/powerpc/configs/ep88xc_defconfig index c5af46ef5f40..1cee889dd9ec 100644 --- a/arch/powerpc/configs/ep88xc_defconfig +++ b/arch/powerpc/configs/ep88xc_defconfig @@ -91,8 +91,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 826a65d3f002..57d3ffa3026a 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -82,8 +82,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig index 942e1193e9e4..1c2dbf07ac35 100644 --- a/arch/powerpc/configs/gamecube_defconfig +++ b/arch/powerpc/configs/gamecube_defconfig @@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig index a211a79959ca..a60d61bee48d 100644 --- a/arch/powerpc/configs/holly_defconfig +++ b/arch/powerpc/configs/holly_defconfig @@ -73,7 +73,6 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_FAIR_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index 76982c51a4c7..151c8e14f3ab 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig @@ -81,8 +81,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig index 588a2add393f..8ecacf74d3e5 100644 --- a/arch/powerpc/configs/linkstation_defconfig +++ b/arch/powerpc/configs/linkstation_defconfig @@ -97,8 +97,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 8b244003b9e1..dc50eec58e78 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -78,8 +78,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig index 0cbd56fe2e1e..b36ebb7e843e 100644 --- a/arch/powerpc/configs/mgcoge_defconfig +++ b/arch/powerpc/configs/mgcoge_defconfig @@ -96,8 +96,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/mgsuvd_defconfig b/arch/powerpc/configs/mgsuvd_defconfig index c1be26151021..0dd5015ea81d 100644 --- a/arch/powerpc/configs/mgsuvd_defconfig +++ b/arch/powerpc/configs/mgsuvd_defconfig @@ -90,8 +90,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/mpc512x_defconfig b/arch/powerpc/configs/mpc512x_defconfig index a04727295d46..aa2654e6edeb 100644 --- a/arch/powerpc/configs/mpc512x_defconfig +++ b/arch/powerpc/configs/mpc512x_defconfig @@ -97,8 +97,7 @@ CONFIG_RCU_FANOUT=32 CONFIG_LOG_BUF_SHIFT=16 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig index 7012ac0134f0..f875ec21c91c 100644 --- a/arch/powerpc/configs/mpc5200_defconfig +++ b/arch/powerpc/configs/mpc5200_defconfig @@ -97,8 +97,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig index 27c63ceeb45a..b1e88fe1d9fb 100644 --- a/arch/powerpc/configs/mpc7448_hpc2_defconfig +++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig @@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 20ba0cfff8ba..74a7216183e8 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig @@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=64 CONFIG_LOG_BUF_SHIFT=17 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index ea8870a34482..753bb7912e28 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -93,8 +93,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig index 35b60683cde5..afb4d1bb2ba9 100644 --- a/arch/powerpc/configs/ppc40x_defconfig +++ b/arch/powerpc/configs/ppc40x_defconfig @@ -99,8 +99,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig index 46f5c47e9f85..bd3d23fb4dd3 100644 --- a/arch/powerpc/configs/ppc44x_defconfig +++ b/arch/powerpc/configs/ppc44x_defconfig @@ -103,8 +103,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index dad617e2a88c..369f4e02c5dd 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -93,8 +93,7 @@ CONFIG_CPUSETS=y # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUP_CPUACCT is not set # CONFIG_RESOURCE_COUNTERS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_PROC_PID_CPUSET=y CONFIG_RELAY=y CONFIG_NAMESPACES=y diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 8195f1650cbf..403e82e2e83c 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig @@ -107,8 +107,7 @@ CONFIG_CPUSETS=y CONFIG_PROC_PID_CPUSET=y # CONFIG_CGROUP_CPUACCT is not set # CONFIG_RESOURCE_COUNTERS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/pq2fads_defconfig b/arch/powerpc/configs/pq2fads_defconfig index 68c175ea427a..12c8ee8dd12b 100644 --- a/arch/powerpc/configs/pq2fads_defconfig +++ b/arch/powerpc/configs/pq2fads_defconfig @@ -96,8 +96,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig index 93f4505b5ac2..a18f597c6e5f 100644 --- a/arch/powerpc/configs/prpmc2800_defconfig +++ b/arch/powerpc/configs/prpmc2800_defconfig @@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 16a14589bd40..16ae717d1958 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -92,8 +92,7 @@ CONFIG_CPUSETS=y # CONFIG_GROUP_SCHED is not set CONFIG_CGROUP_CPUACCT=y # CONFIG_RESOURCE_COUNTERS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_PROC_PID_CPUSET=y CONFIG_RELAY=y CONFIG_NAMESPACES=y diff --git a/arch/powerpc/configs/storcenter_defconfig b/arch/powerpc/configs/storcenter_defconfig index b1625801526e..01be0e207f40 100644 --- a/arch/powerpc/configs/storcenter_defconfig +++ b/arch/powerpc/configs/storcenter_defconfig @@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig index c386828c639a..ee054f8118be 100644 --- a/arch/powerpc/configs/wii_defconfig +++ b/arch/powerpc/configs/wii_defconfig @@ -102,8 +102,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index e054baef1845..ecba37a91749 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -358,7 +358,6 @@ extern void exc_lvl_ctx_init(void); #define exc_lvl_ctx_init() #endif -#ifdef CONFIG_IRQSTACKS /* * Per-cpu stacks for handling hard and soft interrupts. */ @@ -369,11 +368,6 @@ extern void irq_ctx_init(void); extern void call_do_softirq(struct thread_info *tp); extern int call_handle_irq(int irq, void *p1, struct thread_info *tp, void *func); -#else -#define irq_ctx_init() - -#endif /* CONFIG_IRQSTACKS */ - extern void do_IRQ(struct pt_regs *regs); #endif /* _ASM_IRQ_H */ diff --git a/arch/powerpc/include/asm/kdump.h b/arch/powerpc/include/asm/kdump.h index 5ebfe5d3c61f..6857af58b02e 100644 --- a/arch/powerpc/include/asm/kdump.h +++ b/arch/powerpc/include/asm/kdump.h @@ -3,8 +3,17 @@ #include <asm/page.h> -/* Kdump kernel runs at 32 MB, change at your peril. */ +/* + * If CONFIG_RELOCATABLE is enabled we can place the kdump kernel anywhere. + * To keep enough space in the RMO for the first stage kernel on 64bit, we + * place it at 64MB. If CONFIG_RELOCATABLE is not enabled we must place + * the second stage at 32MB. + */ +#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC64) +#define KDUMP_KERNELBASE 0x4000000 +#else #define KDUMP_KERNELBASE 0x2000000 +#endif /* How many bytes to reserve at zero for kdump. The reserve limit should * be greater or equal to the trampoline's end address. diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 30817d9b20cb..3333bbdd23ef 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -317,7 +317,6 @@ void fixup_irqs(const struct cpumask *map) } #endif -#ifdef CONFIG_IRQSTACKS static inline void handle_one_irq(unsigned int irq) { struct thread_info *curtp, *irqtp; @@ -358,12 +357,6 @@ static inline void handle_one_irq(unsigned int irq) if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } -#else -static inline void handle_one_irq(unsigned int irq) -{ - generic_handle_irq(irq); -} -#endif static inline void check_stack_overflow(void) { @@ -455,7 +448,6 @@ void exc_lvl_ctx_init(void) } #endif -#ifdef CONFIG_IRQSTACKS struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; @@ -492,10 +484,6 @@ static inline void do_softirq_onstack(void) irqtp->task = NULL; } -#else -#define do_softirq_onstack() __do_softirq() -#endif /* CONFIG_IRQSTACKS */ - void do_softirq(void) { unsigned long flags; diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 26f9900f773c..ed31a29c4ff7 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -182,28 +182,12 @@ static void kexec_prepare_cpus_wait(int wait_state) my_cpu = get_cpu(); /* Make sure each CPU has atleast made it to the state we need */ - for (i=0; i < NR_CPUS; i++) { + for_each_online_cpu(i) { if (i == my_cpu) continue; while (paca[i].kexec_state < wait_state) { barrier(); - if (!cpu_possible(i)) { - printk("kexec: cpu %d hw_cpu_id %d is not" - " possible, ignoring\n", - i, paca[i].hw_cpu_id); - break; - } - if (!cpu_online(i)) { - /* Fixme: this can be spinning in - * pSeries_secondary_wait with a paca - * waiting for it to go online. - */ - printk("kexec: cpu %d hw_cpu_id %d is not" - " online, ignoring\n", - i, paca[i].hw_cpu_id); - break; - } if (i != notified) { printk( "kexec: waiting for cpu %d (physical" " %d) to enter %i state\n", diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index dc66d52dcff5..6bbd7a604d24 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -33,7 +33,6 @@ .text -#ifdef CONFIG_IRQSTACKS _GLOBAL(call_do_softirq) mflr r0 stw r0,4(r1) @@ -56,7 +55,6 @@ _GLOBAL(call_handle_irq) lwz r0,4(r1) mtlr r0 blr -#endif /* CONFIG_IRQSTACKS */ /* * This returns the high 64 bits of the product of two 64-bit numbers. diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index a2b18dffa03e..e5144906a56d 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -28,7 +28,6 @@ .text -#ifdef CONFIG_IRQSTACKS _GLOBAL(call_do_softirq) mflr r0 std r0,16(r1) @@ -52,7 +51,6 @@ _GLOBAL(call_handle_irq) ld r0,16(r1) mtlr r0 blr -#endif /* CONFIG_IRQSTACKS */ .section ".toc","aw" PPC64_CACHES: diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 6646005dffb1..5b38f6ae2b29 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1309,6 +1309,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) printk(KERN_WARNING "PCI: Cannot allocate resource region " "%d of PCI bridge %d, will remap\n", i, bus->number); clear_resource: + res->start = res->end = 0; res->flags = 0; } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 9d255b4f0a0e..773424df828a 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1005,7 +1005,6 @@ out: return error; } -#ifdef CONFIG_IRQSTACKS static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, unsigned long nbytes) { @@ -1030,10 +1029,6 @@ static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, return 0; } -#else -#define valid_irq_stack(sp, p, nb) 0 -#endif /* CONFIG_IRQSTACKS */ - int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index bfc2abafac44..67a84d8f118d 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -94,12 +94,8 @@ struct flash_block_list { struct flash_block_list *next; struct flash_block blocks[FLASH_BLOCKS_PER_NODE]; }; -struct flash_block_list_header { /* just the header of flash_block_list */ - unsigned long num_blocks; - struct flash_block_list *next; -}; -static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; +static struct flash_block_list *rtas_firmware_flash_list; /* Use slab cache to guarantee 4k alignment */ static struct kmem_cache *flash_block_cache = NULL; @@ -108,13 +104,14 @@ static struct kmem_cache *flash_block_cache = NULL; /* Local copy of the flash block list. * We only allow one open of the flash proc file and create this - * list as we go. This list will be put in the - * rtas_firmware_flash_list var once it is fully read. + * list as we go. The rtas_firmware_flash_list varable will be + * set once the data is fully read. * * For convenience as we build the list we use virtual addrs, * we do not fill in the version number, and the length field * is treated as the number of entries currently in the block - * (i.e. not a byte count). This is all fixed on release. + * (i.e. not a byte count). This is all fixed when calling + * the flash routine. */ /* Status int must be first member of struct */ @@ -201,16 +198,16 @@ static int rtas_flash_release(struct inode *inode, struct file *file) if (uf->flist) { /* File was opened in write mode for a new flash attempt */ /* Clear saved list */ - if (rtas_firmware_flash_list.next) { - free_flash_list(rtas_firmware_flash_list.next); - rtas_firmware_flash_list.next = NULL; + if (rtas_firmware_flash_list) { + free_flash_list(rtas_firmware_flash_list); + rtas_firmware_flash_list = NULL; } if (uf->status != FLASH_AUTH) uf->status = flash_list_valid(uf->flist); if (uf->status == FLASH_IMG_READY) - rtas_firmware_flash_list.next = uf->flist; + rtas_firmware_flash_list = uf->flist; else free_flash_list(uf->flist); @@ -593,7 +590,7 @@ static void rtas_flash_firmware(int reboot_type) unsigned long rtas_block_list; int i, status, update_token; - if (rtas_firmware_flash_list.next == NULL) + if (rtas_firmware_flash_list == NULL) return; /* nothing to do */ if (reboot_type != SYS_RESTART) { @@ -610,20 +607,25 @@ static void rtas_flash_firmware(int reboot_type) return; } - /* NOTE: the "first" block list is a global var with no data - * blocks in the kernel data segment. We do this because - * we want to ensure this block_list addr is under 4GB. + /* + * NOTE: the "first" block must be under 4GB, so we create + * an entry with no data blocks in the reserved buffer in + * the kernel data segment. */ - rtas_firmware_flash_list.num_blocks = 0; - flist = (struct flash_block_list *)&rtas_firmware_flash_list; + spin_lock(&rtas_data_buf_lock); + flist = (struct flash_block_list *)&rtas_data_buf[0]; + flist->num_blocks = 0; + flist->next = rtas_firmware_flash_list; rtas_block_list = virt_to_abs(flist); if (rtas_block_list >= 4UL*1024*1024*1024) { printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); + spin_unlock(&rtas_data_buf_lock); return; } printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); /* Update the block_list in place. */ + rtas_firmware_flash_list = NULL; /* too hard to backout on error */ image_size = 0; for (f = flist; f; f = next) { /* Translate data addrs to absolute */ @@ -664,6 +666,7 @@ static void rtas_flash_firmware(int reboot_type) printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); break; } + spin_unlock(&rtas_data_buf_lock); } static void remove_flash_pde(struct proc_dir_entry *dp) diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 8f58986c2ad9..7d84b210f168 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -241,7 +241,6 @@ int __init ppc_init(void) arch_initcall(ppc_init); -#ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { unsigned int i; @@ -255,9 +254,6 @@ static void __init irqstack_early_init(void) __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); } } -#else -#define irqstack_early_init() -#endif #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) static void __init exc_lvl_early_init(void) diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f3fb5a79de52..643dcac40fcb 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -432,7 +432,6 @@ static u64 slb0_limit(void) return 1UL << SID_SHIFT; } -#ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { u64 limit = slb0_limit(); @@ -451,9 +450,6 @@ static void __init irqstack_early_init(void) THREAD_SIZE, limit)); } } -#else -#define irqstack_early_init() -#endif #ifdef CONFIG_PPC_BOOK3E static void __init exc_lvl_early_init(void) diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index bc2b4004eb26..e8a00b0c4449 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c @@ -164,7 +164,7 @@ static int __init kvmppc_e500_init(void) return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE); } -static void __init kvmppc_e500_exit(void) +static void __exit kvmppc_e500_exit(void) { kvmppc_booke_exit(); } diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 9fc02dc72ce9..34347b2e7e31 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -115,11 +115,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *ptepage; -#ifdef CONFIG_HIGHPTE - gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO; -#else gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO; -#endif ptepage = alloc_pages(flags, 0); if (!ptepage) diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index 2c9e52267292..7fd90d02d8c6 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -1077,7 +1077,7 @@ static int calculate_lfsr(int n) index = ENTRIES-1; /* make sure index is valid */ - if ((index > ENTRIES) || (index < 0)) + if ((index >= ENTRIES) || (index < 0)) index = ENTRIES-1; return initial_lfsr[index]; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c index a55b0b6813ed..76722532bd95 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -64,10 +64,19 @@ int mpc52xx_pm_prepare(void) { .type = "builtin", .compatible = "mpc5200", }, /* efika */ {} }; + struct resource res; /* map the whole register space */ np = of_find_matching_node(NULL, immr_ids); - mbar = of_iomap(np, 0); + + if (of_address_to_resource(np, 0, &res)) { + pr_err("mpc52xx_pm_prepare(): could not get IMMR address\n"); + of_node_put(np); + return -ENOSYS; + } + + mbar = ioremap(res.start, 0xc000); /* we should map whole region including SRAM */ + of_node_put(np); if (!mbar) { pr_err("mpc52xx_pm_prepare(): could not map registers\n"); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 2102487612a4..20b73c025a45 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1666,7 +1666,7 @@ static int mpic_resume(struct sys_device *dev) mpic->save_data[i].dest); #ifdef CONFIG_MPIC_U3_HT_IRQS - { + if (mpic->fixups) { struct mpic_irq_fixup *fixup = &mpic->fixups[i]; if (fixup->base) { diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 55c80ffd42b9..92f1cb745d69 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c @@ -181,7 +181,7 @@ static int __init appldata_os_init(void) goto out; } - appldata_os_data = kzalloc(max_size, GFP_DMA); + appldata_os_data = kzalloc(max_size, GFP_KERNEL | GFP_DMA); if (appldata_os_data == NULL) { rc = -ENOMEM; goto out; diff --git a/arch/s390/defconfig b/arch/s390/defconfig index bcd6884985ad..253f158db668 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.34-rc3 -# Fri Apr 9 09:57:10 2010 +# Linux kernel version: 2.6.35-rc1 +# Fri Jun 4 11:32:40 2010 # CONFIG_SCHED_MC=y CONFIG_MMU=y @@ -35,11 +35,13 @@ CONFIG_CONSTRUCTORS=y CONFIG_EXPERIMENTAL=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set @@ -77,6 +79,7 @@ CONFIG_CGROUP_NS=y # CONFIG_CGROUP_CPUACCT is not set # CONFIG_RESOURCE_COUNTERS is not set # CONFIG_CGROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -157,7 +160,6 @@ CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y CONFIG_BLK_DEV_BSG=y # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_CGROUP is not set CONFIG_BLOCK_COMPAT=y # @@ -166,7 +168,6 @@ CONFIG_BLOCK_COMPAT=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y -# CONFIG_CFQ_GROUP_IOSCHED is not set CONFIG_DEFAULT_DEADLINE=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set @@ -247,7 +248,6 @@ CONFIG_64BIT=y CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y -# CONFIG_SCHED_BOOK is not set CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_AUDIT_ARCH=y @@ -320,7 +320,6 @@ CONFIG_COMPAT_BINFMT_ELF=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=m CONFIG_FORCE_MAX_ZONEORDER=9 -# CONFIG_PROCESS_DEBUG is not set CONFIG_PFAULT=y # CONFIG_SHARED_KERNEL is not set # CONFIG_CMM is not set @@ -457,6 +456,7 @@ CONFIG_NF_CONNTRACK=m # CONFIG_IP6_NF_IPTABLES is not set # CONFIG_IP_DCCP is not set CONFIG_IP_SCTP=m +# CONFIG_NET_SCTPPROBE is not set # CONFIG_SCTP_DBG_MSG is not set # CONFIG_SCTP_DBG_OBJCNT is not set # CONFIG_SCTP_HMAC_NONE is not set @@ -465,6 +465,7 @@ CONFIG_SCTP_HMAC_MD5=y # CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set +# CONFIG_L2TP is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -525,6 +526,7 @@ CONFIG_NET_ACT_NAT=m # CONFIG_NET_CLS_IND is not set CONFIG_NET_SCH_FIFO=y # CONFIG_DCB is not set +CONFIG_RPS=y # # Network testing @@ -546,6 +548,7 @@ CONFIG_CAN_VCAN=m # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set +# CONFIG_CAIF is not set # CONFIG_PCMCIA is not set CONFIG_CCW=y @@ -728,6 +731,7 @@ CONFIG_VIRTIO_NET=m # Character devices # CONFIG_DEVKMEM=y +# CONFIG_N_GSM is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -775,6 +779,7 @@ CONFIG_S390_TAPE_34XX=m # CONFIG_MONREADER is not set CONFIG_MONWRITER=m CONFIG_S390_VMUR=m +# CONFIG_RAMOOPS is not set # # PPS support @@ -788,10 +793,6 @@ CONFIG_S390_VMUR=m # CONFIG_NEW_LEDS is not set CONFIG_ACCESSIBILITY=y # CONFIG_AUXDISPLAY is not set - -# -# TI VLYNQ -# # CONFIG_STAGING is not set # @@ -976,6 +977,7 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y # CONFIG_LKDTM is not set +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y @@ -1010,6 +1012,7 @@ CONFIG_BRANCH_PROFILE_NONE=y CONFIG_KPROBE_EVENT=y # CONFIG_RING_BUFFER_BENCHMARK is not set # CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set CONFIG_SAMPLES=y # CONFIG_SAMPLE_TRACEPOINTS is not set # CONFIG_SAMPLE_TRACE_EVENTS is not set diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 639380a0c45c..22cfd634c355 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -55,8 +55,10 @@ void *module_alloc(unsigned long size) /* Free memory returned from module_alloc */ void module_free(struct module *mod, void *module_region) { - vfree(mod->arch.syminfo); - mod->arch.syminfo = NULL; + if (mod) { + vfree(mod->arch.syminfo); + mod->arch.syminfo = NULL; + } vfree(module_region); } diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 8093e6f47f49..ae3705816878 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -761,7 +761,7 @@ static int __init kvm_s390_init(void) * to hold the maximum amount of facilites. On the other hand, we * only set facilities that are known to work in KVM. */ - facilities = (unsigned long long *) get_zeroed_page(GFP_DMA); + facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); if (!facilities) { kvm_exit(); return -ENOMEM; diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index eff3c5989b46..702276f5e2fa 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -113,7 +113,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) { struct kvm_s390_interrupt_info *inti; - inti = kzalloc(sizeof(*inti), GFP_KERNEL); + inti = kzalloc(sizeof(*inti), GFP_ATOMIC); if (!inti) return -ENOMEM; inti->type = KVM_S390_SIGP_STOP; diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 6409fd57eb04..3cc95dd0a3a6 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -105,7 +105,7 @@ static int dcss_set_subcodes(void) { #ifdef CONFIG_64BIT - char *name = kmalloc(8 * sizeof(char), GFP_DMA); + char *name = kmalloc(8 * sizeof(char), GFP_KERNEL | GFP_DMA); unsigned long rx, ry; int rc; @@ -252,12 +252,13 @@ dcss_diag_translate_rc (int vm_rc) { static int query_segment_type (struct dcss_segment *seg) { - struct qin64 *qin = kmalloc (sizeof(struct qin64), GFP_DMA); - struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA); - - int diag_cc, rc, i; unsigned long dummy, vmrc; + int diag_cc, rc, i; + struct qout64 *qout; + struct qin64 *qin; + qin = kmalloc(sizeof(*qin), GFP_KERNEL | GFP_DMA); + qout = kmalloc(sizeof(*qout), GFP_KERNEL | GFP_DMA); if ((qin == NULL) || (qout == NULL)) { rc = -ENOMEM; goto out_free; @@ -286,7 +287,7 @@ query_segment_type (struct dcss_segment *seg) copy data for the new format. */ if (segext_scode == DCSS_SEGEXT) { struct qout64_old *qout_old; - qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA); + qout_old = kzalloc(sizeof(*qout_old), GFP_KERNEL | GFP_DMA); if (qout_old == NULL) { rc = -ENOMEM; goto out_free; @@ -407,11 +408,11 @@ segment_overlaps_others (struct dcss_segment *seg) static int __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end) { - struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), - GFP_DMA); - int rc, diag_cc; unsigned long start_addr, end_addr, dummy; + struct dcss_segment *seg; + int rc, diag_cc; + seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA); if (seg == NULL) { rc = -ENOMEM; goto out; diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index be1d114d3a43..1d7b495a7db4 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -25,7 +25,6 @@ #include <linux/spi/spi.h> #include <linux/spi/sh_msiof.h> #include <linux/spi/mmc_spi.h> -#include <linux/mmc/host.h> #include <linux/input.h> #include <linux/input/sh_keysc.h> #include <video/sh_mobile_lcdc.h> diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 953af139e230..1e9598d2bbf4 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -139,8 +139,6 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev, for (i = 0; i < PCI_NUM_RESOURCES; i++) { if (!dev->resource[i].start) continue; - if (dev->resource[i].flags & IORESOURCE_PCI_FIXED) - continue; if (dev->resource[i].flags & IORESOURCE_IO) offset = hose->io_offset; else if (dev->resource[i].flags & IORESOURCE_MEM) diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index 18623ba751b3..6379091a1647 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -770,7 +770,7 @@ static void __init pmb_resize(void) spin_unlock_irqrestore(&pmbe->lock, flags); } - read_lock(&pmb_rwlock); + read_unlock(&pmb_rwlock); } #endif diff --git a/arch/um/include/asm/arch_hweight.h b/arch/um/include/asm/arch_hweight.h new file mode 100644 index 000000000000..c656cf443f4a --- /dev/null +++ b/arch/um/include/asm/arch_hweight.h @@ -0,0 +1,6 @@ +#ifndef _ASM_UM_HWEIGHT_H +#define _ASM_UM_HWEIGHT_H + +#include <asm-generic/bitops/arch_hweight.h> + +#endif diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 93a11d7edfa0..e696144d2be3 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -10,6 +10,7 @@ #include <errno.h> #include <fcntl.h> #include <string.h> +#include <sys/stat.h> #include <sys/mman.h> #include <sys/param.h> #include "init.h" diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c index ed7aeff786b2..45bc9402aa49 100644 --- a/arch/x86/boot/video-vga.c +++ b/arch/x86/boot/video-vga.c @@ -41,13 +41,12 @@ static __videocard video_vga; static u8 vga_set_basic_mode(void) { struct biosregs ireg, oreg; - u16 ax; u8 mode; initregs(&ireg); /* Query current mode */ - ax = 0x0f00; + ireg.ax = 0x0f00; intcall(0x10, &ireg, &oreg); mode = oreg.al; diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 63cb4096c3dc..9cb2edb87c2f 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -183,7 +183,7 @@ struct mp_ioapic_gsi{ u32 gsi_end; }; extern struct mp_ioapic_gsi mp_gsi_routing[]; -extern u32 gsi_end; +extern u32 gsi_top; int mp_find_ioapic(u32 gsi); int mp_find_ioapic_pin(int ioapic, u32 gsi); void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); @@ -197,7 +197,7 @@ static const int timer_through_8259 = 0; static inline void ioapic_init_mappings(void) { } static inline void ioapic_insert_resources(void) { } static inline void probe_nr_irqs_gsi(void) { } -#define gsi_end (NR_IRQS_LEGACY - 1) +#define gsi_top (NR_IRQS_LEGACY) static inline int mp_find_ioapic(u32 gsi) { return 0; } struct io_apic_irq_attr; diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index b49d8ca228f6..8c7ae4318629 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -110,6 +110,7 @@ #define MSR_AMD64_PATCH_LOADER 0xc0010020 #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 #define MSR_AMD64_OSVW_STATUS 0xc0010141 +#define MSR_AMD64_DC_CFG 0xc0011022 #define MSR_AMD64_IBSFETCHCTL 0xc0011030 #define MSR_AMD64_IBSFETCHLINAD 0xc0011031 #define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032 diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 0797e748d280..cd28f9ad910d 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -77,6 +77,7 @@ do { \ if (0) { \ pto_T__ pto_tmp__; \ pto_tmp__ = (val); \ + (void)pto_tmp__; \ } \ switch (sizeof(var)) { \ case 1: \ @@ -115,6 +116,7 @@ do { \ if (0) { \ pao_T__ pao_tmp__; \ pao_tmp__ = (val); \ + (void)pao_tmp__; \ } \ switch (sizeof(var)) { \ case 1: \ diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h index 5e67c1532314..ed5903be26fe 100644 --- a/arch/x86/include/asm/pgtable_32_types.h +++ b/arch/x86/include/asm/pgtable_32_types.h @@ -26,7 +26,7 @@ */ #define VMALLOC_OFFSET (8 * 1024 * 1024) -#ifndef __ASSEMBLER__ +#ifndef __ASSEMBLY__ extern bool __vmalloc_start_set; /* set once high_memory is set */ #endif diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h index 48dcfa62ea07..fd921c3a6841 100644 --- a/arch/x86/include/asm/suspend_32.h +++ b/arch/x86/include/asm/suspend_32.h @@ -15,6 +15,8 @@ static inline int arch_prepare_suspend(void) { return 0; } struct saved_context { u16 es, fs, gs, ss; unsigned long cr0, cr2, cr3, cr4; + u64 misc_enable; + bool misc_enable_saved; struct desc_ptr gdt; struct desc_ptr idt; u16 ldt; diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h index 06284f42b759..8d942afae681 100644 --- a/arch/x86/include/asm/suspend_64.h +++ b/arch/x86/include/asm/suspend_64.h @@ -27,6 +27,8 @@ struct saved_context { u16 ds, es, fs, gs, ss; unsigned long gs_base, gs_kernel_base, fs_base; unsigned long cr0, cr2, cr3, cr4, cr8; + u64 misc_enable; + bool misc_enable_saved; unsigned long efer; u16 gdt_pad; u16 gdt_limit; diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index b8fe48ee2ed9..e7f4d33c55ed 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -451,7 +451,7 @@ void stop_this_cpu(void *dummy); * * (Could use an alternative three way for this if there was one.) */ -static inline void rdtsc_barrier(void) +static __always_inline void rdtsc_barrier(void) { alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC); alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC); diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 60cc4058ed5f..c05872aa3ce0 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -118,7 +118,7 @@ static unsigned int gsi_to_irq(unsigned int gsi) if (gsi >= NR_IRQS_LEGACY) irq = gsi; else - irq = gsi_end + 1 + gsi; + irq = gsi_top + gsi; return irq; } @@ -129,10 +129,10 @@ static u32 irq_to_gsi(int irq) if (irq < NR_IRQS_LEGACY) gsi = isa_irq_to_gsi[irq]; - else if (irq <= gsi_end) + else if (irq < gsi_top) gsi = irq; - else if (irq <= (gsi_end + NR_IRQS_LEGACY)) - gsi = irq - gsi_end; + else if (irq < (gsi_top + NR_IRQS_LEGACY)) + gsi = irq - gsi_top; else gsi = 0xffffffff; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 33f3563a2a52..e41ed24ab26d 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -89,8 +89,8 @@ int nr_ioapics; /* IO APIC gsi routing info */ struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS]; -/* The last gsi number used */ -u32 gsi_end; +/* The one past the highest gsi number used */ +u32 gsi_top; /* MP IRQ source entries */ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; @@ -1035,7 +1035,7 @@ static int pin_2_irq(int idx, int apic, int pin) if (gsi >= NR_IRQS_LEGACY) irq = gsi; else - irq = gsi_end + 1 + gsi; + irq = gsi_top + gsi; } #ifdef CONFIG_X86_32 @@ -3853,7 +3853,7 @@ void __init probe_nr_irqs_gsi(void) { int nr; - nr = gsi_end + 1 + NR_IRQS_LEGACY; + nr = gsi_top + NR_IRQS_LEGACY; if (nr > nr_irqs_gsi) nr_irqs_gsi = nr; @@ -4294,8 +4294,8 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) */ nr_ioapic_registers[idx] = entries; - if (mp_gsi_routing[idx].gsi_end > gsi_end) - gsi_end = mp_gsi_routing[idx].gsi_end; + if (mp_gsi_routing[idx].gsi_end >= gsi_top) + gsi_top = mp_gsi_routing[idx].gsi_end + 1; printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].apicid, diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 611df11ba15e..c2897b7b4a3b 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -102,8 +102,8 @@ static const u64 amd_perfmon_event_map[] = [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, - [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, + [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, }; static u64 amd_pmu_event_map(int hw_event) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index fdbc652d3feb..214ac860ebe0 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -72,6 +72,7 @@ static struct event_constraint intel_westmere_event_constraints[] = INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ + INTEL_EVENT_CONSTRAINT(0xb3, 0x1), /* SNOOPQ_REQUEST_OUTSTANDING */ EVENT_CONSTRAINT_END }; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 7bca3c6a02fb..0d6fc71bedb1 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void) struct e820entry *ei = &e820.map[i]; if (ei->type == E820_NVS) - hibernate_nvs_register(ei->addr, ei->size); + suspend_nvs_register(ei->addr, ei->size); } return 0; diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 5ae5d2426edf..d86dbf7e54be 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -123,7 +123,7 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m) printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n", m->apicid, m->apicver, m->apicaddr); - mp_register_ioapic(m->apicid, m->apicaddr, gsi_end + 1); + mp_register_ioapic(m->apicid, m->apicaddr, gsi_top); } static void print_MP_intsrc_info(struct mpc_intsrc *m) diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index fb99f7edb341..0b96b5589f08 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -103,11 +103,16 @@ int use_calgary __read_mostly = 0; #define PMR_SOFTSTOPFAULT 0x40000000 #define PMR_HARDSTOP 0x20000000 -#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ -#define MAX_NUM_CHASSIS 8 /* max number of chassis */ -/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */ -#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) -#define PHBS_PER_CALGARY 4 +/* + * The maximum PHB bus number. + * x3950M2 (rare): 8 chassis, 48 PHBs per chassis = 384 + * x3950M2: 4 chassis, 48 PHBs per chassis = 192 + * x3950 (PCIE): 8 chassis, 32 PHBs per chassis = 256 + * x3950 (PCIX): 8 chassis, 16 PHBs per chassis = 128 + */ +#define MAX_PHB_BUS_NUM 384 + +#define PHBS_PER_CALGARY 4 /* register offsets in Calgary's internal register space */ static const unsigned long tar_offsets[] = { diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 8e1aac86b50c..e3af342fe83a 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -228,6 +228,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"), }, }, + { /* Handle problems with rebooting on Dell T7400's */ + .callback = set_bios_reboot, + .ident = "Dell Precision T7400", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"), + }, + }, { /* Handle problems with rebooting on HP laptops */ .callback = set_bios_reboot, .ident = "HP Compaq Laptop", diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c index 7ded57896c0a..cb22acf3ed09 100644 --- a/arch/x86/kernel/sfi.c +++ b/arch/x86/kernel/sfi.c @@ -93,7 +93,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table) pentry = (struct sfi_apic_table_entry *)sb->pentry; for (i = 0; i < num; i++) { - mp_register_ioapic(i, pentry->phys_addr, gsi_end + 1); + mp_register_ioapic(i, pentry->phys_addr, gsi_top); pentry++; } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 142d70c74b02..725ef4d17cd5 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -526,6 +526,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) { struct task_struct *tsk = current; + int user_icebp = 0; unsigned long dr6; int si_code; @@ -534,6 +535,14 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) /* Filter out all the reserved bits which are preset to 1 */ dr6 &= ~DR6_RESERVED; + /* + * If dr6 has no reason to give us about the origin of this trap, + * then it's very likely the result of an icebp/int01 trap. + * User wants a sigtrap for that. + */ + if (!dr6 && user_mode(regs)) + user_icebp = 1; + /* Catch kmemcheck conditions first of all! */ if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) return; @@ -575,7 +584,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) regs->flags &= ~X86_EFLAGS_TF; } si_code = get_si_code(tsk->thread.debugreg6); - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) + if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) send_sigtrap(tsk, regs, error_code, si_code); preempt_conditional_cli(regs); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 81563e76e28f..a6f695d76928 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1815,6 +1815,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, spte |= PT_WRITABLE_MASK; + if (!tdp_enabled && !(pte_access & ACC_WRITE_MASK)) + spte &= ~PT_USER_MASK; + /* * Optimization: for pte sync, if spte was writable the hash * lookup is unnecessary (and expensive). Write protection @@ -1870,6 +1873,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, child = page_header(pte & PT64_BASE_ADDR_MASK); mmu_page_remove_parent_pte(child, sptep); + __set_spte(sptep, shadow_trap_nonpresent_pte); + kvm_flush_remote_tlbs(vcpu->kvm); } else if (pfn != spte_to_pfn(*sptep)) { pgprintk("hfn old %lx new %lx\n", spte_to_pfn(*sptep), pfn); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 96dc232bfc56..ce438e0fdd26 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -28,6 +28,7 @@ #include <linux/ftrace_event.h> #include <linux/slab.h> +#include <asm/tlbflush.h> #include <asm/desc.h> #include <asm/virtext.h> @@ -56,6 +57,8 @@ MODULE_LICENSE("GPL"); #define DEBUGCTL_RESERVED_BITS (~(0x3fULL)) +static bool erratum_383_found __read_mostly; + static const u32 host_save_user_msrs[] = { #ifdef CONFIG_X86_64 MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE, @@ -374,6 +377,31 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, svm->vmcb->control.event_inj_err = error_code; } +static void svm_init_erratum_383(void) +{ + u32 low, high; + int err; + u64 val; + + /* Only Fam10h is affected */ + if (boot_cpu_data.x86 != 0x10) + return; + + /* Use _safe variants to not break nested virtualization */ + val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err); + if (err) + return; + + val |= (1ULL << 47); + + low = lower_32_bits(val); + high = upper_32_bits(val); + + native_write_msr_safe(MSR_AMD64_DC_CFG, low, high); + + erratum_383_found = true; +} + static int has_svm(void) { const char *msg; @@ -429,6 +457,8 @@ static int svm_hardware_enable(void *garbage) wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT); + svm_init_erratum_383(); + return 0; } @@ -1410,8 +1440,59 @@ static int nm_interception(struct vcpu_svm *svm) return 1; } -static int mc_interception(struct vcpu_svm *svm) +static bool is_erratum_383(void) { + int err, i; + u64 value; + + if (!erratum_383_found) + return false; + + value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err); + if (err) + return false; + + /* Bit 62 may or may not be set for this mce */ + value &= ~(1ULL << 62); + + if (value != 0xb600000000010015ULL) + return false; + + /* Clear MCi_STATUS registers */ + for (i = 0; i < 6; ++i) + native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0); + + value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err); + if (!err) { + u32 low, high; + + value &= ~(1ULL << 2); + low = lower_32_bits(value); + high = upper_32_bits(value); + + native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high); + } + + /* Flush tlb to evict multi-match entries */ + __flush_tlb_all(); + + return true; +} + +static void svm_handle_mce(struct vcpu_svm *svm) +{ + if (is_erratum_383()) { + /* + * Erratum 383 triggered. Guest state is corrupt so kill the + * guest. + */ + pr_err("KVM: Guest triggered AMD Erratum 383\n"); + + set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests); + + return; + } + /* * On an #MC intercept the MCE handler is not called automatically in * the host. So do it by hand here. @@ -1420,6 +1501,11 @@ static int mc_interception(struct vcpu_svm *svm) "int $0x12\n"); /* not sure if we ever come back to this point */ + return; +} + +static int mc_interception(struct vcpu_svm *svm) +{ return 1; } @@ -3088,6 +3174,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR); vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR); } + + /* + * We need to handle MC intercepts here before the vcpu has a chance to + * change the physical cpu + */ + if (unlikely(svm->vmcb->control.exit_code == + SVM_EXIT_EXCP_BASE + MC_VECTOR)) + svm_handle_mce(svm); } #undef R diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index acc15b23b743..64121a18b8cb 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -302,7 +302,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, return -EINVAL; } - new = kmalloc(sizeof(struct memtype), GFP_KERNEL); + new = kzalloc(sizeof(struct memtype), GFP_KERNEL); if (!new) return -ENOMEM; diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c index f537087bb740..f20eeec85a86 100644 --- a/arch/x86/mm/pat_rbtree.c +++ b/arch/x86/mm/pat_rbtree.c @@ -226,6 +226,7 @@ int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type) if (ret_type) new->type = *ret_type; + new->subtree_max_end = new->end; memtype_rb_insert(&memtype_rbroot, new); } return err; diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 97da2ba9344b..6fdb3ec30c31 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -96,6 +96,7 @@ EXPORT_SYMBOL(pcibios_align_resource); * the fact the PCI specs explicitly allow address decoders to be * shared between expansion ROMs and other resource regions, it's * at least dangerous) + * - bad resource sizes or overlaps with other regions * * Our solution: * (1) Allocate resources for all buses behind PCI-to-PCI bridges. @@ -136,6 +137,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) * child resource allocations in this * range. */ + r->start = r->end = 0; r->flags = 0; } } diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 0a979f3e5b8a..1290ba54b350 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -105,6 +105,8 @@ static void __save_processor_state(struct saved_context *ctxt) ctxt->cr4 = read_cr4(); ctxt->cr8 = read_cr8(); #endif + ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE, + &ctxt->misc_enable); } /* Needed by apm.c */ @@ -152,6 +154,8 @@ static void fix_processor_context(void) */ static void __restore_processor_state(struct saved_context *ctxt) { + if (ctxt->misc_enable_saved) + wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable); /* * control registers */ diff --git a/block/blk-core.c b/block/blk-core.c index f84cce42fc58..f0640d7f800f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1149,13 +1149,10 @@ void init_request_from_bio(struct request *req, struct bio *bio) else req->cmd_flags |= bio->bi_rw & REQ_FAILFAST_MASK; - if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) { + if (bio_rw_flagged(bio, BIO_RW_DISCARD)) req->cmd_flags |= REQ_DISCARD; - if (bio_rw_flagged(bio, BIO_RW_BARRIER)) - req->cmd_flags |= REQ_SOFTBARRIER; - } else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) + if (bio_rw_flagged(bio, BIO_RW_BARRIER)) req->cmd_flags |= REQ_HARDBARRIER; - if (bio_rw_flagged(bio, BIO_RW_SYNCIO)) req->cmd_flags |= REQ_RW_SYNC; if (bio_rw_flagged(bio, BIO_RW_META)) @@ -1586,7 +1583,7 @@ void submit_bio(int rw, struct bio *bio) * If it's a regular read/write or a barrier with data attached, * go through the normal accounting stuff before submission. */ - if (bio_has_data(bio)) { + if (bio_has_data(bio) && !(rw & (1 << BIO_RW_DISCARD))) { if (rw & WRITE) { count_vm_events(PGPGOUT, count); } else { diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5ff4f4850e71..7982b830db58 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -14,7 +14,7 @@ #include <linux/rbtree.h> #include <linux/ioprio.h> #include <linux/blktrace_api.h> -#include "blk-cgroup.h" +#include "cfq.h" /* * tunables @@ -879,7 +879,7 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg) if (!RB_EMPTY_NODE(&cfqg->rb_node)) cfq_rb_erase(&cfqg->rb_node, st); cfqg->saved_workload_slice = 0; - blkiocg_update_dequeue_stats(&cfqg->blkg, 1); + cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1); } static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq) @@ -939,8 +939,8 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, st->min_vdisktime); - blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); - blkiocg_set_start_empty_time(&cfqg->blkg); + cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); + cfq_blkiocg_set_start_empty_time(&cfqg->blkg); } #ifdef CONFIG_CFQ_GROUP_IOSCHED @@ -995,7 +995,7 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) /* Add group onto cgroup list */ sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); - blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, + cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, MKDEV(major, minor)); cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev); @@ -1079,7 +1079,7 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd) * it from cgroup list, then it will take care of destroying * cfqg also. */ - if (!blkiocg_del_blkio_group(&cfqg->blkg)) + if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg)) cfq_destroy_cfqg(cfqd, cfqg); } } @@ -1421,10 +1421,10 @@ static void cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq) { elv_rb_del(&cfqq->sort_list, rq); cfqq->queued[rq_is_sync(rq)]--; - blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq), - rq_is_sync(rq)); + cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, + rq_data_dir(rq), rq_is_sync(rq)); cfq_add_rq_rb(rq); - blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg, + cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg, &cfqq->cfqd->serving_group->blkg, rq_data_dir(rq), rq_is_sync(rq)); } @@ -1482,8 +1482,8 @@ static void cfq_remove_request(struct request *rq) cfq_del_rq_rb(rq); cfqq->cfqd->rq_queued--; - blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq), - rq_is_sync(rq)); + cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, + rq_data_dir(rq), rq_is_sync(rq)); if (rq_is_meta(rq)) { WARN_ON(!cfqq->meta_pending); cfqq->meta_pending--; @@ -1518,8 +1518,8 @@ static void cfq_merged_request(struct request_queue *q, struct request *req, static void cfq_bio_merged(struct request_queue *q, struct request *req, struct bio *bio) { - blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg, bio_data_dir(bio), - cfq_bio_sync(bio)); + cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg, + bio_data_dir(bio), cfq_bio_sync(bio)); } static void @@ -1539,8 +1539,8 @@ cfq_merged_requests(struct request_queue *q, struct request *rq, if (cfqq->next_rq == next) cfqq->next_rq = rq; cfq_remove_request(next); - blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(next), - rq_is_sync(next)); + cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg, + rq_data_dir(next), rq_is_sync(next)); } static int cfq_allow_merge(struct request_queue *q, struct request *rq, @@ -1571,7 +1571,7 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq, static inline void cfq_del_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) { del_timer(&cfqd->idle_slice_timer); - blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg); + cfq_blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg); } static void __cfq_set_active_queue(struct cfq_data *cfqd, @@ -1580,7 +1580,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd, if (cfqq) { cfq_log_cfqq(cfqd, cfqq, "set_active wl_prio:%d wl_type:%d", cfqd->serving_prio, cfqd->serving_type); - blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg); + cfq_blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg); cfqq->slice_start = 0; cfqq->dispatch_start = jiffies; cfqq->allocated_slice = 0; @@ -1911,7 +1911,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) sl = cfqd->cfq_slice_idle; mod_timer(&cfqd->idle_slice_timer, jiffies + sl); - blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg); + cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg); cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl); } @@ -1931,7 +1931,7 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq) elv_dispatch_sort(q, rq); cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++; - blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq), + cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq), rq_data_dir(rq), rq_is_sync(rq)); } @@ -1986,6 +1986,15 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq) int process_refs, new_process_refs; struct cfq_queue *__cfqq; + /* + * If there are no process references on the new_cfqq, then it is + * unsafe to follow the ->new_cfqq chain as other cfqq's in the + * chain may have dropped their last reference (not just their + * last process reference). + */ + if (!cfqq_process_refs(new_cfqq)) + return; + /* Avoid a circular list and skip interim queue merges */ while ((__cfqq = new_cfqq->new_cfqq)) { if (__cfqq == cfqq) @@ -1994,17 +2003,17 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq) } process_refs = cfqq_process_refs(cfqq); + new_process_refs = cfqq_process_refs(new_cfqq); /* * If the process for the cfqq has gone away, there is no * sense in merging the queues. */ - if (process_refs == 0) + if (process_refs == 0 || new_process_refs == 0) return; /* * Merge in the direction of the lesser amount of work. */ - new_process_refs = cfqq_process_refs(new_cfqq); if (new_process_refs >= process_refs) { cfqq->new_cfqq = new_cfqq; atomic_add(process_refs, &new_cfqq->ref); @@ -3248,7 +3257,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, cfq_clear_cfqq_wait_request(cfqq); __blk_run_queue(cfqd->queue); } else { - blkiocg_update_idle_time_stats( + cfq_blkiocg_update_idle_time_stats( &cfqq->cfqg->blkg); cfq_mark_cfqq_must_dispatch(cfqq); } @@ -3276,7 +3285,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]); list_add_tail(&rq->queuelist, &cfqq->fifo); cfq_add_rq_rb(rq); - blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg, + cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg, &cfqd->serving_group->blkg, rq_data_dir(rq), rq_is_sync(rq)); cfq_rq_enqueued(cfqd, cfqq, rq); @@ -3364,9 +3373,9 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) WARN_ON(!cfqq->dispatched); cfqd->rq_in_driver--; cfqq->dispatched--; - blkiocg_update_completion_stats(&cfqq->cfqg->blkg, rq_start_time_ns(rq), - rq_io_start_time_ns(rq), rq_data_dir(rq), - rq_is_sync(rq)); + cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg, + rq_start_time_ns(rq), rq_io_start_time_ns(rq), + rq_data_dir(rq), rq_is_sync(rq)); cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; @@ -3730,7 +3739,7 @@ static void cfq_exit_queue(struct elevator_queue *e) cfq_put_async_queues(cfqd); cfq_release_cfq_groups(cfqd); - blkiocg_del_blkio_group(&cfqd->root_group.blkg); + cfq_blkiocg_del_blkio_group(&cfqd->root_group.blkg); spin_unlock_irq(q->queue_lock); @@ -3798,8 +3807,8 @@ static void *cfq_init_queue(struct request_queue *q) */ atomic_set(&cfqg->ref, 1); rcu_read_lock(); - blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd, - 0); + cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, + (void *)cfqd, 0); rcu_read_unlock(); #endif /* diff --git a/block/cfq.h b/block/cfq.h new file mode 100644 index 000000000000..93448e5a2e41 --- /dev/null +++ b/block/cfq.h @@ -0,0 +1,115 @@ +#ifndef _CFQ_H +#define _CFQ_H +#include "blk-cgroup.h" + +#ifdef CONFIG_CFQ_GROUP_IOSCHED +static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg, + struct blkio_group *curr_blkg, bool direction, bool sync) +{ + blkiocg_update_io_add_stats(blkg, curr_blkg, direction, sync); +} + +static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg, + unsigned long dequeue) +{ + blkiocg_update_dequeue_stats(blkg, dequeue); +} + +static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg, + unsigned long time) +{ + blkiocg_update_timeslice_used(blkg, time); +} + +static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) +{ + blkiocg_set_start_empty_time(blkg); +} + +static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg, + bool direction, bool sync) +{ + blkiocg_update_io_remove_stats(blkg, direction, sync); +} + +static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg, + bool direction, bool sync) +{ + blkiocg_update_io_merged_stats(blkg, direction, sync); +} + +static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg) +{ + blkiocg_update_idle_time_stats(blkg); +} + +static inline void +cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg) +{ + blkiocg_update_avg_queue_size_stats(blkg); +} + +static inline void +cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg) +{ + blkiocg_update_set_idle_time_stats(blkg); +} + +static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg, + uint64_t bytes, bool direction, bool sync) +{ + blkiocg_update_dispatch_stats(blkg, bytes, direction, sync); +} + +static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync) +{ + blkiocg_update_completion_stats(blkg, start_time, io_start_time, + direction, sync); +} + +static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, + struct blkio_group *blkg, void *key, dev_t dev) { + blkiocg_add_blkio_group(blkcg, blkg, key, dev); +} + +static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg) +{ + return blkiocg_del_blkio_group(blkg); +} + +#else /* CFQ_GROUP_IOSCHED */ +static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg, + struct blkio_group *curr_blkg, bool direction, bool sync) {} + +static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg, + unsigned long dequeue) {} + +static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg, + unsigned long time) {} +static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {} +static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg, + bool direction, bool sync) {} +static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg, + bool direction, bool sync) {} +static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg) +{ +} +static inline void +cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg) {} + +static inline void +cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg) {} + +static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg, + uint64_t bytes, bool direction, bool sync) {} +static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync) {} + +static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, + struct blkio_group *blkg, void *key, dev_t dev) {} +static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg) +{ + return 0; +} + +#endif /* CFQ_GROUP_IOSCHED */ +#endif diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index d269a8f3329c..446aced33aff 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax; static unsigned char tsc_detected_unstable; static unsigned char tsc_marked_unstable; +static unsigned char lapic_detected_unstable; +static unsigned char lapic_marked_unstable; static void power_saving_mwait_init(void) { @@ -75,9 +77,6 @@ static void power_saving_mwait_init(void) power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | (highest_subcstate - 1); - for_each_online_cpu(i) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i); - #if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86) switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -86,13 +85,15 @@ static void power_saving_mwait_init(void) * AMD Fam10h TSC will tick in all * C/P/S0/S1 states when this bit is set. */ - if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) - return; - - /*FALL THROUGH*/ + if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) + tsc_detected_unstable = 1; + if (!boot_cpu_has(X86_FEATURE_ARAT)) + lapic_detected_unstable = 1; + break; default: - /* TSC could halt in idle */ + /* TSC & LAPIC could halt in idle */ tsc_detected_unstable = 1; + lapic_detected_unstable = 1; } #endif } @@ -180,10 +181,20 @@ static int power_saving_thread(void *data) mark_tsc_unstable("TSC halts in idle"); tsc_marked_unstable = 1; } + if (lapic_detected_unstable && !lapic_marked_unstable) { + int i; + /* LAPIC could halt in idle, so notify users */ + for_each_online_cpu(i) + clockevents_notify( + CLOCK_EVT_NOTIFY_BROADCAST_ON, + &i); + lapic_marked_unstable = 1; + } local_irq_disable(); cpu = smp_processor_id(); - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, - &cpu); + if (lapic_marked_unstable) + clockevents_notify( + CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); stop_critical_timings(); __monitor((void *)¤t_thread_info()->flags, 0, 0); @@ -192,8 +203,9 @@ static int power_saving_thread(void *data) __mwait(power_saving_mwait_eax, 1); start_critical_timings(); - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, - &cpu); + if (lapic_marked_unstable) + clockevents_notify( + CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); local_irq_enable(); if (jiffies > expire_time) { diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h index 33181ad350d5..b17d8de9f6ff 100644 --- a/drivers/acpi/acpica/acconfig.h +++ b/drivers/acpi/acpica/acconfig.h @@ -119,6 +119,10 @@ #define ACPI_MAX_LOOP_ITERATIONS 0xFFFF +/* Maximum sleep allowed via Sleep() operator */ + +#define ACPI_MAX_SLEEP 20000 /* Two seconds */ + /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 64d1e5c2d4ae..c3f43daa8be3 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -80,10 +80,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); acpi_status acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); - -acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); - struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 9070f1fe8f17..899d68afc3c5 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -125,6 +125,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); */ u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); +/* + * Optionally truncate I/O addresses to 16 bits. Provides compatibility + * with other ACPI implementations. NOTE: During ACPICA initialization, + * this value is set to TRUE if any Windows OSI strings have been + * requested by the BIOS. + */ +u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); + /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ struct acpi_table_fadt acpi_gbl_FADT; diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 5900f135dc6d..32391588e163 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -90,7 +90,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); /* * hwgpe - GPE support */ -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); +u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, + struct acpi_gpe_register_info *gpe_register_info); + +acpi_status +acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action); acpi_status acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info); diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index a221ad404167..7c2c336006a1 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -69,7 +69,7 @@ acpi_status acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) { struct acpi_gpe_register_info *gpe_register_info; - u8 register_bit; + u32 register_bit; ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); @@ -78,9 +78,8 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) return_ACPI_STATUS(AE_NOT_EXIST); } - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); + register_bit = acpi_hw_gpe_register_bit(gpe_event_info, + gpe_register_info); /* Clear the wake/run bits up front */ @@ -100,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) return_ACPI_STATUS(AE_OK); } -/******************************************************************************* - * - * FUNCTION: acpi_ev_enable_gpe - * - * PARAMETERS: gpe_event_info - GPE to enable - * - * RETURN: Status - * - * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless - * of type or number of references. - * - * Note: The GPE lock should be already acquired when this function is called. - * - ******************************************************************************/ - -acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ - acpi_status status; - - - ACPI_FUNCTION_TRACE(ev_enable_gpe); - - - /* - * We will only allow a GPE to be enabled if it has either an - * associated method (_Lxx/_Exx) or a handler. Otherwise, the - * GPE will be immediately disabled by acpi_ev_gpe_dispatch the - * first time it fires. - */ - if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { - return_ACPI_STATUS(AE_NO_HANDLER); - } - - /* Ensure the HW enable masks are current */ - - status = acpi_ev_update_gpe_enable_masks(gpe_event_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Clear the GPE (of stale events) */ - - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Enable the requested GPE */ - - status = acpi_hw_write_gpe_enable_reg(gpe_event_info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_disable_gpe - * - * PARAMETERS: gpe_event_info - GPE to disable - * - * RETURN: Status - * - * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, - * regardless of the type or number of references. - * - * Note: The GPE lock should be already acquired when this function is called. - * - ******************************************************************************/ - -acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_disable_gpe); - - - /* - * Note: Always disable the GPE, even if we think that that it is already - * disabled. It is possible that the AML or some other code has enabled - * the GPE behind our back. - */ - - /* Ensure the HW enable masks are current */ - - status = acpi_ev_update_gpe_enable_masks(gpe_event_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Always H/W disable this GPE, even if we don't know the GPE type. - * Simply clear the enable bit for this particular GPE, but do not - * write out the current GPE enable mask since this may inadvertently - * enable GPEs too early. An example is a rogue GPE that has arrived - * during ACPICA initialization - possibly because AML or other code - * has enabled the GPE. - */ - status = acpi_hw_low_disable_gpe(gpe_event_info); - return_ACPI_STATUS(status); -} - /******************************************************************************* * @@ -451,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) return_VOID; } - /* Update the GPE register masks for return to enabled state */ - - (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); - /* * Take a snapshot of the GPE info for this level - we copy the info to * prevent a race condition with remove_handler/remove_block. @@ -607,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * Disable the GPE, so it doesn't keep firing before the method has a * chance to run (it runs asynchronously with interrupts enabled). */ - status = acpi_ev_disable_gpe(gpe_event_info); + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to disable GPE[0x%2X]", @@ -644,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * Disable the GPE. The GPE will remain disabled a handler * is installed or ACPICA is restarted. */ - status = acpi_ev_disable_gpe(gpe_event_info); + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to disable GPE[0x%2X]", diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 7c28f2d9fd35..341a38ce8aa6 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -500,6 +500,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; gpe_event_info = &gpe_block->event_info[gpe_index]; + gpe_number = gpe_index + gpe_block->block_base_number; + + /* + * If the GPE has already been enabled for runtime + * signaling, make sure it remains enabled, but do not + * increment its reference counter. + */ + if (gpe_event_info->runtime_count) { + acpi_set_gpe(gpe_device, gpe_number, + ACPI_GPE_ENABLE); + gpe_enabled_count++; + continue; + } if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { wake_gpe_count++; @@ -516,7 +529,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, /* Enable this GPE */ - gpe_number = gpe_index + gpe_block->block_base_number; status = acpi_enable_gpe(gpe_device, gpe_number, ACPI_GPE_TYPE_RUNTIME); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index cc825023012a..4a531cdf7942 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -719,13 +719,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device, handler->context = context; handler->method_node = gpe_event_info->dispatch.method_node; - /* Disable the GPE before installing the handler */ - - status = acpi_ev_disable_gpe(gpe_event_info); - if (ACPI_FAILURE (status)) { - goto unlock_and_exit; - } - /* Install the handler */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index d5a5efc043bf..d97b8dce1668 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -210,6 +210,44 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) /******************************************************************************* * + * FUNCTION: acpi_clear_and_enable_gpe + * + * PARAMETERS: gpe_event_info - GPE to enable + * + * RETURN: Status + * + * DESCRIPTION: Clear the given GPE from stale events and enable it. + * + ******************************************************************************/ +static acpi_status +acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + /* + * We will only allow a GPE to be enabled if it has either an + * associated method (_Lxx/_Exx) or a handler. Otherwise, the + * GPE will be immediately disabled by acpi_ev_gpe_dispatch the + * first time it fires. + */ + if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { + return_ACPI_STATUS(AE_NO_HANDLER); + } + + /* Clear the GPE (of stale events) */ + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Enable the requested GPE */ + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * * FUNCTION: acpi_set_gpe * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 @@ -249,11 +287,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) switch (action) { case ACPI_GPE_ENABLE: - status = acpi_ev_enable_gpe(gpe_event_info); + status = acpi_clear_and_enable_gpe(gpe_event_info); break; case ACPI_GPE_DISABLE: - status = acpi_ev_disable_gpe(gpe_event_info); + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); break; default: @@ -316,7 +354,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) gpe_event_info->runtime_count++; if (gpe_event_info->runtime_count == 1) { - status = acpi_ev_enable_gpe(gpe_event_info); + status = acpi_ev_update_gpe_enable_masks(gpe_event_info); + if (ACPI_SUCCESS(status)) { + status = acpi_clear_and_enable_gpe(gpe_event_info); + } + if (ACPI_FAILURE(status)) { gpe_event_info->runtime_count--; goto unlock_and_exit; @@ -343,7 +385,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) */ gpe_event_info->wakeup_count++; if (gpe_event_info->wakeup_count == 1) { - (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); + status = acpi_ev_update_gpe_enable_masks(gpe_event_info); } } @@ -403,7 +445,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type gpe_event_info->runtime_count--; if (!gpe_event_info->runtime_count) { - status = acpi_ev_disable_gpe(gpe_event_info); + status = acpi_ev_update_gpe_enable_masks(gpe_event_info); + if (ACPI_SUCCESS(status)) { + status = acpi_hw_low_set_gpe(gpe_event_info, + ACPI_GPE_DISABLE); + } + if (ACPI_FAILURE(status)) { gpe_event_info->runtime_count++; goto unlock_and_exit; @@ -424,7 +471,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type gpe_event_info->wakeup_count--; if (!gpe_event_info->wakeup_count) { - (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); + status = acpi_ev_update_gpe_enable_masks(gpe_event_info); } } diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 6d32e09327f1..675aaa91a770 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -201,6 +201,14 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long) acpi_ex_relinquish_interpreter(); + /* + * For compatibility with other ACPI implementations and to prevent + * accidental deep sleeps, limit the sleep time to something reasonable. + */ + if (how_long > ACPI_MAX_SLEEP) { + how_long = ACPI_MAX_SLEEP; + } + acpi_os_sleep(how_long); /* And now we must get the interpreter again */ diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index bd72319a38f0..3450309c2786 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -57,21 +57,47 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /****************************************************************************** * - * FUNCTION: acpi_hw_low_disable_gpe + * FUNCTION: acpi_hw_gpe_register_bit + * + * PARAMETERS: gpe_event_info - Info block for the GPE + * gpe_register_info - Info block for the GPE register + * + * RETURN: Status + * + * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given + * GPE set. + * + ******************************************************************************/ + +u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, + struct acpi_gpe_register_info *gpe_register_info) +{ + return (u32)1 << (gpe_event_info->gpe_number - + gpe_register_info->base_gpe_number); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_low_set_gpe * * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled + * action - Enable or disable * * RETURN: Status * - * DESCRIPTION: Disable a single GPE in the enable register. + * DESCRIPTION: Enable or disable a single GPE in its enable register. * ******************************************************************************/ -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) +acpi_status +acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) { struct acpi_gpe_register_info *gpe_register_info; acpi_status status; u32 enable_mask; + u32 register_bit; + + ACPI_FUNCTION_ENTRY(); /* Get the info block for the entire GPE register */ @@ -87,11 +113,27 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) return (status); } - /* Clear just the bit that corresponds to this GPE */ + /* Set ot clear just the bit that corresponds to this GPE */ - ACPI_CLEAR_BIT(enable_mask, ((u32)1 << - (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number))); + register_bit = acpi_hw_gpe_register_bit(gpe_event_info, + gpe_register_info); + switch (action) { + case ACPI_GPE_COND_ENABLE: + if (!(register_bit & gpe_register_info->enable_for_run)) + return (AE_BAD_PARAMETER); + + case ACPI_GPE_ENABLE: + ACPI_SET_BIT(enable_mask, register_bit); + break; + + case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT(enable_mask, register_bit); + break; + + default: + ACPI_ERROR((AE_INFO, "Invalid action\n")); + return (AE_BAD_PARAMETER); + } /* Write the updated enable mask */ @@ -116,23 +158,11 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) acpi_status acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) { - struct acpi_gpe_register_info *gpe_register_info; acpi_status status; ACPI_FUNCTION_ENTRY(); - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return (AE_NOT_EXIST); - } - - /* Write the entire GPE (runtime) enable register */ - - status = acpi_hw_write(gpe_register_info->enable_for_run, - &gpe_register_info->enable_address); - + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE); return (status); } @@ -150,21 +180,28 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) { + struct acpi_gpe_register_info *gpe_register_info; acpi_status status; - u8 register_bit; + u32 register_bit; ACPI_FUNCTION_ENTRY(); - register_bit = (u8)(1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + /* Get the info block for the entire GPE register */ + + gpe_register_info = gpe_event_info->register_info; + if (!gpe_register_info) { + return (AE_NOT_EXIST); + } + + register_bit = acpi_hw_gpe_register_bit(gpe_event_info, + gpe_register_info); /* * Write a one to the appropriate bit in the status register to * clear this GPE. */ status = acpi_hw_write(register_bit, - &gpe_event_info->register_info->status_address); + &gpe_register_info->status_address); return (status); } @@ -187,7 +224,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, acpi_event_status * event_status) { u32 in_byte; - u8 register_bit; + u32 register_bit; struct acpi_gpe_register_info *gpe_register_info; acpi_status status; acpi_event_status local_event_status = 0; @@ -204,9 +241,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* Get the register bitmask for this GPE */ - register_bit = (u8)(1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + register_bit = acpi_hw_gpe_register_bit(gpe_event_info, + gpe_register_info); /* GPE currently enabled? (enabled for runtime?) */ diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index c10d587c1641..e1d9c777b213 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -222,6 +222,12 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) u32 one_byte; u32 i; + /* Truncate address to 16 bits if requested */ + + if (acpi_gbl_truncate_io_addresses) { + address &= ACPI_UINT16_MAX; + } + /* Validate the entire request and perform the I/O */ status = acpi_hw_validate_io_request(address, width); @@ -279,6 +285,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) acpi_status status; u32 i; + /* Truncate address to 16 bits if requested */ + + if (acpi_gbl_truncate_io_addresses) { + address &= ACPI_UINT16_MAX; + } + /* Validate the entire request and perform the I/O */ status = acpi_hw_validate_io_request(address, width); diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 9bd6f050f299..4e5272c313e0 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -193,6 +193,15 @@ acpi_status acpi_ns_initialize_devices(void) acpi_ns_init_one_device, NULL, &info, NULL); + /* + * Any _OSI requests should be completed by now. If the BIOS has + * requested any Windows OSI strings, we will always truncate + * I/O addresses to 16 bits -- for Windows compatibility. + */ + if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) { + acpi_gbl_truncate_io_addresses = TRUE; + } + ACPI_FREE(info.evaluate_info); if (ACPI_FAILURE(status)) { goto error_exit; diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index db3946e9c66b..216e1e948ff6 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -34,6 +34,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/acpi.h> +#include <linux/slab.h> #include <linux/io.h> #include <linux/kref.h> #include <linux/rculist.h> diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 2ebc39115507..864dd46c346f 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -781,7 +781,7 @@ static int __init erst_init(void) status = acpi_get_table(ACPI_SIG_ERST, 0, (struct acpi_table_header **)&erst_tab); if (status == AE_NOT_FOUND) { - pr_err(ERST_PFX "Table is not found!\n"); + pr_info(ERST_PFX "Table is not found!\n"); goto err; } else if (ACPI_FAILURE(status)) { const char *msg = acpi_format_exception(status); diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c index 814b19249616..8f8bd736d4ff 100644 --- a/drivers/acpi/atomicio.c +++ b/drivers/acpi/atomicio.c @@ -31,6 +31,7 @@ #include <linux/kref.h> #include <linux/rculist.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <acpi/atomicio.h> #define ACPI_PFX "ACPI: " diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 2815df66f6f7..01381be05e96 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -218,6 +218,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { + .callback = dmi_disable_osi_vista, + .ident = "VGN-NS50B_L", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"), + }, + }, + { .callback = dmi_disable_osi_win7, .ident = "ASUS K50IJ", .matches = { diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index fd51c4ab4829..7d857dabdde4 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE_RUN); + ACPI_GPE_TYPE_RUNTIME); device->wakeup.run_wake_count++; device->wakeup.state.enabled = 1; } @@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type) if (device->wakeup.flags.valid) { acpi_disable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE_RUN); + ACPI_GPE_TYPE_RUNTIME); device->wakeup.run_wake_count--; device->wakeup.state.enabled = 0; } diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index acf2ab249842..8a3b840c0bb2 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -347,7 +347,6 @@ static int __init acpi_fan_init(void) { int result = 0; - #ifdef CONFIG_ACPI_PROCFS acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); if (!acpi_fan_dir) @@ -356,7 +355,9 @@ static int __init acpi_fan_init(void) result = acpi_bus_register_driver(&acpi_fan_driver); if (result < 0) { +#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); +#endif return -ENODEV; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index b1034a9ada4e..38ea0cc6dc49 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) return 0; } +#ifdef CONFIG_SMP + if (pr->id >= setup_max_cpus && pr->id != 0) + return 0; +#endif + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); /* diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3fb4bdea7e06..5b7c52e4a00f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -114,6 +114,8 @@ static int __acpi_pm_prepare(void) { int error = acpi_sleep_prepare(acpi_target_sleep_state); + suspend_nvs_save(); + if (error) acpi_target_sleep_state = ACPI_STATE_S0; return error; @@ -143,6 +145,9 @@ static void acpi_pm_finish(void) { u32 acpi_state = acpi_target_sleep_state; + suspend_nvs_free(); + acpi_ec_unblock_transactions(); + if (acpi_state == ACPI_STATE_S0) return; @@ -192,6 +197,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state) u32 acpi_state = acpi_suspend_states[pm_state]; int error = 0; + error = suspend_nvs_alloc(); + + if (error) + return error; + if (sleep_states[acpi_state]) { acpi_target_sleep_state = acpi_state; acpi_sleep_tts_switch(acpi_target_sleep_state); @@ -269,12 +279,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state) if (acpi_state == ACPI_STATE_S3) acpi_restore_state_mem(); + suspend_nvs_restore(); + return ACPI_SUCCESS(status) ? 0 : -EFAULT; } static void acpi_suspend_finish(void) { - acpi_ec_unblock_transactions(); acpi_pm_finish(); } @@ -404,7 +415,7 @@ static int acpi_hibernation_begin(void) { int error; - error = s4_no_nvs ? 0 : hibernate_nvs_alloc(); + error = s4_no_nvs ? 0 : suspend_nvs_alloc(); if (!error) { acpi_target_sleep_state = ACPI_STATE_S4; acpi_sleep_tts_switch(acpi_target_sleep_state); @@ -418,7 +429,7 @@ static int acpi_hibernation_pre_snapshot(void) int error = acpi_pm_prepare(); if (!error) - hibernate_nvs_save(); + suspend_nvs_save(); return error; } @@ -441,13 +452,6 @@ static int acpi_hibernation_enter(void) return ACPI_SUCCESS(status) ? 0 : -EFAULT; } -static void acpi_hibernation_finish(void) -{ - hibernate_nvs_free(); - acpi_ec_unblock_transactions(); - acpi_pm_finish(); -} - static void acpi_hibernation_leave(void) { /* @@ -464,7 +468,7 @@ static void acpi_hibernation_leave(void) panic("ACPI S4 hardware signature mismatch"); } /* Restore the NVS memory area */ - hibernate_nvs_restore(); + suspend_nvs_restore(); /* Allow EC transactions to happen. */ acpi_ec_unblock_transactions_early(); } @@ -479,7 +483,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { .begin = acpi_hibernation_begin, .end = acpi_pm_end, .pre_snapshot = acpi_hibernation_pre_snapshot, - .finish = acpi_hibernation_finish, + .finish = acpi_pm_finish, .prepare = acpi_pm_prepare, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, @@ -507,7 +511,7 @@ static int acpi_hibernation_begin_old(void) if (!error) { if (!s4_no_nvs) - error = hibernate_nvs_alloc(); + error = suspend_nvs_alloc(); if (!error) acpi_target_sleep_state = ACPI_STATE_S4; } @@ -517,7 +521,7 @@ static int acpi_hibernation_begin_old(void) static int acpi_hibernation_pre_snapshot_old(void) { acpi_pm_freeze(); - hibernate_nvs_save(); + suspend_nvs_save(); return 0; } @@ -529,8 +533,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { .begin = acpi_hibernation_begin_old, .end = acpi_pm_end, .pre_snapshot = acpi_hibernation_pre_snapshot_old, - .finish = acpi_hibernation_finish, .prepare = acpi_pm_freeze, + .finish = acpi_pm_finish, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, .pre_restore = acpi_pm_freeze, diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index c79e789ed03a..f8db50a0941c 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -388,10 +388,12 @@ static ssize_t counter_set(struct kobject *kobj, if (index < num_gpes) { if (!strcmp(buf, "disable\n") && (status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE); + result = acpi_disable_gpe(handle, index, + ACPI_GPE_TYPE_RUNTIME); else if (!strcmp(buf, "enable\n") && !(status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE); + result = acpi_enable_gpe(handle, index, + ACPI_GPE_TYPE_RUNTIME); else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_gpe(handle, index); diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 4b9d339a6e28..388747a7ef4f 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -64,16 +64,13 @@ void acpi_enable_wakeup_device(u8 sleep_state) struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); - if (!dev->wakeup.flags.valid) - continue; - - if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) + if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled || sleep_state > (u32) dev->wakeup.sleep_state) continue; /* The wake-up power should have been enabled already. */ - acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, - ACPI_GPE_ENABLE); + acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE); } } @@ -96,6 +93,8 @@ void acpi_disable_wakeup_device(u8 sleep_state) || (sleep_state > (u32) dev->wakeup.sleep_state)) continue; + acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE); acpi_disable_wakeup_device_power(dev); } } @@ -109,13 +108,8 @@ int __init acpi_wakeup_device_init(void) struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); - /* In case user doesn't load button driver */ - if (!dev->wakeup.flags.always_enabled || - dev->wakeup.state.enabled) - continue; - acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE); - dev->wakeup.state.enabled = 1; + if (dev->wakeup.flags.always_enabled) + dev->wakeup.state.enabled = 1; } mutex_unlock(&acpi_device_lock); return 0; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 8ca16f54e1ed..f2522534ae63 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1053,6 +1053,16 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) return -ENODEV; + /* + * For some reason, MCP89 on MacBook 7,1 doesn't work with + * ahci, use ata_generic instead. + */ + if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && + pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && + pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && + pdev->subsystem_device == 0xcb89) + return -ENODEV; + /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. * At the moment, we can only use the AHCI mode. Let the users know * that for SAS drives they're out of luck. diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 573158a9668d..7107a6929deb 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -32,6 +32,11 @@ * A generic parallel ATA driver using libata */ +enum { + ATA_GEN_CLASS_MATCH = (1 << 0), + ATA_GEN_FORCE_DMA = (1 << 1), +}; + /** * generic_set_mode - mode setting * @link: link to set up @@ -46,13 +51,17 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused) { struct ata_port *ap = link->ap; + const struct pci_device_id *id = ap->host->private_data; int dma_enabled = 0; struct ata_device *dev; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - /* Bits 5 and 6 indicate if DMA is active on master/slave */ - if (ap->ioaddr.bmdma_addr) + if (id->driver_data & ATA_GEN_FORCE_DMA) { + dma_enabled = 0xff; + } else if (ap->ioaddr.bmdma_addr) { + /* Bits 5 and 6 indicate if DMA is active on master/slave */ dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + } if (pdev->vendor == PCI_VENDOR_ID_CENATEK) dma_enabled = 0xFF; @@ -126,7 +135,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id const struct ata_port_info *ppi[] = { &info, NULL }; /* Don't use the generic entry unless instructed to do so */ - if (id->driver_data == 1 && all_generic_ide == 0) + if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0) return -ENODEV; /* Devices that need care */ @@ -155,7 +164,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id return rc; pcim_pin_device(dev); } - return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0); + return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0); } static struct pci_device_id ata_generic[] = { @@ -167,7 +176,15 @@ static struct pci_device_id ata_generic[] = { { PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), }, { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), }, - { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), }, + { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), + .driver_data = ATA_GEN_FORCE_DMA }, + /* + * For some reason, MCP89 on MacBook 7,1 doesn't work with + * ahci, use ata_generic instead. + */ + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA, + PCI_VENDOR_ID_APPLE, 0xcb89, + .driver_data = ATA_GEN_FORCE_DMA }, #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE) { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, @@ -175,7 +192,8 @@ static struct pci_device_id ata_generic[] = { { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), }, #endif /* Must come last. If you add entries adjust this table appropriately */ - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1}, + { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL), + .driver_data = ATA_GEN_CLASS_MATCH }, { 0, }, }; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 1984a6e89e84..81e772a94d59 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -324,6 +324,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev, struct ahci_host_priv *hpriv = ap->host->private_data; void __iomem *mmio = hpriv->mmio; void __iomem *em_mmio = mmio + hpriv->em_loc; + const unsigned char *msg_buf = buf; u32 em_ctl, msg; unsigned long flags; int i; @@ -343,8 +344,8 @@ static ssize_t ahci_store_em_buffer(struct device *dev, } for (i = 0; i < size; i += 4) { - msg = buf[i] | buf[i + 1] << 8 | - buf[i + 2] << 16 | buf[i + 3] << 24; + msg = msg_buf[i] | msg_buf[i + 1] << 8 | + msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24; writel(msg, em_mmio + i); } @@ -541,29 +542,11 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) return -EINVAL; } -static int ahci_is_device_present(void __iomem *port_mmio) -{ - u8 status = readl(port_mmio + PORT_TFDATA) & 0xff; - - /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */ - if (status & (ATA_BUSY | ATA_DRQ)) - return 0; - - /* Make sure PxSSTS.DET is 3h */ - status = readl(port_mmio + PORT_SCR_STAT) & 0xf; - if (status != 3) - return 0; - return 1; -} - void ahci_start_engine(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; - if (!ahci_is_device_present(port_mmio)) - return; - /* start DMA */ tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_START; @@ -1892,6 +1875,9 @@ static void ahci_error_handler(struct ata_port *ap) } sata_pmp_error_handler(ap); + + if (!ata_dev_enabled(ap->link.device)) + ahci_stop_engine(ap); } static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index e9250514734b..be7726d7686d 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -539,12 +539,12 @@ static void sil24_config_port(struct ata_port *ap) writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); /* zero error counters. */ - writel(0x8000, port + PORT_DECODE_ERR_THRESH); - writel(0x8000, port + PORT_CRC_ERR_THRESH); - writel(0x8000, port + PORT_HSHK_ERR_THRESH); - writel(0x0000, port + PORT_DECODE_ERR_CNT); - writel(0x0000, port + PORT_CRC_ERR_CNT); - writel(0x0000, port + PORT_HSHK_ERR_CNT); + writew(0x8000, port + PORT_DECODE_ERR_THRESH); + writew(0x8000, port + PORT_CRC_ERR_THRESH); + writew(0x8000, port + PORT_HSHK_ERR_THRESH); + writew(0x0000, port + PORT_DECODE_ERR_CNT); + writew(0x0000, port + PORT_CRC_ERR_CNT); + writew(0x0000, port + PORT_HSHK_ERR_CNT); /* always use 64bit activation */ writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); @@ -622,6 +622,11 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp, irq_enabled = readl(port + PORT_IRQ_ENABLE_SET); writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR); + /* + * The barrier is required to ensure that writes to cmd_block reach + * the memory before the write to PORT_CMD_ACTIVATE. + */ + wmb(); writel((u32)paddr, port + PORT_CMD_ACTIVATE); writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); @@ -865,7 +870,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) } else { prb = &cb->atapi.prb; sge = cb->atapi.sge; - memset(cb->atapi.cdb, 0, 32); + memset(cb->atapi.cdb, 0, sizeof(cb->atapi.cdb)); memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); if (ata_is_data(qc->tf.protocol)) { @@ -895,6 +900,11 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block); activate = port + PORT_CMD_ACTIVATE + tag * 8; + /* + * The barrier is required to ensure that writes to cmd_block reach + * the memory before the write to PORT_CMD_ACTIVATE. + */ + wmb(); writel((u32)paddr, activate); writel((u64)paddr >> 32, activate + 4); diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 0ecd0f6aa2c0..4730c42a5ee5 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -578,10 +578,24 @@ static void svia_configure(struct pci_dev *pdev) /* * vt6421 has problems talking to some drives. The following - * is the magic fix from Joseph Chan <JosephChan@via.com.tw>. - * Please add proper documentation if possible. + * is the fix from Joseph Chan <JosephChan@via.com.tw>. + * + * When host issues HOLD, device may send up to 20DW of data + * before acknowledging it with HOLDA and the host should be + * able to buffer them in FIFO. Unfortunately, some WD drives + * send upto 40DW before acknowledging HOLD and, in the + * default configuration, this ends up overflowing vt6421's + * FIFO, making the controller abort the transaction with + * R_ERR. + * + * Rx52[2] is the internal 128DW FIFO Flow control watermark + * adjusting mechanism enable bit and the default value 0 + * means host will issue HOLD to device when the left FIFO + * size goes below 32DW. Setting it to 1 makes the watermark + * 64DW. * * https://bugzilla.kernel.org/show_bug.cgi?id=15173 + * http://article.gmane.org/gmane.linux.ide/46352 */ if (pdev->device == 0x3249) { pci_read_config_byte(pdev, 0x52, &tmp8); diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 3381505c8a6c..72dae92f3cab 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -861,6 +861,7 @@ cciss_scsi_detect(int ctlr) sh->n_io_port = 0; // I don't think we use these two... sh->this_id = SELF_SCSI_ID; sh->sg_tablesize = hba[ctlr]->maxsgentries; + sh->max_cmd_len = MAX_COMMAND_SIZE; ((struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr)->scsi_host = sh; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 91d11631cec9..abb4ec6690fc 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -386,7 +386,7 @@ static void __devexit cpqarray_remove_one_eisa (int i) } /* pdev is NULL for eisa */ -static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) +static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev) { struct request_queue *q; int j; @@ -503,7 +503,7 @@ Enomem4: return -1; } -static int __init cpqarray_init_one( struct pci_dev *pdev, +static int __devinit cpqarray_init_one( struct pci_dev *pdev, const struct pci_device_id *ent) { int i; @@ -740,7 +740,7 @@ __setup("smart2=", cpqarray_setup); /* * Find an EISA controller's signature. Set up an hba if we find it. */ -static int __init cpqarray_eisa_detect(void) +static int __devinit cpqarray_eisa_detect(void) { int i=0, j; __u32 board_id; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 6b077f93acc6..7258c95e895e 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, /* Last part of the attaching process ... */ if (ns.conn >= C_CONNECTED && os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) { - kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */ - mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */ drbd_send_sizes(mdev, 0, 0); /* to start sync... */ drbd_send_uuids(mdev); drbd_send_state(mdev); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 632e3245d1bb..2151f18b21de 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp mdev->new_state_tmp.i = ns.i; ns.i = os.i; ns.disk = D_NEGOTIATING; + + /* We expect to receive up-to-date UUIDs soon. + To avoid a race in receive_state, free p_uuid while + holding req_lock. I.e. atomic with the state change */ + kfree(mdev->p_uuid); + mdev->p_uuid = NULL; } rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL); diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 4b51982fd23a..d2abf5143983 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -97,20 +97,18 @@ EXPORT_SYMBOL(agp_flush_chipset); void agp_alloc_page_array(size_t size, struct agp_memory *mem) { mem->pages = NULL; - mem->vmalloc_flag = false; if (size <= 2*PAGE_SIZE) - mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY); + mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); if (mem->pages == NULL) { mem->pages = vmalloc(size); - mem->vmalloc_flag = true; } } EXPORT_SYMBOL(agp_alloc_page_array); void agp_free_page_array(struct agp_memory *mem) { - if (mem->vmalloc_flag) { + if (is_vmalloc_addr(mem->pages)) { vfree(mem->pages); } else { kfree(mem->pages); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 35603dd4e6c5..094bdc355b1f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -302,6 +302,12 @@ struct smi_info { static int force_kipmid[SI_MAX_PARMS]; static int num_force_kipmid; +#ifdef CONFIG_PCI +static int pci_registered; +#endif +#ifdef CONFIG_PPC_OF +static int of_registered; +#endif static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; static int num_max_busy_us; @@ -1018,7 +1024,7 @@ static int ipmi_thread(void *data) else if (smi_result == SI_SM_IDLE) schedule_timeout_interruptible(100); else - schedule_timeout_interruptible(0); + schedule_timeout_interruptible(1); } return 0; } @@ -3314,6 +3320,8 @@ static __devinit int init_ipmi_si(void) rv = pci_register_driver(&ipmi_pci_driver); if (rv) printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv); + else + pci_registered = 1; #endif #ifdef CONFIG_ACPI @@ -3330,6 +3338,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_PPC_OF of_register_platform_driver(&ipmi_of_platform_driver); + of_registered = 1; #endif /* We prefer devices with interrupts, but in the case of a machine @@ -3383,11 +3392,13 @@ static __devinit int init_ipmi_si(void) if (unload_when_empty && list_empty(&smi_infos)) { mutex_unlock(&smi_infos_lock); #ifdef CONFIG_PCI - pci_unregister_driver(&ipmi_pci_driver); + if (pci_registered) + pci_unregister_driver(&ipmi_pci_driver); #endif #ifdef CONFIG_PPC_OF - of_unregister_platform_driver(&ipmi_of_platform_driver); + if (of_registered) + of_unregister_platform_driver(&ipmi_of_platform_driver); #endif driver_unregister(&ipmi_driver.driver); printk(KERN_WARNING PFX @@ -3478,14 +3489,16 @@ static __exit void cleanup_ipmi_si(void) return; #ifdef CONFIG_PCI - pci_unregister_driver(&ipmi_pci_driver); + if (pci_registered) + pci_unregister_driver(&ipmi_pci_driver); #endif #ifdef CONFIG_ACPI pnp_unregister_driver(&ipmi_pnp_driver); #endif #ifdef CONFIG_PPC_OF - of_unregister_platform_driver(&ipmi_of_platform_driver); + if (of_registered) + of_unregister_platform_driver(&ipmi_of_platform_driver); #endif mutex_lock(&smi_infos_lock); diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 5d15630a5830..5d64e3acb000 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -580,8 +580,12 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type, case KEY_RIGHTALT: if (value) sysrq_alt = code; - else if (sysrq_down && code == sysrq_alt_use) - sysrq_down = false; + else { + if (sysrq_down && code == sysrq_alt_use) + sysrq_down = false; + + sysrq_alt = 0; + } break; case KEY_SYSRQ: diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e00b4ddd083..792868d24f2a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -224,6 +224,7 @@ struct tpm_readpubek_params_out { u8 algorithm[4]; u8 encscheme[2]; u8 sigscheme[2]; + __be32 paramsize; u8 parameters[12]; /*assuming RSA*/ __be32 keysize; u8 modulus[256]; diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1296c42ed5c6..7cdb6ee569cd 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -304,7 +304,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr) d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr)); scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row); - scr_memsetw(d + (b - t - nr) * vc->vc_size_row, vc->vc_video_erase_char, + scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char, vc->vc_size_row * nr); } diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index f3d3898898ed..717305d30444 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -449,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, clk_disable(p->clk); /* TODO: calculate good shift from rate and counter bit width */ - cs->shift = 10; + cs->shift = 0; cs->mult = clocksource_hz2mult(p->rate, cs->shift); dev_info(&p->pdev->dev, "used as clock source\n"); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 52ff8aa63f84..1b128702d300 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -143,7 +143,7 @@ static inline int which_bucket(unsigned int duration) * This allows us to calculate * E(duration)|iowait */ - if (nr_iowait_cpu()) + if (nr_iowait_cpu(smp_processor_id())) bucket = BUCKETS/2; if (duration < 10) @@ -175,7 +175,7 @@ static inline int performance_multiplier(void) mult += 2 * get_loadavg(); /* for IO wait tasks (per cpu!) we add 5x each */ - mult += 10 * nr_iowait_cpu(); + mult += 10 * nr_iowait_cpu(smp_processor_id()); return mult; } diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 5a22ca6927e5..7c3747902a37 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -4257,10 +4257,12 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev, struct ppc440spe_adma_chan *chan, int *initcode) { + struct of_device *ofdev; struct device_node *np; int ret; - np = container_of(adev->dev, struct of_device, dev)->node; + ofdev = container_of(adev->dev, struct of_device, dev); + np = ofdev->dev.of_node; if (adev->id != PPC440SPE_XOR_ID) { adev->err_irq = irq_of_parse_and_map(np, 1); if (adev->err_irq == NO_IRQ) { diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index cf17dbb8014f..ac9f7985096d 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1958,20 +1958,20 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) u32 value = 0; int err_sym = 0; - amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value); + if (boot_cpu_data.x86 == 0x10) { - /* F3x180[EccSymbolSize]=1, x8 symbols */ - if (boot_cpu_data.x86 == 0x10 && - boot_cpu_data.x86_model > 7 && - value & BIT(25)) { - err_sym = decode_syndrome(syndrome, x8_vectors, - ARRAY_SIZE(x8_vectors), 8); - return map_err_sym_to_channel(err_sym, 8); - } else { - err_sym = decode_syndrome(syndrome, x4_vectors, - ARRAY_SIZE(x4_vectors), 4); - return map_err_sym_to_channel(err_sym, 4); + amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value); + + /* F3x180[EccSymbolSize]=1 => x8 symbols */ + if (boot_cpu_data.x86_model > 7 && + value & BIT(25)) { + err_sym = decode_syndrome(syndrome, x8_vectors, + ARRAY_SIZE(x8_vectors), 8); + return map_err_sym_to_channel(err_sym, 8); + } } + err_sym = decode_syndrome(syndrome, x4_vectors, ARRAY_SIZE(x4_vectors), 4); + return map_err_sym_to_channel(err_sym, 4); } /* diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 6b8b7b41ec5f..cc9357da0e34 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1233,10 +1233,28 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table) for (i = 0; i < MAX_SOCKET_BUSES; i++) pcibios_scan_specific_bus(255-i); } + pci_dev_put(pdev); table++; } } +static unsigned i7core_pci_lastbus(void) +{ + int last_bus = 0, bus; + struct pci_bus *b = NULL; + + while ((b = pci_find_next_bus(b)) != NULL) { + bus = b->number; + debugf0("Found bus %d\n", bus); + if (bus > last_bus) + last_bus = bus; + } + + debugf0("Last bus %d\n", last_bus); + + return last_bus; +} + /* * i7core_get_devices Find and perform 'get' operation on the MCH's * device/functions we want to reference for this driver @@ -1244,7 +1262,8 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table) * Need to 'get' device 16 func 1 and func 2 */ int i7core_get_onedevice(struct pci_dev **prev, int devno, - struct pci_id_descr *dev_descr, unsigned n_devs) + struct pci_id_descr *dev_descr, unsigned n_devs, + unsigned last_bus) { struct i7core_dev *i7core_dev; @@ -1291,10 +1310,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, } bus = pdev->bus->number; - if (bus == 0x3f) - socket = 0; - else - socket = 255 - bus; + socket = last_bus - bus; i7core_dev = get_i7core_dev(socket); if (!i7core_dev) { @@ -1358,17 +1374,21 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, static int i7core_get_devices(struct pci_id_table *table) { - int i, rc; + int i, rc, last_bus; struct pci_dev *pdev = NULL; struct pci_id_descr *dev_descr; + last_bus = i7core_pci_lastbus(); + while (table && table->descr) { dev_descr = table->descr; for (i = 0; i < table->n_devs; i++) { pdev = NULL; do { - rc = i7core_get_onedevice(&pdev, i, &dev_descr[i], - table->n_devs); + rc = i7core_get_onedevice(&pdev, i, + &dev_descr[i], + table->n_devs, + last_bus); if (rc < 0) { if (i == 0) { i = table->n_devs; @@ -1927,21 +1947,26 @@ fail: * 0 for FOUND a device * < 0 for error code */ + +static int probed = 0; + static int __devinit i7core_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int dev_idx = id->driver_data; int rc; struct i7core_dev *i7core_dev; + /* get the pci devices we want to reserve for our use */ + mutex_lock(&i7core_edac_lock); + /* * All memory controllers are allocated at the first pass. */ - if (unlikely(dev_idx >= 1)) + if (unlikely(probed >= 1)) { + mutex_unlock(&i7core_edac_lock); return -EINVAL; - - /* get the pci devices we want to reserve for our use */ - mutex_lock(&i7core_edac_lock); + } + probed++; rc = i7core_get_devices(pci_dev_table); if (unlikely(rc < 0)) @@ -2013,6 +2038,8 @@ static void __devexit i7core_remove(struct pci_dev *pdev) i7core_dev->socket); } } + probed--; + mutex_unlock(&i7core_edac_lock); } diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 9dcb30466ec0..371713ff0266 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -231,7 +231,7 @@ void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) static void fw_card_bm_work(struct work_struct *work) { struct fw_card *card = container_of(work, struct fw_card, work.work); - struct fw_device *root_device; + struct fw_device *root_device, *irm_device; struct fw_node *root_node; unsigned long flags; int root_id, new_root_id, irm_id, local_id; @@ -239,6 +239,7 @@ static void fw_card_bm_work(struct work_struct *work) bool do_reset = false; bool root_device_is_running; bool root_device_is_cmc; + bool irm_is_1394_1995_only; spin_lock_irqsave(&card->lock, flags); @@ -248,12 +249,18 @@ static void fw_card_bm_work(struct work_struct *work) } generation = card->generation; + root_node = card->root_node; fw_node_get(root_node); root_device = root_node->data; root_device_is_running = root_device && atomic_read(&root_device->state) == FW_DEVICE_RUNNING; root_device_is_cmc = root_device && root_device->cmc; + + irm_device = card->irm_node->data; + irm_is_1394_1995_only = irm_device && irm_device->config_rom && + (irm_device->config_rom[2] & 0x000000f0) == 0; + root_id = root_node->node_id; irm_id = card->irm_node->node_id; local_id = card->local_node->node_id; @@ -276,8 +283,15 @@ static void fw_card_bm_work(struct work_struct *work) if (!card->irm_node->link_on) { new_root_id = local_id; - fw_notify("IRM has link off, making local node (%02x) root.\n", - new_root_id); + fw_notify("%s, making local node (%02x) root.\n", + "IRM has link off", new_root_id); + goto pick_me; + } + + if (irm_is_1394_1995_only) { + new_root_id = local_id; + fw_notify("%s, making local node (%02x) root.\n", + "IRM is not 1394a compliant", new_root_id); goto pick_me; } @@ -316,8 +330,8 @@ static void fw_card_bm_work(struct work_struct *work) * root, and thus, IRM. */ new_root_id = local_id; - fw_notify("BM lock failed, making local node (%02x) root.\n", - new_root_id); + fw_notify("%s, making local node (%02x) root.\n", + "BM lock failed", new_root_id); goto pick_me; } } else if (card->bm_generation != generation) { diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 724038dab4ca..7face915b963 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1,5 +1,5 @@ # -# GPIO infrastructure and expanders +# platform-neutral GPIO infrastructure and expanders # config ARCH_WANT_OPTIONAL_GPIOLIB diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 51c3cdd41b5a..e53dcff49b4f 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -1,4 +1,8 @@ -# gpio support: dedicated expander chips, etc +# generic gpio support: dedicated expander chips, etc +# +# NOTE: platform-specific GPIO drivers don't belong in the +# drivers/gpio directory; put them with other platform setup +# code, IRQ controllers, board init, etc. ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 994d23beeb1d..57cea01c4ffb 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1840,8 +1840,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips)); - if (ret) + if (ret) { + ret = -EFAULT; goto out_err2; + } } if (fb->funcs->dirty) { diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index b3779d243aef..1f2cc6b09623 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -146,7 +146,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn cvt = 1; break; case 'R': - if (!cvt) + if (cvt) rb = 1; break; case 'm': @@ -264,7 +264,7 @@ bool drm_fb_helper_force_kernel_mode(void) int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, void *panic_str) { - DRM_ERROR("panic occurred, switching back to text console\n"); + printk(KERN_ERR "panic occurred, switching back to text console\n"); return drm_fb_helper_force_kernel_mode(); return 0; } @@ -1024,11 +1024,18 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne } create_mode: - mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres, - cmdline_mode->yres, - cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, - cmdline_mode->rb, cmdline_mode->interlace, - cmdline_mode->margins); + if (cmdline_mode->cvt) + mode = drm_cvt_mode(fb_helper_conn->connector->dev, + cmdline_mode->xres, cmdline_mode->yres, + cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, + cmdline_mode->rb, cmdline_mode->interlace, + cmdline_mode->margins); + else + mode = drm_gtf_mode(fb_helper_conn->connector->dev, + cmdline_mode->xres, cmdline_mode->yres, + cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, + cmdline_mode->interlace, + cmdline_mode->margins); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); list_add(&mode->head, &fb_helper_conn->connector->modes); return mode; diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 66c697bc9b22..56f66426207f 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -208,7 +208,7 @@ static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo) uint8_t ctl2; if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) { - if (ctl2 & TFP410_CTL_2_HTPLG) + if (ctl2 & TFP410_CTL_2_RSEN) ret = connector_status_connected; else ret = connector_status_disconnected; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 52510ad8b25d..aee83fa178f6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -620,7 +620,7 @@ static int i915_sr_status(struct seq_file *m, void *unused) drm_i915_private_t *dev_priv = dev->dev_private; bool sr_enabled = false; - if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev)) + if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev)) sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN; else if (IS_I915GM(dev)) sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index b2ebf02e4f8a..f00c5ae9556c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -128,9 +128,11 @@ static int i915_dma_cleanup(struct drm_device * dev) if (dev->irq_enabled) drm_irq_uninstall(dev); + mutex_lock(&dev->struct_mutex); intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); if (HAS_BSD(dev)) intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); + mutex_unlock(&dev->struct_mutex); /* Clear the HWS virtual address at teardown */ if (I915_NEED_GFX_HWS(dev)) @@ -1229,7 +1231,7 @@ static void i915_warn_stolen(struct drm_device *dev) static void i915_setup_compression(struct drm_device *dev, int size) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_mm_node *compressed_fb, *compressed_llb; + struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb); unsigned long cfb_base; unsigned long ll_base = 0; @@ -1402,19 +1404,23 @@ static int i915_load_modeset_init(struct drm_device *dev, /* if we have > 1 VGA cards, then disable the radeon VGA resources */ ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); if (ret) - goto destroy_ringbuffer; + goto cleanup_ringbuffer; ret = vga_switcheroo_register_client(dev->pdev, i915_switcheroo_set_state, i915_switcheroo_can_switch); if (ret) - goto destroy_ringbuffer; + goto cleanup_vga_client; + + /* IIR "flip pending" bit means done if this bit is set */ + if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE)) + dev_priv->flip_pending_is_done = true; intel_modeset_init(dev); ret = drm_irq_install(dev); if (ret) - goto destroy_ringbuffer; + goto cleanup_vga_switcheroo; /* Always safe in the mode setting case. */ /* FIXME: do pre/post-mode set stuff in core KMS code */ @@ -1426,11 +1432,20 @@ static int i915_load_modeset_init(struct drm_device *dev, I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); - intel_fbdev_init(dev); + ret = intel_fbdev_init(dev); + if (ret) + goto cleanup_irq; + drm_kms_helper_poll_init(dev); return 0; -destroy_ringbuffer: +cleanup_irq: + drm_irq_uninstall(dev); +cleanup_vga_switcheroo: + vga_switcheroo_unregister_client(dev->pdev); +cleanup_vga_client: + vga_client_register(dev->pdev, NULL, NULL, NULL); +cleanup_ringbuffer: mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9ed8ecd95801..d147ab2f5bfc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -278,6 +278,7 @@ typedef struct drm_i915_private { struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; + int num_pipe; /* For hangcheck timer */ #define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */ @@ -595,6 +596,7 @@ typedef struct drm_i915_private { struct drm_crtc *plane_to_crtc_mapping[2]; struct drm_crtc *pipe_to_crtc_mapping[2]; wait_queue_head_t pending_flip_queue; + bool flip_pending_is_done; /* Reclocking support */ bool render_reclock_avail; @@ -1075,7 +1077,7 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); 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)); \ + intel_ring_begin(dev, &dev_priv->render_ring, (n)); \ } while (0) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9ded3dae6c87..074385882ccf 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2239,7 +2239,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj, mapping = inode->i_mapping; for (i = 0; i < page_count; i++) { page = read_cache_page_gfp(mapping, i, - mapping_gfp_mask (mapping) | + GFP_HIGHUSER | __GFP_COLD | gfpmask); if (IS_ERR(page)) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2479be001e40..dba53d4b9fb3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -940,22 +940,30 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 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) + if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 0); + if (dev_priv->flip_pending_is_done) + intel_finish_page_flip_plane(dev, 0); + } - if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) + if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 1); + if (dev_priv->flip_pending_is_done) + intel_finish_page_flip_plane(dev, 1); + } if (pipea_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 0); - intel_finish_page_flip(dev, 0); + if (!dev_priv->flip_pending_is_done) + intel_finish_page_flip(dev, 0); } if (pipeb_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 1); - intel_finish_page_flip(dev, 1); + if (!dev_priv->flip_pending_is_done) + intel_finish_page_flip(dev, 1); } if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) || @@ -1387,29 +1395,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev) dev_priv->pipestat[1] = 0; if (I915_HAS_HOTPLUG(dev)) { - u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - - /* Note HDMI and DP share bits */ - if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) - hotplug_en |= HDMIB_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) - hotplug_en |= HDMIC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) - hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOB_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) - hotplug_en |= CRT_HOTPLUG_INT_EN; - /* Ignore TV since it's buggy */ - - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ - i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); + dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT; } /* @@ -1427,16 +1416,41 @@ int i915_driver_irq_postinstall(struct drm_device *dev) } I915_WRITE(EMR, error_mask); - /* Disable pipe interrupt enables, clear pending pipe status */ - I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); - I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); - /* Clear pending interrupt status */ - I915_WRITE(IIR, I915_READ(IIR)); - - I915_WRITE(IER, enable_mask); I915_WRITE(IMR, dev_priv->irq_mask_reg); + I915_WRITE(IER, enable_mask); (void) I915_READ(IER); + if (I915_HAS_HOTPLUG(dev)) { + u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); + + /* Note HDMI and DP share bits */ + if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) + hotplug_en |= HDMID_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { + hotplug_en |= CRT_HOTPLUG_INT_EN; + + /* Programming the CRT detection parameters tends + to generate a spurious hotplug event about three + seconds later. So just do it once. + */ + if (IS_G4X(dev)) + hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; + hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; + } + + /* Ignore TV since it's buggy */ + + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + } + opregion_enable_asle(dev); return 0; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64b0a3afd92b..150400f40534 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -178,6 +178,7 @@ #define MI_OVERLAY_OFF (0x2<<21) #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ @@ -368,6 +369,9 @@ #define CM0_RC_OP_FLUSH_DISABLE (1<<0) #define BB_ADDR 0x02140 /* 8 bytes */ #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ +#define ECOSKPD 0x021d0 +#define ECO_GATING_CX_ONLY (1<<3) +#define ECO_FLIP_DONE (1<<0) /* GEN6 interrupt control */ #define GEN6_RENDER_HWSTAM 0x2098 @@ -1130,7 +1134,6 @@ #define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) #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 PORT_HOTPLUG_STAT 0x61114 #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 22ff38455731..ee0732b222a1 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -234,14 +234,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) else tries = 1; hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN); - hotplug_en &= CRT_HOTPLUG_MASK; hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; - if (IS_G4X(dev)) - hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - - hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; - for (i = 0; i < tries ; i++) { unsigned long timeout; /* turn on the FORCE_DETECT */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 04e1bb499ff8..68dcf36e2793 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2970,11 +2970,13 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, if (srwm < 0) srwm = 1; srwm &= 0x3f; - I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + if (IS_I965GM(dev)) + I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); } else { /* Turn off self refresh if both pipes are enabled */ - I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) - & ~FW_BLC_SELF_EN); + if (IS_I965GM(dev)) + I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) + & ~FW_BLC_SELF_EN); } DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", @@ -3653,6 +3655,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, pipeconf &= ~PIPEACONF_DOUBLE_WIDE; } + dspcntr |= DISPLAY_PLANE_ENABLE; + pipeconf |= PIPEACONF_ENABLE; + dpll |= DPLL_VCO_ENABLE; + + /* Disable the panel fitter if it was on our pipe */ if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe) I915_WRITE(PFIT_CONTROL, 0); @@ -4478,6 +4485,7 @@ static void intel_idle_update(struct work_struct *work) struct drm_device *dev = dev_priv->dev; struct drm_crtc *crtc; struct intel_crtc *intel_crtc; + int enabled = 0; if (!i915_powersave) return; @@ -4486,21 +4494,22 @@ static void intel_idle_update(struct work_struct *work) 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); - } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { /* Skip inactive CRTCs */ if (!crtc->fb) continue; + enabled++; intel_crtc = to_intel_crtc(crtc); if (!intel_crtc->busy) intel_decrease_pllclock(crtc); } + if ((enabled == 1) && (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); + } + mutex_unlock(&dev->struct_mutex); } @@ -4596,10 +4605,10 @@ static void intel_unpin_work_fn(struct work_struct *__work) kfree(work); } -void intel_finish_page_flip(struct drm_device *dev, int pipe) +static void do_intel_finish_page_flip(struct drm_device *dev, + struct drm_crtc *crtc) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; struct drm_i915_gem_object *obj_priv; @@ -4643,6 +4652,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) schedule_work(&work->work); } +void intel_finish_page_flip(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + + do_intel_finish_page_flip(dev, crtc); +} + +void intel_finish_page_flip_plane(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; + + do_intel_finish_page_flip(dev, crtc); +} + void intel_prepare_page_flip(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -4673,6 +4698,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, unsigned long flags; int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; int ret, pipesrc; + u32 flip_mask; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -4726,15 +4752,28 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, atomic_inc(&obj_priv->pending_flip); work->pending_flip_obj = obj; + if (intel_crtc->plane) + flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; + else + flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT; + + /* Wait for any previous flip to finish */ + if (IS_GEN3(dev)) + while (I915_READ(ISR) & flip_mask) + ; + BEGIN_LP_RING(4); - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch); if (IS_I965G(dev)) { + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); pipesrc = I915_READ(pipesrc_reg); OUT_RING(pipesrc & 0x0fff0fff); } else { + OUT_RING(MI_DISPLAY_FLIP_I915 | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); OUT_RING(obj_priv->gtt_offset); OUT_RING(MI_NOOP); } @@ -5470,7 +5509,6 @@ static void intel_init_display(struct drm_device *dev) void intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int num_pipe; int i; drm_mode_config_init(dev); @@ -5500,13 +5538,13 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); if (IS_MOBILE(dev) || IS_I9XX(dev)) - num_pipe = 2; + dev_priv->num_pipe = 2; else - num_pipe = 1; + dev_priv->num_pipe = 1; DRM_DEBUG_KMS("%d display pipe%s available.\n", - num_pipe, num_pipe > 1 ? "s" : ""); + dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); - for (i = 0; i < num_pipe; i++) { + for (i = 0; i < dev_priv->num_pipe; i++) { intel_crtc_init(dev, i); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 49b54f05d3cf..1aac59e83bff 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -136,6 +136,12 @@ intel_dp_link_required(struct drm_device *dev, } static int +intel_dp_max_data_rate(int max_link_clock, int max_lanes) +{ + return (max_link_clock * max_lanes * 8) / 10; +} + +static int intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { @@ -144,8 +150,11 @@ intel_dp_mode_valid(struct drm_connector *connector, int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder)); int max_lanes = intel_dp_max_lane_count(intel_encoder); - if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock) - > max_link_clock * max_lanes) + /* only refuse the mode on non eDP since we have seen some wierd eDP panels + which are outside spec tolerances but somehow work by magic */ + if (!IS_eDP(intel_encoder) && + (intel_dp_link_required(connector->dev, intel_encoder, mode->clock) + > intel_dp_max_data_rate(max_link_clock, max_lanes))) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -506,7 +515,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (clock = 0; clock <= max_clock; clock++) { - int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; + int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock) <= link_avail) { @@ -521,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, } } } + + if (IS_eDP(intel_encoder)) { + /* okay we failed just pick the highest */ + dp_priv->lane_count = max_lane_count; + dp_priv->link_bw = bws[max_clock]; + adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); + DRM_DEBUG_KMS("Force picking display port link bw %02x lane " + "count %d clock %d\n", + dp_priv->link_bw, dp_priv->lane_count, + adjusted_mode->clock); + return true; + } return false; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index df931f787665..72206f37c4fb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -224,6 +224,7 @@ extern void intel_fbdev_fini(struct drm_device *dev); extern void intel_prepare_page_flip(struct drm_device *dev, int plane); extern void intel_finish_page_flip(struct drm_device *dev, int pipe); +extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); extern void intel_setup_overlay(struct drm_device *dev); extern void intel_cleanup_overlay(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index f8c76e64bb77..c3c505244e07 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -245,6 +245,7 @@ int intel_fbdev_init(struct drm_device *dev) { struct intel_fbdev *ifbdev; drm_i915_private_t *dev_priv = dev->dev_private; + int ret; ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); if (!ifbdev) @@ -253,8 +254,13 @@ int intel_fbdev_init(struct drm_device *dev) dev_priv->fbdev = ifbdev; ifbdev->helper.funcs = &intel_fb_helper_funcs; - drm_fb_helper_init(dev, &ifbdev->helper, 2, - INTELFB_CONN_LIMIT); + ret = drm_fb_helper_init(dev, &ifbdev->helper, + dev_priv->num_pipe, + INTELFB_CONN_LIMIT); + if (ret) { + kfree(ifbdev); + return ret; + } drm_fb_helper_single_add_all_connectors(&ifbdev->helper); drm_fb_helper_initial_config(&ifbdev->helper, 32); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 6a1accd83aec..31df55f0a0a7 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -983,8 +983,8 @@ void intel_lvds_init(struct drm_device *dev) drm_connector_attach_property(&intel_connector->base, dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; + DRM_MODE_SCALE_ASPECT); + lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT; /* * LVDS discovery: * 1) check for EDID on DDC diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index cea4f1a8709e..26362f8495a8 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -94,7 +94,7 @@ render_ring_flush(struct drm_device *dev, #if WATCH_EXEC DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd); #endif - intel_ring_begin(dev, ring, 8); + intel_ring_begin(dev, ring, 2); intel_ring_emit(dev, ring, cmd); intel_ring_emit(dev, ring, MI_NOOP); intel_ring_advance(dev, ring); @@ -358,7 +358,7 @@ bsd_ring_flush(struct drm_device *dev, u32 invalidate_domains, u32 flush_domains) { - intel_ring_begin(dev, ring, 8); + intel_ring_begin(dev, ring, 2); intel_ring_emit(dev, ring, MI_FLUSH); intel_ring_emit(dev, ring, MI_NOOP); intel_ring_advance(dev, ring); @@ -687,6 +687,7 @@ int intel_wrap_ring_buffer(struct drm_device *dev, *virt++ = MI_NOOP; ring->tail = 0; + ring->space = ring->head - 8; return 0; } @@ -721,8 +722,9 @@ int intel_wait_ring_buffer(struct drm_device *dev, } void intel_ring_begin(struct drm_device *dev, - struct intel_ring_buffer *ring, int n) + struct intel_ring_buffer *ring, int num_dwords) { + int n = 4*num_dwords; if (unlikely(ring->tail + n > ring->size)) intel_wrap_ring_buffer(dev, ring); if (unlikely(ring->space < n)) @@ -752,7 +754,7 @@ void intel_fill_struct(struct drm_device *dev, { unsigned int *virt = ring->virtual_start + ring->tail; BUG_ON((len&~(4-1)) != 0); - intel_ring_begin(dev, ring, len); + intel_ring_begin(dev, ring, len/4); memcpy(virt, data, len); ring->tail += len; ring->tail &= ring->size - 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 9ba2deaadcc7..fc924b649195 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -834,7 +834,7 @@ init_i2c_device_find(struct drm_device *dev, int i2c_index) if (i2c_index == 0x81) i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; - if (i2c_index > DCB_MAX_NUM_I2C_ENTRIES) { + if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) { NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); return NULL; } @@ -3920,7 +3920,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b static uint8_t * bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, - uint16_t record, int record_len, int record_nr) + uint16_t record, int record_len, int record_nr, + bool match_link) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvbios *bios = &dev_priv->vbios; @@ -3928,12 +3929,28 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, uint16_t table; int i, v; + switch (dcbent->type) { + case OUTPUT_TMDS: + case OUTPUT_LVDS: + case OUTPUT_DP: + break; + default: + match_link = false; + break; + } + for (i = 0; i < record_nr; i++, record += record_len) { table = ROM16(bios->data[record]); if (!table) continue; entry = ROM32(bios->data[table]); + if (match_link) { + v = (entry & 0x00c00000) >> 22; + if (!(v & dcbent->sorconf.link)) + continue; + } + v = (entry & 0x000f0000) >> 16; if (!(v & dcbent->or)) continue; @@ -3975,7 +3992,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, *length = table[4]; return bios_output_config_match(dev, dcbent, bios->display.dp_table_ptr + table[1], - table[2], table[3]); + table[2], table[3], table[0] >= 0x21); } int @@ -4064,7 +4081,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, dcbent->type, dcbent->location, dcbent->or); otable = bios_output_config_match(dev, dcbent, table[1] + bios->display.script_table_ptr, - table[2], table[3]); + table[2], table[3], table[0] >= 0x21); if (!otable) { NV_ERROR(dev, "Couldn't find matching output script table\n"); return 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index fd4a2df715e9..c9a4a0d2a115 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -377,6 +377,7 @@ int nouveau_fbcon_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fbdev *nfbdev; + int ret; nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); if (!nfbdev) @@ -386,7 +387,12 @@ int nouveau_fbcon_init(struct drm_device *dev) dev_priv->nfbdev = nfbdev; nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; - drm_fb_helper_init(dev, &nfbdev->helper, 2, 4); + ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4); + if (ret) { + kfree(nfbdev); + return ret; + } + drm_fb_helper_single_add_all_connectors(&nfbdev->helper); drm_fb_helper_initial_config(&nfbdev->helper, 32); return 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 147e59c40151..b02a231d6937 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -779,29 +779,24 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) return ret; } - /* map larger RAMIN aperture on NV40 cards */ - dev_priv->ramin = NULL; + /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ if (dev_priv->card_type >= NV_40) { int ramin_bar = 2; if (pci_resource_len(dev->pdev, ramin_bar) == 0) ramin_bar = 3; dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar); - dev_priv->ramin = ioremap( - pci_resource_start(dev->pdev, ramin_bar), + dev_priv->ramin = + ioremap(pci_resource_start(dev->pdev, ramin_bar), dev_priv->ramin_size); if (!dev_priv->ramin) { - NV_ERROR(dev, "Failed to init RAMIN mapping, " - "limited instance memory available\n"); + NV_ERROR(dev, "Failed to PRAMIN BAR"); + return -ENOMEM; } - } - - /* On older cards (or if the above failed), create a map covering - * the BAR0 PRAMIN aperture */ - if (!dev_priv->ramin) { + } else { dev_priv->ramin_size = 1 * 1024 * 1024; dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN, - dev_priv->ramin_size); + dev_priv->ramin_size); if (!dev_priv->ramin) { NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c index a95e6941ba88..32611bd30e6d 100644 --- a/drivers/gpu/drm/nouveau/nv50_fb.c +++ b/drivers/gpu/drm/nouveau/nv50_fb.c @@ -6,10 +6,16 @@ int nv50_fb_init(struct drm_device *dev) { - /* This is needed to get meaningful information from 100c90 - * on traps. No idea what these values mean exactly. */ struct drm_nouveau_private *dev_priv = dev->dev_private; + /* Not a clue what this is exactly. Without pointing it at a + * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) + * cause IOMMU "read from address 0" errors (rh#561267) + */ + nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8); + + /* This is needed to get meaningful information from 100c90 + * on traps. No idea what these values mean exactly. */ switch (dev_priv->chipset) { case 0x50: nv_wr32(dev, 0x100c90, 0x0707ff); diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index c61782b314e7..bb47ad737267 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -31,7 +31,7 @@ nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) { const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; - if (gpio->line > 32) + if (gpio->line >= 32) return -EINVAL; *reg = nv50_gpio_reg[gpio->line >> 3]; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f3f2827017ef..8c2d6478a221 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -498,7 +498,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if ((rdev->family == CHIP_RS600) || (rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) - pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV | + pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/ RADEON_PLL_PREFER_CLOSEST_LOWER); if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0440c0939bdd..1caf625e472b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -41,12 +41,18 @@ void evergreen_fini(struct radeon_device *rdev); void evergreen_pm_misc(struct radeon_device *rdev) { - int requested_index = rdev->pm.requested_power_state_index; - struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; - struct radeon_voltage *voltage = &ps->clock_info[0].voltage; - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) - radeon_atom_set_voltage(rdev, voltage->voltage); + int req_ps_idx = rdev->pm.requested_power_state_index; + int req_cm_idx = rdev->pm.requested_clock_mode_index; + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: v: %d\n", voltage->voltage); + } + } } void evergreen_pm_prepare(struct radeon_device *rdev) @@ -601,7 +607,7 @@ static void evergreen_mc_program(struct radeon_device *rdev) WREG32(MC_VM_FB_LOCATION, tmp); WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7)); - WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); if (rdev->flags & RADEON_IS_AGP) { WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16); WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); @@ -1216,11 +1222,11 @@ static void evergreen_gpu_init(struct radeon_device *rdev) ps_thread_count = 128; sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count); - sq_thread_resource_mgmt |= NUM_VS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; - sq_thread_resource_mgmt |= NUM_GS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; - sq_thread_resource_mgmt |= NUM_ES_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; - sq_thread_resource_mgmt_2 = NUM_HS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; - sq_thread_resource_mgmt_2 |= NUM_LS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; + sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); + sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); @@ -1254,6 +1260,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(VGT_GS_VERTEX_REUSE, 16); WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14); + WREG32(VGT_OUT_DEALLOC_CNTL, 16); + WREG32(CB_PERF_CTR0_SEL_0, 0); WREG32(CB_PERF_CTR0_SEL_1, 0); WREG32(CB_PERF_CTR1_SEL_0, 0); @@ -1263,6 +1272,26 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(CB_PERF_CTR3_SEL_0, 0); WREG32(CB_PERF_CTR3_SEL_1, 0); + /* clear render buffer base addresses */ + WREG32(CB_COLOR0_BASE, 0); + WREG32(CB_COLOR1_BASE, 0); + WREG32(CB_COLOR2_BASE, 0); + WREG32(CB_COLOR3_BASE, 0); + WREG32(CB_COLOR4_BASE, 0); + WREG32(CB_COLOR5_BASE, 0); + WREG32(CB_COLOR6_BASE, 0); + WREG32(CB_COLOR7_BASE, 0); + WREG32(CB_COLOR8_BASE, 0); + WREG32(CB_COLOR9_BASE, 0); + WREG32(CB_COLOR10_BASE, 0); + WREG32(CB_COLOR11_BASE, 0); + + /* set the shader const cache sizes to 0 */ + for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4) + WREG32(i, 0); + for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) + WREG32(i, 0); + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); @@ -2153,7 +2182,7 @@ int evergreen_init(struct radeon_device *rdev) if (r) return r; - rdev->accel_working = false; + rdev->accel_working = true; r = evergreen_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 64516b950891..010963d4570f 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -1197,7 +1197,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, DRM_ERROR("bad SET_RESOURCE (tex)\n"); return -EINVAL; } - ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) @@ -1209,7 +1209,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, DRM_ERROR("bad SET_RESOURCE (tex)\n"); return -EINVAL; } - ib[idx+1+(i*8)+4] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); mipmap = reloc->robj; r = evergreen_check_texture_resource(p, idx+1+(i*8), texture, mipmap); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 79683f6b4452..a1cd621780e2 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -713,6 +713,9 @@ #define SQ_GSVS_RING_OFFSET_2 0x28930 #define SQ_GSVS_RING_OFFSET_3 0x28934 +#define SQ_ALU_CONST_BUFFER_SIZE_PS_0 0x28140 +#define SQ_ALU_CONST_BUFFER_SIZE_HS_0 0x28f80 + #define SQ_ALU_CONST_CACHE_PS_0 0x28940 #define SQ_ALU_CONST_CACHE_PS_1 0x28944 #define SQ_ALU_CONST_CACHE_PS_2 0x28948 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index cc004b05d63e..3970e62eaab8 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -162,6 +162,11 @@ void r100_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; @@ -172,6 +177,11 @@ void r100_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; @@ -1618,6 +1628,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p, case RADEON_TXFORMAT_RGB332: case RADEON_TXFORMAT_Y8: track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case RADEON_TXFORMAT_AI88: case RADEON_TXFORMAT_ARGB1555: @@ -1629,12 +1640,14 @@ static int r100_packet0_check(struct radeon_cs_parser *p, case RADEON_TXFORMAT_LDUDV655: case RADEON_TXFORMAT_DUDV88: track->textures[i].cpp = 2; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case RADEON_TXFORMAT_ARGB8888: case RADEON_TXFORMAT_RGBA8888: case RADEON_TXFORMAT_SHADOW32: case RADEON_TXFORMAT_LDUDUV8888: track->textures[i].cpp = 4; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case RADEON_TXFORMAT_DXT1: track->textures[i].cpp = 1; @@ -2594,12 +2607,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg, int surf_index = reg * 16; int flags = 0; - /* r100/r200 divide by 16 */ - if (rdev->family < CHIP_R300) - flags = pitch / 16; - else - flags = pitch / 8; - if (rdev->family <= CHIP_RS200) { if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) @@ -2623,6 +2630,20 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg, if (tiling_flags & RADEON_TILING_SWAP_32BIT) flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; + /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */ + if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) { + if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) + if (ASIC_IS_RN50(rdev)) + pitch /= 16; + } + + /* r100/r200 divide by 16 */ + if (rdev->family < CHIP_R300) + flags |= pitch / 16; + else + flags |= pitch / 8; + + DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); WREG32(RADEON_SURFACE0_INFO + surf_index, flags); WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); @@ -3137,33 +3158,6 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t) DRM_ERROR("compress format %d\n", t->compress_format); } -static int r100_cs_track_cube(struct radeon_device *rdev, - struct r100_cs_track *track, unsigned idx) -{ - unsigned face, w, h; - struct radeon_bo *cube_robj; - unsigned long size; - - for (face = 0; face < 5; face++) { - cube_robj = track->textures[idx].cube_info[face].robj; - w = track->textures[idx].cube_info[face].width; - h = track->textures[idx].cube_info[face].height; - - size = w * h; - size *= track->textures[idx].cpp; - - size += track->textures[idx].cube_info[face].offset; - - if (size > radeon_bo_size(cube_robj)) { - DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", - size, radeon_bo_size(cube_robj)); - r100_cs_track_texture_print(&track->textures[idx]); - return -1; - } - } - return 0; -} - static int r100_track_compress_size(int compress_format, int w, int h) { int block_width, block_height, block_bytes; @@ -3194,6 +3188,37 @@ static int r100_track_compress_size(int compress_format, int w, int h) return sz; } +static int r100_cs_track_cube(struct radeon_device *rdev, + struct r100_cs_track *track, unsigned idx) +{ + unsigned face, w, h; + struct radeon_bo *cube_robj; + unsigned long size; + unsigned compress_format = track->textures[idx].compress_format; + + for (face = 0; face < 5; face++) { + cube_robj = track->textures[idx].cube_info[face].robj; + w = track->textures[idx].cube_info[face].width; + h = track->textures[idx].cube_info[face].height; + + if (compress_format) { + size = r100_track_compress_size(compress_format, w, h); + } else + size = w * h; + size *= track->textures[idx].cpp; + + size += track->textures[idx].cube_info[face].offset; + + if (size > radeon_bo_size(cube_robj)) { + DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", + size, radeon_bo_size(cube_robj)); + r100_cs_track_texture_print(&track->textures[idx]); + return -1; + } + } + return 0; +} + static int r100_cs_track_texture_check(struct radeon_device *rdev, struct r100_cs_track *track) { diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index 85617c311212..0266d72e0a4c 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -415,6 +415,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, /* 2D, 3D, CUBE */ switch (tmp) { case 0: + case 3: + case 4: case 5: case 6: case 7: @@ -450,6 +452,7 @@ int r200_packet0_check(struct radeon_cs_parser *p, case R200_TXFORMAT_RGB332: case R200_TXFORMAT_Y8: track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R200_TXFORMAT_AI88: case R200_TXFORMAT_ARGB1555: @@ -461,6 +464,7 @@ int r200_packet0_check(struct radeon_cs_parser *p, case R200_TXFORMAT_DVDU88: case R200_TXFORMAT_AVYU4444: track->textures[i].cpp = 2; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R200_TXFORMAT_ARGB8888: case R200_TXFORMAT_RGBA8888: @@ -468,6 +472,7 @@ int r200_packet0_check(struct radeon_cs_parser *p, case R200_TXFORMAT_BGR111110: case R200_TXFORMAT_LDVDU8888: track->textures[i].cpp = 4; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R200_TXFORMAT_DXT1: track->textures[i].cpp = 1; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index b2f9efe2897c..7e81db5eb804 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -881,6 +881,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, case R300_TX_FORMAT_Y4X4: case R300_TX_FORMAT_Z3Y3X2: track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R300_TX_FORMAT_X16: case R300_TX_FORMAT_Y8X8: @@ -892,6 +893,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, case R300_TX_FORMAT_B8G8_B8G8: case R300_TX_FORMAT_G8R8_G8B8: track->textures[i].cpp = 2; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R300_TX_FORMAT_Y16X16: case R300_TX_FORMAT_Z11Y11X10: @@ -902,14 +904,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p, case R300_TX_FORMAT_FL_I32: case 0x1e: track->textures[i].cpp = 4; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R300_TX_FORMAT_W16Z16Y16X16: case R300_TX_FORMAT_FL_R16G16B16A16: case R300_TX_FORMAT_FL_I32A32: track->textures[i].cpp = 8; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R300_TX_FORMAT_FL_R32G32B32A32: track->textures[i].cpp = 16; + track->textures[i].compress_format = R100_TRACK_COMP_NONE; break; case R300_TX_FORMAT_DXT1: track->textures[i].cpp = 1; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 4415a5ee5871..e6c89142bb4d 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -45,9 +45,14 @@ void r420_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; /* low sh */ rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; @@ -58,6 +63,11 @@ void r420_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e14f59748e65..3d6645ce2151 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -130,9 +130,14 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev) break; } } - } else - rdev->pm.requested_power_state_index = - rdev->pm.current_power_state_index - 1; + } else { + if (rdev->pm.current_power_state_index == 0) + rdev->pm.requested_power_state_index = + rdev->pm.num_power_states - 1; + else + rdev->pm.requested_power_state_index = + rdev->pm.current_power_state_index - 1; + } } rdev->pm.requested_clock_mode_index = 0; /* don't use the power state if crtcs are active and no display flag is set */ @@ -291,6 +296,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; @@ -301,6 +311,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1; @@ -317,6 +332,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2; @@ -327,6 +347,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; @@ -343,6 +368,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3; @@ -353,6 +383,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3; @@ -375,6 +410,11 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; @@ -385,6 +425,11 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* mid mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; @@ -401,7 +446,12 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + /* mid sh */ + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; @@ -411,7 +461,12 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + /* low mh */ + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; @@ -430,14 +485,30 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; } else { rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + } + /* mid sh */ + if (rdev->flags & RADEON_IS_MOBILITY) { + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; + } else { + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; } /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = @@ -453,14 +524,30 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; } else { rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + } + /* mid mh */ + if (rdev->flags & RADEON_IS_MOBILITY) { + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; + } else { + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = + r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; } /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = @@ -475,13 +562,18 @@ void r600_pm_init_profile(struct radeon_device *rdev) void r600_pm_misc(struct radeon_device *rdev) { - int requested_index = rdev->pm.requested_power_state_index; - struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; - struct radeon_voltage *voltage = &ps->clock_info[0].voltage; - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) - radeon_atom_set_voltage(rdev, voltage->voltage); + int req_ps_idx = rdev->pm.requested_power_state_index; + int req_cm_idx = rdev->pm.requested_clock_mode_index; + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: v: %d\n", voltage->voltage); + } + } } bool r600_gui_idle(struct radeon_device *rdev) @@ -1010,7 +1102,7 @@ static void r600_mc_program(struct radeon_device *rdev) WREG32(MC_VM_FB_LOCATION, tmp); WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7)); - WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); if (rdev->flags & RADEON_IS_AGP) { WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22); WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); @@ -1132,8 +1224,10 @@ int r600_mc_init(struct radeon_device *rdev) rdev->mc.visible_vram_size = rdev->mc.aper_size; r600_vram_gtt_location(rdev, &rdev->mc); - if (rdev->flags & RADEON_IS_IGP) + if (rdev->flags & RADEON_IS_IGP) { + rs690_pm_info(rdev); rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + } radeon_update_bandwidth_info(rdev); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5f96fe871b3f..ab61aaa887bb 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -177,6 +177,7 @@ void radeon_pm_resume(struct radeon_device *rdev); void radeon_combios_get_power_modes(struct radeon_device *rdev); void radeon_atombios_get_power_modes(struct radeon_device *rdev); void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level); +void rs690_pm_info(struct radeon_device *rdev); /* * Fences. @@ -619,7 +620,8 @@ enum radeon_dynpm_state { DYNPM_STATE_DISABLED, DYNPM_STATE_MINIMUM, DYNPM_STATE_PAUSED, - DYNPM_STATE_ACTIVE + DYNPM_STATE_ACTIVE, + DYNPM_STATE_SUSPENDED, }; enum radeon_dynpm_action { DYNPM_ACTION_NONE, @@ -648,15 +650,18 @@ enum radeon_pm_profile_type { PM_PROFILE_DEFAULT, PM_PROFILE_AUTO, PM_PROFILE_LOW, + PM_PROFILE_MID, PM_PROFILE_HIGH, }; #define PM_PROFILE_DEFAULT_IDX 0 #define PM_PROFILE_LOW_SH_IDX 1 -#define PM_PROFILE_HIGH_SH_IDX 2 -#define PM_PROFILE_LOW_MH_IDX 3 -#define PM_PROFILE_HIGH_MH_IDX 4 -#define PM_PROFILE_MAX 5 +#define PM_PROFILE_MID_SH_IDX 2 +#define PM_PROFILE_HIGH_SH_IDX 3 +#define PM_PROFILE_LOW_MH_IDX 4 +#define PM_PROFILE_MID_MH_IDX 5 +#define PM_PROFILE_HIGH_MH_IDX 6 +#define PM_PROFILE_MAX 7 struct radeon_pm_profile { int dpms_off_ps_idx; @@ -745,6 +750,7 @@ struct radeon_pm { int default_power_state_index; u32 current_sclk; u32 current_mclk; + u32 current_vddc; struct radeon_i2c_chan *i2c_bus; /* selected pm method */ enum radeon_pm_method pm_method; diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 87f7e2cc52d4..646f96f97c77 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -780,6 +780,13 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_R423: case CHIP_RV410: rdev->asic = &r420_asic; + /* handle macs */ + if (rdev->bios == NULL) { + rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock; + rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock; + rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock; + rdev->asic->set_memory_clock = NULL; + } break; case CHIP_RS400: case CHIP_RS480: diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 4305cd55d0ac..99bd8a9c56b3 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1833,10 +1833,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) /* skip invalid modes */ if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) continue; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = - VOLTAGE_SW; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = - clock_info->usVDDC; + /* voltage works differently on IGPs */ mode_index++; } else if (ASIC_IS_DCE4(rdev)) { struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info = @@ -1969,6 +1966,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; rdev->pm.current_clock_mode_index = 0; + rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; } void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index fbba938f8048..2c9213739999 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -48,6 +48,10 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev) resource_size_t vram_base; resource_size_t size = 256 * 1024; /* ??? */ + if (!(rdev->flags & RADEON_IS_IGP)) + if (!radeon_card_posted(rdev)) + return false; + rdev->bios = NULL; vram_base = drm_get_resource_start(rdev->ddev, 0); bios = ioremap(vram_base, size); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 102c744eaf5a..d1c1d8dd93ce 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1411,6 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; } else #endif /* CONFIG_PPC_PMAC */ +#ifdef CONFIG_PPC64 + if (ASIC_IS_RN50(rdev)) + rdev->mode_info.connector_table = CT_RN50_POWER; + else +#endif rdev->mode_info.connector_table = CT_GENERIC; } @@ -1853,6 +1858,33 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_SVIDEO, &hpd); break; + case CT_RN50_POWER: + DRM_INFO("Connector Table: %d (rn50-power)\n", + rdev->mode_info.connector_table); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_id(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_id(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + break; default: DRM_INFO("Connector table: %d (invalid)\n", rdev->mode_info.connector_table); @@ -1906,15 +1938,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, return false; } - /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */ - if (dev->pdev->device == 0x5159 && - dev->pdev->subsystem_vendor == 0x1002 && - dev->pdev->subsystem_device == 0x013a) { - if (*legacy_connector == CONNECTOR_DVI_I_LEGACY) - *legacy_connector = CONNECTOR_CRT_LEGACY; - - } - /* X300 card with extra non-existent DVI port */ if (dev->pdev->device == 0x5B60 && dev->pdev->subsystem_vendor == 0x17af && @@ -2026,6 +2049,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); break; default: + ddc_i2c.valid = false; break; } @@ -2339,6 +2363,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) if (RBIOS8(tv_info + 6) == 'T') { if (radeon_apply_legacy_tv_quirks(dev)) { hpd.hpd = RADEON_HPD_NONE; + ddc_i2c.valid = false; radeon_add_legacy_encoder(dev, radeon_get_encoder_id (dev, @@ -2455,7 +2480,7 @@ default_mode: rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0]; if ((state_index > 0) && - (rdev->pm.power_state[0].clock_info[0].voltage.type = VOLTAGE_GPIO)) + (rdev->pm.power_state[0].clock_info[0].voltage.type == VOLTAGE_GPIO)) rdev->pm.power_state[state_index].clock_info[0].voltage = rdev->pm.power_state[0].clock_info[0].voltage; else @@ -3017,6 +3042,14 @@ void radeon_combios_asic_init(struct drm_device *dev) combios_write_ram_size(dev); } + /* quirk for rs4xx HP nx6125 laptop to make it resume + * - it hangs on resume inside the dynclk 1 table. + */ + if (rdev->family == CHIP_RS480 && + rdev->pdev->subsystem_vendor == 0x103c && + rdev->pdev->subsystem_device == 0x308b) + return; + /* DYN CLK 1 */ table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); if (table) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index b7023fff89eb..4eb67c0e0996 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -194,7 +194,7 @@ unpin: fail: drm_gem_object_unreference_unlocked(obj); - return 0; + return ret; } int radeon_crtc_cursor_move(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f10faed21567..5f317317aba2 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -779,6 +779,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) int radeon_resume_kms(struct drm_device *dev) { + struct drm_connector *connector; struct radeon_device *rdev = dev->dev_private; if (rdev->powered_down) @@ -797,6 +798,12 @@ int radeon_resume_kms(struct drm_device *dev) radeon_resume(rdev); radeon_pm_resume(rdev); radeon_restore_bios_scratch_regs(rdev); + + /* turn on display hw */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + radeon_fbdev_set_suspend(rdev, 0); release_console_sem(); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1006549d1570..8154cdf796e4 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -284,8 +284,7 @@ static const char *connector_names[15] = { "eDP", }; -static const char *hpd_names[7] = { - "NONE", +static const char *hpd_names[6] = { "HPD1", "HPD2", "HPD3", diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 902d1731a652..e166fe4d7c30 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -45,9 +45,10 @@ * - 2.2.0 - add r6xx/r7xx const buffer support * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs * - 2.4.0 - add crtc id query + * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 4 +#define KMS_DRIVER_MINOR 5 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 1ebb100015b7..e0b30b264c28 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1072,6 +1072,8 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (is_dig) { switch (mode) { case DRM_MODE_DPMS_ON: + if (!ASIC_IS_DCE4(rdev)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); @@ -1079,8 +1081,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); } - if (!ASIC_IS_DCE4(rdev)) - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index e192acfbf0cd..dc1634bb0c11 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -363,6 +363,7 @@ int radeon_fbdev_init(struct radeon_device *rdev) { struct radeon_fbdev *rfbdev; int bpp_sel = 32; + int ret; /* select 8 bpp console on RN50 or 16MB cards */ if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024)) @@ -376,9 +377,14 @@ int radeon_fbdev_init(struct radeon_device *rdev) rdev->mode_info.rfbdev = rfbdev; rfbdev->helper.funcs = &radeon_fb_helper_funcs; - drm_fb_helper_init(rdev->ddev, &rfbdev->helper, - rdev->num_crtc, - RADEONFB_CONN_LIMIT); + ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper, + rdev->num_crtc, + RADEONFB_CONN_LIMIT); + if (ret) { + kfree(rfbdev); + return ret; + } + drm_fb_helper_single_add_all_connectors(&rfbdev->helper); drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); return 0; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 04068352ccd2..6a70c0dc7f92 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -118,7 +118,11 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) value = rdev->num_z_pipes; break; case RADEON_INFO_ACCEL_WORKING: - value = rdev->accel_working; + /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ + if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) + value = false; + else + value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: for (i = 0, found = 0; i < rdev->num_crtc; i++) { @@ -134,6 +138,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return -EINVAL; } break; + case RADEON_INFO_ACCEL_WORKING2: + value = rdev->accel_working; + break; default: DRM_DEBUG("Invalid request %d\n", info->request); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 5a13b3eeef19..bad77f40a9da 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -928,16 +928,14 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, if (ASIC_IS_R300(rdev)) { gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1; disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); - } - - if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) - disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); - else + } else if (rdev->family != CHIP_R200) disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); - - if (rdev->family == CHIP_R200) + else if (rdev->family == CHIP_R200) fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + if (rdev->family >= CHIP_R200) + disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); + if (is_tv) { uint32_t dac_cntl; @@ -1002,15 +1000,13 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, if (ASIC_IS_R300(rdev)) { WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); - } + } else if (rdev->family != CHIP_R200) + WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + else if (rdev->family == CHIP_R200) + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); if (rdev->family >= CHIP_R200) WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl); - else - WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); - - if (rdev->family == CHIP_R200) - WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); if (is_tv) radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode); @@ -1168,6 +1164,17 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; bool color = true; + struct drm_crtc *crtc; + + /* find out if crtc2 is in use or if this encoder is using it */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + if ((radeon_crtc->crtc_id == 1) && crtc->enabled) { + if (encoder->crtc != crtc) { + return connector_status_disconnected; + } + } + } if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO || connector->connector_type == DRM_MODE_CONNECTOR_Composite || diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 67358baf28b2..95696aa57ac8 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -206,6 +206,7 @@ enum radeon_connector_table { CT_MINI_INTERNAL, CT_IMAC_G5_ISIGHT, CT_EMAC, + CT_RN50_POWER, }; enum radeon_dvo_chip { diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 02281269a881..115d26b762cc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -33,6 +33,14 @@ #define RADEON_WAIT_VBLANK_TIMEOUT 200 #define RADEON_WAIT_IDLE_TIMEOUT 200 +static const char *radeon_pm_state_type_name[5] = { + "Default", + "Powersave", + "Battery", + "Balanced", + "Performance", +}; + static void radeon_dynpm_idle_work_handler(struct work_struct *work); static int radeon_debugfs_pm_init(struct radeon_device *rdev); static bool radeon_pm_in_vbl(struct radeon_device *rdev); @@ -84,9 +92,9 @@ static void radeon_pm_update_profile(struct radeon_device *rdev) rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX; } else { if (rdev->pm.active_crtc_count > 1) - rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX; + rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX; else - rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; + rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX; } break; case PM_PROFILE_LOW: @@ -95,6 +103,12 @@ static void radeon_pm_update_profile(struct radeon_device *rdev) else rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; break; + case PM_PROFILE_MID: + if (rdev->pm.active_crtc_count > 1) + rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX; + else + rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX; + break; case PM_PROFILE_HIGH: if (rdev->pm.active_crtc_count > 1) rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX; @@ -127,15 +141,6 @@ static void radeon_unmap_vram_bos(struct radeon_device *rdev) if (bo->tbo.mem.mem_type == TTM_PL_VRAM) ttm_bo_unmap_virtual(&bo->tbo); } - - if (rdev->gart.table.vram.robj) - ttm_bo_unmap_virtual(&rdev->gart.table.vram.robj->tbo); - - if (rdev->stollen_vga_memory) - ttm_bo_unmap_virtual(&rdev->stollen_vga_memory->tbo); - - if (rdev->r600_blit.shader_obj) - ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo); } static void radeon_sync_with_vblank(struct radeon_device *rdev) @@ -281,6 +286,42 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) mutex_unlock(&rdev->ddev->struct_mutex); } +static void radeon_pm_print_states(struct radeon_device *rdev) +{ + int i, j; + struct radeon_power_state *power_state; + struct radeon_pm_clock_info *clock_info; + + DRM_DEBUG("%d Power State(s)\n", rdev->pm.num_power_states); + for (i = 0; i < rdev->pm.num_power_states; i++) { + power_state = &rdev->pm.power_state[i]; + DRM_DEBUG("State %d: %s\n", i, + radeon_pm_state_type_name[power_state->type]); + if (i == rdev->pm.default_power_state_index) + DRM_DEBUG("\tDefault"); + if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP)) + DRM_DEBUG("\t%d PCIE Lanes\n", power_state->pcie_lanes); + if (power_state->flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) + DRM_DEBUG("\tSingle display only\n"); + DRM_DEBUG("\t%d Clock Mode(s)\n", power_state->num_clock_modes); + for (j = 0; j < power_state->num_clock_modes; j++) { + clock_info = &(power_state->clock_info[j]); + if (rdev->flags & RADEON_IS_IGP) + DRM_DEBUG("\t\t%d e: %d%s\n", + j, + clock_info->sclk * 10, + clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : ""); + else + DRM_DEBUG("\t\t%d e: %d\tm: %d\tv: %d%s\n", + j, + clock_info->sclk * 10, + clock_info->mclk * 10, + clock_info->voltage.voltage, + clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : ""); + } + } +} + static ssize_t radeon_get_pm_profile(struct device *dev, struct device_attribute *attr, char *buf) @@ -311,6 +352,8 @@ static ssize_t radeon_set_pm_profile(struct device *dev, rdev->pm.profile = PM_PROFILE_AUTO; else if (strncmp("low", buf, strlen("low")) == 0) rdev->pm.profile = PM_PROFILE_LOW; + else if (strncmp("mid", buf, strlen("mid")) == 0) + rdev->pm.profile = PM_PROFILE_MID; else if (strncmp("high", buf, strlen("high")) == 0) rdev->pm.profile = PM_PROFILE_HIGH; else { @@ -354,13 +397,20 @@ static ssize_t radeon_set_pm_method(struct device *dev, rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; mutex_unlock(&rdev->pm.mutex); } else if (strncmp("profile", buf, strlen("profile")) == 0) { + bool flush_wq = false; + mutex_lock(&rdev->pm.mutex); - rdev->pm.pm_method = PM_METHOD_PROFILE; + if (rdev->pm.pm_method == PM_METHOD_DYNPM) { + cancel_delayed_work(&rdev->pm.dynpm_idle_work); + flush_wq = true; + } /* disable dynpm */ rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; - cancel_delayed_work(&rdev->pm.dynpm_idle_work); + rdev->pm.pm_method = PM_METHOD_PROFILE; mutex_unlock(&rdev->pm.mutex); + if (flush_wq) + flush_workqueue(rdev->wq); } else { DRM_ERROR("invalid power method!\n"); goto fail; @@ -375,17 +425,36 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon void radeon_pm_suspend(struct radeon_device *rdev) { + bool flush_wq = false; + mutex_lock(&rdev->pm.mutex); - cancel_delayed_work(&rdev->pm.dynpm_idle_work); - rdev->pm.current_power_state_index = -1; - rdev->pm.current_clock_mode_index = -1; - rdev->pm.current_sclk = 0; - rdev->pm.current_mclk = 0; + if (rdev->pm.pm_method == PM_METHOD_DYNPM) { + cancel_delayed_work(&rdev->pm.dynpm_idle_work); + if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) + rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED; + flush_wq = true; + } mutex_unlock(&rdev->pm.mutex); + if (flush_wq) + flush_workqueue(rdev->wq); } void radeon_pm_resume(struct radeon_device *rdev) { + /* asic init will reset the default power state */ + mutex_lock(&rdev->pm.mutex); + rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; + rdev->pm.current_clock_mode_index = 0; + rdev->pm.current_sclk = rdev->clock.default_sclk; + rdev->pm.current_mclk = rdev->clock.default_mclk; + rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; + if (rdev->pm.pm_method == PM_METHOD_DYNPM + && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { + rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; + queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, + msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); + } + mutex_unlock(&rdev->pm.mutex); radeon_pm_compute_clocks(rdev); } @@ -394,32 +463,24 @@ int radeon_pm_init(struct radeon_device *rdev) int ret; /* default to profile method */ rdev->pm.pm_method = PM_METHOD_PROFILE; + rdev->pm.profile = PM_PROFILE_DEFAULT; rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; rdev->pm.dynpm_can_upclock = true; rdev->pm.dynpm_can_downclock = true; - rdev->pm.current_sclk = 0; - rdev->pm.current_mclk = 0; + rdev->pm.current_sclk = rdev->clock.default_sclk; + rdev->pm.current_mclk = rdev->clock.default_mclk; if (rdev->bios) { if (rdev->is_atom_bios) radeon_atombios_get_power_modes(rdev); else radeon_combios_get_power_modes(rdev); + radeon_pm_print_states(rdev); radeon_pm_init_profile(rdev); - rdev->pm.current_power_state_index = -1; - rdev->pm.current_clock_mode_index = -1; } if (rdev->pm.num_power_states > 1) { - if (rdev->pm.pm_method == PM_METHOD_PROFILE) { - mutex_lock(&rdev->pm.mutex); - rdev->pm.profile = PM_PROFILE_DEFAULT; - radeon_pm_update_profile(rdev); - radeon_pm_set_clocks(rdev); - mutex_unlock(&rdev->pm.mutex); - } - /* where's the best place to put these? */ ret = device_create_file(rdev->dev, &dev_attr_power_profile); if (ret) @@ -447,6 +508,8 @@ int radeon_pm_init(struct radeon_device *rdev) void radeon_pm_fini(struct radeon_device *rdev) { if (rdev->pm.num_power_states > 1) { + bool flush_wq = false; + mutex_lock(&rdev->pm.mutex); if (rdev->pm.pm_method == PM_METHOD_PROFILE) { rdev->pm.profile = PM_PROFILE_DEFAULT; @@ -454,13 +517,16 @@ void radeon_pm_fini(struct radeon_device *rdev) radeon_pm_set_clocks(rdev); } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { /* cancel work */ - cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); + cancel_delayed_work(&rdev->pm.dynpm_idle_work); + flush_wq = true; /* reset default clocks */ rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; radeon_pm_set_clocks(rdev); } mutex_unlock(&rdev->pm.mutex); + if (flush_wq) + flush_workqueue(rdev->wq); device_remove_file(rdev->dev, &dev_attr_power_profile); device_remove_file(rdev->dev, &dev_attr_power_method); @@ -681,12 +747,12 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work) radeon_pm_get_dynpm_state(rdev); radeon_pm_set_clocks(rdev); } + + queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, + msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); } mutex_unlock(&rdev->pm.mutex); ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); - - queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, - msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); } /* @@ -705,6 +771,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); if (rdev->asic->get_memory_clock) seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); + if (rdev->pm.current_vddc) + seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc); if (rdev->asic->get_pcie_lanes) seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index b5c757f68d3c..f78fd592544d 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -80,8 +80,8 @@ evergreen 0x9400 0x00028010 DB_RENDER_OVERRIDE2 0x00028028 DB_STENCIL_CLEAR 0x0002802C DB_DEPTH_CLEAR -0x00028034 PA_SC_SCREEN_SCISSOR_BR 0x00028030 PA_SC_SCREEN_SCISSOR_TL +0x00028034 PA_SC_SCREEN_SCISSOR_BR 0x0002805C DB_DEPTH_SLICE 0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 @@ -460,8 +460,8 @@ evergreen 0x9400 0x00028844 SQ_PGM_RESOURCES_PS 0x00028848 SQ_PGM_RESOURCES_2_PS 0x0002884C SQ_PGM_EXPORTS_PS -0x0002885C SQ_PGM_RESOURCES_VS -0x00028860 SQ_PGM_RESOURCES_2_VS +0x00028860 SQ_PGM_RESOURCES_VS +0x00028864 SQ_PGM_RESOURCES_2_VS 0x00028878 SQ_PGM_RESOURCES_GS 0x0002887C SQ_PGM_RESOURCES_2_GS 0x00028890 SQ_PGM_RESOURCES_ES @@ -469,8 +469,8 @@ evergreen 0x9400 0x000288A8 SQ_PGM_RESOURCES_FS 0x000288BC SQ_PGM_RESOURCES_HS 0x000288C0 SQ_PGM_RESOURCES_2_HS -0x000288D0 SQ_PGM_RESOURCES_LS -0x000288D4 SQ_PGM_RESOURCES_2_LS +0x000288D4 SQ_PGM_RESOURCES_LS +0x000288D8 SQ_PGM_RESOURCES_2_LS 0x000288E8 SQ_LDS_ALLOC 0x000288EC SQ_LDS_ALLOC_PS 0x000288F0 SQ_VTX_SEMANTIC_CLEAR diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index bcc33195ebc2..f4f0a61bcdce 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -79,7 +79,13 @@ void rs690_pm_info(struct radeon_device *rdev) tmp.full = dfixed_const(100); rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock); rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); - rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); + if (info->info.usK8MemoryClock) + rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); + else if (rdev->clock.default_mclk) { + rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); + rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); + } else + rdev->pm.igp_system_mclk.full = dfixed_const(400); rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock)); rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth); break; @@ -87,34 +93,31 @@ void rs690_pm_info(struct radeon_device *rdev) tmp.full = dfixed_const(100); rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock); rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); - rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock); + if (info->info_v2.ulBootUpUMAClock) + rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock); + else if (rdev->clock.default_mclk) + rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); + else + rdev->pm.igp_system_mclk.full = dfixed_const(66700); rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq); rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp); rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth)); break; default: - tmp.full = dfixed_const(100); /* We assume the slower possible clock ie worst case */ - /* DDR 333Mhz */ - rdev->pm.igp_sideport_mclk.full = dfixed_const(333); - /* FIXME: system clock ? */ - rdev->pm.igp_system_mclk.full = dfixed_const(100); - rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); - rdev->pm.igp_ht_link_clk.full = dfixed_const(200); + rdev->pm.igp_sideport_mclk.full = dfixed_const(200); + rdev->pm.igp_system_mclk.full = dfixed_const(200); + rdev->pm.igp_ht_link_clk.full = dfixed_const(1000); rdev->pm.igp_ht_link_width.full = dfixed_const(8); DRM_ERROR("No integrated system info for your GPU, using safe default\n"); break; } } else { - tmp.full = dfixed_const(100); /* We assume the slower possible clock ie worst case */ - /* DDR 333Mhz */ - rdev->pm.igp_sideport_mclk.full = dfixed_const(333); - /* FIXME: system clock ? */ - rdev->pm.igp_system_mclk.full = dfixed_const(100); - rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); - rdev->pm.igp_ht_link_clk.full = dfixed_const(200); + rdev->pm.igp_sideport_mclk.full = dfixed_const(200); + rdev->pm.igp_system_mclk.full = dfixed_const(200); + rdev->pm.igp_ht_link_clk.full = dfixed_const(1000); rdev->pm.igp_ht_link_width.full = dfixed_const(8); DRM_ERROR("No integrated system info for your GPU, using safe default\n"); } @@ -228,10 +231,6 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, fixed20_12 a, b, c; fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; - /* FIXME: detect IGP with sideport memory, i don't think there is any - * such product available - */ - bool sideport = false; if (!crtc->base.enabled) { /* FIXME: wouldn't it better to set priority mark to maximum */ @@ -300,7 +299,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, /* Maximun bandwidth is the minimun bandwidth of all component */ rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; - if (sideport) { + if (rdev->mc.igp_sideport_enabled) { if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && rdev->pm.sideport_bandwidth.full) rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 33952da65340..b7fd82064922 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -44,12 +44,18 @@ void rv770_fini(struct radeon_device *rdev); void rv770_pm_misc(struct radeon_device *rdev) { - int requested_index = rdev->pm.requested_power_state_index; - struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; - struct radeon_voltage *voltage = &ps->clock_info[0].voltage; - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) - radeon_atom_set_voltage(rdev, voltage->voltage); + int req_ps_idx = rdev->pm.requested_power_state_index; + int req_cm_idx = rdev->pm.requested_clock_mode_index; + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: v: %d\n", voltage->voltage); + } + } } /* @@ -218,7 +224,7 @@ static void rv770_mc_program(struct radeon_device *rdev) WREG32(MC_VM_FB_LOCATION, tmp); WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7)); - WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); if (rdev->flags & RADEON_IS_AGP) { WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16); WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ef910694bd63..2f047577b1e3 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -667,7 +667,7 @@ int ttm_get_pages(struct list_head *pages, int flags, { struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); struct page *p = NULL; - int gfp_flags = 0; + int gfp_flags = GFP_USER; int r; /* set zero flag for page allocation if required */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index bdd67cf83315..8e396850513c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -644,6 +644,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, ret = copy_from_user(cmd, user_cmd, arg->command_size); if (unlikely(ret != 0)) { + ret = -EFAULT; DRM_ERROR("Failed copying commands.\n"); goto out_commit; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index f8fbbc67a406..8612378b131e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -597,8 +597,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, ret = copy_from_user(srf->sizes, user_sizes, srf->num_sizes * sizeof(*srf->sizes)); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { + ret = -EFAULT; goto out_err1; + } if (srf->scanout && srf->num_sizes == 1 && @@ -697,9 +699,11 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, if (user_sizes) ret = copy_to_user(user_sizes, srf->sizes, srf->num_sizes * sizeof(*srf->sizes)); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { DRM_ERROR("copy_to_user failed %p %u\n", user_sizes, srf->num_sizes); + ret = -EFAULT; + } out_bad_resource: out_no_reference: ttm_base_object_unref(&base); diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index e880e2c3871d..937983407e2a 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -289,6 +289,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) iattr->s_attr.dev_attr.attr.mode = S_IRUGO; iattr->s_attr.dev_attr.show = show_label; iattr->s_attr.index = k; + sysfs_attr_init(&iattr->s_attr.dev_attr.attr); res = device_create_file(&pdev->dev, &iattr->s_attr.dev_attr); if (res) @@ -303,6 +304,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) iattr->s_attr.dev_attr.attr.mode = S_IRUGO; iattr->s_attr.dev_attr.show = show_amb_temp; iattr->s_attr.index = k; + sysfs_attr_init(&iattr->s_attr.dev_attr.attr); res = device_create_file(&pdev->dev, &iattr->s_attr.dev_attr); if (res) @@ -318,6 +320,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) iattr->s_attr.dev_attr.show = show_amb_min; iattr->s_attr.dev_attr.store = store_amb_min; iattr->s_attr.index = k; + sysfs_attr_init(&iattr->s_attr.dev_attr.attr); res = device_create_file(&pdev->dev, &iattr->s_attr.dev_attr); if (res) @@ -333,6 +336,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) iattr->s_attr.dev_attr.show = show_amb_mid; iattr->s_attr.dev_attr.store = store_amb_mid; iattr->s_attr.index = k; + sysfs_attr_init(&iattr->s_attr.dev_attr.attr); res = device_create_file(&pdev->dev, &iattr->s_attr.dev_attr); if (res) @@ -348,6 +352,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) iattr->s_attr.dev_attr.show = show_amb_max; iattr->s_attr.dev_attr.store = store_amb_max; iattr->s_attr.index = k; + sysfs_attr_init(&iattr->s_attr.dev_attr.attr); res = device_create_file(&pdev->dev, &iattr->s_attr.dev_attr); if (res) @@ -362,6 +367,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) iattr->s_attr.dev_attr.attr.mode = S_IRUGO; iattr->s_attr.dev_attr.show = show_amb_alarm; iattr->s_attr.index = k; + sysfs_attr_init(&iattr->s_attr.dev_attr.attr); res = device_create_file(&pdev->dev, &iattr->s_attr.dev_attr); if (res) diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index 099a2138cdf6..da5a2404cd3e 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -112,11 +112,21 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev) if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3) return false; - /* Differentiate between AM2+ (bad) and AM3 (good) */ + /* DDR3 memory implies socket AM3, which is good */ pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 2), REG_DCT0_CONFIG_HIGH, ®_dram_cfg); - return !(reg_dram_cfg & DDR3_MODE); + if (reg_dram_cfg & DDR3_MODE) + return false; + + /* + * Unfortunately it is possible to run a socket AM3 CPU with DDR2 + * memory. We blacklist all the cores which do exist in socket AM2+ + * format. It still isn't perfect, as RB-C2 cores exist in both AM2+ + * and AM3 formats, but that's the best we can do. + */ + return boot_cpu_data.x86_model < 4 || + (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2); } static int __devinit k10temp_probe(struct pci_dev *pdev, diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 0ceb6d6200a3..f26acdb11681 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -120,7 +120,7 @@ static ssize_t show_temp(struct device *dev, int temp; struct k8temp_data *data = k8temp_update_device(dev); - if (data->swap_core_select) + if (data->swap_core_select && (data->sensorsp & SEL_CORE)) core = core ? 0 : 1; temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index d8fa5d724c57..0f9a4785d798 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -69,7 +69,7 @@ config KEYBOARD_ATARI module will be called atakbd. config KEYBOARD_ATKBD - tristate "AT keyboard" if EMBEDDED || !X86 + tristate "AT keyboard" if EMBEDDED || !X86 || X86_MRST default y select SERIO select SERIO_LIBPS2 diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index e00a1cc79c0a..c19066479057 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c @@ -678,7 +678,7 @@ static const struct file_operations hp_sdc_rtc_fops = { .llseek = no_llseek, .read = hp_sdc_rtc_read, .poll = hp_sdc_rtc_poll, - .unlocked_ioctl = hp_sdc_rtc_ioctl, + .unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl, .open = hp_sdc_rtc_open, .fasync = hp_sdc_rtc_fasync, }; diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 0ac47d2898ec..4b42ffc0532a 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -69,7 +69,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id) unsigned char nextstate = read_state(lp); if (lp->laststate != nextstate) { - int key_down = nextstate <= ARRAY_SIZE(lp->btncode); + int key_down = nextstate < ARRAY_SIZE(lp->btncode); unsigned short keycode = key_down ? lp->btncode[nextstate] : lp->btncode[lp->laststate]; diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 3bfe8fafc6ad..256b9e9394dc 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -22,7 +22,7 @@ config SERIO_I8042 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ - (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN + (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !X86_MRST help i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index d564af58175c..415f6306105d 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -284,12 +284,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (data[4] << 20) + (data[5] << 12) + (data[6] << 4) + (data[7] >> 4); - wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); + wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | + ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12); - switch (wacom->id[idx]) { + switch (wacom->id[idx] & 0xfffff) { case 0x812: /* Inking pen */ case 0x801: /* Intuos3 Inking pen */ - case 0x20802: /* Intuos4 Classic Pen */ + case 0x20802: /* Intuos4 Inking Pen */ case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL; break; @@ -513,7 +514,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); - if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | + if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) | data[2] | (data[3] & 0x1f) | data[4] | data[8] | (data[7] & 0x01)) { input_report_key(input, wacom->tool[1], 1); diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 0d2d7e54b465..5f0221cffef9 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -679,6 +679,13 @@ static int __devinit ad7877_probe(struct spi_device *spi) return -EINVAL; } + spi->bits_per_word = 16; + err = spi_setup(spi); + if (err) { + dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n"); + return err; + } + ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL); input_dev = input_allocate_device(); if (!ts || !input_dev) { diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index c5016bd2d94f..c3b1dc3a13a0 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) return numbytes; } -/* set up next receive skb for data mode - */ -static void new_rcv_skb(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - unsigned short hw_hdr_len = cs->hw_hdr_len; - - if (bcs->ignore) { - bcs->skb = NULL; - return; - } - - bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len); - if (bcs->skb == NULL) { - dev_warn(cs->dev, "could not allocate new skb\n"); - return; - } - skb_reserve(bcs->skb, hw_hdr_len); -} - /* process a block of received bytes in HDLC data mode * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. @@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) struct cardstate *cs = inbuf->cs; struct bc_state *bcs = cs->bcs; int inputstate = bcs->inputstate; - __u16 fcs = bcs->fcs; - struct sk_buff *skb = bcs->skb; + __u16 fcs = bcs->rx_fcs; + struct sk_buff *skb = bcs->rx_skb; unsigned char *src = inbuf->data + inbuf->head; unsigned procbytes = 0; unsigned char c; @@ -245,8 +225,7 @@ byte_stuff: /* prepare reception of next frame */ inputstate &= ~INS_have_data; - new_rcv_skb(bcs); - skb = bcs->skb; + skb = gigaset_new_rx_skb(bcs); } else { /* empty frame (7E 7E) */ #ifdef CONFIG_GIGASET_DEBUG @@ -255,8 +234,7 @@ byte_stuff: if (!skb) { /* skipped (?) */ gigaset_isdn_rcv_err(bcs); - new_rcv_skb(bcs); - skb = bcs->skb; + skb = gigaset_new_rx_skb(bcs); } } @@ -279,11 +257,11 @@ byte_stuff: #endif inputstate |= INS_have_data; if (skb) { - if (skb->len == SBUFSIZE) { + if (skb->len >= bcs->rx_bufsize) { dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); /* skip remainder of packet */ - bcs->skb = skb = NULL; + bcs->rx_skb = skb = NULL; } else { *__skb_put(skb, 1) = c; fcs = crc_ccitt_byte(fcs, c); @@ -292,7 +270,7 @@ byte_stuff: } bcs->inputstate = inputstate; - bcs->fcs = fcs; + bcs->rx_fcs = fcs; return procbytes; } @@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) struct cardstate *cs = inbuf->cs; struct bc_state *bcs = cs->bcs; int inputstate = bcs->inputstate; - struct sk_buff *skb = bcs->skb; + struct sk_buff *skb = bcs->rx_skb; unsigned char *src = inbuf->data + inbuf->head; unsigned procbytes = 0; unsigned char c; if (!skb) { /* skip this block */ - new_rcv_skb(bcs); + gigaset_new_rx_skb(bcs); return numbytes; } - while (procbytes < numbytes && skb->len < SBUFSIZE) { + while (procbytes < numbytes && skb->len < bcs->rx_bufsize) { c = *src++; procbytes++; @@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) if (inputstate & INS_have_data) { gigaset_skb_rcvd(bcs, skb); inputstate &= ~INS_have_data; - new_rcv_skb(bcs); + gigaset_new_rx_skb(bcs); } bcs->inputstate = inputstate; diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 8f78f15c8ef7..6fbe8999c419 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -70,7 +70,7 @@ #define MAX_NUMBER_DIGITS 20 #define MAX_FMT_IE_LEN 20 -/* values for gigaset_capi_appl.connected */ +/* values for bcs->apconnstate */ #define APCONN_NONE 0 /* inactive/listening */ #define APCONN_SETUP 1 /* connecting */ #define APCONN_ACTIVE 2 /* B channel up */ @@ -80,10 +80,10 @@ struct gigaset_capi_appl { struct list_head ctrlist; struct gigaset_capi_appl *bcnext; u16 id; + struct capi_register_params rp; u16 nextMessageNumber; u32 listenInfoMask; u32 listenCIPmask; - int connected; }; /* CAPI specific controller data structure */ @@ -319,6 +319,39 @@ static const char *format_ie(const char *ie) return result; } +/* + * emit DATA_B3_CONF message + */ +static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr, + u16 appl, u16 msgid, int channel, + u16 handle, u16 info) +{ + struct sk_buff *cskb; + u8 *msg; + + cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); + if (!cskb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + /* frequent message, avoid _cmsg overhead */ + msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN); + CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN); + CAPIMSG_SETAPPID(msg, appl); + CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3); + CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF); + CAPIMSG_SETMSGID(msg, msgid); + CAPIMSG_SETCONTROLLER(msg, ctr->cnr); + CAPIMSG_SETPLCI_PART(msg, channel); + CAPIMSG_SETNCCI_PART(msg, 1); + CAPIMSG_SETHANDLE_CONF(msg, handle); + CAPIMSG_SETINFO_CONF(msg, info); + + /* emit message */ + dump_rawmsg(DEBUG_MCMD, __func__, msg); + capi_ctr_handle_message(ctr, appl, cskb); +} + /* * driver interface functions @@ -339,7 +372,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) struct gigaset_capi_ctr *iif = cs->iif; struct gigaset_capi_appl *ap = bcs->ap; unsigned char *req = skb_mac_header(dskb); - struct sk_buff *cskb; u16 flags; /* update statistics */ @@ -351,39 +383,22 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) } /* don't send further B3 messages if disconnected */ - if (ap->connected < APCONN_ACTIVE) { + if (bcs->apconnstate < APCONN_ACTIVE) { gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); return; } - /* ToDo: honor unset "delivery confirmation" bit */ + /* + * send DATA_B3_CONF if "delivery confirmation" bit was set in request; + * otherwise it has already been sent by do_data_b3_req() + */ flags = CAPIMSG_FLAGS(req); - - /* build DATA_B3_CONF message */ - cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); - if (!cskb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - /* frequent message, avoid _cmsg overhead */ - CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN); - CAPIMSG_SETAPPID(cskb->data, ap->id); - CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3); - CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF); - CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req)); - CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr); - CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1); - CAPIMSG_SETNCCI_PART(cskb->data, 1); - CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req)); - if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) - CAPIMSG_SETINFO_CONF(cskb->data, - CapiFlagsNotSupportedByProtocol); - else - CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR); - - /* emit message */ - dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data); - capi_ctr_handle_message(&iif->ctr, ap->id, cskb); + if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION) + send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req), + bcs->channel + 1, CAPIMSG_HANDLE_REQ(req), + (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ? + CapiFlagsNotSupportedByProtocol : + CAPI_NOERROR); } EXPORT_SYMBOL_GPL(gigaset_skb_sent); @@ -412,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) } /* don't send further B3 messages if disconnected */ - if (ap->connected < APCONN_ACTIVE) { + if (bcs->apconnstate < APCONN_ACTIVE) { gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); dev_kfree_skb_any(skb); return; @@ -484,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) u32 actCIPmask; struct sk_buff *skb; unsigned int msgsize; + unsigned long flags; int i; /* @@ -608,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state) format_ie(iif->hcmsg.CalledPartyNumber)); /* scan application list for matching listeners */ - bcs->ap = NULL; + spin_lock_irqsave(&bcs->aplock, flags); + if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) { + dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", + __func__, bcs->ap, bcs->apconnstate); + bcs->ap = NULL; + bcs->apconnstate = APCONN_NONE; + } + spin_unlock_irqrestore(&bcs->aplock, flags); actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); list_for_each_entry(ap, &iif->appls, ctrlist) if (actCIPmask & ap->listenCIPmask) { @@ -626,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state) dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); /* add to listeners on this B channel, update state */ + spin_lock_irqsave(&bcs->aplock, flags); ap->bcnext = bcs->ap; bcs->ap = ap; bcs->chstate |= CHS_NOTIFY_LL; - ap->connected = APCONN_SETUP; + bcs->apconnstate = APCONN_SETUP; + spin_unlock_irqrestore(&bcs->aplock, flags); /* emit message */ capi_ctr_handle_message(&iif->ctr, ap->id, skb); @@ -654,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs, struct gigaset_capi_ctr *iif = cs->iif; struct sk_buff *skb; - if (ap->connected == APCONN_NONE) + if (bcs->apconnstate == APCONN_NONE) return; capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, @@ -668,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs, } capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN)); dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - ap->connected = APCONN_NONE; capi_ctr_handle_message(&iif->ctr, ap->id, skb); } @@ -685,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs, struct sk_buff *skb; /* nothing to do if no logical connection active */ - if (ap->connected < APCONN_ACTIVE) + if (bcs->apconnstate < APCONN_ACTIVE) return; - ap->connected = APCONN_SETUP; + bcs->apconnstate = APCONN_SETUP; capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, ap->nextMessageNumber++, @@ -714,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs) { struct cardstate *cs = bcs->cs; struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap = bcs->ap; + struct gigaset_capi_appl *ap; struct sk_buff *skb; unsigned int msgsize; + unsigned long flags; + spin_lock_irqsave(&bcs->aplock, flags); + ap = bcs->ap; if (!ap) { + spin_unlock_irqrestore(&bcs->aplock, flags); dev_err(cs->dev, "%s: no application\n", __func__); return; } + if (bcs->apconnstate == APCONN_NONE) { + spin_unlock_irqrestore(&bcs->aplock, flags); + dev_warn(cs->dev, "%s: application %u not connected\n", + __func__, ap->id); + return; + } + spin_unlock_irqrestore(&bcs->aplock, flags); while (ap->bcnext) { /* this should never happen */ dev_warn(cs->dev, "%s: dropping extra application %u\n", @@ -730,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs) CapiCallGivenToOtherApplication); ap->bcnext = ap->bcnext->bcnext; } - if (ap->connected == APCONN_NONE) { - dev_warn(cs->dev, "%s: application %u not connected\n", - __func__, ap->id); - return; - } /* prepare CONNECT_ACTIVE_IND message * Note: LLC not supported by device @@ -772,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs) void gigaset_isdn_hupD(struct bc_state *bcs) { struct gigaset_capi_appl *ap; + unsigned long flags; /* * ToDo: pass on reason code reported by device * (requires ev-layer state machine extension to collect * ZCAU device reply) */ - for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { + spin_lock_irqsave(&bcs->aplock, flags); + while (bcs->ap != NULL) { + ap = bcs->ap; + bcs->ap = ap->bcnext; + spin_unlock_irqrestore(&bcs->aplock, flags); send_disconnect_b3_ind(bcs, ap); send_disconnect_ind(bcs, ap, 0); + spin_lock_irqsave(&bcs->aplock, flags); } - bcs->ap = NULL; + bcs->apconnstate = APCONN_NONE; + spin_unlock_irqrestore(&bcs->aplock, flags); } /** @@ -796,24 +833,21 @@ void gigaset_isdn_connB(struct bc_state *bcs) { struct cardstate *cs = bcs->cs; struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap = bcs->ap; + struct gigaset_capi_appl *ap; struct sk_buff *skb; + unsigned long flags; unsigned int msgsize; u8 command; + spin_lock_irqsave(&bcs->aplock, flags); + ap = bcs->ap; if (!ap) { + spin_unlock_irqrestore(&bcs->aplock, flags); dev_err(cs->dev, "%s: no application\n", __func__); return; } - while (ap->bcnext) { - /* this should never happen */ - dev_warn(cs->dev, "%s: dropping extra application %u\n", - __func__, ap->bcnext->id); - send_disconnect_ind(bcs, ap->bcnext, - CapiCallGivenToOtherApplication); - ap->bcnext = ap->bcnext->bcnext; - } - if (!ap->connected) { + if (!bcs->apconnstate) { + spin_unlock_irqrestore(&bcs->aplock, flags); dev_warn(cs->dev, "%s: application %u not connected\n", __func__, ap->id); return; @@ -825,13 +859,26 @@ void gigaset_isdn_connB(struct bc_state *bcs) * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP * Parameters in both cases always: NCCI = 1, NCPI empty */ - if (ap->connected >= APCONN_ACTIVE) { + if (bcs->apconnstate >= APCONN_ACTIVE) { command = CAPI_CONNECT_B3_ACTIVE; msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; } else { command = CAPI_CONNECT_B3; msgsize = CAPI_CONNECT_B3_IND_BASELEN; } + bcs->apconnstate = APCONN_ACTIVE; + + spin_unlock_irqrestore(&bcs->aplock, flags); + + while (ap->bcnext) { + /* this should never happen */ + dev_warn(cs->dev, "%s: dropping extra application %u\n", + __func__, ap->bcnext->id); + send_disconnect_ind(bcs, ap->bcnext, + CapiCallGivenToOtherApplication); + ap->bcnext = ap->bcnext->bcnext; + } + capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, ap->nextMessageNumber++, iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); @@ -842,7 +889,6 @@ void gigaset_isdn_connB(struct bc_state *bcs) } capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - ap->connected = APCONN_ACTIVE; capi_ctr_handle_message(&iif->ctr, ap->id, skb); } @@ -945,8 +991,64 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, return; } ap->id = appl; + ap->rp = *rp; list_add(&ap->ctrlist, &iif->appls); + dev_info(cs->dev, "application %u registered\n", ap->id); +} + +/* + * remove CAPI application from channel + * helper function to keep indentation levels down and stay in 80 columns + */ + +static inline void remove_appl_from_channel(struct bc_state *bcs, + struct gigaset_capi_appl *ap) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_appl *bcap; + unsigned long flags; + int prevconnstate; + + spin_lock_irqsave(&bcs->aplock, flags); + bcap = bcs->ap; + if (bcap == NULL) { + spin_unlock_irqrestore(&bcs->aplock, flags); + return; + } + + /* check first application on channel */ + if (bcap == ap) { + bcs->ap = ap->bcnext; + if (bcs->ap != NULL) { + spin_unlock_irqrestore(&bcs->aplock, flags); + return; + } + + /* none left, clear channel state */ + prevconnstate = bcs->apconnstate; + bcs->apconnstate = APCONN_NONE; + spin_unlock_irqrestore(&bcs->aplock, flags); + + if (prevconnstate == APCONN_ACTIVE) { + dev_notice(cs->dev, "%s: hanging up channel %u\n", + __func__, bcs->channel); + gigaset_add_event(cs, &bcs->at_state, + EV_HUP, NULL, 0, NULL); + gigaset_schedule_event(cs); + } + return; + } + + /* check remaining list */ + do { + if (bcap->bcnext == ap) { + bcap->bcnext = bcap->bcnext->bcnext; + return; + } + bcap = bcap->bcnext; + } while (bcap != NULL); + spin_unlock_irqrestore(&bcs->aplock, flags); } /* @@ -958,19 +1060,19 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) = container_of(ctr, struct gigaset_capi_ctr, ctr); struct cardstate *cs = iif->ctr.driverdata; struct gigaset_capi_appl *ap, *tmp; + unsigned ch; list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) if (ap->id == appl) { - if (ap->connected != APCONN_NONE) { - dev_err(cs->dev, - "%s: application %u still connected\n", - __func__, ap->id); - /* ToDo: clear active connection */ - } + /* remove from any channels */ + for (ch = 0; ch < cs->channels; ch++) + remove_appl_from_channel(&cs->bcs[ch], ap); + + /* remove from registration list */ list_del(&ap->ctrlist); kfree(ap); + dev_info(cs->dev, "application %u released\n", appl); } - } /* @@ -1149,7 +1251,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, char **commands; char *s; u8 *pp; - int i, l; + unsigned long flags; + int i, l, lbc, lhlc; u16 info; /* decode message */ @@ -1164,8 +1267,18 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, send_conf(iif, ap, skb, CapiNoPlciAvailable); return; } + spin_lock_irqsave(&bcs->aplock, flags); + if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) + dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", + __func__, bcs->ap, bcs->apconnstate); ap->bcnext = NULL; bcs->ap = ap; + bcs->apconnstate = APCONN_SETUP; + spin_unlock_irqrestore(&bcs->aplock, flags); + + bcs->rx_bufsize = ap->rp.datablklen; + dev_kfree_skb(bcs->rx_skb); + gigaset_new_rx_skb(bcs); cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; /* build command table */ @@ -1273,42 +1386,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, goto error; } - /* check/encode parameter: BC */ - if (cmsg->BC && cmsg->BC[0]) { - /* explicit BC overrides CIP */ - l = 2*cmsg->BC[0] + 7; + /* + * check/encode parameters: BC & HLC + * must be encoded together as device doesn't accept HLC separately + * explicit parameters override values derived from CIP + */ + + /* determine lengths */ + if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ + lbc = 2*cmsg->BC[0]; + else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */ + lbc = strlen(cip2bchlc[cmsg->CIPValue].bc); + else /* no BC */ + lbc = 0; + if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */ + lhlc = 2*cmsg->HLC[0]; + else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */ + lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc); + else /* no HLC */ + lhlc = 0; + + if (lbc) { + /* have BC: allocate and assemble command string */ + l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */ + if (lhlc) + l += lhlc + 7; /* ";^SHLC=" + value */ commands[AT_BC] = kmalloc(l, GFP_KERNEL); if (!commands[AT_BC]) goto oom; strcpy(commands[AT_BC], "^SBC="); - decode_ie(cmsg->BC, commands[AT_BC]+5); + if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ + decode_ie(cmsg->BC, commands[AT_BC] + 5); + else /* BC derived from CIP */ + strcpy(commands[AT_BC] + 5, + cip2bchlc[cmsg->CIPValue].bc); + if (lhlc) { + strcpy(commands[AT_BC] + lbc + 5, ";^SHLC="); + if (cmsg->HLC && cmsg->HLC[0]) + /* HLC specified explicitly */ + decode_ie(cmsg->HLC, + commands[AT_BC] + lbc + 12); + else /* HLC derived from CIP */ + strcpy(commands[AT_BC] + lbc + 12, + cip2bchlc[cmsg->CIPValue].hlc); + } strcpy(commands[AT_BC] + l - 2, "\r"); - } else if (cip2bchlc[cmsg->CIPValue].bc) { - l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; - commands[AT_BC] = kmalloc(l, GFP_KERNEL); - if (!commands[AT_BC]) - goto oom; - snprintf(commands[AT_BC], l, "^SBC=%s\r", - cip2bchlc[cmsg->CIPValue].bc); - } - - /* check/encode parameter: HLC */ - if (cmsg->HLC && cmsg->HLC[0]) { - /* explicit HLC overrides CIP */ - l = 2*cmsg->HLC[0] + 7; - commands[AT_HLC] = kmalloc(l, GFP_KERNEL); - if (!commands[AT_HLC]) - goto oom; - strcpy(commands[AT_HLC], "^SHLC="); - decode_ie(cmsg->HLC, commands[AT_HLC]+5); - strcpy(commands[AT_HLC] + l - 2, "\r"); - } else if (cip2bchlc[cmsg->CIPValue].hlc) { - l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; - commands[AT_HLC] = kmalloc(l, GFP_KERNEL); - if (!commands[AT_HLC]) - goto oom; - snprintf(commands[AT_HLC], l, "^SHLC=%s\r", - cip2bchlc[cmsg->CIPValue].hlc); + } else { + /* no BC */ + if (lhlc) { + dev_notice(cs->dev, "%s: cannot set HLC without BC\n", + "CONNECT_REQ"); + info = CapiIllMessageParmCoding; /* ? */ + goto error; + } } /* check/encode parameter: B Protocol */ @@ -1322,13 +1452,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, bcs->proto2 = L2_HDLC; break; case 1: - bcs->proto2 = L2_BITSYNC; + bcs->proto2 = L2_VOICE; break; default: dev_warn(cs->dev, "B1 Protocol %u unsupported, using Transparent\n", cmsg->B1protocol); - bcs->proto2 = L2_BITSYNC; + bcs->proto2 = L2_VOICE; } if (cmsg->B2protocol != 1) dev_warn(cs->dev, @@ -1382,7 +1512,6 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, goto error; } gigaset_schedule_event(cs); - ap->connected = APCONN_SETUP; send_conf(iif, ap, skb, CapiSuccess); return; @@ -1410,6 +1539,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, _cmsg *cmsg = &iif->acmsg; struct bc_state *bcs; struct gigaset_capi_appl *oap; + unsigned long flags; int channel; /* decode message */ @@ -1429,12 +1559,24 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, switch (cmsg->Reject) { case 0: /* Accept */ /* drop all competing applications, keep only this one */ - for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) - if (oap != ap) + spin_lock_irqsave(&bcs->aplock, flags); + while (bcs->ap != NULL) { + oap = bcs->ap; + bcs->ap = oap->bcnext; + if (oap != ap) { + spin_unlock_irqrestore(&bcs->aplock, flags); send_disconnect_ind(bcs, oap, CapiCallGivenToOtherApplication); + spin_lock_irqsave(&bcs->aplock, flags); + } + } ap->bcnext = NULL; bcs->ap = ap; + spin_unlock_irqrestore(&bcs->aplock, flags); + + bcs->rx_bufsize = ap->rp.datablklen; + dev_kfree_skb(bcs->rx_skb); + gigaset_new_rx_skb(bcs); bcs->chstate |= CHS_NOTIFY_LL; /* check/encode B channel protocol */ @@ -1448,13 +1590,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, bcs->proto2 = L2_HDLC; break; case 1: - bcs->proto2 = L2_BITSYNC; + bcs->proto2 = L2_VOICE; break; default: dev_warn(cs->dev, "B1 Protocol %u unsupported, using Transparent\n", cmsg->B1protocol); - bcs->proto2 = L2_BITSYNC; + bcs->proto2 = L2_VOICE; } if (cmsg->B2protocol != 1) dev_warn(cs->dev, @@ -1502,31 +1644,45 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, send_disconnect_ind(bcs, ap, 0); /* remove it from the list of listening apps */ + spin_lock_irqsave(&bcs->aplock, flags); if (bcs->ap == ap) { bcs->ap = ap->bcnext; - if (bcs->ap == NULL) + if (bcs->ap == NULL) { /* last one: stop ev-layer hupD notifications */ + bcs->apconnstate = APCONN_NONE; bcs->chstate &= ~CHS_NOTIFY_LL; + } + spin_unlock_irqrestore(&bcs->aplock, flags); return; } for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { if (oap->bcnext == ap) { oap->bcnext = oap->bcnext->bcnext; + spin_unlock_irqrestore(&bcs->aplock, flags); return; } } + spin_unlock_irqrestore(&bcs->aplock, flags); dev_err(cs->dev, "%s: application %u not found\n", __func__, ap->id); return; default: /* Reject */ /* drop all competing applications, keep only this one */ - for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) - if (oap != ap) + spin_lock_irqsave(&bcs->aplock, flags); + while (bcs->ap != NULL) { + oap = bcs->ap; + bcs->ap = oap->bcnext; + if (oap != ap) { + spin_unlock_irqrestore(&bcs->aplock, flags); send_disconnect_ind(bcs, oap, CapiCallGivenToOtherApplication); + spin_lock_irqsave(&bcs->aplock, flags); + } + } ap->bcnext = NULL; bcs->ap = ap; + spin_unlock_irqrestore(&bcs->aplock, flags); /* reject call - will trigger DISCONNECT_IND for this app */ dev_info(cs->dev, "%s: Reject=%x\n", @@ -1549,6 +1705,7 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif, { struct cardstate *cs = iif->ctr.driverdata; _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; int channel; /* decode message */ @@ -1563,9 +1720,10 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif, send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } + bcs = &cs->bcs[channel-1]; /* mark logical connection active */ - ap->connected = APCONN_ACTIVE; + bcs->apconnstate = APCONN_ACTIVE; /* build NCCI: always 1 (one B3 connection only) */ cmsg->adr.adrNCCI |= 1 << 16; @@ -1611,7 +1769,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, if (cmsg->Reject) { /* Reject: clear B3 connect received flag */ - ap->connected = APCONN_SETUP; + bcs->apconnstate = APCONN_SETUP; /* trigger hangup, causing eventual DISCONNECT_IND */ if (!gigaset_add_event(cs, &bcs->at_state, @@ -1683,11 +1841,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, } /* skip if DISCONNECT_IND already sent */ - if (!ap->connected) + if (!bcs->apconnstate) return; /* check for active logical connection */ - if (ap->connected >= APCONN_ACTIVE) { + if (bcs->apconnstate >= APCONN_ACTIVE) { /* * emit DISCONNECT_B3_IND with cause 0x3301 * use separate cmsg structure, as the content of iif->acmsg @@ -1736,6 +1894,7 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, { struct cardstate *cs = iif->ctr.driverdata; _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; int channel; /* decode message */ @@ -1751,17 +1910,17 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } + bcs = &cs->bcs[channel-1]; /* reject if logical connection not active */ - if (ap->connected < APCONN_ACTIVE) { + if (bcs->apconnstate < APCONN_ACTIVE) { send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); return; } /* trigger hangup, causing eventual DISCONNECT_B3_IND */ - if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, - EV_HUP, NULL, 0, NULL)) { + if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } @@ -1782,11 +1941,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + struct bc_state *bcs; int channel = CAPIMSG_PLCI_PART(skb->data); u16 ncci = CAPIMSG_NCCI_PART(skb->data); u16 msglen = CAPIMSG_LEN(skb->data); u16 datalen = CAPIMSG_DATALEN(skb->data); u16 flags = CAPIMSG_FLAGS(skb->data); + u16 msgid = CAPIMSG_MSGID(skb->data); + u16 handle = CAPIMSG_HANDLE_REQ(skb->data); /* frequent message, avoid _cmsg overhead */ dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); @@ -1802,6 +1964,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif, send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } + bcs = &cs->bcs[channel-1]; if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) dev_notice(cs->dev, "%s: unexpected length %d\n", "DATA_B3_REQ", msglen); @@ -1821,7 +1984,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif, } /* reject if logical connection not active */ - if (ap->connected < APCONN_ACTIVE) { + if (bcs->apconnstate < APCONN_ACTIVE) { send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); return; } @@ -1832,17 +1995,19 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif, skb_pull(skb, msglen); /* pass to device-specific module */ - if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { + if (cs->ops->send_skb(bcs, skb) < 0) { send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } - /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ - /* - * ToDo: honor unset "delivery confirmation" bit - * (send DATA_B3_CONF immediately?) + * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery + * confirmation" bit is set; otherwise we have to send it now */ + if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)) + send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle, + flags ? CapiFlagsNotSupportedByProtocol + : CAPI_NOERROR); } /* diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index f6f45f221920..5d4befb81057 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs) gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); - dev_kfree_skb(bcs->skb); - bcs->skb = NULL; + dev_kfree_skb(bcs->rx_skb); + bcs->rx_skb = NULL; for (i = 0; i < AT_NUM; ++i) { kfree(bcs->commands[i]); @@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->emptycount = 0; #endif - gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); - bcs->fcs = PPP_INITFCS; + bcs->rx_bufsize = 0; + bcs->rx_skb = NULL; + bcs->rx_fcs = PPP_INITFCS; bcs->inputstate = 0; - if (cs->ignoreframes) { - bcs->skb = NULL; - } else { - bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); - if (bcs->skb != NULL) - skb_reserve(bcs->skb, cs->hw_hdr_len); - else - pr_err("out of memory\n"); - } - bcs->channel = channel; bcs->cs = cs; @@ -658,16 +649,15 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, for (i = 0; i < AT_NUM; ++i) bcs->commands[i] = NULL; + spin_lock_init(&bcs->aplock); + bcs->ap = NULL; + bcs->apconnstate = 0; + gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); if (cs->ops->initbcshw(bcs)) return bcs; gig_dbg(DEBUG_INIT, " failed"); - - gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); - dev_kfree_skb(bcs->skb); - bcs->skb = NULL; - return NULL; } @@ -839,14 +829,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs) bcs->emptycount = 0; #endif - bcs->fcs = PPP_INITFCS; + bcs->rx_fcs = PPP_INITFCS; bcs->chstate = 0; bcs->ignore = cs->ignoreframes; - if (bcs->ignore) { - dev_kfree_skb(bcs->skb); - bcs->skb = NULL; - } + dev_kfree_skb(bcs->rx_skb); + bcs->rx_skb = NULL; cs->ops->reinitbcshw(bcs); } diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 206c380c5235..ceaef9a04a42 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] = /* dial */ {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, -{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} }, -{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, -{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD+AT_PROTO} }, {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 05947f9c1849..8738b0821fc9 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -45,10 +45,6 @@ #define MAX_EVENTS 64 /* size of event queue */ #define RBUFSIZE 8192 -#define SBUFSIZE 4096 /* sk_buff payload size */ - -#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ -#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ /* compile time options */ #define GIG_MAJOR 0 @@ -190,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define AT_BC 3 #define AT_PROTO 4 #define AT_TYPE 5 -#define AT_HLC 6 -#define AT_CLIP 7 +#define AT_CLIP 6 /* total number */ -#define AT_NUM 8 +#define AT_NUM 7 /* variables in struct at_state_t */ #define VAR_ZSAU 0 @@ -380,8 +375,10 @@ struct bc_state { struct at_state_t at_state; - __u16 fcs; - struct sk_buff *skb; + /* receive buffer */ + unsigned rx_bufsize; /* max size accepted by application */ + struct sk_buff *rx_skb; + __u16 rx_fcs; int inputstate; /* see INS_XXXX */ int channel; @@ -406,7 +403,9 @@ struct bc_state { struct bas_bc_state *bas; /* usb hardware driver (base) */ } hw; - void *ap; /* LL application structure */ + void *ap; /* associated LL application */ + int apconnstate; /* LL application connection state */ + spinlock_t aplock; }; struct cardstate { @@ -801,8 +800,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) gigaset_schedule_event(bcs->cs); } -/* handling routines for sk_buff */ -/* ============================= */ +/* set up next receive skb for data mode */ +static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + unsigned short hw_hdr_len = cs->hw_hdr_len; + + if (bcs->ignore) { + bcs->rx_skb = NULL; + } else { + bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len); + if (bcs->rx_skb == NULL) + dev_warn(cs->dev, "could not allocate skb\n"); + else + skb_reserve(bcs->rx_skb, hw_hdr_len); + } + return bcs->rx_skb; +} /* append received bytes to inbuf */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c22e5ace8276..f01c3c2e2e46 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -16,7 +16,10 @@ #include "gigaset.h" #include <linux/isdnif.h> +#define SBUFSIZE 4096 /* sk_buff payload size */ +#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ #define HW_HDR_LEN 2 /* Header size used to store ack info */ +#define MAX_BUF_SIZE (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */ /* == Handling of I4L IO =====================================================*/ @@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl) dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); return -EBUSY; } + switch (bcs->proto2) { + case L2_HDLC: + bcs->rx_bufsize = SBUFSIZE; + break; + default: /* assume transparent */ + bcs->rx_bufsize = TRANSBUFSIZE; + } + dev_kfree_skb(bcs->rx_skb); + gigaset_new_rx_skb(bcs); commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); if (!commands) { @@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl) return -EINVAL; } bcs = cs->bcs + ch; + switch (bcs->proto2) { + case L2_HDLC: + bcs->rx_bufsize = SBUFSIZE; + break; + default: /* assume transparent */ + bcs->rx_bufsize = TRANSBUFSIZE; + } + dev_kfree_skb(bcs->rx_skb); + gigaset_new_rx_skb(bcs); if (!gigaset_add_event(cs, &bcs->at_state, EV_ACCEPT, NULL, 0, NULL)) return -ENOMEM; diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 16fd3bd48883..2dfd346fc889 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) */ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) { - bcs->fcs = crc_ccitt_byte(bcs->fcs, c); - if (unlikely(bcs->skb == NULL)) { + bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c); + if (bcs->rx_skb == NULL) /* skipping */ return; - } - if (unlikely(bcs->skb->len == SBUFSIZE)) { + if (bcs->rx_skb->len >= bcs->rx_bufsize) { dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); bcs->hw.bas->giants++; - dev_kfree_skb_any(bcs->skb); - bcs->skb = NULL; + dev_kfree_skb_any(bcs->rx_skb); + bcs->rx_skb = NULL; return; } - *__skb_put(bcs->skb, 1) = c; + *__skb_put(bcs->rx_skb, 1) = c; } /* hdlc_flush @@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) static inline void hdlc_flush(struct bc_state *bcs) { /* clear skb or allocate new if not skipping */ - if (likely(bcs->skb != NULL)) - skb_trim(bcs->skb, 0); - else if (!bcs->ignore) { - bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); - if (bcs->skb) - skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); - else - dev_err(bcs->cs->dev, "could not allocate skb\n"); - } + if (bcs->rx_skb != NULL) + skb_trim(bcs->rx_skb, 0); + else + gigaset_new_rx_skb(bcs); /* reset packet state */ - bcs->fcs = PPP_INITFCS; + bcs->rx_fcs = PPP_INITFCS; } /* hdlc_done @@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs) hdlc_flush(bcs); return; } - procskb = bcs->skb; + procskb = bcs->rx_skb; if (procskb == NULL) { /* previous error */ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); @@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs) bcs->hw.bas->runts++; dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); - } else if (bcs->fcs != PPP_GOODFCS) { - dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); + } else if (bcs->rx_fcs != PPP_GOODFCS) { + dev_notice(cs->dev, "frame check error\n"); bcs->hw.bas->fcserrs++; dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); @@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs) bcs->hw.bas->goodbytes += len; gigaset_skb_rcvd(bcs, procskb); } - - bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); - if (bcs->skb) - skb_reserve(bcs->skb, cs->hw_hdr_len); - else - dev_err(cs->dev, "could not allocate skb\n"); - bcs->fcs = PPP_INITFCS; + gigaset_new_rx_skb(bcs); + bcs->rx_fcs = PPP_INITFCS; } /* hdlc_frag @@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); bcs->hw.bas->alignerrs++; gigaset_isdn_rcv_err(bcs); - __skb_trim(bcs->skb, 0); - bcs->fcs = PPP_INITFCS; + __skb_trim(bcs->rx_skb, 0); + bcs->rx_fcs = PPP_INITFCS; } /* bit counts lookup table for HDLC bit unstuffing @@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, static inline void trans_receive(unsigned char *src, unsigned count, struct bc_state *bcs) { - struct cardstate *cs = bcs->cs; struct sk_buff *skb; int dobytes; unsigned char *dst; @@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count, hdlc_flush(bcs); return; } - skb = bcs->skb; - if (unlikely(skb == NULL)) { - bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); - if (!skb) { - dev_err(cs->dev, "could not allocate skb\n"); - return; - } - skb_reserve(skb, cs->hw_hdr_len); - } + skb = bcs->rx_skb; + if (skb == NULL) + skb = gigaset_new_rx_skb(bcs); bcs->hw.bas->goodbytes += skb->len; - dobytes = TRANSBUFSIZE - skb->len; + dobytes = bcs->rx_bufsize - skb->len; while (count > 0) { dst = skb_put(skb, count < dobytes ? count : dobytes); while (count > 0 && dobytes > 0) { @@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count, dump_bytes(DEBUG_STREAM_DUMP, "rcv data", skb->data, skb->len); gigaset_skb_rcvd(bcs, skb); - bcs->skb = skb = - dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); - if (!skb) { - dev_err(cs->dev, "could not allocate skb\n"); + skb = gigaset_new_rx_skb(bcs); + if (skb == NULL) return; - } - skb_reserve(skb, cs->hw_hdr_len); - dobytes = TRANSBUFSIZE; + dobytes = bcs->rx_bufsize; } } } diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index 72eb92647c1b..feec8d89d719 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -187,12 +187,13 @@ void hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len) { struct net_local *lp = card->netif; - struct net_device *dev = lp->dev; + struct net_device *dev; struct sk_buff *skb; if (!lp) return; /* non existing device */ + dev = lp->dev; dev->stats.rx_bytes += len; skb = dev_alloc_skb(len); diff --git a/drivers/md/md.c b/drivers/md/md.c index 46b3a044eadf..cb20d0b0555a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares) /* First make sure individual recovery_offsets are correct */ list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk >= 0 && + mddev->delta_disks >= 0 && !test_bit(In_sync, &rdev->flags) && mddev->curr_resync_completed > rdev->recovery_offset) rdev->recovery_offset = mddev->curr_resync_completed; @@ -3001,6 +3002,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len) return -EINVAL; } + list_for_each_entry(rdev, &mddev->disks, same_set) + rdev->new_raid_disk = rdev->raid_disk; + /* ->takeover must set new_* and/or delta_disks * if it succeeds, and may set them when it fails. */ @@ -3051,13 +3055,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len) mddev->safemode = 0; } - module_put(mddev->pers->owner); - /* Invalidate devices that are now superfluous */ - list_for_each_entry(rdev, &mddev->disks, same_set) - if (rdev->raid_disk >= mddev->raid_disks) { - rdev->raid_disk = -1; + list_for_each_entry(rdev, &mddev->disks, same_set) { + char nm[20]; + if (rdev->raid_disk < 0) + continue; + if (rdev->new_raid_disk > mddev->raid_disks) + rdev->new_raid_disk = -1; + if (rdev->new_raid_disk == rdev->raid_disk) + continue; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + } + list_for_each_entry(rdev, &mddev->disks, same_set) { + if (rdev->raid_disk < 0) + continue; + if (rdev->new_raid_disk == rdev->raid_disk) + continue; + rdev->raid_disk = rdev->new_raid_disk; + if (rdev->raid_disk < 0) clear_bit(In_sync, &rdev->flags); + else { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) + printk("md: cannot register %s for %s after level change\n", + nm, mdname(mddev)); } + } + + module_put(mddev->pers->owner); mddev->pers = pers; mddev->private = priv; strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); @@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) atomic_inc(&mddev->openers); mutex_unlock(&mddev->open_mutex); + check_disk_size_change(mddev->gendisk, bdev); out: return err; } @@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev) rcu_read_lock(); list_for_each_entry_rcu(rdev, &mddev->disks, same_set) if (rdev->raid_disk >= 0 && + mddev->delta_disks >= 0 && !test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) && rdev->recovery_offset < mddev->curr_resync) diff --git a/drivers/md/md.h b/drivers/md/md.h index 7ab5ea155452..10597bfec000 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -78,6 +78,9 @@ struct mdk_rdev_s int desc_nr; /* descriptor index in the superblock */ int raid_disk; /* role of device in array */ + int new_raid_disk; /* role that the device will have in + * the array after a level-change completes. + */ int saved_raid_disk; /* role that device used to have in the * array and could again if we did a partial * resync from the bitmap diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index e70f004c99e8..563abed5a2cb 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -173,9 +173,11 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf) list_for_each_entry(rdev1, &mddev->disks, same_set) { int j = rdev1->raid_disk; - if (mddev->level == 10) + if (mddev->level == 10) { /* taking over a raid10-n2 array */ j /= 2; + rdev1->new_raid_disk = j; + } if (j < 0 || j >= mddev->raid_disks) { printk(KERN_ERR "md/raid0:%s: bad disk number %d - " @@ -361,12 +363,6 @@ static int raid0_run(mddev_t *mddev) mddev->private = conf; } conf = mddev->private; - if (conf->scale_raid_disks) { - int i; - for (i=0; i < conf->strip_zone[0].nb_dev; i++) - conf->devlist[i]->raid_disk /= conf->scale_raid_disks; - /* FIXME update sysfs rd links */ - } /* calculate array device size */ md_set_array_sectors(mddev, raid0_size(mddev, 0, 0)); @@ -573,7 +569,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev) return; } -static void *raid0_takeover_raid5(mddev_t *mddev) +static void *raid0_takeover_raid45(mddev_t *mddev) { mdk_rdev_t *rdev; raid0_conf_t *priv_conf; @@ -596,6 +592,7 @@ static void *raid0_takeover_raid5(mddev_t *mddev) /* Set new parameters */ mddev->new_level = 0; + mddev->new_layout = 0; mddev->new_chunk_sectors = mddev->chunk_sectors; mddev->raid_disks--; mddev->delta_disks = -1; @@ -635,6 +632,7 @@ static void *raid0_takeover_raid10(mddev_t *mddev) /* Set new parameters */ mddev->new_level = 0; + mddev->new_layout = 0; mddev->new_chunk_sectors = mddev->chunk_sectors; mddev->delta_disks = - mddev->raid_disks / 2; mddev->raid_disks += mddev->delta_disks; @@ -643,19 +641,22 @@ static void *raid0_takeover_raid10(mddev_t *mddev) mddev->recovery_cp = MaxSector; create_strip_zones(mddev, &priv_conf); - priv_conf->scale_raid_disks = 2; return priv_conf; } static void *raid0_takeover(mddev_t *mddev) { /* raid0 can take over: + * raid4 - if all data disks are active. * raid5 - providing it is Raid4 layout and one disk is faulty * raid10 - assuming we have all necessary active disks */ + if (mddev->level == 4) + return raid0_takeover_raid45(mddev); + if (mddev->level == 5) { if (mddev->layout == ALGORITHM_PARITY_N) - return raid0_takeover_raid5(mddev); + return raid0_takeover_raid45(mddev); printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n", mdname(mddev), ALGORITHM_PARITY_N); diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h index d724e664ca4d..91f8e876ee64 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h @@ -13,9 +13,6 @@ struct raid0_private_data struct strip_zone *strip_zone; mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */ int nr_strip_zones; - int scale_raid_disks; /* divide rdev->raid_disks by this in run() - * to handle conversion from raid10 - */ }; typedef struct raid0_private_data raid0_conf_t; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 03724992cdf2..42e64e4e5e25 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) int sectors = r10_bio->sectors; mdk_rdev_t*rdev; int max_read_errors = atomic_read(&mddev->max_corr_read_errors); + int d = r10_bio->devs[r10_bio->read_slot].devnum; rcu_read_lock(); - { - int d = r10_bio->devs[r10_bio->read_slot].devnum; + rdev = rcu_dereference(conf->mirrors[d].rdev); + if (rdev) { /* If rdev is not NULL */ char b[BDEVNAME_SIZE]; int cur_read_error_count = 0; - rdev = rcu_dereference(conf->mirrors[d].rdev); bdevname(rdev->bdev, b); if (test_bit(Faulty, &rdev->flags)) { @@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) rcu_read_lock(); do { - int d = r10_bio->devs[sl].devnum; + d = r10_bio->devs[sl].devnum; rdev = rcu_dereference(conf->mirrors[d].rdev); if (rdev && test_bit(In_sync, &rdev->flags)) { @@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) rcu_read_lock(); while (sl != r10_bio->read_slot) { char b[BDEVNAME_SIZE]; - int d; + if (sl==0) sl = conf->copies; sl--; @@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) } sl = start; while (sl != r10_bio->read_slot) { - int d; + if (sl==0) sl = conf->copies; sl--; @@ -2161,22 +2161,22 @@ static conf_t *setup_conf(mddev_t *mddev) sector_t stride, size; int err = -EINVAL; - if (mddev->chunk_sectors < (PAGE_SIZE >> 9) || - !is_power_of_2(mddev->chunk_sectors)) { + if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) || + !is_power_of_2(mddev->new_chunk_sectors)) { printk(KERN_ERR "md/raid10:%s: chunk size must be " "at least PAGE_SIZE(%ld) and be a power of 2.\n", mdname(mddev), PAGE_SIZE); goto out; } - nc = mddev->layout & 255; - fc = (mddev->layout >> 8) & 255; - fo = mddev->layout & (1<<16); + nc = mddev->new_layout & 255; + fc = (mddev->new_layout >> 8) & 255; + fo = mddev->new_layout & (1<<16); if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || - (mddev->layout >> 17)) { + (mddev->new_layout >> 17)) { printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n", - mdname(mddev), mddev->layout); + mdname(mddev), mddev->new_layout); goto out; } @@ -2241,7 +2241,6 @@ static conf_t *setup_conf(mddev_t *mddev) if (!conf->thread) goto out; - conf->scale_disks = 0; conf->mddev = mddev; return conf; @@ -2300,11 +2299,6 @@ static int run(mddev_t *mddev) if (disk_idx >= conf->raid_disks || disk_idx < 0) continue; - if (conf->scale_disks) { - disk_idx *= conf->scale_disks; - rdev->raid_disk = disk_idx; - /* MOVE 'rd%d' link !! */ - } disk = conf->mirrors + disk_idx; disk->rdev = rdev; @@ -2435,26 +2429,22 @@ static void *raid10_takeover_raid0(mddev_t *mddev) return ERR_PTR(-EINVAL); } - /* Update slot numbers to obtain - * degraded raid10 with missing mirrors - */ - list_for_each_entry(rdev, &mddev->disks, same_set) { - rdev->raid_disk *= 2; - } - /* Set new parameters */ mddev->new_level = 10; /* new layout: far_copies = 1, near_copies = 2 */ mddev->new_layout = (1<<8) + 2; mddev->new_chunk_sectors = mddev->chunk_sectors; mddev->delta_disks = mddev->raid_disks; - mddev->degraded = mddev->raid_disks; mddev->raid_disks *= 2; /* make sure it will be not marked as dirty */ mddev->recovery_cp = MaxSector; conf = setup_conf(mddev); - conf->scale_disks = 2; + if (!IS_ERR(conf)) + list_for_each_entry(rdev, &mddev->disks, same_set) + if (rdev->raid_disk >= 0) + rdev->new_raid_disk = rdev->raid_disk * 2; + return conf; } diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 3824a087e17c..2316ac2e8e21 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -38,11 +38,6 @@ struct r10_private_data_s { int chunk_shift; /* shift from chunks to sectors */ sector_t chunk_mask; - int scale_disks; /* When starting array, multiply - * each ->raid_disk by this. - * Need for raid0->raid10 migration - */ - struct list_head retry_list; /* queue pending writes and submit them on unplug */ struct bio_list pending_bio_list; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d2c0f94fa37d..96c690279fc6 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -277,12 +277,13 @@ out: return sh; } -static void shrink_buffers(struct stripe_head *sh, int num) +static void shrink_buffers(struct stripe_head *sh) { struct page *p; int i; + int num = sh->raid_conf->pool_size; - for (i=0; i<num ; i++) { + for (i = 0; i < num ; i++) { p = sh->dev[i].page; if (!p) continue; @@ -291,11 +292,12 @@ static void shrink_buffers(struct stripe_head *sh, int num) } } -static int grow_buffers(struct stripe_head *sh, int num) +static int grow_buffers(struct stripe_head *sh) { int i; + int num = sh->raid_conf->pool_size; - for (i=0; i<num; i++) { + for (i = 0; i < num; i++) { struct page *page; if (!(page = alloc_page(GFP_KERNEL))) { @@ -364,6 +366,73 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, return NULL; } +/* + * Need to check if array has failed when deciding whether to: + * - start an array + * - remove non-faulty devices + * - add a spare + * - allow a reshape + * This determination is simple when no reshape is happening. + * However if there is a reshape, we need to carefully check + * both the before and after sections. + * This is because some failed devices may only affect one + * of the two sections, and some non-in_sync devices may + * be insync in the section most affected by failed devices. + */ +static int has_failed(raid5_conf_t *conf) +{ + int degraded; + int i; + if (conf->mddev->reshape_position == MaxSector) + return conf->mddev->degraded > conf->max_degraded; + + rcu_read_lock(); + degraded = 0; + for (i = 0; i < conf->previous_raid_disks; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); + if (!rdev || test_bit(Faulty, &rdev->flags)) + degraded++; + else if (test_bit(In_sync, &rdev->flags)) + ; + else + /* not in-sync or faulty. + * If the reshape increases the number of devices, + * this is being recovered by the reshape, so + * this 'previous' section is not in_sync. + * If the number of devices is being reduced however, + * the device can only be part of the array if + * we are reverting a reshape, so this section will + * be in-sync. + */ + if (conf->raid_disks >= conf->previous_raid_disks) + degraded++; + } + rcu_read_unlock(); + if (degraded > conf->max_degraded) + return 1; + rcu_read_lock(); + degraded = 0; + for (i = 0; i < conf->raid_disks; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); + if (!rdev || test_bit(Faulty, &rdev->flags)) + degraded++; + else if (test_bit(In_sync, &rdev->flags)) + ; + else + /* not in-sync or faulty. + * If reshape increases the number of devices, this + * section has already been recovered, else it + * almost certainly hasn't. + */ + if (conf->raid_disks <= conf->previous_raid_disks) + degraded++; + } + rcu_read_unlock(); + if (degraded > conf->max_degraded) + return 1; + return 0; +} + static void unplug_slaves(mddev_t *mddev); static void raid5_unplug_device(struct request_queue *q); @@ -1240,19 +1309,18 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) static int grow_one_stripe(raid5_conf_t *conf) { struct stripe_head *sh; - int disks = max(conf->raid_disks, conf->previous_raid_disks); sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); if (!sh) return 0; - memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev)); + memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev)); sh->raid_conf = conf; spin_lock_init(&sh->lock); #ifdef CONFIG_MULTICORE_RAID456 init_waitqueue_head(&sh->ops.wait_for_ops); #endif - if (grow_buffers(sh, disks)) { - shrink_buffers(sh, disks); + if (grow_buffers(sh)) { + shrink_buffers(sh); kmem_cache_free(conf->slab_cache, sh); return 0; } @@ -1468,7 +1536,7 @@ static int drop_one_stripe(raid5_conf_t *conf) if (!sh) return 0; BUG_ON(atomic_read(&sh->count)); - shrink_buffers(sh, conf->pool_size); + shrink_buffers(sh); kmem_cache_free(conf->slab_cache, sh); atomic_dec(&conf->active_stripes); return 1; @@ -2963,7 +3031,6 @@ static void handle_stripe5(struct stripe_head *sh) mdk_rdev_t *rdev; dev = &sh->dev[i]; - clear_bit(R5_Insync, &dev->flags); pr_debug("check %d: state 0x%lx toread %p read %p write %p " "written %p\n", i, dev->flags, dev->toread, dev->read, @@ -3000,17 +3067,27 @@ static void handle_stripe5(struct stripe_head *sh) blocked_rdev = rdev; atomic_inc(&rdev->nr_pending); } - if (!rdev || !test_bit(In_sync, &rdev->flags)) { + clear_bit(R5_Insync, &dev->flags); + if (!rdev) + /* Not in-sync */; + else if (test_bit(In_sync, &rdev->flags)) + set_bit(R5_Insync, &dev->flags); + else { + /* could be in-sync depending on recovery/reshape status */ + if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) + set_bit(R5_Insync, &dev->flags); + } + if (!test_bit(R5_Insync, &dev->flags)) { /* The ReadError flag will just be confusing now */ clear_bit(R5_ReadError, &dev->flags); clear_bit(R5_ReWrite, &dev->flags); } - if (!rdev || !test_bit(In_sync, &rdev->flags) - || test_bit(R5_ReadError, &dev->flags)) { + if (test_bit(R5_ReadError, &dev->flags)) + clear_bit(R5_Insync, &dev->flags); + if (!test_bit(R5_Insync, &dev->flags)) { s.failed++; s.failed_num = i; - } else - set_bit(R5_Insync, &dev->flags); + } } rcu_read_unlock(); @@ -3244,7 +3321,6 @@ static void handle_stripe6(struct stripe_head *sh) for (i=disks; i--; ) { mdk_rdev_t *rdev; dev = &sh->dev[i]; - clear_bit(R5_Insync, &dev->flags); pr_debug("check %d: state 0x%lx read %p write %p written %p\n", i, dev->flags, dev->toread, dev->towrite, dev->written); @@ -3282,18 +3358,28 @@ static void handle_stripe6(struct stripe_head *sh) blocked_rdev = rdev; atomic_inc(&rdev->nr_pending); } - if (!rdev || !test_bit(In_sync, &rdev->flags)) { + clear_bit(R5_Insync, &dev->flags); + if (!rdev) + /* Not in-sync */; + else if (test_bit(In_sync, &rdev->flags)) + set_bit(R5_Insync, &dev->flags); + else { + /* in sync if before recovery_offset */ + if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) + set_bit(R5_Insync, &dev->flags); + } + if (!test_bit(R5_Insync, &dev->flags)) { /* The ReadError flag will just be confusing now */ clear_bit(R5_ReadError, &dev->flags); clear_bit(R5_ReWrite, &dev->flags); } - if (!rdev || !test_bit(In_sync, &rdev->flags) - || test_bit(R5_ReadError, &dev->flags)) { + if (test_bit(R5_ReadError, &dev->flags)) + clear_bit(R5_Insync, &dev->flags); + if (!test_bit(R5_Insync, &dev->flags)) { if (s.failed < 2) r6s.failed_num[s.failed] = i; s.failed++; - } else - set_bit(R5_Insync, &dev->flags); + } } rcu_read_unlock(); @@ -4971,8 +5057,10 @@ static int run(mddev_t *mddev) list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk < 0) continue; - if (test_bit(In_sync, &rdev->flags)) + if (test_bit(In_sync, &rdev->flags)) { working_disks++; + continue; + } /* This disc is not fully in-sync. However if it * just stored parity (beyond the recovery_offset), * when we don't need to be concerned about the @@ -5005,7 +5093,7 @@ static int run(mddev_t *mddev) mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks) - working_disks); - if (mddev->degraded > conf->max_degraded) { + if (has_failed(conf)) { printk(KERN_ERR "md/raid:%s: not enough operational devices" " (%d/%d failed)\n", mdname(mddev), mddev->degraded, conf->raid_disks); @@ -5207,6 +5295,7 @@ static int raid5_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev + && tmp->rdev->recovery_offset == MaxSector && !test_bit(Faulty, &tmp->rdev->flags) && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { unsigned long flags; @@ -5242,7 +5331,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number) * isn't possible. */ if (!test_bit(Faulty, &rdev->flags) && - mddev->degraded <= conf->max_degraded && + !has_failed(conf) && number < conf->raid_disks) { err = -EBUSY; goto abort; @@ -5270,7 +5359,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) int first = 0; int last = conf->raid_disks - 1; - if (mddev->degraded > conf->max_degraded) + if (has_failed(conf)) /* no point adding a device */ return -EINVAL; @@ -5362,7 +5451,7 @@ static int check_reshape(mddev_t *mddev) if (mddev->bitmap) /* Cannot grow a bitmap yet */ return -EBUSY; - if (mddev->degraded > conf->max_degraded) + if (has_failed(conf)) return -EINVAL; if (mddev->delta_disks < 0) { /* We might be able to shrink, but the devices must @@ -5437,8 +5526,13 @@ static int raid5_start_reshape(mddev_t *mddev) /* Add some new drives, as many as will fit. * We know there are enough to make the newly sized array work. + * Don't add devices if we are reducing the number of + * devices in the array. This is because it is not possible + * to correctly record the "partially reconstructed" state of + * such devices during the reshape and confusion could result. */ - list_for_each_entry(rdev, &mddev->disks, same_set) + if (mddev->delta_disks >= 0) + list_for_each_entry(rdev, &mddev->disks, same_set) if (rdev->raid_disk < 0 && !test_bit(Faulty, &rdev->flags)) { if (raid5_add_disk(mddev, rdev) == 0) { @@ -5460,7 +5554,7 @@ static int raid5_start_reshape(mddev_t *mddev) } /* When a reshape changes the number of devices, ->degraded - * is measured against the large of the pre and post number of + * is measured against the larger of the pre and post number of * devices.*/ if (mddev->delta_disks > 0) { spin_lock_irqsave(&conf->device_lock, flags); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e171e77f6129..f06d06e7fdfa 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -249,7 +249,7 @@ config MMC_IMX config MMC_MSM7X00A tristate "Qualcomm MSM 7X00A SDCC Controller Support" - depends on MMC && ARCH_MSM + depends on MMC && ARCH_MSM && !ARCH_MSM7X30 help This provides support for the SD/MMC cell found in the MSM 7X00A controllers from Qualcomm. diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 000d65ea55a4..91c8013cf0d9 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -404,14 +404,9 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) return -EINVAL; - ops.oobbuf = kmalloc(length, GFP_KERNEL); - if (!ops.oobbuf) - return -ENOMEM; - - if (copy_from_user(ops.oobbuf, ptr, length)) { - kfree(ops.oobbuf); - return -EFAULT; - } + ops.oobbuf = memdup_user(ptr, length); + if (IS_ERR(ops.oobbuf)) + return PTR_ERR(ops.oobbuf); start &= ~((uint64_t)mtd->oobsize - 1); ret = mtd->write_oob(mtd, start, &ops); diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 98a04b3c9526..ffc3720929f1 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,13 +1,3 @@ -menuconfig MTD_NAND - tristate "NAND Device Support" - depends on MTD - select MTD_NAND_IDS - select MTD_NAND_ECC - help - This enables support for accessing all type of NAND flash - devices. For further information see - <http://www.linux-mtd.infradead.org/doc/nand.html>. - config MTD_NAND_ECC tristate @@ -19,6 +9,17 @@ config MTD_NAND_ECC_SMC Software ECC according to the Smart Media Specification. The original Linux implementation had byte 0 and 1 swapped. + +menuconfig MTD_NAND + tristate "NAND Device Support" + depends on MTD + select MTD_NAND_IDS + select MTD_NAND_ECC + help + This enables support for accessing all type of NAND flash + devices. For further information see + <http://www.linux-mtd.infradead.org/doc/nand.html>. + if MTD_NAND config MTD_NAND_VERIFY_WRITE diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 78a423295474..bcfc851fe550 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -150,7 +150,6 @@ static void r852_dma_done(struct r852_device *dev, int error) if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer) pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN, dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - complete(&dev->dma_done); } /* @@ -182,6 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) /* Set dma direction */ dev->dma_dir = do_read; dev->dma_stage = 1; + INIT_COMPLETION(dev->dma_done); dbg_verbose("doing dma %s ", do_read ? "read" : "write"); @@ -494,6 +494,11 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, if (dev->card_unstable) return 0; + if (dev->dma_error) { + dev->dma_error = 0; + return -1; + } + r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS); ecc_reg = r852_read_reg_dword(dev, R852_DATALINE); r852_write_reg(dev, R852_CTL, dev->ctlreg); @@ -707,6 +712,7 @@ void r852_card_detect_work(struct work_struct *work) container_of(work, struct r852_device, card_detect_work.work); r852_card_update_present(dev); + r852_update_card_detect(dev); dev->card_unstable = 0; /* False alarm */ @@ -722,7 +728,6 @@ void r852_card_detect_work(struct work_struct *work) else r852_unregister_nand_device(dev); exit: - /* Update detection logic */ r852_update_card_detect(dev); } @@ -796,6 +801,7 @@ static irqreturn_t r852_irq(int irq, void *data) if (dma_status & R852_DMA_IRQ_ERROR) { dbg("recieved dma error IRQ"); r852_dma_done(dev, -EIO); + complete(&dev->dma_done); goto out; } @@ -825,8 +831,10 @@ static irqreturn_t r852_irq(int irq, void *data) r852_dma_enable(dev); /* Operation done */ - if (dev->dma_stage == 3) + if (dev->dma_stage == 3) { r852_dma_done(dev, 0); + complete(&dev->dma_done); + } goto out; } @@ -940,18 +948,19 @@ int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) r852_dma_test(dev); + dev->irq = pci_dev->irq; + spin_lock_init(&dev->irqlock); + + dev->card_detected = 0; + r852_card_update_present(dev); + /*register irq handler*/ error = -ENODEV; if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED, DRV_NAME, dev)) goto error10; - dev->irq = pci_dev->irq; - spin_lock_init(&dev->irqlock); - /* kick initial present test */ - dev->card_detected = 0; - r852_card_update_present(dev); queue_delayed_work(dev->card_workqueue, &dev->card_detect_work, 0); @@ -1081,7 +1090,7 @@ int r852_resume(struct device *device) dev->card_detected ? "added" : "removed"); queue_delayed_work(dev->card_workqueue, - &dev->card_detect_work, 1000); + &dev->card_detect_work, msecs_to_jiffies(1000)); return 0; } diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 9c149750e2bf..284a5f4a63ac 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -598,8 +598,8 @@ rx_next: goto rx_status_loop; spin_lock_irqsave(&cp->lock, flags); - cpw16_f(IntrMask, cp_intr_mask); __napi_complete(napi); + cpw16_f(IntrMask, cp_intr_mask); spin_unlock_irqrestore(&cp->lock, flags); } diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 4ba72933f0da..97d8068b372b 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -860,6 +860,7 @@ retry: } /* if unknown chip, assume array element #0, original RTL-8139 in this case */ + i = 0; dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); tp->chipset = 0; @@ -2088,8 +2089,8 @@ static int rtl8139_poll(struct napi_struct *napi, int budget) * again when we think we are done. */ spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); __napi_complete(napi); + RTL_W16_F(IntrMask, rtl8139_intr_mask); spin_unlock_irqrestore(&tp->lock, flags); } spin_unlock(&tp->rx_lock); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2decc597bda7..ce2fcdd4ab90 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2754,6 +2754,7 @@ config MYRI10GE_DCA config NETXEN_NIC tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC" depends on PCI + select FW_LOADER help This enables the support for NetXen's Gigabit Ethernet card. @@ -2819,6 +2820,7 @@ config BNX2X config QLCNIC tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support" depends on PCI + select FW_LOADER help This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet devices. diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 949d7a9dcf92..117432222a09 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3073,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; struct l2_fhdr *rx_hdr; int rx_pkt = 0, pg_ring_used = 0; - struct pci_dev *pdev = bp->pdev; hw_cons = bnx2_get_hw_rx_cons(bnapi); sw_cons = rxr->rx_cons; @@ -3099,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) skb = rx_buf->skb; prefetchw(skb); - if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) { - next_rx_buf = - &rxr->rx_buf_ring[ - RX_RING_IDX(NEXT_RX_BD(sw_cons))]; - prefetch(next_rx_buf->desc); - } + next_rx_buf = + &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))]; + prefetch(next_rx_buf->desc); + rx_buf->skb = NULL; dma_addr = dma_unmap_addr(rx_buf, mapping); diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index fe925663d39a..80471269977a 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev) HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS; context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID; - context->xstorm_st_context.statistics_data = (cli | - XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE); + if (cli < MAX_X_STAT_COUNTER_ID) + context->xstorm_st_context.statistics_data = cli | + XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE; context->xstorm_ag_context.cdu_reserved = CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func), @@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev) ETH_CONNECTION_TYPE); /* reset xstorm per client statistics */ - val = BAR_XSTRORM_INTMEM + - XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); - for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++) - CNIC_WR(dev, val + i * 4, 0); + if (cli < MAX_X_STAT_COUNTER_ID) { + val = BAR_XSTRORM_INTMEM + + XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); + for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++) + CNIC_WR(dev, val + i * 4, 0); + } cp->tx_cons_ptr = &cp->bnx2x_def_status_blk->c_def_status_block.index_values[ @@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev) BNX2X_ISCSI_RX_SB_INDEX_NUM; context->ustorm_st_context.common.clientId = cli; context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID; - context->ustorm_st_context.common.flags = - USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS; - context->ustorm_st_context.common.statistics_counter_id = cli; + if (cli < MAX_U_STAT_COUNTER_ID) { + context->ustorm_st_context.common.flags = + USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS; + context->ustorm_st_context.common.statistics_counter_id = cli; + } context->ustorm_st_context.common.mc_alignment_log_size = 0; context->ustorm_st_context.common.bd_buff_size = cp->l2_single_buf_size; @@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev) /* client tstorm info */ tstorm_client.mtu = cp->l2_single_buf_size - 14; - tstorm_client.config_flags = - (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE | - TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE); - tstorm_client.statistics_counter_id = cli; + tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE; + + if (cli < MAX_T_STAT_COUNTER_ID) { + tstorm_client.config_flags |= + TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; + tstorm_client.statistics_counter_id = cli; + } CNIC_WR(dev, BAR_TSTRORM_INTMEM + TSTORM_CLIENT_CONFIG_OFFSET(port, cli), @@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev) ((u32 *)&tstorm_client)[1]); /* reset tstorm per client statistics */ - val = BAR_TSTRORM_INTMEM + - TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); - for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++) - CNIC_WR(dev, val + i * 4, 0); + if (cli < MAX_T_STAT_COUNTER_ID) { + + val = BAR_TSTRORM_INTMEM + + TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); + for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++) + CNIC_WR(dev, val + i * 4, 0); + } /* reset ustorm per client statistics */ - val = BAR_USTRORM_INTMEM + - USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); - for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++) - CNIC_WR(dev, val + i * 4, 0); + if (cli < MAX_U_STAT_COUNTER_ID) { + val = BAR_USTRORM_INTMEM + + USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); + for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++) + CNIC_WR(dev, val + i * 4, 0); + } cp->rx_cons_ptr = &cp->bnx2x_def_status_blk->u_def_status_block.index_values[ diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 3c58db595285..23786ee34bed 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) if (netif_msg_drv(priv)) printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(priv->phy); + rc = PTR_ERR(priv->phy); + goto fail; } if ((rc = register_netdev(dev))) { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ebdea0891665..68a80893dce1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, goto err_register; /* print bus type/speed/width info */ - e_info("(PCI%s:%s:%s) ", - ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), - ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" : - (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" : - (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" : - (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"), - ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit")); - - e_info("%pM\n", netdev->dev_addr); + e_info("(PCI%s:%dMHz:%d-bit) %pM\n", + ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), + ((hw->bus_speed == e1000_bus_speed_133) ? 133 : + (hw->bus_speed == e1000_bus_speed_120) ? 120 : + (hw->bus_speed == e1000_bus_speed_100) ? 100 : + (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33), + ((hw->bus_width == e1000_bus_width_64) ? 64 : 32), + netdev->dev_addr); /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0630980a2722..0060e422f171 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0103" +#define DRV_VERSION "EHEA_0105" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f547894ff48f..8b92acb448c2 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget) ehea_reset_cq_ep(pr->send_cq); ehea_reset_cq_n1(pr->recv_cq); ehea_reset_cq_n1(pr->send_cq); + rmb(); cqe = ehea_poll_rq1(pr->qp, &wqe_index); cqe_skb = ehea_poll_cq(pr->send_cq); @@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work) container_of(work, struct ehea_port, reset_task); struct net_device *dev = port->netdev; + mutex_lock(&dlpar_mem_lock); port->resets++; mutex_lock(&port->port_lock); netif_stop_queue(dev); @@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work) netif_wake_queue(dev); out: mutex_unlock(&port->port_lock); + mutex_unlock(&dlpar_mem_lock); } static void ehea_rereg_mrs(struct work_struct *work) @@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb, int ret = NOTIFY_BAD; struct memory_notify *arg = data; - if (!mutex_trylock(&dlpar_mem_lock)) { - ehea_info("ehea_mem_notifier must not be called parallelized"); - goto out; - } + mutex_lock(&dlpar_mem_lock); switch (action) { case MEM_CANCEL_OFFLINE: @@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb, out_unlock: mutex_unlock(&dlpar_mem_lock); -out: return ret; } diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 2b3e16db5c82..e0d33281ec98 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len) { u64 a0, a1 = len; int wait = 1000; - u64 prov_pa; + dma_addr_t prov_pa; void *prov_buf; int ret; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 1830f3199cb5..28b53d1cd4f1 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev) /* Insert receive time stamps into padding alignment bytes */ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) { rctrl &= ~RCTRL_PAL_MASK; - rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8); + rctrl |= RCTRL_PADDING(8); priv->padding = 8; } + /* Enable HW time stamping if requested from user space */ + if (priv->hwts_rx_en) + rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE; + /* keep vlan related bits if it's enabled */ if (priv->vlgrp) { rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; @@ -806,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev, switch (config.rx_filter) { case HWTSTAMP_FILTER_NONE: - priv->hwts_rx_en = 0; + if (priv->hwts_rx_en) { + stop_gfar(netdev); + priv->hwts_rx_en = 0; + startup_gfar(netdev); + } break; default: if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)) return -ERANGE; - priv->hwts_rx_en = 1; + if (!priv->hwts_rx_en) { + stop_gfar(netdev); + priv->hwts_rx_en = 1; + startup_gfar(netdev); + } config.rx_filter = HWTSTAMP_FILTER_ALL; break; } @@ -2643,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, priv->rx_buffer_size, DMA_FROM_DEVICE); + if (unlikely(!(bdp->status & RXBD_ERR) && + bdp->length > priv->rx_buffer_size)) + bdp->status = RXBD_LARGE; + /* We drop the frame if we failed to allocate a new buffer */ if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || bdp->status & RXBD_ERR)) { diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index c50a7541ffec..3a93a81872b8 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev, return 0; } -/* - * this function must be called before setting the new value of - * rx_itr_setting - */ -static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter, - struct ethtool_coalesce *ec) -{ - /* check the old value and enable RSC if necessary */ - if ((adapter->rx_itr_setting == 0) && - (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) { - adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; - adapter->netdev->features |= NETIF_F_LRO; - DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n", - ec->rx_coalesce_usecs); - return true; - } - return false; -} - static int ixgbe_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { @@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev, (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE)) return -EINVAL; - /* check the old value and enable RSC if necessary */ - need_reset = ixgbe_reenable_rsc(adapter, ec); - /* store the value in ints/second */ adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs; @@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev, /* clear the lower bit as its used for dynamic state */ adapter->rx_itr_setting &= ~1; } else if (ec->rx_coalesce_usecs == 1) { - /* check the old value and enable RSC if necessary */ - need_reset = ixgbe_reenable_rsc(adapter, ec); - /* 1 means dynamic mode */ adapter->rx_eitr_param = 20000; adapter->rx_itr_setting = 1; @@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev, */ if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; - netdev->features &= ~NETIF_F_LRO; - DPRINTK(PROBE, INFO, - "rx-usecs set to 0, disabling RSC\n"); - + if (netdev->features & NETIF_F_LRO) { + netdev->features &= ~NETIF_F_LRO; + DPRINTK(PROBE, INFO, "rx-usecs set to 0, " + "disabling LRO/RSC\n"); + } need_reset = true; } } @@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data) } } else if (!adapter->rx_itr_setting) { netdev->features &= ~ETH_FLAG_LRO; + if (data & ETH_FLAG_LRO) + DPRINTK(PROBE, INFO, "rx-usecs set to 0, " + "LRO/RSC cannot be enabled.\n"); } } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b2af2f67f604..ce30c62a97f7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5282,6 +5282,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; u64 non_eop_descs = 0, restart_queue = 0; + if (test_bit(__IXGBE_DOWN, &adapter->state) || + test_bit(__IXGBE_RESETTING, &adapter->state)) + return; + if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { u64 rsc_count = 0; u64 rsc_flush = 0; diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 09e1911ff510..48325a5beff2 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) * 4 SFP_DA_CORE1 - 82599-specific * 5 SFP_SR/LR_CORE0 - 82599-specific * 6 SFP_SR/LR_CORE1 - 82599-specific + * 7 SFP_act_lmt_DA_CORE0 - 82599-specific + * 8 SFP_act_lmt_DA_CORE1 - 82599-specific */ if (hw->mac.type == ixgbe_mac_82598EB) { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index ce5d6e909218..c27f4291b350 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev) DEB(DEB_MULTI, printk(KERN_DEBUG "%s: set multicast list, %d entries, promisc %s, allmulti %s\n", - dev->name, dev->mc_count, + dev->name, netdev_mc_count(dev), dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 8e9704f5c122..869f0ea43a5b 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __init mipsnet_probe(struct platform_device *dev) +static int __devinit mipsnet_probe(struct platform_device *dev) { struct net_device *netdev; int err; diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index f26e54716c88..3a41b6a84a68 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (addr == NULL) { dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", netdev->name); - return -ENOMEM; + err = -ENOMEM; + goto err_out_free; } tx_ring->desc_head = (struct cmd_desc_type0 *)addr; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 5c496f8d7c49..29d7b93d0493 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off) window = CRB_HI(off); - if (adapter->ahw.crb_win == window) - return; - writel(window, addr); if (readl(addr) != window) { if (printk_ratelimit()) @@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off) "failed to set CRB window to %d off 0x%lx\n", window, off); } - adapter->ahw.crb_win = window; } static void __iomem * diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 045a7c8f5bdf..c865dda2adf1 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) if (cmd_buf_arr == NULL) { dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", netdev->name); - return -ENOMEM; + goto err_out; } memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); tx_ring->cmd_buf_arr = cmd_buf_arr; @@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) if (rds_ring == NULL) { dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n", netdev->name); - return -ENOMEM; + goto err_out; } recv_ctx->rds_rings = rds_ring; @@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, netxen_ctx_msg msg = 0; struct list_head *head; + spin_lock(&rds_ring->lock); + producer = rds_ring->producer; - spin_lock(&rds_ring->lock); head = &rds_ring->free_list; while (!list_empty(head)) { @@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, producer = get_next_index(producer, rds_ring->num_desc); } - spin_unlock(&rds_ring->lock); if (count) { rds_ring->producer = producer; @@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, NETXEN_RCV_PRODUCER_OFFSET), msg); } } + + spin_unlock(&rds_ring->lock); } static void @@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, int producer, count = 0; struct list_head *head; - producer = rds_ring->producer; if (!spin_trylock(&rds_ring->lock)) return; + producer = rds_ring->producer; + head = &rds_ring->free_list; while (!list_empty(head)) { diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 6f77a768ba88..bfdef72c5d5e 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"), diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 7b6fe89f9db0..307cd1721e91 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -322,6 +322,7 @@ static int smc91c92_probe(struct pcmcia_device *link) return -ENOMEM; smc = netdev_priv(dev); smc->p_dev = link; + link->priv = dev; spin_lock_init(&smc->lock); link->io.NumPorts1 = 16; @@ -1504,12 +1505,20 @@ irq_done: writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR); writeb(cor, smc->base + MOT_LAN + CISREG_COR); } -#ifdef DOES_NOT_WORK - if (smc->base != NULL) { /* Megahertz MFC's */ - readb(smc->base+MEGAHERTZ_ISR); - readb(smc->base+MEGAHERTZ_ISR); + + if ((smc->base != NULL) && /* Megahertz MFC's */ + (smc->manfid == MANFID_MEGAHERTZ) && + (smc->cardid == PRODID_MEGAHERTZ_EM3288)) { + + u_char tmp; + tmp = readb(smc->base+MEGAHERTZ_ISR); + tmp = readb(smc->base+MEGAHERTZ_ISR); + + /* Retrigger interrupt if needed */ + writeb(tmp, smc->base + MEGAHERTZ_ISR); + writeb(tmp, smc->base + MEGAHERTZ_ISR); } -#endif + spin_unlock(&smc->lock); return IRQ_RETVAL(handled); } diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 8ee929b796d8..29c39ff85de5 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -53,6 +53,9 @@ #define MII_LXT971_ISR 19 /* Interrupt Status Register */ +/* register definitions for the 973 */ +#define MII_LXT973_PCR 16 /* Port Configuration Register */ +#define PCR_FIBER_SELECT 1 MODULE_DESCRIPTION("Intel LXT PHY driver"); MODULE_AUTHOR("Andy Fleming"); @@ -119,6 +122,33 @@ static int lxt971_config_intr(struct phy_device *phydev) return err; } +static int lxt973_probe(struct phy_device *phydev) +{ + int val = phy_read(phydev, MII_LXT973_PCR); + + if (val & PCR_FIBER_SELECT) { + /* + * If fiber is selected, then the only correct setting + * is 100Mbps, full duplex, and auto negotiation off. + */ + val = phy_read(phydev, MII_BMCR); + val |= (BMCR_SPEED100 | BMCR_FULLDPLX); + val &= ~BMCR_ANENABLE; + phy_write(phydev, MII_BMCR, val); + /* Remember that the port is in fiber mode. */ + phydev->priv = lxt973_probe; + } else { + phydev->priv = NULL; + } + return 0; +} + +static int lxt973_config_aneg(struct phy_device *phydev) +{ + /* Do nothing if port is in fiber mode. */ + return phydev->priv ? 0 : genphy_config_aneg(phydev); +} + static struct phy_driver lxt970_driver = { .phy_id = 0x78100000, .name = "LXT970", @@ -146,6 +176,18 @@ static struct phy_driver lxt971_driver = { .driver = { .owner = THIS_MODULE,}, }; +static struct phy_driver lxt973_driver = { + .phy_id = 0x00137a10, + .name = "LXT973", + .phy_id_mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .flags = 0, + .probe = lxt973_probe, + .config_aneg = lxt973_config_aneg, + .read_status = genphy_read_status, + .driver = { .owner = THIS_MODULE,}, +}; + static int __init lxt_init(void) { int ret; @@ -157,9 +199,15 @@ static int __init lxt_init(void) ret = phy_driver_register(&lxt971_driver); if (ret) goto err2; + + ret = phy_driver_register(&lxt973_driver); + if (ret) + goto err3; return 0; - err2: + err3: + phy_driver_unregister(&lxt971_driver); + err2: phy_driver_unregister(&lxt970_driver); err1: return ret; @@ -169,6 +217,7 @@ static void __exit lxt_exit(void) { phy_driver_unregister(&lxt970_driver); phy_driver_unregister(&lxt971_driver); + phy_driver_unregister(&lxt973_driver); } module_init(lxt_init); @@ -177,6 +226,7 @@ module_exit(lxt_exit); static struct mdio_device_id lxt_tbl[] = { { 0x78100000, 0xfffffff0 }, { 0x001378e0, 0xfffffff0 }, + { 0x00137a10, 0xfffffff0 }, { } }; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 217e709bda3e..96b6cfbf0a3a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -559,6 +559,11 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) break; udelay(25); } + /* + * According to hardware specs a 20us delay is required after write + * complete indication, but before sending next command. + */ + udelay(20); } static int mdio_read(void __iomem *ioaddr, int reg_addr) @@ -578,6 +583,12 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) } udelay(25); } + /* + * According to hardware specs a 20us delay is required after read + * complete indication, but before sending next command. + */ + udelay(20); + return value; } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2111c7bbf578..7985165e84fc 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); } +/* Enable Rx/Tx */ +static void sky2_enable_rx_tx(struct sky2_port *sky2) +{ + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u16 reg; + + reg = gma_read16(hw, port, GM_GP_CTRL); + reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; + gma_write16(hw, port, GM_GP_CTRL, reg); +} + /* Force a renegotiation */ static void sky2_phy_reinit(struct sky2_port *sky2) { spin_lock_bh(&sky2->phy_lock); sky2_phy_init(sky2->hw, sky2->port); + sky2_enable_rx_tx(sky2); spin_unlock_bh(&sky2->phy_lock); } @@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2) { struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u16 reg; static const char *fc_name[] = { [FC_NONE] = "none", [FC_TX] = "tx", @@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2) [FC_BOTH] = "both", }; - /* enable Rx/Tx */ - reg = gma_read16(hw, port, GM_GP_CTRL); - reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; - gma_write16(hw, port, GM_GP_CTRL, reg); + sky2_enable_rx_tx(sky2); gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index c0e70006374e..06b552fca63d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -367,8 +367,8 @@ static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; -#define dr32(reg) readl(de->regs + (reg)) -#define dw32(reg,val) writel((val), de->regs + (reg)) +#define dr32(reg) ioread32(de->regs + (reg)) +#define dw32(reg, val) iowrite32((val), de->regs + (reg)) static void de_rx_err_acct (struct de_private *de, unsigned rx_tail, @@ -1706,6 +1706,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de) int value, boguscnt = 100000; do { value = dr32(ROMCmd); + rmb(); } while (value < 0 && --boguscnt > 0); de->dev->dev_addr[i] = value; udelay(1); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 4a34833b85dd..807470e156af 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit __func__, __LINE__, (u32) skb); if (skb) { skb->data = skb->head + NET_SKB_PAD; + skb->len = 0; + skb_reset_tail_pointer(skb); __skb_queue_head(&ugeth->rx_recycle, skb); } diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 1f802e90474c..9516f382a6ba 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -344,7 +344,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return 2; } - if (size > ETH_FRAME_LEN) { + if (size > dev->net->mtu + ETH_HLEN) { netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", size); return 0; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 0a3c41faea9c..4dd23513c5af 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) /* check for port already opened, if not set the termios */ serial->open_count++; if (serial->open_count == 1) { - tty->low_latency = 1; serial->rx_state = RX_IDLE; /* Force default termio settings */ _hso_serial_set_termios(tty, NULL); diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index b504bd561362..d14e207de1df 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -2262,7 +2262,8 @@ start: vxge_debug_init(VXGE_ERR, "%s: memory allocation failed", VXGE_DRIVER_NAME); - return -ENOMEM; + ret = -ENOMEM; + goto alloc_entries_failed; } vdev->vxge_entries = @@ -2271,8 +2272,8 @@ start: if (!vdev->vxge_entries) { vxge_debug_init(VXGE_ERR, "%s: memory allocation failed", VXGE_DRIVER_NAME); - kfree(vdev->entries); - return -ENOMEM; + ret = -ENOMEM; + goto alloc_vxge_entries_failed; } for (i = 0, j = 0; i < vdev->no_of_vpath; i++) { @@ -2303,22 +2304,32 @@ start: vxge_debug_init(VXGE_ERR, "%s: MSI-X enable failed for %d vectors, ret: %d", VXGE_DRIVER_NAME, vdev->intr_cnt, ret); + if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) { + ret = -ENODEV; + goto enable_msix_failed; + } + kfree(vdev->entries); kfree(vdev->vxge_entries); vdev->entries = NULL; vdev->vxge_entries = NULL; - - if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) - return -ENODEV; /* Try with less no of vector by reducing no of vpaths count */ temp = (ret - 1)/2; vxge_close_vpaths(vdev, temp); vdev->no_of_vpath = temp; goto start; - } else if (ret < 0) - return -ENODEV; - + } else if (ret < 0) { + ret = -ENODEV; + goto enable_msix_failed; + } return 0; + +enable_msix_failed: + kfree(vdev->vxge_entries); +alloc_vxge_entries_failed: + kfree(vdev->entries); +alloc_entries_failed: + return ret; } static int vxge_enable_msix(struct vxgedev *vdev) diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 3f283bff0ff7..11491354e5b5 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -1192,7 +1192,7 @@ int i2400m_fw_hdr_check(struct i2400m *i2400m, unsigned module_type, header_len, major_version, minor_version, module_id, module_vendor, date, size; - module_type = bcf_hdr->module_type; + module_type = le32_to_cpu(bcf_hdr->module_type); header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len); major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000) >> 16; diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index e0c244b02f05..31c008042bfe 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; ah->ah_noise_floor = -95; /* until first NF calibration is run */ sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; + ah->ah_current_channel = &sc->channels[0]; /* * Find the mac version diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2978359c4366..648972df369d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = { static int __devinit ath5k_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void __devexit ath5k_pci_remove(struct pci_dev *pdev); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ath5k_pci_suspend(struct device *dev); static int ath5k_pci_resume(struct device *dev); @@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); #define ATH5K_PM_OPS (&ath5k_pm_ops) #else #define ATH5K_PM_OPS NULL -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ static struct pci_driver ath5k_pci_driver = { .name = KBUILD_MODNAME, @@ -708,7 +708,7 @@ ath5k_pci_remove(struct pci_dev *pdev) ieee80211_free_hw(hw); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ath5k_pci_suspend(struct device *dev) { struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); @@ -734,7 +734,7 @@ static int ath5k_pci_resume(struct device *dev) ath5k_led_enable(sc); return 0; } -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ /***********************\ @@ -3140,13 +3140,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { if (*new_flags & FIF_PROMISC_IN_BSS) { - rfilt |= AR5K_RX_FILTER_PROM; __set_bit(ATH_STAT_PROMISC, sc->status); } else { __clear_bit(ATH_STAT_PROMISC, sc->status); } } + if (test_bit(ATH_STAT_PROMISC, sc->status)) + rfilt |= AR5K_RX_FILTER_PROM; + /* Note, AR5K_RX_FILTER_MCAST is already enabled */ if (*new_flags & FIF_ALLMULTI) { mfilt[0] = ~0; diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1b81c4778800..492cbb15720d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1814,6 +1814,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) u8 def_ant, tx_ant, ee_mode; u32 sta_id1 = 0; + /* if channel is not initialized yet we can't set the antennas + * so just store the mode. it will be set on the next reset */ + if (channel == NULL) { + ah->ah_ant_mode = ant_mode; + return; + } + def_ant = ah->ah_def_ant; ATH5K_TRACE(ah->ah_sc); diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index db72461c486b..29b31a694b59 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link) local_info_t *local; int ret = 1; struct hostap_cs_priv *hw_priv; + unsigned long flags; PDEBUG(DEBUG_FLOW, "prism2_config()\n"); @@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link) local->hw_priv = hw_priv; hw_priv->link = link; + /* + * Make sure the IRQ handler cannot proceed until at least + * dev->base_addr is initialized. + */ + spin_lock_irqsave(&local->irq_init_lock, flags); + ret = pcmcia_request_irq(link, prism2_interrupt); if (ret) - goto failed; + goto failed_unlock; /* * This actually configures the PCMCIA socket -- setting up @@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link) */ ret = pcmcia_request_configuration(link, &link->conf); if (ret) - goto failed; + goto failed_unlock; dev->irq = link->irq; dev->base_addr = link->io.BasePort1; + spin_unlock_irqrestore(&local->irq_init_lock, flags); + /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x: ", dev_info, link->conf.ConfigIndex); @@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link) return ret; + failed_unlock: + spin_unlock_irqrestore(&local->irq_init_lock, flags); failed: kfree(hw_priv); prism2_release((u_long)link); diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index d70732819423..2f999fc94f60 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -2618,17 +2618,20 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) int events = 0; u16 ev; + iface = netdev_priv(dev); + local = iface->local; + /* Detect early interrupt before driver is fully configued */ + spin_lock(&local->irq_init_lock); if (!dev->base_addr) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", dev->name); } + spin_unlock(&local->irq_init_lock); return IRQ_HANDLED; } - - iface = netdev_priv(dev); - local = iface->local; + spin_unlock(&local->irq_init_lock); prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); @@ -3147,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, spin_lock_init(&local->cmdlock); spin_lock_init(&local->baplock); spin_lock_init(&local->lock); + spin_lock_init(&local->irq_init_lock); mutex_init(&local->rid_bap_mtx); if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 3d238917af07..1ba33be98b25 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -654,7 +654,7 @@ struct local_info { rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock * when removing entries from the list. * TX and RX paths can use read lock. */ - spinlock_t cmdlock, baplock, lock; + spinlock_t cmdlock, baplock, lock, irq_init_lock; struct mutex rid_bap_mtx; u16 infofid; /* MAC buffer id for info frame */ /* txfid, intransmitfid, next_txtid, and next_alloc are protected by diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 068f7f8435c5..c44a303e62ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2852,6 +2852,7 @@ static struct iwl_lib_ops iwl3945_lib = { .isr = iwl_isr_legacy, .config_ap = iwl3945_config_ap, .manage_ibss_station = iwl3945_manage_ibss_station, + .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl3945_good_plcp_health, .debugfs_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 1004cfc403b1..0f292a210ed9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1119,10 +1119,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, struct iwl_scan_channel *scan_ch) { const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; - int i, added = 0; + int added = 0; u16 channel = 0; sband = iwl_get_hw_mode(priv, band); @@ -1137,32 +1136,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, if (passive_dwell <= active_dwell) passive_dwell = active_dwell + 1; - /* only scan single channel, good enough to reset the RF */ - /* pick the first valid not in-use channel */ - if (band == IEEE80211_BAND_5GHZ) { - for (i = 14; i < priv->channel_count; i++) { - if (priv->channel_info[i].channel != - le16_to_cpu(priv->staging_rxon.channel)) { - channel = priv->channel_info[i].channel; - ch_info = iwl_get_channel_info(priv, - band, channel); - if (is_channel_valid(ch_info)) - break; - } - } - } else { - for (i = 0; i < 14; i++) { - if (priv->channel_info[i].channel != - le16_to_cpu(priv->staging_rxon.channel)) { - channel = - priv->channel_info[i].channel; - ch_info = iwl_get_channel_info(priv, - band, channel); - if (is_channel_valid(ch_info)) - break; - } - } - } + channel = iwl_get_single_channel_number(priv, band); if (channel) { scan_ch->channel = cpu_to_le16(channel); scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c402bfc83f36..7d614c4d3c62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1125,6 +1125,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_sta *sta; struct iwl_station_priv *sta_priv; + rcu_read_lock(); sta = ieee80211_find_sta(priv->vif, hdr->addr1); if (sta) { sta_priv = (void *)sta->drv_priv; @@ -1133,6 +1134,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) atomic_dec_return(&sta_priv->pending_frames) == 0) ieee80211_sta_block_awake(priv->hw, sta, false); } + rcu_read_unlock(); ieee80211_tx_status_irqsafe(priv->hw, skb); } @@ -1297,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, sta_id = ba_resp->sta_id; tid = ba_resp->tid; agg = &priv->stations[sta_id].tid[tid].agg; + if (unlikely(agg->txq_id != scd_flow)) { + IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n", + scd_flow, agg->txq_id); + return; + } /* Find index just before block-ack window */ index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index aef4f71f1981..24aff654fa9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1484,6 +1484,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv, } +/***************************************************************************** + * + * sysfs attributes + * + *****************************************************************************/ + +#ifdef CONFIG_IWLWIFI_DEBUG + +/* + * The following adds a new attribute to the sysfs representation + * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) + * used for controlling the debug level. + * + * See the level definitions in iwl for details. + * + * The debug_level being managed using sysfs below is a per device debug + * level that is used instead of the global debug level if it (the per + * device debug level) is set. + */ +static ssize_t show_debug_level(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); +} +static ssize_t store_debug_level(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 0, &val); + if (ret) + IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); + else { + priv->debug_level = val; + if (iwl_alloc_traffic_mem(priv)) + IWL_ERR(priv, + "Not enough memory to generate traffic log\n"); + } + return strnlen(buf, count); +} + +static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, + show_debug_level, store_debug_level); + + +#endif /* CONFIG_IWLWIFI_DEBUG */ + + +static ssize_t show_temperature(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + return sprintf(buf, "%d\n", priv->temperature); +} + +static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); + +static ssize_t show_tx_power(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + + if (!iwl_is_ready_rf(priv)) + return sprintf(buf, "off\n"); + else + return sprintf(buf, "%d\n", priv->tx_power_user_lmt); +} + +static ssize_t store_tx_power(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + IWL_INFO(priv, "%s is not in decimal form.\n", buf); + else { + ret = iwl_set_tx_power(priv, val, false); + if (ret) + IWL_ERR(priv, "failed setting tx power (0x%d).\n", + ret); + else + ret = count; + } + return ret; +} + +static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); + +static ssize_t show_rts_ht_protection(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + + return sprintf(buf, "%s\n", + priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); +} + +static ssize_t store_rts_ht_protection(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + IWL_INFO(priv, "Input is not in decimal form.\n"); + else { + if (!iwl_is_associated(priv)) + priv->cfg->use_rts_for_ht = val ? true : false; + else + IWL_ERR(priv, "Sta associated with AP - " + "Change protection mechanism is not allowed\n"); + ret = count; + } + return ret; +} + +static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, + show_rts_ht_protection, store_rts_ht_protection); + + +static struct attribute *iwl_sysfs_entries[] = { + &dev_attr_temperature.attr, + &dev_attr_tx_power.attr, + &dev_attr_rts_ht_protection.attr, +#ifdef CONFIG_IWLWIFI_DEBUG + &dev_attr_debug_level.attr, +#endif + NULL +}; + +static struct attribute_group iwl_attribute_group = { + .name = NULL, /* put in device directory */ + .attrs = iwl_sysfs_entries, +}; + /****************************************************************************** * * uCode download functions @@ -1965,6 +2115,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (err) IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); + err = sysfs_create_group(&priv->pci_dev->dev.kobj, + &iwl_attribute_group); + if (err) { + IWL_ERR(priv, "failed to create sysfs device attributes\n"); + goto out_unbind; + } + /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); complete(&priv->_agn.firmware_loading_complete); @@ -3234,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, int ret; u8 sta_id; - sta_priv->common.sta_id = IWL_INVALID_STATION; - IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); + mutex_lock(&priv->mutex); + IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", + sta->addr); + sta_priv->common.sta_id = IWL_INVALID_STATION; atomic_set(&sta_priv->pending_frames, 0); if (vif->type == NL80211_IFTYPE_AP) @@ -3249,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ + mutex_unlock(&priv->mutex); return ret; } @@ -3258,147 +3418,13 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); + mutex_unlock(&priv->mutex); return 0; } /***************************************************************************** * - * sysfs attributes - * - *****************************************************************************/ - -#ifdef CONFIG_IWLWIFI_DEBUG - -/* - * The following adds a new attribute to the sysfs representation - * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) - * used for controlling the debug level. - * - * See the level definitions in iwl for details. - * - * The debug_level being managed using sysfs below is a per device debug - * level that is used instead of the global debug level if it (the per - * device debug level) is set. - */ -static ssize_t show_debug_level(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); -} -static ssize_t store_debug_level(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - int ret; - - ret = strict_strtoul(buf, 0, &val); - if (ret) - IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); - else { - priv->debug_level = val; - if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, - "Not enough memory to generate traffic log\n"); - } - return strnlen(buf, count); -} - -static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, - show_debug_level, store_debug_level); - - -#endif /* CONFIG_IWLWIFI_DEBUG */ - - -static ssize_t show_temperature(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - return sprintf(buf, "%d\n", priv->temperature); -} - -static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); - -static ssize_t show_tx_power(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - if (!iwl_is_ready_rf(priv)) - return sprintf(buf, "off\n"); - else - return sprintf(buf, "%d\n", priv->tx_power_user_lmt); -} - -static ssize_t store_tx_power(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - int ret; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - IWL_INFO(priv, "%s is not in decimal form.\n", buf); - else { - ret = iwl_set_tx_power(priv, val, false); - if (ret) - IWL_ERR(priv, "failed setting tx power (0x%d).\n", - ret); - else - ret = count; - } - return ret; -} - -static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); - -static ssize_t show_rts_ht_protection(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "%s\n", - priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); -} - -static ssize_t store_rts_ht_protection(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - int ret; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - IWL_INFO(priv, "Input is not in decimal form.\n"); - else { - if (!iwl_is_associated(priv)) - priv->cfg->use_rts_for_ht = val ? true : false; - else - IWL_ERR(priv, "Sta associated with AP - " - "Change protection mechanism is not allowed\n"); - ret = count; - } - return ret; -} - -static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, - show_rts_ht_protection, store_rts_ht_protection); - - -/***************************************************************************** - * * driver setup and teardown * *****************************************************************************/ @@ -3550,21 +3576,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) kfree(priv->scan_cmd); } -static struct attribute *iwl_sysfs_entries[] = { - &dev_attr_temperature.attr, - &dev_attr_tx_power.attr, - &dev_attr_rts_ht_protection.attr, -#ifdef CONFIG_IWLWIFI_DEBUG - &dev_attr_debug_level.attr, -#endif - NULL -}; - -static struct attribute_group iwl_attribute_group = { - .name = NULL, /* put in device directory */ - .attrs = iwl_sysfs_entries, -}; - static struct ieee80211_ops iwl_hw_ops = { .tx = iwl_mac_tx, .start = iwl_mac_start, @@ -3750,11 +3761,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); goto out_disable_msi; } - err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); - if (err) { - IWL_ERR(priv, "failed to create sysfs device attributes\n"); - goto out_free_irq; - } iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); @@ -3788,15 +3794,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = iwl_request_firmware(priv, true); if (err) - goto out_remove_sysfs; + goto out_destroy_workqueue; return 0; - out_remove_sysfs: + out_destroy_workqueue: destroy_workqueue(priv->workqueue); priv->workqueue = NULL; - sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); - out_free_irq: free_irq(priv->pci_dev->irq, priv); iwl_free_isr_ict(priv); out_disable_msi: diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5a7eca8fb789..426e95567de3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -854,6 +854,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_set_rxon_chain); +/* Return valid channel */ +u8 iwl_get_single_channel_number(struct iwl_priv *priv, + enum ieee80211_band band) +{ + const struct iwl_channel_info *ch_info; + int i; + u8 channel = 0; + + /* only scan single channel, good enough to reset the RF */ + /* pick the first valid not in-use channel */ + if (band == IEEE80211_BAND_5GHZ) { + for (i = 14; i < priv->channel_count; i++) { + if (priv->channel_info[i].channel != + le16_to_cpu(priv->staging_rxon.channel)) { + channel = priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, + band, channel); + if (is_channel_valid(ch_info)) + break; + } + } + } else { + for (i = 0; i < 14; i++) { + if (priv->channel_info[i].channel != + le16_to_cpu(priv->staging_rxon.channel)) { + channel = + priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, + band, channel); + if (is_channel_valid(ch_info)) + break; + } + } + } + + return channel; +} +EXPORT_SYMBOL(iwl_get_single_channel_number); + /** * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7e5a5ba41fd2..31775bd9c361 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -343,6 +343,8 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv); int iwl_full_rxon_required(struct iwl_priv *priv); void iwl_set_rxon_chain(struct iwl_priv *priv); int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); +u8 iwl_get_single_channel_number(struct iwl_priv *priv, + enum ieee80211_band band); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *sta_ht_inf); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5d3f51ff2f0d..386c5f96eff8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work) mutex_lock(&priv->mutex); + cancel_delayed_work_sync(&priv->scan_check); set_bit(STATUS_SCAN_ABORTING, &priv->status); iwl_send_scan_abort(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 83a26361a9b5..c27c13fbb1ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); + mutex_lock(&priv->mutex); + IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", + sta->addr); ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); + mutex_unlock(&priv->mutex); return ret; } EXPORT_SYMBOL(iwl_mac_sta_remove); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3e5bffb6034f..a27872de4106 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1844,6 +1844,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) #endif } +static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv, + struct ieee80211_vif *vif, + enum ieee80211_band band, + struct iwl3945_scan_channel *scan_ch) +{ + const struct ieee80211_supported_band *sband; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int added = 0; + u8 channel = 0; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) { + IWL_ERR(priv, "invalid band\n"); + return added; + } + + active_dwell = iwl_get_active_dwell_time(priv, band, 0); + passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); + + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + + + channel = iwl_get_single_channel_number(priv, band); + + if (channel) { + scan_ch->channel = channel; + scan_ch->type = 0; /* passive */ + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + /* Set txpower levels to defaults */ + scan_ch->tpc.dsp_atten = 110; + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); + added++; + } else + IWL_ERR(priv, "no valid channel found\n"); + return added; +} + static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 n_probes, @@ -2992,9 +3035,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); - scan->channel_count = - iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); + if (priv->is_internal_short_scan) { + scan->channel_count = + iwl3945_get_single_channel_for_scan(priv, vif, band, + (void *)&scan->data[le16_to_cpu( + scan->tx_cmd.len)]); + } else { + scan->channel_count = + iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); + } if (scan->channel_count == 0) { IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); @@ -3387,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, bool is_ap = vif->type == NL80211_IFTYPE_STATION; u8 sta_id; - sta_priv->common.sta_id = IWL_INVALID_STATION; - IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); + mutex_lock(&priv->mutex); + IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", + sta->addr); + sta_priv->common.sta_id = IWL_INVALID_STATION; + ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, &sta_id); @@ -3398,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ + mutex_unlock(&priv->mutex); return ret; } @@ -3407,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl3945_rs_rate_init(priv, sta, sta_id); + mutex_unlock(&priv->mutex); return 0; } diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 6a04c2157f73..817fffc0de4b 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) prxpd = (struct rxpd *) skb->data; - stats.flag = 0; + memset(&stats, 0, sizeof(stats)); if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) stats.flag |= RX_FLAG_FAILED_FCS_CRC; stats.freq = priv->cur_freq; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 07c4528f6e6b..a5ea89cde8c4 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = { { PCI_DEVICE(0x1260, 0x3877) }, /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ { PCI_DEVICE(0x1260, 0x3886) }, + /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ + { PCI_DEVICE(0x1260, 0xffff) }, { }, }; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index d5b197b4d5bb..73073259f508 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ + {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ {} diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index d234285c2c81..c561332e7009 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -259,6 +259,7 @@ disable: sdio_disable_func(func); release: sdio_release_host(func); + wl1251_free_hw(wl); return ret; } diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index b3e5580c837b..4952c3b9379d 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -828,7 +828,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_name(pdev), err); return err; } + bus = pdev->subordinate; + if (!bus) { + dev_notice(&pdev->dev, "the device is not a bridge, " + "skipping\n"); + rc = -ENODEV; + goto err_disable_device; + } /* Need to read VID early b/c it's used to differentiate CPQ and INTC * discovery diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 796828fce34c..c9171be74564 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -340,7 +340,7 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_DMAR_DEFAULT_ON*/ -static int __initdata dmar_map_gfx = 1; +static int dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; @@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) } } if (found) { + spin_unlock_irqrestore(&device_domain_lock, flags); free_devinfo_mem(info); domain_exit(domain); domain = found; } else { list_add(&info->link, &domain->devices); list_add(&info->global, &device_domain_list); + spin_unlock_irqrestore(&device_domain_lock, flags); } - spin_unlock_irqrestore(&device_domain_lock, flags); } found_domain: @@ -3603,7 +3604,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, pte = dmar_domain->pgd; if (dma_pte_present(pte)) { free_pgtable_page(dmar_domain->pgd); - dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte); + dmar_domain->pgd = (struct dma_pte *) + phys_to_virt(dma_pte_addr(pte)); } dmar_domain->agaw--; } @@ -3719,6 +3721,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; + + /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ + if (dev->revision == 0x07) { + printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); + dmar_map_gfx = 0; + } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index afd2fbf7d797..c9957f68ac9b 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1035,39 +1035,6 @@ error: return retval; } -static void pci_remove_slot_links(struct pci_dev *dev) -{ - char func[10]; - struct pci_slot *slot; - - sysfs_remove_link(&dev->dev.kobj, "slot"); - list_for_each_entry(slot, &dev->bus->slots, list) { - if (slot->number != PCI_SLOT(dev->devfn)) - continue; - snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); - sysfs_remove_link(&slot->kobj, func); - } -} - -static int pci_create_slot_links(struct pci_dev *dev) -{ - int result = 0; - char func[10]; - struct pci_slot *slot; - - list_for_each_entry(slot, &dev->bus->slots, list) { - if (slot->number != PCI_SLOT(dev->devfn)) - continue; - result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot"); - if (result) - goto out; - snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); - result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func); - } -out: - return result; -} - int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) { int retval; @@ -1130,8 +1097,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) if (retval) goto err_vga_file; - pci_create_slot_links(pdev); - return 0; err_vga_file: @@ -1181,8 +1146,6 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) if (!sysfs_initialized) return; - pci_remove_slot_links(pdev); - pci_remove_capabilities_sysfs(pdev); if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60f30e7f1c8c..740fb4ea9669 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2292,6 +2292,7 @@ void pci_msi_off(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); } } +EXPORT_SYMBOL_GPL(pci_msi_off); #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c index aac285a16b62..d672a0a63816 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme/pcie_pme.c @@ -34,7 +34,7 @@ * being registered. Consequently, the interrupt-based PCIe PME signaling will * not be used by any PCIe root ports in that case. */ -static bool pcie_pme_disabled; +static bool pcie_pme_disabled = true; /* * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: @@ -64,12 +64,19 @@ bool pcie_pme_msi_disabled; static int __init pcie_pme_setup(char *str) { - if (!strcmp(str, "off")) - pcie_pme_disabled = true; - else if (!strcmp(str, "force")) + if (!strncmp(str, "auto", 4)) + pcie_pme_disabled = false; + else if (!strncmp(str, "force", 5)) pcie_pme_force_enable = true; - else if (!strcmp(str, "nomsi")) - pcie_pme_msi_disabled = true; + + str = strchr(str, ','); + if (str) { + str++; + str += strspn(str, " \t"); + if (*str && !strcmp(str, "nomsi")) + pcie_pme_msi_disabled = true; + } + return 1; } __setup("pcie_pme=", pcie_pme_setup); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b7512cf08c58..477345d41641 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1457,7 +1457,8 @@ static void quirk_jmicron_ata(struct pci_dev *pdev) conf5 &= ~(1 << 24); /* Clear bit 24 */ switch (pdev->device) { - case PCI_DEVICE_ID_JMICRON_JMB360: + case PCI_DEVICE_ID_JMICRON_JMB360: /* SATA single port */ + case PCI_DEVICE_ID_JMICRON_JMB362: /* SATA dual ports */ /* The controller should be in single function ahci mode */ conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */ break; @@ -1493,12 +1494,14 @@ static void quirk_jmicron_ata(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 17bed18d24ad..92379e2d37e7 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -97,16 +97,16 @@ int pci_claim_resource(struct pci_dev *dev, int resource) root = pci_find_parent_resource(dev, res); if (!root) { - dev_err(&dev->dev, "no compatible bridge window for %pR\n", - res); + dev_info(&dev->dev, "no compatible bridge window for %pR\n", + res); return -EINVAL; } conflict = request_resource_conflict(root, res); if (conflict) { - dev_err(&dev->dev, - "address space collision: %pR conflicts with %s %pR\n", - res, conflict->name, conflict); + dev_info(&dev->dev, + "address space collision: %pR conflicts with %s %pR\n", + res, conflict->name, conflict); return -EBUSY; } diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index e0189cf7c558..659eaa0fc48f 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -97,50 +97,6 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) return bus_speed_read(slot->bus->cur_bus_speed, buf); } -static void remove_sysfs_files(struct pci_slot *slot) -{ - char func[10]; - struct list_head *tmp; - - list_for_each(tmp, &slot->bus->devices) { - struct pci_dev *dev = pci_dev_b(tmp); - if (PCI_SLOT(dev->devfn) != slot->number) - continue; - sysfs_remove_link(&dev->dev.kobj, "slot"); - - snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); - sysfs_remove_link(&slot->kobj, func); - } -} - -static int create_sysfs_files(struct pci_slot *slot) -{ - int result; - char func[10]; - struct list_head *tmp; - - list_for_each(tmp, &slot->bus->devices) { - struct pci_dev *dev = pci_dev_b(tmp); - if (PCI_SLOT(dev->devfn) != slot->number) - continue; - - result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot"); - if (result) - goto fail; - - snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); - result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func); - if (result) - goto fail; - } - - return 0; - -fail: - remove_sysfs_files(slot); - return result; -} - static void pci_slot_release(struct kobject *kobj) { struct pci_dev *dev; @@ -153,8 +109,6 @@ static void pci_slot_release(struct kobject *kobj) if (PCI_SLOT(dev->devfn) == slot->number) dev->slot = NULL; - remove_sysfs_files(slot); - list_del(&slot->list); kfree(slot); @@ -346,8 +300,6 @@ placeholder: INIT_LIST_HEAD(&slot->list); list_add(&slot->list, &parent->slots); - create_sysfs_files(slot); - list_for_each_entry(dev, &parent->devices, bus_list) if (PCI_SLOT(dev->devfn) == slot_nr) dev->slot = slot; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 7ef7adee5e4f..9fc339845538 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -671,6 +671,7 @@ static void pcmcia_requery(struct pcmcia_socket *s) if (old_funcs != new_funcs) { /* we need to re-start */ pcmcia_card_remove(s, NULL); + s->functions = 0; pcmcia_card_add(s); } } diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 424e576f3acb..f1d41374eea7 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -880,6 +880,12 @@ static struct cardbus_type cardbus_type[] = { .restore_state = ti_restore_state, .sock_init = ti_init, }, + [CARDBUS_TYPE_ENE] = { + .override = ene_override, + .save_state = ti_save_state, + .restore_state = ti_restore_state, + .sock_init = ti_init, + }, #endif #ifdef CONFIG_YENTA_RICOH [CARDBUS_TYPE_RICOH] = { @@ -902,14 +908,6 @@ static struct cardbus_type cardbus_type[] = { .restore_state = o2micro_restore_state, }, #endif -#ifdef CONFIG_YENTA_TI - [CARDBUS_TYPE_ENE] = { - .override = ene_override, - .save_state = ti_save_state, - .restore_state = ti_restore_state, - .sock_init = ti_init, - }, -#endif }; @@ -975,7 +973,7 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id) /* probes the PCI interrupt, use only on override functions */ static int yenta_probe_cb_irq(struct yenta_socket *socket) { - u8 reg; + u8 reg = 0; if (!socket->cb_irq) return -1; @@ -989,7 +987,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) } /* generate interrupt, wait */ - reg = exca_readb(socket, I365_CSCINT); + if (!socket->dev->irq) + reg = exca_readb(socket, I365_CSCINT); exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG); cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index 9cca465436e3..85064a9f649e 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c @@ -9,19 +9,13 @@ * */ -#include <linux/init.h> -#include <linux/kernel.h> #include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/power_supply.h> -#include <linux/i2c.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> #include <linux/gpio.h> +#include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/irq.h> -#include <asm/irq.h> -#include <asm/mach/irq.h> +#include <linux/power_supply.h> +#include <linux/slab.h> #include <linux/z2_battery.h> #define Z2_DEFAULT_NAME "Z2" diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 92a8f6cacda9..34647fc1ee98 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -29,6 +29,7 @@ #include <linux/bcd.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/slab.h> /* * The DaVinci RTC is a simple RTC with the following diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index de033b7ac21f..d827ce570a8c 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -777,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, read_rtc: /* read RTC registers */ - tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf); + tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf); if (tmp != 8) { pr_debug("read error %d\n", tmp); err = -EIO; @@ -862,7 +862,7 @@ read_rtc: if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) tmp += 12; i2c_smbus_write_byte_data(client, - DS1307_REG_HOUR, + ds1307->offset + DS1307_REG_HOUR, bin2bcd(tmp)); } diff --git a/drivers/s390/cio/itcw.c b/drivers/s390/cio/itcw.c index 17da9ab932ed..a0ae29564774 100644 --- a/drivers/s390/cio/itcw.c +++ b/drivers/s390/cio/itcw.c @@ -42,7 +42,7 @@ * size_t size; * * size = itcw_calc_size(1, 2, 0); - * buffer = kmalloc(size, GFP_DMA); + * buffer = kmalloc(size, GFP_KERNEL | GFP_DMA); * if (!buffer) * return -ENOMEM; * itcw = itcw_init(buffer, size, ITCW_OP_READ, 1, 2, 0); diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 9eb62a256e9a..cd6cf575902e 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags) } } +#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE) +/* + * Write a string to the serial port + * Note that this is called with interrupts already disabled + */ +static void cpm_uart_early_write(struct uart_cpm_port *pinfo, + const char *string, u_int count) +{ + unsigned int i; + cbd_t __iomem *bdp, *bdbase; + unsigned char *cpm_outp_addr; + + /* Get the address of the host memory buffer. + */ + bdp = pinfo->tx_cur; + bdbase = pinfo->tx_bd_base; + + /* + * Now, do each character. This is not as bad as it looks + * since this is a holding FIFO and not a transmitting FIFO. + * We could add the complexity of filling the entire transmit + * buffer, but we would just wait longer between accesses...... + */ + for (i = 0; i < count; i++, string++) { + /* Wait for transmitter fifo to empty. + * Ready indicates output is ready, and xmt is doing + * that, not that it is ready for us to send. + */ + while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) + ; + + /* Send the character out. + * If the buffer address is in the CPM DPRAM, don't + * convert it. + */ + cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), + pinfo); + *cpm_outp_addr = *string; + + out_be16(&bdp->cbd_datlen, 1); + setbits16(&bdp->cbd_sc, BD_SC_READY); + + if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) + bdp = bdbase; + else + bdp++; + + /* if a LF, also do CR... */ + if (*string == 10) { + while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) + ; + + cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), + pinfo); + *cpm_outp_addr = 13; + + out_be16(&bdp->cbd_datlen, 1); + setbits16(&bdp->cbd_sc, BD_SC_READY); + + if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) + bdp = bdbase; + else + bdp++; + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) + ; + + pinfo->tx_cur = bdp; +} +#endif + #ifdef CONFIG_CONSOLE_POLL /* Serial polling routines for writing and reading from the uart while * in an interrupt or debug context. @@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port, static char ch[2]; ch[0] = (char)c; - cpm_uart_early_write(pinfo->port.line, ch, 1); + cpm_uart_early_write(pinfo, ch, 1); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s, u_int count) { struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; - unsigned int i; - cbd_t __iomem *bdp, *bdbase; - unsigned char *cp; unsigned long flags; int nolock = oops_in_progress; @@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, spin_lock_irqsave(&pinfo->port.lock, flags); } - /* Get the address of the host memory buffer. - */ - bdp = pinfo->tx_cur; - bdbase = pinfo->tx_bd_base; - - /* - * Now, do each character. This is not as bad as it looks - * since this is a holding FIFO and not a transmitting FIFO. - * We could add the complexity of filling the entire transmit - * buffer, but we would just wait longer between accesses...... - */ - for (i = 0; i < count; i++, s++) { - /* Wait for transmitter fifo to empty. - * Ready indicates output is ready, and xmt is doing - * that, not that it is ready for us to send. - */ - while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) - ; - - /* Send the character out. - * If the buffer address is in the CPM DPRAM, don't - * convert it. - */ - cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); - *cp = *s; - - out_be16(&bdp->cbd_datlen, 1); - setbits16(&bdp->cbd_sc, BD_SC_READY); - - if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) - bdp = bdbase; - else - bdp++; - - /* if a LF, also do CR... */ - if (*s == 10) { - while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) - ; - - cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); - *cp = 13; - - out_be16(&bdp->cbd_datlen, 1); - setbits16(&bdp->cbd_sc, BD_SC_READY); - - if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) - bdp = bdbase; - else - bdp++; - } - } - - /* - * Finally, Wait for transmitter & holding register to empty - * and restore the IER - */ - while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) - ; - - pinfo->tx_cur = bdp; + cpm_uart_early_write(pinfo, s, count); if (unlikely(nolock)) { local_irq_restore(flags); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 526307368f8b..ab17c08ddc03 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -821,6 +821,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"), diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index e2c000b80ca0..212bc21e6d68 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = { NULL, }; -static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj, return hna_local_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj, return hna_global_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t originators_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj, return orig_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t vis_data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index 7eb6559e0315..32204b5572d0 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, kfree(device_packet); if (error) - return error; + return -EFAULT; return sizeof(struct icmp_packet); } diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 36a254cd4413..39d112b708e3 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, plx9050_interrupt_control(dev_private->lcr_io_base, true, true, false, true, true); - dev_private->scan_delay = - (async_cmd->scan_begin_arg / (async_cmd->convert_arg * - async_cmd->chanlist_len)) - 1; + if (async_cmd->scan_begin_src == TRIG_TIMER) { + dev_private->scan_delay = + (async_cmd->scan_begin_arg / + (async_cmd->convert_arg * + async_cmd->chanlist_len)) - 1; + } break; diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 81829d6fd287..c374bee25068 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -52,7 +52,6 @@ Please report success/failure with other different cards to #include "8255.h" #define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */ -#define N_BOARDS 10 /* Number of boards in cb_pcidda_boards */ #define EEPROM_SIZE 128 /* number of entries in eeprom */ #define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */ @@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev, continue; } } - for (index = 0; index < N_BOARDS; index++) { + for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) { if (cb_pcidda_boards[index].device_id == pcidev->device) { goto found; diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 3f53b4d1e4cf..12db555a3a5d 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/completion.h> #include "osd.h" #include "logging.h" #include "vmbus_private.h" @@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel) Channel); } + +DECLARE_COMPLETION(hv_channel_ready); + +/* + * Count initialized channels, and ensure all channels are ready when hv_vmbus + * module loading completes. + */ +static void count_hv_channel(void) +{ + static int counter; + unsigned long flags; + + spin_lock_irqsave(&gVmbusConnection.channel_lock, flags); + if (++counter == MAX_MSG_TYPES) + complete(&hv_channel_ready); + spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags); +} + + /* * VmbusChannelProcessOffer - Process the offer by creating a channel/device * associated with this offer @@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context) * can cleanup properly */ newChannel->State = CHANNEL_OPEN_STATE; - cnt = 0; - while (cnt != MAX_MSG_TYPES) { + /* Open IC channels */ + for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) { if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType, &hv_cb_utils[cnt].data, - sizeof(struct hv_guid)) == 0) { + sizeof(struct hv_guid)) == 0 && + VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, + 2 * PAGE_SIZE, NULL, 0, + hv_cb_utils[cnt].callback, + newChannel) == 0) { + hv_cb_utils[cnt].channel = newChannel; DPRINT_INFO(VMBUS, "%s", - hv_cb_utils[cnt].log_msg); - - if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, - 2 * PAGE_SIZE, NULL, 0, - hv_cb_utils[cnt].callback, - newChannel) == 0) - hv_cb_utils[cnt].channel = newChannel; + hv_cb_utils[cnt].log_msg); + count_hv_channel(); } - cnt++; } } DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c index 8a49aafea37a..2adc9b48ca9c 100644 --- a/drivers/staging/hv/hv_utils.c +++ b/drivers/staging/hv/hv_utils.c @@ -24,6 +24,8 @@ #include <linux/slab.h> #include <linux/sysctl.h> #include <linux/reboot.h> +#include <linux/dmi.h> +#include <linux/pci.h> #include "logging.h" #include "osd.h" @@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context) DPRINT_EXIT(VMBUS); } +static const struct pci_device_id __initconst +hv_utils_pci_table[] __maybe_unused = { + { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */ + { 0 } +}; +MODULE_DEVICE_TABLE(pci, hv_utils_pci_table); + + +static const struct dmi_system_id __initconst +hv_utils_dmi_table[] __maybe_unused = { + { + .ident = "Hyper-V", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), + }, + }, + { }, +}; +MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table); + + static int __init init_hyperv_utils(void) { printk(KERN_INFO "Registering HyperV Utility Driver\n"); + if (!dmi_check_system(hv_utils_dmi_table)) + return -ENODEV; + hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback = &shutdown_onchannelcallback; hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h index 0c6ee0f487f3..3c14b2926e00 100644 --- a/drivers/staging/hv/vmbus.h +++ b/drivers/staging/hv/vmbus.h @@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx); void vmbus_child_driver_unregister(struct driver_context *driver_ctx); void vmbus_get_interface(struct vmbus_channel_interface *interface); +extern struct completion hv_channel_ready; + #endif /* _VMBUS_H_ */ diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index c21731a12ca7..22c80ece6388 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -27,6 +27,7 @@ #include <linux/pci.h> #include <linux/dmi.h> #include <linux/slab.h> +#include <linux/completion.h> #include "version_info.h" #include "osd.h" #include "logging.h" @@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv)) vmbus_drv_obj->GetChannelOffers(); + wait_for_completion(&hv_channel_ready); + cleanup: DPRINT_EXIT(VMBUS_DRV); diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c index 1db00975a594..abba22f921be 100644 --- a/drivers/staging/mrst-touchscreen/intel-mid-touch.c +++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c @@ -817,9 +817,9 @@ static int mrstouch_remove(struct spi_device *spi) free_irq(mrstouchdevp->irq, mrstouchdevp); input_unregister_device(mrstouchdevp->input); input_free_device(mrstouchdevp->input); - kfree(mrstouchdevp); if (mrstouchdevp->pendet_thrd) kthread_stop(mrstouchdevp->pendet_thrd); + kfree(mrstouchdevp); return 0; } diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index b740662d095a..674769d2b59b 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x083A, 0x7522)}, /* Arcadyan */ {USB_DEVICE(0x0CDE, 0x0022)}, /* ZCOM */ {USB_DEVICE(0x0586, 0x3416)}, /* Zyxel */ + {USB_DEVICE(0x0586, 0x341a)}, /* Zyxel NWD-270N */ {USB_DEVICE(0x0CDE, 0x0025)}, /* Zyxel */ {USB_DEVICE(0x1740, 0x9701)}, /* EnGenius */ {USB_DEVICE(0x1740, 0x9702)}, /* EnGenius */ diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index dacefea78113..49ab9fa9ffa7 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -66,8 +66,6 @@ static int hwseqnum = 0; static int hwwep = 0; static int channels = 0x3fff; -#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0) -#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5]) MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl); MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 447d6474a70c..1b6890611fb6 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -112,28 +112,29 @@ u32 rt_global_debug_component = \ #define CAM_CONTENT_COUNT 8 static const struct usb_device_id rtl8192_usb_id_tbl[] = { - /* Realtek */ - {USB_DEVICE(0x0bda, 0x8171)}, - {USB_DEVICE(0x0bda, 0x8192)}, - {USB_DEVICE(0x0bda, 0x8709)}, - /* Corega */ - {USB_DEVICE(0x07aa, 0x0043)}, - /* Belkin */ - {USB_DEVICE(0x050d, 0x805E)}, - {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */ - /* Sitecom */ - {USB_DEVICE(0x0df6, 0x0031)}, - {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */ - /* EnGenius */ - {USB_DEVICE(0x1740, 0x9201)}, - /* Dlink */ - {USB_DEVICE(0x2001, 0x3301)}, - /* Zinwell */ - {USB_DEVICE(0x5a57, 0x0290)}, - /* Guillemot */ - {USB_DEVICE(0x06f8, 0xe031)}, - //92SU + {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */ {USB_DEVICE(0x0bda, 0x8172)}, + {USB_DEVICE(0x0bda, 0x8173)}, + {USB_DEVICE(0x0bda, 0x8174)}, + {USB_DEVICE(0x0bda, 0x8712)}, + {USB_DEVICE(0x0bda, 0x8713)}, + {USB_DEVICE(0x07aa, 0x0047)}, + {USB_DEVICE(0x07d1, 0x3303)}, + {USB_DEVICE(0x07d1, 0x3302)}, + {USB_DEVICE(0x07d1, 0x3300)}, + {USB_DEVICE(0x1740, 0x9603)}, + {USB_DEVICE(0x1740, 0x9605)}, + {USB_DEVICE(0x050d, 0x815F)}, + {USB_DEVICE(0x06f8, 0xe031)}, + {USB_DEVICE(0x7392, 0x7611)}, + {USB_DEVICE(0x7392, 0x7612)}, + {USB_DEVICE(0x7392, 0x7622)}, + {USB_DEVICE(0x0DF6, 0x0045)}, + {USB_DEVICE(0x0E66, 0x0015)}, + {USB_DEVICE(0x0E66, 0x0016)}, + {USB_DEVICE(0x0b05, 0x1786)}, + /* these are not in the official list */ + {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */ {} }; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 2bede271a2f0..f38472c2e75c 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = { {USB_DEVICE(0x2001, 0x3301)}, /* Zinwell */ {USB_DEVICE(0x5a57, 0x0290)}, + /* LG */ + {USB_DEVICE(0x043e, 0x7a01)}, {} }; diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c index ce081cd44ad4..273e26ede650 100644 --- a/drivers/staging/tm6000/tm6000-alsa.c +++ b/drivers/staging/tm6000/tm6000-alsa.c @@ -15,6 +15,7 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/usb.h> +#include <linux/slab.h> #include <asm/delay.h> #include <sound/core.h> diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c index cedd9044022f..6a9ae40c7c6d 100644 --- a/drivers/staging/tm6000/tm6000-cards.c +++ b/drivers/staging/tm6000/tm6000-cards.c @@ -24,6 +24,7 @@ #include <linux/i2c.h> #include <linux/usb.h> #include <linux/version.h> +#include <linux/slab.h> #include <media/v4l2-common.h> #include <media/tuner.h> #include <media/tvaudio.h> diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c index 27f3f551b545..c3690e3580da 100644 --- a/drivers/staging/tm6000/tm6000-core.c +++ b/drivers/staging/tm6000/tm6000-core.c @@ -22,6 +22,7 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/usb.h> #include <linux/i2c.h> #include "tm6000.h" diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c index 261e66acbe46..86c1c8b5f25a 100644 --- a/drivers/staging/tm6000/tm6000-dvb.c +++ b/drivers/staging/tm6000/tm6000-dvb.c @@ -18,6 +18,7 @@ */ #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/usb.h> #include "tm6000.h" diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 52408164036f..6a499f0eb594 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -378,47 +378,67 @@ int usbip_thread(void *param) complete_and_exit(&ut->thread_done, 0); } +static void stop_rx_thread(struct usbip_device *ud) +{ + if (ud->tcp_rx.thread != NULL) { + send_sig(SIGKILL, ud->tcp_rx.thread, 1); + wait_for_completion(&ud->tcp_rx.thread_done); + usbip_udbg("rx_thread for ud %p has finished\n", ud); + } +} + +static void stop_tx_thread(struct usbip_device *ud) +{ + if (ud->tcp_tx.thread != NULL) { + send_sig(SIGKILL, ud->tcp_tx.thread, 1); + wait_for_completion(&ud->tcp_tx.thread_done); + usbip_udbg("tx_thread for ud %p has finished\n", ud); + } +} + int usbip_start_threads(struct usbip_device *ud) { /* * threads are invoked per one device (per one connection). */ struct task_struct *th; + int err = 0; th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip"); if (IS_ERR(th)) { printk(KERN_WARNING "Unable to start control thread\n"); - return PTR_ERR(th); + err = PTR_ERR(th); + goto ust_exit; } + th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip"); if (IS_ERR(th)) { printk(KERN_WARNING "Unable to start control thread\n"); - return PTR_ERR(th); + err = PTR_ERR(th); + goto tx_thread_err; } /* confirm threads are starting */ wait_for_completion(&ud->tcp_rx.thread_done); wait_for_completion(&ud->tcp_tx.thread_done); + return 0; + +tx_thread_err: + stop_rx_thread(ud); + +ust_exit: + return err; } EXPORT_SYMBOL_GPL(usbip_start_threads); void usbip_stop_threads(struct usbip_device *ud) { /* kill threads related to this sdev, if v.c. exists */ - if (ud->tcp_rx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_rx.thread, 1); - wait_for_completion(&ud->tcp_rx.thread_done); - usbip_udbg("rx_thread for ud %p has finished\n", ud); - } - - if (ud->tcp_tx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_tx.thread, 1); - wait_for_completion(&ud->tcp_tx.thread_done); - usbip_udbg("tx_thread for ud %p has finished\n", ud); - } + stop_rx_thread(ud); + stop_tx_thread(ud); } EXPORT_SYMBOL_GPL(usbip_stop_threads); diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c index 48c44c8fdb28..26cf5486edd6 100644 --- a/drivers/staging/wlags49_h2/wl_enc.c +++ b/drivers/staging/wlags49_h2/wl_enc.c @@ -62,6 +62,7 @@ /******************************************************************************* * include files ******************************************************************************/ +#include <linux/string.h> #include <wl_version.h> #include <debug.h> diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h index 6d96d03cf490..fa658c38001e 100644 --- a/drivers/staging/wlags49_h2/wl_sysfs.h +++ b/drivers/staging/wlags49_h2/wl_sysfs.h @@ -2,6 +2,6 @@ extern void register_wlags_sysfs(struct net_device *); extern void unregister_wlags_sysfs(struct net_device *); #else -static void register_wlags_sysfs(struct net_device *) { return; }; -static void unregister_wlags_sysfs(struct net_device *) { return; }; +static inline void register_wlags_sysfs(struct net_device *net) { } +static inline void unregister_wlags_sysfs(struct net_device *net) { } #endif diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index de98a94d1853..a6bd53ace035 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) static void choose_wakeup(struct usb_device *udev, pm_message_t msg) { - int w, i; - struct usb_interface *intf; + int w; /* Remote wakeup is needed only when we actually go to sleep. * For things like FREEZE and QUIESCE, if the device is already @@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg) return; } - /* If remote wakeup is permitted, see whether any interface drivers + /* Enable remote wakeup if it is allowed, even if no interface drivers * actually want it. */ - w = 0; - if (device_may_wakeup(&udev->dev) && udev->actconfig) { - for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - intf = udev->actconfig->interface[i]; - w |= intf->needs_remote_wakeup; - } - } + w = device_may_wakeup(&udev->dev); /* If the device is autosuspended with the wrong wakeup setting, * autoresume now so the setting can be changed. diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index a73e08fdab36..fd4c36ea5e46 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, /* A length of zero means transfer the whole sg list */ len = length; if (len == 0) { - for_each_sg(sg, sg, nents, i) - len += sg->length; + struct scatterlist *sg2; + int j; + + for_each_sg(sg, sg2, nents, j) + len += sg2->length; } } else { /* diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 38226e9a371d..95dd4662d6a8 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port, crc = get_unaligned_le32(skb->data + len - ETH_FCS_LEN); crc2 = ~crc32_le(~0, - skb->data, - skb->len - ETH_FCS_LEN); + skb->data, len - ETH_FCS_LEN); } else { crc = get_unaligned_be32(skb->data + len - ETH_FCS_LEN); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 7d05a0be5c60..4ce899c9b165 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -321,8 +321,8 @@ struct fsg_dev; /* Data shared by all the FSG instances. */ struct fsg_common { struct usb_gadget *gadget; - struct fsg_dev *fsg; - struct fsg_dev *prev_fsg; + struct fsg_dev *fsg, *new_fsg; + wait_queue_head_t fsg_wait; /* filesem protects: backing files in use */ struct rw_semaphore filesem; @@ -351,7 +351,6 @@ struct fsg_common { enum fsg_state state; /* For exception handling */ unsigned int exception_req_tag; - u8 config, new_config; enum data_direction data_dir; u32 data_size; u32 data_size_from_cmnd; @@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f, u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); - if (!fsg->common->config) + if (!fsg_is_set(fsg->common)) return -EOPNOTSUPP; switch (ctrl->bRequest) { @@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep, return -ENOMEM; } -/* - * Reset interface setting and re-init endpoint state (toggle etc). - * Call with altsetting < 0 to disable the interface. The only other - * available altsetting is 0, which enables the interface. - */ -static int do_set_interface(struct fsg_common *common, int altsetting) +/* Reset interface setting and re-init endpoint state (toggle etc). */ +static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) { - int rc = 0; - int i; - const struct usb_endpoint_descriptor *d; + const struct usb_endpoint_descriptor *d; + struct fsg_dev *fsg; + int i, rc = 0; if (common->running) DBG(common, "reset interface\n"); reset: /* Deallocate the requests */ - if (common->prev_fsg) { - struct fsg_dev *fsg = common->prev_fsg; + if (common->fsg) { + fsg = common->fsg; for (i = 0; i < FSG_NUM_BUFFERS; ++i) { struct fsg_buffhd *bh = &common->buffhds[i]; @@ -2345,88 +2340,53 @@ reset: fsg->bulk_out_enabled = 0; } - common->prev_fsg = 0; + common->fsg = NULL; + wake_up(&common->fsg_wait); } common->running = 0; - if (altsetting < 0 || rc != 0) + if (!new_fsg || rc) return rc; - DBG(common, "set interface %d\n", altsetting); + common->fsg = new_fsg; + fsg = common->fsg; - if (fsg_is_set(common)) { - struct fsg_dev *fsg = common->fsg; - common->prev_fsg = common->fsg; + /* Enable the endpoints */ + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); + rc = enable_endpoint(common, fsg->bulk_in, d); + if (rc) + goto reset; + fsg->bulk_in_enabled = 1; + + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); + rc = enable_endpoint(common, fsg->bulk_out, d); + if (rc) + goto reset; + fsg->bulk_out_enabled = 1; + common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - /* Enable the endpoints */ - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); - rc = enable_endpoint(common, fsg->bulk_in, d); + /* Allocate the requests */ + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + rc = alloc_request(common, fsg->bulk_in, &bh->inreq); if (rc) goto reset; - fsg->bulk_in_enabled = 1; - - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); - rc = enable_endpoint(common, fsg->bulk_out, d); + rc = alloc_request(common, fsg->bulk_out, &bh->outreq); if (rc) goto reset; - fsg->bulk_out_enabled = 1; - common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); - clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - - /* Allocate the requests */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - struct fsg_buffhd *bh = &common->buffhds[i]; - - rc = alloc_request(common, fsg->bulk_in, &bh->inreq); - if (rc) - goto reset; - rc = alloc_request(common, fsg->bulk_out, &bh->outreq); - if (rc) - goto reset; - bh->inreq->buf = bh->outreq->buf = bh->buf; - bh->inreq->context = bh->outreq->context = bh; - bh->inreq->complete = bulk_in_complete; - bh->outreq->complete = bulk_out_complete; - } - - common->running = 1; - for (i = 0; i < common->nluns; ++i) - common->luns[i].unit_attention_data = SS_RESET_OCCURRED; - return rc; - } else { - return -EIO; - } -} - - -/* - * Change our operational configuration. This code must agree with the code - * that returns config descriptors, and with interface altsetting code. - * - * It's also responsible for power management interactions. Some - * configurations might not work with our current power sources. - * For now we just assume the gadget is always self-powered. - */ -static int do_set_config(struct fsg_common *common, u8 new_config) -{ - int rc = 0; - - /* Disable the single interface */ - if (common->config != 0) { - DBG(common, "reset config\n"); - common->config = 0; - rc = do_set_interface(common, -1); + bh->inreq->buf = bh->outreq->buf = bh->buf; + bh->inreq->context = bh->outreq->context = bh; + bh->inreq->complete = bulk_in_complete; + bh->outreq->complete = bulk_out_complete; } - /* Enable the interface */ - if (new_config != 0) { - common->config = new_config; - rc = do_set_interface(common, 0); - if (rc != 0) - common->config = 0; /* Reset on errors */ - } + common->running = 1; + for (i = 0; i < common->nluns; ++i) + common->luns[i].unit_attention_data = SS_RESET_OCCURRED; return rc; } @@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config) static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->prev_fsg = fsg->common->fsg; - fsg->common->fsg = fsg; - fsg->common->new_config = 1; + fsg->common->new_fsg = fsg; raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); return 0; } @@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) static void fsg_disable(struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->prev_fsg = fsg->common->fsg; - fsg->common->fsg = fsg; - fsg->common->new_config = 0; + fsg->common->new_fsg = NULL; raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); } @@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f) static void handle_exception(struct fsg_common *common) { siginfo_t info; - int sig; int i; struct fsg_buffhd *bh; enum fsg_state old_state; - u8 new_config; struct fsg_lun *curlun; unsigned int exception_req_tag; - int rc; /* Clear the existing signals. Anything but SIGUSR1 is converted * into a high-priority EXIT exception. */ for (;;) { - sig = dequeue_signal_lock(current, ¤t->blocked, &info); + int sig = + dequeue_signal_lock(current, ¤t->blocked, &info); if (!sig) break; if (sig != SIGUSR1) { @@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common) } /* Cancel all the pending transfers */ - if (fsg_is_set(common)) { + if (likely(common->fsg)) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) { bh = &common->buffhds[i]; if (bh->inreq_busy) @@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common) common->next_buffhd_to_fill = &common->buffhds[0]; common->next_buffhd_to_drain = &common->buffhds[0]; exception_req_tag = common->exception_req_tag; - new_config = common->new_config; old_state = common->state; if (old_state == FSG_STATE_ABORT_BULK_OUT) @@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common) break; case FSG_STATE_CONFIG_CHANGE: - rc = do_set_config(common, new_config); + do_set_interface(common, common->new_fsg); break; case FSG_STATE_EXIT: case FSG_STATE_TERMINATED: - do_set_config(common, 0); /* Free resources */ + do_set_interface(common, NULL); /* Free resources */ spin_lock_irq(&common->lock); common->state = FSG_STATE_TERMINATED; /* Stop the thread */ spin_unlock_irq(&common->lock); @@ -2863,6 +2816,7 @@ buffhds_first_it: goto error_release; } init_completion(&common->thread_notifier); + init_waitqueue_head(&common->fsg_wait); #undef OR @@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref) static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); + struct fsg_common *common = fsg->common; DBG(fsg, "unbind\n"); - fsg_common_put(fsg->common); + if (fsg->common->fsg == fsg) { + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + /* FIXME: make interruptible or killable somehow? */ + wait_event(common->fsg_wait, common->fsg != fsg); + } + + fsg_common_put(common); usb_free_descriptors(fsg->function.descriptors); usb_free_descriptors(fsg->function.hs_descriptors); kfree(fsg); @@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); struct usb_gadget *gadget = c->cdev->gadget; - int rc; int i; struct usb_ep *ep; @@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ep->driver_data = fsg->common; /* claim the endpoint */ fsg->bulk_out = ep; + /* Copy descriptors */ + f->descriptors = usb_copy_descriptors(fsg_fs_function); + if (unlikely(!f->descriptors)) + return -ENOMEM; + if (gadget_is_dualspeed(gadget)) { /* Assume endpoint addresses are the same for both speeds */ fsg_hs_bulk_in_desc.bEndpointAddress = @@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg_hs_bulk_out_desc.bEndpointAddress = fsg_fs_bulk_out_desc.bEndpointAddress; f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); - if (unlikely(!f->hs_descriptors)) + if (unlikely(!f->hs_descriptors)) { + usb_free_descriptors(f->descriptors); return -ENOMEM; + } } return 0; autoconf_fail: ERROR(fsg, "unable to autoconfigure all endpoints\n"); - rc = -ENOTSUPP; - return rc; + return -ENOTSUPP; } @@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev, fsg->function.name = FSG_DRIVER_DESC; fsg->function.strings = fsg_strings_array; - fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function); - if (unlikely(!fsg->function.descriptors)) { - rc = -ENOMEM; - goto error_free_fsg; - } fsg->function.bind = fsg_bind; fsg->function.unbind = fsg_unbind; fsg->function.setup = fsg_setup; @@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev, rc = usb_add_function(c, &fsg->function); if (unlikely(rc)) - goto error_free_all; - - fsg_common_get(fsg->common); - return 0; - -error_free_all: - usb_free_descriptors(fsg->function.descriptors); - /* fsg_bind() might have copied those; or maybe not? who cares - * -- free it just in case. */ - usb_free_descriptors(fsg->function.hs_descriptors); -error_free_fsg: - kfree(fsg); - + kfree(fsg); + else + fsg_common_get(fsg->common); return rc; } diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 4b0e4a040d6f..d1af253a9105 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c, if (unlikely(ret < 0)) return ret; + /* After previous do_configs there may be some invalid + * pointers in c->interface array. This happens every time + * a user space function with fewer interfaces than a user + * space function that was run before the new one is run. The + * compasit's set_config() assumes that if there is no more + * then MAX_CONFIG_INTERFACES interfaces in a configuration + * then there is a NULL pointer after the last interface in + * c->interface array. We need to make sure this is true. */ + if (c->next_interface_id < ARRAY_SIZE(c->interface)) + c->interface[c->next_interface_id] = NULL; + return 0; } diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 43abf55d8c60..4c3ac5c42237 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -82,7 +82,7 @@ static struct class *usb_gadget_class; struct printer_dev { spinlock_t lock; /* lock this structure */ /* lock buffer lists during read/write calls */ - spinlock_t lock_printer_io; + struct mutex lock_printer_io; struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ u8 config; @@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) DBG(dev, "printer_read trying to read %d bytes\n", (int)len); - spin_lock(&dev->lock_printer_io); + mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); /* We will use this flag later to check if a printer reset happened @@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) * call or not. */ if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) if (dev->reset_printer) { list_add(¤t_rx_req->list, &dev->rx_reqs); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) dev->current_rx_buf = current_rx_buf; spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied); @@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (len == 0) return -EINVAL; - spin_lock(&dev->lock_printer_io); + mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); /* Check if a printer reset happens while we have interrupts on */ @@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) * a NON-Blocking call or not. */ if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (copy_from_user(req->buf, buf, size)) { list_add(&req->list, &dev->tx_reqs); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return bytes_copied; } @@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (dev->reset_printer) { list_add(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) { list_add(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) } spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied); @@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait) unsigned long flags; int status = 0; - spin_lock(&dev->lock_printer_io); + mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); setup_rx_reqs(dev); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); poll_wait(fd, &dev->rx_wait, wait); poll_wait(fd, &dev->tx_wait, wait); @@ -1461,7 +1461,7 @@ autoconf_fail: } spin_lock_init(&dev->lock); - spin_lock_init(&dev->lock_printer_io); + mutex_init(&dev->lock_printer_io); INIT_LIST_HEAD(&dev->tx_reqs); INIT_LIST_HEAD(&dev->tx_reqs_active); INIT_LIST_HEAD(&dev->rx_reqs); @@ -1594,7 +1594,7 @@ cleanup(void) { int status; - spin_lock(&usb_printer_gadget.lock_printer_io); + mutex_lock(&usb_printer_gadget.lock_printer_io); class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 2); @@ -1602,6 +1602,6 @@ cleanup(void) if (status) ERROR(dev, "usb_gadget_unregister_driver %x\n", status); - spin_unlock(&usb_printer_gadget.lock_printer_io); + mutex_unlock(&usb_printer_gadget.lock_printer_io); } module_exit(cleanup); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index d5f4c1d45c97..e724a051bfdd 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1700,9 +1700,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!driver || driver != udc->driver || !driver->unbind) return -EINVAL; - dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n", + dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n", driver->driver.name); + /* report disconnect */ + if (driver->disconnect) + driver->disconnect(&udc->gadget); + driver->unbind(&udc->gadget); device_del(&udc->gadget.dev); diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 16bdf77f582a..3e8dcb5455e3 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -536,17 +536,11 @@ recycle: list_move(&req->list, &port->read_pool); } - /* Push from tty to ldisc; this is immediate with low_latency, and - * may trigger callbacks to this driver ... so drop the spinlock. + /* Push from tty to ldisc; without low_latency set this is handled by + * a workqueue, so we won't get callbacks and can hold port_lock */ if (tty && do_push) { - spin_unlock_irq(&port->port_lock); tty_flip_buffer_push(tty); - wake_up_interruptible(&tty->read_wait); - spin_lock_irq(&port->port_lock); - - /* tty may have been closed */ - tty = port->port_tty; } @@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file) port->open_count = 1; port->openclose = false; - /* low_latency means ldiscs work in tasklet context, without - * needing a workqueue schedule ... easier to keep up. - */ - tty->low_latency = 1; - /* if connected, start the I/O stream */ if (port->port_usb) { struct gserial *gser = port->port_usb; @@ -1195,6 +1184,7 @@ void gserial_cleanup(void) n_ports = 0; tty_unregister_driver(gs_tty_driver); + put_tty_driver(gs_tty_driver); gs_tty_driver = NULL; pr_debug("%s: cleaned up ttyGS* support\n", __func__); diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 544ccfd7056e..bd4027745aa7 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) /* Initialize the transceiver */ if (pdata->otg) { pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; - if (otg_init(pdata->otg) != 0) - dev_err(dev, "unable to init transceiver\n"); - else if (otg_set_vbus(pdata->otg, 1) != 0) + ret = otg_init(pdata->otg); + if (ret) { + dev_err(dev, "unable to init transceiver, probably missing\n"); + ret = -ENODEV; + goto err_add; + } + ret = otg_set_vbus(pdata->otg, 1); + if (ret) { dev_err(dev, "unable to enable vbus on transceiver\n"); + goto err_add; + } } priv->hcd = hcd; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 20a0dfe0fe36..0587ad4ce5c2 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) /*-------------------------------------------------------------------------*/ -static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) +static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) { int tmp = 20; - unsigned long flags; - - spin_lock_irqsave(&isp1362_hcd->lock, flags); isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC); isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR); @@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) } if (!tmp) pr_err("Software reset timeout\n"); +} + +static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) +{ + unsigned long flags; + + spin_lock_irqsave(&isp1362_hcd->lock, flags); + __isp1362_sw_reset(isp1362_hcd); spin_unlock_irqrestore(&isp1362_hcd->lock, flags); } @@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd) if (isp1362_hcd->board && isp1362_hcd->board->reset) isp1362_hcd->board->reset(hcd->self.controller, 1); else - isp1362_sw_reset(isp1362_hcd); + __isp1362_sw_reset(isp1362_hcd); if (isp1362_hcd->board && isp1362_hcd->board->clock) isp1362_hcd->board->clock(hcd->self.controller, 0); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 1a2bb4ce638f..77be3c24a427 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port) else if (speed == LSMODE) rh->port |= USB_PORT_STAT_LOW_SPEED; - rh->port &= USB_PORT_STAT_RESET; + rh->port &= ~USB_PORT_STAT_RESET; rh->port |= USB_PORT_STAT_ENABLE; } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9012098add6b..94e6934edb09 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer * set, but other sections talk about dealing with the chain bit set. This was * fixed in the 0.96 specification errata, but we have to assume that all 0.95 * xHCI hardware can't handle the chain bit being cleared on a link TRB. + * + * @more_trbs_coming: Will you enqueue more TRBs before calling + * prepare_transfer()? */ -static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer) +static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, + bool consumer, bool more_trbs_coming) { u32 chain; union xhci_trb *next; @@ -199,15 +203,28 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer while (last_trb(xhci, ring, ring->enq_seg, next)) { if (!consumer) { if (ring != xhci->event_ring) { - if (chain) { - next->link.control |= TRB_CHAIN; - - /* Give this link TRB to the hardware */ - wmb(); - next->link.control ^= TRB_CYCLE; - } else { + /* + * If the caller doesn't plan on enqueueing more + * TDs before ringing the doorbell, then we + * don't want to give the link TRB to the + * hardware just yet. We'll give the link TRB + * back in prepare_ring() just before we enqueue + * the TD at the top of the ring. + */ + if (!chain && !more_trbs_coming) break; + + /* If we're not dealing with 0.95 hardware, + * carry over the chain bit of the previous TRB + * (which may mean the chain bit is cleared). + */ + if (!xhci_link_trb_quirk(xhci)) { + next->link.control &= ~TRB_CHAIN; + next->link.control |= chain; } + /* Give this link TRB to the hardware */ + wmb(); + next->link.control ^= TRB_CYCLE; } /* Toggle the cycle bit after the last ring segment. */ if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) { @@ -1707,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci) /* * Generic function for queueing a TRB on a ring. * The caller must have checked to make sure there's room on the ring. + * + * @more_trbs_coming: Will you enqueue more TRBs before calling + * prepare_transfer()? */ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, - bool consumer, + bool consumer, bool more_trbs_coming, u32 field1, u32 field2, u32 field3, u32 field4) { struct xhci_generic_trb *trb; @@ -1719,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, trb->field[1] = field2; trb->field[2] = field3; trb->field[3] = field4; - inc_enq(xhci, ring, consumer); + inc_enq(xhci, ring, consumer, more_trbs_coming); } /* @@ -1988,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int trb_buff_len, this_sg_len, running_total; bool first_trb; u64 addr; + bool more_trbs_coming; struct xhci_generic_trb *start_trb; int start_cycle; @@ -2073,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, length_field = TRB_LEN(trb_buff_len) | remainder | TRB_INTR_TARGET(0); - queue_trb(xhci, ep_ring, false, + if (num_trbs > 1) + more_trbs_coming = true; + else + more_trbs_coming = false; + queue_trb(xhci, ep_ring, false, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), length_field, @@ -2124,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int num_trbs; struct xhci_generic_trb *start_trb; bool first_trb; + bool more_trbs_coming; int start_cycle; u32 field, length_field; @@ -2212,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, length_field = TRB_LEN(trb_buff_len) | remainder | TRB_INTR_TARGET(0); - queue_trb(xhci, ep_ring, false, + if (num_trbs > 1) + more_trbs_coming = true; + else + more_trbs_coming = false; + queue_trb(xhci, ep_ring, false, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), length_field, @@ -2291,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Queue setup TRB - see section 6.4.1.2.1 */ /* FIXME better way to translate setup_packet into two u32 fields? */ setup = (struct usb_ctrlrequest *) urb->setup_packet; - queue_trb(xhci, ep_ring, false, + queue_trb(xhci, ep_ring, false, true, /* FIXME endianness is probably going to bite my ass here. */ setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16, setup->wIndex | setup->wLength << 16, @@ -2307,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (urb->transfer_buffer_length > 0) { if (setup->bRequestType & USB_DIR_IN) field |= TRB_DIR_IN; - queue_trb(xhci, ep_ring, false, + queue_trb(xhci, ep_ring, false, true, lower_32_bits(urb->transfer_dma), upper_32_bits(urb->transfer_dma), length_field, @@ -2324,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field = 0; else field = TRB_DIR_IN; - queue_trb(xhci, ep_ring, false, + queue_trb(xhci, ep_ring, false, false, 0, 0, TRB_INTR_TARGET(0), @@ -2361,7 +2391,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2, "unfailable commands failed.\n"); return -ENOMEM; } - queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3, + queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3, field4 | xhci->cmd_ring->cycle_state); return 0; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fad70bc83555..3b795c56221f 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg, return 0; } #else -#define musb_ulpi_read(a, b) NULL -#define musb_ulpi_write(a, b, c) NULL +#define musb_ulpi_read NULL +#define musb_ulpi_write NULL #endif static struct otg_io_access_ops musb_ulpi_access = { @@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb) * @param power */ -#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \ - | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \ - | MUSB_INTR_RESET) - static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, u8 devctl, u8 power) { @@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, handled = IRQ_HANDLED; } - +#endif if (int_usb & MUSB_INTR_SUSPEND) { DBG(1, "SUSPEND (%s) devctl %02x power %02x\n", otg_state_string(musb), devctl, power); @@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, } } +#ifdef CONFIG_USB_MUSB_HDRC_HCD if (int_usb & MUSB_INTR_CONNECT) { struct usb_hcd *hcd = musb_to_hcd(musb); void __iomem *mbase = musb->mregs; @@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb) /* the core can interrupt us for multiple reasons; docs have * a generic interrupt flowchart to follow */ - if (musb->int_usb & STAGE0_MASK) + if (musb->int_usb) retval |= musb_stage0_irq(musb, musb->int_usb, devctl, power); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index b22d02dea7d3..91d67794e350 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -470,7 +470,8 @@ struct musb_csr_regs { struct musb_context_registers { -#ifdef CONFIG_PM +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) u32 otg_sysconfig, otg_forcestandby; #endif u8 power; @@ -484,7 +485,8 @@ struct musb_context_registers { struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; }; -#ifdef CONFIG_PM +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) extern void musb_platform_save_context(struct musb *musb, struct musb_context_registers *musb_context); extern void musb_platform_restore_context(struct musb *musb, diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 1008044a3bbc..dc66e4376d49 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel, if (mode) { csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; BUG_ON(len < packet_sz); - - if (packet_sz >= 64) { - csr |= MUSB_HSDMA_BURSTMODE_INCR16 - << MUSB_HSDMA_BURSTMODE_SHIFT; - } else if (packet_sz >= 32) { - csr |= MUSB_HSDMA_BURSTMODE_INCR8 - << MUSB_HSDMA_BURSTMODE_SHIFT; - } else if (packet_sz >= 16) { - csr |= MUSB_HSDMA_BURSTMODE_INCR4 - << MUSB_HSDMA_BURSTMODE_SHIFT; - } } + csr |= MUSB_HSDMA_BURSTMODE_INCR16 + << MUSB_HSDMA_BURSTMODE_SHIFT; csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) | (1 << MUSB_HSDMA_ENABLE_SHIFT) diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index b1b346932946..d331b222ad21 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg) static int ulpi_init(struct otg_transceiver *otg) { - int i, vid, pid; - - vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) | - otg_io_read(otg, ULPI_VENDOR_ID_LOW); - pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) | - otg_io_read(otg, ULPI_PRODUCT_ID_LOW); + int i, vid, pid, ret; + u32 ulpi_id = 0; + + for (i = 0; i < 4; i++) { + ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i); + if (ret < 0) + return ret; + ulpi_id = (ulpi_id << 8) | ret; + } + vid = ulpi_id & 0xffff; + pid = ulpi_id >> 16; pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 79dd1ae195e5..da7e334b0407 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, - { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 94d86c3febcb..bbc159a1df45 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -501,13 +501,6 @@ #define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ /* - * Contec products (http://www.contec.com) - * Submitted by Daniel Sangorrin - */ -#define CONTEC_VID 0x06CE /* Vendor ID */ -#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ - -/* * Definitions for B&B Electronics products. */ #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 04bb759536bb..93d72eb8cafc 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -139,6 +139,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) "Could not set interface, error %d\n", retval); retval = -ENODEV; + kfree(data); } return retval; } @@ -155,6 +156,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) "Could not set interface, error %d\n", retval); retval = -ENODEV; + kfree(data); } return retval; } @@ -163,6 +165,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) default: dev_err(&serial->dev->dev, "unknown number of interfaces: %d\n", nintf); + kfree(data); return -ENODEV; } diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 0f41c9195e9b..df5b6b971f26 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -637,7 +637,7 @@ const static struct file_operations vhost_net_fops = { }; static struct miscdevice vhost_net_misc = { - VHOST_NET_MINOR, + MISC_DYNAMIC_MINOR, "vhost-net", &vhost_net_fops, }; diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 76e7dac6f259..70b1d9d51c96 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c @@ -40,7 +40,7 @@ static int vram; static int vt_switch; /* Modes relevant to the GX (taken from modedb.c) */ -static struct fb_videomode gx_modedb[] __initdata = { +static struct fb_videomode gx_modedb[] __devinitdata = { /* 640x480-60 VESA */ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -110,14 +110,15 @@ static struct fb_videomode gx_modedb[] __initdata = { #ifdef CONFIG_OLPC #include <asm/olpc.h> -static struct fb_videomode gx_dcon_modedb[] __initdata = { +static struct fb_videomode gx_dcon_modedb[] __devinitdata = { /* The only mode the DCON has is 1200x900 */ { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 } }; -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, + unsigned int *size) { if (olpc_has_dcon()) { *modedb = (struct fb_videomode *) gx_dcon_modedb; @@ -129,7 +130,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) } #else -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, + unsigned int *size) { *modedb = (struct fb_videomode *) gx_modedb; *size = ARRAY_SIZE(gx_modedb); @@ -226,7 +228,8 @@ static int gxfb_blank(int blank_mode, struct fb_info *info) return gx_blank_display(info, blank_mode); } -static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) +static int __devinit gxfb_map_video_memory(struct fb_info *info, + struct pci_dev *dev) { struct gxfb_par *par = info->par; int ret; @@ -290,7 +293,7 @@ static struct fb_ops gxfb_ops = { .fb_imageblit = cfb_imageblit, }; -static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) +static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev) { struct gxfb_par *par; struct fb_info *info; @@ -371,7 +374,8 @@ static int gxfb_resume(struct pci_dev *pdev) } #endif -static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int __devinit gxfb_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { struct gxfb_par *par; struct fb_info *info; @@ -451,7 +455,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i return ret; } -static void gxfb_remove(struct pci_dev *pdev) +static void __devexit gxfb_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); struct gxfb_par *par = info->par; diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index 1a18da86d3fa..39bdbedf43b4 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c @@ -35,7 +35,7 @@ static int vt_switch; * we try to make it something sane - 640x480-60 is sane */ -static struct fb_videomode geode_modedb[] __initdata = { +static struct fb_videomode geode_modedb[] __devinitdata = { /* 640x480-60 */ { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, @@ -219,14 +219,15 @@ static struct fb_videomode geode_modedb[] __initdata = { #ifdef CONFIG_OLPC #include <asm/olpc.h> -static struct fb_videomode olpc_dcon_modedb[] __initdata = { +static struct fb_videomode olpc_dcon_modedb[] __devinitdata = { /* The only mode the DCON has is 1200x900 */ { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 } }; -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, + unsigned int *size) { if (olpc_has_dcon()) { *modedb = (struct fb_videomode *) olpc_dcon_modedb; @@ -238,7 +239,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) } #else -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, + unsigned int *size) { *modedb = (struct fb_videomode *) geode_modedb; *size = ARRAY_SIZE(geode_modedb); @@ -334,7 +336,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info) } -static int __init lxfb_map_video_memory(struct fb_info *info, +static int __devinit lxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) { struct lxfb_par *par = info->par; @@ -412,7 +414,7 @@ static struct fb_ops lxfb_ops = { .fb_imageblit = cfb_imageblit, }; -static struct fb_info * __init lxfb_init_fbinfo(struct device *dev) +static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev) { struct lxfb_par *par; struct fb_info *info; @@ -496,7 +498,7 @@ static int lxfb_resume(struct pci_dev *pdev) #define lxfb_resume NULL #endif -static int __init lxfb_probe(struct pci_dev *pdev, +static int __devinit lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct lxfb_par *par; @@ -588,7 +590,7 @@ err: return ret; } -static void lxfb_remove(struct pci_dev *pdev) +static void __devexit lxfb_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); struct lxfb_par *par = info->par; diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index d4cde79ea15e..81687ed26ba9 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c @@ -596,8 +596,6 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev) goto release_regs; } - nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2); - fbi->clk = clk_get(&pdev->dev, NULL); if (!fbi->clk || IS_ERR(fbi->clk)) { printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index 43ab7d8b66b2..7767338f8b14 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c @@ -572,22 +572,12 @@ static enum omapfb_update_mode omap_lcdc_get_update_mode(void) /* PM code called only in internal controller mode */ static void omap_lcdc_suspend(void) { - if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { - disable_controller(); - omap_stop_lcd_dma(); - } + omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED); } static void omap_lcdc_resume(void) { - if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { - setup_regs(); - load_palette(); - setup_lcd_dma(); - set_load_mode(OMAP_LCDC_LOAD_FRAME); - enable_irqs(OMAP_LCDC_IRQ_DONE); - enable_controller(); - } + omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE); } static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps) diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index 1162603c72e5..eada9f12efc7 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c @@ -26,6 +26,7 @@ #include <linux/interrupt.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/platform_device.h> #include "omapfb.h" #include "dispc.h" @@ -83,13 +84,13 @@ static inline u32 rfbi_read_reg(int idx) static int rfbi_get_clocks(void) { - rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick"); + rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick"); if (IS_ERR(rfbi.dss_ick)) { dev_err(rfbi.fbdev->dev, "can't get ick\n"); return PTR_ERR(rfbi.dss_ick); } - rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck"); + rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck"); if (IS_ERR(rfbi.dss1_fck)) { dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); clk_put(rfbi.dss_ick); diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 95896f387927..ef8d9d558fc7 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -636,6 +636,9 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, INIT_LIST_HEAD(&vp_dev->virtqueues); spin_lock_init(&vp_dev->lock); + /* Disable MSI/MSIX to bring device to a known good state. */ + pci_msi_off(pci_dev); + /* enable the device */ err = pci_enable_device(pci_dev); if (err) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 1ca88908723b..afe7e21dd0ae 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -119,7 +119,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq, desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); if (!desc) - return vq->vring.num; + return -ENOMEM; /* Transfer entries from the sg list into the indirect page */ for (i = 0; i < out; i++) { diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 1cddf92cb9a6..750bc5281d79 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -346,9 +346,13 @@ static int __init at32_wdt_probe(struct platform_device *pdev) } else { wdt->users = 0; } - wdt->miscdev.minor = WATCHDOG_MINOR; - wdt->miscdev.name = "watchdog"; - wdt->miscdev.fops = &at32_wdt_fops; + + wdt->miscdev.minor = WATCHDOG_MINOR; + wdt->miscdev.name = "watchdog"; + wdt->miscdev.fops = &at32_wdt_fops; + wdt->miscdev.parent = &pdev->dev; + + platform_set_drvdata(pdev, wdt); if (at32_wdt_settimeout(timeout)) { at32_wdt_settimeout(TIMEOUT_DEFAULT); @@ -360,17 +364,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev) ret = misc_register(&wdt->miscdev); if (ret) { dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); - goto err_iounmap; + goto err_register; } - platform_set_drvdata(pdev, wdt); - wdt->miscdev.parent = &pdev->dev; dev_info(&pdev->dev, "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n", wdt->regs, wdt->timeout, nowayout); return 0; +err_register: + platform_set_drvdata(pdev, NULL); err_iounmap: iounmap(wdt->regs); err_free: diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index ea25885781bb..2ee7dac55a3c 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -330,7 +330,6 @@ static void imx2_wdt_shutdown(struct platform_device *pdev) } static struct platform_driver imx2_wdt_driver = { - .probe = imx2_wdt_probe, .remove = __exit_p(imx2_wdt_remove), .shutdown = imx2_wdt_shutdown, .driver = { diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index 89dd7b035295..b68d928c8f90 100644 --- a/drivers/watchdog/wm8350_wdt.c +++ b/drivers/watchdog/wm8350_wdt.c @@ -284,7 +284,7 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev) struct wm8350 *wm8350 = platform_get_drvdata(pdev); if (!wm8350) { - dev_err(wm8350->dev, "No driver data supplied\n"); + pr_err("No driver data supplied\n"); return -ENODEV; } diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index b6ab27ccf214..811384bec8de 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -68,11 +68,7 @@ * Here we can be a bit looser than the data sections since this * needs to only meet arch ABI requirements. */ -#ifdef ARCH_SLAB_MINALIGN -#define FLAT_STACK_ALIGN (ARCH_SLAB_MINALIGN) -#else -#define FLAT_STACK_ALIGN (sizeof(void *)) -#endif +#define FLAT_STACK_ALIGN max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN) #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ diff --git a/fs/block_dev.c b/fs/block_dev.c index 7346c96308a5..99d6af811747 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -706,8 +706,13 @@ retry: * @bdev is about to be opened exclusively. Check @bdev can be opened * exclusively and mark that an exclusive open is in progress. Each * successful call to this function must be matched with a call to - * either bd_claim() or bd_abort_claiming(). If this function - * succeeds, the matching bd_claim() is guaranteed to succeed. + * either bd_finish_claiming() or bd_abort_claiming() (which do not + * fail). + * + * This function is used to gain exclusive access to the block device + * without actually causing other exclusive open attempts to fail. It + * should be used when the open sequence itself requires exclusive + * access but may subsequently fail. * * CONTEXT: * Might sleep. @@ -734,6 +739,7 @@ static struct block_device *bd_start_claiming(struct block_device *bdev, return ERR_PTR(-ENXIO); whole = bdget_disk(disk, 0); + module_put(disk->fops->owner); put_disk(disk); if (!whole) return ERR_PTR(-ENOMEM); @@ -782,15 +788,46 @@ static void bd_abort_claiming(struct block_device *whole, void *holder) __bd_abort_claiming(whole, holder); /* releases bdev_lock */ } +/* increment holders when we have a legitimate claim. requires bdev_lock */ +static void __bd_claim(struct block_device *bdev, struct block_device *whole, + void *holder) +{ + /* note that for a whole device bd_holders + * will be incremented twice, and bd_holder will + * be set to bd_claim before being set to holder + */ + whole->bd_holders++; + whole->bd_holder = bd_claim; + bdev->bd_holders++; + bdev->bd_holder = holder; +} + +/** + * bd_finish_claiming - finish claiming a block device + * @bdev: block device of interest (passed to bd_start_claiming()) + * @whole: whole block device returned by bd_start_claiming() + * @holder: holder trying to claim @bdev + * + * Finish a claiming block started by bd_start_claiming(). + * + * CONTEXT: + * Grabs and releases bdev_lock. + */ +static void bd_finish_claiming(struct block_device *bdev, + struct block_device *whole, void *holder) +{ + spin_lock(&bdev_lock); + BUG_ON(!bd_may_claim(bdev, whole, holder)); + __bd_claim(bdev, whole, holder); + __bd_abort_claiming(whole, holder); /* not actually an abort */ +} + /** * bd_claim - claim a block device * @bdev: block device to claim * @holder: holder trying to claim @bdev * - * Try to claim @bdev which must have been opened successfully. This - * function may be called with or without preceding - * blk_start_claiming(). In the former case, this function is always - * successful and terminates the claiming block. + * Try to claim @bdev which must have been opened successfully. * * CONTEXT: * Might sleep. @@ -806,23 +843,10 @@ int bd_claim(struct block_device *bdev, void *holder) might_sleep(); spin_lock(&bdev_lock); - res = bd_prepare_to_claim(bdev, whole, holder); - if (res == 0) { - /* note that for a whole device bd_holders - * will be incremented twice, and bd_holder will - * be set to bd_claim before being set to holder - */ - whole->bd_holders++; - whole->bd_holder = bd_claim; - bdev->bd_holders++; - bdev->bd_holder = holder; - } - - if (whole->bd_claiming) - __bd_abort_claiming(whole, holder); /* releases bdev_lock */ - else - spin_unlock(&bdev_lock); + if (res == 0) + __bd_claim(bdev, whole, holder); + spin_unlock(&bdev_lock); return res; } @@ -1476,7 +1500,7 @@ static int blkdev_open(struct inode * inode, struct file * filp) if (whole) { if (res == 0) - BUG_ON(bd_claim(bdev, filp) != 0); + bd_finish_claiming(bdev, whole, filp); else bd_abort_claiming(whole, filp); } @@ -1712,7 +1736,7 @@ struct block_device *open_bdev_exclusive(const char *path, fmode_t mode, void *h if ((mode & FMODE_WRITE) && bdev_read_only(bdev)) goto out_blkdev_put; - BUG_ON(bd_claim(bdev, holder) != 0); + bd_finish_claiming(bdev, whole, holder); return bdev; out_blkdev_put: diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 8d432cd9d580..2222d161c7b6 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -60,6 +60,8 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) size = __btrfs_getxattr(inode, name, value, size); if (size > 0) { acl = posix_acl_from_xattr(value, size); + if (IS_ERR(acl)) + return acl; set_cached_acl(inode, type, acl); } kfree(value); @@ -160,6 +162,12 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, int ret; struct posix_acl *acl = NULL; + if (!is_owner_or_cap(dentry->d_inode)) + return -EPERM; + + if (!IS_POSIXACL(dentry->d_inode)) + return -EOPNOTSUPP; + if (value) { acl = posix_acl_from_xattr(value, size); if (acl == NULL) { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index f3b287c22caf..34f7c375567e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1941,8 +1941,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, btrfs_level_size(tree_root, btrfs_super_log_root_level(disk_super)); - log_tree_root = kzalloc(sizeof(struct btrfs_root), - GFP_NOFS); + log_tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); + if (!log_tree_root) { + err = -ENOMEM; + goto fail_trans_kthread; + } __setup_root(nodesize, leafsize, sectorsize, stripesize, log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID); @@ -1982,6 +1985,10 @@ struct btrfs_root *open_ctree(struct super_block *sb, fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); if (!fs_info->fs_root) goto fail_trans_kthread; + if (IS_ERR(fs_info->fs_root)) { + err = PTR_ERR(fs_info->fs_root); + goto fail_trans_kthread; + } if (!(sb->s_flags & MS_RDONLY)) { down_read(&fs_info->cleanup_work_sem); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b9080d71991a..32d094002a57 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4360,7 +4360,8 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, block_rsv = get_block_rsv(trans, root); cache = btrfs_lookup_block_group(root->fs_info, buf->start); - BUG_ON(block_rsv->space_info != cache->space_info); + if (block_rsv->space_info != cache->space_info) + goto out; if (btrfs_header_generation(buf) == trans->transid) { if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 787b50a16a14..e354c33df082 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1140,7 +1140,7 @@ int btrfs_sync_file(struct file *file, int datasync) /* * ok we haven't committed the transaction yet, lets do a commit */ - if (file && file->private_data) + if (file->private_data) btrfs_ioctl_trans_end(file); trans = btrfs_start_transaction(root, 0); @@ -1190,14 +1190,22 @@ static const struct vm_operations_struct btrfs_file_vm_ops = { static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma) { - vma->vm_ops = &btrfs_file_vm_ops; + struct address_space *mapping = filp->f_mapping; + + if (!mapping->a_ops->readpage) + return -ENOEXEC; + file_accessed(filp); + vma->vm_ops = &btrfs_file_vm_ops; + vma->vm_flags |= VM_CAN_NONLINEAR; + return 0; } const struct file_operations btrfs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, + .write = do_sync_write, .aio_read = generic_file_aio_read, .splice_read = generic_file_splice_read, .aio_write = btrfs_file_aio_write, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fa6ccc1bfe2a..1bff92ad4744 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2673,7 +2673,7 @@ static int check_path_shared(struct btrfs_root *root, struct extent_buffer *eb; int level; int ret; - u64 refs; + u64 refs = 1; for (level = 0; level < BTRFS_MAX_LEVEL; level++) { if (!path->nodes[level]) @@ -6884,7 +6884,7 @@ static long btrfs_fallocate(struct inode *inode, int mode, if (em->block_start == EXTENT_MAP_HOLE || (cur_offset >= inode->i_size && !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { - ret = btrfs_prealloc_file_range(inode, 0, cur_offset, + ret = btrfs_prealloc_file_range(inode, mode, cur_offset, last_byte - cur_offset, 1 << inode->i_blkbits, offset + len, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4cdb98cf26de..4dbaf89b1337 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1280,7 +1280,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) { err = PTR_ERR(trans); - goto out; + goto out_up_write; } trans->block_rsv = &root->fs_info->global_block_rsv; @@ -1845,7 +1845,7 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path, dir_id, "default", 7, 1); - if (!di) { + if (IS_ERR_OR_NULL(di)) { btrfs_free_path(path); btrfs_end_transaction(trans, root); printk(KERN_ERR "Umm, you don't have the default dir item, " diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 05d41e569236..b37d723b9d4a 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -784,16 +784,17 @@ again: struct btrfs_extent_ref_v0 *ref0; ref0 = btrfs_item_ptr(eb, path1->slots[0], struct btrfs_extent_ref_v0); - root = find_tree_root(rc, eb, ref0); - if (!root->ref_cows) - cur->cowonly = 1; if (key.objectid == key.offset) { + root = find_tree_root(rc, eb, ref0); if (root && !should_ignore_root(root)) cur->root = root; else list_add(&cur->list, &useless); break; } + if (is_cowonly_root(btrfs_ref_root_v0(eb, + ref0))) + cur->cowonly = 1; } #else BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY); diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index b91ccd972644..2d958be761c8 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -330,7 +330,6 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, { struct btrfs_path *path; int ret; - u32 refs; struct btrfs_root_item *ri; struct extent_buffer *leaf; @@ -344,8 +343,6 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, leaf = path->nodes[0]; ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item); - refs = btrfs_disk_root_refs(leaf, ri); - BUG_ON(refs != 0); ret = btrfs_del_item(trans, root, path); out: btrfs_free_path(path); diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index d34b2dfc9628..f2393b390318 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -360,6 +360,8 @@ static struct dentry *get_default_root(struct super_block *sb, */ dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0); + if (IS_ERR(di)) + return ERR_CAST(di); if (!di) { /* * Ok the default dir item isn't there. This is weird since @@ -390,8 +392,8 @@ setup_root: location.offset = 0; inode = btrfs_iget(sb, &location, new_root, &new); - if (!inode) - return ERR_PTR(-ENOMEM); + if (IS_ERR(inode)) + return ERR_CAST(inode); /* * If we're just mounting the root most subvol put the inode and return diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index ae3e3a306445..619b61655ee5 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -981,6 +981,46 @@ static int send_cap_msg(struct ceph_mds_session *session, return 0; } +static void __queue_cap_release(struct ceph_mds_session *session, + u64 ino, u64 cap_id, u32 migrate_seq, + u32 issue_seq) +{ + struct ceph_msg *msg; + struct ceph_mds_cap_release *head; + struct ceph_mds_cap_item *item; + + spin_lock(&session->s_cap_lock); + BUG_ON(!session->s_num_cap_releases); + msg = list_first_entry(&session->s_cap_releases, + struct ceph_msg, list_head); + + dout(" adding %llx release to mds%d msg %p (%d left)\n", + ino, session->s_mds, msg, session->s_num_cap_releases); + + BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE); + head = msg->front.iov_base; + head->num = cpu_to_le32(le32_to_cpu(head->num) + 1); + item = msg->front.iov_base + msg->front.iov_len; + item->ino = cpu_to_le64(ino); + item->cap_id = cpu_to_le64(cap_id); + item->migrate_seq = cpu_to_le32(migrate_seq); + item->seq = cpu_to_le32(issue_seq); + + session->s_num_cap_releases--; + + msg->front.iov_len += sizeof(*item); + if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) { + dout(" release msg %p full\n", msg); + list_move_tail(&msg->list_head, &session->s_cap_releases_done); + } else { + dout(" release msg %p at %d/%d (%d)\n", msg, + (int)le32_to_cpu(head->num), + (int)CEPH_CAPS_PER_RELEASE, + (int)msg->front.iov_len); + } + spin_unlock(&session->s_cap_lock); +} + /* * Queue cap releases when an inode is dropped from our cache. Since * inode is about to be destroyed, there is no need for i_lock. @@ -994,41 +1034,9 @@ void ceph_queue_caps_release(struct inode *inode) while (p) { struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node); struct ceph_mds_session *session = cap->session; - struct ceph_msg *msg; - struct ceph_mds_cap_release *head; - struct ceph_mds_cap_item *item; - spin_lock(&session->s_cap_lock); - BUG_ON(!session->s_num_cap_releases); - msg = list_first_entry(&session->s_cap_releases, - struct ceph_msg, list_head); - - dout(" adding %p release to mds%d msg %p (%d left)\n", - inode, session->s_mds, msg, session->s_num_cap_releases); - - BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE); - head = msg->front.iov_base; - head->num = cpu_to_le32(le32_to_cpu(head->num) + 1); - item = msg->front.iov_base + msg->front.iov_len; - item->ino = cpu_to_le64(ceph_ino(inode)); - item->cap_id = cpu_to_le64(cap->cap_id); - item->migrate_seq = cpu_to_le32(cap->mseq); - item->seq = cpu_to_le32(cap->issue_seq); - - session->s_num_cap_releases--; - - msg->front.iov_len += sizeof(*item); - if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) { - dout(" release msg %p full\n", msg); - list_move_tail(&msg->list_head, - &session->s_cap_releases_done); - } else { - dout(" release msg %p at %d/%d (%d)\n", msg, - (int)le32_to_cpu(head->num), - (int)CEPH_CAPS_PER_RELEASE, - (int)msg->front.iov_len); - } - spin_unlock(&session->s_cap_lock); + __queue_cap_release(session, ceph_ino(inode), cap->cap_id, + cap->mseq, cap->issue_seq); p = rb_next(p); __ceph_remove_cap(cap); } @@ -2655,7 +2663,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, struct ceph_mds_caps *h; int mds = session->s_mds; int op; - u32 seq; + u32 seq, mseq; struct ceph_vino vino; u64 cap_id; u64 size, max_size; @@ -2675,6 +2683,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, vino.snap = CEPH_NOSNAP; cap_id = le64_to_cpu(h->cap_id); seq = le32_to_cpu(h->seq); + mseq = le32_to_cpu(h->migrate_seq); size = le64_to_cpu(h->size); max_size = le64_to_cpu(h->max_size); @@ -2689,6 +2698,18 @@ void ceph_handle_caps(struct ceph_mds_session *session, vino.snap, inode); if (!inode) { dout(" i don't have ino %llx\n", vino.ino); + + if (op == CEPH_CAP_OP_IMPORT) + __queue_cap_release(session, vino.ino, cap_id, + mseq, seq); + + /* + * send any full release message to try to move things + * along for the mds (who clearly thinks we still have this + * cap). + */ + ceph_add_cap_releases(mdsc, session, -1); + ceph_send_cap_releases(mdsc, session); goto done; } @@ -2714,7 +2735,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, spin_lock(&inode->i_lock); cap = __get_cap_for_mds(ceph_inode(inode), mds); if (!cap) { - dout("no cap on %p ino %llx.%llx from mds%d, releasing\n", + dout(" no cap on %p ino %llx.%llx from mds%d\n", inode, ceph_ino(inode), ceph_snap(inode), mds); spin_unlock(&inode->i_lock); goto done; diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 226f5a50d362..ab47f46ca282 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -827,7 +827,7 @@ static void ceph_set_dentry_offset(struct dentry *dn) spin_lock(&dcache_lock); spin_lock(&dn->d_lock); - list_move_tail(&dir->d_subdirs, &dn->d_u.d_child); + list_move(&dn->d_u.d_child, &dir->d_subdirs); dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, dn->d_u.d_child.prev, dn->d_u.d_child.next); spin_unlock(&dn->d_lock); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index b49f12822cbc..1766947fc07a 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1066,9 +1066,9 @@ static int trim_caps(struct ceph_mds_client *mdsc, * * Called under s_mutex. */ -static int add_cap_releases(struct ceph_mds_client *mdsc, - struct ceph_mds_session *session, - int extra) +int ceph_add_cap_releases(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, + int extra) { struct ceph_msg *msg; struct ceph_mds_cap_release *head; @@ -1176,8 +1176,8 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) /* * called under s_mutex */ -static void send_cap_releases(struct ceph_mds_client *mdsc, - struct ceph_mds_session *session) +void ceph_send_cap_releases(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) { struct ceph_msg *msg; @@ -1980,7 +1980,7 @@ out_err: } mutex_unlock(&mdsc->mutex); - add_cap_releases(mdsc, req->r_session, -1); + ceph_add_cap_releases(mdsc, req->r_session, -1); mutex_unlock(&session->s_mutex); /* kick calling process */ @@ -2433,6 +2433,7 @@ static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_dentry_info *di; int mds = session->s_mds; struct ceph_mds_lease *h = msg->front.iov_base; + u32 seq; struct ceph_vino vino; int mask; struct qstr dname; @@ -2446,6 +2447,7 @@ static void handle_lease(struct ceph_mds_client *mdsc, vino.ino = le64_to_cpu(h->ino); vino.snap = CEPH_NOSNAP; mask = le16_to_cpu(h->mask); + seq = le32_to_cpu(h->seq); dname.name = (void *)h + sizeof(*h) + sizeof(u32); dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32); if (dname.len != get_unaligned_le32(h+1)) @@ -2456,8 +2458,9 @@ static void handle_lease(struct ceph_mds_client *mdsc, /* lookup inode */ inode = ceph_find_inode(sb, vino); - dout("handle_lease '%s', mask %d, ino %llx %p\n", - ceph_lease_op_name(h->action), mask, vino.ino, inode); + dout("handle_lease %s, mask %d, ino %llx %p %.*s\n", + ceph_lease_op_name(h->action), mask, vino.ino, inode, + dname.len, dname.name); if (inode == NULL) { dout("handle_lease no inode %llx\n", vino.ino); goto release; @@ -2482,7 +2485,8 @@ static void handle_lease(struct ceph_mds_client *mdsc, switch (h->action) { case CEPH_MDS_LEASE_REVOKE: if (di && di->lease_session == session) { - h->seq = cpu_to_le32(di->lease_seq); + if (ceph_seq_cmp(di->lease_seq, seq) > 0) + h->seq = cpu_to_le32(di->lease_seq); __ceph_mdsc_drop_dentry_lease(dentry); } release = 1; @@ -2496,7 +2500,7 @@ static void handle_lease(struct ceph_mds_client *mdsc, unsigned long duration = le32_to_cpu(h->duration_ms) * HZ / 1000; - di->lease_seq = le32_to_cpu(h->seq); + di->lease_seq = seq; dentry->d_time = di->lease_renew_from + duration; di->lease_renew_after = di->lease_renew_from + (duration >> 1); @@ -2686,10 +2690,10 @@ static void delayed_work(struct work_struct *work) send_renew_caps(mdsc, s); else ceph_con_keepalive(&s->s_con); - add_cap_releases(mdsc, s, -1); + ceph_add_cap_releases(mdsc, s, -1); if (s->s_state == CEPH_MDS_SESSION_OPEN || s->s_state == CEPH_MDS_SESSION_HUNG) - send_cap_releases(mdsc, s); + ceph_send_cap_releases(mdsc, s); mutex_unlock(&s->s_mutex); ceph_put_mds_session(s); diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index d9936c4f1212..b292fa42a66d 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -322,6 +322,12 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req) kref_put(&req->r_kref, ceph_mdsc_release_request); } +extern int ceph_add_cap_releases(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, + int extra); +extern void ceph_send_cap_releases(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session); + extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c index 21c62e9b7d1d..07a539906e67 100644 --- a/fs/ceph/mon_client.c +++ b/fs/ceph/mon_client.c @@ -400,6 +400,8 @@ static void release_generic_request(struct kref *kref) ceph_msg_put(req->reply); if (req->request) ceph_msg_put(req->request); + + kfree(req); } static void put_generic_request(struct ceph_mon_generic_request *req) diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 4e0bee240b9d..fa87f51e38e1 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -89,7 +89,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = le64_to_cpu(st.num_objects); buf->f_ffree = -1; - buf->f_namelen = PATH_MAX; + buf->f_namelen = NAME_MAX; buf->f_frsize = PAGE_CACHE_SIZE; /* leave fsid little-endian, regardless of host endianness */ @@ -926,7 +926,7 @@ static int ceph_compare_super(struct super_block *sb, void *data) /* * construct our own bdi so we can control readahead, etc. */ -static atomic_long_t bdi_seq = ATOMIC_INIT(0); +static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 78c02eb4cb1f..484e52bb40bb 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -473,14 +473,24 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data) return 0; } +void cifs_drop_inode(struct inode *inode) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) + return generic_drop_inode(inode); + + return generic_delete_inode(inode); +} + static const struct super_operations cifs_super_ops = { .put_super = cifs_put_super, .statfs = cifs_statfs, .alloc_inode = cifs_alloc_inode, .destroy_inode = cifs_destroy_inode, -/* .drop_inode = generic_delete_inode, - .delete_inode = cifs_delete_inode, */ /* Do not need above two - functions unless later we add lazy close of inodes or unless the + .drop_inode = cifs_drop_inode, +/* .delete_inode = cifs_delete_inode, */ /* Do not need above + function unless later we add lazy close of inodes or unless the kernel forgets to call us with the same number of releases (closes) as opens */ .show_options = cifs_show_options, diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fb1657e0fdb8..fb6318b81509 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, struct vfsmount *mnt, unsigned int oflags); extern int cifs_posix_open(char *full_path, struct inode **pinode, - struct vfsmount *mnt, struct super_block *sb, int mode, int oflags, __u32 *poplock, __u16 *pnetfid, int xid); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 391816b461ca..e7ae78b66fa1 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -25,6 +25,7 @@ #include <linux/slab.h> #include <linux/namei.h> #include <linux/mount.h> +#include <linux/file.h> #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -184,12 +185,13 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, } write_unlock(&GlobalSMBSeslock); + file->private_data = pCifsFile; + return pCifsFile; } int cifs_posix_open(char *full_path, struct inode **pinode, - struct vfsmount *mnt, struct super_block *sb, - int mode, int oflags, + struct super_block *sb, int mode, int oflags, __u32 *poplock, __u16 *pnetfid, int xid) { int rc; @@ -258,19 +260,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode, cifs_fattr_to_inode(*pinode, &fattr); } - /* - * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to - * file->private_data. - */ - if (mnt) { - struct cifsFileInfo *pfile_info; - - pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, - oflags); - if (pfile_info == NULL) - rc = -ENOMEM; - } - posix_open_ret: kfree(presp_data); return rc; @@ -298,7 +287,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, int create_options = CREATE_NOT_DIR; __u32 oplock = 0; int oflags; - bool posix_create = false; /* * BB below access is probably too much for mknod to request * but we have to do query and setpathinfo so requesting @@ -339,7 +327,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { rc = cifs_posix_open(full_path, &newinode, - nd ? nd->path.mnt : NULL, inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); /* EIO could indicate that (posix open) operation is not supported, despite what server claimed in capability @@ -347,7 +334,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, handled in posix open */ if (rc == 0) { - posix_create = true; if (newinode == NULL) /* query inode info */ goto cifs_create_get_file_info; else /* success, no need to query */ @@ -478,21 +464,28 @@ cifs_create_set_dentry: else cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); - /* nfsd case - nfs srv does not set nd */ - if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { - /* mknod case - do not leave file open */ - CIFSSMBClose(xid, tcon, fileHandle); - } else if (!(posix_create) && (newinode)) { + if (newinode && nd && (nd->flags & LOOKUP_OPEN)) { struct cifsFileInfo *pfile_info; - /* - * cifs_fill_filedata() takes care of setting cifsFileInfo - * pointer to file->private_data. - */ - pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL, + struct file *filp; + + filp = lookup_instantiate_filp(nd, direntry, generic_file_open); + if (IS_ERR(filp)) { + rc = PTR_ERR(filp); + CIFSSMBClose(xid, tcon, fileHandle); + goto cifs_create_out; + } + + pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp, nd->path.mnt, oflags); - if (pfile_info == NULL) + if (pfile_info == NULL) { + fput(filp); + CIFSSMBClose(xid, tcon, fileHandle); rc = -ENOMEM; + } + } else { + CIFSSMBClose(xid, tcon, fileHandle); } + cifs_create_out: kfree(buf); kfree(full_path); @@ -636,6 +629,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, bool posix_open = false; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + struct cifsFileInfo *cfile; struct inode *newInode = NULL; char *full_path = NULL; struct file *filp; @@ -703,7 +697,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && (nd->intent.open.flags & O_CREAT)) { - rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, + rc = cifs_posix_open(full_path, &newInode, parent_dir_inode->i_sb, nd->intent.open.create_mode, nd->intent.open.flags, &oplock, @@ -733,8 +727,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, else direntry->d_op = &cifs_dentry_ops; d_add(direntry, newInode); - if (posix_open) - filp = lookup_instantiate_filp(nd, direntry, NULL); + if (posix_open) { + filp = lookup_instantiate_filp(nd, direntry, + generic_file_open); + if (IS_ERR(filp)) { + rc = PTR_ERR(filp); + CIFSSMBClose(xid, pTcon, fileHandle); + goto lookup_out; + } + + cfile = cifs_new_fileinfo(newInode, fileHandle, filp, + nd->path.mnt, + nd->intent.open.flags); + if (cfile == NULL) { + fput(filp); + CIFSSMBClose(xid, pTcon, fileHandle); + rc = -ENOMEM; + goto lookup_out; + } + } /* since paths are not looked up by component - the parent directories are presumed to be good here */ renew_parental_timestamps(direntry); @@ -755,6 +766,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, is a common return code */ } +lookup_out: kfree(full_path); FreeXid(xid); return ERR_PTR(rc); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 75541af4b3db..409e4f523e61 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -162,44 +162,12 @@ psx_client_can_cache: return 0; } -static struct cifsFileInfo * -cifs_fill_filedata(struct file *file) -{ - struct list_head *tmp; - struct cifsFileInfo *pCifsFile = NULL; - struct cifsInodeInfo *pCifsInode = NULL; - - /* search inode for this file and fill in file->private_data */ - pCifsInode = CIFS_I(file->f_path.dentry->d_inode); - read_lock(&GlobalSMBSeslock); - list_for_each(tmp, &pCifsInode->openFileList) { - pCifsFile = list_entry(tmp, struct cifsFileInfo, flist); - if ((pCifsFile->pfile == NULL) && - (pCifsFile->pid == current->tgid)) { - /* mode set in cifs_create */ - - /* needed for writepage */ - pCifsFile->pfile = file; - file->private_data = pCifsFile; - break; - } - } - read_unlock(&GlobalSMBSeslock); - - if (file->private_data != NULL) { - return pCifsFile; - } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL)) - cERROR(1, "could not find file instance for " - "new file %p", file); - return NULL; -} - /* all arguments to this function must be checked for validity in caller */ -static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, - struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, +static inline int cifs_open_inode_helper(struct inode *inode, struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, char *full_path, int xid) { + struct cifsInodeInfo *pCifsInode = CIFS_I(inode); struct timespec temp; int rc; @@ -213,36 +181,35 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, /* if not oplocked, invalidate inode pages if mtime or file size changed */ temp = cifs_NTtimeToUnix(buf->LastWriteTime); - if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && - (file->f_path.dentry->d_inode->i_size == + if (timespec_equal(&inode->i_mtime, &temp) && + (inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) { cFYI(1, "inode unchanged on server"); } else { - if (file->f_path.dentry->d_inode->i_mapping) { + if (inode->i_mapping) { /* BB no need to lock inode until after invalidate since namei code should already have it locked? */ - rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); + rc = filemap_write_and_wait(inode->i_mapping); if (rc != 0) - CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; + pCifsInode->write_behind_rc = rc; } cFYI(1, "invalidating remote inode since open detected it " "changed"); - invalidate_remote_inode(file->f_path.dentry->d_inode); + invalidate_remote_inode(inode); } client_can_cache: if (pTcon->unix_ext) - rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode, - full_path, inode->i_sb, xid); + rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, + xid); else - rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, - full_path, buf, inode->i_sb, xid, NULL); + rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, + xid, NULL); if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = true; pCifsInode->clientCanCacheRead = true; - cFYI(1, "Exclusive Oplock granted on inode %p", - file->f_path.dentry->d_inode); + cFYI(1, "Exclusive Oplock granted on inode %p", inode); } else if ((*oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = true; @@ -256,7 +223,7 @@ int cifs_open(struct inode *inode, struct file *file) __u32 oplock; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; - struct cifsFileInfo *pCifsFile; + struct cifsFileInfo *pCifsFile = NULL; struct cifsInodeInfo *pCifsInode; char *full_path = NULL; int desiredAccess; @@ -270,12 +237,6 @@ int cifs_open(struct inode *inode, struct file *file) tcon = cifs_sb->tcon; pCifsInode = CIFS_I(file->f_path.dentry->d_inode); - pCifsFile = cifs_fill_filedata(file); - if (pCifsFile) { - rc = 0; - FreeXid(xid); - return rc; - } full_path = build_path_from_dentry(file->f_path.dentry); if (full_path == NULL) { @@ -299,8 +260,7 @@ int cifs_open(struct inode *inode, struct file *file) int oflags = (int) cifs_posix_convert_flags(file->f_flags); oflags |= SMB_O_CREAT; /* can not refresh inode info since size could be stale */ - rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, - inode->i_sb, + rc = cifs_posix_open(full_path, &inode, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, oflags, &oplock, &netfid, xid); if (rc == 0) { @@ -308,9 +268,20 @@ int cifs_open(struct inode *inode, struct file *file) /* no need for special case handling of setting mode on read only files needed here */ - pCifsFile = cifs_fill_filedata(file); - cifs_posix_open_inode_helper(inode, file, pCifsInode, - oplock, netfid); + rc = cifs_posix_open_inode_helper(inode, file, + pCifsInode, oplock, netfid); + if (rc != 0) { + CIFSSMBClose(xid, tcon, netfid); + goto out; + } + + pCifsFile = cifs_new_fileinfo(inode, netfid, file, + file->f_path.mnt, + oflags); + if (pCifsFile == NULL) { + CIFSSMBClose(xid, tcon, netfid); + rc = -ENOMEM; + } goto out; } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { if (tcon->ses->serverNOS) @@ -391,17 +362,17 @@ int cifs_open(struct inode *inode, struct file *file) goto out; } + rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid); + if (rc != 0) + goto out; + pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, file->f_flags); - file->private_data = pCifsFile; - if (file->private_data == NULL) { + if (pCifsFile == NULL) { rc = -ENOMEM; goto out; } - rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon, - &oplock, buf, full_path, xid); - if (oplock & CIFS_CREATE_ACTION) { /* time to set mode which we can not set earlier due to problems creating new read-only files */ @@ -513,8 +484,7 @@ reopen_error_exit: le64_to_cpu(tcon->fsUnixInfo.Capability))) { int oflags = (int) cifs_posix_convert_flags(file->f_flags); /* can not refresh inode info since size could be stale */ - rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, - inode->i_sb, + rc = cifs_posix_open(full_path, NULL, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, oflags, &oplock, &netfid, xid); if (rc == 0) { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 62b324f26a56..6f0683c68952 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1401,6 +1401,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, if (rc == 0 || rc != -ETXTBSY) return rc; + /* open-file renames don't work across directories */ + if (to_dentry->d_parent != from_dentry->d_parent) + return rc; + /* open the file to be renamed -- we need DELETE perms */ rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, CREATE_NOT_DIR, &srcfid, &oplock, NULL, diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 7707389bdf2c..0a57cb7db5dd 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -730,15 +730,7 @@ ssetup_ntlmssp_authenticate: /* calculate session key */ setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); - if (first_time) /* should this be moved into common code - with similar ntlmv2 path? */ - /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, - response BB FIXME, v2_sess_key); */ - - /* copy session key */ - - /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE); - bcc_ptr += LM2_SESS_KEY_SIZE; */ + /* FIXME: calculate MAC key */ memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp)); bcc_ptr += sizeof(struct ntlmv2_resp); diff --git a/fs/dcache.c b/fs/dcache.c index d96047b4a633..c8c78ba07827 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -590,6 +590,8 @@ static void prune_dcache(int count) up_read(&sb->s_umount); } spin_lock(&sb_lock); + /* lock was dropped, must reset next */ + list_safe_reset_next(sb, n, s_list); count -= pruned; __put_super(sb); /* more work left to do? */ diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index ca7e2a0ed98a..2bcc0431bada 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -200,6 +200,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) return error; else { inode->i_mode = mode; + inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); if (error == 0) acl = NULL; diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index 01552abbca3c..8a11fe212183 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -205,6 +205,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, return error; else { inode->i_mode = mode; + inode->i_ctime = CURRENT_TIME_SEC; ext3_mark_inode_dirty(handle, inode); if (error == 0) acl = NULL; diff --git a/fs/fcntl.c b/fs/fcntl.c index 51e11bf5708f..9d175d623aab 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -733,12 +733,14 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band) { while (fa) { struct fown_struct *fown; + unsigned long flags; + if (fa->magic != FASYNC_MAGIC) { printk(KERN_ERR "kill_fasync: bad magic number in " "fasync_struct!\n"); return; } - spin_lock(&fa->fa_lock); + spin_lock_irqsave(&fa->fa_lock, flags); if (fa->fa_file) { fown = &fa->fa_file->f_owner; /* Don't send SIGURG to processes which have not set a @@ -747,7 +749,7 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band) if (!(sig == SIGURG && fown->signum == 0)) send_sigio(fown, fa->fa_fd, band); } - spin_unlock(&fa->fa_lock); + spin_unlock_irqrestore(&fa->fa_lock, flags); fa = rcu_dereference(fa->fa_next); } } diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1d1088f48bc2..0609607d3955 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -63,24 +63,16 @@ struct bdi_work { }; enum { - WS_USED_B = 0, - WS_ONSTACK_B, + WS_INPROGRESS = 0, + WS_ONSTACK, }; -#define WS_USED (1 << WS_USED_B) -#define WS_ONSTACK (1 << WS_ONSTACK_B) - -static inline bool bdi_work_on_stack(struct bdi_work *work) -{ - return test_bit(WS_ONSTACK_B, &work->state); -} - static inline void bdi_work_init(struct bdi_work *work, struct wb_writeback_args *args) { INIT_RCU_HEAD(&work->rcu_head); work->args = *args; - work->state = WS_USED; + __set_bit(WS_INPROGRESS, &work->state); } /** @@ -95,43 +87,16 @@ int writeback_in_progress(struct backing_dev_info *bdi) return !list_empty(&bdi->work_list); } -static void bdi_work_clear(struct bdi_work *work) -{ - clear_bit(WS_USED_B, &work->state); - smp_mb__after_clear_bit(); - /* - * work can have disappeared at this point. bit waitq functions - * should be able to tolerate this, provided bdi_sched_wait does - * not dereference it's pointer argument. - */ - wake_up_bit(&work->state, WS_USED_B); -} - static void bdi_work_free(struct rcu_head *head) { struct bdi_work *work = container_of(head, struct bdi_work, rcu_head); - if (!bdi_work_on_stack(work)) - kfree(work); - else - bdi_work_clear(work); -} - -static void wb_work_complete(struct bdi_work *work) -{ - const enum writeback_sync_modes sync_mode = work->args.sync_mode; - int onstack = bdi_work_on_stack(work); + clear_bit(WS_INPROGRESS, &work->state); + smp_mb__after_clear_bit(); + wake_up_bit(&work->state, WS_INPROGRESS); - /* - * For allocated work, we can clear the done/seen bit right here. - * For on-stack work, we need to postpone both the clear and free - * to after the RCU grace period, since the stack could be invalidated - * as soon as bdi_work_clear() has done the wakeup. - */ - if (!onstack) - bdi_work_clear(work); - if (sync_mode == WB_SYNC_NONE || onstack) - call_rcu(&work->rcu_head, bdi_work_free); + if (!test_bit(WS_ONSTACK, &work->state)) + kfree(work); } static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work) @@ -147,7 +112,7 @@ static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work) list_del_rcu(&work->list); spin_unlock(&bdi->wb_lock); - wb_work_complete(work); + call_rcu(&work->rcu_head, bdi_work_free); } } @@ -185,9 +150,9 @@ static void bdi_queue_work(struct backing_dev_info *bdi, struct bdi_work *work) * Used for on-stack allocated work items. The caller needs to wait until * the wb threads have acked the work before it's safe to continue. */ -static void bdi_wait_on_work_clear(struct bdi_work *work) +static void bdi_wait_on_work_done(struct bdi_work *work) { - wait_on_bit(&work->state, WS_USED_B, bdi_sched_wait, + wait_on_bit(&work->state, WS_INPROGRESS, bdi_sched_wait, TASK_UNINTERRUPTIBLE); } @@ -213,37 +178,28 @@ static void bdi_alloc_queue_work(struct backing_dev_info *bdi, } /** - * bdi_sync_writeback - start and wait for writeback - * @bdi: the backing device to write from + * bdi_queue_work_onstack - start and wait for writeback * @sb: write inodes from this super_block * * Description: - * This does WB_SYNC_ALL data integrity writeback and waits for the - * IO to complete. Callers must hold the sb s_umount semaphore for + * This function initiates writeback and waits for the operation to + * complete. Callers must hold the sb s_umount semaphore for * reading, to avoid having the super disappear before we are done. */ -static void bdi_sync_writeback(struct backing_dev_info *bdi, - struct super_block *sb) +static void bdi_queue_work_onstack(struct wb_writeback_args *args) { - struct wb_writeback_args args = { - .sb = sb, - .sync_mode = WB_SYNC_ALL, - .nr_pages = LONG_MAX, - .range_cyclic = 0, - }; struct bdi_work work; - bdi_work_init(&work, &args); - work.state |= WS_ONSTACK; + bdi_work_init(&work, args); + __set_bit(WS_ONSTACK, &work.state); - bdi_queue_work(bdi, &work); - bdi_wait_on_work_clear(&work); + bdi_queue_work(args->sb->s_bdi, &work); + bdi_wait_on_work_done(&work); } /** * bdi_start_writeback - start writeback * @bdi: the backing device to write from - * @sb: write inodes from this super_block * @nr_pages: the number of pages to write * * Description: @@ -252,25 +208,34 @@ static void bdi_sync_writeback(struct backing_dev_info *bdi, * completion. Caller need not hold sb s_umount semaphore. * */ -void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb, - long nr_pages) +void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages) { struct wb_writeback_args args = { - .sb = sb, .sync_mode = WB_SYNC_NONE, .nr_pages = nr_pages, .range_cyclic = 1, }; - /* - * We treat @nr_pages=0 as the special case to do background writeback, - * ie. to sync pages until the background dirty threshold is reached. - */ - if (!nr_pages) { - args.nr_pages = LONG_MAX; - args.for_background = 1; - } + bdi_alloc_queue_work(bdi, &args); +} +/** + * bdi_start_background_writeback - start background writeback + * @bdi: the backing device to write from + * + * Description: + * This does WB_SYNC_NONE background writeback. The IO is only + * started when this function returns, we make no guarentees on + * completion. Caller need not hold sb s_umount semaphore. + */ +void bdi_start_background_writeback(struct backing_dev_info *bdi) +{ + struct wb_writeback_args args = { + .sync_mode = WB_SYNC_NONE, + .nr_pages = LONG_MAX, + .for_background = 1, + .range_cyclic = 1, + }; bdi_alloc_queue_work(bdi, &args); } @@ -561,48 +526,30 @@ select_queue: return ret; } -static void unpin_sb_for_writeback(struct super_block *sb) -{ - up_read(&sb->s_umount); - put_super(sb); -} - -enum sb_pin_state { - SB_PINNED, - SB_NOT_PINNED, - SB_PIN_FAILED -}; - /* - * For WB_SYNC_NONE writeback, the caller does not have the sb pinned + * For background writeback the caller does not have the sb pinned * before calling writeback. So make sure that we do pin it, so it doesn't * go away while we are writing inodes from it. */ -static enum sb_pin_state pin_sb_for_writeback(struct writeback_control *wbc, - struct super_block *sb) +static bool pin_sb_for_writeback(struct super_block *sb) { - /* - * Caller must already hold the ref for this - */ - if (wbc->sync_mode == WB_SYNC_ALL) { - WARN_ON(!rwsem_is_locked(&sb->s_umount)); - return SB_NOT_PINNED; - } spin_lock(&sb_lock); + if (list_empty(&sb->s_instances)) { + spin_unlock(&sb_lock); + return false; + } + sb->s_count++; + spin_unlock(&sb_lock); + if (down_read_trylock(&sb->s_umount)) { - if (sb->s_root) { - spin_unlock(&sb_lock); - return SB_PINNED; - } - /* - * umounted, drop rwsem again and fall through to failure - */ + if (sb->s_root) + return true; up_read(&sb->s_umount); } - sb->s_count--; - spin_unlock(&sb_lock); - return SB_PIN_FAILED; + + put_super(sb); + return false; } /* @@ -681,24 +628,31 @@ static void writeback_inodes_wb(struct bdi_writeback *wb, struct inode *inode = list_entry(wb->b_io.prev, struct inode, i_list); struct super_block *sb = inode->i_sb; - enum sb_pin_state state; - if (wbc->sb && sb != wbc->sb) { - /* super block given and doesn't - match, skip this inode */ - redirty_tail(inode); - continue; - } - state = pin_sb_for_writeback(wbc, sb); + if (wbc->sb) { + /* + * We are requested to write out inodes for a specific + * superblock. This means we already have s_umount + * taken by the caller which also waits for us to + * complete the writeout. + */ + if (sb != wbc->sb) { + redirty_tail(inode); + continue; + } - if (state == SB_PIN_FAILED) { - requeue_io(inode); - continue; + WARN_ON(!rwsem_is_locked(&sb->s_umount)); + + ret = writeback_sb_inodes(sb, wb, wbc); + } else { + if (!pin_sb_for_writeback(sb)) { + requeue_io(inode); + continue; + } + ret = writeback_sb_inodes(sb, wb, wbc); + drop_super(sb); } - ret = writeback_sb_inodes(sb, wb, wbc); - if (state == SB_PINNED) - unpin_sb_for_writeback(sb); if (ret) break; } @@ -911,7 +865,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait) * If this isn't a data integrity operation, just notify * that we have seen this work and we are now starting it. */ - if (args.sync_mode == WB_SYNC_NONE) + if (!test_bit(WS_ONSTACK, &work->state)) wb_clear_pending(wb, work); wrote += wb_writeback(wb, &args); @@ -920,7 +874,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait) * This is a data integrity writeback, so only do the * notification when we have completed the work. */ - if (args.sync_mode == WB_SYNC_ALL) + if (test_bit(WS_ONSTACK, &work->state)) wb_clear_pending(wb, work); } @@ -978,42 +932,32 @@ int bdi_writeback_task(struct bdi_writeback *wb) } /* - * Schedule writeback for all backing devices. This does WB_SYNC_NONE - * writeback, for integrity writeback see bdi_sync_writeback(). + * Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back + * the whole world. */ -static void bdi_writeback_all(struct super_block *sb, long nr_pages) +void wakeup_flusher_threads(long nr_pages) { + struct backing_dev_info *bdi; struct wb_writeback_args args = { - .sb = sb, - .nr_pages = nr_pages, .sync_mode = WB_SYNC_NONE, }; - struct backing_dev_info *bdi; - rcu_read_lock(); + if (nr_pages) { + args.nr_pages = nr_pages; + } else { + args.nr_pages = global_page_state(NR_FILE_DIRTY) + + global_page_state(NR_UNSTABLE_NFS); + } + rcu_read_lock(); list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { if (!bdi_has_dirty_io(bdi)) continue; - bdi_alloc_queue_work(bdi, &args); } - rcu_read_unlock(); } -/* - * Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back - * the whole world. - */ -void wakeup_flusher_threads(long nr_pages) -{ - if (nr_pages == 0) - nr_pages = global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS); - bdi_writeback_all(NULL, nr_pages); -} - static noinline void block_dump___mark_inode_dirty(struct inode *inode) { if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) { @@ -1218,12 +1162,17 @@ void writeback_inodes_sb(struct super_block *sb) { unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); - long nr_to_write; + struct wb_writeback_args args = { + .sb = sb, + .sync_mode = WB_SYNC_NONE, + }; + + WARN_ON(!rwsem_is_locked(&sb->s_umount)); - nr_to_write = nr_dirty + nr_unstable + + args.nr_pages = nr_dirty + nr_unstable + (inodes_stat.nr_inodes - inodes_stat.nr_unused); - bdi_start_writeback(sb->s_bdi, sb, nr_to_write); + bdi_queue_work_onstack(&args); } EXPORT_SYMBOL(writeback_inodes_sb); @@ -1237,7 +1186,9 @@ EXPORT_SYMBOL(writeback_inodes_sb); int writeback_inodes_sb_if_idle(struct super_block *sb) { if (!writeback_in_progress(sb->s_bdi)) { + down_read(&sb->s_umount); writeback_inodes_sb(sb); + up_read(&sb->s_umount); return 1; } else return 0; @@ -1253,7 +1204,16 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle); */ void sync_inodes_sb(struct super_block *sb) { - bdi_sync_writeback(sb->s_bdi, sb); + struct wb_writeback_args args = { + .sb = sb, + .sync_mode = WB_SYNC_ALL, + .nr_pages = LONG_MAX, + .range_cyclic = 0, + }; + + WARN_ON(!rwsem_is_locked(&sb->s_umount)); + + bdi_queue_work_onstack(&args); wait_sb_inodes(sb); } EXPORT_SYMBOL(sync_inodes_sb); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index a33aab6b5e68..54a92fd02bbd 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -234,8 +234,9 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) if (inode->i_mode != mode) { struct iattr attr; - attr.ia_valid = ATTR_MODE; + attr.ia_valid = ATTR_MODE | ATTR_CTIME; attr.ia_mode = mode; + attr.ia_ctime = CURRENT_TIME_SEC; rc = jffs2_do_setattr(inode, &attr); if (rc < 0) return rc; diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 7aa4417e085f..166062a68230 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -222,15 +222,18 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); jffs2_free_raw_inode(ri); - d_instantiate(dentry, inode); D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink, inode->i_mapping->nrpages)); + + d_instantiate(dentry, inode); + unlock_new_inode(inode); return 0; fail: make_bad_inode(inode); + unlock_new_inode(inode); iput(inode); jffs2_free_raw_inode(ri); return ret; @@ -360,8 +363,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char /* Eeek. Wave bye bye */ mutex_unlock(&f->sem); jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return PTR_ERR(fn); + ret = PTR_ERR(fn); + goto fail; } /* We use f->target field to store the target path. */ @@ -370,8 +373,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); mutex_unlock(&f->sem); jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return -ENOMEM; + ret = -ENOMEM; + goto fail; } memcpy(f->target, target, targetlen + 1); @@ -386,30 +389,24 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char jffs2_complete_reservation(c); ret = jffs2_init_security(inode, dir_i); - if (ret) { - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; + ret = jffs2_init_acl_post(inode); - if (ret) { - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); - if (ret) { - /* Eep. */ - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return -ENOMEM; + ret = -ENOMEM; + goto fail; } dir_f = JFFS2_INODE_INFO(dir_i); @@ -437,8 +434,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); mutex_unlock(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); + ret = PTR_ERR(fd); + goto fail; } dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); @@ -453,7 +450,14 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char jffs2_complete_reservation(c); d_instantiate(dentry, inode); + unlock_new_inode(inode); return 0; + + fail: + make_bad_inode(inode); + unlock_new_inode(inode); + iput(inode); + return ret; } @@ -519,8 +523,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) /* Eeek. Wave bye bye */ mutex_unlock(&f->sem); jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return PTR_ERR(fn); + ret = PTR_ERR(fn); + goto fail; } /* No data here. Only a metadata node, which will be obsoleted by the first data write @@ -531,30 +535,24 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_complete_reservation(c); ret = jffs2_init_security(inode, dir_i); - if (ret) { - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; + ret = jffs2_init_acl_post(inode); - if (ret) { - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); - if (ret) { - /* Eep. */ - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return -ENOMEM; + ret = -ENOMEM; + goto fail; } dir_f = JFFS2_INODE_INFO(dir_i); @@ -582,8 +580,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); mutex_unlock(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); + ret = PTR_ERR(fd); + goto fail; } dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); @@ -599,7 +597,14 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_complete_reservation(c); d_instantiate(dentry, inode); + unlock_new_inode(inode); return 0; + + fail: + make_bad_inode(inode); + unlock_new_inode(inode); + iput(inode); + return ret; } static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) @@ -693,8 +698,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de /* Eeek. Wave bye bye */ mutex_unlock(&f->sem); jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return PTR_ERR(fn); + ret = PTR_ERR(fn); + goto fail; } /* No data here. Only a metadata node, which will be obsoleted by the first data write @@ -705,30 +710,24 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de jffs2_complete_reservation(c); ret = jffs2_init_security(inode, dir_i); - if (ret) { - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; + ret = jffs2_init_acl_post(inode); - if (ret) { - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); - if (ret) { - /* Eep. */ - jffs2_clear_inode(inode); - return ret; - } + if (ret) + goto fail; rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ jffs2_complete_reservation(c); - jffs2_clear_inode(inode); - return -ENOMEM; + ret = -ENOMEM; + goto fail; } dir_f = JFFS2_INODE_INFO(dir_i); @@ -759,8 +758,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); mutex_unlock(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); + ret = PTR_ERR(fd); + goto fail; } dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); @@ -775,8 +774,14 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de jffs2_complete_reservation(c); d_instantiate(dentry, inode); - + unlock_new_inode(inode); return 0; + + fail: + make_bad_inode(inode); + unlock_new_inode(inode); + iput(inode); + return ret; } static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 8bc2c80ab159..459d39d1ea0b 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -465,7 +465,12 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i inode->i_blocks = 0; inode->i_size = 0; - insert_inode_hash(inode); + if (insert_inode_locked(inode) < 0) { + make_bad_inode(inode); + unlock_new_inode(inode); + iput(inode); + return ERR_PTR(-EINVAL); + } return inode; } diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 7ec9b34a59f8..d25b5257b7a1 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -1286,6 +1286,55 @@ static void nfs4_session_set_rwsize(struct nfs_server *server) #endif /* CONFIG_NFS_V4_1 */ } +static int nfs4_server_common_setup(struct nfs_server *server, + struct nfs_fh *mntfh) +{ + struct nfs_fattr *fattr; + int error; + + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + + fattr = nfs_alloc_fattr(); + if (fattr == NULL) + return -ENOMEM; + + /* We must ensure the session is initialised first */ + error = nfs4_init_session(server); + if (error < 0) + goto out; + + /* Probe the root fh to retrieve its FSID and filehandle */ + error = nfs4_get_rootfh(server, mntfh); + if (error < 0) + goto out; + + dprintk("Server FSID: %llx:%llx\n", + (unsigned long long) server->fsid.major, + (unsigned long long) server->fsid.minor); + dprintk("Mount FH: %d\n", mntfh->size); + + nfs4_session_set_rwsize(server); + + error = nfs_probe_fsinfo(server, mntfh, fattr); + if (error < 0) + goto out; + + if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) + server->namelen = NFS4_MAXNAMLEN; + + spin_lock(&nfs_client_lock); + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); + list_add_tail(&server->master_link, &nfs_volume_list); + spin_unlock(&nfs_client_lock); + + server->mount_time = jiffies; +out: + nfs_free_fattr(fattr); + return error; +} + /* * Create a version 4 volume record */ @@ -1346,7 +1395,6 @@ error: struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, struct nfs_fh *mntfh) { - struct nfs_fattr *fattr; struct nfs_server *server; int error; @@ -1356,55 +1404,19 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, if (!server) return ERR_PTR(-ENOMEM); - error = -ENOMEM; - fattr = nfs_alloc_fattr(); - if (fattr == NULL) - goto error; - /* set up the general RPC client */ error = nfs4_init_server(server, data); if (error < 0) goto error; - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - error = nfs4_init_session(server); - if (error < 0) - goto error; - - /* Probe the root fh to retrieve its FSID */ - error = nfs4_get_rootfh(server, mntfh); + error = nfs4_server_common_setup(server, mntfh); if (error < 0) goto error; - dprintk("Server FSID: %llx:%llx\n", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - dprintk("Mount FH: %d\n", mntfh->size); - - nfs4_session_set_rwsize(server); - - error = nfs_probe_fsinfo(server, mntfh, fattr); - if (error < 0) - goto error; - - if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) - server->namelen = NFS4_MAXNAMLEN; - - spin_lock(&nfs_client_lock); - list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); - list_add_tail(&server->master_link, &nfs_volume_list); - spin_unlock(&nfs_client_lock); - - server->mount_time = jiffies; dprintk("<-- nfs4_create_server() = %p\n", server); - nfs_free_fattr(fattr); return server; error: - nfs_free_fattr(fattr); nfs_free_server(server); dprintk("<-- nfs4_create_server() = error %d\n", error); return ERR_PTR(error); @@ -1418,7 +1430,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, { struct nfs_client *parent_client; struct nfs_server *server, *parent_server; - struct nfs_fattr *fattr; int error; dprintk("--> nfs4_create_referral_server()\n"); @@ -1427,11 +1438,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, if (!server) return ERR_PTR(-ENOMEM); - error = -ENOMEM; - fattr = nfs_alloc_fattr(); - if (fattr == NULL) - goto error; - parent_server = NFS_SB(data->sb); parent_client = parent_server->nfs_client; @@ -1456,40 +1462,14 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, if (error < 0) goto error; - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - /* Probe the root fh to retrieve its FSID and filehandle */ - error = nfs4_get_rootfh(server, mntfh); - if (error < 0) - goto error; - - /* probe the filesystem info for this server filesystem */ - error = nfs_probe_fsinfo(server, mntfh, fattr); + error = nfs4_server_common_setup(server, mntfh); if (error < 0) goto error; - if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) - server->namelen = NFS4_MAXNAMLEN; - - dprintk("Referral FSID: %llx:%llx\n", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - - spin_lock(&nfs_client_lock); - list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); - list_add_tail(&server->master_link, &nfs_volume_list); - spin_unlock(&nfs_client_lock); - - server->mount_time = jiffies; - - nfs_free_fattr(fattr); dprintk("<-- nfs_create_referral_server() = %p\n", server); return server; error: - nfs_free_fattr(fattr); nfs_free_server(server); dprintk("<-- nfs4_create_referral_server() = error %d\n", error); return ERR_PTR(error); diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 7428f7d6273b..a70e446e1605 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -146,7 +146,7 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh) goto out; } - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE) + if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) || !S_ISDIR(fsinfo.fattr->mode)) { printk(KERN_ERR "nfs4_get_rootfh:" " getroot encountered non-directory\n"); diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6bdef28efa33..65c8dae4b267 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -862,8 +862,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); *p++ = cpu_to_be32(0); - *p++ = cpu_to_be32(iap->ia_mtime.tv_sec); - *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); + *p++ = cpu_to_be32(iap->ia_atime.tv_sec); + *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); } else if (iap->ia_valid & ATTR_ATIME) { bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 04214fc5c304..f9df16de4a56 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -570,6 +570,22 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, nfs_show_mountd_netid(m, nfss, showdefaults); } +#ifdef CONFIG_NFS_V4 +static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss, + int showdefaults) +{ + struct nfs_client *clp = nfss->nfs_client; + + seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr); + seq_printf(m, ",minorversion=%u", clp->cl_minorversion); +} +#else +static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss, + int showdefaults) +{ +} +#endif + /* * Describe the mount options in force on this server representation */ @@ -631,11 +647,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, if (version != 4) nfs_show_mountd_options(m, nfss, showdefaults); + else + nfs_show_nfsv4_options(m, nfss, showdefaults); -#ifdef CONFIG_NFS_V4 - if (clp->rpc_ops->version == 4) - seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr); -#endif if (nfss->options & NFS_OPTION_FSCACHE) seq_printf(m, ",fsc"); } diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 12f7109720c2..4a2734758778 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4122,8 +4122,8 @@ nfs4_state_shutdown(void) nfs4_lock_state(); nfs4_release_reclaim(); __nfs4_state_shutdown(); - nfsd4_destroy_callback_queue(); nfs4_unlock_state(); + nfsd4_destroy_callback_queue(); } /* diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index ebbf3b6b2457..3c111120b619 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -443,8 +443,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, if (size_change) put_write_access(inode); if (!err) - if (EX_ISSYNC(fhp->fh_export)) - write_inode_now(inode, 1); + commit_metadata(fhp); out: return err; diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c index 40650021fc24..d8b6e4259b80 100644 --- a/fs/ocfs2/reservations.c +++ b/fs/ocfs2/reservations.c @@ -26,7 +26,6 @@ #include <linux/fs.h> #include <linux/types.h> -#include <linux/slab.h> #include <linux/highmem.h> #include <linux/bitops.h> #include <linux/list.h> diff --git a/fs/pipe.c b/fs/pipe.c index 69c4c7c13ea9..279eef96c51c 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1145,13 +1145,20 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) * and adjust the indexes. */ if (pipe->nrbufs) { - const unsigned int tail = pipe->nrbufs & (pipe->buffers - 1); - const unsigned int head = pipe->nrbufs - tail; + unsigned int tail; + unsigned int head; + tail = pipe->curbuf + pipe->nrbufs; + if (tail < pipe->buffers) + tail = 0; + else + tail &= (pipe->buffers - 1); + + head = pipe->nrbufs - tail; if (head) memcpy(bufs, pipe->bufs + pipe->curbuf, head * sizeof(struct pipe_buffer)); if (tail) - memcpy(bufs + head, pipe->bufs + pipe->curbuf, tail * sizeof(struct pipe_buffer)); + memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer)); } pipe->curbuf = 0; @@ -1208,12 +1215,13 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) size = round_pipe_size(arg); nr_pages = size >> PAGE_SHIFT; + ret = -EINVAL; + if (!nr_pages) + goto out; + if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) { ret = -EPERM; goto out; - } else if (nr_pages < PAGE_SIZE) { - ret = -EINVAL; - goto out; } ret = pipe_set_size(pipe, nr_pages); break; diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index ce94801f48ca..d9396a4fc7ff 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -209,6 +209,9 @@ void proc_device_tree_add_node(struct device_node *np, for (pp = np->properties; pp != NULL; pp = pp->next) { p = pp->name; + if (strchr(p, '/')) + continue; + if (duplicate_name(de, p)) p = fixup_name(np, de, p); diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 46d4b5d72bd3..cb6306e63843 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -122,11 +122,20 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, return size; } +static void pad_len_spaces(struct seq_file *m, int len) +{ + len = 25 + sizeof(void*) * 6 - len; + if (len < 1) + len = 1; + seq_printf(m, "%*c", len, ' '); +} + /* * display a single VMA to a sequenced file */ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) { + struct mm_struct *mm = vma->vm_mm; unsigned long ino = 0; struct file *file; dev_t dev = 0; @@ -155,11 +164,14 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) MAJOR(dev), MINOR(dev), ino, &len); if (file) { - len = 25 + sizeof(void *) * 6 - len; - if (len < 1) - len = 1; - seq_printf(m, "%*c", len, ' '); + pad_len_spaces(m, len); seq_path(m, &file->f_path, ""); + } else if (mm) { + if (vma->vm_start <= mm->start_stack && + vma->vm_end >= mm->start_stack) { + pad_len_spaces(m, len); + seq_puts(m, "[stack]"); + } } seq_putc(m, '\n'); diff --git a/fs/super.c b/fs/super.c index 5c35bc7a499e..938119ab8dcb 100644 --- a/fs/super.c +++ b/fs/super.c @@ -374,6 +374,8 @@ void sync_supers(void) up_read(&sb->s_umount); spin_lock(&sb_lock); + /* lock was dropped, must reset next */ + list_safe_reset_next(sb, n, s_list); __put_super(sb); } } @@ -405,6 +407,8 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg) up_read(&sb->s_umount); spin_lock(&sb_lock); + /* lock was dropped, must reset next */ + list_safe_reset_next(sb, n, s_list); __put_super(sb); } spin_unlock(&sb_lock); @@ -585,6 +589,8 @@ static void do_emergency_remount(struct work_struct *work) } up_write(&sb->s_umount); spin_lock(&sb_lock); + /* lock was dropped, must reset next */ + list_safe_reset_next(sb, n, s_list); __put_super(sb); } spin_unlock(&sb_lock); diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index bbd69bdb0fa8..fcc498ec9b33 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -25,6 +25,7 @@ #include <linux/stat.h> #include <linux/string.h> #include <linux/buffer_head.h> +#include <linux/writeback.h> #include "sysv.h" /* We don't trust the value of @@ -139,6 +140,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) struct inode *inode; sysv_ino_t ino; unsigned count; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_NONE + }; inode = new_inode(sb); if (!inode) @@ -168,7 +172,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) insert_inode_hash(inode); mark_inode_dirty(inode); - sysv_write_inode(inode, 0); /* ensure inode not allocated again */ + sysv_write_inode(inode, &wbc); /* ensure inode not allocated again */ mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ /* That's it. */ unlock_super(sb); diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 076ca50e9933..c8ff0d1ae5d3 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -62,7 +62,9 @@ */ static void shrink_liability(struct ubifs_info *c, int nr_to_write) { + down_read(&c->vfs_sb->s_umount); writeback_inodes_sb(c->vfs_sb); + up_read(&c->vfs_sb->s_umount); } /** diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index a0fa3bf0d1bb..34640d6dbdcb 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1381,14 +1381,6 @@ xfs_vm_writepage( if (!page_has_buffers(page)) create_empty_buffers(page, 1 << inode->i_blkbits, 0); - - /* - * VM calculation for nr_to_write seems off. Bump it way - * up, this gets simple streaming writes zippy again. - * To be reviewed again after Jens' writeback changes. - */ - wbc->nr_to_write *= 4; - /* * Convert delayed allocate, unwritten or unmapped space * to real space and flush out to disk. diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 846b75aeb2ab..e7839ee49e43 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -128,13 +128,12 @@ xfs_nfs_get_inode( return ERR_PTR(-ESTALE); /* - * The XFS_IGET_BULKSTAT means that an invalid inode number is just - * fine and not an indication of a corrupted filesystem. Because - * clients can send any kind of invalid file handle, e.g. after - * a restore on the server we have to deal with this case gracefully. + * The XFS_IGET_UNTRUSTED means that an invalid inode number is just + * fine and not an indication of a corrupted filesystem as clients can + * send invalid file handles and we have to handle it gracefully.. */ - error = xfs_iget(mp, NULL, ino, XFS_IGET_BULKSTAT, - XFS_ILOCK_SHARED, &ip, 0); + error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED, + XFS_ILOCK_SHARED, &ip); if (error) { /* * EINVAL means the inode cluster doesn't exist anymore. diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 699b60cbab9c..e59a81062830 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -679,10 +679,9 @@ xfs_ioc_bulkstat( error = xfs_bulkstat_single(mp, &inlast, bulkreq.ubuffer, &done); else /* XFS_IOC_FSBULKSTAT */ - error = xfs_bulkstat(mp, &inlast, &count, - (bulkstat_one_pf)xfs_bulkstat_one, NULL, - sizeof(xfs_bstat_t), bulkreq.ubuffer, - BULKSTAT_FG_QUICK, &done); + error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one, + sizeof(xfs_bstat_t), bulkreq.ubuffer, + &done); if (error) return -error; diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 9287135e9bfc..52ed49e6465c 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -237,15 +237,12 @@ xfs_bulkstat_one_compat( xfs_ino_t ino, /* inode number to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ - void *private_data, /* my private data */ - xfs_daddr_t bno, /* starting bno of inode cluster */ int *ubused, /* bytes used by me */ - void *dibuff, /* on-disk inode buffer */ int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, - xfs_bulkstat_one_fmt_compat, bno, - ubused, dibuff, stat); + xfs_bulkstat_one_fmt_compat, + ubused, stat); } /* copied from xfs_ioctl.c */ @@ -298,13 +295,11 @@ xfs_compat_ioc_bulkstat( int res; error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer, - sizeof(compat_xfs_bstat_t), - NULL, 0, NULL, NULL, &res); + sizeof(compat_xfs_bstat_t), 0, &res); } else if (cmd == XFS_IOC_FSBULKSTAT_32) { error = xfs_bulkstat(mp, &inlast, &count, - xfs_bulkstat_one_compat, NULL, - sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, - BULKSTAT_FG_QUICK, &done); + xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t), + bulkreq.ubuffer, &done); } else error = XFS_ERROR(EINVAL); if (error) diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 2d8b7bc792c9..8c117ff2e3ab 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1632,10 +1632,7 @@ xfs_qm_dqusage_adjust( xfs_ino_t ino, /* inode number to get data for */ void __user *buffer, /* not used */ int ubsize, /* not used */ - void *private_data, /* not used */ - xfs_daddr_t bno, /* starting block of inode cluster */ int *ubused, /* not used */ - void *dip, /* on-disk inode pointer (not used) */ int *res) /* result code value */ { xfs_inode_t *ip; @@ -1660,7 +1657,7 @@ xfs_qm_dqusage_adjust( * the case in all other instances. It's OK that we do this because * quotacheck is done only at mount time. */ - if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) { + if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) { *res = BULKSTAT_RV_NOTHING; return error; } @@ -1796,12 +1793,13 @@ xfs_qm_quotacheck( * Iterate thru all the inodes in the file system, * adjusting the corresponding dquot counters in core. */ - if ((error = xfs_bulkstat(mp, &lastino, &count, - xfs_qm_dqusage_adjust, NULL, - structsz, NULL, BULKSTAT_FG_IGET, &done))) + error = xfs_bulkstat(mp, &lastino, &count, + xfs_qm_dqusage_adjust, + structsz, NULL, &done); + if (error) break; - } while (! done); + } while (!done); /* * We've made all the changes that we need to make incore. @@ -1889,14 +1887,14 @@ xfs_qm_init_quotainos( mp->m_sb.sb_uquotino != NULLFSINO) { ASSERT(mp->m_sb.sb_uquotino > 0); if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, - 0, 0, &uip, 0))) + 0, 0, &uip))) return XFS_ERROR(error); } if (XFS_IS_OQUOTA_ON(mp) && mp->m_sb.sb_gquotino != NULLFSINO) { ASSERT(mp->m_sb.sb_gquotino > 0); if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, - 0, 0, &gip, 0))) { + 0, 0, &gip))) { if (uip) IRELE(uip); return XFS_ERROR(error); diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 92b002f1805f..b4487764e923 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -262,7 +262,7 @@ xfs_qm_scall_trunc_qfiles( } if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) { - error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0); + error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip); if (!error) { error = xfs_truncate_file(mp, qip); IRELE(qip); @@ -271,7 +271,7 @@ xfs_qm_scall_trunc_qfiles( if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) && mp->m_sb.sb_gquotino != NULLFSINO) { - error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0); + error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip); if (!error2) { error2 = xfs_truncate_file(mp, qip); IRELE(qip); @@ -417,12 +417,12 @@ xfs_qm_scall_getqstat( } if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) { if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, - 0, 0, &uip, 0) == 0) + 0, 0, &uip) == 0) tempuqip = B_TRUE; } if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) { if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, - 0, 0, &gip, 0) == 0) + 0, 0, &gip) == 0) tempgqip = B_TRUE; } if (uip) { @@ -1109,10 +1109,7 @@ xfs_qm_internalqcheck_adjust( xfs_ino_t ino, /* inode number to get data for */ void __user *buffer, /* not used */ int ubsize, /* not used */ - void *private_data, /* not used */ - xfs_daddr_t bno, /* starting block of inode cluster */ int *ubused, /* not used */ - void *dip, /* not used */ int *res) /* bulkstat result code */ { xfs_inode_t *ip; @@ -1134,7 +1131,7 @@ xfs_qm_internalqcheck_adjust( ipreleased = B_FALSE; again: lock_flags = XFS_ILOCK_SHARED; - if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) { + if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip))) { *res = BULKSTAT_RV_NOTHING; return (error); } @@ -1205,15 +1202,15 @@ xfs_qm_internalqcheck( * Iterate thru all the inodes in the file system, * adjusting the corresponding dquot counters */ - if ((error = xfs_bulkstat(mp, &lastino, &count, - xfs_qm_internalqcheck_adjust, NULL, - 0, NULL, BULKSTAT_FG_IGET, &done))) { + error = xfs_bulkstat(mp, &lastino, &count, + xfs_qm_internalqcheck_adjust, + 0, NULL, &done); + if (error) { + cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error); break; } - } while (! done); - if (error) { - cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error); - } + } while (!done); + cmn_err(CE_DEBUG, "Checking results against system dquots"); for (i = 0; i < qmtest_hashmask; i++) { xfs_dqtest_t *d, *n; diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 5bba29a07812..7f159d2a429a 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -69,7 +69,9 @@ xfs_swapext( goto out; } - if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) { + if (!(file->f_mode & FMODE_WRITE) || + !(file->f_mode & FMODE_READ) || + (file->f_flags & O_APPEND)) { error = XFS_ERROR(EBADF); goto out_put_file; } @@ -81,6 +83,7 @@ xfs_swapext( } if (!(tmp_file->f_mode & FMODE_WRITE) || + !(tmp_file->f_mode & FMODE_READ) || (tmp_file->f_flags & O_APPEND)) { error = XFS_ERROR(EBADF); goto out_put_tmp_file; diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 9d884c127bb9..c7142a064c48 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1203,6 +1203,63 @@ error0: return error; } +STATIC int +xfs_imap_lookup( + struct xfs_mount *mp, + struct xfs_trans *tp, + xfs_agnumber_t agno, + xfs_agino_t agino, + xfs_agblock_t agbno, + xfs_agblock_t *chunk_agbno, + xfs_agblock_t *offset_agbno, + int flags) +{ + struct xfs_inobt_rec_incore rec; + struct xfs_btree_cur *cur; + struct xfs_buf *agbp; + xfs_agino_t startino; + int error; + int i; + + error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); + if (error) { + xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " + "xfs_ialloc_read_agi() returned " + "error %d, agno %d", + error, agno); + return error; + } + + /* + * derive and lookup the exact inode record for the given agino. If the + * record cannot be found, then it's an invalid inode number and we + * should abort. + */ + cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); + startino = agino & ~(XFS_IALLOC_INODES(mp) - 1); + error = xfs_inobt_lookup(cur, startino, XFS_LOOKUP_EQ, &i); + if (!error) { + if (i) + error = xfs_inobt_get_rec(cur, &rec, &i); + if (!error && i == 0) + error = EINVAL; + } + + xfs_trans_brelse(tp, agbp); + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + if (error) + return error; + + /* for untrusted inodes check it is allocated first */ + if ((flags & XFS_IGET_UNTRUSTED) && + (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))) + return EINVAL; + + *chunk_agbno = XFS_AGINO_TO_AGBNO(mp, rec.ir_startino); + *offset_agbno = agbno - *chunk_agbno; + return 0; +} + /* * Return the location of the inode in imap, for mapping it into a buffer. */ @@ -1235,8 +1292,11 @@ xfs_imap( if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || ino != XFS_AGINO_TO_INO(mp, agno, agino)) { #ifdef DEBUG - /* no diagnostics for bulkstat, ino comes from userspace */ - if (flags & XFS_IGET_BULKSTAT) + /* + * Don't output diagnostic information for untrusted inodes + * as they can be invalid without implying corruption. + */ + if (flags & XFS_IGET_UNTRUSTED) return XFS_ERROR(EINVAL); if (agno >= mp->m_sb.sb_agcount) { xfs_fs_cmn_err(CE_ALERT, mp, @@ -1263,6 +1323,23 @@ xfs_imap( return XFS_ERROR(EINVAL); } + blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog; + + /* + * For bulkstat and handle lookups, we have an untrusted inode number + * that we have to verify is valid. We cannot do this just by reading + * the inode buffer as it may have been unlinked and removed leaving + * inodes in stale state on disk. Hence we have to do a btree lookup + * in all cases where an untrusted inode number is passed. + */ + if (flags & XFS_IGET_UNTRUSTED) { + error = xfs_imap_lookup(mp, tp, agno, agino, agbno, + &chunk_agbno, &offset_agbno, flags); + if (error) + return error; + goto out_map; + } + /* * If the inode cluster size is the same as the blocksize or * smaller we get to the buffer by simple arithmetics. @@ -1277,24 +1354,6 @@ xfs_imap( return 0; } - blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog; - - /* - * If we get a block number passed from bulkstat we can use it to - * find the buffer easily. - */ - if (imap->im_blkno) { - offset = XFS_INO_TO_OFFSET(mp, ino); - ASSERT(offset < mp->m_sb.sb_inopblock); - - cluster_agbno = xfs_daddr_to_agbno(mp, imap->im_blkno); - offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock; - - imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster); - imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog); - return 0; - } - /* * If the inode chunks are aligned then use simple maths to * find the location. Otherwise we have to do a btree @@ -1304,50 +1363,13 @@ xfs_imap( offset_agbno = agbno & mp->m_inoalign_mask; chunk_agbno = agbno - offset_agbno; } else { - xfs_btree_cur_t *cur; /* inode btree cursor */ - xfs_inobt_rec_incore_t chunk_rec; - xfs_buf_t *agbp; /* agi buffer */ - int i; /* temp state */ - - error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); - if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "xfs_ialloc_read_agi() returned " - "error %d, agno %d", - error, agno); - return error; - } - - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); - error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); - if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "xfs_inobt_lookup() failed"); - goto error0; - } - - error = xfs_inobt_get_rec(cur, &chunk_rec, &i); - if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "xfs_inobt_get_rec() failed"); - goto error0; - } - if (i == 0) { -#ifdef DEBUG - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "xfs_inobt_get_rec() failed"); -#endif /* DEBUG */ - error = XFS_ERROR(EINVAL); - } - error0: - xfs_trans_brelse(tp, agbp); - xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + error = xfs_imap_lookup(mp, tp, agno, agino, agbno, + &chunk_agbno, &offset_agbno, flags); if (error) return error; - chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_rec.ir_startino); - offset_agbno = agbno - chunk_agbno; } +out_map: ASSERT(agbno >= chunk_agbno); cluster_agbno = chunk_agbno + ((offset_agbno / blks_per_cluster) * blks_per_cluster); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 75df75f43d48..8f8b91be2c99 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -259,7 +259,6 @@ xfs_iget_cache_miss( xfs_trans_t *tp, xfs_ino_t ino, struct xfs_inode **ipp, - xfs_daddr_t bno, int flags, int lock_flags) { @@ -272,7 +271,7 @@ xfs_iget_cache_miss( if (!ip) return ENOMEM; - error = xfs_iread(mp, tp, ip, bno, flags); + error = xfs_iread(mp, tp, ip, flags); if (error) goto out_destroy; @@ -358,8 +357,6 @@ out_destroy: * within the file system for the inode being requested. * lock_flags -- flags indicating how to lock the inode. See the comment * for xfs_ilock() for a list of valid values. - * bno -- the block number starting the buffer containing the inode, - * if known (as by bulkstat), else 0. */ int xfs_iget( @@ -368,8 +365,7 @@ xfs_iget( xfs_ino_t ino, uint flags, uint lock_flags, - xfs_inode_t **ipp, - xfs_daddr_t bno) + xfs_inode_t **ipp) { xfs_inode_t *ip; int error; @@ -397,7 +393,7 @@ again: read_unlock(&pag->pag_ici_lock); XFS_STATS_INC(xs_ig_missed); - error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip, bno, + error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip, flags, lock_flags); if (error) goto out_error_or_again; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index d53c39de7d05..b76a829d7e20 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -177,7 +177,7 @@ xfs_imap_to_bp( if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, XFS_RANDOM_ITOBP_INOTOBP))) { - if (iget_flags & XFS_IGET_BULKSTAT) { + if (iget_flags & XFS_IGET_UNTRUSTED) { xfs_trans_brelse(tp, bp); return XFS_ERROR(EINVAL); } @@ -787,7 +787,6 @@ xfs_iread( xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *ip, - xfs_daddr_t bno, uint iget_flags) { xfs_buf_t *bp; @@ -797,11 +796,9 @@ xfs_iread( /* * Fill in the location information in the in-core inode. */ - ip->i_imap.im_blkno = bno; error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags); if (error) return error; - ASSERT(bno == 0 || bno == ip->i_imap.im_blkno); /* * Get pointers to the on-disk inode and the buffer containing it. diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 9965e40a4615..78550df13cd6 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -442,7 +442,7 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) * xfs_iget.c prototypes. */ int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, - uint, uint, xfs_inode_t **, xfs_daddr_t); + uint, uint, xfs_inode_t **); void xfs_iput(xfs_inode_t *, uint); void xfs_iput_new(xfs_inode_t *, uint); void xfs_ilock(xfs_inode_t *, uint); @@ -500,7 +500,7 @@ do { \ * Flags for xfs_iget() */ #define XFS_IGET_CREATE 0x1 -#define XFS_IGET_BULKSTAT 0x2 +#define XFS_IGET_UNTRUSTED 0x2 int xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, struct xfs_dinode **, @@ -509,7 +509,7 @@ int xfs_itobp(struct xfs_mount *, struct xfs_trans *, struct xfs_inode *, struct xfs_dinode **, struct xfs_buf **, uint); int xfs_iread(struct xfs_mount *, struct xfs_trans *, - struct xfs_inode *, xfs_daddr_t, uint); + struct xfs_inode *, uint); void xfs_dinode_to_disk(struct xfs_dinode *, struct xfs_icdinode *); void xfs_idestroy_fork(struct xfs_inode *, int); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index b1b801e4a28e..2b86f8610512 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -49,24 +49,40 @@ xfs_internal_inum( (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))); } -STATIC int -xfs_bulkstat_one_iget( - xfs_mount_t *mp, /* mount point for filesystem */ - xfs_ino_t ino, /* inode number to get data for */ - xfs_daddr_t bno, /* starting bno of inode cluster */ - xfs_bstat_t *buf, /* return buffer */ - int *stat) /* BULKSTAT_RV_... */ +/* + * Return stat information for one inode. + * Return 0 if ok, else errno. + */ +int +xfs_bulkstat_one_int( + struct xfs_mount *mp, /* mount point for filesystem */ + xfs_ino_t ino, /* inode to get data for */ + void __user *buffer, /* buffer to place output in */ + int ubsize, /* size of buffer */ + bulkstat_one_fmt_pf formatter, /* formatter, copy to user */ + int *ubused, /* bytes used by me */ + int *stat) /* BULKSTAT_RV_... */ { - xfs_icdinode_t *dic; /* dinode core info pointer */ - xfs_inode_t *ip; /* incore inode pointer */ - struct inode *inode; - int error; + struct xfs_icdinode *dic; /* dinode core info pointer */ + struct xfs_inode *ip; /* incore inode pointer */ + struct inode *inode; + struct xfs_bstat *buf; /* return buffer */ + int error = 0; /* error value */ + + *stat = BULKSTAT_RV_NOTHING; + + if (!buffer || xfs_internal_inum(mp, ino)) + return XFS_ERROR(EINVAL); + + buf = kmem_alloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL); + if (!buf) + return XFS_ERROR(ENOMEM); error = xfs_iget(mp, NULL, ino, - XFS_IGET_BULKSTAT, XFS_ILOCK_SHARED, &ip, bno); + XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip); if (error) { *stat = BULKSTAT_RV_NOTHING; - return error; + goto out_free; } ASSERT(ip != NULL); @@ -127,77 +143,16 @@ xfs_bulkstat_one_iget( buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks; break; } - xfs_iput(ip, XFS_ILOCK_SHARED); - return error; -} -STATIC void -xfs_bulkstat_one_dinode( - xfs_mount_t *mp, /* mount point for filesystem */ - xfs_ino_t ino, /* inode number to get data for */ - xfs_dinode_t *dic, /* dinode inode pointer */ - xfs_bstat_t *buf) /* return buffer */ -{ - /* - * The inode format changed when we moved the link count and - * made it 32 bits long. If this is an old format inode, - * convert it in memory to look like a new one. If it gets - * flushed to disk we will convert back before flushing or - * logging it. We zero out the new projid field and the old link - * count field. We'll handle clearing the pad field (the remains - * of the old uuid field) when we actually convert the inode to - * the new format. We don't change the version number so that we - * can distinguish this from a real new format inode. - */ - if (dic->di_version == 1) { - buf->bs_nlink = be16_to_cpu(dic->di_onlink); - buf->bs_projid = 0; - } else { - buf->bs_nlink = be32_to_cpu(dic->di_nlink); - buf->bs_projid = be16_to_cpu(dic->di_projid); - } + error = formatter(buffer, ubsize, ubused, buf); - buf->bs_ino = ino; - buf->bs_mode = be16_to_cpu(dic->di_mode); - buf->bs_uid = be32_to_cpu(dic->di_uid); - buf->bs_gid = be32_to_cpu(dic->di_gid); - buf->bs_size = be64_to_cpu(dic->di_size); - buf->bs_atime.tv_sec = be32_to_cpu(dic->di_atime.t_sec); - buf->bs_atime.tv_nsec = be32_to_cpu(dic->di_atime.t_nsec); - buf->bs_mtime.tv_sec = be32_to_cpu(dic->di_mtime.t_sec); - buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec); - buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec); - buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec); - buf->bs_xflags = xfs_dic2xflags(dic); - buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog; - buf->bs_extents = be32_to_cpu(dic->di_nextents); - buf->bs_gen = be32_to_cpu(dic->di_gen); - memset(buf->bs_pad, 0, sizeof(buf->bs_pad)); - buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask); - buf->bs_dmstate = be16_to_cpu(dic->di_dmstate); - buf->bs_aextents = be16_to_cpu(dic->di_anextents); - buf->bs_forkoff = XFS_DFORK_BOFF(dic); + if (!error) + *stat = BULKSTAT_RV_DIDONE; - switch (dic->di_format) { - case XFS_DINODE_FMT_DEV: - buf->bs_rdev = xfs_dinode_get_rdev(dic); - buf->bs_blksize = BLKDEV_IOSIZE; - buf->bs_blocks = 0; - break; - case XFS_DINODE_FMT_LOCAL: - case XFS_DINODE_FMT_UUID: - buf->bs_rdev = 0; - buf->bs_blksize = mp->m_sb.sb_blocksize; - buf->bs_blocks = 0; - break; - case XFS_DINODE_FMT_EXTENTS: - case XFS_DINODE_FMT_BTREE: - buf->bs_rdev = 0; - buf->bs_blksize = mp->m_sb.sb_blocksize; - buf->bs_blocks = be64_to_cpu(dic->di_nblocks); - break; - } + out_free: + kmem_free(buf); + return error; } /* Return 0 on success or positive error */ @@ -217,118 +172,17 @@ xfs_bulkstat_one_fmt( return 0; } -/* - * Return stat information for one inode. - * Return 0 if ok, else errno. - */ -int /* error status */ -xfs_bulkstat_one_int( - xfs_mount_t *mp, /* mount point for filesystem */ - xfs_ino_t ino, /* inode number to get data for */ - void __user *buffer, /* buffer to place output in */ - int ubsize, /* size of buffer */ - bulkstat_one_fmt_pf formatter, /* formatter, copy to user */ - xfs_daddr_t bno, /* starting bno of inode cluster */ - int *ubused, /* bytes used by me */ - void *dibuff, /* on-disk inode buffer */ - int *stat) /* BULKSTAT_RV_... */ -{ - xfs_bstat_t *buf; /* return buffer */ - int error = 0; /* error value */ - xfs_dinode_t *dip; /* dinode inode pointer */ - - dip = (xfs_dinode_t *)dibuff; - *stat = BULKSTAT_RV_NOTHING; - - if (!buffer || xfs_internal_inum(mp, ino)) - return XFS_ERROR(EINVAL); - - buf = kmem_alloc(sizeof(*buf), KM_SLEEP); - - if (dip == NULL) { - /* We're not being passed a pointer to a dinode. This happens - * if BULKSTAT_FG_IGET is selected. Do the iget. - */ - error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat); - if (error) - goto out_free; - } else { - xfs_bulkstat_one_dinode(mp, ino, dip, buf); - } - - error = formatter(buffer, ubsize, ubused, buf); - if (error) - goto out_free; - - *stat = BULKSTAT_RV_DIDONE; - - out_free: - kmem_free(buf); - return error; -} - int xfs_bulkstat_one( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t ino, /* inode number to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ - void *private_data, /* my private data */ - xfs_daddr_t bno, /* starting bno of inode cluster */ int *ubused, /* bytes used by me */ - void *dibuff, /* on-disk inode buffer */ int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, - xfs_bulkstat_one_fmt, bno, - ubused, dibuff, stat); -} - -/* - * Test to see whether we can use the ondisk inode directly, based - * on the given bulkstat flags, filling in dipp accordingly. - * Returns zero if the inode is dodgey. - */ -STATIC int -xfs_bulkstat_use_dinode( - xfs_mount_t *mp, - int flags, - xfs_buf_t *bp, - int clustidx, - xfs_dinode_t **dipp) -{ - xfs_dinode_t *dip; - unsigned int aformat; - - *dipp = NULL; - if (!bp || (flags & BULKSTAT_FG_IGET)) - return 1; - dip = (xfs_dinode_t *) - xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog); - /* - * Check the buffer containing the on-disk inode for di_mode == 0. - * This is to prevent xfs_bulkstat from picking up just reclaimed - * inodes that have their in-core state initialized but not flushed - * to disk yet. This is a temporary hack that would require a proper - * fix in the future. - */ - if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC || - !XFS_DINODE_GOOD_VERSION(dip->di_version) || - !dip->di_mode) - return 0; - if (flags & BULKSTAT_FG_QUICK) { - *dipp = dip; - return 1; - } - /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */ - aformat = dip->di_aformat; - if ((XFS_DFORK_Q(dip) == 0) || - (aformat == XFS_DINODE_FMT_LOCAL) || - (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_anextents)) { - *dipp = dip; - return 1; - } - return 1; + xfs_bulkstat_one_fmt, ubused, stat); } #define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) @@ -342,10 +196,8 @@ xfs_bulkstat( xfs_ino_t *lastinop, /* last inode returned */ int *ubcountp, /* size of buffer/count returned */ bulkstat_one_pf formatter, /* func that'd fill a single buf */ - void *private_data,/* private data for formatter */ size_t statstruct_size, /* sizeof struct filling */ char __user *ubuffer, /* buffer with inode stats */ - int flags, /* defined in xfs_itable.h */ int *done) /* 1 if there are more stats to get */ { xfs_agblock_t agbno=0;/* allocation group block number */ @@ -380,14 +232,12 @@ xfs_bulkstat( int ubelem; /* spaces used in user's buffer */ int ubused; /* bytes used by formatter */ xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ - xfs_dinode_t *dip; /* ptr into bp for specific inode */ /* * Get the last inode value, see if there's nothing to do. */ ino = (xfs_ino_t)*lastinop; lastino = ino; - dip = NULL; agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); if (agno >= mp->m_sb.sb_agcount || @@ -612,37 +462,6 @@ xfs_bulkstat( irbp->ir_startino) + ((chunkidx & nimask) >> mp->m_sb.sb_inopblog); - - if (flags & (BULKSTAT_FG_QUICK | - BULKSTAT_FG_INLINE)) { - int offset; - - ino = XFS_AGINO_TO_INO(mp, agno, - agino); - bno = XFS_AGB_TO_DADDR(mp, agno, - agbno); - - /* - * Get the inode cluster buffer - */ - if (bp) - xfs_buf_relse(bp); - - error = xfs_inotobp(mp, NULL, ino, &dip, - &bp, &offset, - XFS_IGET_BULKSTAT); - - if (!error) - clustidx = offset / mp->m_sb.sb_inodesize; - if (XFS_TEST_ERROR(error != 0, - mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK, - XFS_RANDOM_BULKSTAT_READ_CHUNK)) { - bp = NULL; - ubleft = 0; - rval = error; - break; - } - } } ino = XFS_AGINO_TO_INO(mp, agno, agino); bno = XFS_AGB_TO_DADDR(mp, agno, agbno); @@ -658,35 +477,13 @@ xfs_bulkstat( * when the chunk is used up. */ irbp->ir_freecount++; - if (!xfs_bulkstat_use_dinode(mp, flags, bp, - clustidx, &dip)) { - lastino = ino; - continue; - } - /* - * If we need to do an iget, cannot hold bp. - * Drop it, until starting the next cluster. - */ - if ((flags & BULKSTAT_FG_INLINE) && !dip) { - if (bp) - xfs_buf_relse(bp); - bp = NULL; - } /* * Get the inode and fill in a single buffer. - * BULKSTAT_FG_QUICK uses dip to fill it in. - * BULKSTAT_FG_IGET uses igets. - * BULKSTAT_FG_INLINE uses dip if we have an - * inline attr fork, else igets. - * See: xfs_bulkstat_one & xfs_dm_bulkstat_one. - * This is also used to count inodes/blks, etc - * in xfs_qm_quotacheck. */ ubused = statstruct_size; - error = formatter(mp, ino, ubufp, - ubleft, private_data, - bno, &ubused, dip, &fmterror); + error = formatter(mp, ino, ubufp, ubleft, + &ubused, &fmterror); if (fmterror == BULKSTAT_RV_NOTHING) { if (error && error != ENOENT && error != EINVAL) { @@ -778,8 +575,7 @@ xfs_bulkstat_single( */ ino = (xfs_ino_t)*lastinop; - error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), - NULL, 0, NULL, NULL, &res); + error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res); if (error) { /* * Special case way failed, do it the "long" way @@ -788,8 +584,7 @@ xfs_bulkstat_single( (*lastinop)--; count = 1; if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one, - NULL, sizeof(xfs_bstat_t), buffer, - BULKSTAT_FG_IGET, done)) + sizeof(xfs_bstat_t), buffer, done)) return error; if (count == 0 || (xfs_ino_t)*lastinop != ino) return error == EFSCORRUPTED ? diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index 20792bf45946..97295d91d170 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h @@ -27,10 +27,7 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp, xfs_ino_t ino, void __user *buffer, int ubsize, - void *private_data, - xfs_daddr_t bno, int *ubused, - void *dip, int *stat); /* @@ -41,13 +38,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp, #define BULKSTAT_RV_GIVEUP 2 /* - * Values for bulkstat flag argument. - */ -#define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */ -#define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */ -#define BULKSTAT_FG_INLINE 0x4 /* No iget if inline attrs */ - -/* * Return stat information in bulk (by-inode) for the filesystem. */ int /* error status */ @@ -56,10 +46,8 @@ xfs_bulkstat( xfs_ino_t *lastino, /* last inode returned */ int *count, /* size of buffer/count returned */ bulkstat_one_pf formatter, /* func that'd fill a single buf */ - void *private_data, /* private data for formatter */ size_t statstruct_size,/* sizeof struct that we're filling */ char __user *ubuffer,/* buffer with inode stats */ - int flags, /* flag to control access method */ int *done); /* 1 if there are more stats to get */ int @@ -82,9 +70,7 @@ xfs_bulkstat_one_int( void __user *buffer, int ubsize, bulkstat_one_fmt_pf formatter, - xfs_daddr_t bno, int *ubused, - void *dibuff, int *stat); int @@ -93,10 +79,7 @@ xfs_bulkstat_one( xfs_ino_t ino, void __user *buffer, int ubsize, - void *private_data, - xfs_daddr_t bno, int *ubused, - void *dibuff, int *stat); typedef int (*inumbers_fmt_pf)( diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index ed0684cc50ee..9ac5cfab27b9 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3198,7 +3198,7 @@ xlog_recover_process_one_iunlink( int error; ino = XFS_AGINO_TO_INO(mp, agno, agino); - error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0); + error = xfs_iget(mp, NULL, ino, 0, 0, &ip); if (error) goto fail; diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index d59f4e8bedcf..69f62d8b2816 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1300,7 +1300,7 @@ xfs_mountfs( * Get and sanity-check the root inode. * Save the pointer to it in the mount structure. */ - error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0); + error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip); if (error) { cmn_err(CE_WARN, "XFS: failed to read root inode"); goto out_log_dealloc; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 16445518506d..a2d32ce335aa 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2277,12 +2277,12 @@ xfs_rtmount_inodes( sbp = &mp->m_sb; if (sbp->sb_rbmino == NULLFSINO) return 0; - error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0); + error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip); if (error) return error; ASSERT(mp->m_rbmip != NULL); ASSERT(sbp->sb_rsumino != NULLFSINO); - error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0); + error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip); if (error) { IRELE(mp->m_rbmip); return error; diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 785ff101da0a..2559dfec946b 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -62,7 +62,7 @@ xfs_trans_iget( { int error; - error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp, 0); + error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp); if (!error && tp) xfs_trans_ijoin(tp, *ipp, lock_flags); return error; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index a06bd62504fc..c1646838898f 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1269,7 +1269,7 @@ xfs_lookup( if (error) goto out; - error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0); + error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp); if (error) goto out_free_name; diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 5958d7845bd5..17714beb868e 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -212,7 +212,7 @@ char const *acpi_gbl_exception_names_env[] = { "AE_NO_GLOBAL_LOCK", "AE_ABORT_METHOD", "AE_SAME_HANDLER", - "AE_WAKE_ONLY_GPE", + "AE_NO_HANDLER", "AE_OWNER_ID_LIMIT" }; diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 0e4ab1fe5966..1371cc997393 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -69,6 +69,7 @@ extern acpi_name acpi_gbl_trace_method_name; extern u32 acpi_gbl_trace_flags; extern u8 acpi_gbl_enable_aml_debug_object; extern u8 acpi_gbl_copy_dsdt_locally; +extern u8 acpi_gbl_truncate_io_addresses; extern u32 acpi_current_gpe_count; extern struct acpi_table_fadt acpi_gbl_FADT; diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index bade172cad47..d55f4a7b824d 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -663,10 +663,11 @@ typedef u32 acpi_event_status; #define ACPI_GPE_MAX 0xFF #define ACPI_NUM_GPE 256 -/* Actions for acpi_set_gpe */ +/* Actions for acpi_set_gpe and acpi_hw_low_set_gpe */ #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 +#define ACPI_GPE_COND_ENABLE 2 /* gpe_types for acpi_enable_gpe and acpi_disable_gpe */ diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 3ff9fc071dfe..5347063e9d5a 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -903,6 +903,7 @@ struct drm_radeon_cs { #define RADEON_INFO_NUM_Z_PIPES 0x02 #define RADEON_INFO_ACCEL_WORKING 0x03 #define RADEON_INFO_CRTC_FROM_ID 0x04 +#define RADEON_INFO_ACCEL_WORKING2 0x05 struct drm_radeon_info { uint32_t request; diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h index 9101ed64f803..09ea4a1e9505 100644 --- a/include/linux/agp_backend.h +++ b/include/linux/agp_backend.h @@ -79,7 +79,6 @@ struct agp_memory { u32 physical; bool is_bound; bool is_flushed; - bool vmalloc_flag; /* list of agp_memory mapped to the aperture */ struct list_head mapped_list; /* DMA-mapped addresses */ diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index aee5f6ce166e..9ae2889096b6 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -105,8 +105,8 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent, int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); void bdi_unregister(struct backing_dev_info *bdi); int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int); -void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb, - long nr_pages); +void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages); +void bdi_start_background_writeback(struct backing_dev_info *bdi); int bdi_writeback_task(struct bdi_writeback *wb); int bdi_has_dirty_io(struct backing_dev_info *bdi); void bdi_arm_supers_timer(void); diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 0c621604baa1..e3d00fdb858d 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -525,13 +525,21 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state( return cgrp->subsys[subsys_id]; } -static inline struct cgroup_subsys_state *task_subsys_state( - struct task_struct *task, int subsys_id) +/* + * function to get the cgroup_subsys_state which allows for extra + * rcu_dereference_check() conditions, such as locks used during the + * cgroup_subsys::attach() methods. + */ +#define task_subsys_state_check(task, subsys_id, __c) \ + rcu_dereference_check(task->cgroups->subsys[subsys_id], \ + rcu_read_lock_held() || \ + lockdep_is_held(&task->alloc_lock) || \ + cgroup_lock_is_held() || (__c)) + +static inline struct cgroup_subsys_state * +task_subsys_state(struct task_struct *task, int subsys_id) { - return rcu_dereference_check(task->cgroups->subsys[subsys_id], - rcu_read_lock_held() || - lockdep_is_held(&task->alloc_lock) || - cgroup_lock_is_held()); + return task_subsys_state_check(task, subsys_id, false); } static inline struct cgroup* task_cgroup(struct task_struct *task, diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 73dcf804bc94..0da5b187f124 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -58,8 +58,12 @@ * naked functions because then mcount is called without stack and frame pointer * being set up and there is no chance to restore the lr register to the value * before mcount was called. + * + * The asm() bodies of naked functions often depend on standard calling conventions, + * therefore they must be noinline and noclone. GCC 4.[56] currently fail to enforce + * this, so we must do so ourselves. See GCC PR44290. */ -#define __naked __attribute__((naked)) notrace +#define __naked __attribute__((naked)) noinline __noclone notrace #define __noreturn __attribute__((noreturn)) @@ -85,3 +89,7 @@ #define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h) #define gcc_header(x) _gcc_header(x) #include gcc_header(__GNUC__) + +#if !defined(__noclone) +#define __noclone /* not needed */ +#endif diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 94dea3ffbfa1..fcfa5b9a4317 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -48,6 +48,10 @@ * unreleased. Really, we need to have autoconf for the kernel. */ #define unreachable() __builtin_unreachable() + +/* Mark a function definition as prohibited from being cloned. */ +#define __noclone __attribute__((__noclone__)) + #endif #endif diff --git a/include/linux/drbd.h b/include/linux/drbd.h index 30da4ae48972..b8d2516668aa 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -53,7 +53,7 @@ extern const char *drbd_buildtag(void); -#define REL_VERSION "8.3.8rc2" +#define REL_VERSION "8.3.8" #define API_VERSION 88 #define PRO_VERSION_MIN 86 #define PRO_VERSION_MAX 94 diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index b3cd4de9432b..52c0da4bdd18 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -40,7 +40,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n, const char *modname); #if defined(CONFIG_DYNAMIC_DEBUG) -extern int ddebug_remove_module(char *mod_name); +extern int ddebug_remove_module(const char *mod_name); #define __dynamic_dbg_enabled(dd) ({ \ int __ret = 0; \ @@ -73,7 +73,7 @@ extern int ddebug_remove_module(char *mod_name); #else -static inline int ddebug_remove_module(char *mod) +static inline int ddebug_remove_module(const char *mod) { return 0; } diff --git a/include/linux/fb.h b/include/linux/fb.h index 907ace3a64c8..8e5a9dfb76bf 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -786,8 +786,6 @@ struct fb_tile_ops { #define FBINFO_MISC_USEREVENT 0x10000 /* event request from userspace */ #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ -#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware - inited framebuffer */ /* A driver may set this flag to indicate that it does want a set_par to be * called every time when fbcon_switch is executed. The advantage is that with @@ -801,6 +799,8 @@ struct fb_tile_ops { */ #define FBINFO_MISC_ALWAYS_SETPAR 0x40000 +/* where the fb is a firmware driver, and can be replaced with a proper one */ +#define FBINFO_MISC_FIRMWARE 0x80000 /* * Host and GPU endianness differ. */ diff --git a/include/linux/list.h b/include/linux/list.h index 8392884a2977..5d57a3a1fa1b 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -544,6 +544,21 @@ static inline void list_splice_tail_init(struct list_head *list, &pos->member != (head); \ pos = n, n = list_entry(n->member.prev, typeof(*n), member)) +/** + * list_safe_reset_next - reset a stale list_for_each_entry_safe loop + * @pos: the loop cursor used in the list_for_each_entry_safe loop + * @n: temporary storage used in list_for_each_entry_safe + * @member: the name of the list_struct within the struct. + * + * list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define list_safe_reset_next(pos, n, member) \ + n = list_entry(pos->member.next, typeof(*pos), member) + /* * Double linked lists with a single pointer list head. * Mostly useful for hash tables where the two pointer list head is diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index b631c46cffd9..f6c9b7dcb9fd 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -3,6 +3,12 @@ #include <linux/module.h> #include <linux/major.h> +/* + * These allocations are managed by device@lanana.org. If you use an + * entry that is not in assigned your entry may well be moved and + * reassigned, or set dynamic if a fixed value is not justified. + */ + #define PSMOUSE_MINOR 1 #define MS_BUSMOUSE_MINOR 2 #define ATIXL_BUSMOUSE_MINOR 3 @@ -30,7 +36,6 @@ #define HPET_MINOR 228 #define FUSE_MINOR 229 #define KVM_MINOR 232 -#define VHOST_NET_MINOR 233 #define BTRFS_MINOR 234 #define AUTOFS_MINOR 235 #define MISC_DYNAMIC_MINOR 255 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f149dd10908b..3bedcc149c84 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1261,6 +1261,7 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA 0x0D85 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_TT128 0x9128 @@ -2321,6 +2322,7 @@ #define PCI_VENDOR_ID_JMICRON 0x197B #define PCI_DEVICE_ID_JMICRON_JMB360 0x2360 #define PCI_DEVICE_ID_JMICRON_JMB361 0x2361 +#define PCI_DEVICE_ID_JMICRON_JMB362 0x2362 #define PCI_DEVICE_ID_JMICRON_JMB363 0x2363 #define PCI_DEVICE_ID_JMICRON_JMB365 0x2365 #define PCI_DEVICE_ID_JMICRON_JMB366 0x2366 diff --git a/include/linux/sched.h b/include/linux/sched.h index f118809c953f..747fcaedddb7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -139,7 +139,7 @@ extern int nr_processes(void); extern unsigned long nr_running(void); extern unsigned long nr_uninterruptible(void); extern unsigned long nr_iowait(void); -extern unsigned long nr_iowait_cpu(void); +extern unsigned long nr_iowait_cpu(int cpu); extern unsigned long this_cpu_load(void); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index bf243fc54959..f89e7fd59a4c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -380,7 +380,10 @@ struct sk_buff { kmemcheck_bitfield_begin(flags2); __u16 queue_mapping:16; #ifdef CONFIG_IPV6_NDISC_NODETYPE - __u8 ndisc_nodetype:2; + __u8 ndisc_nodetype:2, + deliver_no_wcard:1; +#else + __u8 deliver_no_wcard:1; #endif kmemcheck_bitfield_end(flags2); diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5e781d824e6d..bc7d6bb4cd8e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; } static inline bool system_entering_hibernation(void) { return false; } #endif /* CONFIG_HIBERNATION */ -#ifdef CONFIG_HIBERNATION_NVS -extern int hibernate_nvs_register(unsigned long start, unsigned long size); -extern int hibernate_nvs_alloc(void); -extern void hibernate_nvs_free(void); -extern void hibernate_nvs_save(void); -extern void hibernate_nvs_restore(void); -#else /* CONFIG_HIBERNATION_NVS */ -static inline int hibernate_nvs_register(unsigned long a, unsigned long b) +#ifdef CONFIG_SUSPEND_NVS +extern int suspend_nvs_register(unsigned long start, unsigned long size); +extern int suspend_nvs_alloc(void); +extern void suspend_nvs_free(void); +extern void suspend_nvs_save(void); +extern void suspend_nvs_restore(void); +#else /* CONFIG_SUSPEND_NVS */ +static inline int suspend_nvs_register(unsigned long a, unsigned long b) { return 0; } -static inline int hibernate_nvs_alloc(void) { return 0; } -static inline void hibernate_nvs_free(void) {} -static inline void hibernate_nvs_save(void) {} -static inline void hibernate_nvs_restore(void) {} -#endif /* CONFIG_HIBERNATION_NVS */ +static inline int suspend_nvs_alloc(void) { return 0; } +static inline void suspend_nvs_free(void) {} +static inline void suspend_nvs_save(void) {} +static inline void suspend_nvs_restore(void) {} +#endif /* CONFIG_SUSPEND_NVS */ #ifdef CONFIG_PM_SLEEP void save_processor_state(void); diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 9a59d1f98cd4..103d1b61aacb 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -14,6 +14,7 @@ * See the file COPYING for more details. */ +#include <linux/errno.h> #include <linux/types.h> #include <linux/rcupdate.h> diff --git a/include/linux/writeback.h b/include/linux/writeback.h index f64134653a8c..d63ef8f9609f 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -56,15 +56,6 @@ struct writeback_control { unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned range_cyclic:1; /* range_start is cyclic */ unsigned more_io:1; /* more io to be dispatched */ - /* - * write_cache_pages() won't update wbc->nr_to_write and - * mapping->writeback_index if no_nrwrite_index_update - * is set. write_cache_pages() may write more than we - * requested and we want to make sure nr_to_write and - * writeback_index are updated in a consistent manner - * so we use a single control to update them - */ - unsigned no_nrwrite_index_update:1; }; /* diff --git a/include/net/snmp.h b/include/net/snmp.h index 92456f1035f5..899003d18db9 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -134,7 +134,7 @@ struct linux_xfrm_mib { #define SNMP_ADD_STATS_USER(mib, field, addend) \ this_cpu_add(mib[1]->mibs[field], addend) #define SNMP_ADD_STATS(mib, field, addend) \ - this_cpu_add(mib[0]->mibs[field], addend) + this_cpu_add(mib[!in_softirq()]->mibs[field], addend) /* * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr" * to make @ptr a non-percpu pointer. diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index f5b1ba90e952..f3865c7b4166 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h @@ -306,7 +306,6 @@ TRACE_EVENT(ext4_da_writepages_result, __field( int, pages_written ) __field( long, pages_skipped ) __field( char, more_io ) - __field( char, no_nrwrite_index_update ) __field( pgoff_t, writeback_index ) ), @@ -317,16 +316,14 @@ TRACE_EVENT(ext4_da_writepages_result, __entry->pages_written = pages_written; __entry->pages_skipped = wbc->pages_skipped; __entry->more_io = wbc->more_io; - __entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update; __entry->writeback_index = inode->i_mapping->writeback_index; ), - TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d no_nrwrite_index_update %d writeback_index %lu", + TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d writeback_index %lu", jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, __entry->ret, __entry->pages_written, __entry->pages_skipped, __entry->more_io, - __entry->no_nrwrite_index_update, (unsigned long) __entry->writeback_index) ); diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h index 814566c99d29..17df43464df0 100644 --- a/include/trace/events/signal.h +++ b/include/trace/events/signal.h @@ -10,7 +10,8 @@ #define TP_STORE_SIGINFO(__entry, info) \ do { \ - if (info == SEND_SIG_NOINFO) { \ + if (info == SEND_SIG_NOINFO || \ + info == SEND_SIG_FORCED) { \ __entry->errno = 0; \ __entry->code = SI_USER; \ } else if (info == SEND_SIG_PRIV) { \ diff --git a/init/main.c b/init/main.c index 3bdb152f412f..a42fdf4aeba9 100644 --- a/init/main.c +++ b/init/main.c @@ -125,7 +125,9 @@ static char *ramdisk_execute_command; #ifdef CONFIG_SMP /* Setup configured maximum number of CPUs to activate */ -unsigned int __initdata setup_max_cpus = NR_CPUS; +unsigned int setup_max_cpus = NR_CPUS; +EXPORT_SYMBOL(setup_max_cpus); + /* * Setup routine for controlling SMP activation @@ -422,18 +424,26 @@ static void __init setup_command_line(char *command_line) * gcc-3.4 accidentally inlines this function, so use noinline. */ +static __initdata DECLARE_COMPLETION(kthreadd_done); + static noinline void __init_refok rest_init(void) __releases(kernel_lock) { int pid; rcu_scheduler_starting(); + /* + * We need to spawn init first so that it obtains pid 1, however + * the init task will end up wanting to create kthreads, which, if + * we schedule it before we create kthreadd, will OOPS. + */ kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); numa_default_policy(); pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); rcu_read_lock(); kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); rcu_read_unlock(); + complete(&kthreadd_done); unlock_kernel(); /* @@ -855,6 +865,10 @@ static noinline int init_post(void) static int __init kernel_init(void * unused) { + /* + * Wait until kthreadd is all set-up. + */ + wait_for_completion(&kthreadd_done); lock_kernel(); /* diff --git a/kernel/futex.c b/kernel/futex.c index e7a35f1039e7..6a3a5fa1526d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -429,20 +429,11 @@ static void free_pi_state(struct futex_pi_state *pi_state) static struct task_struct * futex_find_get_task(pid_t pid) { struct task_struct *p; - const struct cred *cred = current_cred(), *pcred; rcu_read_lock(); p = find_task_by_vpid(pid); - if (!p) { - p = ERR_PTR(-ESRCH); - } else { - pcred = __task_cred(p); - if (cred->euid != pcred->euid && - cred->euid != pcred->uid) - p = ERR_PTR(-ESRCH); - else - get_task_struct(p); - } + if (p) + get_task_struct(p); rcu_read_unlock(); @@ -564,8 +555,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, if (!pid) return -ESRCH; p = futex_find_get_task(pid); - if (IS_ERR(p)) - return PTR_ERR(p); + if (!p) + return -ESRCH; /* * We need to look at the task state flags to figure out, diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 3164ba7ce151..e1497481fe8a 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -456,6 +456,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */ desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK); desc->status |= flags; + + if (chip != desc->chip) + irq_chip_set_defaults(desc->chip); } return ret; diff --git a/kernel/kexec.c b/kernel/kexec.c index 474a84715eac..131b1703936f 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1089,9 +1089,10 @@ void crash_kexec(struct pt_regs *regs) size_t crash_get_memory_size(void) { - size_t size; + size_t size = 0; mutex_lock(&kexec_mutex); - size = crashk_res.end - crashk_res.start + 1; + if (crashk_res.end != crashk_res.start) + size = crashk_res.end - crashk_res.start + 1; mutex_unlock(&kexec_mutex); return size; } @@ -1134,7 +1135,7 @@ int crash_shrink_memory(unsigned long new_size) free_reserved_phys_range(end, crashk_res.end); - if (start == end) + if ((start == end) && (crashk_res.parent != NULL)) release_resource(&crashk_res); crashk_res.end = end - 1; diff --git a/kernel/module.c b/kernel/module.c index 8c6b42840dd1..5d2d28197c82 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2062,6 +2062,12 @@ static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num) #endif } +static void dynamic_debug_remove(struct _ddebug *debug) +{ + if (debug) + ddebug_remove_module(debug->modname); +} + static void *module_alloc_update_bounds(unsigned long size) { void *ret = module_alloc(size); @@ -2124,6 +2130,8 @@ static noinline struct module *load_module(void __user *umod, void *ptr = NULL; /* Stops spurious gcc warning */ unsigned long symoffs, stroffs, *strmap; void __percpu *percpu; + struct _ddebug *debug = NULL; + unsigned int num_debug = 0; mm_segment_t old_fs; @@ -2476,15 +2484,9 @@ static noinline struct module *load_module(void __user *umod, kfree(strmap); strmap = NULL; - if (!mod->taints) { - struct _ddebug *debug; - unsigned int num_debug; - + if (!mod->taints) debug = section_objs(hdr, sechdrs, secstrings, "__verbose", sizeof(*debug), &num_debug); - if (debug) - dynamic_debug_setup(debug, num_debug); - } err = module_finalize(hdr, sechdrs, mod); if (err < 0) @@ -2526,10 +2528,13 @@ static noinline struct module *load_module(void __user *umod, goto unlock; } + if (debug) + dynamic_debug_setup(debug, num_debug); + /* Find duplicate symbols */ err = verify_export_symbols(mod); if (err < 0) - goto unlock; + goto ddebug; list_add_rcu(&mod->list, &modules); mutex_unlock(&module_mutex); @@ -2557,6 +2562,8 @@ static noinline struct module *load_module(void __user *umod, mutex_lock(&module_mutex); /* Unlink carefully: kallsyms could be walking list. */ list_del_rcu(&mod->list); + ddebug: + dynamic_debug_remove(debug); unlock: mutex_unlock(&module_mutex); synchronize_sched(); diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 31d6afe92594..ff86c558af4c 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1507,6 +1507,9 @@ do { \ divisor = nsec * frequency; } + if (!divisor) + return dividend; + return div64_u64(dividend, divisor); } @@ -1529,7 +1532,7 @@ static int perf_event_start(struct perf_event *event) static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) { struct hw_perf_event *hwc = &event->hw; - u64 period, sample_period; + s64 period, sample_period; s64 delta; period = perf_calculate_period(event, nsec, count); diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 5c36ea9d55d2..ca6066a6952e 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG depends on PM_ADVANCED_DEBUG default n +config SUSPEND_NVS + bool + config SUSPEND bool "Suspend to RAM and standby" depends on PM && ARCH_SUSPEND_POSSIBLE + select SUSPEND_NVS if HAS_IOMEM default y ---help--- Allow the system to enter sleep states in which main memory is @@ -130,13 +134,10 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. -config HIBERNATION_NVS - bool - config HIBERNATION bool "Hibernation (aka 'suspend to disk')" depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE - select HIBERNATION_NVS if HAS_IOMEM + select SUSPEND_NVS if HAS_IOMEM ---help--- Enable the suspend to disk (STD) functionality, which is usually called "hibernation" in user interfaces. STD checkpoints the diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 524e058dcf06..f9063c6b185d 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ block_io.o -obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o +obj-$(CONFIG_SUSPEND_NVS) += nvs.o obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o diff --git a/kernel/power/hibernate_nvs.c b/kernel/power/nvs.c index fdcad9ed5a7b..1836db60bbb6 100644 --- a/kernel/power/hibernate_nvs.c +++ b/kernel/power/nvs.c @@ -15,7 +15,7 @@ /* * Platforms, like ACPI, may want us to save some memory used by them during - * hibernation and to restore the contents of this memory during the subsequent + * suspend and to restore the contents of this memory during the subsequent * resume. The code below implements a mechanism allowing us to do that. */ @@ -30,7 +30,7 @@ struct nvs_page { static LIST_HEAD(nvs_list); /** - * hibernate_nvs_register - register platform NVS memory region to save + * suspend_nvs_register - register platform NVS memory region to save * @start - physical address of the region * @size - size of the region * @@ -38,7 +38,7 @@ static LIST_HEAD(nvs_list); * things so that the data from page-aligned addresses in this region will * be copied into separate RAM pages. */ -int hibernate_nvs_register(unsigned long start, unsigned long size) +int suspend_nvs_register(unsigned long start, unsigned long size) { struct nvs_page *entry, *next; @@ -68,9 +68,9 @@ int hibernate_nvs_register(unsigned long start, unsigned long size) } /** - * hibernate_nvs_free - free data pages allocated for saving NVS regions + * suspend_nvs_free - free data pages allocated for saving NVS regions */ -void hibernate_nvs_free(void) +void suspend_nvs_free(void) { struct nvs_page *entry; @@ -86,16 +86,16 @@ void hibernate_nvs_free(void) } /** - * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions + * suspend_nvs_alloc - allocate memory necessary for saving NVS regions */ -int hibernate_nvs_alloc(void) +int suspend_nvs_alloc(void) { struct nvs_page *entry; list_for_each_entry(entry, &nvs_list, node) { entry->data = (void *)__get_free_page(GFP_KERNEL); if (!entry->data) { - hibernate_nvs_free(); + suspend_nvs_free(); return -ENOMEM; } } @@ -103,9 +103,9 @@ int hibernate_nvs_alloc(void) } /** - * hibernate_nvs_save - save NVS memory regions + * suspend_nvs_save - save NVS memory regions */ -void hibernate_nvs_save(void) +void suspend_nvs_save(void) { struct nvs_page *entry; @@ -119,12 +119,12 @@ void hibernate_nvs_save(void) } /** - * hibernate_nvs_restore - restore NVS memory regions + * suspend_nvs_restore - restore NVS memory regions * * This function is going to be called with interrupts disabled, so it * cannot iounmap the virtual addresses used to access the NVS region. */ -void hibernate_nvs_restore(void) +void suspend_nvs_restore(void) { struct nvs_page *entry; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 56e7dbb8b996..f37cb7dd4402 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -16,6 +16,12 @@ #include <linux/cpu.h> #include <linux/syscalls.h> #include <linux/gfp.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/suspend.h> #include "power.h" diff --git a/kernel/sched.c b/kernel/sched.c index f8b8996228dd..f52a8801b7a2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -306,52 +306,6 @@ static int init_task_group_load = INIT_TASK_GROUP_LOAD; */ struct task_group init_task_group; -/* return group to which a task belongs */ -static inline struct task_group *task_group(struct task_struct *p) -{ - struct task_group *tg; - -#ifdef CONFIG_CGROUP_SCHED - tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id), - struct task_group, css); -#else - tg = &init_task_group; -#endif - return tg; -} - -/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ -static inline void set_task_rq(struct task_struct *p, unsigned int cpu) -{ - /* - * Strictly speaking this rcu_read_lock() is not needed since the - * task_group is tied to the cgroup, which in turn can never go away - * as long as there are tasks attached to it. - * - * However since task_group() uses task_subsys_state() which is an - * rcu_dereference() user, this quiets CONFIG_PROVE_RCU. - */ - rcu_read_lock(); -#ifdef CONFIG_FAIR_GROUP_SCHED - p->se.cfs_rq = task_group(p)->cfs_rq[cpu]; - p->se.parent = task_group(p)->se[cpu]; -#endif - -#ifdef CONFIG_RT_GROUP_SCHED - p->rt.rt_rq = task_group(p)->rt_rq[cpu]; - p->rt.parent = task_group(p)->rt_se[cpu]; -#endif - rcu_read_unlock(); -} - -#else - -static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { } -static inline struct task_group *task_group(struct task_struct *p) -{ - return NULL; -} - #endif /* CONFIG_CGROUP_SCHED */ /* CFS-related fields in a runqueue */ @@ -644,6 +598,49 @@ static inline int cpu_of(struct rq *rq) #define cpu_curr(cpu) (cpu_rq(cpu)->curr) #define raw_rq() (&__raw_get_cpu_var(runqueues)) +#ifdef CONFIG_CGROUP_SCHED + +/* + * Return the group to which this tasks belongs. + * + * We use task_subsys_state_check() and extend the RCU verification + * with lockdep_is_held(&task_rq(p)->lock) because cpu_cgroup_attach() + * holds that lock for each task it moves into the cgroup. Therefore + * by holding that lock, we pin the task to the current cgroup. + */ +static inline struct task_group *task_group(struct task_struct *p) +{ + struct cgroup_subsys_state *css; + + css = task_subsys_state_check(p, cpu_cgroup_subsys_id, + lockdep_is_held(&task_rq(p)->lock)); + return container_of(css, struct task_group, css); +} + +/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ +static inline void set_task_rq(struct task_struct *p, unsigned int cpu) +{ +#ifdef CONFIG_FAIR_GROUP_SCHED + p->se.cfs_rq = task_group(p)->cfs_rq[cpu]; + p->se.parent = task_group(p)->se[cpu]; +#endif + +#ifdef CONFIG_RT_GROUP_SCHED + p->rt.rt_rq = task_group(p)->rt_rq[cpu]; + p->rt.parent = task_group(p)->rt_se[cpu]; +#endif +} + +#else /* CONFIG_CGROUP_SCHED */ + +static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { } +static inline struct task_group *task_group(struct task_struct *p) +{ + return NULL; +} + +#endif /* CONFIG_CGROUP_SCHED */ + inline void update_rq_clock(struct rq *rq) { if (!rq->skip_clock_update) @@ -1257,6 +1254,12 @@ static void sched_avg_update(struct rq *rq) s64 period = sched_avg_period(); while ((s64)(rq->clock - rq->age_stamp) > period) { + /* + * Inline assembly required to prevent the compiler + * optimising this loop into a divmod call. + * See __iter_div_u64_rem() for another example of this. + */ + asm("" : "+rm" (rq->age_stamp)); rq->age_stamp += period; rq->rt_avg /= 2; } @@ -1660,9 +1663,6 @@ static void update_shares(struct sched_domain *sd) static void update_h_load(long cpu) { - if (root_task_group_empty()) - return; - walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); } @@ -2494,7 +2494,16 @@ void sched_fork(struct task_struct *p, int clone_flags) if (p->sched_class->task_fork) p->sched_class->task_fork(p); + /* + * The child is not yet in the pid-hash so no cgroup attach races, + * and the cgroup is pinned to this child due to cgroup_fork() + * is ran before sched_fork(). + * + * Silence PROVE_RCU. + */ + rcu_read_lock(); set_task_cpu(p, cpu); + rcu_read_unlock(); #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) if (likely(sched_info_on())) @@ -2864,9 +2873,9 @@ unsigned long nr_iowait(void) return sum; } -unsigned long nr_iowait_cpu(void) +unsigned long nr_iowait_cpu(int cpu) { - struct rq *this = this_rq(); + struct rq *this = cpu_rq(cpu); return atomic_read(&this->nr_iowait); } @@ -4465,16 +4474,6 @@ recheck: } if (user) { -#ifdef CONFIG_RT_GROUP_SCHED - /* - * Do not allow realtime tasks into groups that have no runtime - * assigned. - */ - if (rt_bandwidth_enabled() && rt_policy(policy) && - task_group(p)->rt_bandwidth.rt_runtime == 0) - return -EPERM; -#endif - retval = security_task_setscheduler(p, policy, param); if (retval) return retval; @@ -4490,6 +4489,22 @@ recheck: * runqueue lock must be held. */ rq = __task_rq_lock(p); + +#ifdef CONFIG_RT_GROUP_SCHED + if (user) { + /* + * Do not allow realtime tasks into groups that have no runtime + * assigned. + */ + if (rt_bandwidth_enabled() && rt_policy(policy) && + task_group(p)->rt_bandwidth.rt_runtime == 0) { + __task_rq_unlock(rq); + raw_spin_unlock_irqrestore(&p->pi_lock, flags); + return -EPERM; + } + } +#endif + /* recheck policy now with rq lock held */ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { policy = oldpolicy = -1; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index eed35eded602..a878b5332daa 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1240,6 +1240,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) * effect of the currently running task from the load * of the current CPU: */ + rcu_read_lock(); if (sync) { tg = task_group(current); weight = current->se.load.weight; @@ -1275,6 +1276,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) balanced = this_eff_load <= prev_eff_load; } else balanced = true; + rcu_read_unlock(); /* * If the currently running task will sleep within diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 1d7b9bc1c034..813993b5fb61 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -154,14 +154,14 @@ static void tick_nohz_update_jiffies(ktime_t now) * Updates the per cpu time idle statistics counters */ static void -update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time) +update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_update_time) { ktime_t delta; if (ts->idle_active) { delta = ktime_sub(now, ts->idle_entrytime); ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); - if (nr_iowait_cpu() > 0) + if (nr_iowait_cpu(cpu) > 0) ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta); ts->idle_entrytime = now; } @@ -175,19 +175,19 @@ static void tick_nohz_stop_idle(int cpu, ktime_t now) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); - update_ts_time_stats(ts, now, NULL); + update_ts_time_stats(cpu, ts, now, NULL); ts->idle_active = 0; sched_clock_idle_wakeup_event(0); } -static ktime_t tick_nohz_start_idle(struct tick_sched *ts) +static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts) { ktime_t now; now = ktime_get(); - update_ts_time_stats(ts, now, NULL); + update_ts_time_stats(cpu, ts, now, NULL); ts->idle_entrytime = now; ts->idle_active = 1; @@ -216,7 +216,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) if (!tick_nohz_enabled) return -1; - update_ts_time_stats(ts, ktime_get(), last_update_time); + update_ts_time_stats(cpu, ts, ktime_get(), last_update_time); return ktime_to_us(ts->idle_sleeptime); } @@ -242,7 +242,7 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time) if (!tick_nohz_enabled) return -1; - update_ts_time_stats(ts, ktime_get(), last_update_time); + update_ts_time_stats(cpu, ts, ktime_get(), last_update_time); return ktime_to_us(ts->iowait_sleeptime); } @@ -284,7 +284,7 @@ void tick_nohz_stop_sched_tick(int inidle) */ ts->inidle = 1; - now = tick_nohz_start_idle(ts); + now = tick_nohz_start_idle(cpu, ts); /* * If this cpu is offline and it is the one which updates @@ -315,9 +315,6 @@ void tick_nohz_stop_sched_tick(int inidle) goto end; } - if (nohz_ratelimit(cpu)) - goto end; - ts->idle_calls++; /* Read jiffies and the time when jiffies were updated last */ do { @@ -328,7 +325,7 @@ void tick_nohz_stop_sched_tick(int inidle) } while (read_seqretry(&xtime_lock, seq)); if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || - arch_needs_cpu(cpu)) { + arch_needs_cpu(cpu) || nohz_ratelimit(cpu)) { next_jiffies = last_jiffies + 1; delta_jiffies = 1; } else { diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index e6f65887842c..8a2b73f7c068 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -96,7 +96,9 @@ int perf_trace_init(struct perf_event *p_event) mutex_lock(&event_mutex); list_for_each_entry(tp_event, &ftrace_events, list) { if (tp_event->event.type == event_id && - tp_event->class && tp_event->class->perf_probe && + tp_event->class && + (tp_event->class->perf_probe || + tp_event->class->reg) && try_module_get(tp_event->mod)) { ret = perf_trace_event_init(tp_event, p_event); break; diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 3df8eb17a607..02afc2533728 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -692,7 +692,7 @@ static void ddebug_table_free(struct ddebug_table *dt) * Called in response to a module being unloaded. Removes * any ddebug_table's which point at the module. */ -int ddebug_remove_module(char *mod_name) +int ddebug_remove_module(const char *mod_name) { struct ddebug_table *dt, *nextdt; int ret = -ENOENT; diff --git a/lib/genalloc.c b/lib/genalloc.c index 736c3b06398e..1923f1490e72 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -128,7 +128,6 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); end_bit = (chunk->end_addr - chunk->start_addr) >> order; - end_bit -= nbits + 1; spin_lock_irqsave(&chunk->lock, flags); start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0, diff --git a/lib/idr.c b/lib/idr.c index c1a206901761..7f1a4f0acf50 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -602,7 +602,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) /* find first ent */ n = idp->layers * IDR_BITS; max = 1 << n; - p = rcu_dereference(idp->top); + p = rcu_dereference_raw(idp->top); if (!p) return NULL; @@ -610,7 +610,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) while (n > 0 && p) { n -= IDR_BITS; *paa++ = p; - p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); + p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); } if (p) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c6ece0a57595..20a8193a7af8 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1370,7 +1370,7 @@ static void memcg_wakeup_oom(struct mem_cgroup *mem) static void memcg_oom_recover(struct mem_cgroup *mem) { - if (mem->oom_kill_disable && atomic_read(&mem->oom_lock)) + if (atomic_read(&mem->oom_lock)) memcg_wakeup_oom(mem); } @@ -3781,6 +3781,8 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp, return -EINVAL; } mem->oom_kill_disable = val; + if (!val) + memcg_oom_recover(mem); cgroup_unlock(); return 0; } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 5d6fb339de03..5bc0a96beb51 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2094,7 +2094,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol) NODEMASK_SCRATCH(scratch); if (!scratch) - return; + goto put_mpol; /* contextualize the tmpfs mount point mempolicy */ new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask); if (IS_ERR(new)) @@ -2103,19 +2103,20 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol) task_lock(current); ret = mpol_set_nodemask(new, &mpol->w.user_nodemask, scratch); task_unlock(current); - mpol_put(mpol); /* drop our ref on sb mpol */ if (ret) - goto put_free; + goto put_new; /* Create pseudo-vma that contains just the policy */ memset(&pvma, 0, sizeof(struct vm_area_struct)); pvma.vm_end = TASK_SIZE; /* policy covers entire file */ mpol_set_shared_policy(sp, &pvma, new); /* adds ref */ -put_free: +put_new: mpol_put(new); /* drop initial ref */ free_scratch: NODEMASK_SCRATCH_FREE(scratch); +put_mpol: + mpol_put(mpol); /* drop our incoming ref on sb mpol */ } } diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 5fa63bdf52e4..54f28bd493d3 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -597,7 +597,7 @@ static void balance_dirty_pages(struct address_space *mapping, (!laptop_mode && ((global_page_state(NR_FILE_DIRTY) + global_page_state(NR_UNSTABLE_NFS)) > background_thresh))) - bdi_start_writeback(bdi, NULL, 0); + bdi_start_background_writeback(bdi); } void set_page_dirty_balance(struct page *page, int page_mkwrite) @@ -705,9 +705,8 @@ void laptop_mode_timer_fn(unsigned long data) * We want to write everything out, not just down to the dirty * threshold */ - if (bdi_has_dirty_io(&q->backing_dev_info)) - bdi_start_writeback(&q->backing_dev_info, NULL, nr_pages); + bdi_start_writeback(&q->backing_dev_info, nr_pages); } /* @@ -835,7 +834,6 @@ int write_cache_pages(struct address_space *mapping, pgoff_t done_index; int cycled; int range_whole = 0; - long nr_to_write = wbc->nr_to_write; pagevec_init(&pvec, 0); if (wbc->range_cyclic) { @@ -852,7 +850,22 @@ int write_cache_pages(struct address_space *mapping, if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) range_whole = 1; cycled = 1; /* ignore range_cyclic tests */ + + /* + * If this is a data integrity sync, cap the writeback to the + * current end of file. Any extension to the file that occurs + * after this is a new write and we don't need to write those + * pages out to fulfil our data integrity requirements. If we + * try to write them out, we can get stuck in this scan until + * the concurrent writer stops adding dirty pages and extending + * EOF. + */ + if (wbc->sync_mode == WB_SYNC_ALL && + wbc->range_end == LLONG_MAX) { + end = i_size_read(mapping->host) >> PAGE_CACHE_SHIFT; + } } + retry: done_index = index; while (!done && (index <= end)) { @@ -935,11 +948,10 @@ continue_unlock: done = 1; break; } - } + } - if (nr_to_write > 0) { - nr_to_write--; - if (nr_to_write == 0 && + if (wbc->nr_to_write > 0) { + if (--wbc->nr_to_write == 0 && wbc->sync_mode == WB_SYNC_NONE) { /* * We stop writing back only if we are @@ -970,11 +982,8 @@ continue_unlock: end = writeback_index - 1; goto retry; } - if (!wbc->no_nrwrite_index_update) { - if (wbc->range_cyclic || (range_whole && nr_to_write > 0)) - mapping->writeback_index = done_index; - wbc->nr_to_write = nr_to_write; - } + if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) + mapping->writeback_index = done_index; return ret; } diff --git a/mm/percpu.c b/mm/percpu.c index 39f7dfd59585..6470e7710231 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -229,8 +229,8 @@ static int __maybe_unused pcpu_page_idx(unsigned int cpu, int page_idx) return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx; } -static unsigned long __maybe_unused pcpu_chunk_addr(struct pcpu_chunk *chunk, - unsigned int cpu, int page_idx) +static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk, + unsigned int cpu, int page_idx) { return (unsigned long)chunk->base_addr + pcpu_unit_offsets[cpu] + (page_idx << PAGE_SHIFT); @@ -978,7 +978,32 @@ bool is_kernel_percpu_address(unsigned long addr) */ phys_addr_t per_cpu_ptr_to_phys(void *addr) { - if (pcpu_addr_in_first_chunk(addr)) { + void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); + bool in_first_chunk = false; + unsigned long first_start, first_end; + unsigned int cpu; + + /* + * The following test on first_start/end isn't strictly + * necessary but will speed up lookups of addresses which + * aren't in the first chunk. + */ + first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0); + first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu, + pcpu_unit_pages); + if ((unsigned long)addr >= first_start && + (unsigned long)addr < first_end) { + for_each_possible_cpu(cpu) { + void *start = per_cpu_ptr(base, cpu); + + if (addr >= start && addr < start + pcpu_unit_size) { + in_first_chunk = true; + break; + } + } + } + + if (in_first_chunk) { if ((unsigned long)addr < VMALLOC_START || (unsigned long)addr >= VMALLOC_END) return __pa(addr); @@ -1086,7 +1111,7 @@ struct pcpu_alloc_info * __init pcpu_build_alloc_info( static int group_map[NR_CPUS] __initdata; static int group_cnt[NR_CPUS] __initdata; const size_t static_size = __per_cpu_end - __per_cpu_start; - int group_cnt_max = 0, nr_groups = 1, nr_units = 0; + int nr_groups = 1, nr_units = 0; size_t size_sum, min_unit_size, alloc_size; int upa, max_upa, uninitialized_var(best_upa); /* units_per_alloc */ int last_allocs, group, unit; @@ -1096,7 +1121,7 @@ struct pcpu_alloc_info * __init pcpu_build_alloc_info( /* this function may be called multiple times */ memset(group_map, 0, sizeof(group_map)); - memset(group_cnt, 0, sizeof(group_map)); + memset(group_cnt, 0, sizeof(group_cnt)); /* * Determine min_unit_size, alloc_size and max_upa such that @@ -1130,7 +1155,6 @@ struct pcpu_alloc_info * __init pcpu_build_alloc_info( } group_map[cpu] = group; group_cnt[group]++; - group_cnt_max = max(group_cnt_max, group_cnt[group]); } /* diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index bd537fc10254..50f58f5f1c34 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -12,7 +12,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, return NET_RX_DROP; if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) - goto drop; + skb->deliver_no_wcard = 1; skb->skb_iif = skb->dev->ifindex; __vlan_hwaccel_put_tag(skb, vlan_tci); @@ -84,7 +84,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, struct sk_buff *p; if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) - goto drop; + skb->deliver_no_wcard = 1; skb->skb_iif = skb->dev->ifindex; __vlan_hwaccel_put_tag(skb, vlan_tci); diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 0faad5ce6dc4..8c100c9dae28 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -104,6 +104,8 @@ static void bnep_net_set_mc_list(struct net_device *dev) break; memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); + + i++; } r->len = htons(skb->len - len); } diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 26637439965b..b01dde35a69e 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -128,7 +128,7 @@ void br_fdb_cleanup(unsigned long _data) { struct net_bridge *br = (struct net_bridge *)_data; unsigned long delay = hold_time(br); - unsigned long next_timer = jiffies + br->forward_delay; + unsigned long next_timer = jiffies + br->ageing_time; int i; spin_lock_bh(&br->hash_lock); @@ -149,9 +149,7 @@ void br_fdb_cleanup(unsigned long _data) } spin_unlock_bh(&br->hash_lock); - /* Add HZ/4 to ensure we round the jiffies upwards to be after the next - * timer, otherwise we might round down and will have no-op run. */ - mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4)); + mod_timer(&br->gc_timer, round_jiffies_up(next_timer)); } /* Completely flush all dynamic entries in forwarding database.*/ diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index a98ef1393097..a4e72a89e4ff 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -140,10 +140,10 @@ static int deliver_clone(const struct net_bridge_port *prev, void (*__packet_hook)(const struct net_bridge_port *p, struct sk_buff *skb)) { + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; + skb = skb_clone(skb, GFP_ATOMIC); if (!skb) { - struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; - dev->stats.tx_dropped++; return -ENOMEM; } diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index cd2830fec935..fd27b172fb5d 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -83,7 +83,7 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) if (!cfsrvl_ready(service, &ret)) return ret; - if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { + if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { pr_err("CAIF: %s():Packet too large - size=%d\n", __func__, cfpkt_getlen(pkt)); return -EOVERFLOW; diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c index 0fd827f49491..e04f7d964e83 100644 --- a/net/caif/cfveil.c +++ b/net/caif/cfveil.c @@ -84,7 +84,7 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) return ret; caif_assert(layr->dn != NULL); caif_assert(layr->dn->transmit != NULL); - if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { + if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { pr_warning("CAIF: %s(): Packet too large - size=%d\n", __func__, cfpkt_getlen(pkt)); return -EOVERFLOW; diff --git a/net/core/dev.c b/net/core/dev.c index d03470f5260a..2b3bf53bc687 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2253,11 +2253,9 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (skb_rx_queue_recorded(skb)) { u16 index = skb_get_rx_queue(skb); if (unlikely(index >= dev->num_rx_queues)) { - if (net_ratelimit()) { - pr_warning("%s received packet on queue " - "%u, but number of RX queues is %u\n", - dev->name, index, dev->num_rx_queues); - } + WARN_ONCE(dev->num_rx_queues > 1, "%s received packet " + "on queue %u, but number of RX queues is %u\n", + dev->name, index, dev->num_rx_queues); goto done; } rxqueue = dev->_rx + index; @@ -2812,13 +2810,24 @@ static int __netif_receive_skb(struct sk_buff *skb) if (!skb->skb_iif) skb->skb_iif = skb->dev->ifindex; + /* + * bonding note: skbs received on inactive slaves should only + * be delivered to pkt handlers that are exact matches. Also + * the deliver_no_wcard flag will be set. If packet handlers + * are sensitive to duplicate packets these skbs will need to + * be dropped at the handler. The vlan accel path may have + * already set the deliver_no_wcard flag. + */ null_or_orig = NULL; orig_dev = skb->dev; master = ACCESS_ONCE(orig_dev->master); - if (master) { - if (skb_bond_should_drop(skb, master)) + if (skb->deliver_no_wcard) + null_or_orig = orig_dev; + else if (master) { + if (skb_bond_should_drop(skb, master)) { + skb->deliver_no_wcard = 1; null_or_orig = orig_dev; /* deliver only exact match */ - else + } else skb->dev = master; } diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index cf8e70392fe0..785e5276a300 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -107,6 +107,7 @@ static DEFINE_RWLOCK(est_lock); /* Protects against soft lockup during large deletion */ static struct rb_root est_root = RB_ROOT; +static DEFINE_SPINLOCK(est_tree_lock); static void est_timer(unsigned long arg) { @@ -201,7 +202,6 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats * * Returns 0 on success or a negative error code. * - * NOTE: Called under rtnl_mutex */ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est, @@ -232,6 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10; + spin_lock(&est_tree_lock); if (!elist[idx].timer.function) { INIT_LIST_HEAD(&elist[idx].list); setup_timer(&elist[idx].timer, est_timer, idx); @@ -242,6 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, list_add_rcu(&est->list, &elist[idx].list); gen_add_node(est); + spin_unlock(&est_tree_lock); return 0; } @@ -261,13 +263,13 @@ static void __gen_kill_estimator(struct rcu_head *head) * * Removes the rate estimator specified by &bstats and &rate_est. * - * NOTE: Called under rtnl_mutex */ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est) { struct gen_estimator *e; + spin_lock(&est_tree_lock); while ((e = gen_find_node(bstats, rate_est))) { rb_erase(&e->node, &est_root); @@ -278,6 +280,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, list_del_rcu(&e->list); call_rcu(&e->e_rcu, __gen_kill_estimator); } + spin_unlock(&est_tree_lock); } EXPORT_SYMBOL(gen_kill_estimator); @@ -312,8 +315,14 @@ EXPORT_SYMBOL(gen_replace_estimator); bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, const struct gnet_stats_rate_est *rate_est) { + bool res; + ASSERT_RTNL(); - return gen_find_node(bstats, rate_est) != NULL; + spin_lock(&est_tree_lock); + res = gen_find_node(bstats, rate_est) != NULL; + spin_unlock(&est_tree_lock); + + return res; } EXPORT_SYMBOL(gen_estimator_active); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 2ad68da418df..1dacd7ba8dbb 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2170,7 +2170,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) end_time = ktime_now(); pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time)); - pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay); + pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay); } static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 9f07e749d7b1..34432b4e96bb 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -532,6 +532,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->ip_summed = old->ip_summed; skb_copy_queue_mapping(new, old); new->priority = old->priority; + new->deliver_no_wcard = old->deliver_no_wcard; #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) new->ipvs_property = old->ipvs_property; #endif @@ -569,7 +570,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) C(len); C(data_len); C(mac_len); - C(rxhash); n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; n->cloned = 1; n->nohdr = 0; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 9a4a6c96cb0d..041d41df1224 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -873,8 +873,10 @@ int ip_append_data(struct sock *sk, !exthdrlen) csummode = CHECKSUM_PARTIAL; + skb = skb_peek_tail(&sk->sk_write_queue); + inet->cork.length += length; - if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) && + if (((length > mtu) || (skb && skb_is_gso(skb))) && (sk->sk_protocol == IPPROTO_UDP) && (rt->u.dst.dev->features & NETIF_F_UFO)) { err = ip_ufo_append_data(sk, getfrag, from, length, hh_len, @@ -892,7 +894,7 @@ int ip_append_data(struct sock *sk, * adding appropriate IP header. */ - if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) + if (!skb) goto alloc_new_skb; while (length > 0) { @@ -1121,7 +1123,8 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, return -EINVAL; inet->cork.length += size; - if ((sk->sk_protocol == IPPROTO_UDP) && + if ((size + skb->len > mtu) && + (sk->sk_protocol == IPPROTO_UDP) && (rt->u.dst.dev->features & NETIF_F_UFO)) { skb_shinfo(skb)->gso_size = mtu - fragheaderlen; skb_shinfo(skb)->gso_type = SKB_GSO_UDP; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 856123fe32f9..757f25eb9b4b 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -267,8 +267,10 @@ static void __net_exit ipmr_rules_exit(struct net *net) { struct mr_table *mrt, *next; - list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) + list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { + list_del(&mrt->list); kfree(mrt); + } fib_rules_unregister(net->ipv4.mr_rules_ops); } #else diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index ce7992982557..03e62f94ff8e 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -483,7 +483,7 @@ route_done: np->tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT, np->dontfrag); if (err) { - ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); + ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); ip6_flush_pending_frames(sk); goto out_put; } @@ -565,7 +565,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) np->dontfrag); if (err) { - ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); + ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); ip6_flush_pending_frames(sk); goto out_put; } diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 073071f2b75b..66078dad7fe8 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt); static void ipmr_expire_process(unsigned long arg); #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES -#define ip6mr_for_each_table(mrt, met) \ +#define ip6mr_for_each_table(mrt, net) \ list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) @@ -254,8 +254,10 @@ static void __net_exit ip6mr_rules_exit(struct net *net) { struct mr6_table *mrt, *next; - list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) + list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) { + list_del(&mrt->list); ip6mr_free_table(mrt); + } fib_rules_unregister(net->ipv6.mr6_rules_ops); } #else diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 59f1881968c7..ab1622d7d409 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1356,7 +1356,10 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) IPV6_TLV_PADN, 0 }; /* we assume size > sizeof(ra) here */ - skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err); + size += LL_ALLOCATED_SPACE(dev); + /* limit our allocations to order-0 page */ + size = min_t(int, size, SKB_MAX_ORDER(0, 0)); + skb = sock_alloc_send_skb(sk, size, 1, &err); if (!skb) return NULL; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0abdc242ddb7..2efef52fb461 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -586,6 +586,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, src_addr = solicited_addr; if (ifp->flags & IFA_F_OPTIMISTIC) override = 0; + inc_opt |= ifp->idev->cnf.force_tllao; in6_ifa_put(ifp); } else { if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr, @@ -599,7 +600,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, icmp6h.icmp6_solicited = solicited; icmp6h.icmp6_override = override; - inc_opt |= ifp->idev->cnf.force_tllao; __ndisc_send(dev, neigh, daddr, src_addr, &icmp6h, solicited_addr, inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4f2271316650..9c1da0809160 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -349,7 +349,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx, struct survey_info *survey) { int ret = -EOPNOTSUPP; - if (local->ops->conf_tx) + if (local->ops->get_survey) ret = local->ops->get_survey(&local->hw, idx, survey); /* trace_drv_get_survey(local, idx, survey, ret); */ return ret; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0839c4e8fd2e..f803f8b72a93 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1692,14 +1692,52 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: - if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) + switch (mgmt->u.action.category) { + case WLAN_CATEGORY_BACK: { + struct ieee80211_local *local = sdata->local; + int len = skb->len; + struct sta_info *sta; + + rcu_read_lock(); + sta = sta_info_get(sdata, mgmt->sa); + if (!sta) { + rcu_read_unlock(); + break; + } + + local_bh_disable(); + + switch (mgmt->u.action.u.addba_req.action_code) { + case WLAN_ACTION_ADDBA_REQ: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.addba_req))) + break; + ieee80211_process_addba_request(local, sta, mgmt, len); + break; + case WLAN_ACTION_ADDBA_RESP: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.addba_resp))) + break; + ieee80211_process_addba_resp(local, sta, mgmt, len); + break; + case WLAN_ACTION_DELBA: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.delba))) + break; + ieee80211_process_delba(sdata, sta, mgmt, len); + break; + } + local_bh_enable(); + rcu_read_unlock(); break; - - ieee80211_sta_process_chanswitch(sdata, - &mgmt->u.action.u.chan_switch.sw_elem, - (void *)ifmgd->associated->priv, - rx_status->mactime); - break; + } + case WLAN_CATEGORY_SPECTRUM_MGMT: + ieee80211_sta_process_chanswitch(sdata, + &mgmt->u.action.u.chan_switch.sw_elem, + (void *)ifmgd->associated->priv, + rx_status->mactime); + break; + } } mutex_unlock(&ifmgd->mtx); @@ -1722,9 +1760,45 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mutex_unlock(&ifmgd->mtx); if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) - cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); + (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) { + struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk; + + mutex_lock(&local->work_mtx); + list_for_each_entry(wk, &local->work_list, list) { + if (wk->sdata != sdata) + continue; + + if (wk->type != IEEE80211_WORK_ASSOC) + continue; + + if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN)) + continue; + if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN)) + continue; + /* + * Printing the message only here means we can't + * spuriously print it, but it also means that it + * won't be printed when the frame comes in before + * we even tried to associate or in similar cases. + * + * Ultimately, I suspect cfg80211 should print the + * messages instead. + */ + printk(KERN_DEBUG + "%s: deauthenticated from %pM (Reason: %u)\n", + sdata->name, mgmt->bssid, + le16_to_cpu(mgmt->u.deauth.reason_code)); + + list_del_rcu(&wk->list); + free_work(wk); + break; + } + mutex_unlock(&local->work_mtx); + + cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); + } out: kfree_skb(skb); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5e0b65406c44..be9abc2e6348 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1944,6 +1944,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (len < IEEE80211_MIN_ACTION_SIZE + 1) break; + if (sdata->vif.type == NL80211_IFTYPE_STATION) + return ieee80211_sta_rx_mgmt(sdata, rx->skb); + switch (mgmt->u.action.u.addba_req.action_code) { case WLAN_ACTION_ADDBA_REQ: if (len < (IEEE80211_MIN_ACTION_SIZE + diff --git a/net/mac80211/work.c b/net/mac80211/work.c index be3d4a698692..b025dc7bb0fd 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -715,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status; struct ieee80211_mgmt *mgmt; struct ieee80211_work *wk; - enum work_action rma; + enum work_action rma = WORK_ACT_NONE; u16 fc; rx_status = (struct ieee80211_rx_status *) skb->cb; diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index d8f7e8ef67b4..ff04e9edbed6 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -162,6 +162,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp) hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport); ct_write_lock(hash); + spin_lock(&cp->lock); if (!(cp->flags & IP_VS_CONN_F_HASHED)) { list_add(&cp->c_list, &ip_vs_conn_tab[hash]); @@ -174,6 +175,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp) ret = 0; } + spin_unlock(&cp->lock); ct_write_unlock(hash); return ret; @@ -193,6 +195,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp) hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport); ct_write_lock(hash); + spin_lock(&cp->lock); if (cp->flags & IP_VS_CONN_F_HASHED) { list_del(&cp->c_list); @@ -202,6 +205,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp) } else ret = 0; + spin_unlock(&cp->lock); ct_write_unlock(hash); return ret; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 3415b6ce1c0a..807643bdcbac 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -449,6 +449,7 @@ static __init void teql_master_setup(struct net_device *dev) dev->tx_queue_len = 100; dev->flags = IFF_NOARP; dev->hard_header_len = LL_MAX_HEADER; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } static LIST_HEAD(master_dev_list); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 2a9675136c68..7ca65c7005ea 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -210,7 +210,8 @@ struct sock_xprt { * State of TCP reply receive */ __be32 tcp_fraghdr, - tcp_xid; + tcp_xid, + tcp_calldir; u32 tcp_offset, tcp_reclen; @@ -927,7 +928,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, { size_t len, used; u32 offset; - __be32 calldir; + char *p; /* * We want transport->tcp_offset to be 8 at the end of this routine @@ -936,26 +937,33 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, * transport->tcp_offset is 4 (after having already read the xid). */ offset = transport->tcp_offset - sizeof(transport->tcp_xid); - len = sizeof(calldir) - offset; + len = sizeof(transport->tcp_calldir) - offset; dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len); - used = xdr_skb_read_bits(desc, &calldir, len); + p = ((char *) &transport->tcp_calldir) + offset; + used = xdr_skb_read_bits(desc, p, len); transport->tcp_offset += used; if (used != len) return; transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR; - transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; - transport->tcp_flags |= TCP_RCV_COPY_DATA; /* * We don't yet have the XDR buffer, so we will write the calldir * out after we get the buffer from the 'struct rpc_rqst' */ - if (ntohl(calldir) == RPC_REPLY) + switch (ntohl(transport->tcp_calldir)) { + case RPC_REPLY: + transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; + transport->tcp_flags |= TCP_RCV_COPY_DATA; transport->tcp_flags |= TCP_RPC_REPLY; - else + break; + case RPC_CALL: + transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; + transport->tcp_flags |= TCP_RCV_COPY_DATA; transport->tcp_flags &= ~TCP_RPC_REPLY; - dprintk("RPC: reading %s CALL/REPLY flag %08x\n", - (transport->tcp_flags & TCP_RPC_REPLY) ? - "reply for" : "request with", calldir); + break; + default: + dprintk("RPC: invalid request message type\n"); + xprt_force_disconnect(&transport->xprt); + } xs_tcp_check_fraghdr(transport); } @@ -975,12 +983,10 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt, /* * Save the RPC direction in the XDR buffer */ - __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ? - htonl(RPC_REPLY) : 0; - memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied, - &calldir, sizeof(calldir)); - transport->tcp_copied += sizeof(calldir); + &transport->tcp_calldir, + sizeof(transport->tcp_calldir)); + transport->tcp_copied += sizeof(transport->tcp_calldir); transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4bf27d901333..af1c173be4ad 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2300,7 +2300,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, return 0; if (xdst->xfrm_genid != dst->xfrm->genid) return 0; - if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) + if (xdst->num_pols > 0 && + xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) return 0; if (strict && fl && diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin index 102a276f6eea..1adb974e6950 100644 --- a/scripts/Makefile.modbuiltin +++ b/scripts/Makefile.modbuiltin @@ -14,6 +14,11 @@ __modbuiltin: include scripts/Kbuild.include +ifneq ($(KBUILD_SRC),) +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) +endif + # The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3318692e4e76..f8779006986d 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1342,7 +1342,7 @@ static unsigned int *reloc_location(struct elf_info *elf, int section = sechdr->sh_info; return (void *)elf->hdr + sechdrs[section].sh_offset + - (r->r_offset - sechdrs[section].sh_addr); + r->r_offset - sechdrs[section].sh_addr; } static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) diff --git a/scripts/package/Makefile b/scripts/package/Makefile index 62fcc3a7f4d3..3a681ef25306 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -44,7 +44,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec FORCE fi $(MAKE) clean $(PREV) ln -sf $(srctree) $(KERNELPATH) - $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion + $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --scm-only > $(objtree)/.scmversion $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. $(PREV) rm $(KERNELPATH) rm -f $(objtree)/.scmversion diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 46989b88d734..d6a866ed1835 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -10,73 +10,158 @@ # usage() { - echo "Usage: $0 [srctree]" >&2 + echo "Usage: $0 [--scm-only] [srctree]" >&2 exit 1 } -cd "${1:-.}" || usage +scm_only=false +srctree=. +if test "$1" = "--scm-only"; then + scm_only=true + shift +fi +if test $# -gt 0; then + srctree=$1 + shift +fi +if test $# -gt 0 -o ! -d "$srctree"; then + usage +fi -# Check for git and a git repo. -if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then +scm_version() +{ + local short=false - # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it, - # because this version is defined in the top level Makefile. - if [ -z "`git describe --exact-match 2>/dev/null`" ]; then + cd "$srctree" + if test -e .scmversion; then + cat "$_" + return + fi + if test "$1" = "--short"; then + short=true + fi - # If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"), - # we pretty print it. - if atag="`git describe 2>/dev/null`"; then - echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' + # Check for git and a git repo. + if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then + + # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore + # it, because this version is defined in the top level Makefile. + if [ -z "`git describe --exact-match 2>/dev/null`" ]; then + + # If only the short version is requested, don't bother + # running further git commands + if $short; then + echo "+" + return + fi + # If we are past a tagged commit (like + # "v2.6.30-rc5-302-g72357d5"), we pretty print it. + if atag="`git describe 2>/dev/null`"; then + echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' + + # If we don't have a tag at all we print -g{commitish}. + else + printf '%s%s' -g $head + fi + fi - # If we don't have a tag at all we print -g{commitish}. - else - printf '%s%s' -g $head + # Is this git on svn? + if git config --get svn-remote.svn.url >/dev/null; then + printf -- '-svn%s' "`git svn find-rev $head`" fi - fi - # Is this git on svn? - if git config --get svn-remote.svn.url >/dev/null; then - printf -- '-svn%s' "`git svn find-rev $head`" - fi + # Update index only on r/w media + [ -w . ] && git update-index --refresh --unmerged > /dev/null - # Update index only on r/w media - [ -w . ] && git update-index --refresh --unmerged > /dev/null + # Check for uncommitted changes + if git diff-index --name-only HEAD | grep -v "^scripts/package" \ + | read dummy; then + printf '%s' -dirty + fi - # Check for uncommitted changes - if git diff-index --name-only HEAD | grep -v "^scripts/package" \ - | read dummy; then - printf '%s' -dirty + # All done with git + return fi - # All done with git - exit -fi + # Check for mercurial and a mercurial repo. + if hgid=`hg id 2>/dev/null`; then + tag=`printf '%s' "$hgid" | cut -d' ' -f2` + + # Do we have an untagged version? + if [ -z "$tag" -o "$tag" = tip ]; then + id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` + printf '%s%s' -hg "$id" + fi -# Check for mercurial and a mercurial repo. -if hgid=`hg id 2>/dev/null`; then - tag=`printf '%s' "$hgid" | cut -d' ' -f2` + # Are there uncommitted changes? + # These are represented by + after the changeset id. + case "$hgid" in + *+|*+\ *) printf '%s' -dirty ;; + esac - # Do we have an untagged version? - if [ -z "$tag" -o "$tag" = tip ]; then - id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` - printf '%s%s' -hg "$id" + # All done with mercurial + return fi - # Are there uncommitted changes? - # These are represented by + after the changeset id. - case "$hgid" in - *+|*+\ *) printf '%s' -dirty ;; - esac + # Check for svn and a svn repo. + if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then + rev=`echo $rev | awk '{print $NF}'` + printf -- '-svn%s' "$rev" - # All done with mercurial + # All done with svn + return + fi +} + +collect_files() +{ + local file res + + for file; do + case "$file" in + *\~*) + continue + ;; + esac + if test -e "$file"; then + res="$res$(cat "$file")" + fi + done + echo "$res" +} + +if $scm_only; then + scm_version exit fi -# Check for svn and a svn repo. -if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then - rev=`echo $rev | awk '{print $NF}'` - printf -- '-svn%s' "$rev" +if test -e include/config/auto.conf; then + source "$_" +else + echo "Error: kernelrelease not valid - run 'make prepare' to update it" + exit 1 +fi - # All done with svn - exit +# localversion* files in the build and source directory +res="$(collect_files localversion*)" +if test ! "$srctree" -ef .; then + res="$res$(collect_files "$srctree"/localversion*)" +fi + +# CONFIG_LOCALVERSION and LOCALVERSION (if set) +res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" + +# scm version string if not at a tagged commit +if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then + # full scm version string + res="$res$(scm_version)" +else + # apped a plus sign if the repository is not in a clean tagged + # state and LOCALVERSION= is not specified + if test "${LOCALVERSION+set}" != "set"; then + scm=$(scm_version --short) + res="$res${scm:++}" + fi fi + +echo "$res" diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 13074b454743..6261745e4459 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -33,7 +33,7 @@ static int key_get_type_from_user(char *type, ret = strncpy_from_user(type, _type, len); if (ret < 0) - return -EFAULT; + return ret; if (ret == 0 || ret >= len) return -EINVAL; @@ -1080,7 +1080,7 @@ set: return old_setting; error: abort_creds(new); - return -EINVAL; + return ret; } /* end keyctl_set_reqkey_keyring() */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d792cddbf4c2..ff614dd824c1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1268,8 +1268,10 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec) struct alc_spec *spec = codec->spec; ass = codec->subsystem_id & 0xffff; - if (ass != codec->bus->pci->subsystem_device && (ass & 1)) + if (ass != codec->bus->pci->subsystem_device && (ass & 1)) { + spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ goto do_sku; + } nid = 0x1d; if (codec->vendor_id == 0x10ec0260) @@ -2547,7 +2549,7 @@ static struct snd_kcontrol_new alc_beep_mixer[] = { static int alc_build_controls(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - struct snd_kcontrol *kctl; + struct snd_kcontrol *kctl = NULL; struct snd_kcontrol_new *knew; int i, j, err; unsigned int u; @@ -2619,16 +2621,18 @@ static int alc_build_controls(struct hda_codec *codec) } /* assign Capture Source enums to NID */ - kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); - if (!kctl) - kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); - for (i = 0; kctl && i < kctl->count; i++) { - hda_nid_t *nids = spec->capsrc_nids; - if (!nids) - nids = spec->adc_nids; - err = snd_hda_add_nid(codec, kctl, i, nids[i]); - if (err < 0) - return err; + if (spec->capsrc_nids || spec->adc_nids) { + kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); + if (!kctl) + kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); + for (i = 0; kctl && i < kctl->count; i++) { + hda_nid_t *nids = spec->capsrc_nids; + if (!nids) + nids = spec->adc_nids; + err = snd_hda_add_nid(codec, kctl, i, nids[i]); + if (err < 0) + return err; + } } if (spec->cap_mixer) { const char *kname = kctl ? kctl->id.name : NULL; @@ -6948,7 +6952,7 @@ static struct hda_input_mux mb5_capture_source = { .num_items = 3, .items = { { "Mic", 0x1 }, - { "Line", 0x2 }, + { "Line", 0x7 }, { "CD", 0x4 }, }, }; @@ -7469,8 +7473,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), + HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT), @@ -7853,10 +7857,9 @@ static struct hda_verb alc885_mb5_init_verbs[] = { {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)}, { } }; @@ -9477,11 +9480,15 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24), SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31), + SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M), + SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3), + SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21), SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24), SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91), SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), + SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5), /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2, * so apparently no perfect solution yet */ diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 79f0f4ad242c..d3955096d872 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -612,7 +612,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) NUMDMA_MASK); mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); } if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -623,7 +622,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) NUMDMA_MASK); mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); } } diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 22208b373fb9..e1ec6d91ea38 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -73,7 +73,7 @@ struct psc_dma { }; /* Utility for retrieving psc_dma_stream structure from a substream */ -inline struct psc_dma_stream * +static inline struct psc_dma_stream * to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) { if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1941a357e8c4..d256f5f313b5 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -328,38 +328,6 @@ static struct snd_soc_device spitz_snd_devdata = { .codec_dev = &soc_codec_dev_wm8750, }; -/* - * FIXME: This is a temporary bodge to avoid cross-tree merge issues. - * New drivers should register the wm8750 I2C device in the machine - * setup code (under arch/arm for ARM systems). - */ -static int wm8750_i2c_register(void) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = 0x1b; - strlcpy(info.type, "wm8750", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(0); - if (!adapter) { - printk(KERN_ERR "can't get i2c adapter 0\n"); - return -ENODEV; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - printk(KERN_ERR "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - return -ENODEV; - } - - return 0; -} - static struct platform_device *spitz_snd_device; static int __init spitz_init(void) @@ -369,10 +337,6 @@ static int __init spitz_init(void) if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) return -ENODEV; - ret = wm8750_i2c_setup(); - if (ret != 0) - return ret; - spitz_snd_device = platform_device_alloc("soc-audio", -1); if (!spitz_snd_device) return -ENOMEM; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dc3435e18bde..711745f56bba 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -193,7 +193,7 @@ static void sig_handler(int sig) static void sig_atexit(void) { - if (child_pid != -1) + if (child_pid > 0) kill(child_pid, SIGTERM); if (signr == -1) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 1f08f008d289..2fbf6a463c81 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -538,8 +538,10 @@ int event__process_task(event_t *self, struct perf_session *session) dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, self->fork.ppid, self->fork.ptid); - if (self->header.type == PERF_RECORD_EXIT) + if (self->header.type == PERF_RECORD_EXIT) { + perf_session__remove_thread(session, thread); return 0; + } if (thread == NULL || parent == NULL || thread__fork(thread, parent) < 0) { diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index cf182ca132fe..7537ca15900b 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -43,6 +43,9 @@ struct ui_progress *ui_progress__new(const char *title, u64 total) if (self != NULL) { int cols; + + if (use_browser <= 0) + return self; newtGetScreenSize(&cols, NULL); cols -= 4; newtCenteredWindow(cols, 1, title); @@ -67,14 +70,22 @@ out_free_self: void ui_progress__update(struct ui_progress *self, u64 curr) { + /* + * FIXME: We should have a per UI backend way of showing progress, + * stdio will just show a percentage as NN%, etc. + */ + if (use_browser <= 0) + return; newtScaleSet(self->scale, curr); newtRefresh(); } void ui_progress__delete(struct ui_progress *self) { - newtFormDestroy(self->form); - newtPopWindow(); + if (use_browser > 0) { + newtFormDestroy(self->form); + newtPopWindow(); + } free(self); } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8f83a1835766..c422cd676313 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -90,6 +90,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc memcpy(self->filename, filename, len); self->threads = RB_ROOT; + INIT_LIST_HEAD(&self->dead_threads); self->hists_tree = RB_ROOT; self->last_match = NULL; self->mmap_window = 32; @@ -131,6 +132,16 @@ void perf_session__delete(struct perf_session *self) free(self); } +void perf_session__remove_thread(struct perf_session *self, struct thread *th) +{ + rb_erase(&th->rb_node, &self->threads); + /* + * We may have references to this thread, for instance in some hist_entry + * instances, so just move them to a separate list. + */ + list_add_tail(&th->node, &self->dead_threads); +} + static bool symbol__match_parent_regex(struct symbol *sym) { if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 55c6881b218d..9fa0fc2a863f 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -26,6 +26,7 @@ struct perf_session { unsigned long size; unsigned long mmap_window; struct rb_root threads; + struct list_head dead_threads; struct thread *last_match; struct machine host_machine; struct rb_root machines; @@ -99,6 +100,7 @@ int perf_session__create_kernel_maps(struct perf_session *self); int do_read(int fd, void *buf, size_t size); void perf_session__update_sample_type(struct perf_session *self); +void perf_session__remove_thread(struct perf_session *self, struct thread *th); static inline struct machine *perf_session__find_host_machine(struct perf_session *self) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 7fd6b151feb5..b63e5713849f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1745,7 +1745,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, if (symbol_conf.vmlinux_name != NULL) { err = dso__load_vmlinux(self, map, symbol_conf.vmlinux_name, filter); - goto out_try_fixup; + if (err > 0) { + dso__set_long_name(self, + strdup(symbol_conf.vmlinux_name)); + goto out_fixup; + } + return err; } if (vmlinux_path != NULL) { @@ -1806,7 +1811,6 @@ do_kallsyms: pr_debug("Using %s for symbols\n", kallsyms_filename); free(kallsyms_allocated_filename); -out_try_fixup: if (err > 0) { out_fixup: if (kallsyms_filename != NULL) diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 1f7ecd47f499..9a448b47400c 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -7,6 +7,15 @@ #include "util.h" #include "debug.h" +/* Skip "." and ".." directories */ +static int filter(const struct dirent *dir) +{ + if (dir->d_name[0] == '.') + return 0; + else + return 1; +} + int find_all_tid(int pid, pid_t ** all_tid) { char name[256]; @@ -16,7 +25,7 @@ int find_all_tid(int pid, pid_t ** all_tid) int i; sprintf(name, "/proc/%d/task", pid); - items = scandir(name, &namelist, NULL, NULL); + items = scandir(name, &namelist, filter, NULL); if (items <= 0) return -ENOENT; *all_tid = malloc(sizeof(pid_t) * items); diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 1dfd9ff8bdcd..ee6bbcf277ca 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -6,7 +6,10 @@ #include "symbol.h" struct thread { - struct rb_node rb_node; + union { + struct rb_node rb_node; + struct list_head node; + }; struct map_groups mg; pid_t pid; char shortname[3]; diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 7c79c1d76d0c..3500dee9cf2b 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -192,12 +192,13 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) { - u32 old_irr = ioapic->irr; + u32 old_irr; u32 mask = 1 << irq; union kvm_ioapic_redirect_entry entry; int ret = 1; spin_lock(&ioapic->lock); + old_irr = ioapic->irr; if (irq >= 0 && irq < IOAPIC_NUM_PINS) { entry = ioapic->redirtbl[irq]; level ^= entry.fields.polarity; diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index d2f06be63354..96048ee9e39e 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c @@ -271,7 +271,7 @@ static void kvm_iommu_put_pages(struct kvm *kvm, pfn = phys >> PAGE_SHIFT; /* Unmap address from IO address space */ - order = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE); + order = iommu_unmap(domain, gfn_to_gpa(gfn), 0); unmap_pages = 1ULL << order; /* Unpin all pages we just unmapped to not leak any memory */ |