diff options
author | Steve French <sfrench@us.ibm.com> | 2010-06-16 13:19:36 (GMT) |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-06-16 13:19:36 (GMT) |
commit | 0933a95dfdb1ae5c93e1ede5899f35acc2bb244d (patch) | |
tree | 55ac47b819a2a2084f82f9d823d9152ac2a7f2b3 | |
parent | 12420ac341533f3715b3deb788637568f22b78ff (diff) | |
parent | 7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff) | |
download | linux-fsl-qoriq-0933a95dfdb1ae5c93e1ede5899f35acc2bb244d.tar.xz |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
167 files changed, 1660 insertions, 877 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index 428676c..25be325 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/MAINTAINERS b/MAINTAINERS index 67accd7..6d119c9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2978,7 +2978,6 @@ 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 @@ -2988,7 +2987,6 @@ 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 @@ -3019,8 +3017,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 +3028,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 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 35 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc3 NAME = Sheep on Meth # *DOCUMENTATION* @@ -1095,7 +1095,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 +1117,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/arm/common/sa1111.c b/arch/arm/common/sa1111.c index a52a27c..6f80665 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/mach-msm/dma.c b/arch/arm/mach-msm/dma.c index d029d1f..02cae5e 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-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c index 2c471fc..f035f41 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 5563985..78da2e7 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 91c3c90..ac58e3b 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-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c index 033b567..ce1104d 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 4d2413e..c1048a3 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-ux500/Makefile b/arch/arm/mach-ux500/Makefile index c7bc419..4556aea 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 6544855..fe84b90 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 e4f99b6..a058025 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 d81ad02..e0fd747 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/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c index 5eb4fd9..ac163de 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 7c2eb55..cb589cb 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 172e6a5..30c7d04 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 747ad41..f9cde07 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/fault.c b/arch/arm/mm/fault.c index 92f5801..cbfb2ed 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 77b030f..086816b 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 1ba6cf5..f6a9994 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 0ff3798..08aaa4a 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/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 66dc2d0..d66cead 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 84d103c3..a4dba6b 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 d5f4e91..21b7013 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/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index de493f8..464ff32 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 9dcd90b..79c7465 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 9cb782b..23be25f 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 d6119b8..45b40ac 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/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 6646005..5b38f6a 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/kvm/e500.c b/arch/powerpc/kvm/e500.c index bc2b400..e8a00b0 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/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index 2c9e522..7fd90d0 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/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 55c80ffd..92f1cb7 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 bcd6884..253f158 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 639380a..22cfd63 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 8093e6f..ae37058 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 eff3c59..702276f 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 6409fd5..3cc95dd 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/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index b49d8ca..8c7ae43 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/suspend_32.h b/arch/x86/include/asm/suspend_32.h index 48dcfa6..fd921c3 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 06284f4..8d942af 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/kvm/mmu.c b/arch/x86/kvm/mmu.c index 81563e7..a6f695d 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 96dc232..ce438e0 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/pci/i386.c b/arch/x86/pci/i386.c index 97da2ba..6fdb3ec 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 0a979f3..1290ba5 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/drivers/ata/libahci.c b/drivers/ata/libahci.c index 1984a6e..261f86d 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -541,29 +541,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 +1874,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 e925051..be7726d 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 0ecd0f6..4730c42 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/char/vt.c b/drivers/char/vt.c index 1296c42..7cdb6ee 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/firewire/core-card.c b/drivers/firewire/core-card.c index 9dcb304..371713f 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/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 994d23b..57cea01 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 b3779d2..08c4c92 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -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; } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index b2ebf02..59a2bf8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1402,19 +1402,19 @@ 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; 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 +1426,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 9ed8ecd..2765831 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 */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 88a1ab7..cc8131f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3653,6 +3653,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); @@ -3973,6 +3978,13 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, DRM_ERROR("failed to pin cursor bo\n"); goto fail_locked; } + + ret = i915_gem_object_set_to_gtt_domain(bo, 0); + if (ret) { + DRM_ERROR("failed to move cursor bo into the GTT\n"); + goto fail_unpin; + } + addr = obj_priv->gtt_offset; } else { ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); @@ -4016,6 +4028,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, intel_crtc->cursor_bo = bo; return 0; +fail_unpin: + i915_gem_object_unpin(bo); fail_locked: mutex_unlock(&dev->struct_mutex); fail: @@ -5461,7 +5475,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); @@ -5491,13 +5504,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_fb.c b/drivers/gpu/drm/i915/intel_fb.c index f8c76e6..c3c5052 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/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 9ba2dea..fc924b6 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 fd4a2df..c9a4a0d 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 147e59c..b02a231 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 a95e694..32611bd 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 c61782b..bb47ad7 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/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0440c09..4b6623d 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) @@ -2153,7 +2159,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/r100.c b/drivers/gpu/drm/radeon/r100.c index cc004b0..cf89aa2 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; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 4415a5e..e6c8914 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 e14f597..0e91871 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -291,6 +291,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 +306,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 +327,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 +342,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 +363,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 +378,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 +405,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 +420,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 +441,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 +456,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 +480,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 +519,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 +557,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) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5f96fe8..8e1d44c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -648,15 +648,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 +748,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_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 4305cd5..99bd8a9 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_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 102c744..1bee2f9 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2026,6 +2026,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 +2340,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 +2457,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 diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1006549..8154cdf 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 902d173..e166fe4 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_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index e192acf..dc1634b 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 0406835..6a70c0d 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 5a13b3e..5b07b88 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1168,6 +1168,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_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 0228126..63f679a 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 { @@ -377,15 +420,19 @@ void radeon_pm_suspend(struct radeon_device *rdev) { 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; mutex_unlock(&rdev->pm.mutex); } 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; + mutex_unlock(&rdev->pm.mutex); radeon_pm_compute_clocks(rdev); } @@ -394,32 +441,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) @@ -705,6 +744,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/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 33952da..cec536c 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); + } + } } /* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index bdd67cf..8e39685 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 f8fbbc6..8612378 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/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index e00a1cc..c190664 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/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e171e77..f06d06e 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 000d65e..91c8013 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 98a04b3..ffc3720 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 78a4232..bcfc851 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 9c14975..284a5f4 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 4ba7293..97d8068 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/gianfar.c b/drivers/net/gianfar.c index 1830f31..46c69cd 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -747,8 +747,7 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN | FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | - FSL_GIANFAR_DEV_HAS_EXTENDED_HASH | - FSL_GIANFAR_DEV_HAS_TIMER; + FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; ctype = of_get_property(np, "phy-connection-type", NULL); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 7b6fe89..64e6a84 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; diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 8ee929b..dbd0034 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); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 217e709..96b6cfb 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/usb/asix.c b/drivers/net/usb/asix.c index 1f802e9..9516f38 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/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 3f283bf..1149135 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/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2978359..648972d 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 1b81c47..492cbb1 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_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index d707328..ff9b5c8 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) int events = 0; u16 ev; - /* Detect early interrupt before driver is fully configued */ - if (!dev->base_addr) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", - dev->name); - } - return IRQ_HANDLED; - } - iface = netdev_priv(dev); local = iface->local; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 068f7f8..c44a303 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 1004cfc..0f292a2 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 c402bfc..a732f10 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); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index aef4f71..7726e67 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); @@ -3264,141 +3421,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, /***************************************************************************** * - * 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 +3572,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 +3757,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 +3790,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 5a7eca8..426e955 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 7e5a5ba..31775bd 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/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3e5bffb..6c353ca 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); diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index d5b197b..7307325 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 d234285..c561332 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 b3e5580..4952c3b 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/pci-sysfs.c b/drivers/pci/pci-sysfs.c index afd2fbf..c9957f6 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/quirks.c b/drivers/pci/quirks.c index b7512cf..477345d 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 17bed18..92379e2 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 e0189cf..659eaa0 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 7ef7ade..9fc3398 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 424e576..f1d4137 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/s390/cio/itcw.c b/drivers/s390/cio/itcw.c index 17da9ab..a0ae295 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/vhost/net.c b/drivers/vhost/net.c index 0f41c91..df5b6b9 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/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index 89dd7b0..b68d928 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/block_dev.c b/fs/block_dev.c index 7346c96..99d6af8 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 8d432cd..2222d16 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 f3b287c..34f7c37 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 b9080d7..32d0940 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 787b50a..e354c33 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 fa6ccc1..1bff92a 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 4cdb98c..4dbaf89 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 05d41e5..b37d723 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 b91ccd9..2d958be 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 d34b2df..f2393b3 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 ae3e3a3..619b616 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 226f5a5..ab47f46 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 b49f128..1766947 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 d9936c4..b292fa4 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 21c62e9..07a5399 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 4e0bee2..fa87f51 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/ext4/inode.c b/fs/ext4/inode.c index 19df61c..42272d6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4942,20 +4942,26 @@ void ext4_set_inode_flags(struct inode *inode) /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ void ext4_get_inode_flags(struct ext4_inode_info *ei) { - unsigned int flags = ei->vfs_inode.i_flags; - - ei->i_flags &= ~(EXT4_SYNC_FL|EXT4_APPEND_FL| - EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|EXT4_DIRSYNC_FL); - if (flags & S_SYNC) - ei->i_flags |= EXT4_SYNC_FL; - if (flags & S_APPEND) - ei->i_flags |= EXT4_APPEND_FL; - if (flags & S_IMMUTABLE) - ei->i_flags |= EXT4_IMMUTABLE_FL; - if (flags & S_NOATIME) - ei->i_flags |= EXT4_NOATIME_FL; - if (flags & S_DIRSYNC) - ei->i_flags |= EXT4_DIRSYNC_FL; + unsigned int vfs_fl; + unsigned long old_fl, new_fl; + + do { + vfs_fl = ei->vfs_inode.i_flags; + old_fl = ei->i_flags; + new_fl = old_fl & ~(EXT4_SYNC_FL|EXT4_APPEND_FL| + EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL| + EXT4_DIRSYNC_FL); + if (vfs_fl & S_SYNC) + new_fl |= EXT4_SYNC_FL; + if (vfs_fl & S_APPEND) + new_fl |= EXT4_APPEND_FL; + if (vfs_fl & S_IMMUTABLE) + new_fl |= EXT4_IMMUTABLE_FL; + if (vfs_fl & S_NOATIME) + new_fl |= EXT4_NOATIME_FL; + if (vfs_fl & S_DIRSYNC) + new_fl |= EXT4_DIRSYNC_FL; + } while (cmpxchg(&ei->i_flags, old_fl, new_fl) != old_fl); } static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, @@ -5191,7 +5197,7 @@ static int ext4_inode_blocks_set(handle_t *handle, */ raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); raw_inode->i_blocks_high = 0; - ei->i_flags &= ~EXT4_HUGE_FILE_FL; + ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); return 0; } if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) @@ -5204,9 +5210,9 @@ static int ext4_inode_blocks_set(handle_t *handle, */ raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); - ei->i_flags &= ~EXT4_HUGE_FILE_FL; + ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); } else { - ei->i_flags |= EXT4_HUGE_FILE_FL; + ext4_set_inode_flag(inode, EXT4_INODE_HUGE_FILE); /* i_block is stored in file system block size */ i_blocks = i_blocks >> (inode->i_blkbits - 9); raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 3a6c92a..52abfa1 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -960,6 +960,9 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } + if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode)) + return -EPERM; + /* Ext4 move extent does not support swapfile */ if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { ext4_debug("ext4 move extent: The argument files should " diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index a33aab6..54a92fd 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 7aa4417..166062a 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 8bc2c80..459d39d 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/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 12f7109..4a27347 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 ebbf3b6..3c11112 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; @@ -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/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index a0fa3bf..34640d6 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/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 3ff9fc0..5347063 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/miscdevice.h b/include/linux/miscdevice.h index b631c46..f6c9b7d 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 f149dd1..4eb4679 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2321,6 +2321,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/skbuff.h b/include/linux/skbuff.h index bf243fc..f89e7fd 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/writeback.h b/include/linux/writeback.h index f641346..d63ef8f 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/trace/events/ext4.h b/include/trace/events/ext4.h index f5b1ba9..f3865c7 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 814566c..17df434 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/kernel/perf_event.c b/kernel/perf_event.c index 31d6afe..ff86c55 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/mm/page-writeback.c b/mm/page-writeback.c index 5fa63bd..bbd396a 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -835,7 +835,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 +851,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 +949,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 +983,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/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index bd537fc..50f58f5 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/caif/cfrfml.c b/net/caif/cfrfml.c index cd2830f..fd27b17 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 0fd827f..e04f7d9 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 d03470f..2b3bf53 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 cf8e703..785e527 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 2ad68da..1dacd7b 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/ipv4/ipmr.c b/net/ipv4/ipmr.c index 856123f..757f25eb 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 ce79929..03e62f9 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 073071f..66078da 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 59f1881..ab1622d 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/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4f22713..9c1da08 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 0839c4e..f803f8b 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 5e0b654..be9abc2 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/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin index 102a276..1adb974 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/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 428121a..10c3a87 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -657,7 +657,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) if (sr & AC97C_SR_CAEVT) { struct snd_pcm_runtime *runtime; int offset, next_period, block_size; - dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", + dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", casr & AC97C_CSR_OVRUN ? " OVRUN" : "", casr & AC97C_CSR_RXRDY ? " RXRDY" : "", casr & AC97C_CSR_UNRUN ? " UNRUN" : "", diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d792cdd..fc767b6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9477,6 +9477,9 @@ 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), diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1941a35..d256f5f 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/sound/spi/at73c213.c b/sound/spi/at73c213.c index 4c7b051..1bc56b2 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -69,7 +69,6 @@ struct snd_at73c213 { int irq; int period; unsigned long bitrate; - struct clk *bitclk; struct ssc_device *ssc; struct spi_device *spi; u8 spi_wbuffer[2]; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 7fd6b15..b63e571 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/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 7c79c1d..3500dee 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 d2f06be..96048ee 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 */ |