diff options
300 files changed, 5405 insertions, 1922 deletions
diff --git a/Documentation/devicetree/bindings/mips/cpu_irq.txt b/Documentation/devicetree/bindings/mips/cpu_irq.txt new file mode 100644 index 00000000000..13aa4b62c62 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cpu_irq.txt @@ -0,0 +1,47 @@ +MIPS CPU interrupt controller + +On MIPS the mips_cpu_intc_init() helper can be used to initialize the 8 CPU +IRQs from a devicetree file and create a irq_domain for IRQ controller. + +With the irq_domain in place we can describe how the 8 IRQs are wired to the +platforms internal interrupt controller cascade. + +Below is an example of a platform describing the cascade inside the devicetree +and the code used to load it inside arch_init_irq(). + +Required properties: +- compatible : Should be "mti,cpu-interrupt-controller" + +Example devicetree: +	cpu-irq: cpu-irq@0 { +		#address-cells = <0>; + +		interrupt-controller; +		#interrupt-cells = <1>; + +		compatible = "mti,cpu-interrupt-controller"; +	}; + +	intc: intc@200 { +		compatible = "ralink,rt2880-intc"; +		reg = <0x200 0x100>; + +		interrupt-controller; +		#interrupt-cells = <1>; + +		interrupt-parent = <&cpu-irq>; +		interrupts = <2>; +	}; + + +Example platform irq.c: +static struct of_device_id __initdata of_irq_ids[] = { +	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init }, +	{ .compatible = "ralink,rt2880-intc", .data = intc_of_init }, +	{}, +}; + +void __init arch_init_irq(void) +{ +	of_irq_init(of_irq_ids); +} diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt new file mode 100644 index 00000000000..5b78591aaa4 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt @@ -0,0 +1,16 @@ +Lantiq SoC ASC serial controller + +Required properties: +- compatible : Should be "lantiq,asc" +- reg : Address and length of the register set for the device +- interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier +  depends on the interrupt-parent interrupt controller. + +Example: + +asc1: serial@E100C00 { +	compatible = "lantiq,asc"; +	reg = <0xE100C00 0x400>; +	interrupt-parent = <&icu0>; +	interrupts = <112 113 114>; +}; diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 363e348bff9..6c723811c0a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2438,7 +2438,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.  			real-time workloads.  It can also improve energy  			efficiency for asymmetric multiprocessors. -	rcu_nocbs_poll	[KNL,BOOT] +	rcu_nocb_poll	[KNL,BOOT]  			Rather than requiring that offloaded CPUs  			(specified by rcu_nocbs= above) explicitly  			awaken the corresponding "rcuoN" kthreads, diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 3edb4c2887a..e540fd67f76 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -57,7 +57,7 @@ Protocol 2.10:	(Kernel 2.6.31) Added a protocol for relaxed alignment  Protocol 2.11:	(Kernel 3.6) Added a field for offset of EFI handover  		protocol entry point. -Protocol 2.12:	(Kernel 3.9) Added the xloadflags field and extension fields +Protocol 2.12:	(Kernel 3.8) Added the xloadflags field and extension fields  	 	to struct boot_params for for loading bzImage and ramdisk  		above 4G in 64bit. diff --git a/MAINTAINERS b/MAINTAINERS index 212c255b934..35a56bcd5e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1489,7 +1489,7 @@ AVR32 ARCHITECTURE  M:	Haavard Skinnemoen <hskinnemoen@gmail.com>  M:	Hans-Christian Egtvedt <egtvedt@samfundet.no>  W:	http://www.atmel.com/products/AVR32/ -W:	http://avr32linux.org/ +W:	http://mirror.egtvedt.no/avr32linux.org/  W:	http://avrfreaks.net/  S:	Maintained  F:	arch/avr32/ @@ -1,7 +1,7 @@  VERSION = 3  PATCHLEVEL = 8  SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7  NAME = Unicycling Gorilla  # *DOCUMENTATION* diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 36ae03a3f5d..87dfa9026c5 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -351,6 +351,25 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)  	irq_set_chained_handler(irq, gic_handle_cascade_irq);  } +static u8 gic_get_cpumask(struct gic_chip_data *gic) +{ +	void __iomem *base = gic_data_dist_base(gic); +	u32 mask, i; + +	for (i = mask = 0; i < 32; i += 4) { +		mask = readl_relaxed(base + GIC_DIST_TARGET + i); +		mask |= mask >> 16; +		mask |= mask >> 8; +		if (mask) +			break; +	} + +	if (!mask) +		pr_crit("GIC CPU mask not found - kernel will fail to boot.\n"); + +	return mask; +} +  static void __init gic_dist_init(struct gic_chip_data *gic)  {  	unsigned int i; @@ -369,7 +388,9 @@ static void __init gic_dist_init(struct gic_chip_data *gic)  	/*  	 * Set all global interrupts to this CPU only.  	 */ -	cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0); +	cpumask = gic_get_cpumask(gic); +	cpumask |= cpumask << 8; +	cpumask |= cpumask << 16;  	for (i = 32; i < gic_irqs; i += 4)  		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); @@ -400,7 +421,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)  	 * Get what the GIC says our CPU mask is.  	 */  	BUG_ON(cpu >= NR_GIC_CPU_IF); -	cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0); +	cpu_mask = gic_get_cpumask(gic);  	gic_cpu_map[cpu] = cpu_mask;  	/* diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 73cf03aa981..1c4df27f933 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -37,7 +37,7 @@   */  #define PAGE_OFFSET		UL(CONFIG_PAGE_OFFSET)  #define TASK_SIZE		(UL(CONFIG_PAGE_OFFSET) - UL(0x01000000)) -#define TASK_UNMAPPED_BASE	(UL(CONFIG_PAGE_OFFSET) / 3) +#define TASK_UNMAPPED_BASE	ALIGN(TASK_SIZE / 3, SZ_16M)  /*   * The maximum size of a 26-bit user space task. diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index e103c290bc9..85afb031b67 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -414,7 +414,7 @@ config MACH_EXYNOS4_DT  	select CPU_EXYNOS4210  	select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD  	select PINCTRL -	select PINCTRL_EXYNOS4 +	select PINCTRL_EXYNOS  	select USE_OF  	help  	  Machine support for Samsung Exynos4 machine with device tree enabled. diff --git a/arch/arm/mach-realview/include/mach/irqs-eb.h b/arch/arm/mach-realview/include/mach/irqs-eb.h index d6b5073692d..44754230fdc 100644 --- a/arch/arm/mach-realview/include/mach/irqs-eb.h +++ b/arch/arm/mach-realview/include/mach/irqs-eb.h @@ -115,7 +115,7 @@  /*   * Only define NR_IRQS if less than NR_IRQS_EB   */ -#define NR_IRQS_EB		(IRQ_EB_GIC_START + 96) +#define NR_IRQS_EB		(IRQ_EB_GIC_START + 128)  #if defined(CONFIG_MACH_REALVIEW_EB) \  	&& (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB)) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 076c26d4386..dda3904dc64 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -640,7 +640,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,  	if (is_coherent || nommu())  		addr = __alloc_simple_buffer(dev, size, gfp, &page); -	else if (gfp & GFP_ATOMIC) +	else if (!(gfp & __GFP_WAIT))  		addr = __alloc_from_pool(size, &page);  	else if (!IS_ENABLED(CONFIG_CMA))  		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); diff --git a/arch/avr32/include/asm/dma-mapping.h b/arch/avr32/include/asm/dma-mapping.h index aaf5199d8fc..b3d18f9f3e8 100644 --- a/arch/avr32/include/asm/dma-mapping.h +++ b/arch/avr32/include/asm/dma-mapping.h @@ -336,4 +336,14 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,  #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)  #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) +/* drivers/base/dma-mapping.c */ +extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, +			   void *cpu_addr, dma_addr_t dma_addr, size_t size); +extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size); + +#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) +#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) +  #endif /* __ASM_AVR32_DMA_MAPPING_H */ diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h index bbf461076a0..054d9ec57d9 100644 --- a/arch/blackfin/include/asm/dma-mapping.h +++ b/arch/blackfin/include/asm/dma-mapping.h @@ -154,4 +154,14 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,  	_dma_sync((dma_addr_t)vaddr, size, dir);  } +/* drivers/base/dma-mapping.c */ +extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, +			   void *cpu_addr, dma_addr_t dma_addr, size_t size); +extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size); + +#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) +#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) +  #endif				/* _BLACKFIN_DMA_MAPPING_H */ diff --git a/arch/c6x/include/asm/dma-mapping.h b/arch/c6x/include/asm/dma-mapping.h index 3c694065030..88bd0d899bd 100644 --- a/arch/c6x/include/asm/dma-mapping.h +++ b/arch/c6x/include/asm/dma-mapping.h @@ -89,4 +89,19 @@ extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);  #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f))  #define dma_free_noncoherent(d, s, v, h)  dma_free_coherent((d), (s), (v), (h)) +/* Not supported for now */ +static inline int dma_mmap_coherent(struct device *dev, +				    struct vm_area_struct *vma, void *cpu_addr, +				    dma_addr_t dma_addr, size_t size) +{ +	return -EINVAL; +} + +static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size) +{ +	return -EINVAL; +} +  #endif	/* _ASM_C6X_DMA_MAPPING_H */ diff --git a/arch/cris/include/asm/dma-mapping.h b/arch/cris/include/asm/dma-mapping.h index 8588b2ccf85..2f0f654f1b4 100644 --- a/arch/cris/include/asm/dma-mapping.h +++ b/arch/cris/include/asm/dma-mapping.h @@ -158,5 +158,15 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,  {  } +/* drivers/base/dma-mapping.c */ +extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, +			   void *cpu_addr, dma_addr_t dma_addr, size_t size); +extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size); + +#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) +#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) +  #endif diff --git a/arch/frv/include/asm/dma-mapping.h b/arch/frv/include/asm/dma-mapping.h index dfb811002c6..1746a2b8e6e 100644 --- a/arch/frv/include/asm/dma-mapping.h +++ b/arch/frv/include/asm/dma-mapping.h @@ -132,4 +132,19 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,  	flush_write_buffers();  } +/* Not supported for now */ +static inline int dma_mmap_coherent(struct device *dev, +				    struct vm_area_struct *vma, void *cpu_addr, +				    dma_addr_t dma_addr, size_t size) +{ +	return -EINVAL; +} + +static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size) +{ +	return -EINVAL; +} +  #endif  /* _ASM_DMA_MAPPING_H */ diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h index 3e6b8445af6..292805f0762 100644 --- a/arch/m68k/include/asm/dma-mapping.h +++ b/arch/m68k/include/asm/dma-mapping.h @@ -115,4 +115,14 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t handle)  #include <asm-generic/dma-mapping-broken.h>  #endif +/* drivers/base/dma-mapping.c */ +extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, +			   void *cpu_addr, dma_addr_t dma_addr, size_t size); +extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size); + +#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) +#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) +  #endif  /* _M68K_DMA_MAPPING_H */ diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 5c088494e04..4b597d91a8d 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -21,6 +21,7 @@ platforms += netlogic  platforms += pmcs-msp71xx  platforms += pnx833x  platforms += powertv +platforms += ralink  platforms += rb532  platforms += sgi-ip22  platforms += sgi-ip27 diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index af4e04fde0b..6fe9a188c49 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -107,12 +107,14 @@ config ATH79  config BCM47XX  	bool "Broadcom BCM47XX based boards"  	select ARCH_WANT_OPTIONAL_GPIOLIB +	select BOOT_RAW  	select CEVT_R4K  	select CSRC_R4K  	select DMA_NONCOHERENT  	select FW_CFE  	select HW_HAS_PCI  	select IRQ_CPU +	select NO_EXCEPT_FILL  	select SYS_SUPPORTS_32BIT_KERNEL  	select SYS_SUPPORTS_LITTLE_ENDIAN  	select SYS_HAS_EARLY_PRINTK @@ -294,6 +296,7 @@ config MIPS_MALTA  	select BOOT_RAW  	select CEVT_R4K  	select CSRC_R4K +	select CSRC_GIC  	select DMA_NONCOHERENT  	select GENERIC_ISA_DMA  	select HAVE_PCSPKR_PLATFORM @@ -425,6 +428,22 @@ config POWERTV  	help  	  This enables support for the Cisco PowerTV Platform. +config RALINK +	bool "Ralink based machines" +	select CEVT_R4K +	select CSRC_R4K +	select BOOT_RAW +	select DMA_NONCOHERENT +	select IRQ_CPU +	select USE_OF +	select SYS_HAS_CPU_MIPS32_R1 +	select SYS_HAS_CPU_MIPS32_R2 +	select SYS_SUPPORTS_32BIT_KERNEL +	select SYS_SUPPORTS_LITTLE_ENDIAN +	select SYS_HAS_EARLY_PRINTK +	select HAVE_MACH_CLKDEV +	select CLKDEV_LOOKUP +  config SGI_IP22  	bool "SGI IP22 (Indy/Indigo2)"  	select FW_ARC @@ -837,6 +856,7 @@ source "arch/mips/lantiq/Kconfig"  source "arch/mips/lasat/Kconfig"  source "arch/mips/pmcs-msp71xx/Kconfig"  source "arch/mips/powertv/Kconfig" +source "arch/mips/ralink/Kconfig"  source "arch/mips/sgi-ip27/Kconfig"  source "arch/mips/sibyte/Kconfig"  source "arch/mips/txx9/Kconfig" @@ -917,6 +937,9 @@ config CSRC_POWERTV  config CSRC_R4K  	bool +config CSRC_GIC +	bool +  config CSRC_SB1250  	bool diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index f44feee2d67..3995e31a73e 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -14,6 +14,18 @@ config ATH79_MACH_AP121  	  Say 'Y' here if you want your kernel to support the  	  Atheros AP121 reference board. +config ATH79_MACH_AP136 +	bool "Atheros AP136 reference board" +	select SOC_QCA955X +	select ATH79_DEV_GPIO_BUTTONS +	select ATH79_DEV_LEDS_GPIO +	select ATH79_DEV_SPI +	select ATH79_DEV_USB +	select ATH79_DEV_WMAC +	help +	  Say 'Y' here if you want your kernel to support the +	  Atheros AP136 reference board. +  config ATH79_MACH_AP81  	bool "Atheros AP81 reference board"  	select SOC_AR913X @@ -88,6 +100,12 @@ config SOC_AR934X  	select PCI_AR724X if PCI  	def_bool n +config SOC_QCA955X +	select USB_ARCH_HAS_EHCI +	select HW_HAS_PCI +	select PCI_AR724X if PCI +	def_bool n +  config PCI_AR724X  	def_bool n @@ -104,7 +122,7 @@ config ATH79_DEV_USB  	def_bool n  config ATH79_DEV_WMAC -	depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X) +	depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X)  	def_bool n  endif diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile index 2b54d98263f..5c9ff692ff3 100644 --- a/arch/mips/ath79/Makefile +++ b/arch/mips/ath79/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_ATH79_DEV_WMAC)		+= dev-wmac.o  # Machines  #  obj-$(CONFIG_ATH79_MACH_AP121)		+= mach-ap121.o +obj-$(CONFIG_ATH79_MACH_AP136)		+= mach-ap136.o  obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o  obj-$(CONFIG_ATH79_MACH_DB120)		+= mach-db120.o  obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 8c1b8bf9b32..765ef30e3e1 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -295,6 +295,82 @@ static void __init ar934x_clocks_init(void)  	iounmap(dpll_base);  } +static void __init qca955x_clocks_init(void) +{ +	u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; +	u32 cpu_pll, ddr_pll; +	u32 bootstrap; + +	bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); +	if (bootstrap &	QCA955X_BOOTSTRAP_REF_CLK_40) +		ath79_ref_clk.rate = 40 * 1000 * 1000; +	else +		ath79_ref_clk.rate = 25 * 1000 * 1000; + +	pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); +	out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & +		  QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; +	ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & +		  QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; +	nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & +	       QCA955X_PLL_CPU_CONFIG_NINT_MASK; +	frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & +	       QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; + +	cpu_pll = nint * ath79_ref_clk.rate / ref_div; +	cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); +	cpu_pll /= (1 << out_div); + +	pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); +	out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & +		  QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; +	ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & +		  QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; +	nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & +	       QCA955X_PLL_DDR_CONFIG_NINT_MASK; +	frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & +	       QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; + +	ddr_pll = nint * ath79_ref_clk.rate / ref_div; +	ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); +	ddr_pll /= (1 << out_div); + +	clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); + +	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & +		  QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + +	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) +		ath79_cpu_clk.rate = ath79_ref_clk.rate; +	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) +		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1); +	else +		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1); + +	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & +		  QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + +	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) +		ath79_ddr_clk.rate = ath79_ref_clk.rate; +	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) +		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1); +	else +		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1); + +	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & +		  QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + +	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) +		ath79_ahb_clk.rate = ath79_ref_clk.rate; +	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) +		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1); +	else +		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1); + +	ath79_wdt_clk.rate = ath79_ref_clk.rate; +	ath79_uart_clk.rate = ath79_ref_clk.rate; +} +  void __init ath79_clocks_init(void)  {  	if (soc_is_ar71xx()) @@ -307,6 +383,8 @@ void __init ath79_clocks_init(void)  		ar933x_clocks_init();  	else if (soc_is_ar934x())  		ar934x_clocks_init(); +	else if (soc_is_qca955x()) +		qca955x_clocks_init();  	else  		BUG(); diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index 5a4adfc9d79..eb3966cd8cf 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -72,6 +72,8 @@ void ath79_device_reset_set(u32 mask)  		reg = AR933X_RESET_REG_RESET_MODULE;  	else if (soc_is_ar934x())  		reg = AR934X_RESET_REG_RESET_MODULE; +	else if (soc_is_qca955x()) +		reg = QCA955X_RESET_REG_RESET_MODULE;  	else  		BUG(); @@ -98,6 +100,8 @@ void ath79_device_reset_clear(u32 mask)  		reg = AR933X_RESET_REG_RESET_MODULE;  	else if (soc_is_ar934x())  		reg = AR934X_RESET_REG_RESET_MODULE; +	else if (soc_is_qca955x()) +		reg = QCA955X_RESET_REG_RESET_MODULE;  	else  		BUG(); diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c index 45efc63b08b..9516aab2713 100644 --- a/arch/mips/ath79/dev-common.c +++ b/arch/mips/ath79/dev-common.c @@ -36,7 +36,7 @@ static struct resource ath79_uart_resources[] = {  static struct plat_serial8250_port ath79_uart_data[] = {  	{  		.mapbase	= AR71XX_UART_BASE, -		.irq		= ATH79_MISC_IRQ_UART, +		.irq		= ATH79_MISC_IRQ(3),  		.flags		= AR71XX_UART_FLAGS,  		.iotype		= UPIO_MEM32,  		.regshift	= 2, @@ -62,8 +62,8 @@ static struct resource ar933x_uart_resources[] = {  		.flags	= IORESOURCE_MEM,  	},  	{ -		.start	= ATH79_MISC_IRQ_UART, -		.end	= ATH79_MISC_IRQ_UART, +		.start	= ATH79_MISC_IRQ(3), +		.end	= ATH79_MISC_IRQ(3),  		.flags	= IORESOURCE_IRQ,  	},  }; @@ -90,7 +90,8 @@ void __init ath79_register_uart(void)  	if (soc_is_ar71xx() ||  	    soc_is_ar724x() ||  	    soc_is_ar913x() || -	    soc_is_ar934x()) { +	    soc_is_ar934x() || +	    soc_is_qca955x()) {  		ath79_uart_data[0].uartclk = clk_get_rate(clk);  		platform_device_register(&ath79_uart_device);  	} else if (soc_is_ar933x()) { diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c index bd2bc108e1b..8227265bcc2 100644 --- a/arch/mips/ath79/dev-usb.c +++ b/arch/mips/ath79/dev-usb.c @@ -25,29 +25,11 @@  #include "common.h"  #include "dev-usb.h" -static struct resource ath79_ohci_resources[2]; - -static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32); +static u64 ath79_usb_dmamask = DMA_BIT_MASK(32);  static struct usb_ohci_pdata ath79_ohci_pdata = {  }; -static struct platform_device ath79_ohci_device = { -	.name		= "ohci-platform", -	.id		= -1, -	.resource	= ath79_ohci_resources, -	.num_resources	= ARRAY_SIZE(ath79_ohci_resources), -	.dev = { -		.dma_mask		= &ath79_ohci_dmamask, -		.coherent_dma_mask	= DMA_BIT_MASK(32), -		.platform_data		= &ath79_ohci_pdata, -	}, -}; - -static struct resource ath79_ehci_resources[2]; - -static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32); -  static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {  	.has_synopsys_hc_bug	= 1,  }; @@ -57,22 +39,16 @@ static struct usb_ehci_pdata ath79_ehci_pdata_v2 = {  	.has_tt			= 1,  }; -static struct platform_device ath79_ehci_device = { -	.name		= "ehci-platform", -	.id		= -1, -	.resource	= ath79_ehci_resources, -	.num_resources	= ARRAY_SIZE(ath79_ehci_resources), -	.dev = { -		.dma_mask		= &ath79_ehci_dmamask, -		.coherent_dma_mask	= DMA_BIT_MASK(32), -	}, -}; - -static void __init ath79_usb_init_resource(struct resource res[2], -					   unsigned long base, -					   unsigned long size, -					   int irq) +static void __init ath79_usb_register(const char *name, int id, +				      unsigned long base, unsigned long size, +				      int irq, const void *data, +				      size_t data_size)  { +	struct resource res[2]; +	struct platform_device *pdev; + +	memset(res, 0, sizeof(res)); +  	res[0].flags = IORESOURCE_MEM;  	res[0].start = base;  	res[0].end = base + size - 1; @@ -80,6 +56,19 @@ static void __init ath79_usb_init_resource(struct resource res[2],  	res[1].flags = IORESOURCE_IRQ;  	res[1].start = irq;  	res[1].end = irq; + +	pdev = platform_device_register_resndata(NULL, name, id, +						 res, ARRAY_SIZE(res), +						 data, data_size); + +	if (IS_ERR(pdev)) { +		pr_err("ath79: unable to register USB at %08lx, err=%d\n", +		       base, (int) PTR_ERR(pdev)); +		return; +	} + +	pdev->dev.dma_mask = &ath79_usb_dmamask; +	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);  }  #define AR71XX_USB_RESET_MASK	(AR71XX_RESET_USB_HOST | \ @@ -106,14 +95,15 @@ static void __init ath79_usb_setup(void)  	mdelay(900); -	ath79_usb_init_resource(ath79_ohci_resources, AR71XX_OHCI_BASE, -				AR71XX_OHCI_SIZE, ATH79_MISC_IRQ_OHCI); -	platform_device_register(&ath79_ohci_device); +	ath79_usb_register("ohci-platform", -1, +			   AR71XX_OHCI_BASE, AR71XX_OHCI_SIZE, +			   ATH79_MISC_IRQ(6), +			   &ath79_ohci_pdata, sizeof(ath79_ohci_pdata)); -	ath79_usb_init_resource(ath79_ehci_resources, AR71XX_EHCI_BASE, -				AR71XX_EHCI_SIZE, ATH79_CPU_IRQ_USB); -	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v1; -	platform_device_register(&ath79_ehci_device); +	ath79_usb_register("ehci-platform", -1, +			   AR71XX_EHCI_BASE, AR71XX_EHCI_SIZE, +			   ATH79_CPU_IRQ(3), +			   &ath79_ehci_pdata_v1, sizeof(ath79_ehci_pdata_v1));  }  static void __init ar7240_usb_setup(void) @@ -135,9 +125,10 @@ static void __init ar7240_usb_setup(void)  	iounmap(usb_ctrl_base); -	ath79_usb_init_resource(ath79_ohci_resources, AR7240_OHCI_BASE, -				AR7240_OHCI_SIZE, ATH79_CPU_IRQ_USB); -	platform_device_register(&ath79_ohci_device); +	ath79_usb_register("ohci-platform", -1, +			   AR7240_OHCI_BASE, AR7240_OHCI_SIZE, +			   ATH79_CPU_IRQ(3), +			   &ath79_ohci_pdata, sizeof(ath79_ohci_pdata));  }  static void __init ar724x_usb_setup(void) @@ -151,10 +142,10 @@ static void __init ar724x_usb_setup(void)  	ath79_device_reset_clear(AR724X_RESET_USB_PHY);  	mdelay(10); -	ath79_usb_init_resource(ath79_ehci_resources, AR724X_EHCI_BASE, -				AR724X_EHCI_SIZE, ATH79_CPU_IRQ_USB); -	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; -	platform_device_register(&ath79_ehci_device); +	ath79_usb_register("ehci-platform", -1, +			   AR724X_EHCI_BASE, AR724X_EHCI_SIZE, +			   ATH79_CPU_IRQ(3), +			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));  }  static void __init ar913x_usb_setup(void) @@ -168,10 +159,10 @@ static void __init ar913x_usb_setup(void)  	ath79_device_reset_clear(AR913X_RESET_USB_PHY);  	mdelay(10); -	ath79_usb_init_resource(ath79_ehci_resources, AR913X_EHCI_BASE, -				AR913X_EHCI_SIZE, ATH79_CPU_IRQ_USB); -	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; -	platform_device_register(&ath79_ehci_device); +	ath79_usb_register("ehci-platform", -1, +			   AR913X_EHCI_BASE, AR913X_EHCI_SIZE, +			   ATH79_CPU_IRQ(3), +			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));  }  static void __init ar933x_usb_setup(void) @@ -185,10 +176,10 @@ static void __init ar933x_usb_setup(void)  	ath79_device_reset_clear(AR933X_RESET_USB_PHY);  	mdelay(10); -	ath79_usb_init_resource(ath79_ehci_resources, AR933X_EHCI_BASE, -				AR933X_EHCI_SIZE, ATH79_CPU_IRQ_USB); -	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; -	platform_device_register(&ath79_ehci_device); +	ath79_usb_register("ehci-platform", -1, +			   AR933X_EHCI_BASE, AR933X_EHCI_SIZE, +			   ATH79_CPU_IRQ(3), +			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));  }  static void __init ar934x_usb_setup(void) @@ -211,10 +202,23 @@ static void __init ar934x_usb_setup(void)  	ath79_device_reset_clear(AR934X_RESET_USB_HOST);  	udelay(1000); -	ath79_usb_init_resource(ath79_ehci_resources, AR934X_EHCI_BASE, -				AR934X_EHCI_SIZE, ATH79_CPU_IRQ_USB); -	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; -	platform_device_register(&ath79_ehci_device); +	ath79_usb_register("ehci-platform", -1, +			   AR934X_EHCI_BASE, AR934X_EHCI_SIZE, +			   ATH79_CPU_IRQ(3), +			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +} + +static void __init qca955x_usb_setup(void) +{ +	ath79_usb_register("ehci-platform", 0, +			   QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE, +			   ATH79_IP3_IRQ(0), +			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); + +	ath79_usb_register("ehci-platform", 1, +			   QCA955X_EHCI1_BASE, QCA955X_EHCI_SIZE, +			   ATH79_IP3_IRQ(1), +			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));  }  void __init ath79_register_usb(void) @@ -231,6 +235,8 @@ void __init ath79_register_usb(void)  		ar933x_usb_setup();  	else if (soc_is_ar934x())  		ar934x_usb_setup(); +	else if (soc_is_qca955x()) +		qca955x_usb_setup();  	else  		BUG();  } diff --git a/arch/mips/ath79/dev-wmac.c b/arch/mips/ath79/dev-wmac.c index d6d893c16ad..da190b1b87c 100644 --- a/arch/mips/ath79/dev-wmac.c +++ b/arch/mips/ath79/dev-wmac.c @@ -55,8 +55,8 @@ static void __init ar913x_wmac_setup(void)  	ath79_wmac_resources[0].start = AR913X_WMAC_BASE;  	ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1; -	ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2; -	ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2; +	ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2); +	ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2);  } @@ -83,8 +83,8 @@ static void __init ar933x_wmac_setup(void)  	ath79_wmac_resources[0].start = AR933X_WMAC_BASE;  	ath79_wmac_resources[0].end = AR933X_WMAC_BASE + AR933X_WMAC_SIZE - 1; -	ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2; -	ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2; +	ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2); +	ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2);  	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);  	if (t & AR933X_BOOTSTRAP_REF_CLK_40) @@ -107,7 +107,7 @@ static void ar934x_wmac_setup(void)  	ath79_wmac_resources[0].start = AR934X_WMAC_BASE;  	ath79_wmac_resources[0].end = AR934X_WMAC_BASE + AR934X_WMAC_SIZE - 1;  	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); -	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); +	ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1);  	t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);  	if (t & AR934X_BOOTSTRAP_REF_CLK_40) @@ -116,6 +116,24 @@ static void ar934x_wmac_setup(void)  		ath79_wmac_data.is_clk_25mhz = true;  } +static void qca955x_wmac_setup(void) +{ +	u32 t; + +	ath79_wmac_device.name = "qca955x_wmac"; + +	ath79_wmac_resources[0].start = QCA955X_WMAC_BASE; +	ath79_wmac_resources[0].end = QCA955X_WMAC_BASE + QCA955X_WMAC_SIZE - 1; +	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); +	ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1); + +	t = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); +	if (t & QCA955X_BOOTSTRAP_REF_CLK_40) +		ath79_wmac_data.is_clk_25mhz = false; +	else +		ath79_wmac_data.is_clk_25mhz = true; +} +  void __init ath79_register_wmac(u8 *cal_data)  {  	if (soc_is_ar913x()) @@ -124,6 +142,8 @@ void __init ath79_register_wmac(u8 *cal_data)  		ar933x_wmac_setup();  	else if (soc_is_ar934x())  		ar934x_wmac_setup(); +	else if (soc_is_qca955x()) +		qca955x_wmac_setup();  	else  		BUG(); diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c index dc938cb2ba5..b955fafc58b 100644 --- a/arch/mips/ath79/early_printk.c +++ b/arch/mips/ath79/early_printk.c @@ -74,6 +74,8 @@ static void prom_putchar_init(void)  	case REV_ID_MAJOR_AR9341:  	case REV_ID_MAJOR_AR9342:  	case REV_ID_MAJOR_AR9344: +	case REV_ID_MAJOR_QCA9556: +	case REV_ID_MAJOR_QCA9558:  		_prom_putchar = prom_putchar_ar71xx;  		break; diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c index 48fe762d252..8d025b028bb 100644 --- a/arch/mips/ath79/gpio.c +++ b/arch/mips/ath79/gpio.c @@ -137,49 +137,45 @@ static struct gpio_chip ath79_gpio_chip = {  	.base			= 0,  }; -void ath79_gpio_function_enable(u32 mask) +static void __iomem *ath79_gpio_get_function_reg(void)  { -	void __iomem *base = ath79_gpio_base; -	unsigned long flags; +	u32 reg = 0; -	spin_lock_irqsave(&ath79_gpio_lock, flags); - -	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask, -		     base + AR71XX_GPIO_REG_FUNC); -	/* flush write */ -	__raw_readl(base + AR71XX_GPIO_REG_FUNC); +	if (soc_is_ar71xx() || +	    soc_is_ar724x() || +	    soc_is_ar913x() || +	    soc_is_ar933x()) +		reg = AR71XX_GPIO_REG_FUNC; +	else if (soc_is_ar934x()) +		reg = AR934X_GPIO_REG_FUNC; +	else +		BUG(); -	spin_unlock_irqrestore(&ath79_gpio_lock, flags); +	return ath79_gpio_base + reg;  } -void ath79_gpio_function_disable(u32 mask) +void ath79_gpio_function_setup(u32 set, u32 clear)  { -	void __iomem *base = ath79_gpio_base; +	void __iomem *reg = ath79_gpio_get_function_reg();  	unsigned long flags;  	spin_lock_irqsave(&ath79_gpio_lock, flags); -	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask, -		     base + AR71XX_GPIO_REG_FUNC); +	__raw_writel((__raw_readl(reg) & ~clear) | set, reg);  	/* flush write */ -	__raw_readl(base + AR71XX_GPIO_REG_FUNC); +	__raw_readl(reg);  	spin_unlock_irqrestore(&ath79_gpio_lock, flags);  } -void ath79_gpio_function_setup(u32 set, u32 clear) +void ath79_gpio_function_enable(u32 mask)  { -	void __iomem *base = ath79_gpio_base; -	unsigned long flags; - -	spin_lock_irqsave(&ath79_gpio_lock, flags); - -	__raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set, -		     base + AR71XX_GPIO_REG_FUNC); -	/* flush write */ -	__raw_readl(base + AR71XX_GPIO_REG_FUNC); +	ath79_gpio_function_setup(mask, 0); +} -	spin_unlock_irqrestore(&ath79_gpio_lock, flags); +void ath79_gpio_function_disable(u32 mask) +{ +	ath79_gpio_function_setup(0, mask);  }  void __init ath79_gpio_init(void) @@ -198,12 +194,14 @@ void __init ath79_gpio_init(void)  		ath79_gpio_count = AR933X_GPIO_COUNT;  	else if (soc_is_ar934x())  		ath79_gpio_count = AR934X_GPIO_COUNT; +	else if (soc_is_qca955x()) +		ath79_gpio_count = QCA955X_GPIO_COUNT;  	else  		BUG();  	ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);  	ath79_gpio_chip.ngpio = ath79_gpio_count; -	if (soc_is_ar934x()) { +	if (soc_is_ar934x() || soc_is_qca955x()) {  		ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;  		ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;  	} diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 90d09fc1539..9c0e1761773 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -35,44 +35,17 @@ static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)  	pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &  		  __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); -	if (pending & MISC_INT_UART) -		generic_handle_irq(ATH79_MISC_IRQ_UART); - -	else if (pending & MISC_INT_DMA) -		generic_handle_irq(ATH79_MISC_IRQ_DMA); - -	else if (pending & MISC_INT_PERFC) -		generic_handle_irq(ATH79_MISC_IRQ_PERFC); - -	else if (pending & MISC_INT_TIMER) -		generic_handle_irq(ATH79_MISC_IRQ_TIMER); - -	else if (pending & MISC_INT_TIMER2) -		generic_handle_irq(ATH79_MISC_IRQ_TIMER2); - -	else if (pending & MISC_INT_TIMER3) -		generic_handle_irq(ATH79_MISC_IRQ_TIMER3); - -	else if (pending & MISC_INT_TIMER4) -		generic_handle_irq(ATH79_MISC_IRQ_TIMER4); - -	else if (pending & MISC_INT_OHCI) -		generic_handle_irq(ATH79_MISC_IRQ_OHCI); - -	else if (pending & MISC_INT_ERROR) -		generic_handle_irq(ATH79_MISC_IRQ_ERROR); - -	else if (pending & MISC_INT_GPIO) -		generic_handle_irq(ATH79_MISC_IRQ_GPIO); - -	else if (pending & MISC_INT_WDOG) -		generic_handle_irq(ATH79_MISC_IRQ_WDOG); +	if (!pending) { +		spurious_interrupt(); +		return; +	} -	else if (pending & MISC_INT_ETHSW) -		generic_handle_irq(ATH79_MISC_IRQ_ETHSW); +	while (pending) { +		int bit = __ffs(pending); -	else -		spurious_interrupt(); +		generic_handle_irq(ATH79_MISC_IRQ(bit)); +		pending &= ~BIT(bit); +	}  }  static void ar71xx_misc_irq_unmask(struct irq_data *d) @@ -130,7 +103,10 @@ static void __init ath79_misc_irq_init(void)  	if (soc_is_ar71xx() || soc_is_ar913x())  		ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; -	else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x()) +	else if (soc_is_ar724x() || +		 soc_is_ar933x() || +		 soc_is_ar934x() || +		 soc_is_qca955x())  		ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;  	else  		BUG(); @@ -141,7 +117,7 @@ static void __init ath79_misc_irq_init(void)  					 handle_level_irq);  	} -	irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); +	irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);  }  static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) @@ -174,7 +150,89 @@ static void ar934x_ip2_irq_init(void)  		irq_set_chip_and_handler(i, &dummy_irq_chip,  					 handle_level_irq); -	irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch); +	irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch); +} + +static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) +{ +	u32 status; + +	disable_irq_nosync(irq); + +	status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); +	status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL; + +	if (status == 0) { +		spurious_interrupt(); +		goto enable; +	} + +	if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) { +		/* TODO: flush DDR? */ +		generic_handle_irq(ATH79_IP2_IRQ(0)); +	} + +	if (status & QCA955X_EXT_INT_WMAC_ALL) { +		/* TODO: flush DDR? */ +		generic_handle_irq(ATH79_IP2_IRQ(1)); +	} + +enable: +	enable_irq(irq); +} + +static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc) +{ +	u32 status; + +	disable_irq_nosync(irq); + +	status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); +	status &= QCA955X_EXT_INT_PCIE_RC2_ALL | +		  QCA955X_EXT_INT_USB1 | +		  QCA955X_EXT_INT_USB2; + +	if (status == 0) { +		spurious_interrupt(); +		goto enable; +	} + +	if (status & QCA955X_EXT_INT_USB1) { +		/* TODO: flush DDR? */ +		generic_handle_irq(ATH79_IP3_IRQ(0)); +	} + +	if (status & QCA955X_EXT_INT_USB2) { +		/* TODO: flush DDR? */ +		generic_handle_irq(ATH79_IP3_IRQ(1)); +	} + +	if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) { +		/* TODO: flush DDR? */ +		generic_handle_irq(ATH79_IP3_IRQ(2)); +	} + +enable: +	enable_irq(irq); +} + +static void qca955x_irq_init(void) +{ +	int i; + +	for (i = ATH79_IP2_IRQ_BASE; +	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) +		irq_set_chip_and_handler(i, &dummy_irq_chip, +					 handle_level_irq); + +	irq_set_chained_handler(ATH79_CPU_IRQ(2), qca955x_ip2_irq_dispatch); + +	for (i = ATH79_IP3_IRQ_BASE; +	     i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++) +		irq_set_chip_and_handler(i, &dummy_irq_chip, +					 handle_level_irq); + +	irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);  }  asmlinkage void plat_irq_dispatch(void) @@ -184,22 +242,22 @@ asmlinkage void plat_irq_dispatch(void)  	pending = read_c0_status() & read_c0_cause() & ST0_IM;  	if (pending & STATUSF_IP7) -		do_IRQ(ATH79_CPU_IRQ_TIMER); +		do_IRQ(ATH79_CPU_IRQ(7));  	else if (pending & STATUSF_IP2)  		ath79_ip2_handler();  	else if (pending & STATUSF_IP4) -		do_IRQ(ATH79_CPU_IRQ_GE0); +		do_IRQ(ATH79_CPU_IRQ(4));  	else if (pending & STATUSF_IP5) -		do_IRQ(ATH79_CPU_IRQ_GE1); +		do_IRQ(ATH79_CPU_IRQ(5));  	else if (pending & STATUSF_IP3)  		ath79_ip3_handler();  	else if (pending & STATUSF_IP6) -		do_IRQ(ATH79_CPU_IRQ_MISC); +		do_IRQ(ATH79_CPU_IRQ(6));  	else  		spurious_interrupt(); @@ -212,63 +270,69 @@ asmlinkage void plat_irq_dispatch(void)   * Issue a flush in the handlers to ensure that the driver sees   * the update.   */ + +static void ath79_default_ip2_handler(void) +{ +	do_IRQ(ATH79_CPU_IRQ(2)); +} + +static void ath79_default_ip3_handler(void) +{ +	do_IRQ(ATH79_CPU_IRQ(3)); +} +  static void ar71xx_ip2_handler(void)  {  	ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); -	do_IRQ(ATH79_CPU_IRQ_IP2); +	do_IRQ(ATH79_CPU_IRQ(2));  }  static void ar724x_ip2_handler(void)  {  	ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); -	do_IRQ(ATH79_CPU_IRQ_IP2); +	do_IRQ(ATH79_CPU_IRQ(2));  }  static void ar913x_ip2_handler(void)  {  	ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); -	do_IRQ(ATH79_CPU_IRQ_IP2); +	do_IRQ(ATH79_CPU_IRQ(2));  }  static void ar933x_ip2_handler(void)  {  	ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); -	do_IRQ(ATH79_CPU_IRQ_IP2); -} - -static void ar934x_ip2_handler(void) -{ -	do_IRQ(ATH79_CPU_IRQ_IP2); +	do_IRQ(ATH79_CPU_IRQ(2));  }  static void ar71xx_ip3_handler(void)  {  	ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); -	do_IRQ(ATH79_CPU_IRQ_USB); +	do_IRQ(ATH79_CPU_IRQ(3));  }  static void ar724x_ip3_handler(void)  {  	ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); -	do_IRQ(ATH79_CPU_IRQ_USB); +	do_IRQ(ATH79_CPU_IRQ(3));  }  static void ar913x_ip3_handler(void)  {  	ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); -	do_IRQ(ATH79_CPU_IRQ_USB); +	do_IRQ(ATH79_CPU_IRQ(3));  }  static void ar933x_ip3_handler(void)  {  	ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); -	do_IRQ(ATH79_CPU_IRQ_USB); +	do_IRQ(ATH79_CPU_IRQ(3));  }  static void ar934x_ip3_handler(void)  {  	ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); -	do_IRQ(ATH79_CPU_IRQ_USB); +	do_IRQ(ATH79_CPU_IRQ(3));  }  void __init arch_init_irq(void) @@ -286,16 +350,21 @@ void __init arch_init_irq(void)  		ath79_ip2_handler = ar933x_ip2_handler;  		ath79_ip3_handler = ar933x_ip3_handler;  	} else if (soc_is_ar934x()) { -		ath79_ip2_handler = ar934x_ip2_handler; +		ath79_ip2_handler = ath79_default_ip2_handler;  		ath79_ip3_handler = ar934x_ip3_handler; +	} else if (soc_is_qca955x()) { +		ath79_ip2_handler = ath79_default_ip2_handler; +		ath79_ip3_handler = ath79_default_ip3_handler;  	} else {  		BUG();  	} -	cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; +	cp0_perfcount_irq = ATH79_MISC_IRQ(5);  	mips_cpu_irq_init();  	ath79_misc_irq_init();  	if (soc_is_ar934x())  		ar934x_ip2_irq_init(); +	else if (soc_is_qca955x()) +		qca955x_irq_init();  } diff --git a/arch/mips/ath79/mach-ap136.c b/arch/mips/ath79/mach-ap136.c new file mode 100644 index 00000000000..479dd4b1d0d --- /dev/null +++ b/arch/mips/ath79/mach-ap136.c @@ -0,0 +1,156 @@ +/* + * Qualcomm Atheros AP136 reference board support + * + * Copyright (c) 2012 Qualcomm Atheros + * Copyright (c) 2012-2013 Gabor Juhos <juhosg@openwrt.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <linux/pci.h> +#include <linux/ath9k_platform.h> + +#include "machtypes.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-spi.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "pci.h" + +#define AP136_GPIO_LED_STATUS_RED	14 +#define AP136_GPIO_LED_STATUS_GREEN	19 +#define AP136_GPIO_LED_USB		4 +#define AP136_GPIO_LED_WLAN_2G		13 +#define AP136_GPIO_LED_WLAN_5G		12 +#define AP136_GPIO_LED_WPS_RED		15 +#define AP136_GPIO_LED_WPS_GREEN	20 + +#define AP136_GPIO_BTN_WPS		16 +#define AP136_GPIO_BTN_RFKILL		21 + +#define AP136_KEYS_POLL_INTERVAL	20	/* msecs */ +#define AP136_KEYS_DEBOUNCE_INTERVAL	(3 * AP136_KEYS_POLL_INTERVAL) + +#define AP136_WMAC_CALDATA_OFFSET 0x1000 +#define AP136_PCIE_CALDATA_OFFSET 0x5000 + +static struct gpio_led ap136_leds_gpio[] __initdata = { +	{ +		.name		= "qca:green:status", +		.gpio		= AP136_GPIO_LED_STATUS_GREEN, +		.active_low	= 1, +	}, +	{ +		.name		= "qca:red:status", +		.gpio		= AP136_GPIO_LED_STATUS_RED, +		.active_low	= 1, +	}, +	{ +		.name		= "qca:green:wps", +		.gpio		= AP136_GPIO_LED_WPS_GREEN, +		.active_low	= 1, +	}, +	{ +		.name		= "qca:red:wps", +		.gpio		= AP136_GPIO_LED_WPS_RED, +		.active_low	= 1, +	}, +	{ +		.name		= "qca:red:wlan-2g", +		.gpio		= AP136_GPIO_LED_WLAN_2G, +		.active_low	= 1, +	}, +	{ +		.name		= "qca:red:usb", +		.gpio		= AP136_GPIO_LED_USB, +		.active_low	= 1, +	} +}; + +static struct gpio_keys_button ap136_gpio_keys[] __initdata = { +	{ +		.desc		= "WPS button", +		.type		= EV_KEY, +		.code		= KEY_WPS_BUTTON, +		.debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL, +		.gpio		= AP136_GPIO_BTN_WPS, +		.active_low	= 1, +	}, +	{ +		.desc		= "RFKILL button", +		.type		= EV_KEY, +		.code		= KEY_RFKILL, +		.debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL, +		.gpio		= AP136_GPIO_BTN_RFKILL, +		.active_low	= 1, +	}, +}; + +static struct spi_board_info ap136_spi_info[] = { +	{ +		.bus_num	= 0, +		.chip_select	= 0, +		.max_speed_hz	= 25000000, +		.modalias	= "mx25l6405d", +	} +}; + +static struct ath79_spi_platform_data ap136_spi_data = { +	.bus_num	= 0, +	.num_chipselect	= 1, +}; + +#ifdef CONFIG_PCI +static struct ath9k_platform_data ap136_ath9k_data; + +static int ap136_pci_plat_dev_init(struct pci_dev *dev) +{ +	if (dev->bus->number == 1 && (PCI_SLOT(dev->devfn)) == 0) +		dev->dev.platform_data = &ap136_ath9k_data; + +	return 0; +} + +static void __init ap136_pci_init(u8 *eeprom) +{ +	memcpy(ap136_ath9k_data.eeprom_data, eeprom, +	       sizeof(ap136_ath9k_data.eeprom_data)); + +	ath79_pci_set_plat_dev_init(ap136_pci_plat_dev_init); +	ath79_register_pci(); +} +#else +static inline void ap136_pci_init(void) {} +#endif /* CONFIG_PCI */ + +static void __init ap136_setup(void) +{ +	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + +	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap136_leds_gpio), +				 ap136_leds_gpio); +	ath79_register_gpio_keys_polled(-1, AP136_KEYS_POLL_INTERVAL, +					ARRAY_SIZE(ap136_gpio_keys), +					ap136_gpio_keys); +	ath79_register_spi(&ap136_spi_data, ap136_spi_info, +			   ARRAY_SIZE(ap136_spi_info)); +	ath79_register_usb(); +	ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET); +	ap136_pci_init(art + AP136_PCIE_CALDATA_OFFSET); +} + +MIPS_MACHINE(ATH79_MACH_AP136_010, "AP136-010", +	     "Atheros AP136-010 reference board", +	     ap136_setup); diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h index af92e5c30d6..26254058c54 100644 --- a/arch/mips/ath79/machtypes.h +++ b/arch/mips/ath79/machtypes.h @@ -17,6 +17,7 @@  enum ath79_mach_type {  	ATH79_MACH_GENERIC = 0,  	ATH79_MACH_AP121,		/* Atheros AP121 reference board */ +	ATH79_MACH_AP136_010,		/* Atheros AP136-010 reference board */  	ATH79_MACH_AP81,		/* Atheros AP81 reference board */  	ATH79_MACH_DB120,		/* Atheros DB120 reference board */  	ATH79_MACH_PB44,		/* Atheros PB44 reference board */ diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index ca83abd9d31..730c0b03060 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c @@ -14,10 +14,11 @@  #include <linux/init.h>  #include <linux/pci.h> +#include <linux/resource.h> +#include <linux/platform_device.h>  #include <asm/mach-ath79/ar71xx_regs.h>  #include <asm/mach-ath79/ath79.h>  #include <asm/mach-ath79/irq.h> -#include <asm/mach-ath79/pci.h>  #include "pci.h"  static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev); @@ -48,6 +49,21 @@ static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {  	}  }; +static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = { +	{ +		.bus	= 0, +		.slot	= 0, +		.pin	= 1, +		.irq	= ATH79_PCI_IRQ(0), +	}, +	{ +		.bus	= 1, +		.slot	= 0, +		.pin	= 1, +		.irq	= ATH79_PCI_IRQ(1), +	}, +}; +  int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)  {  	int irq = -1; @@ -63,6 +79,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)  			   soc_is_ar9344()) {  			ath79_pci_irq_map = ar724x_pci_irq_map;  			ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); +		} else if (soc_is_qca955x()) { +			ath79_pci_irq_map = qca955x_pci_irq_map; +			ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map);  		} else {  			pr_crit("pci %s: invalid irq map\n",  				pci_name((struct pci_dev *) dev)); @@ -74,7 +93,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)  		const struct ath79_pci_irq *entry;  		entry = &ath79_pci_irq_map[i]; -		if (entry->slot == slot && entry->pin == pin) { +		if (entry->bus == dev->bus->number && +		    entry->slot == slot && +		    entry->pin == pin) {  			irq = entry->irq;  			break;  		} @@ -110,21 +131,143 @@ void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))  	ath79_pci_plat_dev_init = func;  } -int __init ath79_register_pci(void) +static struct platform_device * +ath79_register_pci_ar71xx(void) +{ +	struct platform_device *pdev; +	struct resource res[4]; + +	memset(res, 0, sizeof(res)); + +	res[0].name = "cfg_base"; +	res[0].flags = IORESOURCE_MEM; +	res[0].start = AR71XX_PCI_CFG_BASE; +	res[0].end = AR71XX_PCI_CFG_BASE + AR71XX_PCI_CFG_SIZE - 1; + +	res[1].flags = IORESOURCE_IRQ; +	res[1].start = ATH79_CPU_IRQ(2); +	res[1].end = ATH79_CPU_IRQ(2); + +	res[2].name = "io_base"; +	res[2].flags = IORESOURCE_IO; +	res[2].start = 0; +	res[2].end = 0; + +	res[3].name = "mem_base"; +	res[3].flags = IORESOURCE_MEM; +	res[3].start = AR71XX_PCI_MEM_BASE; +	res[3].end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1; + +	pdev = platform_device_register_simple("ar71xx-pci", -1, +					       res, ARRAY_SIZE(res)); +	return pdev; +} + +static struct platform_device * +ath79_register_pci_ar724x(int id, +			  unsigned long cfg_base, +			  unsigned long ctrl_base, +			  unsigned long crp_base, +			  unsigned long mem_base, +			  unsigned long mem_size, +			  unsigned long io_base, +			  int irq)  { -	if (soc_is_ar71xx()) -		return ar71xx_pcibios_init(); +	struct platform_device *pdev; +	struct resource res[6]; + +	memset(res, 0, sizeof(res)); + +	res[0].name = "cfg_base"; +	res[0].flags = IORESOURCE_MEM; +	res[0].start = cfg_base; +	res[0].end = cfg_base + AR724X_PCI_CFG_SIZE - 1; + +	res[1].name = "ctrl_base"; +	res[1].flags = IORESOURCE_MEM; +	res[1].start = ctrl_base; +	res[1].end = ctrl_base + AR724X_PCI_CTRL_SIZE - 1; + +	res[2].flags = IORESOURCE_IRQ; +	res[2].start = irq; +	res[2].end = irq; + +	res[3].name = "mem_base"; +	res[3].flags = IORESOURCE_MEM; +	res[3].start = mem_base; +	res[3].end = mem_base + mem_size - 1; + +	res[4].name = "io_base"; +	res[4].flags = IORESOURCE_IO; +	res[4].start = io_base; +	res[4].end = io_base; -	if (soc_is_ar724x()) -		return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2); +	res[5].name = "crp_base"; +	res[5].flags = IORESOURCE_MEM; +	res[5].start = crp_base; +	res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1; -	if (soc_is_ar9342() || soc_is_ar9344()) { +	pdev = platform_device_register_simple("ar724x-pci", id, +					       res, ARRAY_SIZE(res)); +	return pdev; +} + +int __init ath79_register_pci(void) +{ +	struct platform_device *pdev = NULL; + +	if (soc_is_ar71xx()) { +		pdev = ath79_register_pci_ar71xx(); +	} else if (soc_is_ar724x()) { +		pdev = ath79_register_pci_ar724x(-1, +						 AR724X_PCI_CFG_BASE, +						 AR724X_PCI_CTRL_BASE, +						 AR724X_PCI_CRP_BASE, +						 AR724X_PCI_MEM_BASE, +						 AR724X_PCI_MEM_SIZE, +						 0, +						 ATH79_CPU_IRQ(2)); +	} else if (soc_is_ar9342() || +		   soc_is_ar9344()) {  		u32 bootstrap;  		bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); -		if (bootstrap & AR934X_BOOTSTRAP_PCIE_RC) -			return ar724x_pcibios_init(ATH79_IP2_IRQ(0)); +		if ((bootstrap & AR934X_BOOTSTRAP_PCIE_RC) == 0) +			return -ENODEV; + +		pdev = ath79_register_pci_ar724x(-1, +						 AR724X_PCI_CFG_BASE, +						 AR724X_PCI_CTRL_BASE, +						 AR724X_PCI_CRP_BASE, +						 AR724X_PCI_MEM_BASE, +						 AR724X_PCI_MEM_SIZE, +						 0, +						 ATH79_IP2_IRQ(0)); +	} else if (soc_is_qca9558()) { +		pdev = ath79_register_pci_ar724x(0, +						 QCA955X_PCI_CFG_BASE0, +						 QCA955X_PCI_CTRL_BASE0, +						 QCA955X_PCI_CRP_BASE0, +						 QCA955X_PCI_MEM_BASE0, +						 QCA955X_PCI_MEM_SIZE, +						 0, +						 ATH79_IP2_IRQ(0)); + +		pdev = ath79_register_pci_ar724x(1, +						 QCA955X_PCI_CFG_BASE1, +						 QCA955X_PCI_CTRL_BASE1, +						 QCA955X_PCI_CRP_BASE1, +						 QCA955X_PCI_MEM_BASE1, +						 QCA955X_PCI_MEM_SIZE, +						 1, +						 ATH79_IP3_IRQ(2)); +	} else { +		/* No PCI support */ +		return -ENODEV;  	} -	return -ENODEV; +	if (!pdev) +		pr_err("unable to register PCI controller device\n"); + +	return pdev ? 0 : -ENODEV;  } diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h index 51c6625dcc6..1d00a3803c3 100644 --- a/arch/mips/ath79/pci.h +++ b/arch/mips/ath79/pci.h @@ -14,6 +14,7 @@  #define _ATH79_PCI_H  struct ath79_pci_irq { +	int	bus;  	u8	slot;  	u8	pin;  	int	irq; diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 60d212ef862..d5b3c905701 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -164,13 +164,29 @@ static void __init ath79_detect_sys_type(void)  		rev = id & AR934X_REV_ID_REVISION_MASK;  		break; +	case REV_ID_MAJOR_QCA9556: +		ath79_soc = ATH79_SOC_QCA9556; +		chip = "9556"; +		rev = id & QCA955X_REV_ID_REVISION_MASK; +		break; + +	case REV_ID_MAJOR_QCA9558: +		ath79_soc = ATH79_SOC_QCA9558; +		chip = "9558"; +		rev = id & QCA955X_REV_ID_REVISION_MASK; +		break; +  	default:  		panic("ath79: unknown SoC, id:0x%08x", id);  	}  	ath79_soc_rev = rev; -	sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); +	if (soc_is_qca955x()) +		sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s rev %u", +			chip, rev); +	else +		sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);  	pr_info("SoC: %s\n", ath79_sys_type);  } diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index c37419c11c9..cc40b74940f 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -3,7 +3,7 @@   *   * Copyright (C) 2005 Broadcom Corporation   * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> - * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de> + * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>   *   * This program is free software; you can redistribute	it and/or modify it   * under  the terms of	the GNU General	 Public License as published by the @@ -18,83 +18,160 @@  #include <linux/kernel.h>  #include <linux/string.h>  #include <asm/addrspace.h> -#include <asm/mach-bcm47xx/nvram.h> +#include <bcm47xx_nvram.h>  #include <asm/mach-bcm47xx/bcm47xx.h>  static char nvram_buf[NVRAM_SPACE]; +static u32 find_nvram_size(u32 end) +{ +	struct nvram_header *header; +	u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; +	int i; + +	for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { +		header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]); +		if (header->magic == NVRAM_HEADER) +			return nvram_sizes[i]; +	} + +	return 0; +} +  /* Probe for NVRAM header */ -static void early_nvram_init(void) +static int nvram_find_and_copy(u32 base, u32 lim)  { -#ifdef CONFIG_BCM47XX_SSB -	struct ssb_mipscore *mcore_ssb; -#endif -#ifdef CONFIG_BCM47XX_BCMA -	struct bcma_drv_cc *bcma_cc; -#endif  	struct nvram_header *header;  	int i; -	u32 base = 0; -	u32 lim = 0;  	u32 off;  	u32 *src, *dst; +	u32 size; -	switch (bcm47xx_bus_type) { -#ifdef CONFIG_BCM47XX_SSB -	case BCM47XX_BUS_TYPE_SSB: -		mcore_ssb = &bcm47xx_bus.ssb.mipscore; -		base = mcore_ssb->pflash.window; -		lim = mcore_ssb->pflash.window_size; -		break; -#endif -#ifdef CONFIG_BCM47XX_BCMA -	case BCM47XX_BUS_TYPE_BCMA: -		bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; -		base = bcma_cc->pflash.window; -		lim = bcma_cc->pflash.window_size; -		break; -#endif -	} - +	/* TODO: when nvram is on nand flash check for bad blocks first. */  	off = FLASH_MIN;  	while (off <= lim) {  		/* Windowed flash access */ -		header = (struct nvram_header *) -			KSEG1ADDR(base + off - NVRAM_SPACE); -		if (header->magic == NVRAM_HEADER) +		size = find_nvram_size(base + off); +		if (size) { +			header = (struct nvram_header *)KSEG1ADDR(base + off - +								  size);  			goto found; +		}  		off <<= 1;  	}  	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */  	header = (struct nvram_header *) KSEG1ADDR(base + 4096); -	if (header->magic == NVRAM_HEADER) +	if (header->magic == NVRAM_HEADER) { +		size = NVRAM_SPACE;  		goto found; +	}  	header = (struct nvram_header *) KSEG1ADDR(base + 1024); -	if (header->magic == NVRAM_HEADER) +	if (header->magic == NVRAM_HEADER) { +		size = NVRAM_SPACE;  		goto found; +	} -	return; +	pr_err("no nvram found\n"); +	return -ENXIO;  found: + +	if (header->len > size) +		pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n"); +	if (header->len > NVRAM_SPACE) +		pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", +		       header->len, NVRAM_SPACE); +  	src = (u32 *) header;  	dst = (u32 *) nvram_buf;  	for (i = 0; i < sizeof(struct nvram_header); i += 4)  		*dst++ = *src++; -	for (; i < header->len && i < NVRAM_SPACE; i += 4) +	for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4)  		*dst++ = le32_to_cpu(*src++); +	memset(dst, 0x0, NVRAM_SPACE - i); + +	return 0;  } -int nvram_getenv(char *name, char *val, size_t val_len) +#ifdef CONFIG_BCM47XX_SSB +static int nvram_init_ssb(void) +{ +	struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; +	u32 base; +	u32 lim; + +	if (mcore->pflash.present) { +		base = mcore->pflash.window; +		lim = mcore->pflash.window_size; +	} else { +		pr_err("Couldn't find supported flash memory\n"); +		return -ENXIO; +	} + +	return nvram_find_and_copy(base, lim); +} +#endif + +#ifdef CONFIG_BCM47XX_BCMA +static int nvram_init_bcma(void) +{ +	struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc; +	u32 base; +	u32 lim; + +#ifdef CONFIG_BCMA_NFLASH +	if (cc->nflash.boot) { +		base = BCMA_SOC_FLASH1; +		lim = BCMA_SOC_FLASH1_SZ; +	} else +#endif +	if (cc->pflash.present) { +		base = cc->pflash.window; +		lim = cc->pflash.window_size; +#ifdef CONFIG_BCMA_SFLASH +	} else if (cc->sflash.present) { +		base = cc->sflash.window; +		lim = cc->sflash.size; +#endif +	} else { +		pr_err("Couldn't find supported flash memory\n"); +		return -ENXIO; +	} + +	return nvram_find_and_copy(base, lim); +} +#endif + +static int nvram_init(void) +{ +	switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB +	case BCM47XX_BUS_TYPE_SSB: +		return nvram_init_ssb(); +#endif +#ifdef CONFIG_BCM47XX_BCMA +	case BCM47XX_BUS_TYPE_BCMA: +		return nvram_init_bcma(); +#endif +	} +	return -ENXIO; +} + +int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)  {  	char *var, *value, *end, *eq; +	int err;  	if (!name) -		return NVRAM_ERR_INV_PARAM; +		return -EINVAL; -	if (!nvram_buf[0]) -		early_nvram_init(); +	if (!nvram_buf[0]) { +		err = nvram_init(); +		if (err) +			return err; +	}  	/* Look for name=value and return value */  	var = &nvram_buf[sizeof(struct nvram_header)]; @@ -110,6 +187,6 @@ int nvram_getenv(char *name, char *val, size_t val_len)  			return snprintf(val, val_len, "%s", value);  		}  	} -	return NVRAM_ERR_ENVNOTFOUND; +	return -ENOENT;  } -EXPORT_SYMBOL(nvram_getenv); +EXPORT_SYMBOL(bcm47xx_nvram_getenv); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 4d54b58dbd3..b2246cd9ca1 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -35,7 +35,7 @@  #include <asm/reboot.h>  #include <asm/time.h>  #include <bcm47xx.h> -#include <asm/mach-bcm47xx/nvram.h> +#include <bcm47xx_nvram.h>  union bcm47xx_bus bcm47xx_bus;  EXPORT_SYMBOL(bcm47xx_bus); @@ -115,7 +115,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,  	memset(&iv->sprom, 0, sizeof(struct ssb_sprom));  	bcm47xx_fill_sprom(&iv->sprom, NULL, false); -	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) +	if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)  		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);  	return 0; @@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb(void)  		panic("Failed to initialize SSB bus (err %d)", err);  	mcore = &bcm47xx_bus.ssb.mipscore; -	if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { +	if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {  		if (strstr(buf, "console=ttyS1")) {  			struct ssb_serial_port port; diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index b2a7c251e47..ad03c931b90 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -27,7 +27,7 @@   */  #include <bcm47xx.h> -#include <nvram.h> +#include <bcm47xx_nvram.h>  static void create_key(const char *prefix, const char *postfix,  		       const char *name, char *buf, int len) @@ -50,10 +50,10 @@ static int get_nvram_var(const char *prefix, const char *postfix,  	create_key(prefix, postfix, name, key, sizeof(key)); -	err = nvram_getenv(key, buf, len); -	if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) { +	err = bcm47xx_nvram_getenv(key, buf, len); +	if (fallback && err == -ENOENT && prefix) {  		create_key(NULL, postfix, name, key, sizeof(key)); -		err = nvram_getenv(key, buf, len); +		err = bcm47xx_nvram_getenv(key, buf, len);  	}  	return err;  } @@ -71,7 +71,7 @@ static void nvram_read_ ## type (const char *prefix,			\  			    fallback);					\  	if (err < 0)							\  		return;							\ -	err = kstrto ## type (buf, 0, &var);				\ +	err = kstrto ## type(strim(buf), 0, &var);			\  	if (err) {							\  		pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",	\  			prefix, name, postfix, buf, err);		\ @@ -99,7 +99,7 @@ static void nvram_read_u32_2(const char *prefix, const char *name,  	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);  	if (err < 0)  		return; -	err = kstrtou32(buf, 0, &val); +	err = kstrtou32(strim(buf), 0, &val);  	if (err) {  		pr_warn("can not parse nvram name %s%s with value %s got %i\n",  			prefix, name, buf, err); @@ -120,7 +120,7 @@ static void nvram_read_leddc(const char *prefix, const char *name,  	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);  	if (err < 0)  		return; -	err = kstrtou32(buf, 0, &val); +	err = kstrtou32(strim(buf), 0, &val);  	if (err) {  		pr_warn("can not parse nvram name %s%s with value %s got %i\n",  			prefix, name, buf, err); @@ -144,7 +144,7 @@ static void nvram_read_macaddr(const char *prefix, const char *name,  	if (err < 0)  		return; -	nvram_parse_macaddr(buf, *val); +	bcm47xx_nvram_parse_macaddr(buf, *val);  }  static void nvram_read_alpha2(const char *prefix, const char *name, @@ -652,12 +652,10 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,  static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,  				    bool fallback)  { -	nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, -		       fallback); +	nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, true);  	nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0,  		       fallback); -	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, -		       fallback); +	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, true);  	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,  			 &sprom->boardflags_hi, fallback);  	nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, diff --git a/arch/mips/bcm63xx/early_printk.c b/arch/mips/bcm63xx/early_printk.c index bf353c937df..aa8f7f9cc7a 100644 --- a/arch/mips/bcm63xx/early_printk.c +++ b/arch/mips/bcm63xx/early_printk.c @@ -10,7 +10,7 @@  #include <bcm63xx_io.h>  #include <bcm63xx_regs.h> -static void __init wait_xfered(void) +static void wait_xfered(void)  {  	unsigned int val; @@ -22,7 +22,7 @@ static void __init wait_xfered(void)  	} while (1);  } -void __init prom_putchar(char c) +void prom_putchar(char c)  {  	wait_xfered();  	bcm_uart0_writel(c, UART_FIFO_REG); diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig index ea87d43ba60..e3a3836508e 100644 --- a/arch/mips/configs/ath79_defconfig +++ b/arch/mips/configs/ath79_defconfig @@ -1,5 +1,6 @@  CONFIG_ATH79=y  CONFIG_ATH79_MACH_AP121=y +CONFIG_ATH79_MACH_AP136=y  CONFIG_ATH79_MACH_AP81=y  CONFIG_ATH79_MACH_DB120=y  CONFIG_ATH79_MACH_PB44=y diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig new file mode 100644 index 00000000000..d1741bcf894 --- /dev/null +++ b/arch/mips/configs/rt305x_defconfig @@ -0,0 +1,167 @@ +CONFIG_RALINK=y +CONFIG_DTB_RT305X_EVAL=y +CONFIG_CPU_MIPS32_R2=y +# CONFIG_COMPACTION is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_HZ_100=y +# CONFIG_SECCOMP is not set +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INITRAMFS_ROOT_UID=1000 +CONFIG_INITRAMFS_ROOT_GID=1000 +# CONFIG_RD_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_AIO is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_COREDUMP is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_BRIDGE_NETFILTER is not set +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_RAW=m +CONFIG_BRIDGE=y +# CONFIG_BRIDGE_IGMP_SNOOPING is not set +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_HAMRADIO=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_M25P80=y +CONFIG_EEPROM_93CX6=m +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y +CONFIG_PPP=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPP_ASYNC=m +CONFIG_ISDN=y +CONFIG_INPUT=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SPI=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_HID is not set +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_STAGING=y +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +# CONFIG_JFFS2_FS_POSIX_ACL is not set +# CONFIG_JFFS2_FS_SECURITY is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +# CONFIG_JFFS2_ZLIB is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_ZLIB is not set +CONFIG_SQUASHFS_XZ=y +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +CONFIG_DEBUG_FS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_ITU_T=m +CONFIG_CRC32_SARWATE=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_AVERAGE=y diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 1e83b24fa46..1a57e8b4d09 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -98,6 +98,9 @@  #ifndef cpu_has_rixi  #define cpu_has_rixi		(cpu_data[0].options & MIPS_CPU_RIXI)  #endif +#ifndef cpu_has_mmips +#define cpu_has_mmips		(cpu_data[0].options & MIPS_CPU_MICROMIPS) +#endif  #ifndef cpu_has_vtag_icache  #define cpu_has_vtag_icache	(cpu_data[0].icache.flags & MIPS_CACHE_VTAG)  #endif @@ -273,4 +276,8 @@  #define cpu_has_perf_cntr_intr_bit	(cpu_data[0].options & MIPS_CPU_PCI)  #endif +#ifndef cpu_has_vz +#define cpu_has_vz		(cpu_data[0].ases & MIPS_ASE_VZ) +#endif +  #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 9904697bd79..dd86ab20548 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -96,6 +96,7 @@  #define PRID_IMP_1004K		0x9900  #define PRID_IMP_1074K		0x9a00  #define PRID_IMP_M14KC		0x9c00 +#define PRID_IMP_M14KEC		0x9e00  /*   * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE @@ -264,6 +265,7 @@ enum cpu_type_enum {  	CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,  	CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,  	CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, +	CPU_M14KEC,  	/*  	 * MIPS64 class processors @@ -322,6 +324,7 @@ enum cpu_type_enum {  #define MIPS_CPU_ULRI		0x00200000 /* CPU has ULRI feature */  #define MIPS_CPU_PCI		0x00400000 /* CPU has Perf Ctr Int indicator */  #define MIPS_CPU_RIXI		0x00800000 /* CPU has TLB Read/eXec Inhibit */ +#define MIPS_CPU_MICROMIPS	0x01000000 /* CPU has microMIPS capability */  /*   * CPU ASE encodings @@ -333,6 +336,6 @@ enum cpu_type_enum {  #define MIPS_ASE_DSP		0x00000010 /* Signal Processing ASE */  #define MIPS_ASE_MIPSMT		0x00000020 /* CPU supports MIPS MT */  #define MIPS_ASE_DSP2P		0x00000040 /* Signal Processing ASE Rev 2 */ - +#define MIPS_ASE_VZ		0x00000080 /* Virtualization ASE */  #endif /* _ASM_CPU_H */ diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 61b06d7e7de..bdc9786ab5a 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -359,6 +359,7 @@ struct gic_shared_intr_map {  /* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */  #define GIC_PIN_TO_VEC_OFFSET	(1) +extern int gic_present;  extern unsigned long _gic_base;  extern unsigned int gic_irq_base;  extern unsigned int gic_irq_flags[]; diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 568544b6e85..44d6a5bde4a 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -141,7 +141,7 @@ do {									\  #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \  	defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \ -	defined(CONFIG_CPU_R5500) +	defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)  /*   * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. diff --git a/arch/mips/include/asm/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h index ef6a07cddb2..3f11fdb3ed8 100644 --- a/arch/mips/include/asm/irq_cpu.h +++ b/arch/mips/include/asm/irq_cpu.h @@ -17,4 +17,10 @@ extern void mips_cpu_irq_init(void);  extern void rm7k_cpu_irq_init(void);  extern void rm9k_cpu_irq_init(void); +#ifdef CONFIG_IRQ_DOMAIN +struct device_node; +extern int mips_cpu_intc_init(struct device_node *of_node, +			      struct device_node *parent); +#endif +  #endif /* _ASM_IRQ_CPU_H */ diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h index 8dec938af11..b86a1253a5b 100644 --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h @@ -41,11 +41,37 @@  #define AR71XX_RESET_BASE	(AR71XX_APB_BASE + 0x00060000)  #define AR71XX_RESET_SIZE	0x100 +#define AR71XX_PCI_MEM_BASE	0x10000000 +#define AR71XX_PCI_MEM_SIZE	0x07000000 + +#define AR71XX_PCI_WIN0_OFFS	0x10000000 +#define AR71XX_PCI_WIN1_OFFS	0x11000000 +#define AR71XX_PCI_WIN2_OFFS	0x12000000 +#define AR71XX_PCI_WIN3_OFFS	0x13000000 +#define AR71XX_PCI_WIN4_OFFS	0x14000000 +#define AR71XX_PCI_WIN5_OFFS	0x15000000 +#define AR71XX_PCI_WIN6_OFFS	0x16000000 +#define AR71XX_PCI_WIN7_OFFS	0x07000000 + +#define AR71XX_PCI_CFG_BASE	\ +	(AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) +#define AR71XX_PCI_CFG_SIZE	0x100 +  #define AR7240_USB_CTRL_BASE	(AR71XX_APB_BASE + 0x00030000)  #define AR7240_USB_CTRL_SIZE	0x100  #define AR7240_OHCI_BASE	0x1b000000  #define AR7240_OHCI_SIZE	0x1000 +#define AR724X_PCI_MEM_BASE	0x10000000 +#define AR724X_PCI_MEM_SIZE	0x04000000 + +#define AR724X_PCI_CFG_BASE	0x14000000 +#define AR724X_PCI_CFG_SIZE	0x1000 +#define AR724X_PCI_CRP_BASE	(AR71XX_APB_BASE + 0x000c0000) +#define AR724X_PCI_CRP_SIZE	0x1000 +#define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000) +#define AR724X_PCI_CTRL_SIZE	0x100 +  #define AR724X_EHCI_BASE	0x1b000000  #define AR724X_EHCI_SIZE	0x1000 @@ -68,6 +94,25 @@  #define AR934X_SRIF_BASE	(AR71XX_APB_BASE + 0x00116000)  #define AR934X_SRIF_SIZE	0x1000 +#define QCA955X_PCI_MEM_BASE0	0x10000000 +#define QCA955X_PCI_MEM_BASE1	0x12000000 +#define QCA955X_PCI_MEM_SIZE	0x02000000 +#define QCA955X_PCI_CFG_BASE0	0x14000000 +#define QCA955X_PCI_CFG_BASE1	0x16000000 +#define QCA955X_PCI_CFG_SIZE	0x1000 +#define QCA955X_PCI_CRP_BASE0	(AR71XX_APB_BASE + 0x000c0000) +#define QCA955X_PCI_CRP_BASE1	(AR71XX_APB_BASE + 0x00250000) +#define QCA955X_PCI_CRP_SIZE	0x1000 +#define QCA955X_PCI_CTRL_BASE0	(AR71XX_APB_BASE + 0x000f0000) +#define QCA955X_PCI_CTRL_BASE1	(AR71XX_APB_BASE + 0x00280000) +#define QCA955X_PCI_CTRL_SIZE	0x100 + +#define QCA955X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000) +#define QCA955X_WMAC_SIZE	0x20000 +#define QCA955X_EHCI0_BASE	0x1b000000 +#define QCA955X_EHCI1_BASE	0x1b400000 +#define QCA955X_EHCI_SIZE	0x1000 +  /*   * DDR_CTRL block   */ @@ -199,6 +244,41 @@  #define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL	BIT(21)  #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL	BIT(24) +#define QCA955X_PLL_CPU_CONFIG_REG		0x00 +#define QCA955X_PLL_DDR_CONFIG_REG		0x04 +#define QCA955X_PLL_CLK_CTRL_REG		0x08 + +#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT	0 +#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK	0x3f +#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT	6 +#define QCA955X_PLL_CPU_CONFIG_NINT_MASK	0x3f +#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT	12 +#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK	0x1f +#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT	19 +#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK	0x3 + +#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT	0 +#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK	0x3ff +#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT	10 +#define QCA955X_PLL_DDR_CONFIG_NINT_MASK	0x3f +#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT	16 +#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK	0x1f +#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT	23 +#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK	0x7 + +#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS		BIT(2) +#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS		BIT(3) +#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS		BIT(4) +#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT		5 +#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK		0x1f +#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT		10 +#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK		0x1f +#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT		15 +#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK		0x1f +#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL		BIT(20) +#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL		BIT(21) +#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL		BIT(24) +  /*   * USB_CONFIG block   */ @@ -238,6 +318,10 @@  #define AR934X_RESET_REG_BOOTSTRAP		0xb0  #define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS	0xac +#define QCA955X_RESET_REG_RESET_MODULE		0x1c +#define QCA955X_RESET_REG_BOOTSTRAP		0xb0 +#define QCA955X_RESET_REG_EXT_INT_STATUS	0xac +  #define MISC_INT_ETHSW			BIT(12)  #define MISC_INT_TIMER4			BIT(10)  #define MISC_INT_TIMER3			BIT(9) @@ -315,6 +399,8 @@  #define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1)  #define AR934X_BOOTSTRAP_DDR1		BIT(0) +#define QCA955X_BOOTSTRAP_REF_CLK_40	BIT(4) +  #define AR934X_PCIE_WMAC_INT_WMAC_MISC		BIT(0)  #define AR934X_PCIE_WMAC_INT_WMAC_TX		BIT(1)  #define AR934X_PCIE_WMAC_INT_WMAC_RXLP		BIT(2) @@ -333,6 +419,37 @@  	 AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \  	 AR934X_PCIE_WMAC_INT_PCIE_RC3) +#define QCA955X_EXT_INT_WMAC_MISC		BIT(0) +#define QCA955X_EXT_INT_WMAC_TX			BIT(1) +#define QCA955X_EXT_INT_WMAC_RXLP		BIT(2) +#define QCA955X_EXT_INT_WMAC_RXHP		BIT(3) +#define QCA955X_EXT_INT_PCIE_RC1		BIT(4) +#define QCA955X_EXT_INT_PCIE_RC1_INT0		BIT(5) +#define QCA955X_EXT_INT_PCIE_RC1_INT1		BIT(6) +#define QCA955X_EXT_INT_PCIE_RC1_INT2		BIT(7) +#define QCA955X_EXT_INT_PCIE_RC1_INT3		BIT(8) +#define QCA955X_EXT_INT_PCIE_RC2		BIT(12) +#define QCA955X_EXT_INT_PCIE_RC2_INT0		BIT(13) +#define QCA955X_EXT_INT_PCIE_RC2_INT1		BIT(14) +#define QCA955X_EXT_INT_PCIE_RC2_INT2		BIT(15) +#define QCA955X_EXT_INT_PCIE_RC2_INT3		BIT(16) +#define QCA955X_EXT_INT_USB1			BIT(24) +#define QCA955X_EXT_INT_USB2			BIT(28) + +#define QCA955X_EXT_INT_WMAC_ALL \ +	(QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \ +	 QCA955X_EXT_INT_WMAC_RXLP | QCA955X_EXT_INT_WMAC_RXHP) + +#define QCA955X_EXT_INT_PCIE_RC1_ALL \ +	(QCA955X_EXT_INT_PCIE_RC1 | QCA955X_EXT_INT_PCIE_RC1_INT0 | \ +	 QCA955X_EXT_INT_PCIE_RC1_INT1 | QCA955X_EXT_INT_PCIE_RC1_INT2 | \ +	 QCA955X_EXT_INT_PCIE_RC1_INT3) + +#define QCA955X_EXT_INT_PCIE_RC2_ALL \ +	(QCA955X_EXT_INT_PCIE_RC2 | QCA955X_EXT_INT_PCIE_RC2_INT0 | \ +	 QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \ +	 QCA955X_EXT_INT_PCIE_RC2_INT3) +  #define REV_ID_MAJOR_MASK		0xfff0  #define REV_ID_MAJOR_AR71XX		0x00a0  #define REV_ID_MAJOR_AR913X		0x00b0 @@ -344,6 +461,8 @@  #define REV_ID_MAJOR_AR9341		0x0120  #define REV_ID_MAJOR_AR9342		0x1120  #define REV_ID_MAJOR_AR9344		0x2120 +#define REV_ID_MAJOR_QCA9556		0x0130 +#define REV_ID_MAJOR_QCA9558		0x1130  #define AR71XX_REV_ID_MINOR_MASK	0x3  #define AR71XX_REV_ID_MINOR_AR7130	0x0 @@ -364,6 +483,8 @@  #define AR934X_REV_ID_REVISION_MASK	0xf +#define QCA955X_REV_ID_REVISION_MASK	0xf +  /*   * SPI block   */ @@ -401,12 +522,15 @@  #define AR71XX_GPIO_REG_INT_ENABLE	0x24  #define AR71XX_GPIO_REG_FUNC		0x28 +#define AR934X_GPIO_REG_FUNC		0x6c +  #define AR71XX_GPIO_COUNT		16  #define AR7240_GPIO_COUNT		18  #define AR7241_GPIO_COUNT		20  #define AR913X_GPIO_COUNT		22  #define AR933X_GPIO_COUNT		30  #define AR934X_GPIO_COUNT		23 +#define QCA955X_GPIO_COUNT		24  /*   * SRIF block diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h index 4f248c3d7b2..1557934aaca 100644 --- a/arch/mips/include/asm/mach-ath79/ath79.h +++ b/arch/mips/include/asm/mach-ath79/ath79.h @@ -32,6 +32,8 @@ enum ath79_soc_type {  	ATH79_SOC_AR9341,  	ATH79_SOC_AR9342,  	ATH79_SOC_AR9344, +	ATH79_SOC_QCA9556, +	ATH79_SOC_QCA9558,  };  extern enum ath79_soc_type ath79_soc; @@ -98,6 +100,21 @@ static inline int soc_is_ar934x(void)  	return soc_is_ar9341() || soc_is_ar9342() || soc_is_ar9344();  } +static inline int soc_is_qca9556(void) +{ +	return ath79_soc == ATH79_SOC_QCA9556; +} + +static inline int soc_is_qca9558(void) +{ +	return ath79_soc == ATH79_SOC_QCA9558; +} + +static inline int soc_is_qca955x(void) +{ +	return soc_is_qca9556() || soc_is_qca9558(); +} +  extern void __iomem *ath79_ddr_base;  extern void __iomem *ath79_pll_base;  extern void __iomem *ath79_reset_base; diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h index 0968f69e201..5c9ca76a7eb 100644 --- a/arch/mips/include/asm/mach-ath79/irq.h +++ b/arch/mips/include/asm/mach-ath79/irq.h @@ -10,10 +10,13 @@  #define __ASM_MACH_ATH79_IRQ_H  #define MIPS_CPU_IRQ_BASE	0 -#define NR_IRQS			48 +#define NR_IRQS			51 + +#define ATH79_CPU_IRQ(_x)	(MIPS_CPU_IRQ_BASE + (_x))  #define ATH79_MISC_IRQ_BASE	8  #define ATH79_MISC_IRQ_COUNT	32 +#define ATH79_MISC_IRQ(_x)	(ATH79_MISC_IRQ_BASE + (_x))  #define ATH79_PCI_IRQ_BASE	(ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)  #define ATH79_PCI_IRQ_COUNT	6 @@ -23,25 +26,9 @@  #define ATH79_IP2_IRQ_COUNT	2  #define ATH79_IP2_IRQ(_x)	(ATH79_IP2_IRQ_BASE + (_x)) -#define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2) -#define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3) -#define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4) -#define ATH79_CPU_IRQ_GE1	(MIPS_CPU_IRQ_BASE + 5) -#define ATH79_CPU_IRQ_MISC	(MIPS_CPU_IRQ_BASE + 6) -#define ATH79_CPU_IRQ_TIMER	(MIPS_CPU_IRQ_BASE + 7) - -#define ATH79_MISC_IRQ_TIMER	(ATH79_MISC_IRQ_BASE + 0) -#define ATH79_MISC_IRQ_ERROR	(ATH79_MISC_IRQ_BASE + 1) -#define ATH79_MISC_IRQ_GPIO	(ATH79_MISC_IRQ_BASE + 2) -#define ATH79_MISC_IRQ_UART	(ATH79_MISC_IRQ_BASE + 3) -#define ATH79_MISC_IRQ_WDOG	(ATH79_MISC_IRQ_BASE + 4) -#define ATH79_MISC_IRQ_PERFC	(ATH79_MISC_IRQ_BASE + 5) -#define ATH79_MISC_IRQ_OHCI	(ATH79_MISC_IRQ_BASE + 6) -#define ATH79_MISC_IRQ_DMA	(ATH79_MISC_IRQ_BASE + 7) -#define ATH79_MISC_IRQ_TIMER2	(ATH79_MISC_IRQ_BASE + 8) -#define ATH79_MISC_IRQ_TIMER3	(ATH79_MISC_IRQ_BASE + 9) -#define ATH79_MISC_IRQ_TIMER4	(ATH79_MISC_IRQ_BASE + 10) -#define ATH79_MISC_IRQ_ETHSW	(ATH79_MISC_IRQ_BASE + 12) +#define ATH79_IP3_IRQ_BASE	(ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT) +#define ATH79_IP3_IRQ_COUNT     3 +#define ATH79_IP3_IRQ(_x)       (ATH79_IP3_IRQ_BASE + (_x))  #include_next <irq.h> diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h deleted file mode 100644 index 7868f7fa028..00000000000 --- a/arch/mips/include/asm/mach-ath79/pci.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - *  Atheros AR71XX/AR724X PCI support - * - *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com> - *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> - *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> - * - *  This program is free software; you can redistribute it and/or modify it - *  under the terms of the GNU General Public License version 2 as published - *  by the Free Software Foundation. - */ - -#ifndef __ASM_MACH_ATH79_PCI_H -#define __ASM_MACH_ATH79_PCI_H - -#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR71XX) -int ar71xx_pcibios_init(void); -#else -static inline int ar71xx_pcibios_init(void) { return 0; } -#endif - -#if defined(CONFIG_PCI_AR724X) -int ar724x_pcibios_init(int irq); -#else -static inline int ar724x_pcibios_init(int irq) { return 0; } -#endif - -#endif /* __ASM_MACH_ATH79_PCI_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h index 69ef3efe06e..b8e7be8f34d 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h @@ -8,8 +8,8 @@   *  option) any later version.   */ -#ifndef __NVRAM_H -#define __NVRAM_H +#ifndef __BCM47XX_NVRAM_H +#define __BCM47XX_NVRAM_H  #include <linux/types.h>  #include <linux/kernel.h> @@ -32,12 +32,9 @@ struct nvram_header {  #define NVRAM_MAX_VALUE_LEN 255  #define NVRAM_MAX_PARAM_LEN 64 -#define NVRAM_ERR_INV_PARAM	-8 -#define NVRAM_ERR_ENVNOTFOUND	-9 +extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len); -extern int nvram_getenv(char *name, char *val, size_t val_len); - -static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6]) +static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])  {  	if (strchr(buf, ':'))  		sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], @@ -51,4 +48,4 @@ static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])  		printk(KERN_WARNING "Can not parse mac address: %s\n", buf);  } -#endif +#endif /* __BCM47XX_NVRAM_H */ diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h index 5e8a6e96575..f196cceb732 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq.h @@ -34,6 +34,7 @@ extern spinlock_t ebu_lock;  extern void ltq_disable_irq(struct irq_data *data);  extern void ltq_mask_and_ack_irq(struct irq_data *data);  extern void ltq_enable_irq(struct irq_data *data); +extern int ltq_eiu_get_irq(int exin);  /* clock handling */  extern int clk_activate(struct clk *clk); @@ -41,6 +42,7 @@ extern void clk_deactivate(struct clk *clk);  extern struct clk *clk_get_cpu(void);  extern struct clk *clk_get_fpi(void);  extern struct clk *clk_get_io(void); +extern struct clk *clk_get_ppe(void);  /* find out what bootsource we have */  extern unsigned char ltq_boot_select(void); diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h new file mode 100644 index 00000000000..5a508f9f943 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h @@ -0,0 +1,39 @@ +/* + *  Ralink SoC register definitions + * + *  Copyright (C) 2013 John Crispin <blogic@openwrt.org> + *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> + *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License version 2 as published + *  by the Free Software Foundation. + */ + +#ifndef _RALINK_REGS_H_ +#define _RALINK_REGS_H_ + +extern __iomem void *rt_sysc_membase; +extern __iomem void *rt_memc_membase; + +static inline void rt_sysc_w32(u32 val, unsigned reg) +{ +	__raw_writel(val, rt_sysc_membase + reg); +} + +static inline u32 rt_sysc_r32(unsigned reg) +{ +	return __raw_readl(rt_sysc_membase + reg); +} + +static inline void rt_memc_w32(u32 val, unsigned reg) +{ +	__raw_writel(val, rt_memc_membase + reg); +} + +static inline u32 rt_memc_r32(unsigned reg) +{ +	return __raw_readl(rt_memc_membase + reg); +} + +#endif /* _RALINK_REGS_H_ */ diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h new file mode 100644 index 00000000000..7d344f2d7d0 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -0,0 +1,139 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RT305X_REGS_H_ +#define _RT305X_REGS_H_ + +enum rt305x_soc_type { +	RT305X_SOC_UNKNOWN = 0, +	RT305X_SOC_RT3050, +	RT305X_SOC_RT3052, +	RT305X_SOC_RT3350, +	RT305X_SOC_RT3352, +	RT305X_SOC_RT5350, +}; + +extern enum rt305x_soc_type rt305x_soc; + +static inline int soc_is_rt3050(void) +{ +	return rt305x_soc == RT305X_SOC_RT3050; +} + +static inline int soc_is_rt3052(void) +{ +	return rt305x_soc == RT305X_SOC_RT3052; +} + +static inline int soc_is_rt305x(void) +{ +	return soc_is_rt3050() || soc_is_rt3052(); +} + +static inline int soc_is_rt3350(void) +{ +	return rt305x_soc == RT305X_SOC_RT3350; +} + +static inline int soc_is_rt3352(void) +{ +	return rt305x_soc == RT305X_SOC_RT3352; +} + +static inline int soc_is_rt5350(void) +{ +	return rt305x_soc == RT305X_SOC_RT5350; +} + +#define RT305X_SYSC_BASE		0x10000000 + +#define SYSC_REG_CHIP_NAME0		0x00 +#define SYSC_REG_CHIP_NAME1		0x04 +#define SYSC_REG_CHIP_ID		0x0c +#define SYSC_REG_SYSTEM_CONFIG		0x10 + +#define RT3052_CHIP_NAME0		0x30335452 +#define RT3052_CHIP_NAME1		0x20203235 + +#define RT3350_CHIP_NAME0		0x33335452 +#define RT3350_CHIP_NAME1		0x20203035 + +#define RT3352_CHIP_NAME0		0x33335452 +#define RT3352_CHIP_NAME1		0x20203235 + +#define RT5350_CHIP_NAME0		0x33355452 +#define RT5350_CHIP_NAME1		0x20203035 + +#define CHIP_ID_ID_MASK			0xff +#define CHIP_ID_ID_SHIFT		8 +#define CHIP_ID_REV_MASK		0xff + +#define RT305X_SYSCFG_CPUCLK_SHIFT		18 +#define RT305X_SYSCFG_CPUCLK_MASK		0x1 +#define RT305X_SYSCFG_CPUCLK_LOW		0x0 +#define RT305X_SYSCFG_CPUCLK_HIGH		0x1 + +#define RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT	2 +#define RT305X_SYSCFG_CPUCLK_MASK		0x1 +#define RT305X_SYSCFG_SRAM_CS0_MODE_WDT		0x1 + +#define RT3352_SYSCFG0_CPUCLK_SHIFT	8 +#define RT3352_SYSCFG0_CPUCLK_MASK	0x1 +#define RT3352_SYSCFG0_CPUCLK_LOW	0x0 +#define RT3352_SYSCFG0_CPUCLK_HIGH	0x1 + +#define RT5350_SYSCFG0_CPUCLK_SHIFT	8 +#define RT5350_SYSCFG0_CPUCLK_MASK	0x3 +#define RT5350_SYSCFG0_CPUCLK_360	0x0 +#define RT5350_SYSCFG0_CPUCLK_320	0x2 +#define RT5350_SYSCFG0_CPUCLK_300	0x3 + +/* multi function gpio pins */ +#define RT305X_GPIO_I2C_SD		1 +#define RT305X_GPIO_I2C_SCLK		2 +#define RT305X_GPIO_SPI_EN		3 +#define RT305X_GPIO_SPI_CLK		4 +/* GPIO 7-14 is shared between UART0, PCM  and I2S interfaces */ +#define RT305X_GPIO_7			7 +#define RT305X_GPIO_10			10 +#define RT305X_GPIO_14			14 +#define RT305X_GPIO_UART1_TXD		15 +#define RT305X_GPIO_UART1_RXD		16 +#define RT305X_GPIO_JTAG_TDO		17 +#define RT305X_GPIO_JTAG_TDI		18 +#define RT305X_GPIO_MDIO_MDC		22 +#define RT305X_GPIO_MDIO_MDIO		23 +#define RT305X_GPIO_SDRAM_MD16		24 +#define RT305X_GPIO_SDRAM_MD31		39 +#define RT305X_GPIO_GE0_TXD0		40 +#define RT305X_GPIO_GE0_RXCLK		51 + +#define RT305X_GPIO_MODE_I2C		BIT(0) +#define RT305X_GPIO_MODE_SPI		BIT(1) +#define RT305X_GPIO_MODE_UART0_SHIFT	2 +#define RT305X_GPIO_MODE_UART0_MASK	0x7 +#define RT305X_GPIO_MODE_UART0(x)	((x) << RT305X_GPIO_MODE_UART0_SHIFT) +#define RT305X_GPIO_MODE_UARTF		0x0 +#define RT305X_GPIO_MODE_PCM_UARTF	0x1 +#define RT305X_GPIO_MODE_PCM_I2S	0x2 +#define RT305X_GPIO_MODE_I2S_UARTF	0x3 +#define RT305X_GPIO_MODE_PCM_GPIO	0x4 +#define RT305X_GPIO_MODE_GPIO_UARTF	0x5 +#define RT305X_GPIO_MODE_GPIO_I2S	0x6 +#define RT305X_GPIO_MODE_GPIO		0x7 +#define RT305X_GPIO_MODE_UART1		BIT(5) +#define RT305X_GPIO_MODE_JTAG		BIT(6) +#define RT305X_GPIO_MODE_MDIO		BIT(7) +#define RT305X_GPIO_MODE_SDRAM		BIT(8) +#define RT305X_GPIO_MODE_RGMII		BIT(9) + +#endif diff --git a/arch/mips/include/asm/mach-ralink/war.h b/arch/mips/include/asm/mach-ralink/war.h new file mode 100644 index 00000000000..a7b712cf2d2 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> + */ +#ifndef __ASM_MACH_RALINK_WAR_H +#define __ASM_MACH_RALINK_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR	0 +#define R4600_V1_HIT_CACHEOP_WAR	0 +#define R4600_V2_HIT_CACHEOP_WAR	0 +#define R5432_CP0_INTERRUPT_WAR		0 +#define BCM1250_M3_WAR			0 +#define SIBYTE_1956_WAR			0 +#define MIPS4K_ICACHE_REFILL_WAR	0 +#define MIPS_CACHE_SYNC_WAR		0 +#define TX49XX_ICACHE_INDEX_INV_WAR	0 +#define RM9000_CDEX_SMP_WAR		0 +#define ICACHE_REFILLS_WORKAROUND_WAR	0 +#define R10000_LLSC_WAR			0 +#define MIPS34K_MISSED_ITLB_WAR		0 + +#endif /* __ASM_MACH_RALINK_WAR_H */ diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h index 1465b1193b1..44a09a64160 100644 --- a/arch/mips/include/asm/mips-boards/generic.h +++ b/arch/mips/include/asm/mips-boards/generic.h @@ -1,21 +1,14 @@  /* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive   * for more details.   * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - *   * Defines of the MIPS boards specific address-MAP, registers, etc. + * + * Copyright (C) 2000,2012 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard <carstenl@mips.com> + *          Steven J. Hill <sjhill@mips.com>   */  #ifndef __ASM_MIPS_BOARDS_GENERIC_H  #define __ASM_MIPS_BOARDS_GENERIC_H @@ -30,13 +23,6 @@  #define ASCII_DISPLAY_WORD_BASE	   0x1f000410  #define ASCII_DISPLAY_POS_BASE	   0x1f000418 - -/* - * Yamon Prom print address. - */ -#define YAMON_PROM_PRINT_ADDR	   0x1fc00504 - -  /*   * Reset register.   */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 2145162674b..12b70c25906 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -595,6 +595,8 @@  #define MIPS_CONF3_DSP2P	(_ULCAST_(1) << 11)  #define MIPS_CONF3_RXI		(_ULCAST_(1) << 12)  #define MIPS_CONF3_ULRI		(_ULCAST_(1) << 13) +#define MIPS_CONF3_ISA		(_ULCAST_(3) << 14) +#define MIPS_CONF3_VZ		(_ULCAST_(1) << 23)  #define MIPS_CONF4_MMUSIZEEXT	(_ULCAST_(255) << 0)  #define MIPS_CONF4_MMUEXTDEF	(_ULCAST_(3) << 14) @@ -1158,36 +1160,26 @@ do {									\  	__res;								\  }) +#ifdef HAVE_AS_DSP  #define rddsp(mask)							\  ({									\ -	unsigned int __res;						\ +	unsigned int __dspctl;						\  									\  	__asm__ __volatile__(						\ -	"	.set	push				\n"		\ -	"	.set	noat				\n"		\ -	"	# rddsp $1, %x1				\n"		\ -	"	.word	0x7c000cb8 | (%x1 << 16)	\n"		\ -	"	move	%0, $1				\n"		\ -	"	.set	pop				\n"		\ -	: "=r" (__res)							\ +	"	rddsp	%0, %x1					\n"	\ +	: "=r" (__dspctl)						\  	: "i" (mask));							\ -	__res;								\ +	__dspctl;							\  })  #define wrdsp(val, mask)						\  do {									\  	__asm__ __volatile__(						\ -	"	.set	push					\n"	\ -	"	.set	noat					\n"	\ -	"	move	$1, %0					\n"	\ -	"	# wrdsp $1, %x1					\n"	\ -	"	.word	0x7c2004f8 | (%x1 << 11)		\n"	\ -	"	.set	pop					\n"	\ +	"	wrdsp	%0, %x1					\n"	\  	:								\  	: "r" (val), "i" (mask));					\  } while (0) -#if 0	/* Need DSP ASE capable assembler ... */  #define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})  #define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})  #define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;}) @@ -1210,230 +1202,177 @@ do {									\  #else -#define mfhi0()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mfhi	%0, $ac0		\n"			\ -	"	.word	0x00000810		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mfhi1()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mfhi	%0, $ac1		\n"			\ -	"	.word	0x00200810		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mfhi2()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mfhi	%0, $ac2		\n"			\ -	"	.word	0x00400810		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mfhi3()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mfhi	%0, $ac3		\n"			\ -	"	.word	0x00600810		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mflo0()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mflo	%0, $ac0		\n"			\ -	"	.word	0x00000812		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mflo1()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mflo	%0, $ac1		\n"			\ -	"	.word	0x00200812		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mflo2()								\ -({									\ -	unsigned long __treg;						\ -									\ -	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mflo	%0, $ac2		\n"			\ -	"	.word	0x00400812		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mflo3()								\ +#ifdef CONFIG_CPU_MICROMIPS +#define rddsp(mask)							\  ({									\ -	unsigned long __treg;						\ +	unsigned int __res;						\  									\  	__asm__ __volatile__(						\ -	"	.set	push			\n"			\ -	"	.set	noat			\n"			\ -	"	# mflo	%0, $ac3		\n"			\ -	"	.word	0x00600812		\n"			\ -	"	move	%0, $1			\n"			\ -	"	.set	pop			\n"			\ -	: "=r" (__treg));						\ -	__treg;								\ -}) - -#define mthi0(x)							\ -do {									\ -	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\ -	"	move	$1, %0					\n"	\ -	"	# mthi	$1, $ac0				\n"	\ -	"	.word	0x00200011				\n"	\ +	"	# rddsp $1, %x1					\n"	\ +	"	.hword	((0x0020067c | (%x1 << 14)) >> 16)	\n"	\ +	"	.hword	((0x0020067c | (%x1 << 14)) & 0xffff)	\n"	\ +	"	move	%0, $1					\n"	\  	"	.set	pop					\n"	\ -	:								\ -	: "r" (x));							\ -} while (0) +	: "=r" (__res)							\ +	: "i" (mask));							\ +	__res;								\ +}) -#define mthi1(x)							\ +#define wrdsp(val, mask)						\  do {									\  	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\  	"	move	$1, %0					\n"	\ -	"	# mthi	$1, $ac1				\n"	\ -	"	.word	0x00200811				\n"	\ +	"	# wrdsp $1, %x1					\n"	\ +	"	.hword	((0x0020167c | (%x1 << 14)) >> 16)	\n"	\ +	"	.hword	((0x0020167c | (%x1 << 14)) & 0xffff)	\n"	\  	"	.set	pop					\n"	\  	:								\ -	: "r" (x));							\ +	: "r" (val), "i" (mask));					\  } while (0) -#define mthi2(x)							\ -do {									\ +#define _umips_dsp_mfxxx(ins)						\ +({									\ +	unsigned long __treg;						\ +									\  	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\ -	"	move	$1, %0					\n"	\ -	"	# mthi	$1, $ac2				\n"	\ -	"	.word	0x00201011				\n"	\ +	"	.hword	0x0001					\n"	\ +	"	.hword	%x1					\n"	\ +	"	move	%0, $1					\n"	\  	"	.set	pop					\n"	\ -	:								\ -	: "r" (x));							\ -} while (0) +	: "=r" (__treg)							\ +	: "i" (ins));							\ +	__treg;								\ +}) -#define mthi3(x)							\ +#define _umips_dsp_mtxxx(val, ins)					\  do {									\  	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\  	"	move	$1, %0					\n"	\ -	"	# mthi	$1, $ac3				\n"	\ -	"	.word	0x00201811				\n"	\ +	"	.hword	0x0001					\n"	\ +	"	.hword	%x1					\n"	\  	"	.set	pop					\n"	\  	:								\ -	: "r" (x));							\ +	: "r" (val), "i" (ins));					\  } while (0) -#define mtlo0(x)							\ -do {									\ +#define _umips_dsp_mflo(reg) _umips_dsp_mfxxx((reg << 14) | 0x107c) +#define _umips_dsp_mfhi(reg) _umips_dsp_mfxxx((reg << 14) | 0x007c) + +#define _umips_dsp_mtlo(val, reg) _umips_dsp_mtxxx(val, ((reg << 14) | 0x307c)) +#define _umips_dsp_mthi(val, reg) _umips_dsp_mtxxx(val, ((reg << 14) | 0x207c)) + +#define mflo0() _umips_dsp_mflo(0) +#define mflo1() _umips_dsp_mflo(1) +#define mflo2() _umips_dsp_mflo(2) +#define mflo3() _umips_dsp_mflo(3) + +#define mfhi0() _umips_dsp_mfhi(0) +#define mfhi1() _umips_dsp_mfhi(1) +#define mfhi2() _umips_dsp_mfhi(2) +#define mfhi3() _umips_dsp_mfhi(3) + +#define mtlo0(x) _umips_dsp_mtlo(x, 0) +#define mtlo1(x) _umips_dsp_mtlo(x, 1) +#define mtlo2(x) _umips_dsp_mtlo(x, 2) +#define mtlo3(x) _umips_dsp_mtlo(x, 3) + +#define mthi0(x) _umips_dsp_mthi(x, 0) +#define mthi1(x) _umips_dsp_mthi(x, 1) +#define mthi2(x) _umips_dsp_mthi(x, 2) +#define mthi3(x) _umips_dsp_mthi(x, 3) + +#else  /* !CONFIG_CPU_MICROMIPS */ +#define rddsp(mask)							\ +({									\ +	unsigned int __res;						\ +									\  	__asm__ __volatile__(						\ -	"	.set	push					\n"	\ -	"	.set	noat					\n"	\ -	"	move	$1, %0					\n"	\ -	"	# mtlo	$1, $ac0				\n"	\ -	"	.word	0x00200013				\n"	\ -	"	.set	pop					\n"	\ -	:								\ -	: "r" (x));							\ -} while (0) +	"	.set	push				\n"		\ +	"	.set	noat				\n"		\ +	"	# rddsp $1, %x1				\n"		\ +	"	.word	0x7c000cb8 | (%x1 << 16)	\n"		\ +	"	move	%0, $1				\n"		\ +	"	.set	pop				\n"		\ +	: "=r" (__res)							\ +	: "i" (mask));							\ +	__res;								\ +}) -#define mtlo1(x)							\ +#define wrdsp(val, mask)						\  do {									\  	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\  	"	move	$1, %0					\n"	\ -	"	# mtlo	$1, $ac1				\n"	\ -	"	.word	0x00200813				\n"	\ +	"	# wrdsp $1, %x1					\n"	\ +	"	.word	0x7c2004f8 | (%x1 << 11)		\n"	\  	"	.set	pop					\n"	\ -	:								\ -	: "r" (x));							\ +        :								\ +	: "r" (val), "i" (mask));					\  } while (0) -#define mtlo2(x)							\ -do {									\ +#define _dsp_mfxxx(ins)							\ +({									\ +	unsigned long __treg;						\ +									\  	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\ -	"	move	$1, %0					\n"	\ -	"	# mtlo	$1, $ac2				\n"	\ -	"	.word	0x00201013				\n"	\ +	"	.word	(0x00000810 | %1)			\n"	\ +	"	move	%0, $1					\n"	\  	"	.set	pop					\n"	\ -	:								\ -	: "r" (x));							\ -} while (0) +	: "=r" (__treg)							\ +	: "i" (ins));							\ +	__treg;								\ +}) -#define mtlo3(x)							\ +#define _dsp_mtxxx(val, ins)						\  do {									\  	__asm__ __volatile__(						\  	"	.set	push					\n"	\  	"	.set	noat					\n"	\  	"	move	$1, %0					\n"	\ -	"	# mtlo	$1, $ac3				\n"	\ -	"	.word	0x00201813				\n"	\ +	"	.word	(0x00200011 | %1)			\n"	\  	"	.set	pop					\n"	\  	:								\ -	: "r" (x));							\ +	: "r" (val), "i" (ins));					\  } while (0) +#define _dsp_mflo(reg) _dsp_mfxxx((reg << 21) | 0x0002) +#define _dsp_mfhi(reg) _dsp_mfxxx((reg << 21) | 0x0000) + +#define _dsp_mtlo(val, reg) _dsp_mtxxx(val, ((reg << 11) | 0x0002)) +#define _dsp_mthi(val, reg) _dsp_mtxxx(val, ((reg << 11) | 0x0000)) + +#define mflo0() _dsp_mflo(0) +#define mflo1() _dsp_mflo(1) +#define mflo2() _dsp_mflo(2) +#define mflo3() _dsp_mflo(3) + +#define mfhi0() _dsp_mfhi(0) +#define mfhi1() _dsp_mfhi(1) +#define mfhi2() _dsp_mfhi(2) +#define mfhi3() _dsp_mfhi(3) + +#define mtlo0(x) _dsp_mtlo(x, 0) +#define mtlo1(x) _dsp_mtlo(x, 1) +#define mtlo2(x) _dsp_mtlo(x, 2) +#define mtlo3(x) _dsp_mtlo(x, 3) + +#define mthi0(x) _dsp_mthi(x, 0) +#define mthi1(x) _dsp_mthi(x, 1) +#define mthi2(x) _dsp_mthi(x, 2) +#define mthi3(x) _dsp_mthi(x, 3) + +#endif /* CONFIG_CPU_MICROMIPS */  #endif  /* diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h index 8ffae43107e..8ad2e0f8171 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -68,6 +68,85 @@ do {									\  		__write_64bit_c0_register($9, 7, (val));		\  } while (0) +/* + * Handling the 64 bit EIMR and EIRR registers in 32-bit mode with + * standard functions will be very inefficient. This provides + * optimized functions for the normal operations on the registers. + * + * Call with interrupts disabled. + */ +static inline void ack_c0_eirr(int irq) +{ +	__asm__ __volatile__( +		".set	push\n\t" +		".set	mips64\n\t" +		".set	noat\n\t" +		"li	$1, 1\n\t" +		"dsllv	$1, $1, %0\n\t" +		"dmtc0	$1, $9, 6\n\t" +		".set	pop" +		: : "r" (irq)); +} + +static inline void set_c0_eimr(int irq) +{ +	__asm__ __volatile__( +		".set	push\n\t" +		".set	mips64\n\t" +		".set	noat\n\t" +		"li	$1, 1\n\t" +		"dsllv	%0, $1, %0\n\t" +		"dmfc0	$1, $9, 7\n\t" +		"or	$1, %0\n\t" +		"dmtc0	$1, $9, 7\n\t" +		".set	pop" +		: "+r" (irq)); +} + +static inline void clear_c0_eimr(int irq) +{ +	__asm__ __volatile__( +		".set	push\n\t" +		".set	mips64\n\t" +		".set	noat\n\t" +		"li	$1, 1\n\t" +		"dsllv	%0, $1, %0\n\t" +		"dmfc0	$1, $9, 7\n\t" +		"or	$1, %0\n\t" +		"xor	$1, %0\n\t" +		"dmtc0	$1, $9, 7\n\t" +		".set	pop" +		: "+r" (irq)); +} + +/* + * Read c0 eimr and c0 eirr, do AND of the two values, the result is + * the interrupts which are raised and are not masked. + */ +static inline uint64_t read_c0_eirr_and_eimr(void) +{ +	uint64_t val; + +#ifdef CONFIG_64BIT +	val = read_c0_eimr() & read_c0_eirr(); +#else +	__asm__ __volatile__( +		".set	push\n\t" +		".set	mips64\n\t" +		".set	noat\n\t" +		"dmfc0	%M0, $9, 6\n\t" +		"dmfc0	%L0, $9, 7\n\t" +		"and	%M0, %L0\n\t" +		"dsll	%L0, %M0, 32\n\t" +		"dsra	%M0, %M0, 32\n\t" +		"dsra	%L0, %L0, 32\n\t" +		".set	pop" +		: "=r" (val)); +#endif + +	return val; +} +  static inline int hard_smp_processor_id(void)  {  	return __read_32bit_c0_register($15, 1) & 0x3ff; diff --git a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h index 7b63a6b722a..6d2e58a9a54 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h @@ -46,6 +46,8 @@  #define CPU_BLOCKID_FPU		9  #define CPU_BLOCKID_MAP		10 +#define ICU_DEFEATURE		0x100 +  #define LSU_DEFEATURE		0x304  #define LSU_DEBUG_ADDR		0x305  #define LSU_DEBUG_DATA0		0x306 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index 46ace0ca26d..3df53017fe5 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -261,6 +261,8 @@  #define PIC_LOCAL_SCHEDULING		1  #define PIC_GLOBAL_SCHEDULING		0 +#define PIC_CLK_HZ			133333333 +  #define nlm_read_pic_reg(b, r)	nlm_read_reg64(b, r)  #define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v)  #define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node)) @@ -315,6 +317,12 @@ nlm_pic_read_timer(uint64_t base, int timer)  	return nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer));  } +static inline uint32_t +nlm_pic_read_timer32(uint64_t base, int timer) +{ +	return (uint32_t)nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer)); +} +  static inline void  nlm_pic_write_timer(uint64_t base, int timer, uint64_t value)  { @@ -376,9 +384,9 @@ nlm_pic_ack(uint64_t base, int irt_num)  }  static inline void -nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt) +nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt, int en)  { -	nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt); +	nlm_pic_write_irt_direct(base, irt, en, 0, 0, irq, hwt);  }  int nlm_irq_to_irt(int irq); diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h index 2f549453585..63c99176dff 100644 --- a/arch/mips/include/asm/netlogic/xlr/pic.h +++ b/arch/mips/include/asm/netlogic/xlr/pic.h @@ -35,10 +35,11 @@  #ifndef _ASM_NLM_XLR_PIC_H  #define _ASM_NLM_XLR_PIC_H -#define PIC_CLKS_PER_SEC		66666666ULL +#define PIC_CLK_HZ			66666666  /* PIC hardware interrupt numbers */  #define PIC_IRT_WD_INDEX		0  #define PIC_IRT_TIMER_0_INDEX		1 +#define PIC_IRT_TIMER_INDEX(i)		((i) + PIC_IRT_TIMER_0_INDEX)  #define PIC_IRT_TIMER_1_INDEX		2  #define PIC_IRT_TIMER_2_INDEX		3  #define PIC_IRT_TIMER_3_INDEX		4 @@ -99,6 +100,7 @@  /* PIC Registers */  #define PIC_CTRL			0x00 +#define PIC_CTRL_STE			8	/* timer enable start bit */  #define PIC_IPI				0x04  #define PIC_INT_ACK			0x06 @@ -251,12 +253,52 @@ nlm_pic_ack(uint64_t base, int irt)  }  static inline void -nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt) +nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt, int en)  {  	nlm_write_reg(base, PIC_IRT_0(irt), (1u << hwt));  	/* local scheduling, invalid, level by default */  	nlm_write_reg(base, PIC_IRT_1(irt), -		(1 << 30) | (1 << 6) | irq); +		(en << 30) | (1 << 6) | irq); +} + +static inline uint64_t +nlm_pic_read_timer(uint64_t base, int timer) +{ +	uint32_t up1, up2, low; + +	up1 = nlm_read_reg(base, PIC_TIMER_COUNT_1(timer)); +	low = nlm_read_reg(base, PIC_TIMER_COUNT_0(timer)); +	up2 = nlm_read_reg(base, PIC_TIMER_COUNT_1(timer)); + +	if (up1 != up2) /* wrapped, get the new low */ +		low = nlm_read_reg(base, PIC_TIMER_COUNT_0(timer)); +	return ((uint64_t)up2 << 32) | low; + +} + +static inline uint32_t +nlm_pic_read_timer32(uint64_t base, int timer) +{ +	return nlm_read_reg(base, PIC_TIMER_COUNT_0(timer)); +} + +static inline void +nlm_pic_set_timer(uint64_t base, int timer, uint64_t value, int irq, int cpu) +{ +	uint32_t up, low; +	uint64_t pic_ctrl = nlm_read_reg(base, PIC_CTRL); +	int en; + +	en = (irq > 0); +	up = value >> 32; +	low = value & 0xFFFFFFFF; +	nlm_write_reg(base, PIC_TIMER_MAXVAL_0(timer), low); +	nlm_write_reg(base, PIC_TIMER_MAXVAL_1(timer), up); +	nlm_pic_init_irt(base, PIC_IRT_TIMER_INDEX(timer), irq, cpu, 0); + +	/* enable the timer */ +	pic_ctrl |= (1 << (PIC_CTRL_STE + timer)); +	nlm_write_reg(base, PIC_CTRL, pic_ctrl);  }  #endif  #endif /* _ASM_NLM_XLR_PIC_H */ diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index e224876cc34..b8e24fd4cbc 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -144,8 +144,13 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)  extern char * (*pcibios_plat_setup)(char *str); +#ifdef CONFIG_OF  /* this function parses memory ranges from a device node */  extern void pci_load_of_ranges(struct pci_controller *hose,  			       struct device_node *node); +#else +static inline void pci_load_of_ranges(struct pci_controller *hose, +				      struct device_node *node) {} +#endif  #endif /* _ASM_PCI_H */ diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index 96353075cc6..debc8009bd5 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h @@ -75,7 +75,7 @@ extern int init_r4k_clocksource(void);  static inline int init_mips_clocksource(void)  { -#ifdef CONFIG_CSRC_R4K +#if defined(CONFIG_CSRC_R4K) && !defined(CONFIG_CSRC_GIC)  	return init_r4k_clocksource();  #else  	return 0; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index c48ed923fd5..f81d98f6184 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_CSRC_IOASIC)	+= csrc-ioasic.o  obj-$(CONFIG_CSRC_POWERTV)	+= csrc-powertv.o  obj-$(CONFIG_CSRC_R4K)		+= csrc-r4k.o  obj-$(CONFIG_CSRC_SB1250)	+= csrc-sb1250.o +obj-$(CONFIG_CSRC_GIC)		+= csrc-gic.o  obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o  obj-$(CONFIG_STACKTRACE)	+= stacktrace.o @@ -98,4 +99,35 @@ obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event_mipsxx.o  obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o +# +# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is safe +# to enable DSP assembler support here even if the MIPS Release 2 CPU we +# are targetting does not support DSP because all code-paths making use of +# it properly check that the running CPU *actually does* support these +# instructions. +# +ifeq ($(CONFIG_CPU_MIPSR2), y) +CFLAGS_DSP 			= -DHAVE_AS_DSP + +# +# Check if assembler supports DSP ASE +# +ifeq ($(call cc-option-yn,-mdsp), y) +CFLAGS_DSP			+= -mdsp +endif + +# +# Check if assembler supports DSP ASE Rev2 +# +ifeq ($(call cc-option-yn,-mdspr2), y) +CFLAGS_DSP			+= -mdspr2 +endif + +CFLAGS_signal.o			= $(CFLAGS_DSP) +CFLAGS_signal32.o		= $(CFLAGS_DSP) +CFLAGS_process.o		= $(CFLAGS_DSP) +CFLAGS_branch.o			= $(CFLAGS_DSP) +CFLAGS_ptrace.o			= $(CFLAGS_DSP) +endif +  CPPFLAGS_vmlinux.lds		:= $(KBUILD_CFLAGS) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 2656c898e33..6bfccc227a9 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -201,6 +201,7 @@ void __init check_wait(void)  		break;  	case CPU_M14KC: +	case CPU_M14KEC:  	case CPU_24K:  	case CPU_34K:  	case CPU_1004K: @@ -467,6 +468,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)  		c->ases |= MIPS_ASE_MIPSMT;  	if (config3 & MIPS_CONF3_ULRI)  		c->options |= MIPS_CPU_ULRI; +	if (config3 & MIPS_CONF3_ISA) +		c->options |= MIPS_CPU_MICROMIPS; +	if (config3 & MIPS_CONF3_VZ) +		c->ases |= MIPS_ASE_VZ;  	return config3 & MIPS_CONF_M;  } @@ -866,10 +871,13 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)  		__cpu_name[cpu] = "MIPS 20Kc";  		break;  	case PRID_IMP_24K: -	case PRID_IMP_24KE:  		c->cputype = CPU_24K;  		__cpu_name[cpu] = "MIPS 24Kc";  		break; +	case PRID_IMP_24KE: +		c->cputype = CPU_24K; +		__cpu_name[cpu] = "MIPS 24KEc"; +		break;  	case PRID_IMP_25KF:  		c->cputype = CPU_25KF;  		__cpu_name[cpu] = "MIPS 25Kc"; @@ -886,6 +894,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)  		c->cputype = CPU_M14KC;  		__cpu_name[cpu] = "MIPS M14Kc";  		break; +	case PRID_IMP_M14KEC: +		c->cputype = CPU_M14KEC; +		__cpu_name[cpu] = "MIPS M14KEc"; +		break;  	case PRID_IMP_1004K:  		c->cputype = CPU_1004K;  		__cpu_name[cpu] = "MIPS 1004Kc"; diff --git a/arch/mips/kernel/csrc-gic.c b/arch/mips/kernel/csrc-gic.c new file mode 100644 index 00000000000..5dca24bce51 --- /dev/null +++ b/arch/mips/kernel/csrc-gic.c @@ -0,0 +1,49 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved. + */ +#include <linux/clocksource.h> +#include <linux/init.h> + +#include <asm/time.h> +#include <asm/gic.h> + +static cycle_t gic_hpt_read(struct clocksource *cs) +{ +	unsigned int hi, hi2, lo; + +	do { +		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi); +		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo); +		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2); +	} while (hi2 != hi); + +	return (((cycle_t) hi) << 32) + lo; +} + +static struct clocksource gic_clocksource = { +	.name	= "GIC", +	.read	= gic_hpt_read, +	.flags	= CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init gic_clocksource_init(unsigned int frequency) +{ +	unsigned int config, bits; + +	/* Calculate the clocksource mask. */ +	GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), config); +	bits = 32 + ((config & GIC_SH_CONFIG_COUNTBITS_MSK) >> +		(GIC_SH_CONFIG_COUNTBITS_SHF - 2)); + +	/* Set clocksource mask. */ +	gic_clocksource.mask = CLOCKSOURCE_MASK(bits); + +	/* Calculate a somewhat reasonable rating value. */ +	gic_clocksource.rating = 200 + frequency / 10000000; + +	clocksource_register_hz(&gic_clocksource, frequency); +} diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c index 9ae813eb782..9e6440eaa45 100644 --- a/arch/mips/kernel/early_printk.c +++ b/arch/mips/kernel/early_printk.c @@ -14,8 +14,7 @@  extern void prom_putchar(char); -static void __init -early_console_write(struct console *con, const char *s, unsigned n) +static void early_console_write(struct console *con, const char *s, unsigned n)  {  	while (n-- && *s) {  		if (*s == '\n') @@ -25,7 +24,7 @@ early_console_write(struct console *con, const char *s, unsigned n)  	}  } -static struct console early_console __initdata = { +static struct console early_console = {  	.name	= "early",  	.write	= early_console_write,  	.flags	= CON_PRINTBUFFER | CON_BOOT, diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 0207a44917b..72ef2d25cbf 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -31,6 +31,7 @@  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/irq.h> +#include <linux/irqdomain.h>  #include <asm/irq_cpu.h>  #include <asm/mipsregs.h> @@ -113,3 +114,44 @@ void __init mips_cpu_irq_init(void)  		irq_set_chip_and_handler(i, &mips_cpu_irq_controller,  					 handle_percpu_irq);  } + +#ifdef CONFIG_IRQ_DOMAIN +static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, +			     irq_hw_number_t hw) +{ +	static struct irq_chip *chip; + +	if (hw < 2 && cpu_has_mipsmt) { +		/* Software interrupts are used for MT/CMT IPI */ +		chip = &mips_mt_cpu_irq_controller; +	} else { +		chip = &mips_cpu_irq_controller; +	} + +	irq_set_chip_and_handler(irq, chip, handle_percpu_irq); + +	return 0; +} + +static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = { +	.map = mips_cpu_intc_map, +	.xlate = irq_domain_xlate_onecell, +}; + +int __init mips_cpu_intc_init(struct device_node *of_node, +			      struct device_node *parent) +{ +	struct irq_domain *domain; + +	/* Mask interrupts. */ +	clear_c0_status(ST0_IM); +	clear_c0_cause(CAUSEF_IP); + +	domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0, +				       &mips_cpu_intc_irq_domain_ops, NULL); +	if (!domain) +		panic("Failed to add irqdomain for MIPS CPU\n"); + +	return 0; +} +#endif /* CONFIG_IRQ_DOMAIN */ diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 79d4b8edbd7..135c4aadccb 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -95,6 +95,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)  	if (cpu_has_dsp)	seq_printf(m, "%s", " dsp");  	if (cpu_has_dsp2)	seq_printf(m, "%s", " dsp2");  	if (cpu_has_mipsmt)	seq_printf(m, "%s", " mt"); +	if (cpu_has_mmips)	seq_printf(m, "%s", " micromips"); +	if (cpu_has_vz)		seq_printf(m, "%s", " vz");  	seq_printf(m, "\n");  	seq_printf(m, "shadow register sets\t: %d\n", diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 653197e151d..4c774d5d508 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -480,34 +480,75 @@ static int __init early_parse_mem(char *p)  }  early_param("mem", early_parse_mem); -static void __init arch_mem_init(char **cmdline_p) +#ifdef CONFIG_PROC_VMCORE +unsigned long setup_elfcorehdr, setup_elfcorehdr_size; +static int __init early_parse_elfcorehdr(char *p) +{ +	int i; + +	setup_elfcorehdr = memparse(p, &p); + +	for (i = 0; i < boot_mem_map.nr_map; i++) { +		unsigned long start = boot_mem_map.map[i].addr; +		unsigned long end = (boot_mem_map.map[i].addr + +				     boot_mem_map.map[i].size); +		if (setup_elfcorehdr >= start && setup_elfcorehdr < end) { +			/* +			 * Reserve from the elf core header to the end of +			 * the memory segment, that should all be kdump +			 * reserved memory. +			 */ +			setup_elfcorehdr_size = end - setup_elfcorehdr; +			break; +		} +	} +	/* +	 * If we don't find it in the memory map, then we shouldn't +	 * have to worry about it, as the new kernel won't use it. +	 */ +	return 0; +} +early_param("elfcorehdr", early_parse_elfcorehdr); +#endif + +static void __init arch_mem_addpart(phys_t mem, phys_t end, int type)  { -	phys_t init_mem, init_end, init_size; +	phys_t size; +	int i; +	size = end - mem; +	if (!size) +		return; + +	/* Make sure it is in the boot_mem_map */ +	for (i = 0; i < boot_mem_map.nr_map; i++) { +		if (mem >= boot_mem_map.map[i].addr && +		    mem < (boot_mem_map.map[i].addr + +			   boot_mem_map.map[i].size)) +			return; +	} +	add_memory_region(mem, size, type); +} + +static void __init arch_mem_init(char **cmdline_p) +{  	extern void plat_mem_setup(void);  	/* call board setup routine */  	plat_mem_setup(); -	init_mem = PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT; -	init_end = PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT; -	init_size = init_end - init_mem; -	if (init_size) { -		/* Make sure it is in the boot_mem_map */ -		int i, found; -		found = 0; -		for (i = 0; i < boot_mem_map.nr_map; i++) { -			if (init_mem >= boot_mem_map.map[i].addr && -			    init_mem < (boot_mem_map.map[i].addr + -					boot_mem_map.map[i].size)) { -				found = 1; -				break; -			} -		} -		if (!found) -			add_memory_region(init_mem, init_size, -					  BOOT_MEM_INIT_RAM); -	} +	/* +	 * Make sure all kernel memory is in the maps.  The "UP" and +	 * "DOWN" are opposite for initdata since if it crosses over +	 * into another memory section you don't want that to be +	 * freed when the initdata is freed. +	 */ +	arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT, +			 PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT, +			 BOOT_MEM_RAM); +	arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT, +			 PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT, +			 BOOT_MEM_INIT_RAM);  	pr_info("Determined physical RAM map:\n");  	print_memory_map(); @@ -537,6 +578,14 @@ static void __init arch_mem_init(char **cmdline_p)  	}  	bootmem_init(); +#ifdef CONFIG_PROC_VMCORE +	if (setup_elfcorehdr && setup_elfcorehdr_size) { +		printk(KERN_INFO "kdump reserved memory at %lx-%lx\n", +		       setup_elfcorehdr, setup_elfcorehdr_size); +		reserve_bootmem(setup_elfcorehdr, setup_elfcorehdr_size, +				BOOTMEM_DEFAULT); +	} +#endif  #ifdef CONFIG_KEXEC  	if (crashk_res.start != crashk_res.end)  		reserve_bootmem(crashk_res.start, diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 1c152a93dc7..7186222dc5b 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -41,6 +41,7 @@  #include <asm/addrspace.h>  #include <asm/smtc.h>  #include <asm/smtc_proc.h> +#include <asm/setup.h>  /*   * SMTC Kernel needs to manipulate low-level CPU interrupt mask diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 32fc5d4a22e..b4c01522edd 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -697,18 +697,7 @@ static int vpe_run(struct vpe * v)  	dmt_flag = dmt();  	vpeflags = dvpe(); -	if (!list_empty(&v->tc)) { -		if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) { -			evpe(vpeflags); -			emt(dmt_flag); -			local_irq_restore(flags); - -			printk(KERN_WARNING -			       "VPE loader: TC %d is already in use.\n", -			       v->tc->index); -			return -ENOEXEC; -		} -	} else { +	if (list_empty(&v->tc)) {  		evpe(vpeflags);  		emt(dmt_flag);  		local_irq_restore(flags); @@ -720,6 +709,8 @@ static int vpe_run(struct vpe * v)  		return -ENOEXEC;  	} +	t = list_first_entry(&v->tc, struct tc, tc); +  	/* Put MVPE's into 'configuration state' */  	set_c0_mvpcontrol(MVPCONTROL_VPC); diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index 186fd3e4424..3fc2e6d70c7 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -26,13 +26,15 @@  #include "prom.h"  /* lantiq socs have 3 static clocks */ -static struct clk cpu_clk_generic[3]; +static struct clk cpu_clk_generic[4]; -void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io) +void clkdev_add_static(unsigned long cpu, unsigned long fpi, +			unsigned long io, unsigned long ppe)  {  	cpu_clk_generic[0].rate = cpu;  	cpu_clk_generic[1].rate = fpi;  	cpu_clk_generic[2].rate = io; +	cpu_clk_generic[3].rate = ppe;  }  struct clk *clk_get_cpu(void) @@ -51,6 +53,12 @@ struct clk *clk_get_io(void)  	return &cpu_clk_generic[2];  } +struct clk *clk_get_ppe(void) +{ +	return &cpu_clk_generic[3]; +} +EXPORT_SYMBOL_GPL(clk_get_ppe); +  static inline int clk_good(struct clk *clk)  {  	return clk && !IS_ERR(clk); diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h index fa670602b91..77e4bdb1fe8 100644 --- a/arch/mips/lantiq/clk.h +++ b/arch/mips/lantiq/clk.h @@ -27,12 +27,15 @@  #define CLOCK_167M	166666667  #define CLOCK_196_608M	196608000  #define CLOCK_200M	200000000 +#define CLOCK_222M	222000000 +#define CLOCK_240M	240000000  #define CLOCK_250M	250000000  #define CLOCK_266M	266666666  #define CLOCK_300M	300000000  #define CLOCK_333M	333333333  #define CLOCK_393M	393215332  #define CLOCK_400M	400000000 +#define CLOCK_450M	450000000  #define CLOCK_500M	500000000  #define CLOCK_600M	600000000 @@ -64,15 +67,17 @@ struct clk {  };  extern void clkdev_add_static(unsigned long cpu, unsigned long fpi, -				unsigned long io); +				unsigned long io, unsigned long ppe);  extern unsigned long ltq_danube_cpu_hz(void);  extern unsigned long ltq_danube_fpi_hz(void); +extern unsigned long ltq_danube_pp32_hz(void);  extern unsigned long ltq_ar9_cpu_hz(void);  extern unsigned long ltq_ar9_fpi_hz(void);  extern unsigned long ltq_vr9_cpu_hz(void);  extern unsigned long ltq_vr9_fpi_hz(void); +extern unsigned long ltq_vr9_pp32_hz(void);  #endif diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index 2d4ced332b3..ff4894a833e 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c @@ -241,9 +241,9 @@ void __init ltq_soc_init(void)  	/* get our 3 static rates for cpu, fpi and io clocks */  	if (ltq_sys1_r32(SYS1_CPU0CC) & CPU0CC_CPUDIV) -		clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M); +		clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M, 0);  	else -		clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M); +		clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M, 0);  	/* add our clock domains */  	clkdev_add_sys("1d810000.gpio", SYSCTL_SYSETH, ACTS_P0); diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 5323308aab3..51194875f15 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -33,17 +33,10 @@  /* register definitions - external irqs */  #define LTQ_EIU_EXIN_C		0x0000  #define LTQ_EIU_EXIN_INIC	0x0004 +#define LTQ_EIU_EXIN_INC	0x0008  #define LTQ_EIU_EXIN_INEN	0x000C -/* irq numbers used by the external interrupt unit (EIU) */ -#define LTQ_EIU_IR0		(INT_NUM_IM4_IRL0 + 30) -#define LTQ_EIU_IR1		(INT_NUM_IM3_IRL0 + 31) -#define LTQ_EIU_IR2		(INT_NUM_IM1_IRL0 + 26) -#define LTQ_EIU_IR3		INT_NUM_IM1_IRL0 -#define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1) -#define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2) -#define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30) -#define XWAY_EXIN_COUNT		3 +/* number of external interrupts */  #define MAX_EIU			6  /* the performance counter */ @@ -72,20 +65,19 @@  int gic_present;  #endif -static unsigned short ltq_eiu_irq[MAX_EIU] = { -	LTQ_EIU_IR0, -	LTQ_EIU_IR1, -	LTQ_EIU_IR2, -	LTQ_EIU_IR3, -	LTQ_EIU_IR4, -	LTQ_EIU_IR5, -}; -  static int exin_avail; +static struct resource ltq_eiu_irq[MAX_EIU];  static void __iomem *ltq_icu_membase[MAX_IM];  static void __iomem *ltq_eiu_membase;  static struct irq_domain *ltq_domain; +int ltq_eiu_get_irq(int exin) +{ +	if (exin < exin_avail) +		return ltq_eiu_irq[exin].start; +	return -1; +} +  void ltq_disable_irq(struct irq_data *d)  {  	u32 ier = LTQ_ICU_IM0_IER; @@ -128,19 +120,65 @@ void ltq_enable_irq(struct irq_data *d)  	ltq_icu_w32(im, ltq_icu_r32(im, ier) | BIT(offset), ier);  } +static int ltq_eiu_settype(struct irq_data *d, unsigned int type) +{ +	int i; + +	for (i = 0; i < MAX_EIU; i++) { +		if (d->hwirq == ltq_eiu_irq[i].start) { +			int val = 0; +			int edge = 0; + +			switch (type) { +			case IRQF_TRIGGER_NONE: +				break; +			case IRQF_TRIGGER_RISING: +				val = 1; +				edge = 1; +				break; +			case IRQF_TRIGGER_FALLING: +				val = 2; +				edge = 1; +				break; +			case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING: +				val = 3; +				edge = 1; +				break; +			case IRQF_TRIGGER_HIGH: +				val = 5; +				break; +			case IRQF_TRIGGER_LOW: +				val = 6; +				break; +			default: +				pr_err("invalid type %d for irq %ld\n", +					type, d->hwirq); +				return -EINVAL; +			} + +			if (edge) +				irq_set_handler(d->hwirq, handle_edge_irq); + +			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) | +				(val << (i * 4)), LTQ_EIU_EXIN_C); +		} +	} + +	return 0; +} +  static unsigned int ltq_startup_eiu_irq(struct irq_data *d)  {  	int i;  	ltq_enable_irq(d);  	for (i = 0; i < MAX_EIU; i++) { -		if (d->hwirq == ltq_eiu_irq[i]) { -			/* low level - we should really handle set_type */ -			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) | -				(0x6 << (i * 4)), LTQ_EIU_EXIN_C); +		if (d->hwirq == ltq_eiu_irq[i].start) { +			/* by default we are low level triggered */ +			ltq_eiu_settype(d, IRQF_TRIGGER_LOW);  			/* clear all pending */ -			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~BIT(i), -				LTQ_EIU_EXIN_INIC); +			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INC) & ~BIT(i), +				LTQ_EIU_EXIN_INC);  			/* enable */  			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | BIT(i),  				LTQ_EIU_EXIN_INEN); @@ -157,7 +195,7 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d)  	ltq_disable_irq(d);  	for (i = 0; i < MAX_EIU; i++) { -		if (d->hwirq == ltq_eiu_irq[i]) { +		if (d->hwirq == ltq_eiu_irq[i].start) {  			/* disable */  			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~BIT(i),  				LTQ_EIU_EXIN_INEN); @@ -186,6 +224,7 @@ static struct irq_chip ltq_eiu_type = {  	.irq_ack = ltq_ack_irq,  	.irq_mask = ltq_disable_irq,  	.irq_mask_ack = ltq_mask_and_ack_irq, +	.irq_set_type = ltq_eiu_settype,  };  static void ltq_hw_irqdispatch(int module) @@ -301,7 +340,7 @@ static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)  		return 0;  	for (i = 0; i < exin_avail; i++) -		if (hw == ltq_eiu_irq[i]) +		if (hw == ltq_eiu_irq[i].start)  			chip = <q_eiu_type;  	irq_set_chip_and_handler(hw, chip, handle_level_irq); @@ -323,7 +362,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)  {  	struct device_node *eiu_node;  	struct resource res; -	int i; +	int i, ret;  	for (i = 0; i < MAX_IM; i++) {  		if (of_address_to_resource(node, i, &res)) @@ -340,17 +379,19 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)  	}  	/* the external interrupts are optional and xway only */ -	eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu"); +	eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");  	if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {  		/* find out how many external irq sources we have */ -		const __be32 *count = of_get_property(node, -							"lantiq,count", NULL); +		exin_avail = of_irq_count(eiu_node); -		if (count) -			exin_avail = *count;  		if (exin_avail > MAX_EIU)  			exin_avail = MAX_EIU; +		ret = of_irq_to_resource_table(eiu_node, +						ltq_eiu_irq, exin_avail); +		if (ret != exin_avail) +			panic("failed to load external irq resources\n"); +  		if (request_mem_region(res.start, resource_size(&res),  							res.name) < 0)  			pr_err("Failed to request eiu memory"); diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 9aa17f79a74..1ab576dc9bd 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -53,6 +53,29 @@ unsigned long ltq_danube_cpu_hz(void)  	}  } +unsigned long ltq_danube_pp32_hz(void) +{ +	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 7) & 3; +	unsigned long clk; + +	switch (clksys) { +	case 1: +		clk = CLOCK_240M; +		break; +	case 2: +		clk = CLOCK_222M; +		break; +	case 3: +		clk = CLOCK_133M; +		break; +	default: +		clk = CLOCK_266M; +		break; +	} + +	return clk; +} +  unsigned long ltq_ar9_sys_hz(void)  {  	if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2) @@ -149,3 +172,23 @@ unsigned long ltq_vr9_fpi_hz(void)  	return clk;  } + +unsigned long ltq_vr9_pp32_hz(void) +{ +	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3; +	unsigned long clk; + +	switch (clksys) { +	case 1: +		clk = CLOCK_450M; +		break; +	case 2: +		clk = CLOCK_300M; +		break; +	default: +		clk = CLOCK_500M; +		break; +	} + +	return clk; +} diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 544dbb7fb42..1fa0f175357 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -78,10 +78,19 @@ static struct ltq_xrx200_gphy_reset {  /* reset and boot a gphy. these phys only exist on xrx200 SoC */  int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)  { +	struct clk *clk; +  	if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {  		dev_err(dev, "this SoC has no GPHY\n");  		return -EINVAL;  	} + +	clk = clk_get_sys("1f203000.rcu", "gphy"); +	if (IS_ERR(clk)) +		return PTR_ERR(clk); + +	clk_enable(clk); +  	if (id > 1) {  		dev_err(dev, "%u is an invalid gphy id\n", id);  		return -EINVAL; diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 3925e6609ac..c24924fe087 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -305,7 +305,7 @@ void __init ltq_soc_init(void)  	/* check if all the core register ranges are available */  	if (!np_pmu || !np_cgu || !np_ebu) -		panic("Failed to load core nodess from devicetree"); +		panic("Failed to load core nodes from devicetree");  	if (of_address_to_resource(np_pmu, 0, &res_pmu) ||  			of_address_to_resource(np_cgu, 0, &res_cgu) || @@ -356,14 +356,16 @@ void __init ltq_soc_init(void)  	if (of_machine_is_compatible("lantiq,ase")) {  		if (ltq_cgu_r32(CGU_SYS) & (1 << 5)) -			clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M); +			clkdev_add_static(CLOCK_266M, CLOCK_133M, +						CLOCK_133M, CLOCK_266M);  		else -			clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M); +			clkdev_add_static(CLOCK_133M, CLOCK_133M, +						CLOCK_133M, CLOCK_133M);  		clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),  		clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);  	} else if (of_machine_is_compatible("lantiq,vr9")) {  		clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), -				ltq_vr9_fpi_hz()); +				ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz());  		clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);  		clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);  		clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI); @@ -374,12 +376,13 @@ void __init ltq_soc_init(void)  				PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |  				PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |  				PMU_PPE_QSB | PMU_PPE_TOP); +		clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);  	} else if (of_machine_is_compatible("lantiq,ar9")) {  		clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), -				ltq_ar9_fpi_hz()); +				ltq_ar9_fpi_hz(), CLOCK_250M);  		clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);  	} else {  		clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), -				ltq_danube_fpi_hz()); +				ltq_danube_fpi_hz(), ltq_danube_pp32_hz());  	}  } diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c index 2dd9c5648d7..2a47af5a55c 100644 --- a/arch/mips/loongson1/common/prom.c +++ b/arch/mips/loongson1/common/prom.c @@ -73,7 +73,7 @@ void __init prom_free_prom_memory(void)  #define PORT(offset)	(u8 *)(KSEG1ADDR(LS1X_UART0_BASE + offset)) -void __init prom_putchar(char c) +void prom_putchar(char c)  {  	int timeout; diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index d45f8e28b47..ecca559b8d7 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1057,6 +1057,7 @@ static void __cpuinit probe_pcache(void)  		break;  	case CPU_M14KC: +	case CPU_M14KEC:  	case CPU_24K:  	case CPU_34K:  	case CPU_74K: diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 36b9bd89c79..820e6612d74 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -581,6 +581,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,  	case CPU_4KC:  	case CPU_4KEC:  	case CPU_M14KC: +	case CPU_M14KEC:  	case CPU_SB1:  	case CPU_SB1A:  	case CPU_4KSC: diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 8607b0dd29f..a144b89cf9b 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -17,7 +17,6 @@   *   * Setting up the clock on the MIPS boards.   */ -  #include <linux/types.h>  #include <linux/i8253.h>  #include <linux/init.h> @@ -25,7 +24,6 @@  #include <linux/sched.h>  #include <linux/spinlock.h>  #include <linux/interrupt.h> -#include <linux/time.h>  #include <linux/timex.h>  #include <linux/mc146818rtc.h> @@ -34,11 +32,11 @@  #include <asm/hardirq.h>  #include <asm/irq.h>  #include <asm/div64.h> -#include <asm/cpu.h>  #include <asm/setup.h>  #include <asm/time.h>  #include <asm/mc146818-time.h>  #include <asm/msc01_ic.h> +#include <asm/gic.h>  #include <asm/mips-boards/generic.h>  #include <asm/mips-boards/prom.h> @@ -46,6 +44,7 @@  #include <asm/mips-boards/maltaint.h>  unsigned long cpu_khz; +int gic_frequency;  static int mips_cpu_timer_irq;  static int mips_cpu_perf_irq; @@ -61,44 +60,50 @@ static void mips_perf_dispatch(void)  	do_IRQ(mips_cpu_perf_irq);  } +static unsigned int freqround(unsigned int freq, unsigned int amount) +{ +	freq += amount; +	freq -= freq % (amount*2); +	return freq; +} +  /* - * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect + * Estimate CPU and GIC frequencies.   */ -static unsigned int __init estimate_cpu_frequency(void) +static void __init estimate_frequencies(void)  { -	unsigned int prid = read_c0_prid() & 0xffff00; -	unsigned int count; -  	unsigned long flags; -	unsigned int start; +	unsigned int count, start; +	unsigned int giccount = 0, gicstart = 0;  	local_irq_save(flags); -	/* Start counter exactly on falling edge of update flag */ +	/* Start counter exactly on falling edge of update flag. */  	while (CMOS_READ(RTC_REG_A) & RTC_UIP);  	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); -	/* Start r4k counter. */ +	/* Initialize counters. */  	start = read_c0_count(); +	if (gic_present) +		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), gicstart); -	/* Read counter exactly on falling edge of update flag */ +	/* Read counter exactly on falling edge of update flag. */  	while (CMOS_READ(RTC_REG_A) & RTC_UIP);  	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); -	count = read_c0_count() - start; +	count = read_c0_count(); +	if (gic_present) +		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), giccount); -	/* restore interrupts */  	local_irq_restore(flags); -	mips_hpt_frequency = count; -	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && -	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) -		count *= 2; - -	count += 5000;	  /* round */ -	count -= count%10000; +	count -= start; +	if (gic_present) +		giccount -= gicstart; -	return count; +	mips_hpt_frequency = count; +	if (gic_present) +		gic_frequency = giccount;  }  void read_persistent_clock(struct timespec *ts) @@ -144,22 +149,34 @@ unsigned int __cpuinit get_c0_compare_int(void)  void __init plat_time_init(void)  { -	unsigned int est_freq; - -	/* Set Data mode - binary. */ -	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); +	unsigned int prid = read_c0_prid() & 0xffff00; +	unsigned int freq; -	est_freq = estimate_cpu_frequency(); +	estimate_frequencies(); -	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, -	       (est_freq%1000000)*100/1000000); +	freq = mips_hpt_frequency; +	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && +	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) +		freq *= 2; +	freq = freqround(freq, 5000); +	pr_debug("CPU frequency %d.%02d MHz\n", freq/1000000, +	       (freq%1000000)*100/1000000); +	cpu_khz = freq / 1000; -	cpu_khz = est_freq / 1000; +	if (gic_present) { +		freq = freqround(gic_frequency, 5000); +		pr_debug("GIC frequency %d.%02d MHz\n", freq/1000000, +		       (freq%1000000)*100/1000000); +		gic_clocksource_init(gic_frequency); +	} else +		init_r4k_clocksource(); -	mips_scroll_message(); -#ifdef CONFIG_I8253		/* Only Malta has a PIT */ +#ifdef CONFIG_I8253 +	/* Only Malta has a PIT. */  	setup_pit_timer();  #endif +	mips_scroll_message(); +  	plat_perf_setup();  } diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 780832e391f..9f84c60bf53 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -105,21 +105,23 @@ static void xlp_pic_disable(struct irq_data *d)  static void xlp_pic_mask_ack(struct irq_data *d)  {  	struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d); -	uint64_t mask = 1ull << pd->picirq; -	write_c0_eirr(mask);		/* ack by writing EIRR */ +	clear_c0_eimr(pd->picirq); +	ack_c0_eirr(pd->picirq);  }  static void xlp_pic_unmask(struct irq_data *d)  {  	struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d); -	if (!pd) -		return; +	BUG_ON(!pd);  	if (pd->extra_ack)  		pd->extra_ack(d); +	/* re-enable the intr on this cpu */ +	set_c0_eimr(pd->picirq); +  	/* Ack is a single write, no need to lock */  	nlm_pic_ack(pd->node->picbase, pd->irt);  } @@ -134,32 +136,17 @@ static struct irq_chip xlp_pic = {  static void cpuintr_disable(struct irq_data *d)  { -	uint64_t eimr; -	uint64_t mask = 1ull << d->irq; - -	eimr = read_c0_eimr(); -	write_c0_eimr(eimr & ~mask); +	clear_c0_eimr(d->irq);  }  static void cpuintr_enable(struct irq_data *d)  { -	uint64_t eimr; -	uint64_t mask = 1ull << d->irq; - -	eimr = read_c0_eimr(); -	write_c0_eimr(eimr | mask); +	set_c0_eimr(d->irq);  }  static void cpuintr_ack(struct irq_data *d)  { -	uint64_t mask = 1ull << d->irq; - -	write_c0_eirr(mask); -} - -static void cpuintr_nop(struct irq_data *d) -{ -	WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq); +	ack_c0_eirr(d->irq);  }  /* @@ -170,9 +157,9 @@ struct irq_chip nlm_cpu_intr = {  	.name		= "XLP-CPU-INTR",  	.irq_enable	= cpuintr_enable,  	.irq_disable	= cpuintr_disable, -	.irq_mask	= cpuintr_nop, -	.irq_ack	= cpuintr_nop, -	.irq_eoi	= cpuintr_ack, +	.irq_mask	= cpuintr_disable, +	.irq_ack	= cpuintr_ack, +	.irq_eoi	= cpuintr_enable,  };  static void __init nlm_init_percpu_irqs(void) @@ -230,7 +217,7 @@ static void nlm_init_node_irqs(int node)  		nlm_setup_pic_irq(node, i, i, irt);  		/* set interrupts to first cpu in node */  		nlm_pic_init_irt(nodep->picbase, irt, i, -					node * NLM_CPUS_PER_NODE); +					node * NLM_CPUS_PER_NODE, 0);  		irqmask |= (1ull << i);  	}  	nodep->irqmask = irqmask; @@ -265,7 +252,7 @@ asmlinkage void plat_irq_dispatch(void)  	int i, node;  	node = nlm_nodeid(); -	eirr = read_c0_eirr() & read_c0_eimr(); +	eirr = read_c0_eirr_and_eimr();  	i = __ilog2_u64(eirr);  	if (i == -1) diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index a080d9ee3cd..2bb95dcfe20 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -84,15 +84,19 @@ void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)  /* IRQ_IPI_SMP_FUNCTION Handler */  void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)  { -	write_c0_eirr(1ull << irq); +	clear_c0_eimr(irq); +	ack_c0_eirr(irq);  	smp_call_function_interrupt(); +	set_c0_eimr(irq);  }  /* IRQ_IPI_SMP_RESCHEDULE  handler */  void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)  { -	write_c0_eirr(1ull << irq); +	clear_c0_eimr(irq); +	ack_c0_eirr(irq);  	scheduler_ipi(); +	set_c0_eimr(irq);  }  /* diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 280ff5855ef..02651748858 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -69,6 +69,12 @@  #endif  	mtcr	t1, t0 +	li	t0, ICU_DEFEATURE +	mfcr	t1, t0 +	ori	t1, 0x1000	/* Enable Icache partitioning */ +	mtcr	t1, t0 + +  #ifdef XLP_AX_WORKAROUND  	li	t0, SCHED_DEFEATURE  	lui	t1, 0x0100	/* Disable BRU accepting ALU ops */ diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c index bd3e498157f..5c56555380b 100644 --- a/arch/mips/netlogic/common/time.c +++ b/arch/mips/netlogic/common/time.c @@ -35,17 +35,73 @@  #include <linux/init.h>  #include <asm/time.h> +#include <asm/cpu-features.h> +  #include <asm/netlogic/interrupt.h>  #include <asm/netlogic/common.h> +#include <asm/netlogic/haldefs.h> +#include <asm/netlogic/common.h> + +#if defined(CONFIG_CPU_XLP) +#include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> +#elif defined(CONFIG_CPU_XLR) +#include <asm/netlogic/xlr/iomap.h> +#include <asm/netlogic/xlr/pic.h> +#include <asm/netlogic/xlr/xlr.h> +#else +#error "Unknown CPU" +#endif  unsigned int __cpuinit get_c0_compare_int(void)  {  	return IRQ_TIMER;  } +static cycle_t nlm_get_pic_timer(struct clocksource *cs) +{ +	uint64_t picbase = nlm_get_node(0)->picbase; + +	return ~nlm_pic_read_timer(picbase, PIC_CLOCK_TIMER); +} + +static cycle_t nlm_get_pic_timer32(struct clocksource *cs) +{ +	uint64_t picbase = nlm_get_node(0)->picbase; + +	return ~nlm_pic_read_timer32(picbase, PIC_CLOCK_TIMER); +} + +static struct clocksource csrc_pic = { +	.name		= "PIC", +	.flags		= CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void nlm_init_pic_timer(void) +{ +	uint64_t picbase = nlm_get_node(0)->picbase; + +	nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0); +	if (current_cpu_data.cputype == CPU_XLR) { +		csrc_pic.mask	= CLOCKSOURCE_MASK(32); +		csrc_pic.read	= nlm_get_pic_timer32; +	} else { +		csrc_pic.mask	= CLOCKSOURCE_MASK(64); +		csrc_pic.read	= nlm_get_pic_timer; +	} +	csrc_pic.rating = 1000; +	clocksource_register_hz(&csrc_pic, PIC_CLK_HZ); +} +  void __init plat_time_init(void)  { +	nlm_init_pic_timer();  	mips_hpt_frequency = nlm_get_cpu_frequency(); +	if (current_cpu_type() == CPU_XLR) +		preset_lpj = mips_hpt_frequency / (3 * HZ); +	else +		preset_lpj = mips_hpt_frequency / (2 * HZ);  	pr_info("MIPS counter frequency [%ld]\n",  			(unsigned long)mips_hpt_frequency);  } diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index cb9010642ac..abb3e08cc05 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -51,7 +51,7 @@  #include <asm/netlogic/xlp-hal/xlp.h>  #include <asm/netlogic/xlp-hal/sys.h> -static int xlp_wakeup_core(uint64_t sysbase, int core) +static int xlp_wakeup_core(uint64_t sysbase, int node, int core)  {  	uint32_t coremask, value;  	int count; @@ -82,36 +82,51 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)  	struct nlm_soc_info *nodep;  	uint64_t syspcibase;  	uint32_t syscoremask; -	int core, n, cpu; +	int core, n, cpu, count, val;  	for (n = 0; n < NLM_NR_NODES; n++) {  		syspcibase = nlm_get_sys_pcibase(n);  		if (nlm_read_reg(syspcibase, 0) == 0xffffffff)  			break; -		/* read cores in reset from SYS and account for boot cpu */ -		nlm_node_init(n); +		/* read cores in reset from SYS */ +		if (n != 0) +			nlm_node_init(n);  		nodep = nlm_get_node(n);  		syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET); -		if (n == 0) +		/* The boot cpu */ +		if (n == 0) {  			syscoremask |= 1; +			nodep->coremask = 1; +		}  		for (core = 0; core < NLM_CORES_PER_NODE; core++) { +			/* we will be on node 0 core 0 */ +			if (n == 0 && core == 0) +				continue; +  			/* see if the core exists */  			if ((syscoremask & (1 << core)) == 0)  				continue; -			/* see if at least the first thread is enabled */ +			/* see if at least the first hw thread is enabled */  			cpu = (n * NLM_CORES_PER_NODE + core)  						* NLM_THREADS_PER_CORE;  			if (!cpumask_test_cpu(cpu, wakeup_mask))  				continue;  			/* wake up the core */ -			if (xlp_wakeup_core(nodep->sysbase, core)) -				nodep->coremask |= 1u << core; -			else -				pr_err("Failed to enable core %d\n", core); +			if (!xlp_wakeup_core(nodep->sysbase, n, core)) +				continue; + +			/* core is up */ +			nodep->coremask |= 1u << core; + +			/* spin until the first hw thread sets its ready */ +			count = 0x20000000; +			do { +				val = *(volatile int *)&nlm_cpu_ready[cpu]; +			} while (val == 0 && --count > 0);  		}  	}  } diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c index f5bddf95bf2..ed3bf0e3f30 100644 --- a/arch/mips/netlogic/xlr/fmn-config.c +++ b/arch/mips/netlogic/xlr/fmn-config.c @@ -216,6 +216,8 @@ void xlr_board_info_setup(void)  	case PRID_IMP_NETLOGIC_XLS404B:  	case PRID_IMP_NETLOGIC_XLS408B:  	case PRID_IMP_NETLOGIC_XLS416B: +	case PRID_IMP_NETLOGIC_XLS608B: +	case PRID_IMP_NETLOGIC_XLS616B:  		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,  					FMN_STNID_GMAC0_TX3, 8, 8, 32);  		setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0, diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c index e287277d32b..7b96a91f477 100644 --- a/arch/mips/netlogic/xlr/platform.c +++ b/arch/mips/netlogic/xlr/platform.c @@ -64,7 +64,7 @@ void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)  		.iotype		= UPIO_MEM32,		\  		.flags		= (UPF_SKIP_TEST |	\  			 UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\ -		.uartclk	= PIC_CLKS_PER_SEC,	\ +		.uartclk	= PIC_CLK_HZ,		\  		.type		= PORT_16550A,		\  		.serial_in	= nlm_xlr_uart_in,	\  		.serial_out	= nlm_xlr_uart_out,	\ diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index f088efb8fe4..e3e094100e3 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -70,7 +70,7 @@ static void __init nlm_early_serial_setup(void)  	s.iotype	= UPIO_MEM32;  	s.regshift	= 2;  	s.irq		= PIC_UART_0_IRQ; -	s.uartclk	= PIC_CLKS_PER_SEC; +	s.uartclk	= PIC_CLK_HZ;  	s.serial_in	= nlm_xlr_uart_in;  	s.serial_out	= nlm_xlr_uart_out;  	s.mapbase	= uart_base; diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index 56f2cf221c7..af763e838fd 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -78,6 +78,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)  	switch (current_cpu_type()) {  	case CPU_5KC:  	case CPU_M14KC: +	case CPU_M14KEC:  	case CPU_20KC:  	case CPU_24K:  	case CPU_25KF: diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 1cfab95755b..1fd361462c0 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -351,6 +351,10 @@ static int __init mipsxx_init(void)  		op_model_mipsxx_ops.cpu_type = "mips/M14Kc";  		break; +	case CPU_M14KEC: +		op_model_mipsxx_ops.cpu_type = "mips/M14KEc"; +		break; +  	case CPU_20KC:  		op_model_mipsxx_ops.cpu_type = "mips/20K";  		break; diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index 6eaa4f2d0e3..412ec025cf5 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c @@ -18,26 +18,11 @@  #include <linux/pci.h>  #include <linux/pci_regs.h>  #include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/platform_device.h>  #include <asm/mach-ath79/ar71xx_regs.h>  #include <asm/mach-ath79/ath79.h> -#include <asm/mach-ath79/pci.h> - -#define AR71XX_PCI_MEM_BASE	0x10000000 -#define AR71XX_PCI_MEM_SIZE	0x07000000 - -#define AR71XX_PCI_WIN0_OFFS		0x10000000 -#define AR71XX_PCI_WIN1_OFFS		0x11000000 -#define AR71XX_PCI_WIN2_OFFS		0x12000000 -#define AR71XX_PCI_WIN3_OFFS		0x13000000 -#define AR71XX_PCI_WIN4_OFFS		0x14000000 -#define AR71XX_PCI_WIN5_OFFS		0x15000000 -#define AR71XX_PCI_WIN6_OFFS		0x16000000 -#define AR71XX_PCI_WIN7_OFFS		0x07000000 - -#define AR71XX_PCI_CFG_BASE		\ -	(AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) -#define AR71XX_PCI_CFG_SIZE		0x100  #define AR71XX_PCI_REG_CRP_AD_CBE	0x00  #define AR71XX_PCI_REG_CRP_WRDATA	0x04 @@ -63,8 +48,15 @@  #define AR71XX_PCI_IRQ_COUNT		5 -static DEFINE_SPINLOCK(ar71xx_pci_lock); -static void __iomem *ar71xx_pcicfg_base; +struct ar71xx_pci_controller { +	void __iomem *cfg_base; +	spinlock_t lock; +	int irq; +	int irq_base; +	struct pci_controller pci_ctrl; +	struct resource io_res; +	struct resource mem_res; +};  /* Byte lane enable bits */  static const u8 ar71xx_pci_ble_table[4][4] = { @@ -107,9 +99,18 @@ static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn,  	return ret;  } -static int ar71xx_pci_check_error(int quiet) +static inline struct ar71xx_pci_controller * +pci_bus_to_ar71xx_controller(struct pci_bus *bus)  { -	void __iomem *base = ar71xx_pcicfg_base; +	struct pci_controller *hose; + +	hose = (struct pci_controller *) bus->sysdata; +	return container_of(hose, struct ar71xx_pci_controller, pci_ctrl); +} + +static int ar71xx_pci_check_error(struct ar71xx_pci_controller *apc, int quiet) +{ +	void __iomem *base = apc->cfg_base;  	u32 pci_err;  	u32 ahb_err; @@ -144,9 +145,10 @@ static int ar71xx_pci_check_error(int quiet)  	return !!(ahb_err | pci_err);  } -static inline void ar71xx_pci_local_write(int where, int size, u32 value) +static inline void ar71xx_pci_local_write(struct ar71xx_pci_controller *apc, +					  int where, int size, u32 value)  { -	void __iomem *base = ar71xx_pcicfg_base; +	void __iomem *base = apc->cfg_base;  	u32 ad_cbe;  	value = value << (8 * (where & 3)); @@ -162,7 +164,8 @@ static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus,  					 unsigned int devfn,  					 int where, int size, u32 cmd)  { -	void __iomem *base = ar71xx_pcicfg_base; +	struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); +	void __iomem *base = apc->cfg_base;  	u32 addr;  	addr = ar71xx_pci_bus_addr(bus, devfn, where); @@ -171,13 +174,14 @@ static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus,  	__raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0),  		     base + AR71XX_PCI_REG_CFG_CBE); -	return ar71xx_pci_check_error(1); +	return ar71xx_pci_check_error(apc, 1);  }  static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,  				  int where, int size, u32 *value)  { -	void __iomem *base = ar71xx_pcicfg_base; +	struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); +	void __iomem *base = apc->cfg_base;  	unsigned long flags;  	u32 data;  	int err; @@ -186,7 +190,7 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,  	ret = PCIBIOS_SUCCESSFUL;  	data = ~0; -	spin_lock_irqsave(&ar71xx_pci_lock, flags); +	spin_lock_irqsave(&apc->lock, flags);  	err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size,  				     AR71XX_PCI_CFG_CMD_READ); @@ -195,7 +199,7 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,  	else  		data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); -	spin_unlock_irqrestore(&ar71xx_pci_lock, flags); +	spin_unlock_irqrestore(&apc->lock, flags);  	*value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; @@ -205,7 +209,8 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,  static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,  				   int where, int size, u32 value)  { -	void __iomem *base = ar71xx_pcicfg_base; +	struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); +	void __iomem *base = apc->cfg_base;  	unsigned long flags;  	int err;  	int ret; @@ -213,7 +218,7 @@ static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,  	value = value << (8 * (where & 3));  	ret = PCIBIOS_SUCCESSFUL; -	spin_lock_irqsave(&ar71xx_pci_lock, flags); +	spin_lock_irqsave(&apc->lock, flags);  	err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size,  				     AR71XX_PCI_CFG_CMD_WRITE); @@ -222,7 +227,7 @@ static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,  	else  		__raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); -	spin_unlock_irqrestore(&ar71xx_pci_lock, flags); +	spin_unlock_irqrestore(&apc->lock, flags);  	return ret;  } @@ -232,45 +237,28 @@ static struct pci_ops ar71xx_pci_ops = {  	.write	= ar71xx_pci_write_config,  }; -static struct resource ar71xx_pci_io_resource = { -	.name		= "PCI IO space", -	.start		= 0, -	.end		= 0, -	.flags		= IORESOURCE_IO, -}; - -static struct resource ar71xx_pci_mem_resource = { -	.name		= "PCI memory space", -	.start		= AR71XX_PCI_MEM_BASE, -	.end		= AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, -	.flags		= IORESOURCE_MEM -}; - -static struct pci_controller ar71xx_pci_controller = { -	.pci_ops	= &ar71xx_pci_ops, -	.mem_resource	= &ar71xx_pci_mem_resource, -	.io_resource	= &ar71xx_pci_io_resource, -}; -  static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc)  { +	struct ar71xx_pci_controller *apc;  	void __iomem *base = ath79_reset_base;  	u32 pending; +	apc = irq_get_handler_data(irq); +  	pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &  		  __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);  	if (pending & AR71XX_PCI_INT_DEV0) -		generic_handle_irq(ATH79_PCI_IRQ(0)); +		generic_handle_irq(apc->irq_base + 0);  	else if (pending & AR71XX_PCI_INT_DEV1) -		generic_handle_irq(ATH79_PCI_IRQ(1)); +		generic_handle_irq(apc->irq_base + 1);  	else if (pending & AR71XX_PCI_INT_DEV2) -		generic_handle_irq(ATH79_PCI_IRQ(2)); +		generic_handle_irq(apc->irq_base + 2);  	else if (pending & AR71XX_PCI_INT_CORE) -		generic_handle_irq(ATH79_PCI_IRQ(4)); +		generic_handle_irq(apc->irq_base + 4);  	else  		spurious_interrupt(); @@ -278,10 +266,14 @@ static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc)  static void ar71xx_pci_irq_unmask(struct irq_data *d)  { -	unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; +	struct ar71xx_pci_controller *apc; +	unsigned int irq;  	void __iomem *base = ath79_reset_base;  	u32 t; +	apc = irq_data_get_irq_chip_data(d); +	irq = d->irq - apc->irq_base; +  	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);  	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); @@ -291,10 +283,14 @@ static void ar71xx_pci_irq_unmask(struct irq_data *d)  static void ar71xx_pci_irq_mask(struct irq_data *d)  { -	unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; +	struct ar71xx_pci_controller *apc; +	unsigned int irq;  	void __iomem *base = ath79_reset_base;  	u32 t; +	apc = irq_data_get_irq_chip_data(d); +	irq = d->irq - apc->irq_base; +  	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);  	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); @@ -309,7 +305,7 @@ static struct irq_chip ar71xx_pci_irq_chip = {  	.irq_mask_ack	= ar71xx_pci_irq_mask,  }; -static __init void ar71xx_pci_irq_init(void) +static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)  {  	void __iomem *base = ath79_reset_base;  	int i; @@ -319,15 +315,19 @@ static __init void ar71xx_pci_irq_init(void)  	BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); -	for (i = ATH79_PCI_IRQ_BASE; -	     i < ATH79_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) +	apc->irq_base = ATH79_PCI_IRQ_BASE; +	for (i = apc->irq_base; +	     i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) {  		irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip,  					 handle_level_irq); +		irq_set_chip_data(i, apc); +	} -	irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar71xx_pci_irq_handler); +	irq_set_handler_data(apc->irq, apc); +	irq_set_chained_handler(apc->irq, ar71xx_pci_irq_handler);  } -static __init void ar71xx_pci_reset(void) +static void ar71xx_pci_reset(void)  {  	void __iomem *ddr_base = ath79_ddr_base; @@ -349,27 +349,83 @@ static __init void ar71xx_pci_reset(void)  	mdelay(100);  } -__init int ar71xx_pcibios_init(void) +static int ar71xx_pci_probe(struct platform_device *pdev)  { +	struct ar71xx_pci_controller *apc; +	struct resource *res;  	u32 t; -	ar71xx_pcicfg_base = ioremap(AR71XX_PCI_CFG_BASE, AR71XX_PCI_CFG_SIZE); -	if (ar71xx_pcicfg_base == NULL) +	apc = devm_kzalloc(&pdev->dev, sizeof(struct ar71xx_pci_controller), +			   GFP_KERNEL); +	if (!apc) +		return -ENOMEM; + +	spin_lock_init(&apc->lock); + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); +	if (!res) +		return -EINVAL; + +	apc->cfg_base = devm_request_and_ioremap(&pdev->dev, res); +	if (!apc->cfg_base)  		return -ENOMEM; +	apc->irq = platform_get_irq(pdev, 0); +	if (apc->irq < 0) +		return -EINVAL; + +	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); +	if (!res) +		return -EINVAL; + +	apc->io_res.parent = res; +	apc->io_res.name = "PCI IO space"; +	apc->io_res.start = res->start; +	apc->io_res.end = res->end; +	apc->io_res.flags = IORESOURCE_IO; + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); +	if (!res) +		return -EINVAL; + +	apc->mem_res.parent = res; +	apc->mem_res.name = "PCI memory space"; +	apc->mem_res.start = res->start; +	apc->mem_res.end = res->end; +	apc->mem_res.flags = IORESOURCE_MEM; +  	ar71xx_pci_reset();  	/* setup COMMAND register */  	t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE  	  | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; -	ar71xx_pci_local_write(PCI_COMMAND, 4, t); +	ar71xx_pci_local_write(apc, PCI_COMMAND, 4, t);  	/* clear bus errors */ -	ar71xx_pci_check_error(1); +	ar71xx_pci_check_error(apc, 1); + +	ar71xx_pci_irq_init(apc); -	ar71xx_pci_irq_init(); +	apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; +	apc->pci_ctrl.mem_resource = &apc->mem_res; +	apc->pci_ctrl.io_resource = &apc->io_res; -	register_pci_controller(&ar71xx_pci_controller); +	register_pci_controller(&apc->pci_ctrl);  	return 0;  } + +static struct platform_driver ar71xx_pci_driver = { +	.probe = ar71xx_pci_probe, +	.driver = { +		.name = "ar71xx-pci", +		.owner = THIS_MODULE, +	}, +}; + +static int __init ar71xx_pci_init(void) +{ +	return platform_driver_register(&ar71xx_pci_driver); +} + +postcore_initcall(ar71xx_pci_init); diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 279585d6eca..8a0700d448f 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -9,19 +9,13 @@   *  by the Free Software Foundation.   */ +#include <linux/spinlock.h>  #include <linux/irq.h>  #include <linux/pci.h> +#include <linux/module.h> +#include <linux/platform_device.h>  #include <asm/mach-ath79/ath79.h>  #include <asm/mach-ath79/ar71xx_regs.h> -#include <asm/mach-ath79/pci.h> - -#define AR724X_PCI_CFG_BASE	0x14000000 -#define AR724X_PCI_CFG_SIZE	0x1000 -#define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000) -#define AR724X_PCI_CTRL_SIZE	0x100 - -#define AR724X_PCI_MEM_BASE	0x10000000 -#define AR724X_PCI_MEM_SIZE	0x04000000  #define AR724X_PCI_REG_RESET		0x18  #define AR724X_PCI_REG_INT_STATUS	0x4c @@ -35,38 +29,112 @@  #define AR7240_BAR0_WAR_VALUE	0xffff -static DEFINE_SPINLOCK(ar724x_pci_lock); -static void __iomem *ar724x_pci_devcfg_base; -static void __iomem *ar724x_pci_ctrl_base; +#define AR724X_PCI_CMD_INIT	(PCI_COMMAND_MEMORY |		\ +				 PCI_COMMAND_MASTER |		\ +				 PCI_COMMAND_INVALIDATE |	\ +				 PCI_COMMAND_PARITY |		\ +				 PCI_COMMAND_SERR |		\ +				 PCI_COMMAND_FAST_BACK) + +struct ar724x_pci_controller { +	void __iomem *devcfg_base; +	void __iomem *ctrl_base; +	void __iomem *crp_base; + +	int irq; +	int irq_base; + +	bool link_up; +	bool bar0_is_cached; +	u32  bar0_value; -static u32 ar724x_pci_bar0_value; -static bool ar724x_pci_bar0_is_cached; -static bool ar724x_pci_link_up; +	spinlock_t lock; -static inline bool ar724x_pci_check_link(void) +	struct pci_controller pci_controller; +	struct resource io_res; +	struct resource mem_res; +}; + +static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)  {  	u32 reset; -	reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET); +	reset = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET);  	return reset & AR724X_PCI_RESET_LINK_UP;  } +static inline struct ar724x_pci_controller * +pci_bus_to_ar724x_controller(struct pci_bus *bus) +{ +	struct pci_controller *hose; + +	hose = (struct pci_controller *) bus->sysdata; +	return container_of(hose, struct ar724x_pci_controller, pci_controller); +} + +static int ar724x_pci_local_write(struct ar724x_pci_controller *apc, +				  int where, int size, u32 value) +{ +	unsigned long flags; +	void __iomem *base; +	u32 data; +	int s; + +	WARN_ON(where & (size - 1)); + +	if (!apc->link_up) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	base = apc->crp_base; + +	spin_lock_irqsave(&apc->lock, flags); +	data = __raw_readl(base + (where & ~3)); + +	switch (size) { +	case 1: +		s = ((where & 3) * 8); +		data &= ~(0xff << s); +		data |= ((value & 0xff) << s); +		break; +	case 2: +		s = ((where & 2) * 8); +		data &= ~(0xffff << s); +		data |= ((value & 0xffff) << s); +		break; +	case 4: +		data = value; +		break; +	default: +		spin_unlock_irqrestore(&apc->lock, flags); +		return PCIBIOS_BAD_REGISTER_NUMBER; +	} + +	__raw_writel(data, base + (where & ~3)); +	/* flush write */ +	__raw_readl(base + (where & ~3)); +	spin_unlock_irqrestore(&apc->lock, flags); + +	return PCIBIOS_SUCCESSFUL; +} +  static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,  			    int size, uint32_t *value)  { +	struct ar724x_pci_controller *apc;  	unsigned long flags;  	void __iomem *base;  	u32 data; -	if (!ar724x_pci_link_up) +	apc = pci_bus_to_ar724x_controller(bus); +	if (!apc->link_up)  		return PCIBIOS_DEVICE_NOT_FOUND;  	if (devfn)  		return PCIBIOS_DEVICE_NOT_FOUND; -	base = ar724x_pci_devcfg_base; +	base = apc->devcfg_base; -	spin_lock_irqsave(&ar724x_pci_lock, flags); +	spin_lock_irqsave(&apc->lock, flags);  	data = __raw_readl(base + (where & ~3));  	switch (size) { @@ -85,17 +153,17 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,  	case 4:  		break;  	default: -		spin_unlock_irqrestore(&ar724x_pci_lock, flags); +		spin_unlock_irqrestore(&apc->lock, flags);  		return PCIBIOS_BAD_REGISTER_NUMBER;  	} -	spin_unlock_irqrestore(&ar724x_pci_lock, flags); +	spin_unlock_irqrestore(&apc->lock, flags);  	if (where == PCI_BASE_ADDRESS_0 && size == 4 && -	    ar724x_pci_bar0_is_cached) { +	    apc->bar0_is_cached) {  		/* use the cached value */ -		*value = ar724x_pci_bar0_value; +		*value = apc->bar0_value;  	} else {  		*value = data;  	} @@ -106,12 +174,14 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,  static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,  			     int size, uint32_t value)  { +	struct ar724x_pci_controller *apc;  	unsigned long flags;  	void __iomem *base;  	u32 data;  	int s; -	if (!ar724x_pci_link_up) +	apc = pci_bus_to_ar724x_controller(bus); +	if (!apc->link_up)  		return PCIBIOS_DEVICE_NOT_FOUND;  	if (devfn) @@ -129,18 +199,18 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,  			 * BAR0 register in order to make the device memory  			 * accessible.  			 */ -			ar724x_pci_bar0_is_cached = true; -			ar724x_pci_bar0_value = value; +			apc->bar0_is_cached = true; +			apc->bar0_value = value;  			value = AR7240_BAR0_WAR_VALUE;  		} else { -			ar724x_pci_bar0_is_cached = false; +			apc->bar0_is_cached = false;  		}  	} -	base = ar724x_pci_devcfg_base; +	base = apc->devcfg_base; -	spin_lock_irqsave(&ar724x_pci_lock, flags); +	spin_lock_irqsave(&apc->lock, flags);  	data = __raw_readl(base + (where & ~3));  	switch (size) { @@ -158,7 +228,7 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,  		data = value;  		break;  	default: -		spin_unlock_irqrestore(&ar724x_pci_lock, flags); +		spin_unlock_irqrestore(&apc->lock, flags);  		return PCIBIOS_BAD_REGISTER_NUMBER;  	} @@ -166,7 +236,7 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,  	__raw_writel(data, base + (where & ~3));  	/* flush write */  	__raw_readl(base + (where & ~3)); -	spin_unlock_irqrestore(&ar724x_pci_lock, flags); +	spin_unlock_irqrestore(&apc->lock, flags);  	return PCIBIOS_SUCCESSFUL;  } @@ -176,38 +246,20 @@ static struct pci_ops ar724x_pci_ops = {  	.write	= ar724x_pci_write,  }; -static struct resource ar724x_io_resource = { -	.name	= "PCI IO space", -	.start	= 0, -	.end	= 0, -	.flags	= IORESOURCE_IO, -}; - -static struct resource ar724x_mem_resource = { -	.name	= "PCI memory space", -	.start	= AR724X_PCI_MEM_BASE, -	.end	= AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1, -	.flags	= IORESOURCE_MEM, -}; - -static struct pci_controller ar724x_pci_controller = { -	.pci_ops	= &ar724x_pci_ops, -	.io_resource	= &ar724x_io_resource, -	.mem_resource	= &ar724x_mem_resource, -}; -  static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)  { +	struct ar724x_pci_controller *apc;  	void __iomem *base;  	u32 pending; -	base = ar724x_pci_ctrl_base; +	apc = irq_get_handler_data(irq); +	base = apc->ctrl_base;  	pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &  		  __raw_readl(base + AR724X_PCI_REG_INT_MASK);  	if (pending & AR724X_PCI_INT_DEV0) -		generic_handle_irq(ATH79_PCI_IRQ(0)); +		generic_handle_irq(apc->irq_base + 0);  	else  		spurious_interrupt(); @@ -215,13 +267,17 @@ static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)  static void ar724x_pci_irq_unmask(struct irq_data *d)  { +	struct ar724x_pci_controller *apc;  	void __iomem *base; +	int offset;  	u32 t; -	base = ar724x_pci_ctrl_base; +	apc = irq_data_get_irq_chip_data(d); +	base = apc->ctrl_base; +	offset = apc->irq_base - d->irq; -	switch (d->irq) { -	case ATH79_PCI_IRQ(0): +	switch (offset) { +	case 0:  		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);  		__raw_writel(t | AR724X_PCI_INT_DEV0,  			     base + AR724X_PCI_REG_INT_MASK); @@ -232,13 +288,17 @@ static void ar724x_pci_irq_unmask(struct irq_data *d)  static void ar724x_pci_irq_mask(struct irq_data *d)  { +	struct ar724x_pci_controller *apc;  	void __iomem *base; +	int offset;  	u32 t; -	base = ar724x_pci_ctrl_base; +	apc = irq_data_get_irq_chip_data(d); +	base = apc->ctrl_base; +	offset = apc->irq_base - d->irq; -	switch (d->irq) { -	case ATH79_PCI_IRQ(0): +	switch (offset) { +	case 0:  		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);  		__raw_writel(t & ~AR724X_PCI_INT_DEV0,  			     base + AR724X_PCI_REG_INT_MASK); @@ -262,53 +322,123 @@ static struct irq_chip ar724x_pci_irq_chip = {  	.irq_mask_ack	= ar724x_pci_irq_mask,  }; -static void __init ar724x_pci_irq_init(int irq) +static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc, +				int id)  {  	void __iomem *base;  	int i; -	base = ar724x_pci_ctrl_base; +	base = apc->ctrl_base;  	__raw_writel(0, base + AR724X_PCI_REG_INT_MASK);  	__raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); -	BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT); +	apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT); -	for (i = ATH79_PCI_IRQ_BASE; -	     i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++) +	for (i = apc->irq_base; +	     i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {  		irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,  					 handle_level_irq); +		irq_set_chip_data(i, apc); +	} -	irq_set_chained_handler(irq, ar724x_pci_irq_handler); +	irq_set_handler_data(apc->irq, apc); +	irq_set_chained_handler(apc->irq, ar724x_pci_irq_handler);  } -int __init ar724x_pcibios_init(int irq) +static int ar724x_pci_probe(struct platform_device *pdev)  { -	int ret; +	struct ar724x_pci_controller *apc; +	struct resource *res; +	int id; -	ret = -ENOMEM; +	id = pdev->id; +	if (id == -1) +		id = 0; -	ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE, -					 AR724X_PCI_CFG_SIZE); -	if (ar724x_pci_devcfg_base == NULL) -		goto err; +	apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller), +			    GFP_KERNEL); +	if (!apc) +		return -ENOMEM; -	ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE, -				       AR724X_PCI_CTRL_SIZE); -	if (ar724x_pci_ctrl_base == NULL) -		goto err_unmap_devcfg; +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base"); +	if (!res) +		return -EINVAL; -	ar724x_pci_link_up = ar724x_pci_check_link(); -	if (!ar724x_pci_link_up) -		pr_warn("ar724x: PCIe link is down\n"); +	apc->ctrl_base = devm_request_and_ioremap(&pdev->dev, res); +	if (apc->ctrl_base == NULL) +		return -EBUSY; -	ar724x_pci_irq_init(irq); -	register_pci_controller(&ar724x_pci_controller); +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); +	if (!res) +		return -EINVAL; -	return PCIBIOS_SUCCESSFUL; +	apc->devcfg_base = devm_request_and_ioremap(&pdev->dev, res); +	if (!apc->devcfg_base) +		return -EBUSY; + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base"); +	if (!res) +		return -EINVAL; -err_unmap_devcfg: -	iounmap(ar724x_pci_devcfg_base); -err: -	return ret; +	apc->crp_base = devm_request_and_ioremap(&pdev->dev, res); +	if (apc->crp_base == NULL) +		return -EBUSY; + +	apc->irq = platform_get_irq(pdev, 0); +	if (apc->irq < 0) +		return -EINVAL; + +	spin_lock_init(&apc->lock); + +	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); +	if (!res) +		return -EINVAL; + +	apc->io_res.parent = res; +	apc->io_res.name = "PCI IO space"; +	apc->io_res.start = res->start; +	apc->io_res.end = res->end; +	apc->io_res.flags = IORESOURCE_IO; + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); +	if (!res) +		return -EINVAL; + +	apc->mem_res.parent = res; +	apc->mem_res.name = "PCI memory space"; +	apc->mem_res.start = res->start; +	apc->mem_res.end = res->end; +	apc->mem_res.flags = IORESOURCE_MEM; + +	apc->pci_controller.pci_ops = &ar724x_pci_ops; +	apc->pci_controller.io_resource = &apc->io_res; +	apc->pci_controller.mem_resource = &apc->mem_res; + +	apc->link_up = ar724x_pci_check_link(apc); +	if (!apc->link_up) +		dev_warn(&pdev->dev, "PCIe link is down\n"); + +	ar724x_pci_irq_init(apc, id); + +	ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT); + +	register_pci_controller(&apc->pci_controller); + +	return 0;  } + +static struct platform_driver ar724x_pci_driver = { +	.probe = ar724x_pci_probe, +	.driver = { +		.name = "ar724x-pci", +		.owner = THIS_MODULE, +	}, +}; + +static int __init ar724x_pci_init(void) +{ +	return platform_driver_register(&ar724x_pci_driver); +} + +postcore_initcall(ar724x_pci_init); diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 95681789b51..f32664bbbe1 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -129,8 +129,16 @@ static int ltq_pci_startup(struct platform_device *pdev)  	/* setup reset gpio used by pci */  	reset_gpio = of_get_named_gpio(node, "gpio-reset", 0); -	if (gpio_is_valid(reset_gpio)) -		devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset"); +	if (gpio_is_valid(reset_gpio)) { +		int ret = devm_gpio_request(&pdev->dev, +						reset_gpio, "pci-reset"); +		if (ret) { +			dev_err(&pdev->dev, +				"failed to request gpio %d\n", reset_gpio); +			return ret; +		} +		gpio_direction_output(reset_gpio, 1); +	}  	/* enable auto-switching between PCI and EBU */  	ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c index ad55f2cfeec..653d2db9e0c 100644 --- a/arch/mips/pci/pci-xlp.c +++ b/arch/mips/pci/pci-xlp.c @@ -46,6 +46,7 @@  #include <asm/netlogic/interrupt.h>  #include <asm/netlogic/haldefs.h> +#include <asm/netlogic/common.h>  #include <asm/netlogic/xlp-hal/iomap.h>  #include <asm/netlogic/xlp-hal/pic.h> @@ -64,8 +65,12 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,  	u32 data;  	u32 *cfgaddr; +	where &= ~3; +	if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) +		return 0xffffffff; +  	cfgaddr = (u32 *)(pci_config_base + -			pci_cfg_addr(bus->number, devfn, where & ~3)); +			pci_cfg_addr(bus->number, devfn, where));  	data = *cfgaddr;  	return data;  } @@ -157,32 +162,38 @@ struct pci_controller nlm_pci_controller = {  	.io_offset	= 0x00000000UL,  }; -static int get_irq_vector(const struct pci_dev *dev) +static struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)  { -	/* -	 * For XLP PCIe, there is an IRQ per Link, find out which -	 * link the device is on to assign interrupts -	*/ -	if (dev->bus->self == NULL) -		return 0; +	struct pci_bus *bus, *p; -	switch	(dev->bus->self->devfn) { -	case 0x8: -		return PIC_PCIE_LINK_0_IRQ; -	case 0x9: -		return PIC_PCIE_LINK_1_IRQ; -	case 0xa: -		return PIC_PCIE_LINK_2_IRQ; -	case 0xb: -		return PIC_PCIE_LINK_3_IRQ; -	} -	WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn); -	return 0; +	/* Find the bridge on bus 0 */ +	bus = dev->bus; +	for (p = bus->parent; p && p->number != 0; p = p->parent) +		bus = p; + +	return p ? bus->self : NULL; +} + +static inline int nlm_pci_link_to_irq(int link) +{ +	return PIC_PCIE_LINK_0_IRQ + link;  }  int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)  { -	return get_irq_vector(dev); +	struct pci_dev *lnkdev; +	int lnkslot, lnkfunc; + +	/* +	 * For XLP PCIe, there is an IRQ per Link, find out which +	 * link the device is on to assign interrupts +	*/ +	lnkdev = xlp_get_pcie_link(dev); +	if (lnkdev == NULL) +		return 0; +	lnkfunc = PCI_FUNC(lnkdev->devfn); +	lnkslot = PCI_SLOT(lnkdev->devfn); +	return nlm_irq_to_xirq(lnkslot / 8, nlm_pci_link_to_irq(lnkfunc));  }  /* Do platform specific device initialization at pci_enable_device() time */ @@ -191,42 +202,48 @@ int pcibios_plat_dev_init(struct pci_dev *dev)  	return 0;  } -static int xlp_enable_pci_bswap(void) +/* + * If big-endian, enable hardware byteswap on the PCIe bridges. + * This will make both the SoC and PCIe devices behave consistently with + * readl/writel. + */ +#ifdef __BIG_ENDIAN +static void xlp_config_pci_bswap(int node, int link)  { -	uint64_t pciebase, sysbase; -	int node, i; +	uint64_t nbubase, lnkbase;  	u32 reg; -	/* Chip-0 so node set to 0 */ -	node = 0; -	sysbase = nlm_get_bridge_regbase(node); +	nbubase = nlm_get_bridge_regbase(node); +	lnkbase = nlm_get_pcie_base(node, link); +  	/*  	 *  Enable byte swap in hardware. Program each link's PCIe SWAP regions  	 * from the link's address ranges.  	 */ -	for (i = 0; i < 4; i++) { -		pciebase = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, i)); -		if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) -			continue; +	reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link); +	nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg); -		reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_BASE0 + i); -		nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_BASE, reg); +	reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_LIMIT0 + link); +	nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff); -		reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_LIMIT0 + i); -		nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_LIM, -			reg | 0xfff); +	reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link); +	nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg); -		reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_BASE0 + i); -		nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_BASE, reg); - -		reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_LIMIT0 + i); -		nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); -	} -	return 0; +	reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link); +	nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff);  } +#else +/* Swap configuration not needed in little-endian mode */ +static inline void xlp_config_pci_bswap(int node, int link) {} +#endif /* __BIG_ENDIAN */  static int __init pcibios_init(void)  { +	struct nlm_soc_info *nodep; +	uint64_t pciebase; +	int link, n; +	u32 reg; +  	/* Firmware assigns PCI resources */  	pci_set_flags(PCI_PROBE_ONLY);  	pci_config_base = ioremap(XLP_DEFAULT_PCI_ECFG_BASE, 64 << 20); @@ -235,7 +252,26 @@ static int __init pcibios_init(void)  	ioport_resource.start =	 0;  	ioport_resource.end   = ~0; -	xlp_enable_pci_bswap(); +	for (n = 0; n < NLM_NR_NODES; n++) { +		nodep = nlm_get_node(n); +		if (!nodep->coremask) +			continue;	/* node does not exist */ + +		for (link = 0; link < 4; link++) { +			pciebase = nlm_get_pcie_base(n, link); +			if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) +				continue; +			xlp_config_pci_bswap(n, link); + +			/* put in intpin and irq - u-boot does not */ +			reg = nlm_read_pci_reg(pciebase, 0xf); +			reg &= ~0x1fu; +			reg |= (1 << 8) | nlm_pci_link_to_irq(link); +			nlm_write_pci_reg(pciebase, 0xf, reg); +			pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link); +		} +	} +  	set_io_port_base(CKSEG1);  	nlm_pci_controller.io_map_base = CKSEG1; diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index e8a14a6514c..0872f12f268 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -175,9 +175,20 @@ static DEFINE_MUTEX(pci_scan_mutex);  void register_pci_controller(struct pci_controller *hose)  { -	if (request_resource(&iomem_resource, hose->mem_resource) < 0) +	struct resource *parent; + +	parent = hose->mem_resource->parent; +	if (!parent) +		parent = &iomem_resource; + +	if (request_resource(parent, hose->mem_resource) < 0)  		goto out; -	if (request_resource(&ioport_resource, hose->io_resource) < 0) { + +	parent = hose->io_resource->parent; +	if (!parent) +		parent = &ioport_resource; + +	if (request_resource(parent, hose->io_resource) < 0) {  		release_resource(hose->mem_resource);  		goto out;  	} diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig new file mode 100644 index 00000000000..a0b0197cab0 --- /dev/null +++ b/arch/mips/ralink/Kconfig @@ -0,0 +1,32 @@ +if RALINK + +choice +	prompt "Ralink SoC selection" +	default SOC_RT305X +	help +	  Select Ralink MIPS SoC type. + +	config SOC_RT305X +		bool "RT305x" +		select USB_ARCH_HAS_HCD +		select USB_ARCH_HAS_OHCI +		select USB_ARCH_HAS_EHCI + +endchoice + +choice +	prompt "Devicetree selection" +	default DTB_RT_NONE +	help +	  Select the devicetree. + +	config DTB_RT_NONE +		bool "None" + +	config DTB_RT305X_EVAL +		bool "RT305x eval kit" +		depends on SOC_RT305X + +endchoice + +endif diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile new file mode 100644 index 00000000000..939757f0e71 --- /dev/null +++ b/arch/mips/ralink/Makefile @@ -0,0 +1,15 @@ +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation.# +# Makefile for the Ralink common stuff +# +# Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> +# Copyright (C) 2013 John Crispin <blogic@openwrt.org> + +obj-y := prom.o of.o reset.o clk.o irq.o + +obj-$(CONFIG_SOC_RT305X) += rt305x.o + +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + +obj-y += dts/ diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform new file mode 100644 index 00000000000..6babd65765e --- /dev/null +++ b/arch/mips/ralink/Platform @@ -0,0 +1,10 @@ +# +# Ralink SoC common stuff +# +core-$(CONFIG_RALINK)		+= arch/mips/ralink/ +cflags-$(CONFIG_RALINK)		+= -I$(srctree)/arch/mips/include/asm/mach-ralink + +# +# Ralink RT305x +# +load-$(CONFIG_SOC_RT305X)	+= 0xffffffff80000000 diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c new file mode 100644 index 00000000000..8dfa22ff300 --- /dev/null +++ b/arch/mips/ralink/clk.c @@ -0,0 +1,72 @@ +/* + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License version 2 as published + *  by the Free Software Foundation. + * + *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + *  Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clkdev.h> +#include <linux/clk.h> + +#include <asm/time.h> + +#include "common.h" + +struct clk { +	struct clk_lookup cl; +	unsigned long rate; +}; + +void ralink_clk_add(const char *dev, unsigned long rate) +{ +	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + +	if (!clk) +		panic("failed to add clock\n"); + +	clk->cl.dev_id = dev; +	clk->cl.clk = clk; + +	clk->rate = rate; + +	clkdev_add(&clk->cl); +} + +/* + * Linux clock API + */ +int clk_enable(struct clk *clk) +{ +	return 0; +} +EXPORT_SYMBOL_GPL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL_GPL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ +	return clk->rate; +} +EXPORT_SYMBOL_GPL(clk_get_rate); + +void __init plat_time_init(void) +{ +	struct clk *clk; + +	ralink_of_remap(); + +	ralink_clk_init(); +	clk = clk_get_sys("cpu", NULL); +	if (IS_ERR(clk)) +		panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); +	pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); +	mips_hpt_frequency = clk_get_rate(clk) / 2; +	clk_put(clk); +} diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h new file mode 100644 index 00000000000..300990313e1 --- /dev/null +++ b/arch/mips/ralink/common.h @@ -0,0 +1,44 @@ +/* + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License version 2 as published + *  by the Free Software Foundation. + * + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RALINK_COMMON_H__ +#define _RALINK_COMMON_H__ + +#define RAMIPS_SYS_TYPE_LEN	32 + +struct ralink_pinmux_grp { +	const char *name; +	u32 mask; +	int gpio_first; +	int gpio_last; +}; + +struct ralink_pinmux { +	struct ralink_pinmux_grp *mode; +	struct ralink_pinmux_grp *uart; +	int uart_shift; +	void (*wdt_reset)(void); +}; +extern struct ralink_pinmux gpio_pinmux; + +struct ralink_soc_info { +	unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; +	unsigned char *compatible; +}; +extern struct ralink_soc_info soc_info; + +extern void ralink_of_remap(void); + +extern void ralink_clk_init(void); +extern void ralink_clk_add(const char *dev, unsigned long rate); + +extern void prom_soc_init(struct ralink_soc_info *soc_info); + +__iomem void *plat_of_remap_node(const char *node); + +#endif /* _RALINK_COMMON_H__ */ diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile new file mode 100644 index 00000000000..1a69fb30095 --- /dev/null +++ b/arch/mips/ralink/dts/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi new file mode 100644 index 00000000000..069d0660e1d --- /dev/null +++ b/arch/mips/ralink/dts/rt3050.dtsi @@ -0,0 +1,106 @@ +/ { +	#address-cells = <1>; +	#size-cells = <1>; +	compatible = "ralink,rt3050-soc", "ralink,rt3052-soc"; + +	cpus { +		cpu@0 { +			compatible = "mips,mips24KEc"; +		}; +	}; + +	chosen { +		bootargs = "console=ttyS0,57600 init=/init"; +	}; + +	cpuintc: cpuintc@0 { +		#address-cells = <0>; +		#interrupt-cells = <1>; +		interrupt-controller; +		compatible = "mti,cpu-interrupt-controller"; +	}; + +	palmbus@10000000 { +		compatible = "palmbus"; +		reg = <0x10000000 0x200000>; +                ranges = <0x0 0x10000000 0x1FFFFF>; + +		#address-cells = <1>; +		#size-cells = <1>; + +		sysc@0 { +			compatible = "ralink,rt3052-sysc", "ralink,rt3050-sysc"; +			reg = <0x0 0x100>; +		}; + +		timer@100 { +			compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt"; +			reg = <0x100 0x100>; +		}; + +		intc: intc@200 { +			compatible = "ralink,rt3052-intc", "ralink,rt2880-intc"; +			reg = <0x200 0x100>; + +			interrupt-controller; +			#interrupt-cells = <1>; + +			interrupt-parent = <&cpuintc>; +			interrupts = <2>; +		}; + +		memc@300 { +			compatible = "ralink,rt3052-memc", "ralink,rt3050-memc"; +			reg = <0x300 0x100>; +		}; + +		gpio0: gpio@600 { +			compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; +			reg = <0x600 0x34>; + +			gpio-controller; +			#gpio-cells = <2>; + +			ralink,ngpio = <24>; +			ralink,regs = [ 00 04 08 0c +					20 24 28 2c +					30 34 ]; +		}; + +		gpio1: gpio@638 { +			compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; +			reg = <0x638 0x24>; + +			gpio-controller; +			#gpio-cells = <2>; + +			ralink,ngpio = <16>; +			ralink,regs = [ 00 04 08 0c +					10 14 18 1c +					20 24 ]; +		}; + +		gpio2: gpio@660 { +			compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; +			reg = <0x660 0x24>; + +			gpio-controller; +			#gpio-cells = <2>; + +			ralink,ngpio = <12>; +			ralink,regs = [ 00 04 08 0c +					10 14 18 1c +					20 24 ]; +		}; + +		uartlite@c00 { +			compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a"; +			reg = <0xc00 0x100>; + +			interrupt-parent = <&intc>; +			interrupts = <12>; + +			reg-shift = <2>; +		}; +	}; +}; diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts new file mode 100644 index 00000000000..148a590bc41 --- /dev/null +++ b/arch/mips/ralink/dts/rt3052_eval.dts @@ -0,0 +1,52 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { +	#address-cells = <1>; +	#size-cells = <1>; +	compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc"; +	model = "Ralink RT3052 evaluation board"; + +	memory@0 { +		reg = <0x0 0x2000000>; +	}; + +	palmbus@10000000 { +		sysc@0 { +			ralink,pinmmux = "uartlite", "spi"; +			ralink,uartmux = "gpio"; +			ralink,wdtmux = <0>; +		}; +	}; + +	cfi@1f000000 { +		compatible = "cfi-flash"; +		reg = <0x1f000000 0x800000>; + +		bank-width = <2>; +		device-width = <2>; +		#address-cells = <1>; +		#size-cells = <1>; + +		partition@0 { +			label = "uboot"; +			reg = <0x0 0x30000>; +			read-only; +		}; +		partition@30000 { +			label = "uboot-env"; +			reg = <0x30000 0x10000>; +			read-only; +		}; +		partition@40000 { +			label = "calibration"; +			reg = <0x40000 0x10000>; +			read-only; +		}; +		partition@50000 { +			label = "linux"; +			reg = <0x50000 0x7b0000>; +		}; +	}; +}; diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c new file mode 100644 index 00000000000..c4ae47eb24a --- /dev/null +++ b/arch/mips/ralink/early_printk.c @@ -0,0 +1,44 @@ +/* + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License version 2 as published + *  by the Free Software Foundation. + * + *  Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + */ + +#include <linux/io.h> +#include <linux/serial_reg.h> + +#include <asm/addrspace.h> + +#define EARLY_UART_BASE         0x10000c00 + +#define UART_REG_RX             0x00 +#define UART_REG_TX             0x04 +#define UART_REG_IER            0x08 +#define UART_REG_IIR            0x0c +#define UART_REG_FCR            0x10 +#define UART_REG_LCR            0x14 +#define UART_REG_MCR            0x18 +#define UART_REG_LSR            0x1c + +static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); + +static inline void uart_w32(u32 val, unsigned reg) +{ +	__raw_writel(val, uart_membase + reg); +} + +static inline u32 uart_r32(unsigned reg) +{ +	return __raw_readl(uart_membase + reg); +} + +void prom_putchar(unsigned char ch) +{ +	while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) +		; +	uart_w32(ch, UART_REG_TX); +	while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) +		; +} diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c new file mode 100644 index 00000000000..6d054c5ec9a --- /dev/null +++ b/arch/mips/ralink/irq.c @@ -0,0 +1,180 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/io.h> +#include <linux/bitops.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/irqdomain.h> +#include <linux/interrupt.h> + +#include <asm/irq_cpu.h> +#include <asm/mipsregs.h> + +#include "common.h" + +/* INTC register offsets */ +#define INTC_REG_STATUS0	0x00 +#define INTC_REG_STATUS1	0x04 +#define INTC_REG_TYPE		0x20 +#define INTC_REG_RAW_STATUS	0x30 +#define INTC_REG_ENABLE		0x34 +#define INTC_REG_DISABLE	0x38 + +#define INTC_INT_GLOBAL		BIT(31) + +#define RALINK_CPU_IRQ_INTC	(MIPS_CPU_IRQ_BASE + 2) +#define RALINK_CPU_IRQ_FE	(MIPS_CPU_IRQ_BASE + 5) +#define RALINK_CPU_IRQ_WIFI	(MIPS_CPU_IRQ_BASE + 6) +#define RALINK_CPU_IRQ_COUNTER	(MIPS_CPU_IRQ_BASE + 7) + +/* we have a cascade of 8 irqs */ +#define RALINK_INTC_IRQ_BASE	8 + +/* we have 32 SoC irqs */ +#define RALINK_INTC_IRQ_COUNT	32 + +#define RALINK_INTC_IRQ_PERFC   (RALINK_INTC_IRQ_BASE + 9) + +static void __iomem *rt_intc_membase; + +static inline void rt_intc_w32(u32 val, unsigned reg) +{ +	__raw_writel(val, rt_intc_membase + reg); +} + +static inline u32 rt_intc_r32(unsigned reg) +{ +	return __raw_readl(rt_intc_membase + reg); +} + +static void ralink_intc_irq_unmask(struct irq_data *d) +{ +	rt_intc_w32(BIT(d->hwirq), INTC_REG_ENABLE); +} + +static void ralink_intc_irq_mask(struct irq_data *d) +{ +	rt_intc_w32(BIT(d->hwirq), INTC_REG_DISABLE); +} + +static struct irq_chip ralink_intc_irq_chip = { +	.name		= "INTC", +	.irq_unmask	= ralink_intc_irq_unmask, +	.irq_mask	= ralink_intc_irq_mask, +	.irq_mask_ack	= ralink_intc_irq_mask, +}; + +unsigned int __cpuinit get_c0_compare_int(void) +{ +	return CP0_LEGACY_COMPARE_IRQ; +} + +static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc) +{ +	u32 pending = rt_intc_r32(INTC_REG_STATUS0); + +	if (pending) { +		struct irq_domain *domain = irq_get_handler_data(irq); +		generic_handle_irq(irq_find_mapping(domain, __ffs(pending))); +	} else { +		spurious_interrupt(); +	} +} + +asmlinkage void plat_irq_dispatch(void) +{ +	unsigned long pending; + +	pending = read_c0_status() & read_c0_cause() & ST0_IM; + +	if (pending & STATUSF_IP7) +		do_IRQ(RALINK_CPU_IRQ_COUNTER); + +	else if (pending & STATUSF_IP5) +		do_IRQ(RALINK_CPU_IRQ_FE); + +	else if (pending & STATUSF_IP6) +		do_IRQ(RALINK_CPU_IRQ_WIFI); + +	else if (pending & STATUSF_IP2) +		do_IRQ(RALINK_CPU_IRQ_INTC); + +	else +		spurious_interrupt(); +} + +static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ +	irq_set_chip_and_handler(irq, &ralink_intc_irq_chip, handle_level_irq); + +	return 0; +} + +static const struct irq_domain_ops irq_domain_ops = { +	.xlate = irq_domain_xlate_onecell, +	.map = intc_map, +}; + +static int __init intc_of_init(struct device_node *node, +			       struct device_node *parent) +{ +	struct resource res; +	struct irq_domain *domain; +	int irq; + +	irq = irq_of_parse_and_map(node, 0); +	if (!irq) +		panic("Failed to get INTC IRQ"); + +	if (of_address_to_resource(node, 0, &res)) +		panic("Failed to get intc memory range"); + +	if (request_mem_region(res.start, resource_size(&res), +				res.name) < 0) +		pr_err("Failed to request intc memory"); + +	rt_intc_membase = ioremap_nocache(res.start, +					resource_size(&res)); +	if (!rt_intc_membase) +		panic("Failed to remap intc memory"); + +	/* disable all interrupts */ +	rt_intc_w32(~0, INTC_REG_DISABLE); + +	/* route all INTC interrupts to MIPS HW0 interrupt */ +	rt_intc_w32(0, INTC_REG_TYPE); + +	domain = irq_domain_add_legacy(node, RALINK_INTC_IRQ_COUNT, +			RALINK_INTC_IRQ_BASE, 0, &irq_domain_ops, NULL); +	if (!domain) +		panic("Failed to add irqdomain"); + +	rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE); + +	irq_set_chained_handler(irq, ralink_intc_irq_handler); +	irq_set_handler_data(irq, domain); + +	cp0_perfcount_irq = irq_create_mapping(domain, 9); + +	return 0; +} + +static struct of_device_id __initdata of_irq_ids[] = { +	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init }, +	{ .compatible = "ralink,rt2880-intc", .data = intc_of_init }, +	{}, +}; + +void __init arch_init_irq(void) +{ +	of_irq_init(of_irq_ids); +} + diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c new file mode 100644 index 00000000000..4165e70775b --- /dev/null +++ b/arch/mips/ralink/of.c @@ -0,0 +1,107 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/init.h> +#include <linux/of_fdt.h> +#include <linux/kernel.h> +#include <linux/bootmem.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> + +#include <asm/reboot.h> +#include <asm/bootinfo.h> +#include <asm/addrspace.h> + +#include "common.h" + +__iomem void *rt_sysc_membase; +__iomem void *rt_memc_membase; + +extern struct boot_param_header __dtb_start; + +__iomem void *plat_of_remap_node(const char *node) +{ +	struct resource res; +	struct device_node *np; + +	np = of_find_compatible_node(NULL, NULL, node); +	if (!np) +		panic("Failed to find %s node", node); + +	if (of_address_to_resource(np, 0, &res)) +		panic("Failed to get resource for %s", node); + +	if ((request_mem_region(res.start, +				resource_size(&res), +				res.name) < 0)) +		panic("Failed to request resources for %s", node); + +	return ioremap_nocache(res.start, resource_size(&res)); +} + +void __init device_tree_init(void) +{ +	unsigned long base, size; +	void *fdt_copy; + +	if (!initial_boot_params) +		return; + +	base = virt_to_phys((void *)initial_boot_params); +	size = be32_to_cpu(initial_boot_params->totalsize); + +	/* Before we do anything, lets reserve the dt blob */ +	reserve_bootmem(base, size, BOOTMEM_DEFAULT); + +	/* The strings in the flattened tree are referenced directly by the +	 * device tree, so copy the flattened device tree from init memory +	 * to regular memory. +	 */ +	fdt_copy = alloc_bootmem(size); +	memcpy(fdt_copy, initial_boot_params, size); +	initial_boot_params = fdt_copy; + +	unflatten_device_tree(); + +	/* free the space reserved for the dt blob */ +	free_bootmem(base, size); +} + +void __init plat_mem_setup(void) +{ +	set_io_port_base(KSEG1); + +	/* +	 * Load the builtin devicetree. This causes the chosen node to be +	 * parsed resulting in our memory appearing +	 */ +	__dt_setup_arch(&__dtb_start); +} + +static int __init plat_of_setup(void) +{ +	static struct of_device_id of_ids[3]; +	int len = sizeof(of_ids[0].compatible); + +	if (!of_have_populated_dt()) +		panic("device tree not present"); + +	strncpy(of_ids[0].compatible, soc_info.compatible, len); +	strncpy(of_ids[1].compatible, "palmbus", len); + +	if (of_platform_populate(NULL, of_ids, NULL, NULL)) +		panic("failed to populate DT\n"); + +	return 0; +} + +arch_initcall(plat_of_setup); diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c new file mode 100644 index 00000000000..9c64f029d04 --- /dev/null +++ b/arch/mips/ralink/prom.c @@ -0,0 +1,69 @@ +/* + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License version 2 as published + *  by the Free Software Foundation. + * + *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> + *  Copyright (C) 2010 Joonas Lahtinen <joonas.lahtinen@gmail.com> + *  Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/string.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> + +#include <asm/bootinfo.h> +#include <asm/addrspace.h> + +#include "common.h" + +struct ralink_soc_info soc_info; + +const char *get_system_type(void) +{ +	return soc_info.sys_type; +} + +static __init void prom_init_cmdline(int argc, char **argv) +{ +	int i; + +	pr_debug("prom: fw_arg0=%08x fw_arg1=%08x fw_arg2=%08x fw_arg3=%08x\n", +	       (unsigned int)fw_arg0, (unsigned int)fw_arg1, +	       (unsigned int)fw_arg2, (unsigned int)fw_arg3); + +	argc = fw_arg0; +	argv = (char **) KSEG1ADDR(fw_arg1); + +	if (!argv) { +		pr_debug("argv=%p is invalid, skipping\n", +		       argv); +		return; +	} + +	for (i = 0; i < argc; i++) { +		char *p = (char *) KSEG1ADDR(argv[i]); + +		if (CPHYSADDR(p) && *p) { +			pr_debug("argv[%d]: %s\n", i, p); +			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); +			strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); +		} +	} +} + +void __init prom_init(void) +{ +	int argc; +	char **argv; + +	prom_soc_init(&soc_info); + +	pr_info("SoC Type: %s\n", get_system_type()); + +	prom_init_cmdline(argc, argv); +} + +void __init prom_free_prom_memory(void) +{ +} diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c new file mode 100644 index 00000000000..22120e512e7 --- /dev/null +++ b/arch/mips/ralink/reset.c @@ -0,0 +1,44 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/pm.h> +#include <linux/io.h> + +#include <asm/reboot.h> + +#include <asm/mach-ralink/ralink_regs.h> + +/* Reset Control */ +#define SYSC_REG_RESET_CTRL     0x034 +#define RSTCTL_RESET_SYSTEM     BIT(0) + +static void ralink_restart(char *command) +{ +	local_irq_disable(); +	rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL); +	unreachable(); +} + +static void ralink_halt(void) +{ +	local_irq_disable(); +	unreachable(); +} + +static int __init mips_reboot_setup(void) +{ +	_machine_restart = ralink_restart; +	_machine_halt = ralink_halt; +	pm_power_off = ralink_halt; + +	return 0; +} + +arch_initcall(mips_reboot_setup); diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c new file mode 100644 index 00000000000..0a4bbdcf59d --- /dev/null +++ b/arch/mips/ralink/rt305x.c @@ -0,0 +1,242 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <asm/mipsregs.h> +#include <asm/mach-ralink/ralink_regs.h> +#include <asm/mach-ralink/rt305x.h> + +#include "common.h" + +enum rt305x_soc_type rt305x_soc; + +struct ralink_pinmux_grp mode_mux[] = { +	{ +		.name = "i2c", +		.mask = RT305X_GPIO_MODE_I2C, +		.gpio_first = RT305X_GPIO_I2C_SD, +		.gpio_last = RT305X_GPIO_I2C_SCLK, +	}, { +		.name = "spi", +		.mask = RT305X_GPIO_MODE_SPI, +		.gpio_first = RT305X_GPIO_SPI_EN, +		.gpio_last = RT305X_GPIO_SPI_CLK, +	}, { +		.name = "uartlite", +		.mask = RT305X_GPIO_MODE_UART1, +		.gpio_first = RT305X_GPIO_UART1_TXD, +		.gpio_last = RT305X_GPIO_UART1_RXD, +	}, { +		.name = "jtag", +		.mask = RT305X_GPIO_MODE_JTAG, +		.gpio_first = RT305X_GPIO_JTAG_TDO, +		.gpio_last = RT305X_GPIO_JTAG_TDI, +	}, { +		.name = "mdio", +		.mask = RT305X_GPIO_MODE_MDIO, +		.gpio_first = RT305X_GPIO_MDIO_MDC, +		.gpio_last = RT305X_GPIO_MDIO_MDIO, +	}, { +		.name = "sdram", +		.mask = RT305X_GPIO_MODE_SDRAM, +		.gpio_first = RT305X_GPIO_SDRAM_MD16, +		.gpio_last = RT305X_GPIO_SDRAM_MD31, +	}, { +		.name = "rgmii", +		.mask = RT305X_GPIO_MODE_RGMII, +		.gpio_first = RT305X_GPIO_GE0_TXD0, +		.gpio_last = RT305X_GPIO_GE0_RXCLK, +	}, {0} +}; + +struct ralink_pinmux_grp uart_mux[] = { +	{ +		.name = "uartf", +		.mask = RT305X_GPIO_MODE_UARTF, +		.gpio_first = RT305X_GPIO_7, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "pcm uartf", +		.mask = RT305X_GPIO_MODE_PCM_UARTF, +		.gpio_first = RT305X_GPIO_7, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "pcm i2s", +		.mask = RT305X_GPIO_MODE_PCM_I2S, +		.gpio_first = RT305X_GPIO_7, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "i2s uartf", +		.mask = RT305X_GPIO_MODE_I2S_UARTF, +		.gpio_first = RT305X_GPIO_7, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "pcm gpio", +		.mask = RT305X_GPIO_MODE_PCM_GPIO, +		.gpio_first = RT305X_GPIO_10, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "gpio uartf", +		.mask = RT305X_GPIO_MODE_GPIO_UARTF, +		.gpio_first = RT305X_GPIO_7, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "gpio i2s", +		.mask = RT305X_GPIO_MODE_GPIO_I2S, +		.gpio_first = RT305X_GPIO_7, +		.gpio_last = RT305X_GPIO_14, +	}, { +		.name = "gpio", +		.mask = RT305X_GPIO_MODE_GPIO, +	}, {0} +}; + +void rt305x_wdt_reset(void) +{ +	u32 t; + +	/* enable WDT reset output on pin SRAM_CS_N */ +	t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); +	t |= RT305X_SYSCFG_SRAM_CS0_MODE_WDT << +		RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT; +	rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); +} + +struct ralink_pinmux gpio_pinmux = { +	.mode = mode_mux, +	.uart = uart_mux, +	.uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, +	.wdt_reset = rt305x_wdt_reset, +}; + +void __init ralink_clk_init(void) +{ +	unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; +	u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); + +	if (soc_is_rt305x() || soc_is_rt3350()) { +		t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & +		     RT305X_SYSCFG_CPUCLK_MASK; +		switch (t) { +		case RT305X_SYSCFG_CPUCLK_LOW: +			cpu_rate = 320000000; +			break; +		case RT305X_SYSCFG_CPUCLK_HIGH: +			cpu_rate = 384000000; +			break; +		} +		sys_rate = uart_rate = wdt_rate = cpu_rate / 3; +	} else if (soc_is_rt3352()) { +		t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & +		     RT3352_SYSCFG0_CPUCLK_MASK; +		switch (t) { +		case RT3352_SYSCFG0_CPUCLK_LOW: +			cpu_rate = 384000000; +			break; +		case RT3352_SYSCFG0_CPUCLK_HIGH: +			cpu_rate = 400000000; +			break; +		} +		sys_rate = wdt_rate = cpu_rate / 3; +		uart_rate = 40000000; +	} else if (soc_is_rt5350()) { +		t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & +		     RT5350_SYSCFG0_CPUCLK_MASK; +		switch (t) { +		case RT5350_SYSCFG0_CPUCLK_360: +			cpu_rate = 360000000; +			sys_rate = cpu_rate / 3; +			break; +		case RT5350_SYSCFG0_CPUCLK_320: +			cpu_rate = 320000000; +			sys_rate = cpu_rate / 4; +			break; +		case RT5350_SYSCFG0_CPUCLK_300: +			cpu_rate = 300000000; +			sys_rate = cpu_rate / 3; +			break; +		default: +			BUG(); +		} +		uart_rate = 40000000; +		wdt_rate = sys_rate; +	} else { +		BUG(); +	} + +	ralink_clk_add("cpu", cpu_rate); +	ralink_clk_add("10000b00.spi", sys_rate); +	ralink_clk_add("10000100.timer", wdt_rate); +	ralink_clk_add("10000500.uart", uart_rate); +	ralink_clk_add("10000c00.uartlite", uart_rate); +} + +void __init ralink_of_remap(void) +{ +	rt_sysc_membase = plat_of_remap_node("ralink,rt3050-sysc"); +	rt_memc_membase = plat_of_remap_node("ralink,rt3050-memc"); + +	if (!rt_sysc_membase || !rt_memc_membase) +		panic("Failed to remap core resources"); +} + +void prom_soc_init(struct ralink_soc_info *soc_info) +{ +	void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); +	unsigned char *name; +	u32 n0; +	u32 n1; +	u32 id; + +	n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); +	n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); + +	if (n0 == RT3052_CHIP_NAME0 && n1 == RT3052_CHIP_NAME1) { +		unsigned long icache_sets; + +		icache_sets = (read_c0_config1() >> 22) & 7; +		if (icache_sets == 1) { +			rt305x_soc = RT305X_SOC_RT3050; +			name = "RT3050"; +			soc_info->compatible = "ralink,rt3050-soc"; +		} else { +			rt305x_soc = RT305X_SOC_RT3052; +			name = "RT3052"; +			soc_info->compatible = "ralink,rt3052-soc"; +		} +	} else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) { +		rt305x_soc = RT305X_SOC_RT3350; +		name = "RT3350"; +		soc_info->compatible = "ralink,rt3350-soc"; +	} else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) { +		rt305x_soc = RT305X_SOC_RT3352; +		name = "RT3352"; +		soc_info->compatible = "ralink,rt3352-soc"; +	} else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) { +		rt305x_soc = RT305X_SOC_RT5350; +		name = "RT5350"; +		soc_info->compatible = "ralink,rt5350-soc"; +	} else { +		panic("rt305x: unknown SoC, n0:%08x n1:%08x\n", n0, n1); +	} + +	id = __raw_readl(sysc + SYSC_REG_CHIP_ID); + +	snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, +		"Ralink %s id:%u rev:%u", +		name, +		(id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, +		(id & CHIP_ID_REV_MASK)); +} diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c index 984e561f0f7..b952d5b1af8 100644 --- a/arch/mips/sgi-ip27/ip27-console.c +++ b/arch/mips/sgi-ip27/ip27-console.c @@ -31,7 +31,7 @@ static inline struct ioc3_uartregs *console_uart(void)  	return &ioc3->sregs.uarta;  } -void __init prom_putchar(char c) +void prom_putchar(char c)  {  	struct ioc3_uartregs *uart = console_uart(); diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 560fe899175..5524f2c7b05 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -513,19 +513,19 @@ void __init txx9_sio_init(unsigned long baseaddr, int irq,  }  #ifdef CONFIG_EARLY_PRINTK -static void __init null_prom_putchar(char c) +static void null_prom_putchar(char c)  {  } -void (*txx9_prom_putchar)(char c) __initdata = null_prom_putchar; +void (*txx9_prom_putchar)(char c) = null_prom_putchar; -void __init prom_putchar(char c) +void prom_putchar(char c)  {  	txx9_prom_putchar(c);  }  static void __iomem *early_txx9_sio_port; -static void __init early_txx9_sio_putchar(char c) +static void early_txx9_sio_putchar(char c)  {  #define TXX9_SICISR	0x0c  #define TXX9_SITFIFO	0x1c diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h index c1be4397b1e..a18abfc558e 100644 --- a/arch/mn10300/include/asm/dma-mapping.h +++ b/arch/mn10300/include/asm/dma-mapping.h @@ -168,4 +168,19 @@ void dma_cache_sync(void *vaddr, size_t size,  	mn10300_dcache_flush_inv();  } +/* Not supported for now */ +static inline int dma_mmap_coherent(struct device *dev, +				    struct vm_area_struct *vma, void *cpu_addr, +				    dma_addr_t dma_addr, size_t size) +{ +	return -EINVAL; +} + +static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size) +{ +	return -EINVAL; +} +  #endif diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index 467bbd510ea..106b395688e 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h @@ -238,4 +238,19 @@ void * sba_get_iommu(struct parisc_device *dev);  /* At the moment, we panic on error for IOMMU resource exaustion */  #define dma_mapping_error(dev, x)	0 +/* This API cannot be supported on PA-RISC */ +static inline int dma_mmap_coherent(struct device *dev, +				    struct vm_area_struct *vma, void *cpu_addr, +				    dma_addr_t dma_addr, size_t size) +{ +	return -EINVAL; +} + +static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size) +{ +	return -EINVAL; +} +  #endif diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 56585086413..7443481a315 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -115,11 +115,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)  	sldi	r29,r5,SID_SHIFT - VPN_SHIFT  	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)  	or	r29,r28,r29 - -	/* Calculate hash value for primary slot and store it in r28 */ -	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */ -	rldicl	r0,r3,64-12,48		/* (ea >> 12) & 0xffff */ -	xor	r28,r5,r0 +	/* +	 * Calculate hash value for primary slot and store it in r28 +	 * r3 = va, r5 = vsid +	 * r0 = (va >> 12) & ((1ul << (28 - 12)) -1) +	 */ +	rldicl	r0,r3,64-12,48 +	xor	r28,r5,r0		/* hash */  	b	4f  3:	/* Calc vpn and put it in r29 */ @@ -130,11 +132,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)  	/*  	 * calculate hash value for primary slot and  	 * store it in r28 for 1T segment +	 * r3 = va, r5 = vsid  	 */ -	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */ -	clrldi	r5,r5,40		/* vsid & 0xffffff */ -	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */ -	xor	r28,r28,r5 +	sldi	r28,r5,25		/* vsid << 25 */ +	/* r0 =  (va >> 12) & ((1ul << (40 - 12)) -1) */ +	rldicl	r0,r3,64-12,36 +	xor	r28,r28,r5		/* vsid ^ ( vsid << 25) */  	xor	r28,r28,r0		/* hash */  	/* Convert linux PTE bits into HW equivalents */ @@ -407,11 +410,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)  	 */  	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)  	or	r29,r28,r29 - -	/* Calculate hash value for primary slot and store it in r28 */ -	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */ -	rldicl	r0,r3,64-12,48		/* (ea >> 12) & 0xffff */ -	xor	r28,r5,r0 +	/* +	 * Calculate hash value for primary slot and store it in r28 +	 * r3 = va, r5 = vsid +	 * r0 = (va >> 12) & ((1ul << (28 - 12)) -1) +	 */ +	rldicl	r0,r3,64-12,48 +	xor	r28,r5,r0		/* hash */  	b	4f  3:	/* Calc vpn and put it in r29 */ @@ -426,11 +431,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)  	/*  	 * Calculate hash value for primary slot and  	 * store it in r28  for 1T segment +	 * r3 = va, r5 = vsid  	 */ -	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */ -	clrldi	r5,r5,40		/* vsid & 0xffffff */ -	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */ -	xor	r28,r28,r5 +	sldi	r28,r5,25		/* vsid << 25 */ +	/* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */ +	rldicl	r0,r3,64-12,36 +	xor	r28,r28,r5		/* vsid ^ ( vsid << 25) */  	xor	r28,r28,r0		/* hash */  	/* Convert linux PTE bits into HW equivalents */ @@ -752,25 +758,27 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)  	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)  	or	r29,r28,r29 -	/* Calculate hash value for primary slot and store it in r28 */ -	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */ -	rldicl	r0,r3,64-16,52		/* (ea >> 16) & 0xfff */ -	xor	r28,r5,r0 +	/* Calculate hash value for primary slot and store it in r28 +	 * r3 = va, r5 = vsid +	 * r0 = (va >> 16) & ((1ul << (28 - 16)) -1) +	 */ +	rldicl	r0,r3,64-16,52 +	xor	r28,r5,r0		/* hash */  	b	4f  3:	/* Calc vpn and put it in r29 */  	sldi	r29,r5,SID_SHIFT_1T - VPN_SHIFT  	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)  	or	r29,r28,r29 -  	/*  	 * calculate hash value for primary slot and  	 * store it in r28 for 1T segment +	 * r3 = va, r5 = vsid  	 */ -	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */ -	clrldi	r5,r5,40		/* vsid & 0xffffff */ -	rldicl	r0,r3,64-16,40		/* (ea >> 16) & 0xffffff */ -	xor	r28,r28,r5 +	sldi	r28,r5,25		/* vsid << 25 */ +	/* r0 = (va >> 16) & ((1ul << (40 - 16)) -1) */ +	rldicl	r0,r3,64-16,40 +	xor	r28,r28,r5		/* vsid ^ ( vsid << 25) */  	xor	r28,r28,r0		/* hash */  	/* Convert linux PTE bits into HW equivalents */ diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 102ff7cb3e4..142c4ceff11 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -207,7 +207,7 @@ sysexit_from_sys_call:  	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jnz ia32_ret_from_sys_call  	TRACE_IRQS_ON -	sti +	ENABLE_INTERRUPTS(CLBR_NONE)  	movl %eax,%esi		/* second arg, syscall return value */  	cmpl $-MAX_ERRNO,%eax	/* is it an error ? */  	jbe 1f @@ -217,7 +217,7 @@ sysexit_from_sys_call:  	call __audit_syscall_exit  	movq RAX-ARGOFFSET(%rsp),%rax	/* reload syscall return value */  	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi -	cli +	DISABLE_INTERRUPTS(CLBR_NONE)  	TRACE_IRQS_OFF  	testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jz \exit diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index fe9edec6698..84c1309c4c0 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -298,8 +298,7 @@ struct _cache_attr {  			 unsigned int);  }; -#ifdef CONFIG_AMD_NB - +#if defined(CONFIG_AMD_NB) && defined(CONFIG_SYSFS)  /*   * L3 cache descriptors   */ @@ -524,9 +523,9 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,  static struct _cache_attr subcaches =  	__ATTR(subcaches, 0644, show_subcaches, store_subcaches); -#else	/* CONFIG_AMD_NB */ +#else  #define amd_init_l3_cache(x, y) -#endif /* CONFIG_AMD_NB */ +#endif  /* CONFIG_AMD_NB && CONFIG_SYSFS */  static int  __cpuinit cpuid4_cache_lookup_regs(int index, diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 93b9e1181f8..4914e94ad6e 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -2019,7 +2019,10 @@ __init int intel_pmu_init(void)  		break;  	case 28: /* Atom */ -	case 54: /* Cedariew */ +	case 38: /* Lincroft */ +	case 39: /* Penwell */ +	case 53: /* Cloverview */ +	case 54: /* Cedarview */  		memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,  		       sizeof(hw_cache_event_ids)); @@ -2084,6 +2087,7 @@ __init int intel_pmu_init(void)  		pr_cont("SandyBridge events, ");  		break;  	case 58: /* IvyBridge */ +	case 62: /* IvyBridge EP */  		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,  		       sizeof(hw_cache_event_ids));  		memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index f2af39f5dc3..4820c232a0b 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -19,7 +19,7 @@ static const u64 p6_perfmon_event_map[] =  }; -static __initconst u64 p6_hw_cache_event_ids +static u64 p6_hw_cache_event_ids  				[PERF_COUNT_HW_CACHE_MAX]  				[PERF_COUNT_HW_CACHE_OP_MAX]  				[PERF_COUNT_HW_CACHE_RESULT_MAX] = diff --git a/arch/x86/tools/insn_sanity.c b/arch/x86/tools/insn_sanity.c index cc2f8c13128..872eb60e780 100644 --- a/arch/x86/tools/insn_sanity.c +++ b/arch/x86/tools/insn_sanity.c @@ -55,7 +55,7 @@ static FILE		*input_file;	/* Input file name */  static void usage(const char *err)  {  	if (err) -		fprintf(stderr, "Error: %s\n\n", err); +		fprintf(stderr, "%s: Error: %s\n\n", prog, err);  	fprintf(stderr, "Usage: %s [-y|-n|-v] [-s seed[,no]] [-m max] [-i input]\n", prog);  	fprintf(stderr, "\t-y	64bit mode\n");  	fprintf(stderr, "\t-n	32bit mode\n"); @@ -269,7 +269,13 @@ int main(int argc, char **argv)  		insns++;  	} -	fprintf(stdout, "%s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", (errors) ? "Failure" : "Success", insns, (input_file) ? "given" : "random", errors, seed); +	fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", +		prog, +		(errors) ? "Failure" : "Success", +		insns, +		(input_file) ? "given" : "random", +		errors, +		seed);  	return errors ? 1 : 0;  } diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h index 4acb5feba1f..172a02a6ad1 100644 --- a/arch/xtensa/include/asm/dma-mapping.h +++ b/arch/xtensa/include/asm/dma-mapping.h @@ -170,4 +170,19 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,  	consistent_sync(vaddr, size, direction);  } +/* Not supported for now */ +static inline int dma_mmap_coherent(struct device *dev, +				    struct vm_area_struct *vma, void *cpu_addr, +				    dma_addr_t dma_addr, size_t size) +{ +	return -EINVAL; +} + +static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt, +				  void *cpu_addr, dma_addr_t dma_addr, +				  size_t size) +{ +	return -EINVAL; +} +  #endif	/* _XTENSA_DMA_MAPPING_H */ diff --git a/block/genhd.c b/block/genhd.c index 9a289d7c84b..3993ebf4135 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -35,6 +35,8 @@ static DEFINE_IDR(ext_devt_idr);  static struct device_type disk_type; +static void disk_check_events(struct disk_events *ev, +			      unsigned int *clearing_ptr);  static void disk_alloc_events(struct gendisk *disk);  static void disk_add_events(struct gendisk *disk);  static void disk_del_events(struct gendisk *disk); @@ -1549,6 +1551,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)  	const struct block_device_operations *bdops = disk->fops;  	struct disk_events *ev = disk->ev;  	unsigned int pending; +	unsigned int clearing = mask;  	if (!ev) {  		/* for drivers still using the old ->media_changed method */ @@ -1558,34 +1561,53 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)  		return 0;  	} -	/* tell the workfn about the events being cleared */ +	disk_block_events(disk); + +	/* +	 * store the union of mask and ev->clearing on the stack so that the +	 * race with disk_flush_events does not cause ambiguity (ev->clearing +	 * can still be modified even if events are blocked). +	 */  	spin_lock_irq(&ev->lock); -	ev->clearing |= mask; +	clearing |= ev->clearing; +	ev->clearing = 0;  	spin_unlock_irq(&ev->lock); -	/* uncondtionally schedule event check and wait for it to finish */ -	disk_block_events(disk); -	queue_delayed_work(system_freezable_wq, &ev->dwork, 0); -	flush_delayed_work(&ev->dwork); -	__disk_unblock_events(disk, false); +	disk_check_events(ev, &clearing); +	/* +	 * if ev->clearing is not 0, the disk_flush_events got called in the +	 * middle of this function, so we want to run the workfn without delay. +	 */ +	__disk_unblock_events(disk, ev->clearing ? true : false);  	/* then, fetch and clear pending events */  	spin_lock_irq(&ev->lock); -	WARN_ON_ONCE(ev->clearing & mask);	/* cleared by workfn */  	pending = ev->pending & mask;  	ev->pending &= ~mask;  	spin_unlock_irq(&ev->lock); +	WARN_ON_ONCE(clearing & mask);  	return pending;  } +/* + * Separate this part out so that a different pointer for clearing_ptr can be + * passed in for disk_clear_events. + */  static void disk_events_workfn(struct work_struct *work)  {  	struct delayed_work *dwork = to_delayed_work(work);  	struct disk_events *ev = container_of(dwork, struct disk_events, dwork); + +	disk_check_events(ev, &ev->clearing); +} + +static void disk_check_events(struct disk_events *ev, +			      unsigned int *clearing_ptr) +{  	struct gendisk *disk = ev->disk;  	char *envp[ARRAY_SIZE(disk_uevents) + 1] = { }; -	unsigned int clearing = ev->clearing; +	unsigned int clearing = *clearing_ptr;  	unsigned int events;  	unsigned long intv;  	int nr_events = 0, i; @@ -1598,7 +1620,7 @@ static void disk_events_workfn(struct work_struct *work)  	events &= ~ev->pending;  	ev->pending |= events; -	ev->clearing &= ~clearing; +	*clearing_ptr &= ~clearing;  	intv = disk_events_poll_jiffies(disk);  	if (!ev->block && intv) diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index 6a0955e6d4f..53ecac5a216 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -636,82 +636,82 @@ struct rx_buf_desc {  #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE    #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE   -typedef volatile u_int  freg_t; +typedef volatile u_int	ffreg_t;  typedef u_int   rreg_t;  typedef struct _ffredn_t { -        freg_t  idlehead_high;  /* Idle cell header (high)              */ -        freg_t  idlehead_low;   /* Idle cell header (low)               */ -        freg_t  maxrate;        /* Maximum rate                         */ -        freg_t  stparms;        /* Traffic Management Parameters        */ -        freg_t  abrubr_abr;     /* ABRUBR Priority Byte 1, TCR Byte 0   */ -        freg_t  rm_type;        /*                                      */ -        u_int   filler5[0x17 - 0x06]; -        freg_t  cmd_reg;        /* Command register                     */ -        u_int   filler18[0x20 - 0x18]; -        freg_t  cbr_base;       /* CBR Pointer Base                     */ -        freg_t  vbr_base;       /* VBR Pointer Base                     */ -        freg_t  abr_base;       /* ABR Pointer Base                     */ -        freg_t  ubr_base;       /* UBR Pointer Base                     */ -        u_int   filler24; -        freg_t  vbrwq_base;     /* VBR Wait Queue Base                  */ -        freg_t  abrwq_base;     /* ABR Wait Queue Base                  */ -        freg_t  ubrwq_base;     /* UBR Wait Queue Base                  */ -        freg_t  vct_base;       /* Main VC Table Base                   */ -        freg_t  vcte_base;      /* Extended Main VC Table Base          */ -        u_int   filler2a[0x2C - 0x2A]; -        freg_t  cbr_tab_beg;    /* CBR Table Begin                      */ -        freg_t  cbr_tab_end;    /* CBR Table End                        */ -        freg_t  cbr_pointer;    /* CBR Pointer                          */ -        u_int   filler2f[0x30 - 0x2F]; -        freg_t  prq_st_adr;     /* Packet Ready Queue Start Address     */ -        freg_t  prq_ed_adr;     /* Packet Ready Queue End Address       */ -        freg_t  prq_rd_ptr;     /* Packet Ready Queue read pointer      */ -        freg_t  prq_wr_ptr;     /* Packet Ready Queue write pointer     */ -        freg_t  tcq_st_adr;     /* Transmit Complete Queue Start Address*/ -        freg_t  tcq_ed_adr;     /* Transmit Complete Queue End Address  */ -        freg_t  tcq_rd_ptr;     /* Transmit Complete Queue read pointer */ -        freg_t  tcq_wr_ptr;     /* Transmit Complete Queue write pointer*/ -        u_int   filler38[0x40 - 0x38]; -        freg_t  queue_base;     /* Base address for PRQ and TCQ         */ -        freg_t  desc_base;      /* Base address of descriptor table     */ -        u_int   filler42[0x45 - 0x42]; -        freg_t  mode_reg_0;     /* Mode register 0                      */ -        freg_t  mode_reg_1;     /* Mode register 1                      */ -        freg_t  intr_status_reg;/* Interrupt Status register            */ -        freg_t  mask_reg;       /* Mask Register                        */ -        freg_t  cell_ctr_high1; /* Total cell transfer count (high)     */ -        freg_t  cell_ctr_lo1;   /* Total cell transfer count (low)      */ -        freg_t  state_reg;      /* Status register                      */ -        u_int   filler4c[0x58 - 0x4c]; -        freg_t  curr_desc_num;  /* Contains the current descriptor num  */ -        freg_t  next_desc;      /* Next descriptor                      */ -        freg_t  next_vc;        /* Next VC                              */ -        u_int   filler5b[0x5d - 0x5b]; -        freg_t  present_slot_cnt;/* Present slot count                  */ -        u_int   filler5e[0x6a - 0x5e]; -        freg_t  new_desc_num;   /* New descriptor number                */ -        freg_t  new_vc;         /* New VC                               */ -        freg_t  sched_tbl_ptr;  /* Schedule table pointer               */ -        freg_t  vbrwq_wptr;     /* VBR wait queue write pointer         */ -        freg_t  vbrwq_rptr;     /* VBR wait queue read pointer          */ -        freg_t  abrwq_wptr;     /* ABR wait queue write pointer         */ -        freg_t  abrwq_rptr;     /* ABR wait queue read pointer          */ -        freg_t  ubrwq_wptr;     /* UBR wait queue write pointer         */ -        freg_t  ubrwq_rptr;     /* UBR wait queue read pointer          */ -        freg_t  cbr_vc;         /* CBR VC                               */ -        freg_t  vbr_sb_vc;      /* VBR SB VC                            */ -        freg_t  abr_sb_vc;      /* ABR SB VC                            */ -        freg_t  ubr_sb_vc;      /* UBR SB VC                            */ -        freg_t  vbr_next_link;  /* VBR next link                        */ -        freg_t  abr_next_link;  /* ABR next link                        */ -        freg_t  ubr_next_link;  /* UBR next link                        */ -        u_int   filler7a[0x7c-0x7a]; -        freg_t  out_rate_head;  /* Out of rate head                     */ -        u_int   filler7d[0xca-0x7d]; /* pad out to full address space   */ -        freg_t  cell_ctr_high1_nc;/* Total cell transfer count (high)   */ -        freg_t  cell_ctr_lo1_nc;/* Total cell transfer count (low)      */ -        u_int   fillercc[0x100-0xcc]; /* pad out to full address space   */ +	ffreg_t	idlehead_high;	/* Idle cell header (high)		*/ +	ffreg_t	idlehead_low;	/* Idle cell header (low)		*/ +	ffreg_t	maxrate;	/* Maximum rate				*/ +	ffreg_t	stparms;	/* Traffic Management Parameters	*/ +	ffreg_t	abrubr_abr;	/* ABRUBR Priority Byte 1, TCR Byte 0	*/ +	ffreg_t	rm_type;	/*					*/ +	u_int	filler5[0x17 - 0x06]; +	ffreg_t	cmd_reg;	/* Command register			*/ +	u_int	filler18[0x20 - 0x18]; +	ffreg_t	cbr_base;	/* CBR Pointer Base			*/ +	ffreg_t	vbr_base;	/* VBR Pointer Base			*/ +	ffreg_t	abr_base;	/* ABR Pointer Base			*/ +	ffreg_t	ubr_base;	/* UBR Pointer Base			*/ +	u_int	filler24; +	ffreg_t	vbrwq_base;	/* VBR Wait Queue Base			*/ +	ffreg_t	abrwq_base;	/* ABR Wait Queue Base			*/ +	ffreg_t	ubrwq_base;	/* UBR Wait Queue Base			*/ +	ffreg_t	vct_base;	/* Main VC Table Base			*/ +	ffreg_t	vcte_base;	/* Extended Main VC Table Base		*/ +	u_int	filler2a[0x2C - 0x2A]; +	ffreg_t	cbr_tab_beg;	/* CBR Table Begin			*/ +	ffreg_t	cbr_tab_end;	/* CBR Table End			*/ +	ffreg_t	cbr_pointer;	/* CBR Pointer				*/ +	u_int	filler2f[0x30 - 0x2F]; +	ffreg_t	prq_st_adr;	/* Packet Ready Queue Start Address	*/ +	ffreg_t	prq_ed_adr;	/* Packet Ready Queue End Address	*/ +	ffreg_t	prq_rd_ptr;	/* Packet Ready Queue read pointer	*/ +	ffreg_t	prq_wr_ptr;	/* Packet Ready Queue write pointer	*/ +	ffreg_t	tcq_st_adr;	/* Transmit Complete Queue Start Address*/ +	ffreg_t	tcq_ed_adr;	/* Transmit Complete Queue End Address	*/ +	ffreg_t	tcq_rd_ptr;	/* Transmit Complete Queue read pointer */ +	ffreg_t	tcq_wr_ptr;	/* Transmit Complete Queue write pointer*/ +	u_int	filler38[0x40 - 0x38]; +	ffreg_t	queue_base;	/* Base address for PRQ and TCQ		*/ +	ffreg_t	desc_base;	/* Base address of descriptor table	*/ +	u_int	filler42[0x45 - 0x42]; +	ffreg_t	mode_reg_0;	/* Mode register 0			*/ +	ffreg_t	mode_reg_1;	/* Mode register 1			*/ +	ffreg_t	intr_status_reg;/* Interrupt Status register		*/ +	ffreg_t	mask_reg;	/* Mask Register			*/ +	ffreg_t	cell_ctr_high1; /* Total cell transfer count (high)	*/ +	ffreg_t	cell_ctr_lo1;	/* Total cell transfer count (low)	*/ +	ffreg_t	state_reg;	/* Status register			*/ +	u_int	filler4c[0x58 - 0x4c]; +	ffreg_t	curr_desc_num;	/* Contains the current descriptor num	*/ +	ffreg_t	next_desc;	/* Next descriptor			*/ +	ffreg_t	next_vc;	/* Next VC				*/ +	u_int	filler5b[0x5d - 0x5b]; +	ffreg_t	present_slot_cnt;/* Present slot count			*/ +	u_int	filler5e[0x6a - 0x5e]; +	ffreg_t	new_desc_num;	/* New descriptor number		*/ +	ffreg_t	new_vc;		/* New VC				*/ +	ffreg_t	sched_tbl_ptr;	/* Schedule table pointer		*/ +	ffreg_t	vbrwq_wptr;	/* VBR wait queue write pointer		*/ +	ffreg_t	vbrwq_rptr;	/* VBR wait queue read pointer		*/ +	ffreg_t	abrwq_wptr;	/* ABR wait queue write pointer		*/ +	ffreg_t	abrwq_rptr;	/* ABR wait queue read pointer		*/ +	ffreg_t	ubrwq_wptr;	/* UBR wait queue write pointer		*/ +	ffreg_t	ubrwq_rptr;	/* UBR wait queue read pointer		*/ +	ffreg_t	cbr_vc;		/* CBR VC				*/ +	ffreg_t	vbr_sb_vc;	/* VBR SB VC				*/ +	ffreg_t	abr_sb_vc;	/* ABR SB VC				*/ +	ffreg_t	ubr_sb_vc;	/* UBR SB VC				*/ +	ffreg_t	vbr_next_link;	/* VBR next link			*/ +	ffreg_t	abr_next_link;	/* ABR next link			*/ +	ffreg_t	ubr_next_link;	/* UBR next link			*/ +	u_int	filler7a[0x7c-0x7a]; +	ffreg_t	out_rate_head;	/* Out of rate head			*/ +	u_int	filler7d[0xca-0x7d]; /* pad out to full address space	*/ +	ffreg_t	cell_ctr_high1_nc;/* Total cell transfer count (high)	*/ +	ffreg_t	cell_ctr_lo1_nc;/* Total cell transfer count (low)	*/ +	u_int	fillercc[0x100-0xcc]; /* pad out to full address space	 */  } ffredn_t;  typedef struct _rfredn_t { diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 19e3fbfd575..cb0c4548857 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -94,11 +94,16 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);  #ifdef CONFIG_BCMA_DRIVER_GPIO  /* driver_gpio.c */  int bcma_gpio_init(struct bcma_drv_cc *cc); +int bcma_gpio_unregister(struct bcma_drv_cc *cc);  #else  static inline int bcma_gpio_init(struct bcma_drv_cc *cc)  {  	return -ENOTSUPP;  } +static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc) +{ +	return 0; +}  #endif /* CONFIG_BCMA_DRIVER_GPIO */  #endif diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c index dbda91e4dff..1f0b83e18f6 100644 --- a/drivers/bcma/driver_chipcommon_nflash.c +++ b/drivers/bcma/driver_chipcommon_nflash.c @@ -21,7 +21,7 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)  	struct bcma_bus *bus = cc->core->bus;  	if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && -	    cc->core->id.rev != 0x38) { +	    cc->core->id.rev != 38) {  		bcma_err(bus, "NAND flash on unsupported board!\n");  		return -ENOTSUPP;  	} diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 9a6f585da2d..71f755c06fc 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -96,3 +96,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)  	return gpiochip_add(chip);  } + +int bcma_gpio_unregister(struct bcma_drv_cc *cc) +{ +	return gpiochip_remove(&cc->gpio); +} diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 4a92f647b58..324f9debda8 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -268,6 +268,13 @@ int bcma_bus_register(struct bcma_bus *bus)  void bcma_bus_unregister(struct bcma_bus *bus)  {  	struct bcma_device *cores[3]; +	int err; + +	err = bcma_gpio_unregister(&bus->drv_cc); +	if (err == -EBUSY) +		bcma_err(bus, "Some GPIOs are still in use.\n"); +	else if (err) +		bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);  	cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);  	cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index f58a4a4b4df..2b8303ad63c 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -168,7 +168,7 @@ static void wake_all_senders(struct drbd_tconn *tconn) {  }  /* must hold resource->req_lock */ -static void start_new_tl_epoch(struct drbd_tconn *tconn) +void start_new_tl_epoch(struct drbd_tconn *tconn)  {  	/* no point closing an epoch, if it is empty, anyways. */  	if (tconn->current_tle_writes == 0) diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 016de6b8bb5..c08d22964d0 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -267,6 +267,7 @@ struct bio_and_error {  	int error;  }; +extern void start_new_tl_epoch(struct drbd_tconn *tconn);  extern void drbd_req_destroy(struct kref *kref);  extern void _req_may_be_done(struct drbd_request *req,  		struct bio_and_error *m); diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 53bf6182bac..0fe220cfb9e 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c @@ -931,6 +931,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,  	enum drbd_state_rv rv = SS_SUCCESS;  	enum sanitize_state_warnings ssw;  	struct after_state_chg_work *ascw; +	bool did_remote, should_do_remote;  	os = drbd_read_state(mdev); @@ -981,11 +982,17 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,  	    (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))  		atomic_inc(&mdev->local_cnt); +	did_remote = drbd_should_do_remote(mdev->state);  	mdev->state.i = ns.i; +	should_do_remote = drbd_should_do_remote(mdev->state);  	mdev->tconn->susp = ns.susp;  	mdev->tconn->susp_nod = ns.susp_nod;  	mdev->tconn->susp_fen = ns.susp_fen; +	/* put replicated vs not-replicated requests in seperate epochs */ +	if (did_remote != should_do_remote) +		start_new_tl_epoch(mdev->tconn); +  	if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)  		drbd_print_uuids(mdev, "attached to UUIDs"); diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 9694dd99bbb..3fd10099045 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -626,12 +626,13 @@ static void mtip_timeout_function(unsigned long int data)  		}  	} -	if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { +	if (cmdto_cnt) {  		print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); - -		mtip_restart_port(port); +		if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { +			mtip_restart_port(port); +			wake_up_interruptible(&port->svc_wait); +		}  		clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); -		wake_up_interruptible(&port->svc_wait);  	}  	if (port->ic_pause_timer) { @@ -3887,7 +3888,12 @@ static int mtip_block_remove(struct driver_data *dd)  	 * Delete our gendisk structure. This also removes the device  	 * from /dev  	 */ -	del_gendisk(dd->disk); +	if (dd->disk) { +		if (dd->disk->queue) +			del_gendisk(dd->disk); +		else +			put_disk(dd->disk); +	}  	spin_lock(&rssd_index_lock);  	ida_remove(&rssd_index_ida, dd->index); @@ -3921,7 +3927,13 @@ static int mtip_block_shutdown(struct driver_data *dd)  		"Shutting down %s ...\n", dd->disk->disk_name);  	/* Delete our gendisk structure, and cleanup the blk queue. */ -	del_gendisk(dd->disk); +	if (dd->disk) { +		if (dd->disk->queue) +			del_gendisk(dd->disk); +		else +			put_disk(dd->disk); +	} +  	spin_lock(&rssd_index_lock);  	ida_remove(&rssd_index_ida, dd->index); diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 74374fb762a..5ac841ff6cc 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,  static void make_response(struct xen_blkif *blkif, u64 id,  			  unsigned short op, int st); -#define foreach_grant(pos, rbtree, node) \ -	for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \ +#define foreach_grant_safe(pos, n, rbtree, node) \ +	for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \ +	     (n) = rb_next(&(pos)->node); \  	     &(pos)->node != NULL; \ -	     (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node)) +	     (pos) = container_of(n, typeof(*(pos)), node), \ +	     (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)  static void add_persistent_gnt(struct rb_root *root, @@ -217,10 +219,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)  	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];  	struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];  	struct persistent_gnt *persistent_gnt; +	struct rb_node *n;  	int ret = 0;  	int segs_to_unmap = 0; -	foreach_grant(persistent_gnt, root, node) { +	foreach_grant_safe(persistent_gnt, n, root, node) {  		BUG_ON(persistent_gnt->handle ==  			BLKBACK_INVALID_HANDLE);  		gnttab_set_unmap_op(&unmap[segs_to_unmap], @@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)  			persistent_gnt->handle);  		pages[segs_to_unmap] = persistent_gnt->page; -		rb_erase(&persistent_gnt->node, root); -		kfree(persistent_gnt); -		num--;  		if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||  			!rb_next(&persistent_gnt->node)) { @@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)  			BUG_ON(ret);  			segs_to_unmap = 0;  		} + +		rb_erase(&persistent_gnt->node, root); +		kfree(persistent_gnt); +		num--;  	}  	BUG_ON(num != 0);  } diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 96e9b00db08..11043c18ac5 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -792,6 +792,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)  {  	struct llist_node *all_gnts;  	struct grant *persistent_gnt; +	struct llist_node *n;  	/* Prevent new requests being issued until we fix things up. */  	spin_lock_irq(&info->io_lock); @@ -804,7 +805,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)  	/* Remove all persistent grants */  	if (info->persistent_gnts_c) {  		all_gnts = llist_del_all(&info->persistent_gnts); -		llist_for_each_entry(persistent_gnt, all_gnts, node) { +		llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) {  			gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);  			__free_page(pfn_to_page(persistent_gnt->pfn));  			kfree(persistent_gnt); @@ -835,7 +836,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)  static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,  			     struct blkif_response *bret)  { -	int i; +	int i = 0;  	struct bio_vec *bvec;  	struct req_iterator iter;  	unsigned long flags; @@ -852,7 +853,8 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,  		 */  		rq_for_each_segment(bvec, s->request, iter) {  			BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE); -			i = offset >> PAGE_SHIFT; +			if (bvec->bv_offset < offset) +				i++;  			BUG_ON(i >= s->req.u.rw.nr_segments);  			shared_data = kmap_atomic(  				pfn_to_page(s->grants_used[i]->pfn)); @@ -861,7 +863,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,  				bvec->bv_len);  			bvec_kunmap_irq(bvec_data, &flags);  			kunmap_atomic(shared_data); -			offset += bvec->bv_len; +			offset = bvec->bv_offset + bvec->bv_len;  		}  	}  	/* Add the persistent grant into the list of free grants */ diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 684b0d53764..ee4dbeafb37 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -2062,7 +2062,8 @@ static void virtcons_remove(struct virtio_device *vdev)  	/* Disable interrupts for vqs */  	vdev->config->reset(vdev);  	/* Finish up work that's lined up */ -	cancel_work_sync(&portdev->control_work); +	if (use_multiport(portdev)) +		cancel_work_sync(&portdev->control_work);  	list_for_each_entry_safe(port, port2, &portdev->ports, list)  		unplug_port(port); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 4d0e60adbc6..a2d478e8692 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1313,14 +1313,18 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav  				if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {  					radeon_wait_for_vblank(rdev, i);  					tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; +					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);  					WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); +					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);  				}  			} else {  				tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);  				if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {  					radeon_wait_for_vblank(rdev, i);  					tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; +					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);  					WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); +					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);  				}  			}  			/* wait for the next frame */ @@ -1345,6 +1349,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav  		blackout &= ~BLACKOUT_MODE_MASK;  		WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);  	} +	/* wait for the MC to settle */ +	udelay(100);  }  void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) @@ -1378,11 +1384,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  			if (ASIC_IS_DCE6(rdev)) {  				tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);  				tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; +				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);  				WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); +				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);  			} else {  				tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);  				tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; +				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);  				WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); +				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);  			}  			/* wait for the next frame */  			frame_count = radeon_get_vblank_counter(rdev, i); @@ -2036,9 +2046,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  	WREG32(HDP_ADDR_CONFIG, gb_addr_config);  	WREG32(DMA_TILING_CONFIG, gb_addr_config); -	tmp = gb_addr_config & NUM_PIPES_MASK; -	tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, -					EVERGREEN_MAX_BACKENDS, disabled_rb_mask); +	if ((rdev->config.evergreen.max_backends == 1) && +	    (rdev->flags & RADEON_IS_IGP)) { +		if ((disabled_rb_mask & 3) == 1) { +			/* RB0 disabled, RB1 enabled */ +			tmp = 0x11111111; +		} else { +			/* RB1 disabled, RB0 enabled */ +			tmp = 0x00000000; +		} +	} else { +		tmp = gb_addr_config & NUM_PIPES_MASK; +		tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, +						EVERGREEN_MAX_BACKENDS, disabled_rb_mask); +	}  	WREG32(GB_BACKEND_MAP, tmp);  	WREG32(CGTS_SYS_TCC_DISABLE, 0); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index bc2540b17c5..becb03e8b32 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1462,12 +1462,15 @@ u32 r6xx_remap_render_backend(struct radeon_device *rdev,  			      u32 disabled_rb_mask)  {  	u32 rendering_pipe_num, rb_num_width, req_rb_num; -	u32 pipe_rb_ratio, pipe_rb_remain; +	u32 pipe_rb_ratio, pipe_rb_remain, tmp;  	u32 data = 0, mask = 1 << (max_rb_num - 1);  	unsigned i, j;  	/* mask out the RBs that don't exist on that asic */ -	disabled_rb_mask |= (0xff << max_rb_num) & 0xff; +	tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff); +	/* make sure at least one RB is available */ +	if ((tmp & 0xff) != 0xff) +		disabled_rb_mask = tmp;  	rendering_pipe_num = 1 << tiling_pipe_num;  	req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 9056fafb00e..0b202c07fe5 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1445,7 +1445,7 @@ static struct radeon_asic cayman_asic = {  	.vm = {  		.init = &cayman_vm_init,  		.fini = &cayman_vm_fini, -		.pt_ring_index = R600_RING_TYPE_DMA_INDEX, +		.pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,  		.set_page = &cayman_vm_set_page,  	},  	.ring = { @@ -1572,7 +1572,7 @@ static struct radeon_asic trinity_asic = {  	.vm = {  		.init = &cayman_vm_init,  		.fini = &cayman_vm_fini, -		.pt_ring_index = R600_RING_TYPE_DMA_INDEX, +		.pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,  		.set_page = &cayman_vm_set_page,  	},  	.ring = { @@ -1699,7 +1699,7 @@ static struct radeon_asic si_asic = {  	.vm = {  		.init = &si_vm_init,  		.fini = &si_vm_fini, -		.pt_ring_index = R600_RING_TYPE_DMA_INDEX, +		.pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,  		.set_page = &si_vm_set_page,  	},  	.ring = { diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 33a56a09ff1..3e403bdda58 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2470,6 +2470,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)  								   1),  								  ATOM_DEVICE_CRT1_SUPPORT);  				} +				/* RV100 board with external TDMS bit mis-set. +				 * Actually uses internal TMDS, clear the bit. +				 */ +				if (dev->pdev->device == 0x5159 && +				    dev->pdev->subsystem_vendor == 0x1014 && +				    dev->pdev->subsystem_device == 0x029A) { +					tmp &= ~(1 << 4); +				}  				if ((tmp >> 4) & 0x1) {  					devices |= ATOM_DEVICE_DFP2_SUPPORT;  					radeon_add_legacy_encoder(dev, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index ff3def78461..05c96fa0b05 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1115,8 +1115,10 @@ radeon_user_framebuffer_create(struct drm_device *dev,  	}  	radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); -	if (radeon_fb == NULL) +	if (radeon_fb == NULL) { +		drm_gem_object_unreference_unlocked(obj);  		return ERR_PTR(-ENOMEM); +	}  	ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);  	if (ret) { diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 2430d80b187..cd72062d5a9 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -377,6 +377,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi  {  	int r; +	/* make sure we aren't trying to allocate more space than there is on the ring */ +	if (ndw > (ring->ring_size / 4)) +		return -ENOMEM;  	/* Align requested size with padding so unlock_commit can  	 * pad safely */  	ndw = (ndw + ring->align_mask) & ~ring->align_mask; diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 0f656b111c1..a072fa8c46b 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,6 @@  cayman 0x9400  0x0000802C GRBM_GFX_INDEX +0x00008040 WAIT_UNTIL  0x000084FC CP_STRMOUT_CNTL  0x000085F0 CP_COHER_CNTL  0x000085F4 CP_COHER_SIZE diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 2bb6d0e84b3..435ed355136 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -336,6 +336,8 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)  				WREG32(R600_CITF_CNTL, blackout);  		}  	} +	/* wait for the MC to settle */ +	udelay(100);  }  void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 44420fca7df..8be35c809c7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -429,7 +429,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,  	struct ttm_bo_device *bdev = bo->bdev;  	struct ttm_bo_driver *driver = bdev->driver; -	fbo = kzalloc(sizeof(*fbo), GFP_KERNEL); +	fbo = kmalloc(sizeof(*fbo), GFP_KERNEL);  	if (!fbo)  		return -ENOMEM; @@ -448,7 +448,12 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,  	fbo->vm_node = NULL;  	atomic_set(&fbo->cpu_writers, 0); -	fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); +	spin_lock(&bdev->fence_lock); +	if (bo->sync_obj) +		fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); +	else +		fbo->sync_obj = NULL; +	spin_unlock(&bdev->fence_lock);  	kref_init(&fbo->list_kref);  	kref_init(&fbo->kref);  	fbo->destroy = &ttm_transfered_destroy; @@ -661,13 +666,11 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,  		 */  		set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); - -		/* ttm_buffer_object_transfer accesses bo->sync_obj */ -		ret = ttm_buffer_object_transfer(bo, &ghost_obj);  		spin_unlock(&bdev->fence_lock);  		if (tmp_obj)  			driver->sync_obj_unref(&tmp_obj); +		ret = ttm_buffer_object_transfer(bo, &ghost_obj);  		if (ret)  			return ret; diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index 4850d03870c..35275099caf 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c @@ -263,20 +263,15 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)  		struct qib_qp __rcu **qpp;  		qpp = &dev->qp_table[n]; -		q = rcu_dereference_protected(*qpp, -			lockdep_is_held(&dev->qpt_lock)); -		for (; q; qpp = &q->next) { +		for (; (q = rcu_dereference_protected(*qpp, +				lockdep_is_held(&dev->qpt_lock))) != NULL; +				qpp = &q->next)  			if (q == qp) {  				atomic_dec(&qp->refcount);  				*qpp = qp->next;  				rcu_assign_pointer(qp->next, NULL); -				q = rcu_dereference_protected(*qpp, -					lockdep_is_held(&dev->qpt_lock));  				break;  			} -			q = rcu_dereference_protected(*qpp, -				lockdep_is_held(&dev->qpt_lock)); -		}  	}  	spin_unlock_irqrestore(&dev->qpt_lock, flags); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 03103d2bd64..67b0c1d2367 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -741,6 +741,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_  	tx_req->mapping = addr; +	skb_orphan(skb); +	skb_dst_drop(skb); +  	rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),  		       addr, skb->len);  	if (unlikely(rc)) { @@ -752,9 +755,6 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_  		dev->trans_start = jiffies;  		++tx->tx_head; -		skb_orphan(skb); -		skb_dst_drop(skb); -  		if (++priv->tx_outstanding == ipoib_sendq_size) {  			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",  				  tx->qp->qp_num); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index a1bca70e20a..2cfa76f5d99 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -600,6 +600,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,  		netif_stop_queue(dev);  	} +	skb_orphan(skb); +	skb_dst_drop(skb); +  	rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),  		       address->ah, qpn, tx_req, phead, hlen);  	if (unlikely(rc)) { @@ -615,9 +618,6 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,  		address->last_send = priv->tx_head;  		++priv->tx_head; - -		skb_orphan(skb); -		skb_dst_drop(skb);  	}  	if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index e10e525f33e..296941a9ae2 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -374,6 +374,7 @@ static int usb_keene_probe(struct usb_interface *intf,  	radio->vdev.ioctl_ops = &usb_keene_ioctl_ops;  	radio->vdev.lock = &radio->lock;  	radio->vdev.release = video_device_release_empty; +	radio->vdev.vfl_dir = VFL_DIR_TX;  	radio->usbdev = interface_to_usbdev(intf);  	radio->intf = intf; diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index a082e400ed0..1507c9d508d 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c @@ -250,6 +250,7 @@ static struct video_device radio_si4713_vdev_template = {  	.name			= "radio-si4713",  	.release		= video_device_release,  	.ioctl_ops		= &radio_si4713_ioctl_ops, +	.vfl_dir		= VFL_DIR_TX,  };  /* Platform driver interface */ diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index c48be195bba..cabbe3adf43 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1971,6 +1971,7 @@ static struct video_device wl1273_viddev_template = {  	.ioctl_ops		= &wl1273_ioctl_ops,  	.name			= WL1273_FM_DRIVER_NAME,  	.release		= wl1273_vdev_release, +	.vfl_dir		= VFL_DIR_TX,  };  static int wl1273_fm_radio_remove(struct platform_device *pdev) diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 048de453603..0a8ee8fab92 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -518,6 +518,16 @@ static struct video_device fm_viddev_template = {  	.ioctl_ops = &fm_drv_ioctl_ops,  	.name = FM_DRV_NAME,  	.release = video_device_release, +	/* +	 * To ensure both the tuner and modulator ioctls are accessible we +	 * set the vfl_dir to M2M to indicate this. +	 * +	 * It is not really a mem2mem device of course, but it can both receive +	 * and transmit using the same radio device. It's the only radio driver +	 * that does this and it should really be split in two radio devices, +	 * but that would affect applications using this driver. +	 */ +	.vfl_dir = VFL_DIR_M2M,  };  int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index e06d782489a..6a1180502cc 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -14,7 +14,7 @@  #include <linux/slab.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h> -#include <asm/mach-bcm47xx/nvram.h> +#include <bcm47xx_nvram.h>  /* 10 parts were found on sflash on Netgear WNDR4500 */  #define BCM47XXPART_MAX_PARTS		12 diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 27f80cd8aef..46dcb54c32e 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -272,6 +272,7 @@ config MTD_DOCG3  	tristate "M-Systems Disk-On-Chip G3"  	select BCH  	select BCH_CONST_PARAMS +	select BITREVERSE  	---help---  	  This provides an MTD device driver for the M-Systems DiskOnChip  	  G3 devices. diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 67cc73c18dd..7901d72c924 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -170,7 +170,7 @@ static int of_flash_probe(struct platform_device *dev)  	resource_size_t res_size;  	struct mtd_part_parser_data ppdata;  	bool map_indirect; -	const char *mtd_name; +	const char *mtd_name = NULL;  	match = of_match_device(of_flash_match, &dev->dev);  	if (!match) diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c index 86c9a79b89b..595de4012e7 100644 --- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c @@ -17,8 +17,8 @@  #include "bcm47xxnflash.h"  /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has - * shown 164 retries as maxiumum. */ -#define NFLASH_READY_RETRIES		1000 + * shown ~1000 retries as maxiumum. */ +#define NFLASH_READY_RETRIES		10000  #define NFLASH_SECTOR_SIZE		512 diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 3502606f648..feae55c7b88 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -523,7 +523,7 @@ static struct nand_ecclayout hwecc4_2048 __initconst = {  static const struct of_device_id davinci_nand_of_match[] = {  	{.compatible = "ti,davinci-nand", },  	{}, -} +};  MODULE_DEVICE_TABLE(of, davinci_nand_of_match);  static struct davinci_nand_pdata diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 8323ac991ad..3766682a028 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2857,8 +2857,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  	int i;  	int val; -	/* ONFI need to be probed in 8 bits mode */ -	WARN_ON(chip->options & NAND_BUSWIDTH_16); +	/* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */ +	if (chip->options & NAND_BUSWIDTH_16) { +		pr_err("Trying ONFI probe in 16 bits mode, aborting !\n"); +		return 0; +	}  	/* Try ONFI for unknown chip or LP */  	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);  	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 1877ed7ca08..1c9e09fbdff 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1053,6 +1053,7 @@ static ssize_t bonding_store_primary(struct device *d,  		pr_info("%s: Setting primary slave to None.\n",  			bond->dev->name);  		bond->primary_slave = NULL; +		memset(bond->params.primary, 0, sizeof(bond->params.primary));  		bond_select_active_slave(bond);  		goto out;  	} diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 58607f196c9..2282b1ae976 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -488,8 +488,12 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,  	priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface),  			IFX_WRITE_LOW_16BIT(mask)); + +	/* According to C_CAN documentation, the reserved bit +	 * in IFx_MASK2 register is fixed 1 +	 */  	priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), -			IFX_WRITE_HIGH_16BIT(mask)); +			IFX_WRITE_HIGH_16BIT(mask) | BIT(13));  	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),  			IFX_WRITE_LOW_16BIT(id)); diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 219f6226fcb..330b0908bf9 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)  }  #ifdef CONFIG_BCM47XX -#include <asm/mach-bcm47xx/nvram.h> +#include <bcm47xx_nvram.h>  static void b44_wap54g10_workaround(struct b44 *bp)  {  	char buf[20]; @@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(struct b44 *bp)  	 * see https://dev.openwrt.org/ticket/146  	 * check and reset bit "isolate"  	 */ -	if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0) +	if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)  		return;  	if (simple_strtoul(buf, NULL, 0) == 2) {  		err = __b44_readphy(bp, 0, MII_BMCR, &val); diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 4eba17b83ba..f1b3df167ff 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -36,13 +36,13 @@  #define DRV_VER			"4.4.161.0u"  #define DRV_NAME		"be2net" -#define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC" -#define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC" -#define OC_NAME			"Emulex OneConnect 10Gbps NIC" +#define BE_NAME			"Emulex BladeEngine2" +#define BE3_NAME		"Emulex BladeEngine3" +#define OC_NAME			"Emulex OneConnect"  #define OC_NAME_BE		OC_NAME	"(be3)"  #define OC_NAME_LANCER		OC_NAME "(Lancer)"  #define OC_NAME_SH		OC_NAME "(Skyhawk)" -#define DRV_DESC		"ServerEngines BladeEngine 10Gbps NIC Driver" +#define DRV_DESC		"Emulex OneConnect 10Gbps NIC Driver"  #define BE_VENDOR_ID 		0x19a2  #define EMULEX_VENDOR_ID	0x10df diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 5c995700e53..4d6f3c54427 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -25,7 +25,7 @@  MODULE_VERSION(DRV_VER);  MODULE_DEVICE_TABLE(pci, be_dev_ids);  MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); -MODULE_AUTHOR("ServerEngines Corporation"); +MODULE_AUTHOR("Emulex Corporation");  MODULE_LICENSE("GPL");  static unsigned int num_vfs; diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index 02a12b69555..4dab6fc265a 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h @@ -232,6 +232,7 @@  #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */  #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */  #define E1000_CTRL_LANPHYPC_VALUE    0x00020000 /* SW value of LANPHYPC */ +#define E1000_CTRL_MEHE     0x00080000  /* Memory Error Handling Enable */  #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */  #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */  #define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */ @@ -389,6 +390,12 @@  #define E1000_PBS_16K E1000_PBA_16K +/* Uncorrectable/correctable ECC Error counts and enable bits */ +#define E1000_PBECCSTS_CORR_ERR_CNT_MASK	0x000000FF +#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK	0x0000FF00 +#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT	8 +#define E1000_PBECCSTS_ECC_ENABLE		0x00010000 +  #define IFS_MAX       80  #define IFS_MIN       40  #define IFS_RATIO     4 @@ -408,6 +415,7 @@  #define E1000_ICR_RXSEQ         0x00000008 /* Rx sequence error */  #define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */  #define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */ +#define E1000_ICR_ECCER         0x00400000 /* Uncorrectable ECC Error */  #define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */  #define E1000_ICR_RXQ0          0x00100000 /* Rx Queue 0 Interrupt */  #define E1000_ICR_RXQ1          0x00200000 /* Rx Queue 1 Interrupt */ @@ -443,6 +451,7 @@  #define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */  #define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */  #define E1000_IMS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */ +#define E1000_IMS_ECCER     E1000_ICR_ECCER     /* Uncorrectable ECC Error */  #define E1000_IMS_RXQ0      E1000_ICR_RXQ0      /* Rx Queue 0 Interrupt */  #define E1000_IMS_RXQ1      E1000_ICR_RXQ1      /* Rx Queue 1 Interrupt */  #define E1000_IMS_TXQ0      E1000_ICR_TXQ0      /* Tx Queue 0 Interrupt */ diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index 6782a2eea1b..7e95f221d60 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -309,6 +309,8 @@ struct e1000_adapter {  	struct napi_struct napi; +	unsigned int uncorr_errors;	/* uncorrectable ECC errors */ +	unsigned int corr_errors;	/* correctable ECC errors */  	unsigned int restart_queue;  	u32 txd_cmd; diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index f95bc6ee1c2..fd4772a2691 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -108,6 +108,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {  	E1000_STAT("dropped_smbus", stats.mgpdc),  	E1000_STAT("rx_dma_failed", rx_dma_failed),  	E1000_STAT("tx_dma_failed", tx_dma_failed), +	E1000_STAT("uncorr_ecc_errors", uncorr_errors), +	E1000_STAT("corr_ecc_errors", corr_errors),  };  #define E1000_GLOBAL_STATS_LEN	ARRAY_SIZE(e1000_gstrings_stats) diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index cf217777586..b88676ff3d8 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h @@ -77,6 +77,7 @@ enum e1e_registers {  #define E1000_POEMB	E1000_PHY_CTRL	/* PHY OEM Bits */  	E1000_PBA      = 0x01000, /* Packet Buffer Allocation - RW */  	E1000_PBS      = 0x01008, /* Packet Buffer Size */ +	E1000_PBECCSTS = 0x0100C, /* Packet Buffer ECC Status - RW */  	E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */  	E1000_EEWR     = 0x0102C, /* EEPROM Write Register - RW */  	E1000_FLOP     = 0x0103C, /* FLASH Opcode Register */ diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 97633654760..24d9f61956f 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -3624,6 +3624,17 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)  	if (hw->mac.type == e1000_ich8lan)  		reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);  	ew32(RFCTL, reg); + +	/* Enable ECC on Lynxpoint */ +	if (hw->mac.type == e1000_pch_lpt) { +		reg = er32(PBECCSTS); +		reg |= E1000_PBECCSTS_ECC_ENABLE; +		ew32(PBECCSTS, reg); + +		reg = er32(CTRL); +		reg |= E1000_CTRL_MEHE; +		ew32(CTRL, reg); +	}  }  /** diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index fbf75fdca99..643c883dd79 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1678,6 +1678,23 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)  			mod_timer(&adapter->watchdog_timer, jiffies + 1);  	} +	/* Reset on uncorrectable ECC error */ +	if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { +		u32 pbeccsts = er32(PBECCSTS); + +		adapter->corr_errors += +		    pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; +		adapter->uncorr_errors += +		    (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> +		    E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; + +		/* Do the reset outside of interrupt context */ +		schedule_work(&adapter->reset_task); + +		/* return immediately since reset is imminent */ +		return IRQ_HANDLED; +	} +  	if (napi_schedule_prep(&adapter->napi)) {  		adapter->total_tx_bytes = 0;  		adapter->total_tx_packets = 0; @@ -1741,6 +1758,23 @@ static irqreturn_t e1000_intr(int irq, void *data)  			mod_timer(&adapter->watchdog_timer, jiffies + 1);  	} +	/* Reset on uncorrectable ECC error */ +	if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { +		u32 pbeccsts = er32(PBECCSTS); + +		adapter->corr_errors += +		    pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; +		adapter->uncorr_errors += +		    (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> +		    E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; + +		/* Do the reset outside of interrupt context */ +		schedule_work(&adapter->reset_task); + +		/* return immediately since reset is imminent */ +		return IRQ_HANDLED; +	} +  	if (napi_schedule_prep(&adapter->napi)) {  		adapter->total_tx_bytes = 0;  		adapter->total_tx_packets = 0; @@ -2104,6 +2138,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)  	if (adapter->msix_entries) {  		ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);  		ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); +	} else if (hw->mac.type == e1000_pch_lpt) { +		ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);  	} else {  		ew32(IMS, IMS_ENABLE_MASK);  	} @@ -4251,6 +4287,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)  	adapter->stats.mgptc += er32(MGTPTC);  	adapter->stats.mgprc += er32(MGTPRC);  	adapter->stats.mgpdc += er32(MGTPDC); + +	/* Correctable ECC Errors */ +	if (hw->mac.type == e1000_pch_lpt) { +		u32 pbeccsts = er32(PBECCSTS); +		adapter->corr_errors += +		    pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; +		adapter->uncorr_errors += +		    (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> +		    E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; +	}  }  /** diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index a6542d75374..5163af31499 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -380,7 +380,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)  		}  	} -	if ((dev_cap->flags & +	if ((dev->caps.flags &  	    (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&  	    mlx4_is_master(dev))  		dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 7992b3e05d3..78ace59efd2 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -1801,7 +1801,7 @@ static void rhine_tx(struct net_device *dev)  					 rp->tx_skbuff[entry]->len,  					 PCI_DMA_TODEVICE);  		} -		dev_kfree_skb_irq(rp->tx_skbuff[entry]); +		dev_kfree_skb(rp->tx_skbuff[entry]);  		rp->tx_skbuff[entry] = NULL;  		entry = (++rp->dirty_tx) % TX_RING_SIZE;  	} @@ -2010,11 +2010,7 @@ static void rhine_slow_event_task(struct work_struct *work)  	if (intr_status & IntrPCIErr)  		netif_warn(rp, hw, dev, "PCI error\n"); -	napi_disable(&rp->napi); -	rhine_irq_disable(rp); -	/* Slow and safe. Consider __napi_schedule as a replacement ? */ -	napi_enable(&rp->napi); -	napi_schedule(&rp->napi); +	iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable);  out_unlock:  	mutex_unlock(&rp->task_lock); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index cc09b67c23b..2917a86f4c4 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -298,11 +298,12 @@ static void tun_flow_cleanup(unsigned long data)  }  static void tun_flow_update(struct tun_struct *tun, u32 rxhash, -			    u16 queue_index) +			    struct tun_file *tfile)  {  	struct hlist_head *head;  	struct tun_flow_entry *e;  	unsigned long delay = tun->ageing_time; +	u16 queue_index = tfile->queue_index;  	if (!rxhash)  		return; @@ -311,7 +312,9 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,  	rcu_read_lock(); -	if (tun->numqueues == 1) +	/* We may get a very small possibility of OOO during switching, not +	 * worth to optimize.*/ +	if (tun->numqueues == 1 || tfile->detached)  		goto unlock;  	e = tun_flow_find(head, rxhash); @@ -411,21 +414,21 @@ static void __tun_detach(struct tun_file *tfile, bool clean)  	tun = rtnl_dereference(tfile->tun); -	if (tun) { +	if (tun && !tfile->detached) {  		u16 index = tfile->queue_index;  		BUG_ON(index >= tun->numqueues);  		dev = tun->dev;  		rcu_assign_pointer(tun->tfiles[index],  				   tun->tfiles[tun->numqueues - 1]); -		rcu_assign_pointer(tfile->tun, NULL);  		ntfile = rtnl_dereference(tun->tfiles[index]);  		ntfile->queue_index = index;  		--tun->numqueues; -		if (clean) +		if (clean) { +			rcu_assign_pointer(tfile->tun, NULL);  			sock_put(&tfile->sk); -		else +		} else  			tun_disable_queue(tun, tfile);  		synchronize_net(); @@ -439,10 +442,13 @@ static void __tun_detach(struct tun_file *tfile, bool clean)  	}  	if (clean) { -		if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && -		    !(tun->flags & TUN_PERSIST)) -			if (tun->dev->reg_state == NETREG_REGISTERED) +		if (tun && tun->numqueues == 0 && tun->numdisabled == 0) { +			netif_carrier_off(tun->dev); + +			if (!(tun->flags & TUN_PERSIST) && +			    tun->dev->reg_state == NETREG_REGISTERED)  				unregister_netdevice(tun->dev); +		}  		BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,  				 &tfile->socket.flags)); @@ -470,6 +476,10 @@ static void tun_detach_all(struct net_device *dev)  		rcu_assign_pointer(tfile->tun, NULL);  		--tun->numqueues;  	} +	list_for_each_entry(tfile, &tun->disabled, next) { +		wake_up_all(&tfile->wq.wait); +		rcu_assign_pointer(tfile->tun, NULL); +	}  	BUG_ON(tun->numqueues != 0);  	synchronize_net(); @@ -500,7 +510,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)  		goto out;  	err = -EINVAL; -	if (rtnl_dereference(tfile->tun)) +	if (rtnl_dereference(tfile->tun) && !tfile->detached)  		goto out;  	err = -EBUSY; @@ -1199,7 +1209,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,  	tun->dev->stats.rx_packets++;  	tun->dev->stats.rx_bytes += len; -	tun_flow_update(tun, rxhash, tfile->queue_index); +	tun_flow_update(tun, rxhash, tfile);  	return total_len;  } @@ -1658,10 +1668,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)  		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||  		    device_create_file(&tun->dev->dev, &dev_attr_group))  			pr_err("Failed to create tun sysfs files\n"); - -		netif_carrier_on(tun->dev);  	} +	netif_carrier_on(tun->dev); +  	tun_debug(KERN_INFO, tun, "tun_set_iff\n");  	if (ifr->ifr_flags & IFF_NO_PI) @@ -1813,7 +1823,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)  		ret = tun_attach(tun, file);  	} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {  		tun = rtnl_dereference(tfile->tun); -		if (!tun || !(tun->flags & TUN_TAP_MQ)) +		if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached)  			ret = -EINVAL;  		else  			__tun_detach(tfile, false); diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 9197b2c72ca..00d3b2d3782 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1215,6 +1215,9 @@ static const struct usb_device_id cdc_devs[] = {  	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),  	  .driver_info = (unsigned long)&wwan_info,  	}, +	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76), +	  .driver_info = (unsigned long)&wwan_info, +	},  	/* Infineon(now Intel) HSPA Modem platform */  	{ USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 575a5839ee3..c8e05e27f38 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -351,6 +351,10 @@ static const struct usb_device_id products[] = {  		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57),  		.driver_info        = (unsigned long)&qmi_wwan_info,  	}, +	{	/* HUAWEI_INTERFACE_NDIS_CONTROL_QUALCOMM */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	},  	/* 2. Combined interface devices matching on class+protocol */  	{	/* Huawei E367 and possibly others in "Windows mode" */ @@ -361,6 +365,14 @@ static const struct usb_device_id products[] = {  		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),  		.driver_info        = (unsigned long)&qmi_wwan_info,  	}, +	{	/* HUAWEI_NDIS_SINGLE_INTERFACE_VDF */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x37), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	}, +	{	/* HUAWEI_INTERFACE_NDIS_HW_QUALCOMM */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x67), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	},  	{	/* Pantech UML290, P4200 and more */  		USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_info, @@ -461,6 +473,7 @@ static const struct usb_device_id products[] = {  	{QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */  	{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},	/* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */  	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */ +	{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},	/* Telit LE920 */  	/* 4. Gobi 1000 devices */  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */ diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f34b2ebee81..5e33606c136 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -380,6 +380,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)  	unsigned long		lockflags;  	size_t			size = dev->rx_urb_size; +	/* prevent rx skb allocation when error ratio is high */ +	if (test_bit(EVENT_RX_KILL, &dev->flags)) { +		usb_free_urb(urb); +		return -ENOLINK; +	} +  	skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);  	if (!skb) {  		netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); @@ -539,6 +545,17 @@ block:  		break;  	} +	/* stop rx if packet error rate is high */ +	if (++dev->pkt_cnt > 30) { +		dev->pkt_cnt = 0; +		dev->pkt_err = 0; +	} else { +		if (state == rx_cleanup) +			dev->pkt_err++; +		if (dev->pkt_err > 20) +			set_bit(EVENT_RX_KILL, &dev->flags); +	} +  	state = defer_bh(dev, skb, &dev->rxq, state);  	if (urb) { @@ -791,6 +808,11 @@ int usbnet_open (struct net_device *net)  		   (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" :  		   "simple"); +	/* reset rx error state */ +	dev->pkt_cnt = 0; +	dev->pkt_err = 0; +	clear_bit(EVENT_RX_KILL, &dev->flags); +  	// delay posting reads until we're fully open  	tasklet_schedule (&dev->bh);  	if (info->manage_power) { @@ -1103,13 +1125,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,  	if (info->tx_fixup) {  		skb = info->tx_fixup (dev, skb, GFP_ATOMIC);  		if (!skb) { -			if (netif_msg_tx_err(dev)) { -				netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); -				goto drop; -			} else { -				/* cdc_ncm collected packet; waits for more */ +			/* packet collected; minidriver waiting for more */ +			if (info->flags & FLAG_MULTI_PACKET)  				goto not_drop; -			} +			netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); +			goto drop;  		}  	}  	length = skb->len; @@ -1254,6 +1274,9 @@ static void usbnet_bh (unsigned long param)  		}  	} +	/* restart RX again after disabling due to high error rate */ +	clear_bit(EVENT_RX_KILL, &dev->flags); +  	// waiting for all pending urbs to complete?  	if (dev->wait) {  		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index dc8913c6238..12c6440d164 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -154,8 +154,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)  	if (ret & 1) { /* Link is up. */  		printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n",  		       adapter->netdev->name, adapter->link_speed); -		if (!netif_carrier_ok(adapter->netdev)) -			netif_carrier_on(adapter->netdev); +		netif_carrier_on(adapter->netdev);  		if (affectTxQueue) {  			for (i = 0; i < adapter->num_tx_queues; i++) @@ -165,8 +164,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)  	} else {  		printk(KERN_INFO "%s: NIC Link is Down\n",  		       adapter->netdev->name); -		if (netif_carrier_ok(adapter->netdev)) -			netif_carrier_off(adapter->netdev); +		netif_carrier_off(adapter->netdev);  		if (affectTxQueue) {  			for (i = 0; i < adapter->num_tx_queues; i++) @@ -3061,6 +3059,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,  	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);  	netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues); +	netif_carrier_off(netdev);  	err = register_netdev(netdev);  	if (err) { diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 0f71d1d4339..e5fd20994be 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -36,6 +36,7 @@  #include "debug.h"  #define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */ +#define BRCMS_FLUSH_TIMEOUT	500 /* msec */  /* Flags we support */  #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ @@ -708,16 +709,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)  	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);  } +static bool brcms_tx_flush_completed(struct brcms_info *wl) +{ +	bool result; + +	spin_lock_bh(&wl->lock); +	result = brcms_c_tx_flush_completed(wl->wlc); +	spin_unlock_bh(&wl->lock); +	return result; +} +  static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)  {  	struct brcms_info *wl = hw->priv; +	int ret;  	no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); -	/* wait for packet queue and dma fifos to run empty */ -	spin_lock_bh(&wl->lock); -	brcms_c_wait_for_tx_completion(wl->wlc, drop); -	spin_unlock_bh(&wl->lock); +	ret = wait_event_timeout(wl->tx_flush_wq, +				 brcms_tx_flush_completed(wl), +				 msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT)); + +	brcms_dbg_mac80211(wl->wlc->hw->d11core, +			   "ret=%d\n", jiffies_to_msecs(ret));  }  static const struct ieee80211_ops brcms_ops = { @@ -772,6 +786,7 @@ void brcms_dpc(unsigned long data)   done:  	spin_unlock_bh(&wl->lock); +	wake_up(&wl->tx_flush_wq);  }  /* @@ -1020,6 +1035,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)  	atomic_set(&wl->callbacks, 0); +	init_waitqueue_head(&wl->tx_flush_wq); +  	/* setup the bottom half handler */  	tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); @@ -1609,13 +1626,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)  	spin_lock_bh(&wl->lock);  	return blocked;  } - -/* - * precondition: perimeter lock has been acquired - */ -void brcms_msleep(struct brcms_info *wl, uint ms) -{ -	spin_unlock_bh(&wl->lock); -	msleep(ms); -	spin_lock_bh(&wl->lock); -} diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 9358bd5ebd3..947ccacf43e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h @@ -68,6 +68,8 @@ struct brcms_info {  	spinlock_t lock;	/* per-device perimeter lock */  	spinlock_t isr_lock;	/* per-device ISR synchronization lock */ +	/* tx flush */ +	wait_queue_head_t tx_flush_wq;  	/* timer related fields */  	atomic_t callbacks;	/* # outstanding callback functions */ @@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,  extern void brcms_free_timer(struct brcms_timer *timer);  extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);  extern bool brcms_del_timer(struct brcms_timer *timer); -extern void brcms_msleep(struct brcms_info *wl, uint ms);  extern void brcms_dpc(unsigned long data);  extern void brcms_timer(struct brcms_timer *t);  extern void brcms_fatal_error(struct brcms_info *wl); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 17594de4199..8b5839008af 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -1027,7 +1027,6 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)  static bool  brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)  { -	bool morepending = false;  	struct bcma_device *core;  	struct tx_status txstatus, *txs;  	u32 s1, s2; @@ -1041,23 +1040,20 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)  	txs = &txstatus;  	core = wlc_hw->d11core;  	*fatal = false; -	s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); -	while (!(*fatal) -	       && (s1 & TXS_V)) { -		/* !give others some time to run! */ -		if (n >= max_tx_num) { -			morepending = true; -			break; -		} +	while (n < max_tx_num) { +		s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));  		if (s1 == 0xffffffff) {  			brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,  				  __func__);  			*fatal = true;  			return false;  		} -		s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); +		/* only process when valid */ +		if (!(s1 & TXS_V)) +			break; +		s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));  		txs->status = s1 & TXS_STATUS_MASK;  		txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;  		txs->sequence = s2 & TXS_SEQ_MASK; @@ -1065,15 +1061,12 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)  		txs->lasttxtime = 0;  		*fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); - -		s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); +		if (*fatal == true) +			return false;  		n++;  	} -	if (*fatal) -		return false; - -	return morepending; +	return n >= max_tx_num;  }  static void brcms_c_tbtt(struct brcms_c_info *wlc) @@ -7518,25 +7511,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)  	return wlc->band->bandunit;  } -void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) +bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc)  { -	int timeout = 20;  	int i;  	/* Kick DMA to send any pending AMPDU */  	for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)  		if (wlc->hw->di[i]) -			dma_txflush(wlc->hw->di[i]); - -	/* wait for queue and DMA fifos to run dry */ -	while (brcms_txpktpendtot(wlc) > 0) { -		brcms_msleep(wlc->wl, 1); - -		if (--timeout == 0) -			break; -	} +			dma_kick_tx(wlc->hw->di[i]); -	WARN_ON_ONCE(timeout == 0); +	return !brcms_txpktpendtot(wlc);  }  void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 4fb2834f4e6..b0f14b7b861 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h @@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);  extern void brcms_c_scan_start(struct brcms_c_info *wlc);  extern void brcms_c_scan_stop(struct brcms_c_info *wlc);  extern int brcms_c_get_curband(struct brcms_c_info *wlc); -extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, -					   bool drop);  extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);  extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);  extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, @@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);  extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);  extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);  extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); +extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);  #endif				/* _BRCM_PUB_H_ */ diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 31534f7c054..279796419ea 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -1153,6 +1153,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,  			next_reclaimed = ssn;  		} +		if (tid != IWL_TID_NON_QOS) { +			priv->tid_data[sta_id][tid].next_reclaimed = +				next_reclaimed; +			IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", +						  next_reclaimed); +		} +  		iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);  		iwlagn_check_ratid_empty(priv, sta_id, tid); @@ -1203,28 +1210,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,  			if (!is_agg)  				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); -			/* -			 * W/A for FW bug - the seq_ctl isn't updated when the -			 * queues are flushed. Fetch it from the packet itself -			 */ -			if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { -				next_reclaimed = le16_to_cpu(hdr->seq_ctrl); -				next_reclaimed = -					SEQ_TO_SN(next_reclaimed + 0x10); -			} -  			is_offchannel_skb =  				(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);  			freed++;  		} -		if (tid != IWL_TID_NON_QOS) { -			priv->tid_data[sta_id][tid].next_reclaimed = -				next_reclaimed; -			IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", -					   next_reclaimed); -		} -  		WARN_ON(!is_agg && freed != 1);  		/* diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 9189a32b784..973a9d90e9e 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1563,7 +1563,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,  		dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",  			scan_rsp->number_of_sets);  		ret = -1; -		goto done; +		goto check_next_scan;  	}  	bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); @@ -1634,7 +1634,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,  		if (!beacon_size || beacon_size > bytes_left) {  			bss_info += bytes_left;  			bytes_left = 0; -			return -1; +			ret = -1; +			goto check_next_scan;  		}  		/* Initialize the current working beacon pointer for this BSS @@ -1690,7 +1691,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,  				dev_err(priv->adapter->dev,  					"%s: bytes left < IE length\n",  					__func__); -				goto done; +				goto check_next_scan;  			}  			if (element_id == WLAN_EID_DS_PARAMS) {  				channel = *(current_ptr + sizeof(struct ieee_types_header)); @@ -1753,6 +1754,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,  		}  	} +check_next_scan:  	spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);  	if (list_empty(&adapter->scan_pending_q)) {  		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); @@ -1813,7 +1815,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,  		}  	} -done:  	return ret;  } diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 4494d130b37..0f8b05185ed 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)  					 is_tx ? "Tx" : "Rx");  				if (is_tx) { -					rtl_lps_leave(hw); +					schedule_work(&rtlpriv-> +						      works.lps_leave_work);  					ppsc->last_delaylps_stamp_jiffies =  					    jiffies;  				} @@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)  		}  	} else if (ETH_P_ARP == ether_type) {  		if (is_tx) { -			rtl_lps_leave(hw); +			schedule_work(&rtlpriv->works.lps_leave_work);  			ppsc->last_delaylps_stamp_jiffies = jiffies;  		} @@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)  			 "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");  		if (is_tx) { -			rtl_lps_leave(hw); +			schedule_work(&rtlpriv->works.lps_leave_work);  			ppsc->last_delaylps_stamp_jiffies = jiffies;  		} diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index f2ecdeb3a90..1535efda3d5 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -542,8 +542,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)  	WARN_ON(skb_queue_empty(&rx_queue));  	while (!skb_queue_empty(&rx_queue)) {  		_skb = skb_dequeue(&rx_queue); -		_rtl_usb_rx_process_agg(hw, skb); -		ieee80211_rx_irqsafe(hw, skb); +		_rtl_usb_rx_process_agg(hw, _skb); +		ieee80211_rx_irqsafe(hw, _skb);  	}  } diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 94b79c3338c..9d7f1723dd8 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb);  /* Notify xenvif that ring now has space to send an skb to the frontend */  void xenvif_notify_tx_completion(struct xenvif *vif); +/* Prevent the device from generating any further traffic. */ +void xenvif_carrier_off(struct xenvif *vif); +  /* Returns number of ring slots required to send an skb to the frontend */  unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index b7d41f8c338..b8c5193bd42 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -343,17 +343,22 @@ err:  	return err;  } -void xenvif_disconnect(struct xenvif *vif) +void xenvif_carrier_off(struct xenvif *vif)  {  	struct net_device *dev = vif->dev; -	if (netif_carrier_ok(dev)) { -		rtnl_lock(); -		netif_carrier_off(dev); /* discard queued packets */ -		if (netif_running(dev)) -			xenvif_down(vif); -		rtnl_unlock(); -		xenvif_put(vif); -	} + +	rtnl_lock(); +	netif_carrier_off(dev); /* discard queued packets */ +	if (netif_running(dev)) +		xenvif_down(vif); +	rtnl_unlock(); +	xenvif_put(vif); +} + +void xenvif_disconnect(struct xenvif *vif) +{ +	if (netif_carrier_ok(vif->dev)) +		xenvif_carrier_off(vif);  	atomic_dec(&vif->refcnt);  	wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f2d6b78d901..2b9520c46e9 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif)  	atomic_dec(&netbk->netfront_count);  } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, +				  u8 status);  static void make_tx_response(struct xenvif *vif,  			     struct xen_netif_tx_request *txp,  			     s8       st); @@ -879,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif,  	do {  		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); -		if (cons >= end) +		if (cons == end)  			break;  		txp = RING_GET_REQUEST(&vif->tx, cons++);  	} while (1); @@ -888,6 +889,13 @@ static void netbk_tx_err(struct xenvif *vif,  	xenvif_put(vif);  } +static void netbk_fatal_tx_err(struct xenvif *vif) +{ +	netdev_err(vif->dev, "fatal error; disabling device\n"); +	xenvif_carrier_off(vif); +	xenvif_put(vif); +} +  static int netbk_count_requests(struct xenvif *vif,  				struct xen_netif_tx_request *first,  				struct xen_netif_tx_request *txp, @@ -901,19 +909,22 @@ static int netbk_count_requests(struct xenvif *vif,  	do {  		if (frags >= work_to_do) { -			netdev_dbg(vif->dev, "Need more frags\n"); +			netdev_err(vif->dev, "Need more frags\n"); +			netbk_fatal_tx_err(vif);  			return -frags;  		}  		if (unlikely(frags >= MAX_SKB_FRAGS)) { -			netdev_dbg(vif->dev, "Too many frags\n"); +			netdev_err(vif->dev, "Too many frags\n"); +			netbk_fatal_tx_err(vif);  			return -frags;  		}  		memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),  		       sizeof(*txp));  		if (txp->size > first->size) { -			netdev_dbg(vif->dev, "Frags galore\n"); +			netdev_err(vif->dev, "Frag is bigger than frame.\n"); +			netbk_fatal_tx_err(vif);  			return -frags;  		} @@ -921,8 +932,9 @@ static int netbk_count_requests(struct xenvif *vif,  		frags++;  		if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { -			netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", +			netdev_err(vif->dev, "txp->offset: %x, size: %u\n",  				 txp->offset, txp->size); +			netbk_fatal_tx_err(vif);  			return -frags;  		}  	} while ((txp++)->flags & XEN_NETTXF_more_data); @@ -966,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,  		pending_idx = netbk->pending_ring[index];  		page = xen_netbk_alloc_page(netbk, skb, pending_idx);  		if (!page) -			return NULL; +			goto err;  		gop->source.u.ref = txp->gref;  		gop->source.domid = vif->domid; @@ -988,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,  	}  	return gop; +err: +	/* Unwind, freeing all pages and sending error responses. */ +	while (i-- > start) { +		xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), +				      XEN_NETIF_RSP_ERROR); +	} +	/* The head too, if necessary. */ +	if (start) +		xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + +	return NULL;  }  static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, @@ -996,30 +1019,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,  {  	struct gnttab_copy *gop = *gopp;  	u16 pending_idx = *((u16 *)skb->data); -	struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; -	struct xenvif *vif = pending_tx_info[pending_idx].vif; -	struct xen_netif_tx_request *txp;  	struct skb_shared_info *shinfo = skb_shinfo(skb);  	int nr_frags = shinfo->nr_frags;  	int i, err, start;  	/* Check status of header. */  	err = gop->status; -	if (unlikely(err)) { -		pending_ring_idx_t index; -		index = pending_index(netbk->pending_prod++); -		txp = &pending_tx_info[pending_idx].req; -		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); -		netbk->pending_ring[index] = pending_idx; -		xenvif_put(vif); -	} +	if (unlikely(err)) +		xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);  	/* Skip first skb fragment if it is on same page as header fragment. */  	start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);  	for (i = start; i < nr_frags; i++) {  		int j, newerr; -		pending_ring_idx_t index;  		pending_idx = frag_get_pending_idx(&shinfo->frags[i]); @@ -1028,16 +1041,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,  		if (likely(!newerr)) {  			/* Had a previous error? Invalidate this fragment. */  			if (unlikely(err)) -				xen_netbk_idx_release(netbk, pending_idx); +				xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);  			continue;  		}  		/* Error on this fragment: respond to client with an error. */ -		txp = &netbk->pending_tx_info[pending_idx].req; -		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); -		index = pending_index(netbk->pending_prod++); -		netbk->pending_ring[index] = pending_idx; -		xenvif_put(vif); +		xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);  		/* Not the first error? Preceding frags already invalidated. */  		if (err) @@ -1045,10 +1054,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,  		/* First error: invalidate header and preceding fragments. */  		pending_idx = *((u16 *)skb->data); -		xen_netbk_idx_release(netbk, pending_idx); +		xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);  		for (j = start; j < i; j++) {  			pending_idx = frag_get_pending_idx(&shinfo->frags[j]); -			xen_netbk_idx_release(netbk, pending_idx); +			xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);  		}  		/* Remember the error: invalidate all subsequent fragments. */ @@ -1082,7 +1091,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)  		/* Take an extra reference to offset xen_netbk_idx_release */  		get_page(netbk->mmap_pages[pending_idx]); -		xen_netbk_idx_release(netbk, pending_idx); +		xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);  	}  } @@ -1095,7 +1104,8 @@ static int xen_netbk_get_extras(struct xenvif *vif,  	do {  		if (unlikely(work_to_do-- <= 0)) { -			netdev_dbg(vif->dev, "Missing extra info\n"); +			netdev_err(vif->dev, "Missing extra info\n"); +			netbk_fatal_tx_err(vif);  			return -EBADR;  		} @@ -1104,8 +1114,9 @@ static int xen_netbk_get_extras(struct xenvif *vif,  		if (unlikely(!extra.type ||  			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {  			vif->tx.req_cons = ++cons; -			netdev_dbg(vif->dev, +			netdev_err(vif->dev,  				   "Invalid extra type: %d\n", extra.type); +			netbk_fatal_tx_err(vif);  			return -EINVAL;  		} @@ -1121,13 +1132,15 @@ static int netbk_set_skb_gso(struct xenvif *vif,  			     struct xen_netif_extra_info *gso)  {  	if (!gso->u.gso.size) { -		netdev_dbg(vif->dev, "GSO size must not be zero.\n"); +		netdev_err(vif->dev, "GSO size must not be zero.\n"); +		netbk_fatal_tx_err(vif);  		return -EINVAL;  	}  	/* Currently only TCPv4 S.O. is supported. */  	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { -		netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); +		netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); +		netbk_fatal_tx_err(vif);  		return -EINVAL;  	} @@ -1264,9 +1277,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)  		/* Get a netif from the list with work to do. */  		vif = poll_net_schedule_list(netbk); +		/* This can sometimes happen because the test of +		 * list_empty(net_schedule_list) at the top of the +		 * loop is unlocked.  Just go back and have another +		 * look. +		 */  		if (!vif)  			continue; +		if (vif->tx.sring->req_prod - vif->tx.req_cons > +		    XEN_NETIF_TX_RING_SIZE) { +			netdev_err(vif->dev, +				   "Impossible number of requests. " +				   "req_prod %d, req_cons %d, size %ld\n", +				   vif->tx.sring->req_prod, vif->tx.req_cons, +				   XEN_NETIF_TX_RING_SIZE); +			netbk_fatal_tx_err(vif); +			continue; +		} +  		RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);  		if (!work_to_do) {  			xenvif_put(vif); @@ -1294,17 +1323,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)  			work_to_do = xen_netbk_get_extras(vif, extras,  							  work_to_do);  			idx = vif->tx.req_cons; -			if (unlikely(work_to_do < 0)) { -				netbk_tx_err(vif, &txreq, idx); +			if (unlikely(work_to_do < 0))  				continue; -			}  		}  		ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); -		if (unlikely(ret < 0)) { -			netbk_tx_err(vif, &txreq, idx - ret); +		if (unlikely(ret < 0))  			continue; -		} +  		idx += ret;  		if (unlikely(txreq.size < ETH_HLEN)) { @@ -1316,11 +1342,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)  		/* No crossing a page as the payload mustn't fragment. */  		if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { -			netdev_dbg(vif->dev, +			netdev_err(vif->dev,  				   "txreq.offset: %x, size: %u, end: %lu\n",  				   txreq.offset, txreq.size,  				   (txreq.offset&~PAGE_MASK) + txreq.size); -			netbk_tx_err(vif, &txreq, idx); +			netbk_fatal_tx_err(vif);  			continue;  		} @@ -1348,8 +1374,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)  			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];  			if (netbk_set_skb_gso(vif, skb, gso)) { +				/* Failure in netbk_set_skb_gso is fatal. */  				kfree_skb(skb); -				netbk_tx_err(vif, &txreq, idx);  				continue;  			}  		} @@ -1448,7 +1474,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)  			txp->size -= data_len;  		} else {  			/* Schedule a response immediately. */ -			xen_netbk_idx_release(netbk, pending_idx); +			xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);  		}  		if (txp->flags & XEN_NETTXF_csum_blank) @@ -1500,7 +1526,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk)  	xen_netbk_tx_submit(netbk);  } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, +				  u8 status)  {  	struct xenvif *vif;  	struct pending_tx_info *pending_tx_info; @@ -1514,7 +1541,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)  	vif = pending_tx_info->vif; -	make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); +	make_tx_response(vif, &pending_tx_info->req, status);  	index = pending_index(netbk->pending_prod++);  	netbk->pending_ring[index] = pending_idx; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index efaecefe3f8..a5f3c8ca480 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -184,8 +184,8 @@ config PINCTRL_SAMSUNG  	select PINMUX  	select PINCONF -config PINCTRL_EXYNOS4 -	bool "Pinctrl driver data for Exynos4 SoC" +config PINCTRL_EXYNOS +	bool "Pinctrl driver data for Samsung EXYNOS SoCs"  	depends on OF && GPIOLIB  	select PINCTRL_SAMSUNG diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index fc4606f27dc..6e87e52eab5 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -36,7 +36,7 @@ obj-$(CONFIG_PINCTRL_TEGRA30)	+= pinctrl-tegra30.o  obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o  obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o  obj-$(CONFIG_PINCTRL_SAMSUNG)	+= pinctrl-samsung.o -obj-$(CONFIG_PINCTRL_EXYNOS4)	+= pinctrl-exynos.o +obj-$(CONFIG_PINCTRL_EXYNOS)	+= pinctrl-exynos.o  obj-$(CONFIG_PINCTRL_EXYNOS5440)	+= pinctrl-exynos5440.o  obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o  obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 498b2ba905d..d02498b30c6 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1246,6 +1246,22 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)  	return of_iomap(np, 0);  } +static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc, +       const struct of_phandle_args *gpiospec, +       u32 *flags) +{ +       if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE) +               return -EINVAL; + +       if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc) +               return -EINVAL; + +       if (flags) +               *flags = gpiospec->args[1]; + +       return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE; +} +  static int sirfsoc_pinmux_probe(struct platform_device *pdev)  {  	int ret; @@ -1736,6 +1752,8 @@ static int sirfsoc_gpio_probe(struct device_node *np)  		bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;  		bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);  		bank->chip.gc.of_node = np; +		bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate; +		bank->chip.gc.of_gpio_n_cells = 2;  		bank->chip.regs = regs;  		bank->id = i;  		bank->is_marco = is_marco; diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index b85040caaea..cca18a3c029 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -379,9 +379,10 @@ static struct regulator_desc regulators[] = {  };  #ifdef CONFIG_OF -static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, +static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,  					struct max77686_platform_data *pdata)  { +	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);  	struct device_node *pmic_np, *regulators_np;  	struct max77686_regulator_data *rdata;  	struct of_regulator_match rmatch; @@ -390,15 +391,15 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,  	pmic_np = iodev->dev->of_node;  	regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");  	if (!regulators_np) { -		dev_err(iodev->dev, "could not find regulators sub-node\n"); +		dev_err(&pdev->dev, "could not find regulators sub-node\n");  		return -EINVAL;  	}  	pdata->num_regulators = ARRAY_SIZE(regulators); -	rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * +	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *  			     pdata->num_regulators, GFP_KERNEL);  	if (!rdata) { -		dev_err(iodev->dev, +		dev_err(&pdev->dev,  			"could not allocate memory for regulator data\n");  		return -ENOMEM;  	} @@ -407,7 +408,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,  		rmatch.name = regulators[i].name;  		rmatch.init_data = NULL;  		rmatch.of_node = NULL; -		of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); +		of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);  		rdata[i].initdata = rmatch.init_data;  		rdata[i].of_node = rmatch.of_node;  	} @@ -417,7 +418,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,  	return 0;  }  #else -static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, +static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,  					struct max77686_platform_data *pdata)  {  	return 0; @@ -440,7 +441,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)  	}  	if (iodev->dev->of_node) { -		ret = max77686_pmic_dt_parse_pdata(iodev, pdata); +		ret = max77686_pmic_dt_parse_pdata(pdev, pdata);  		if (ret)  			return ret;  	} diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index d1a77512d83..d40cf7fdb54 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -237,8 +237,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev)  		return -EINVAL;  	} -	ret = of_regulator_match(pdev->dev.parent, regulators, -				 max8907_matches, +	ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,  				 ARRAY_SIZE(max8907_matches));  	if (ret < 0) {  		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 02be7fcae32..836908ce505 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -934,7 +934,7 @@ static struct regulator_desc regulators[] = {  };  #ifdef CONFIG_OF -static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, +static int max8997_pmic_dt_parse_dvs_gpio(struct platform_device *pdev,  			struct max8997_platform_data *pdata,  			struct device_node *pmic_np)  { @@ -944,7 +944,7 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,  		gpio = of_get_named_gpio(pmic_np,  					"max8997,pmic-buck125-dvs-gpios", i);  		if (!gpio_is_valid(gpio)) { -			dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); +			dev_err(&pdev->dev, "invalid gpio[%d]: %d\n", i, gpio);  			return -EINVAL;  		}  		pdata->buck125_gpios[i] = gpio; @@ -952,22 +952,23 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,  	return 0;  } -static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, +static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,  					struct max8997_platform_data *pdata)  { +	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);  	struct device_node *pmic_np, *regulators_np, *reg_np;  	struct max8997_regulator_data *rdata;  	unsigned int i, dvs_voltage_nr = 1, ret;  	pmic_np = iodev->dev->of_node;  	if (!pmic_np) { -		dev_err(iodev->dev, "could not find pmic sub-node\n"); +		dev_err(&pdev->dev, "could not find pmic sub-node\n");  		return -ENODEV;  	}  	regulators_np = of_find_node_by_name(pmic_np, "regulators");  	if (!regulators_np) { -		dev_err(iodev->dev, "could not find regulators sub-node\n"); +		dev_err(&pdev->dev, "could not find regulators sub-node\n");  		return -EINVAL;  	} @@ -976,11 +977,10 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,  	for_each_child_of_node(regulators_np, reg_np)  		pdata->num_regulators++; -	rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * +	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *  				pdata->num_regulators, GFP_KERNEL);  	if (!rdata) { -		dev_err(iodev->dev, "could not allocate memory for " -						"regulator data\n"); +		dev_err(&pdev->dev, "could not allocate memory for regulator data\n");  		return -ENOMEM;  	} @@ -991,14 +991,14 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,  				break;  		if (i == ARRAY_SIZE(regulators)) { -			dev_warn(iodev->dev, "don't know how to configure " -				"regulator %s\n", reg_np->name); +			dev_warn(&pdev->dev, "don't know how to configure regulator %s\n", +				 reg_np->name);  			continue;  		}  		rdata->id = i; -		rdata->initdata = of_get_regulator_init_data( -						iodev->dev, reg_np); +		rdata->initdata = of_get_regulator_init_data(&pdev->dev, +							     reg_np);  		rdata->reg_node = reg_np;  		rdata++;  	} @@ -1014,7 +1014,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,  	if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||  						pdata->buck5_gpiodvs) { -		ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); +		ret = max8997_pmic_dt_parse_dvs_gpio(pdev, pdata, pmic_np);  		if (ret)  			return -EINVAL; @@ -1025,8 +1025,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,  		} else {  			if (pdata->buck125_default_idx >= 8) {  				pdata->buck125_default_idx = 0; -				dev_info(iodev->dev, "invalid value for " -				"default dvs index, using 0 instead\n"); +				dev_info(&pdev->dev, "invalid value for default dvs index, using 0 instead\n");  			}  		} @@ -1040,28 +1039,28 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,  	if (of_property_read_u32_array(pmic_np,  				"max8997,pmic-buck1-dvs-voltage",  				pdata->buck1_voltage, dvs_voltage_nr)) { -		dev_err(iodev->dev, "buck1 voltages not specified\n"); +		dev_err(&pdev->dev, "buck1 voltages not specified\n");  		return -EINVAL;  	}  	if (of_property_read_u32_array(pmic_np,  				"max8997,pmic-buck2-dvs-voltage",  				pdata->buck2_voltage, dvs_voltage_nr)) { -		dev_err(iodev->dev, "buck2 voltages not specified\n"); +		dev_err(&pdev->dev, "buck2 voltages not specified\n");  		return -EINVAL;  	}  	if (of_property_read_u32_array(pmic_np,  				"max8997,pmic-buck5-dvs-voltage",  				pdata->buck5_voltage, dvs_voltage_nr)) { -		dev_err(iodev->dev, "buck5 voltages not specified\n"); +		dev_err(&pdev->dev, "buck5 voltages not specified\n");  		return -EINVAL;  	}  	return 0;  }  #else -static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, +static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,  					struct max8997_platform_data *pdata)  {  	return 0; @@ -1085,7 +1084,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)  	}  	if (iodev->dev->of_node) { -		ret = max8997_pmic_dt_parse_pdata(iodev, pdata); +		ret = max8997_pmic_dt_parse_pdata(pdev, pdata);  		if (ret)  			return ret;  	} diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 1f0df4046b8..0a8dd1cbee6 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -65,7 +65,7 @@ static const struct voltage_map_desc ldo9_voltage_map_desc = {  	.min = 2800000,	.step = 100000,	.max = 3100000,  };  static const struct voltage_map_desc ldo10_voltage_map_desc = { -	.min = 95000,	.step = 50000,	.max = 1300000, +	.min = 950000,	.step = 50000,	.max = 1300000,  };  static const struct voltage_map_desc ldo1213_voltage_map_desc = {  	.min = 800000,	.step = 100000,	.max = 3300000, diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 6f684916fd7..66ca769287a 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -120,6 +120,12 @@ int of_regulator_match(struct device *dev, struct device_node *node,  	if (!dev || !node)  		return -EINVAL; +	for (i = 0; i < num_matches; i++) { +		struct of_regulator_match *match = &matches[i]; +		match->init_data = NULL; +		match->of_node = NULL; +	} +  	for_each_child_of_node(node, child) {  		name = of_get_property(child,  					"regulator-compatible", NULL); diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index bd062a2ffbe..cd9ea2ea182 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -174,9 +174,9 @@ static struct regulator_ops s2mps11_buck_ops = {  	.min_uV		= S2MPS11_BUCK_MIN2,			\  	.uV_step	= S2MPS11_BUCK_STEP2,			\  	.n_voltages	= S2MPS11_BUCK_N_VOLTAGES,		\ -	.vsel_reg	= S2MPS11_REG_B9CTRL2,			\ +	.vsel_reg	= S2MPS11_REG_B10CTRL2,			\  	.vsel_mask	= S2MPS11_BUCK_VSEL_MASK,		\ -	.enable_reg	= S2MPS11_REG_B9CTRL1,			\ +	.enable_reg	= S2MPS11_REG_B10CTRL1,			\  	.enable_mask	= S2MPS11_ENABLE_MASK			\  } diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 73dce766412..df395187c06 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -305,8 +305,8 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)  	if (!regs)  		return NULL; -	count = of_regulator_match(pdev->dev.parent, regs, -				reg_matches, TPS65217_NUM_REGULATOR); +	count = of_regulator_match(&pdev->dev, regs, reg_matches, +				   TPS65217_NUM_REGULATOR);  	of_node_put(regs);  	if ((count < 0) || (count > TPS65217_NUM_REGULATOR))  		return NULL; diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 59c3770fa77..b0e4c0bc85c 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -998,7 +998,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(  		return NULL;  	} -	ret = of_regulator_match(pdev->dev.parent, regulators, matches, count); +	ret = of_regulator_match(&pdev->dev, regulators, matches, count);  	if (ret < 0) {  		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",  			ret); diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index afb7cfa85cc..c016ad81767 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -506,6 +506,7 @@ isl1208_rtc_interrupt(int irq, void *data)  {  	unsigned long timeout = jiffies + msecs_to_jiffies(1000);  	struct i2c_client *client = data; +	struct rtc_device *rtc = i2c_get_clientdata(client);  	int handled = 0, sr, err;  	/* @@ -528,6 +529,8 @@ isl1208_rtc_interrupt(int irq, void *data)  	if (sr & ISL1208_REG_SR_ALM) {  		dev_dbg(&client->dev, "alarm!\n"); +		rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); +  		/* Clear the alarm */  		sr &= ~ISL1208_REG_SR_ALM;  		sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08378e3cc21..10c1a3454e4 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -44,6 +44,7 @@  #define RTC_YMR		0x34	/* Year match register */  #define RTC_YLR		0x38	/* Year data load register */ +#define RTC_CR_EN	(1 << 0)	/* counter enable bit */  #define RTC_CR_CWEN	(1 << 26)	/* Clockwatch enable bit */  #define RTC_TCR_EN	(1 << 1) /* Periodic timer enable bit */ @@ -320,7 +321,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)  	struct pl031_local *ldata;  	struct pl031_vendor_data *vendor = id->data;  	struct rtc_class_ops *ops = &vendor->ops; -	unsigned long time; +	unsigned long time, data;  	ret = amba_request_regions(adev, NULL);  	if (ret) @@ -345,10 +346,11 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)  	dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));  	dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev)); +	data = readl(ldata->base + RTC_CR);  	/* Enable the clockwatch on ST Variants */  	if (vendor->clockwatch) -		writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, -		       ldata->base + RTC_CR); +		data |= RTC_CR_CWEN; +	writel(data | RTC_CR_EN, ldata->base + RTC_CR);  	/*  	 * On ST PL031 variants, the RTC reset value does not provide correct diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 00c930f4b6f..2730533e2d2 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -137,7 +137,7 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)  		return -EINVAL;  	} -	writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) +	writel((bin2bcd(tm->tm_year % 100) << DATE_YEAR_S)  		| (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)  		| (bin2bcd(tm->tm_mday))  		| ((tm->tm_year >= 200) << DATE_CENTURY_S), diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index a43415a7fbe..4c0f6d883dd 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -14,7 +14,7 @@  #include <linux/delay.h>  #include <linux/export.h>  #ifdef CONFIG_BCM47XX -#include <asm/mach-bcm47xx/nvram.h> +#include <bcm47xx_nvram.h>  #endif  #include "ssb_private.h" @@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)  	if (bus->bustype == SSB_BUSTYPE_SSB) {  #ifdef CONFIG_BCM47XX  		char buf[20]; -		if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) +		if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)  			crystalfreq = simple_strtoul(buf, NULL, 0);  #endif  	} diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c index 97ac0a38e3d..eb2753008ef 100644 --- a/drivers/ssb/driver_gpio.c +++ b/drivers/ssb/driver_gpio.c @@ -174,3 +174,15 @@ int ssb_gpio_init(struct ssb_bus *bus)  	return -1;  } + +int ssb_gpio_unregister(struct ssb_bus *bus) +{ +	if (ssb_chipco_available(&bus->chipco) || +	    ssb_extif_available(&bus->extif)) { +		return gpiochip_remove(&bus->gpio); +	} else { +		SSB_WARN_ON(1); +	} + +	return -1; +} diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 772ad9b5c30..24dc331b470 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -443,6 +443,15 @@ static void ssb_devices_unregister(struct ssb_bus *bus)  void ssb_bus_unregister(struct ssb_bus *bus)  { +	int err; + +	err = ssb_gpio_unregister(bus); +	if (err == -EBUSY) +		ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n"); +	else if (err) +		ssb_dprintk(KERN_ERR PFX +			    "Can not unregister GPIO driver: %i\n", err); +  	ssb_buses_lock();  	ssb_devices_unregister(bus);  	list_del(&bus->list); diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 6c10b66c796..da38305a2d2 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h @@ -252,11 +252,16 @@ static inline void ssb_extif_init(struct ssb_extif *extif)  #ifdef CONFIG_SSB_DRIVER_GPIO  extern int ssb_gpio_init(struct ssb_bus *bus); +extern int ssb_gpio_unregister(struct ssb_bus *bus);  #else /* CONFIG_SSB_DRIVER_GPIO */  static inline int ssb_gpio_init(struct ssb_bus *bus)  {  	return -ENOTSUPP;  } +static inline int ssb_gpio_unregister(struct ssb_bus *bus) +{ +	return 0; +}  #endif /* CONFIG_SSB_DRIVER_GPIO */  #endif /* LINUX_SSB_PRIVATE_H_ */ diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index e2695101bb9..f2aa7543d20 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -941,6 +941,8 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)  int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)  { +	int block_size = dev->dev_attrib.block_size; +  	if (dev->export_count) {  		pr_err("dev[%p]: Unable to change SE Device"  			" fabric_max_sectors while export_count is %d\n", @@ -978,8 +980,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)  	/*  	 * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()  	 */ +	if (!block_size) { +		block_size = 512; +		pr_warn("Defaulting to 512 for zero block_size\n"); +	}  	fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, -						      dev->dev_attrib.block_size); +						      block_size);  	dev->dev_attrib.fabric_max_sectors = fabric_max_sectors;  	pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 810263dfa4a..c57bbbc7a7d 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -754,6 +754,11 @@ static int target_fabric_port_link(  		return -EFAULT;  	} +	if (!(dev->dev_flags & DF_CONFIGURED)) { +		pr_err("se_device not configured yet, cannot port link\n"); +		return -ENODEV; +	} +  	tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;  	se_tpg = container_of(to_config_group(tpg_ci),  				struct se_portal_group, tpg_group); diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 26a6d183ccb..a664c664a31 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -58,11 +58,10 @@ sbc_emulate_readcapacity(struct se_cmd *cmd)  	buf[7] = dev->dev_attrib.block_size & 0xff;  	rbuf = transport_kmap_data_sg(cmd); -	if (!rbuf) -		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - -	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); -	transport_kunmap_data_sg(cmd); +	if (rbuf) { +		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); +		transport_kunmap_data_sg(cmd); +	}  	target_complete_cmd(cmd, GOOD);  	return 0; @@ -97,11 +96,10 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)  		buf[14] = 0x80;  	rbuf = transport_kmap_data_sg(cmd); -	if (!rbuf) -		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - -	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); -	transport_kunmap_data_sg(cmd); +	if (rbuf) { +		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); +		transport_kunmap_data_sg(cmd); +	}  	target_complete_cmd(cmd, GOOD);  	return 0; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 84f9e96e8ac..2d88f087d96 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -641,11 +641,10 @@ spc_emulate_inquiry(struct se_cmd *cmd)  out:  	rbuf = transport_kmap_data_sg(cmd); -	if (!rbuf) -		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - -	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); -	transport_kunmap_data_sg(cmd); +	if (rbuf) { +		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); +		transport_kunmap_data_sg(cmd); +	}  	if (!ret)  		target_complete_cmd(cmd, GOOD); @@ -851,7 +850,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)  {  	struct se_device *dev = cmd->se_dev;  	char *cdb = cmd->t_task_cdb; -	unsigned char *buf, *map_buf; +	unsigned char buf[SE_MODE_PAGE_BUF], *rbuf;  	int type = dev->transport->get_device_type(dev);  	int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);  	bool dbd = !!(cdb[1] & 0x08); @@ -863,26 +862,8 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)  	int ret;  	int i; -	map_buf = transport_kmap_data_sg(cmd); -	if (!map_buf) -		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; -	/* -	 * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we -	 * know we actually allocated a full page.  Otherwise, if the -	 * data buffer is too small, allocate a temporary buffer so we -	 * don't have to worry about overruns in all our INQUIRY -	 * emulation handling. -	 */ -	if (cmd->data_length < SE_MODE_PAGE_BUF && -	    (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { -		buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); -		if (!buf) { -			transport_kunmap_data_sg(cmd); -			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; -		} -	} else { -		buf = map_buf; -	} +	memset(buf, 0, SE_MODE_PAGE_BUF); +  	/*  	 * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for  	 * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). @@ -934,8 +915,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)  	if (page == 0x3f) {  		if (subpage != 0x00 && subpage != 0xff) {  			pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); -			kfree(buf); -			transport_kunmap_data_sg(cmd);  			return TCM_INVALID_CDB_FIELD;  		} @@ -972,7 +951,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)  		pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",  		       page, subpage); -	transport_kunmap_data_sg(cmd);  	return TCM_UNKNOWN_MODE_PAGE;  set_length: @@ -981,12 +959,12 @@ set_length:  	else  		buf[0] = length - 1; -	if (buf != map_buf) { -		memcpy(map_buf, buf, cmd->data_length); -		kfree(buf); +	rbuf = transport_kmap_data_sg(cmd); +	if (rbuf) { +		memcpy(rbuf, buf, min_t(u32, SE_MODE_PAGE_BUF, cmd->data_length)); +		transport_kunmap_data_sg(cmd);  	} -	transport_kunmap_data_sg(cmd);  	target_complete_cmd(cmd, GOOD);  	return 0;  } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 4225d5e7213..8e64adf8e4d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -39,6 +39,7 @@  #include <asm/unaligned.h>  #include <linux/platform_device.h>  #include <linux/workqueue.h> +#include <linux/pm_runtime.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> @@ -1025,6 +1026,49 @@ static int register_root_hub(struct usb_hcd *hcd)  	return retval;  } +/* + * usb_hcd_start_port_resume - a root-hub port is sending a resume signal + * @bus: the bus which the root hub belongs to + * @portnum: the port which is being resumed + * + * HCDs should call this function when they know that a resume signal is + * being sent to a root-hub port.  The root hub will be prevented from + * going into autosuspend until usb_hcd_end_port_resume() is called. + * + * The bus's private lock must be held by the caller. + */ +void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum) +{ +	unsigned bit = 1 << portnum; + +	if (!(bus->resuming_ports & bit)) { +		bus->resuming_ports |= bit; +		pm_runtime_get_noresume(&bus->root_hub->dev); +	} +} +EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume); + +/* + * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal + * @bus: the bus which the root hub belongs to + * @portnum: the port which is being resumed + * + * HCDs should call this function when they know that a resume signal has + * stopped being sent to a root-hub port.  The root hub will be allowed to + * autosuspend again. + * + * The bus's private lock must be held by the caller. + */ +void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum) +{ +	unsigned bit = 1 << portnum; + +	if (bus->resuming_ports & bit) { +		bus->resuming_ports &= ~bit; +		pm_runtime_put_noidle(&bus->root_hub->dev); +	} +} +EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 957ed2c4148..cbf7168e3ce 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2838,6 +2838,23 @@ void usb_enable_ltm(struct usb_device *udev)  EXPORT_SYMBOL_GPL(usb_enable_ltm);  #ifdef	CONFIG_USB_SUSPEND +/* + * usb_disable_function_remotewakeup - disable usb3.0 + * device's function remote wakeup + * @udev: target device + * + * Assume there's only one function on the USB 3.0 + * device and disable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ +static int usb_disable_function_remotewakeup(struct usb_device *udev) +{ +	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), +				USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, +				USB_INTRF_FUNC_SUSPEND,	0, NULL, 0, +				USB_CTRL_SET_TIMEOUT); +}  /*   * usb_port_suspend - suspend a usb device's upstream port @@ -2955,12 +2972,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",  				port1, status);  		/* paranoia:  "should not happen" */ -		if (udev->do_remote_wakeup) -			(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), -				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, -				USB_DEVICE_REMOTE_WAKEUP, 0, -				NULL, 0, -				USB_CTRL_SET_TIMEOUT); +		if (udev->do_remote_wakeup) { +			if (!hub_is_superspeed(hub->hdev)) { +				(void) usb_control_msg(udev, +						usb_sndctrlpipe(udev, 0), +						USB_REQ_CLEAR_FEATURE, +						USB_RECIP_DEVICE, +						USB_DEVICE_REMOTE_WAKEUP, 0, +						NULL, 0, +						USB_CTRL_SET_TIMEOUT); +			} else +				(void) usb_disable_function_remotewakeup(udev); + +		}  		/* Try to enable USB2 hardware LPM again */  		if (udev->usb2_hw_lpm_capable == 1) @@ -3052,20 +3076,30 @@ static int finish_port_resume(struct usb_device *udev)  	 * udev->reset_resume  	 */  	} else if (udev->actconfig && !udev->reset_resume) { -		le16_to_cpus(&devstatus); -		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { -			status = usb_control_msg(udev, -					usb_sndctrlpipe(udev, 0), -					USB_REQ_CLEAR_FEATURE, +		if (!hub_is_superspeed(udev->parent)) { +			le16_to_cpus(&devstatus); +			if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) +				status = usb_control_msg(udev, +						usb_sndctrlpipe(udev, 0), +						USB_REQ_CLEAR_FEATURE,  						USB_RECIP_DEVICE, -					USB_DEVICE_REMOTE_WAKEUP, 0, -					NULL, 0, -					USB_CTRL_SET_TIMEOUT); -			if (status) -				dev_dbg(&udev->dev, -					"disable remote wakeup, status %d\n", -					status); +						USB_DEVICE_REMOTE_WAKEUP, 0, +						NULL, 0, +						USB_CTRL_SET_TIMEOUT); +		} else { +			status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, +					&devstatus); +			le16_to_cpus(&devstatus); +			if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP +					| USB_INTRF_STAT_FUNC_RW)) +				status = +					usb_disable_function_remotewakeup(udev);  		} + +		if (status) +			dev_dbg(&udev->dev, +				"disable remote wakeup, status %d\n", +				status);  		status = 0;  	}  	return status; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 09537b2f100..b416a3fc995 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);  			set_bit(i, &ehci->resuming_ports);  			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); +			usb_hcd_start_port_resume(&hcd->self, i);  			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);  		}  	} diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4ccb97c0678..4d3b294f203 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  			status = STS_PCD;  		}  	} -	/* FIXME autosuspend idle root hubs */ + +	/* If a resume is in progress, make sure it can finish */ +	if (ehci->resuming_ports) +		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); +  	spin_unlock_irqrestore (&ehci->lock, flags);  	return status ? retval : 0;  } @@ -851,6 +855,7 @@ static int ehci_hub_control (  				/* resume signaling for 20 msec */  				ehci->reset_done[wIndex] = jiffies  						+ msecs_to_jiffies(20); +				usb_hcd_start_port_resume(&hcd->self, wIndex);  				/* check the port again */  				mod_timer(&ehci_to_hcd(ehci)->rh_timer,  						ehci->reset_done[wIndex]); @@ -862,6 +867,7 @@ static int ehci_hub_control (  				clear_bit(wIndex, &ehci->suspended_ports);  				set_bit(wIndex, &ehci->port_c_suspend);  				ehci->reset_done[wIndex] = 0; +				usb_hcd_end_port_resume(&hcd->self, wIndex);  				/* stop resume signaling */  				temp = ehci_readl(ehci, status_reg); @@ -950,6 +956,7 @@ static int ehci_hub_control (  			ehci->reset_done[wIndex] = 0;  			if (temp & PORT_PE)  				set_bit(wIndex, &ehci->port_c_suspend); +			usb_hcd_end_port_resume(&hcd->self, wIndex);  		}  		if (temp & PORT_OC) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3d989028c83..fd252f0cfb3 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)  	if (ehci->async_iaa || ehci->async_unlinking)  		return; -	/* Do all the waiting QHs at once */ -	ehci->async_iaa = ehci->async_unlink; -	ehci->async_unlink = NULL; -  	/* If the controller isn't running, we don't have to wait for it */  	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { + +		/* Do all the waiting QHs */ +		ehci->async_iaa = ehci->async_unlink; +		ehci->async_unlink = NULL; +  		if (!nested)		/* Avoid recursion */  			end_unlink_async(ehci);  	/* Otherwise start a new IAA cycle */  	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { +		struct ehci_qh		*qh; + +		/* Do only the first waiting QH (nVidia bug?) */ +		qh = ehci->async_unlink; +		ehci->async_iaa = qh; +		ehci->async_unlink = qh->unlink_next; +		qh->unlink_next = NULL; +  		/* Make sure the unlinks are all visible to the hardware */  		wmb(); @@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)  	}  } +static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); +  static void unlink_empty_async(struct ehci_hcd *ehci)  { -	struct ehci_qh		*qh, *next; -	bool			stopped = (ehci->rh_state < EHCI_RH_RUNNING); +	struct ehci_qh		*qh; +	struct ehci_qh		*qh_to_unlink = NULL;  	bool			check_unlinks_later = false; +	int			count = 0; -	/* Unlink all the async QHs that have been empty for a timer cycle */ -	next = ehci->async->qh_next.qh; -	while (next) { -		qh = next; -		next = qh->qh_next.qh; - +	/* Find the last async QH which has been empty for a timer cycle */ +	for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {  		if (list_empty(&qh->qtd_list) &&  				qh->qh_state == QH_STATE_LINKED) { -			if (!stopped && qh->unlink_cycle == -					ehci->async_unlink_cycle) +			++count; +			if (qh->unlink_cycle == ehci->async_unlink_cycle)  				check_unlinks_later = true;  			else -				single_unlink_async(ehci, qh); +				qh_to_unlink = qh;  		}  	} -	/* Start a new IAA cycle if any QHs are waiting for it */ -	if (ehci->async_unlink) -		start_iaa_cycle(ehci, false); +	/* If nothing else is being unlinked, unlink the last empty QH */ +	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { +		start_unlink_async(ehci, qh_to_unlink); +		--count; +	} -	/* QHs that haven't been empty for long enough will be handled later */ -	if (check_unlinks_later) { +	/* Other QHs will be handled later */ +	if (count > 0) {  		ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);  		++ehci->async_unlink_cycle;  	} diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 69ebee73c0c..b476daf49f6 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)  }  static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };  /* carryover low/fullspeed bandwidth that crosses uframe boundries */  static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) @@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)  	}  	ehci->now_frame = now_frame; +	frame = ehci->last_iso_frame;  	for (;;) {  		union ehci_shadow	q, *q_p;  		__hc32			type, *hw_p; -		frame = ehci->last_iso_frame;  restart:  		/* scan each element in frame's queue for completions */  		q_p = &ehci->pshadow [frame]; @@ -2321,6 +2321,9 @@ restart:  		/* Stop when we have reached the current frame */  		if (frame == now_frame)  			break; -		ehci->last_iso_frame = (frame + 1) & fmask; + +		/* The last frame may still have active siTDs */ +		ehci->last_iso_frame = frame; +		frame = (frame + 1) & fmask;  	}  } diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0..f904071d70d 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->ASS_poll_count++ < 20) { -			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); -			return; -		} -		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", -				want, actual); +		/* Poll again later */ +		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); +		++ehci->ASS_poll_count; +		return;  	} + +	if (ehci->ASS_poll_count > 20) +		ehci_dbg(ehci, "ASS poll count reached %d\n", +				ehci->ASS_poll_count);  	ehci->ASS_poll_count = 0;  	/* The status is up-to-date; restart or stop the schedule as needed */ @@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->PSS_poll_count++ < 20) { -			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); -			return; -		} -		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", -				want, actual); +		/* Poll again later */ +		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); +		return;  	} + +	if (ehci->PSS_poll_count > 20) +		ehci_dbg(ehci, "PSS poll count reached %d\n", +				ehci->PSS_poll_count);  	ehci->PSS_poll_count = 0;  	/* The status is up-to-date; restart or stop the schedule as needed */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index a3b6d7104ae..4c338ec03a0 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)  				"defaulting to EHCI.\n");  		dev_warn(&xhci_pdev->dev,  				"USB 3.0 devices will work at USB 2.0 speeds.\n"); +		usb_disable_xhci_ports(xhci_pdev);  		return;  	} diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 768d54295a2..15d13229ddb 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,  		}  	}  	clear_bit(port, &uhci->resuming_ports); +	usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);  }  /* Wait for the UHCI controller in HP's iLO2 server management chip. @@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)  				set_bit(port, &uhci->resuming_ports);  				uhci->ports_timeout = jiffies +  						msecs_to_jiffies(25); +				usb_hcd_start_port_resume( +						&uhci_to_hcd(uhci)->self, port);  				/* Make sure we see the port again  				 * after the resuming period is over. */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 59fb5c677db..7f76a49e90d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,  				faked_port_index + 1);  		if (slot_id && xhci->devs[slot_id])  			xhci_ring_device(xhci, slot_id); -		if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { +		if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {  			bus_state->port_remote_wakeup &=  				~(1 << faked_port_index);  			xhci_test_and_clear_bit(xhci, port_array, @@ -2589,6 +2589,8 @@ cleanup:  				(trb_comp_code != COMP_STALL &&  					trb_comp_code != COMP_BABBLE))  				xhci_urb_free_priv(xhci, urb_priv); +			else +				kfree(urb_priv);  			usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);  			if ((urb->actual_length != urb->transfer_buffer_length && @@ -3108,7 +3110,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,  	 * running_total.  	 */  	packets_transferred = (running_total + trb_buff_len) / -		usb_endpoint_maxp(&urb->ep->desc); +		GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));  	if ((total_packet_count - packets_transferred) > 31)  		return 31 << 17; @@ -3642,7 +3644,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		td_len = urb->iso_frame_desc[i].length;  		td_remain_len = td_len;  		total_packet_count = DIV_ROUND_UP(td_len, -				usb_endpoint_maxp(&urb->ep->desc)); +				GET_MAX_PACKET( +					usb_endpoint_maxp(&urb->ep->desc)));  		/* A zero-length transfer still involves at least one packet. */  		if (total_packet_count == 0)  			total_packet_count++; @@ -3664,9 +3667,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		td = urb_priv->td[i];  		for (j = 0; j < trbs_per_td; j++) {  			u32 remainder = 0; -			field = TRB_TBC(burst_count) | TRB_TLBPC(residue); +			field = 0;  			if (first_trb) { +				field = TRB_TBC(burst_count) | +					TRB_TLBPC(residue);  				/* Queue the isoc TRB */  				field |= TRB_TYPE(TRB_ISOC);  				/* Assume URB_ISO_ASAP is set */ diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f14736f647f..edc0f0dcad8 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */  	{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */  	{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ +	{ USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */  	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */  	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */  	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ba68835d06a..90ceef1776c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = {  	/*  	 * ELV devices:  	 */ +	{ USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, @@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },  	{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },  	{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },  	{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index fa5d5603827..9d359e189a6 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -147,6 +147,11 @@  #define XSENS_CONVERTER_6_PID	0xD38E  #define XSENS_CONVERTER_7_PID	0xD38F +/** + * Zolix (www.zolix.com.cb) product ids + */ +#define FTDI_OMNI1509			0xD491	/* Omni1509 embedded USB-serial */ +  /*   * NDI (www.ndigital.com) product ids   */ @@ -204,7 +209,7 @@  /*   * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). - * All of these devices use FTDI's vendor ID (0x0403). + * Almost all of these devices use FTDI's vendor ID (0x0403).   * Further IDs taken from ELV Windows .inf file.   *   * The previously included PID for the UO 100 module was incorrect. @@ -212,6 +217,8 @@   *   * Armin Laeuger originally sent the PID for the UM 100 module.   */ +#define FTDI_ELV_VID	0x1B1F	/* ELV AG */ +#define FTDI_ELV_WS300_PID	0xC006	/* eQ3 WS 300 PC II */  #define FTDI_ELV_USR_PID	0xE000	/* ELV Universal-Sound-Recorder */  #define FTDI_ELV_MSM1_PID	0xE001	/* ELV Mini-Sound-Modul */  #define FTDI_ELV_KL100_PID	0xE002	/* ELV Kfz-Leistungsmesser KL 100 */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 0d9dac9e7f9..567bc77d639 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb);  #define TELIT_PRODUCT_CC864_DUAL		0x1005  #define TELIT_PRODUCT_CC864_SINGLE		0x1006  #define TELIT_PRODUCT_DE910_DUAL		0x1010 +#define TELIT_PRODUCT_LE920			0x1200  /* ZTE PRODUCTS */  #define ZTE_VENDOR_ID				0x19d2 @@ -453,6 +454,10 @@ static void option_instat_callback(struct urb *urb);  #define TPLINK_VENDOR_ID			0x2357  #define TPLINK_PRODUCT_MA180			0x0201 +/* Changhong products */ +#define CHANGHONG_VENDOR_ID			0x2077 +#define CHANGHONG_PRODUCT_CH690			0x7001 +  /* some devices interfaces need special handling due to a number of reasons */  enum option_blacklist_reason {  		OPTION_BLACKLIST_NONE = 0, @@ -534,6 +539,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {  	.reserved = BIT(3) | BIT(4),  }; +static const struct option_blacklist_info telit_le920_blacklist = { +	.sendsetup = BIT(0), +	.reserved = BIT(1) | BIT(5), +}; +  static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },  	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -784,6 +794,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },  	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },  	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, +	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), +		.driver_info = (kernel_ulong_t)&telit_le920_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t)&net_intf1_blacklist }, @@ -1318,6 +1330,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },  	{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +	{ USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index aa148c21ea4..24662547dc5 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {  	{DEVICE_G1K(0x05c6, 0x9221)},	/* Generic Gobi QDL device */  	{DEVICE_G1K(0x05c6, 0x9231)},	/* Generic Gobi QDL device */  	{DEVICE_G1K(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */ +	{DEVICE_G1K(0x1bc7, 0x900e)},	/* Telit Gobi QDL device */  	/* Gobi 2000 devices */  	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi 2000 QDL device */ diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 105d900150c..16b0bf055ee 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)  	return 0;  } -/* This places the HUAWEI E220 devices in multi-port mode */ -int usb_stor_huawei_e220_init(struct us_data *us) +/* This places the HUAWEI usb dongles in multi-port mode */ +static int usb_stor_huawei_feature_init(struct us_data *us)  {  	int result; @@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us)  	US_DEBUGP("Huawei mode set result is %d\n", result);  	return 0;  } + +/* + * It will send a scsi switch command called rewind' to huawei dongle. + * When the dongle receives this command at the first time, + * it will reboot immediately. After rebooted, it will ignore this command. + * So it is  unnecessary to read its response. + */ +static int usb_stor_huawei_scsi_init(struct us_data *us) +{ +	int result = 0; +	int act_len = 0; +	struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf; +	char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, +			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +	bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN); +	bcbw->Tag = 0; +	bcbw->DataTransferLength = 0; +	bcbw->Flags = bcbw->Lun = 0; +	bcbw->Length = sizeof(rewind_cmd); +	memset(bcbw->CDB, 0, sizeof(bcbw->CDB)); +	memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd)); + +	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw, +					US_BULK_CB_WRAP_LEN, &act_len); +	US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result); +	return result; +} + +/* + * It tries to find the supported Huawei USB dongles. + * In Huawei, they assign the following product IDs + * for all of their mobile broadband dongles, + * including the new dongles in the future. + * So if the product ID is not included in this list, + * it means it is not Huawei's mobile broadband dongles. + */ +static int usb_stor_huawei_dongles_pid(struct us_data *us) +{ +	struct usb_interface_descriptor *idesc; +	int idProduct; + +	idesc = &us->pusb_intf->cur_altsetting->desc; +	idProduct = us->pusb_dev->descriptor.idProduct; +	/* The first port is CDROM, +	 * means the dongle in the single port mode, +	 * and a switch command is required to be sent. */ +	if (idesc && idesc->bInterfaceNumber == 0) { +		if ((idProduct == 0x1001) +			|| (idProduct == 0x1003) +			|| (idProduct == 0x1004) +			|| (idProduct >= 0x1401 && idProduct <= 0x1500) +			|| (idProduct >= 0x1505 && idProduct <= 0x1600) +			|| (idProduct >= 0x1c02 && idProduct <= 0x2202)) { +			return 1; +		} +	} +	return 0; +} + +int usb_stor_huawei_init(struct us_data *us) +{ +	int result = 0; + +	if (usb_stor_huawei_dongles_pid(us)) { +		if (us->pusb_dev->descriptor.idProduct >= 0x1446) +			result = usb_stor_huawei_scsi_init(us); +		else +			result = usb_stor_huawei_feature_init(us); +	} +	return result; +} diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 529327fbb06..5376d4fc76f 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);   * flash reader */  int usb_stor_ucr61s2b_init(struct us_data *us); -/* This places the HUAWEI E220 devices in multi-port mode */ -int usb_stor_huawei_e220_init(struct us_data *us); +/* This places the HUAWEI usb dongles in multi-port mode */ +int usb_stor_huawei_init(struct us_data *us); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d305a5aa3a5..72923b56bbf 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1527,335 +1527,10 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,  /* Reported by fangxiaozhi <huananhu@huawei.com>   * This brings the HUAWEI data card devices into multi-port mode   */ -UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000, +UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,  		"HUAWEI MOBILE",  		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, -		0), -UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000, -		"HUAWEI MOBILE", -		"Mass Storage", -		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, +		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,  		0),  /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 31b3e1a61bb..cf09b6ba71f 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");  	.useTransport = use_transport,	\  } +#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \ +		vendor_name, product_name, use_protocol, use_transport, \ +		init_function, Flags) \ +{ \ +	.vendorName = vendor_name,	\ +	.productName = product_name,	\ +	.useProtocol = use_protocol,	\ +	.useTransport = use_transport,	\ +	.initFunction = init_function,	\ +} +  static struct us_unusual_dev us_unusual_dev_list[] = {  #	include "unusual_devs.h"  	{ }		/* Terminating entry */ @@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids =  #undef UNUSUAL_DEV  #undef COMPLIANT_DEV  #undef USUAL_DEV +#undef UNUSUAL_VENDOR_INTF  #ifdef CONFIG_LOCKDEP diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index b78a526910f..5ef8ce74aae 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -41,6 +41,20 @@  #define USUAL_DEV(useProto, useTrans) \  { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) } +/* Define the device is matched with Vendor ID and interface descriptors */ +#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \ +			vendorName, productName, useProtocol, useTransport, \ +			initFunction, flags) \ +{ \ +	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ +				| USB_DEVICE_ID_MATCH_VENDOR, \ +	.idVendor    = (id_vendor), \ +	.bInterfaceClass = (cl), \ +	.bInterfaceSubClass = (sc), \ +	.bInterfaceProtocol = (pr), \ +	.driver_info = (flags) \ +} +  struct usb_device_id usb_storage_usb_ids[] = {  #	include "unusual_devs.h"  	{ }		/* Terminating entry */ @@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);  #undef UNUSUAL_DEV  #undef COMPLIANT_DEV  #undef USUAL_DEV +#undef UNUSUAL_VENDOR_INTF  /*   * The table of devices to ignore diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index ebd08b21b23..959b1cd89e6 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -165,12 +165,16 @@ static void tx_poll_stop(struct vhost_net *net)  }  /* Caller must have TX VQ lock */ -static void tx_poll_start(struct vhost_net *net, struct socket *sock) +static int tx_poll_start(struct vhost_net *net, struct socket *sock)  { +	int ret; +  	if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED)) -		return; -	vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file); -	net->tx_poll_state = VHOST_NET_POLL_STARTED; +		return 0; +	ret = vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file); +	if (!ret) +		net->tx_poll_state = VHOST_NET_POLL_STARTED; +	return ret;  }  /* In case of DMA done not in order in lower device driver for some reason. @@ -642,20 +646,23 @@ static void vhost_net_disable_vq(struct vhost_net *n,  		vhost_poll_stop(n->poll + VHOST_NET_VQ_RX);  } -static void vhost_net_enable_vq(struct vhost_net *n, +static int vhost_net_enable_vq(struct vhost_net *n,  				struct vhost_virtqueue *vq)  {  	struct socket *sock; +	int ret;  	sock = rcu_dereference_protected(vq->private_data,  					 lockdep_is_held(&vq->mutex));  	if (!sock) -		return; +		return 0;  	if (vq == n->vqs + VHOST_NET_VQ_TX) {  		n->tx_poll_state = VHOST_NET_POLL_STOPPED; -		tx_poll_start(n, sock); +		ret = tx_poll_start(n, sock);  	} else -		vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file); +		ret = vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file); + +	return ret;  }  static struct socket *vhost_net_stop_vq(struct vhost_net *n, @@ -827,15 +834,18 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)  			r = PTR_ERR(ubufs);  			goto err_ubufs;  		} -		oldubufs = vq->ubufs; -		vq->ubufs = ubufs; +  		vhost_net_disable_vq(n, vq);  		rcu_assign_pointer(vq->private_data, sock); -		vhost_net_enable_vq(n, vq); -  		r = vhost_init_used(vq);  		if (r) -			goto err_vq; +			goto err_used; +		r = vhost_net_enable_vq(n, vq); +		if (r) +			goto err_used; + +		oldubufs = vq->ubufs; +		vq->ubufs = ubufs;  		n->tx_packets = 0;  		n->tx_zcopy_err = 0; @@ -859,6 +869,11 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)  	mutex_unlock(&n->dev.mutex);  	return 0; +err_used: +	rcu_assign_pointer(vq->private_data, oldsock); +	vhost_net_enable_vq(n, vq); +	if (ubufs) +		vhost_ubuf_put_and_wait(ubufs);  err_ubufs:  	fput(sock->file);  err_vq: diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index b20df5c829f..22321cf84fb 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c @@ -575,10 +575,8 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs)  	/* Must use ioctl VHOST_SCSI_SET_ENDPOINT */  	tv_tpg = vs->vs_tpg; -	if (unlikely(!tv_tpg)) { -		pr_err("%s endpoint not set\n", __func__); +	if (unlikely(!tv_tpg))  		return; -	}  	mutex_lock(&vq->mutex);  	vhost_disable_notify(&vs->dev, vq); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 34389f75fe6..9759249e6d9 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -77,26 +77,38 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,  	init_poll_funcptr(&poll->table, vhost_poll_func);  	poll->mask = mask;  	poll->dev = dev; +	poll->wqh = NULL;  	vhost_work_init(&poll->work, fn);  }  /* Start polling a file. We add ourselves to file's wait queue. The caller must   * keep a reference to a file until after vhost_poll_stop is called. */ -void vhost_poll_start(struct vhost_poll *poll, struct file *file) +int vhost_poll_start(struct vhost_poll *poll, struct file *file)  {  	unsigned long mask; +	int ret = 0;  	mask = file->f_op->poll(file, &poll->table);  	if (mask)  		vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); +	if (mask & POLLERR) { +		if (poll->wqh) +			remove_wait_queue(poll->wqh, &poll->wait); +		ret = -EINVAL; +	} + +	return ret;  }  /* Stop polling a file. After this function returns, it becomes safe to drop the   * file reference. You must also flush afterwards. */  void vhost_poll_stop(struct vhost_poll *poll)  { -	remove_wait_queue(poll->wqh, &poll->wait); +	if (poll->wqh) { +		remove_wait_queue(poll->wqh, &poll->wait); +		poll->wqh = NULL; +	}  }  static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, @@ -792,7 +804,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)  		fput(filep);  	if (pollstart && vq->handle_kick) -		vhost_poll_start(&vq->poll, vq->kick); +		r = vhost_poll_start(&vq->poll, vq->kick);  	mutex_unlock(&vq->mutex); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 2639c58b23a..17261e277c0 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -42,7 +42,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work);  void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,  		     unsigned long mask, struct vhost_dev *dev); -void vhost_poll_start(struct vhost_poll *poll, struct file *file); +int vhost_poll_start(struct vhost_poll *poll, struct file *file);  void vhost_poll_stop(struct vhost_poll *poll);  void vhost_poll_flush(struct vhost_poll *poll);  void vhost_poll_queue(struct vhost_poll *poll); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 0be4df39e95..74d77dfa5f6 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -840,7 +840,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)  	if (irq == -1) {  		irq = xen_allocate_irq_dynamic(); -		if (irq == -1) +		if (irq < 0)  			goto out;  		irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, @@ -944,7 +944,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)  	if (irq == -1) {  		irq = xen_allocate_irq_dynamic(); -		if (irq == -1) +		if (irq < 0)  			goto out;  		irq_set_chip_and_handler_name(irq, &xen_percpu_chip, diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 97f5d264c31..37c1f825f51 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -135,7 +135,6 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,  			 struct pci_dev *dev, struct xen_pci_op *op)  {  	struct xen_pcibk_dev_data *dev_data; -	int otherend = pdev->xdev->otherend_id;  	int status;  	if (unlikely(verbose_request)) @@ -144,8 +143,9 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,  	status = pci_enable_msi(dev);  	if (status) { -		printk(KERN_ERR "error enable msi for guest %x status %x\n", -			otherend, status); +		pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI for guest %u: err %d\n", +				    pci_name(dev), pdev->xdev->otherend_id, +				    status);  		op->value = 0;  		return XEN_PCI_ERR_op_failed;  	} @@ -223,10 +223,10 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,  						pci_name(dev), i,  						op->msix_entries[i].vector);  		} -	} else { -		printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n", -			pci_name(dev), result); -	} +	} else +		pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI-X for guest %u: err %d!\n", +				    pci_name(dev), pdev->xdev->otherend_id, +				    result);  	kfree(entries);  	op->value = result; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a8b8adc0507..5a3327b8f90 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4534,7 +4534,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)  	unsigned nr_extents = 0;  	int extra_reserve = 0;  	enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL; -	int ret; +	int ret = 0;  	bool delalloc_lock = true;  	/* If we are a free space inode we need to not flush since we will be in @@ -4579,20 +4579,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)  	csum_bytes = BTRFS_I(inode)->csum_bytes;  	spin_unlock(&BTRFS_I(inode)->lock); -	if (root->fs_info->quota_enabled) { +	if (root->fs_info->quota_enabled)  		ret = btrfs_qgroup_reserve(root, num_bytes +  					   nr_extents * root->leafsize); -		if (ret) { -			spin_lock(&BTRFS_I(inode)->lock); -			calc_csum_metadata_size(inode, num_bytes, 0); -			spin_unlock(&BTRFS_I(inode)->lock); -			if (delalloc_lock) -				mutex_unlock(&BTRFS_I(inode)->delalloc_mutex); -			return ret; -		} -	} -	ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); +	/* +	 * ret != 0 here means the qgroup reservation failed, we go straight to +	 * the shared error handling then. +	 */ +	if (ret == 0) +		ret = reserve_metadata_bytes(root, block_rsv, +					     to_reserve, flush); +  	if (ret) {  		u64 to_free = 0;  		unsigned dropped; diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 2e8cae63d24..fdb7a8db3b5 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -288,7 +288,8 @@ out:  void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em)  {  	clear_bit(EXTENT_FLAG_LOGGING, &em->flags); -	try_merge_map(tree, em); +	if (em->in_tree) +		try_merge_map(tree, em);  }  /** diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f76b1fd160d..aeb84469d2c 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -293,15 +293,24 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,  	struct btrfs_key key;  	struct btrfs_ioctl_defrag_range_args range;  	int num_defrag; +	int index; +	int ret;  	/* get the inode */  	key.objectid = defrag->root;  	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);  	key.offset = (u64)-1; + +	index = srcu_read_lock(&fs_info->subvol_srcu); +  	inode_root = btrfs_read_fs_root_no_name(fs_info, &key);  	if (IS_ERR(inode_root)) { -		kmem_cache_free(btrfs_inode_defrag_cachep, defrag); -		return PTR_ERR(inode_root); +		ret = PTR_ERR(inode_root); +		goto cleanup; +	} +	if (btrfs_root_refs(&inode_root->root_item) == 0) { +		ret = -ENOENT; +		goto cleanup;  	}  	key.objectid = defrag->ino; @@ -309,9 +318,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,  	key.offset = 0;  	inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL);  	if (IS_ERR(inode)) { -		kmem_cache_free(btrfs_inode_defrag_cachep, defrag); -		return PTR_ERR(inode); +		ret = PTR_ERR(inode); +		goto cleanup;  	} +	srcu_read_unlock(&fs_info->subvol_srcu, index);  	/* do a chunk of defrag */  	clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); @@ -346,6 +356,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,  	iput(inode);  	return 0; +cleanup: +	srcu_read_unlock(&fs_info->subvol_srcu, index); +	kmem_cache_free(btrfs_inode_defrag_cachep, defrag); +	return ret;  }  /* @@ -1594,9 +1608,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,  		if (err < 0 && num_written > 0)  			num_written = err;  	} -out: +  	if (sync)  		atomic_dec(&BTRFS_I(inode)->sync_writers); +out:  	sb_end_write(inode->i_sb);  	current->backing_dev_info = NULL;  	return num_written ? num_written : err; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5b22d45d3c6..338f2597bf7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -515,7 +515,6 @@ static noinline int create_subvol(struct btrfs_root *root,  	BUG_ON(ret); -	d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));  fail:  	if (async_transid) {  		*async_transid = trans->transid; @@ -525,6 +524,10 @@ fail:  	}  	if (err && !ret)  		ret = err; + +	if (!ret) +		d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); +  	return ret;  } diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index f1073129704..e5ed5672960 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -836,9 +836,16 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,  	 * if the disk i_size is already at the inode->i_size, or  	 * this ordered extent is inside the disk i_size, we're done  	 */ -	if (disk_i_size == i_size || offset <= disk_i_size) { +	if (disk_i_size == i_size) +		goto out; + +	/* +	 * We still need to update disk_i_size if outstanding_isize is greater +	 * than disk_i_size. +	 */ +	if (offset <= disk_i_size && +	    (!ordered || ordered->outstanding_isize <= disk_i_size))  		goto out; -	}  	/*  	 * walk backward from this ordered extent to disk_i_size. @@ -870,7 +877,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,  			break;  		if (test->file_offset >= i_size)  			break; -		if (test->file_offset >= disk_i_size) { +		if (entry_end(test) > disk_i_size) {  			/*  			 * we don't update disk_i_size now, so record this  			 * undealt i_size. Or we will not know the real diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index bdbb94f245c..67783e03d12 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -580,20 +580,29 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)  	int corrected = 0;  	struct btrfs_key key;  	struct inode *inode = NULL; +	struct btrfs_fs_info *fs_info;  	u64 end = offset + PAGE_SIZE - 1;  	struct btrfs_root *local_root; +	int srcu_index;  	key.objectid = root;  	key.type = BTRFS_ROOT_ITEM_KEY;  	key.offset = (u64)-1; -	local_root = btrfs_read_fs_root_no_name(fixup->root->fs_info, &key); -	if (IS_ERR(local_root)) + +	fs_info = fixup->root->fs_info; +	srcu_index = srcu_read_lock(&fs_info->subvol_srcu); + +	local_root = btrfs_read_fs_root_no_name(fs_info, &key); +	if (IS_ERR(local_root)) { +		srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);  		return PTR_ERR(local_root); +	}  	key.type = BTRFS_INODE_ITEM_KEY;  	key.objectid = inum;  	key.offset = 0; -	inode = btrfs_iget(fixup->root->fs_info->sb, &key, local_root, NULL); +	inode = btrfs_iget(fs_info->sb, &key, local_root, NULL); +	srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);  	if (IS_ERR(inode))  		return PTR_ERR(inode); @@ -606,7 +615,6 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)  	}  	if (PageUptodate(page)) { -		struct btrfs_fs_info *fs_info;  		if (PageDirty(page)) {  			/*  			 * we need to write the data to the defect sector. the @@ -3180,18 +3188,25 @@ static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root, void *ctx)  	u64 physical_for_dev_replace;  	u64 len;  	struct btrfs_fs_info *fs_info = nocow_ctx->sctx->dev_root->fs_info; +	int srcu_index;  	key.objectid = root;  	key.type = BTRFS_ROOT_ITEM_KEY;  	key.offset = (u64)-1; + +	srcu_index = srcu_read_lock(&fs_info->subvol_srcu); +  	local_root = btrfs_read_fs_root_no_name(fs_info, &key); -	if (IS_ERR(local_root)) +	if (IS_ERR(local_root)) { +		srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);  		return PTR_ERR(local_root); +	}  	key.type = BTRFS_INODE_ITEM_KEY;  	key.objectid = inum;  	key.offset = 0;  	inode = btrfs_iget(fs_info->sb, &key, local_root, NULL); +	srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);  	if (IS_ERR(inode))  		return PTR_ERR(inode); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f15494699f3..fc03aa60b68 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -333,12 +333,14 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,  					  &root->fs_info->trans_block_rsv,  					  num_bytes, flush);  		if (ret) -			return ERR_PTR(ret); +			goto reserve_fail;  	}  again:  	h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); -	if (!h) -		return ERR_PTR(-ENOMEM); +	if (!h) { +		ret = -ENOMEM; +		goto alloc_fail; +	}  	/*  	 * If we are JOIN_NOLOCK we're already committing a transaction and @@ -365,11 +367,7 @@ again:  	if (ret < 0) {  		/* We must get the transaction if we are JOIN_NOLOCK. */  		BUG_ON(type == TRANS_JOIN_NOLOCK); - -		if (type < TRANS_JOIN_NOLOCK) -			sb_end_intwrite(root->fs_info->sb); -		kmem_cache_free(btrfs_trans_handle_cachep, h); -		return ERR_PTR(ret); +		goto join_fail;  	}  	cur_trans = root->fs_info->running_transaction; @@ -410,6 +408,19 @@ got_it:  	if (!current->journal_info && type != TRANS_USERSPACE)  		current->journal_info = h;  	return h; + +join_fail: +	if (type < TRANS_JOIN_NOLOCK) +		sb_end_intwrite(root->fs_info->sb); +	kmem_cache_free(btrfs_trans_handle_cachep, h); +alloc_fail: +	if (num_bytes) +		btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv, +					num_bytes); +reserve_fail: +	if (qgroup_reserved) +		btrfs_qgroup_free(root, qgroup_reserved); +	return ERR_PTR(ret);  }  struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 15f6efdf646..5cbb7f4b167 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1556,7 +1556,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)  	ret = 0;  	/* Notify udev that device has changed */ -	btrfs_kobject_uevent(bdev, KOBJ_CHANGE); +	if (bdev) +		btrfs_kobject_uevent(bdev, KOBJ_CHANGE);  error_brelse:  	brelse(bh); diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 7ff49852b0c..911649a47dd 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -503,11 +503,11 @@ static ssize_t device_write(struct file *file, const char __user *buf,  #endif  		return -EINVAL; -#ifdef CONFIG_COMPAT -	if (count > sizeof(struct dlm_write_request32) + DLM_RESNAME_MAXLEN) -#else +	/* +	 * can't compare against COMPAT/dlm_write_request32 because +	 * we don't yet know if is64bit is zero +	 */  	if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN) -#endif  		return -EINVAL;  	kbuf = kzalloc(count + 1, GFP_NOFS); diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index fdb18076948..f3859354e41 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -664,8 +664,11 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,  	if (ret < 0)  		printk(KERN_ERR "NILFS: GC failed during preparation: "  			"cannot read source blocks: err=%d\n", ret); -	else +	else { +		if (nilfs_sb_need_update(nilfs)) +			set_nilfs_discontinued(nilfs);  		ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); +	}  	nilfs_remove_all_gcinodes(nilfs);  	clear_nilfs_gc_running(nilfs); diff --git a/include/linux/llist.h b/include/linux/llist.h index a5199f6d0e8..d0ab98f73d3 100644 --- a/include/linux/llist.h +++ b/include/linux/llist.h @@ -125,6 +125,31 @@ static inline void init_llist_head(struct llist_head *list)  	     (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))  /** + * llist_for_each_entry_safe - iterate safely against remove over some entries + * of lock-less list of given type. + * @pos:	the type * to use as a loop cursor. + * @n:		another type * to use as a temporary storage. + * @node:	the fist entry of deleted list entries. + * @member:	the name of the llist_node with the struct. + * + * In general, some entries of the lock-less list can be traversed + * safely only after being removed from list, so start with an entry + * instead of list head. This variant allows removal of entries + * as we iterate. + * + * If being used on entries deleted from lock-less list directly, the + * traverse order is from the newest to the oldest added entry.  If + * you want to traverse from the oldest to the newest, you must + * reverse the order by yourself before traversing. + */ +#define llist_for_each_entry_safe(pos, n, node, member)		\ +	for ((pos) = llist_entry((node), typeof(*(pos)), member),	\ +	     (n) = (pos)->member.next;					\ +	     &(pos)->member != NULL;					\ +	     (pos) = llist_entry(n, typeof(*(pos)), member),		\ +	     (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL) + +/**   * llist_empty - tests whether a lock-less list is empty   * @head:	the list to test   * diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 0108a56f814..28bd5fa2ff2 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -429,7 +429,7 @@ extern int memcg_limited_groups_array_size;   * the slab_mutex must be held when looping through those caches   */  #define for_each_memcg_cache_index(_idx)	\ -	for ((_idx) = 0; i < memcg_limited_groups_array_size; (_idx)++) +	for ((_idx) = 0; (_idx) < memcg_limited_groups_array_size; (_idx)++)  static inline bool memcg_kmem_enabled(void)  { diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h index bc823c4c028..deca8745252 100644 --- a/include/linux/mmu_notifier.h +++ b/include/linux/mmu_notifier.h @@ -151,7 +151,7 @@ struct mmu_notifier_ops {   * Therefore notifier chains can only be traversed when either   *   * 1. mmap_sem is held. - * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->mutex). + * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->rwsem).   * 3. No other concurrent thread can access the list (release)   */  struct mmu_notifier { diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h index 6b05dcd927f..6d92a92573d 100644 --- a/include/linux/ssb/ssb_driver_gige.h +++ b/include/linux/ssb/ssb_driver_gige.h @@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)  }  #ifdef CONFIG_BCM47XX -#include <asm/mach-bcm47xx/nvram.h> +#include <bcm47xx_nvram.h>  /* Get the device MAC address */  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)  {  	char buf[20]; -	if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0) +	if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)  		return; -	nvram_parse_macaddr(buf, macaddr); +	bcm47xx_nvram_parse_macaddr(buf, macaddr);  }  #else  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) diff --git a/include/linux/usb.h b/include/linux/usb.h index 689b14b26c8..4d22d0f6167 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -357,6 +357,8 @@ struct usb_bus {  	int bandwidth_int_reqs;		/* number of Interrupt requests */  	int bandwidth_isoc_reqs;	/* number of Isoc. requests */ +	unsigned resuming_ports;	/* bit array: resuming root-hub ports */ +  #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)  	struct mon_bus *mon_bus;	/* non-null when associated */  	int monitored;			/* non-zero when monitored */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 608050b2545..0a78df5f6cf 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -430,6 +430,9 @@ extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);  extern void usb_wakeup_notification(struct usb_device *hdev,  		unsigned int portnum); +extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum); +extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum); +  /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */  #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)  #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep))) diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 5de7a220e98..0e5ac93bab1 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -33,6 +33,7 @@ struct usbnet {  	wait_queue_head_t	*wait;  	struct mutex		phy_mutex;  	unsigned char		suspend_count; +	unsigned char		pkt_cnt, pkt_err;  	/* i/o info: pipes etc */  	unsigned		in, out; @@ -70,6 +71,7 @@ struct usbnet {  #		define EVENT_DEV_OPEN	7  #		define EVENT_DEVICE_REPORT_IDLE	8  #		define EVENT_NO_RUNTIME_PM	9 +#		define EVENT_RX_KILL	10  };  static inline struct usb_driver *driver_of(struct usb_interface *intf) @@ -100,7 +102,6 @@ struct driver_info {  #define FLAG_LINK_INTR	0x0800		/* updates link (carrier) status */  #define FLAG_POINTTOPOINT 0x1000	/* possibly use "usb%d" names */ -#define FLAG_NOARP	0x2000		/* device can't do ARP */  /*   * Indicates to usbnet, that USB driver accumulates multiple IP packets. @@ -108,6 +109,7 @@ struct driver_info {   */  #define FLAG_MULTI_PACKET	0x2000  #define FLAG_RX_ASSEMBLE	0x4000	/* rx packets may span >1 frames */ +#define FLAG_NOARP		0x8000	/* device can't do ARP */  	/* init device ... can sleep, or cause probe() failure */  	int	(*bind)(struct usbnet *, struct usb_interface *); diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 498433dd067..938b7fd1120 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -34,17 +34,17 @@ extern int				udpv6_connect(struct sock *sk,  						      struct sockaddr *uaddr,  						      int addr_len); -extern int			datagram_recv_ctl(struct sock *sk, -						  struct msghdr *msg, -						  struct sk_buff *skb); +extern int			ip6_datagram_recv_ctl(struct sock *sk, +						      struct msghdr *msg, +						      struct sk_buff *skb); -extern int			datagram_send_ctl(struct net *net, -						  struct sock *sk, -						  struct msghdr *msg, -						  struct flowi6 *fl6, -						  struct ipv6_txoptions *opt, -						  int *hlimit, int *tclass, -						  int *dontfrag); +extern int			ip6_datagram_send_ctl(struct net *net, +						      struct sock *sk, +						      struct msghdr *msg, +						      struct flowi6 *fl6, +						      struct ipv6_txoptions *opt, +						      int *hlimit, int *tclass, +						      int *dontfrag);  #define		LOOPBACK4_IPV6		cpu_to_be32(0x7f000006) diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 50598472dc4..f738e25377f 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -152,6 +152,12 @@  #define USB_INTRF_FUNC_SUSPEND_LP	(1 << (8 + 0))  #define USB_INTRF_FUNC_SUSPEND_RW	(1 << (8 + 1)) +/* + * Interface status, Figure 9-5 USB 3.0 spec + */ +#define USB_INTRF_STAT_FUNC_RW_CAP     1 +#define USB_INTRF_STAT_FUNC_RW         2 +  #define USB_ENDPOINT_HALT		0	/* IN/OUT will STALL */  /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ diff --git a/kernel/events/core.c b/kernel/events/core.c index 301079d06f2..7b6646a8c06 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -908,6 +908,15 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)  }  /* + * Initialize event state based on the perf_event_attr::disabled. + */ +static inline void perf_event__state_init(struct perf_event *event) +{ +	event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF : +					      PERF_EVENT_STATE_INACTIVE; +} + +/*   * Called at perf_event creation and when events are attached/detached from a   * group.   */ @@ -6179,8 +6188,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,  	event->overflow_handler	= overflow_handler;  	event->overflow_handler_context = context; -	if (attr->disabled) -		event->state = PERF_EVENT_STATE_OFF; +	perf_event__state_init(event);  	pmu = NULL; @@ -6609,9 +6617,17 @@ SYSCALL_DEFINE5(perf_event_open,  		mutex_lock(&gctx->mutex);  		perf_remove_from_context(group_leader); + +		/* +		 * Removing from the context ends up with disabled +		 * event. What we want here is event in the initial +		 * startup state, ready to be add into new context. +		 */ +		perf_event__state_init(group_leader);  		list_for_each_entry(sibling, &group_leader->sibling_list,  				    group_entry) {  			perf_remove_from_context(sibling); +			perf_event__state_init(sibling);  			put_ctx(gctx);  		}  		mutex_unlock(&gctx->mutex); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index f6e5ec2932b..c1cc7e17ff9 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -40,8 +40,7 @@  #ifdef CONFIG_RCU_NOCB_CPU  static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */  static bool have_rcu_nocb_mask;	    /* Was rcu_nocb_mask allocated? */ -static bool rcu_nocb_poll;	    /* Offload kthread are to poll. */ -module_param(rcu_nocb_poll, bool, 0444); +static bool __read_mostly rcu_nocb_poll;    /* Offload kthread are to poll. */  static char __initdata nocb_buf[NR_CPUS * 5];  #endif /* #ifdef CONFIG_RCU_NOCB_CPU */ @@ -2159,6 +2158,13 @@ static int __init rcu_nocb_setup(char *str)  }  __setup("rcu_nocbs=", rcu_nocb_setup); +static int __init parse_rcu_nocb_poll(char *arg) +{ +	rcu_nocb_poll = 1; +	return 0; +} +early_param("rcu_nocb_poll", parse_rcu_nocb_poll); +  /* Is the specified CPU a no-CPUs CPU? */  static bool is_nocb_cpu(int cpu)  { @@ -2366,10 +2372,11 @@ static int rcu_nocb_kthread(void *arg)  	for (;;) {  		/* If not polling, wait for next batch of callbacks. */  		if (!rcu_nocb_poll) -			wait_event(rdp->nocb_wq, rdp->nocb_head); +			wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);  		list = ACCESS_ONCE(rdp->nocb_head);  		if (!list) {  			schedule_timeout_interruptible(1); +			flush_signals(current);  			continue;  		} diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 2cd3c1b4e58..7ae4c4c5420 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -222,8 +222,8 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)  			cfs_rq->runnable_load_avg);  	SEQ_printf(m, "  .%-30s: %lld\n", "blocked_load_avg",  			cfs_rq->blocked_load_avg); -	SEQ_printf(m, "  .%-30s: %ld\n", "tg_load_avg", -			atomic64_read(&cfs_rq->tg->load_avg)); +	SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_avg", +			(unsigned long long)atomic64_read(&cfs_rq->tg->load_avg));  	SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_contrib",  			cfs_rq->tg_load_contrib);  	SEQ_printf(m, "  .%-30s: %d\n", "tg_runnable_contrib", diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 5eea8707234..81fa5364340 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2663,7 +2663,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)  	hrtimer_cancel(&cfs_b->slack_timer);  } -static void unthrottle_offline_cfs_rqs(struct rq *rq) +static void __maybe_unused unthrottle_offline_cfs_rqs(struct rq *rq)  {  	struct cfs_rq *cfs_rq; diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 418feb01344..4f02b284735 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -566,7 +566,7 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)  static int do_balance_runtime(struct rt_rq *rt_rq)  {  	struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); -	struct root_domain *rd = cpu_rq(smp_processor_id())->rd; +	struct root_domain *rd = rq_of_rt_rq(rt_rq)->rd;  	int i, weight, more = 0;  	u64 rt_period; diff --git a/lib/digsig.c b/lib/digsig.c index 8c0e62975c8..dc2be7ed176 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -162,6 +162,8 @@ static int digsig_verify_rsa(struct key *key,  	memset(out1, 0, head);  	memcpy(out1 + head, p, l); +	kfree(p); +  	err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);  	if (err)  		goto err; diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 6001ee6347a..b5783d81eda 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1257,6 +1257,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,  	if (flags & FOLL_WRITE && !pmd_write(*pmd))  		goto out; +	/* Avoid dumping huge zero page */ +	if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd)) +		return ERR_PTR(-EFAULT); +  	page = pmd_page(*pmd);  	VM_BUG_ON(!PageHead(page));  	if (flags & FOLL_TOUCH) { diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 4f3ea0b1e57..546db81820e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3033,6 +3033,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,  		if (!huge_pte_none(huge_ptep_get(ptep))) {  			pte = huge_ptep_get_and_clear(mm, address, ptep);  			pte = pte_mkhuge(pte_modify(pte, newprot)); +			pte = arch_make_huge_pte(pte, vma, NULL, 0);  			set_huge_pte_at(mm, address, ptep, pte);  			pages++;  		} diff --git a/mm/migrate.c b/mm/migrate.c index c38778610aa..2fd8b4af474 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -160,8 +160,10 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,  	if (is_write_migration_entry(entry))  		pte = pte_mkwrite(pte);  #ifdef CONFIG_HUGETLB_PAGE -	if (PageHuge(new)) +	if (PageHuge(new)) {  		pte = pte_mkhuge(pte); +		pte = arch_make_huge_pte(pte, vma, new, 0); +	}  #endif  	flush_cache_page(vma, addr, pte_pfn(pte));  	set_pte_at(mm, addr, ptep, pte); diff --git a/mm/mmap.c b/mm/mmap.c index 35730ee9d51..d1e4124f3d0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2943,7 +2943,7 @@ static void vm_lock_mapping(struct mm_struct *mm, struct address_space *mapping)   * vma in this mm is backed by the same anon_vma or address_space.   *   * We can take all the locks in random order because the VM code - * taking i_mmap_mutex or anon_vma->mutex outside the mmap_sem never + * taking i_mmap_mutex or anon_vma->rwsem outside the mmap_sem never   * takes more than one of them in a row. Secondly we're protected   * against a concurrent mm_take_all_locks() by the mm_all_locks_mutex.   * diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 25bfce0666e..4925a02ae7e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -249,12 +249,12 @@ static void hci_conn_disconnect(struct hci_conn *conn)  	__u8 reason = hci_proto_disconn_ind(conn);  	switch (conn->type) { -	case ACL_LINK: -		hci_acl_disconn(conn, reason); -		break;  	case AMP_LINK:  		hci_amp_disconn(conn, reason);  		break; +	default: +		hci_acl_disconn(conn, reason); +		break;  	}  } diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 68a9587c969..5abefb12891 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -859,6 +859,19 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)  	skb_pull(skb, sizeof(code)); +	/* +	 * The SMP context must be initialized for all other PDUs except +	 * pairing and security requests. If we get any other PDU when +	 * not initialized simply disconnect (done if this function +	 * returns an error). +	 */ +	if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ && +	    !conn->smp_chan) { +		BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); +		kfree_skb(skb); +		return -ENOTSUPP; +	} +  	switch (code) {  	case SMP_CMD_PAIRING_REQ:  		reason = smp_cmd_pairing_req(conn, skb); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b29dacf900f..e6e1cbe863f 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1781,10 +1781,13 @@ static ssize_t pktgen_thread_write(struct file *file,  			return -EFAULT;  		i += len;  		mutex_lock(&pktgen_thread_lock); -		pktgen_add_device(t, f); +		ret = pktgen_add_device(t, f);  		mutex_unlock(&pktgen_thread_lock); -		ret = count; -		sprintf(pg_result, "OK: add_device=%s", f); +		if (!ret) { +			ret = count; +			sprintf(pg_result, "OK: add_device=%s", f); +		} else +			sprintf(pg_result, "ERROR: can not add device %s", f);  		goto out;  	} diff --git a/net/core/skbuff.c b/net/core/skbuff.c index a9a2ae3e221..32443ebc3e8 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -683,7 +683,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)  	new->network_header	= old->network_header;  	new->mac_header		= old->mac_header;  	new->inner_transport_header = old->inner_transport_header; -	new->inner_network_header = old->inner_transport_header; +	new->inner_network_header = old->inner_network_header;  	skb_dst_copy(new, old);  	new->rxhash		= old->rxhash;  	new->ooo_okay		= old->ooo_okay; diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 291f2ed7cc3..cdf2e707bb1 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -310,6 +310,12 @@ void tcp_slow_start(struct tcp_sock *tp)  {  	int cnt; /* increase in packets */  	unsigned int delta = 0; +	u32 snd_cwnd = tp->snd_cwnd; + +	if (unlikely(!snd_cwnd)) { +		pr_err_once("snd_cwnd is nul, please report this bug.\n"); +		snd_cwnd = 1U; +	}  	/* RFC3465: ABC Slow start  	 * Increase only after a full MSS of bytes is acked @@ -324,7 +330,7 @@ void tcp_slow_start(struct tcp_sock *tp)  	if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh)  		cnt = sysctl_tcp_max_ssthresh >> 1;	/* limited slow start */  	else -		cnt = tp->snd_cwnd;			/* exponential increase */ +		cnt = snd_cwnd;				/* exponential increase */  	/* RFC3465: ABC  	 * We MAY increase by 2 if discovered delayed ack @@ -334,11 +340,11 @@ void tcp_slow_start(struct tcp_sock *tp)  	tp->bytes_acked = 0;  	tp->snd_cwnd_cnt += cnt; -	while (tp->snd_cwnd_cnt >= tp->snd_cwnd) { -		tp->snd_cwnd_cnt -= tp->snd_cwnd; +	while (tp->snd_cwnd_cnt >= snd_cwnd) { +		tp->snd_cwnd_cnt -= snd_cwnd;  		delta++;  	} -	tp->snd_cwnd = min(tp->snd_cwnd + delta, tp->snd_cwnd_clamp); +	tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp);  }  EXPORT_SYMBOL_GPL(tcp_slow_start); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 18f97ca76b0..ad70a962c20 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3504,6 +3504,11 @@ static bool tcp_process_frto(struct sock *sk, int flag)  		}  	} else {  		if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) { +			if (!tcp_packets_in_flight(tp)) { +				tcp_enter_frto_loss(sk, 2, flag); +				return true; +			} +  			/* Prevent sending of new data. */  			tp->snd_cwnd = min(tp->snd_cwnd,  					   tcp_packets_in_flight(tp)); @@ -5649,8 +5654,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,  	 * the remote receives only the retransmitted (regular) SYNs: either  	 * the original SYN-data or the corresponding SYN-ACK is lost.  	 */ -	syn_drop = (cookie->len <= 0 && data && -		    inet_csk(sk)->icsk_retransmits); +	syn_drop = (cookie->len <= 0 && data && tp->total_retrans);  	tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 70b09ef2463..eadb693eef5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -496,6 +496,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)  		 * errors returned from accept().  		 */  		inet_csk_reqsk_queue_drop(sk, req, prev); +		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);  		goto out;  	case TCP_SYN_SENT: @@ -1500,8 +1501,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)  	 * clogging syn queue with openreqs with exponentially increasing  	 * timeout.  	 */ -	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) +	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { +		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);  		goto drop; +	}  	req = inet_reqsk_alloc(&tcp_request_sock_ops);  	if (!req) @@ -1666,6 +1669,7 @@ drop_and_release:  drop_and_free:  	reqsk_free(req);  drop: +	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);  	return 0;  }  EXPORT_SYMBOL(tcp_v4_conn_request); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 420e5632638..1b5d8cb9b12 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1660,6 +1660,7 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)  	if (dev->addr_len != IEEE802154_ADDR_LEN)  		return -1;  	memcpy(eui, dev->dev_addr, 8); +	eui[0] ^= 2;  	return 0;  } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 8edf2601065..7a778b9a7b8 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -380,7 +380,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)  		if (skb->protocol == htons(ETH_P_IPV6)) {  			sin->sin6_addr = ipv6_hdr(skb)->saddr;  			if (np->rxopt.all) -				datagram_recv_ctl(sk, msg, skb); +				ip6_datagram_recv_ctl(sk, msg, skb);  			if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)  				sin->sin6_scope_id = IP6CB(skb)->iif;  		} else { @@ -468,7 +468,8 @@ out:  } -int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) +int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, +			  struct sk_buff *skb)  {  	struct ipv6_pinfo *np = inet6_sk(sk);  	struct inet6_skb_parm *opt = IP6CB(skb); @@ -597,11 +598,12 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)  	}  	return 0;  } +EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl); -int datagram_send_ctl(struct net *net, struct sock *sk, -		      struct msghdr *msg, struct flowi6 *fl6, -		      struct ipv6_txoptions *opt, -		      int *hlimit, int *tclass, int *dontfrag) +int ip6_datagram_send_ctl(struct net *net, struct sock *sk, +			  struct msghdr *msg, struct flowi6 *fl6, +			  struct ipv6_txoptions *opt, +			  int *hlimit, int *tclass, int *dontfrag)  {  	struct in6_pktinfo *src_info;  	struct cmsghdr *cmsg; @@ -871,4 +873,4 @@ int datagram_send_ctl(struct net *net, struct sock *sk,  exit_f:  	return err;  } -EXPORT_SYMBOL_GPL(datagram_send_ctl); +EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 29124b7a04c..d6de4b44725 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -365,8 +365,8 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,  		msg.msg_control = (void*)(fl->opt+1);  		memset(&flowi6, 0, sizeof(flowi6)); -		err = datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, &junk, -					&junk, &junk); +		err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, +					    &junk, &junk, &junk);  		if (err)  			goto done;  		err = -EINVAL; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index c727e471275..131dd097736 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -960,7 +960,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,  	int ret;  	if (!ip6_tnl_xmit_ctl(t)) -		return -1; +		goto tx_err;  	switch (skb->protocol) {  	case htons(ETH_P_IP): diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ee94d31c9d4..d1e2e8ef29c 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -476,8 +476,8 @@ sticky_done:  		msg.msg_controllen = optlen;  		msg.msg_control = (void*)(opt+1); -		retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk, -					 &junk); +		retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, +					     &junk, &junk);  		if (retv)  			goto done;  update: @@ -1002,7 +1002,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,  		release_sock(sk);  		if (skb) { -			int err = datagram_recv_ctl(sk, &msg, skb); +			int err = ip6_datagram_recv_ctl(sk, &msg, skb);  			kfree_skb(skb);  			if (err)  				return err; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6cd29b1e8b9..70fa8144999 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -507,7 +507,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,  	sock_recv_ts_and_drops(msg, sk, skb);  	if (np->rxopt.all) -		datagram_recv_ctl(sk, msg, skb); +		ip6_datagram_recv_ctl(sk, msg, skb);  	err = copied;  	if (flags & MSG_TRUNC) @@ -822,8 +822,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  		memset(opt, 0, sizeof(struct ipv6_txoptions));  		opt->tot_len = sizeof(struct ipv6_txoptions); -		err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, -					&hlimit, &tclass, &dontfrag); +		err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, +					    &hlimit, &tclass, &dontfrag);  		if (err < 0) {  			fl6_sock_release(flowlabel);  			return err; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e229a3bc345..363d8b7772e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -928,7 +928,7 @@ restart:  	dst_hold(&rt->dst);  	read_unlock_bh(&table->tb6_lock); -	if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP)) +	if (!rt->n && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL)))  		nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);  	else if (!(rt->dst.flags & DST_HOST))  		nrt = rt6_alloc_clone(rt, &fl6->daddr); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 93825dd3a7c..4f43537197e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -423,6 +423,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  		}  		inet_csk_reqsk_queue_drop(sk, req, prev); +		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);  		goto out;  	case TCP_SYN_SENT: @@ -958,8 +959,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)  			goto drop;  	} -	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) +	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { +		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);  		goto drop; +	}  	req = inet6_reqsk_alloc(&tcp6_request_sock_ops);  	if (req == NULL) @@ -1108,6 +1111,7 @@ drop_and_release:  drop_and_free:  	reqsk_free(req);  drop: +	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);  	return 0; /* don't send reset */  } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index dfaa29b8b29..fb083295ff0 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -443,7 +443,7 @@ try_again:  			ip_cmsg_recv(msg, skb);  	} else {  		if (np->rxopt.all) -			datagram_recv_ctl(sk, msg, skb); +			ip6_datagram_recv_ctl(sk, msg, skb);  	}  	err = copied; @@ -1153,8 +1153,8 @@ do_udp_sendmsg:  		memset(opt, 0, sizeof(struct ipv6_txoptions));  		opt->tot_len = sizeof(*opt); -		err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, -					&hlimit, &tclass, &dontfrag); +		err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, +					    &hlimit, &tclass, &dontfrag);  		if (err < 0) {  			fl6_sock_release(flowlabel);  			return err; diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 1a9f3723c13..2ac884d0e89 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -168,6 +168,51 @@ l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)  } +/* Lookup the tunnel socket, possibly involving the fs code if the socket is + * owned by userspace.  A struct sock returned from this function must be + * released using l2tp_tunnel_sock_put once you're done with it. + */ +struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel) +{ +	int err = 0; +	struct socket *sock = NULL; +	struct sock *sk = NULL; + +	if (!tunnel) +		goto out; + +	if (tunnel->fd >= 0) { +		/* Socket is owned by userspace, who might be in the process +		 * of closing it.  Look the socket up using the fd to ensure +		 * consistency. +		 */ +		sock = sockfd_lookup(tunnel->fd, &err); +		if (sock) +			sk = sock->sk; +	} else { +		/* Socket is owned by kernelspace */ +		sk = tunnel->sock; +	} + +out: +	return sk; +} +EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_lookup); + +/* Drop a reference to a tunnel socket obtained via. l2tp_tunnel_sock_put */ +void l2tp_tunnel_sock_put(struct sock *sk) +{ +	struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk); +	if (tunnel) { +		if (tunnel->fd >= 0) { +			/* Socket is owned by userspace */ +			sockfd_put(sk->sk_socket); +		} +		sock_put(sk); +	} +} +EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put); +  /* Lookup a session by id in the global session list   */  static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id) @@ -1123,8 +1168,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len  	struct udphdr *uh;  	struct inet_sock *inet;  	__wsum csum; -	int old_headroom; -	int new_headroom;  	int headroom;  	int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;  	int udp_len; @@ -1136,16 +1179,12 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len  	 */  	headroom = NET_SKB_PAD + sizeof(struct iphdr) +  		uhlen + hdr_len; -	old_headroom = skb_headroom(skb);  	if (skb_cow_head(skb, headroom)) {  		kfree_skb(skb);  		return NET_XMIT_DROP;  	} -	new_headroom = skb_headroom(skb);  	skb_orphan(skb); -	skb->truesize += new_headroom - old_headroom; -  	/* Setup L2TP header */  	session->build_header(session, __skb_push(skb, hdr_len)); @@ -1607,6 +1646,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32  	tunnel->old_sk_destruct = sk->sk_destruct;  	sk->sk_destruct = &l2tp_tunnel_destruct;  	tunnel->sock = sk; +	tunnel->fd = fd;  	lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");  	sk->sk_allocation = GFP_ATOMIC; @@ -1642,24 +1682,32 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);   */  int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)  { -	int err = 0; -	struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL; +	int err = -EBADF; +	struct socket *sock = NULL; +	struct sock *sk = NULL; + +	sk = l2tp_tunnel_sock_lookup(tunnel); +	if (!sk) +		goto out; + +	sock = sk->sk_socket; +	BUG_ON(!sock);  	/* Force the tunnel socket to close. This will eventually  	 * cause the tunnel to be deleted via the normal socket close  	 * mechanisms when userspace closes the tunnel socket.  	 */ -	if (sock != NULL) { -		err = inet_shutdown(sock, 2); +	err = inet_shutdown(sock, 2); -		/* If the tunnel's socket was created by the kernel, -		 * close the socket here since the socket was not -		 * created by userspace. -		 */ -		if (sock->file == NULL) -			err = inet_release(sock); -	} +	/* If the tunnel's socket was created by the kernel, +	 * close the socket here since the socket was not +	 * created by userspace. +	 */ +	if (sock->file == NULL) +		err = inet_release(sock); +	l2tp_tunnel_sock_put(sk); +out:  	return err;  }  EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 56d583e083a..e62204cad4f 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -188,7 +188,8 @@ struct l2tp_tunnel {  	int (*recv_payload_hook)(struct sk_buff *skb);  	void (*old_sk_destruct)(struct sock *);  	struct sock		*sock;		/* Parent socket */ -	int			fd; +	int			fd;		/* Parent fd, if tunnel socket +						 * was created by userspace */  	uint8_t			priv[0];	/* private data */  }; @@ -228,6 +229,8 @@ out:  	return tunnel;  } +extern struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel); +extern void l2tp_tunnel_sock_put(struct sock *sk);  extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id);  extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);  extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname); diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 927547171bc..8ee4a86ae99 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -554,8 +554,8 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,  		memset(opt, 0, sizeof(struct ipv6_txoptions));  		opt->tot_len = sizeof(struct ipv6_txoptions); -		err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, -					&hlimit, &tclass, &dontfrag); +		err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, +					    &hlimit, &tclass, &dontfrag);  		if (err < 0) {  			fl6_sock_release(flowlabel);  			return err; @@ -646,7 +646,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,  			    struct msghdr *msg, size_t len, int noblock,  			    int flags, int *addr_len)  { -	struct inet_sock *inet = inet_sk(sk); +	struct ipv6_pinfo *np = inet6_sk(sk);  	struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)msg->msg_name;  	size_t copied = 0;  	int err = -EOPNOTSUPP; @@ -688,8 +688,8 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,  			lsa->l2tp_scope_id = IP6CB(skb)->iif;  	} -	if (inet->cmsg_flags) -		ip_cmsg_recv(msg, skb); +	if (np->rxopt.all) +		ip6_datagram_recv_ctl(sk, msg, skb);  	if (flags & MSG_TRUNC)  		copied = skb->len; diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 286366ef893..716605c241f 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -388,8 +388,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)  	struct l2tp_session *session;  	struct l2tp_tunnel *tunnel;  	struct pppol2tp_session *ps; -	int old_headroom; -	int new_headroom;  	int uhlen, headroom;  	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) @@ -408,7 +406,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)  	if (tunnel == NULL)  		goto abort_put_sess; -	old_headroom = skb_headroom(skb);  	uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;  	headroom = NET_SKB_PAD +  		   sizeof(struct iphdr) + /* IP header */ @@ -418,9 +415,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)  	if (skb_cow_head(skb, headroom))  		goto abort_put_sess_tun; -	new_headroom = skb_headroom(skb); -	skb->truesize += new_headroom - old_headroom; -  	/* Setup PPP header */  	__skb_push(skb, sizeof(ppph));  	skb->data[0] = ppph[0]; diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index a9327e2e48c..670cbc3518d 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -35,10 +35,11 @@  /* Must be called with rcu_read_lock. */  static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)  { -	if (unlikely(!vport)) { -		kfree_skb(skb); -		return; -	} +	if (unlikely(!vport)) +		goto error; + +	if (unlikely(skb_warn_if_lro(skb))) +		goto error;  	/* Make our own copy of the packet.  Otherwise we will mangle the  	 * packet for anyone who came before us (e.g. tcpdump via AF_PACKET). @@ -50,6 +51,10 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)  	skb_push(skb, ETH_HLEN);  	ovs_vport_receive(vport, skb); +	return; + +error: +	kfree_skb(skb);  }  /* Called with rcu_read_lock and bottom-halves disabled. */ @@ -169,9 +174,6 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)  		goto error;  	} -	if (unlikely(skb_warn_if_lro(skb))) -		goto error; -  	skb->dev = netdev_vport->dev;  	len = skb->len;  	dev_queue_xmit(skb); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e639645e8fe..c111bd0e083 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2361,13 +2361,15 @@ static int packet_release(struct socket *sock)  	packet_flush_mclist(sk); -	memset(&req_u, 0, sizeof(req_u)); - -	if (po->rx_ring.pg_vec) +	if (po->rx_ring.pg_vec) { +		memset(&req_u, 0, sizeof(req_u));  		packet_set_ring(sk, &req_u, 1, 0); +	} -	if (po->tx_ring.pg_vec) +	if (po->tx_ring.pg_vec) { +		memset(&req_u, 0, sizeof(req_u));  		packet_set_ring(sk, &req_u, 1, 1); +	}  	fanout_release(sk); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 298c0ddfb57..3d2acc7a9c8 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -438,18 +438,18 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)  		if (q->rate) {  			struct sk_buff_head *list = &sch->q; -			delay += packet_len_2_sched_time(skb->len, q); -  			if (!skb_queue_empty(list)) {  				/* -				 * Last packet in queue is reference point (now). -				 * First packet in queue is already in flight, -				 * calculate this time bonus and substract +				 * Last packet in queue is reference point (now), +				 * calculate this time bonus and subtract  				 * from delay.  				 */ -				delay -= now - netem_skb_cb(skb_peek(list))->time_to_send; +				delay -= netem_skb_cb(skb_peek_tail(list))->time_to_send - now; +				delay = max_t(psched_tdiff_t, 0, delay);  				now = netem_skb_cb(skb_peek_tail(list))->time_to_send;  			} + +			delay += packet_len_2_sched_time(skb->len, q);  		}  		cb->time_to_send = now + delay; diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 159b9bc5d63..d8420ae614d 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -71,7 +71,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)  		return;  	if (atomic_dec_and_test(&key->refcnt)) { -		kfree(key); +		kzfree(key);  		SCTP_DBG_OBJCNT_DEC(keys);  	}  } diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 17a001bac2c..1a9c5fb7731 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -249,6 +249,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep)  /* Final destructor for endpoint.  */  static void sctp_endpoint_destroy(struct sctp_endpoint *ep)  { +	int i; +  	SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);  	/* Free up the HMAC transform. */ @@ -271,6 +273,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)  	sctp_inq_free(&ep->base.inqueue);  	sctp_bind_addr_free(&ep->base.bind_addr); +	for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i) +		memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE); +  	/* Remove and free the port */  	if (sctp_sk(ep->base.sk)->bind_hash)  		sctp_put_port(ep->base.sk); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9e65758cb03..cedd9bf67b8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3390,7 +3390,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk,  	ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey);  out: -	kfree(authkey); +	kzfree(authkey);  	return ret;  } diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 0a148c9d2a5..0f679df7d07 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -465,7 +465,7 @@ static int svc_udp_get_dest_address4(struct svc_rqst *rqstp,  }  /* - * See net/ipv6/datagram.c : datagram_recv_ctl + * See net/ipv6/datagram.c : ip6_datagram_recv_ctl   */  static int svc_udp_get_dest_address6(struct svc_rqst *rqstp,  				     struct cmsghdr *cmh) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 01592d7d478..45f1618c8e2 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1358,7 +1358,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,  						  &iwe, IW_EV_UINT_LEN);  	} -	buf = kmalloc(30, GFP_ATOMIC); +	buf = kmalloc(31, GFP_ATOMIC);  	if (buf) {  		memset(&iwe, 0, sizeof(iwe));  		iwe.cmd = IWEVCUSTOM; diff --git a/samples/seccomp/Makefile b/samples/seccomp/Makefile index bbbd276659b..7203e66dcd6 100644 --- a/samples/seccomp/Makefile +++ b/samples/seccomp/Makefile @@ -19,6 +19,7 @@ bpf-direct-objs := bpf-direct.o  # Try to match the kernel target.  ifndef CONFIG_64BIT +ifndef CROSS_COMPILE  # s390 has -m31 flag to build 31 bit binaries  ifndef CONFIG_S390 @@ -35,6 +36,7 @@ HOSTLOADLIBES_bpf-direct += $(MFLAG)  HOSTLOADLIBES_bpf-fancy += $(MFLAG)  HOSTLOADLIBES_dropper += $(MFLAG)  endif +endif  # Tell kbuild to always build the programs  always := $(hostprogs-y) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 4d2c7dfdaab..2bb08a962ce 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -230,12 +230,12 @@ our $Inline	= qr{inline|__always_inline|noinline};  our $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};  our $Lval	= qr{$Ident(?:$Member)*}; -our $Float_hex	= qr{(?i:0x[0-9a-f]+p-?[0-9]+[fl]?)}; -our $Float_dec	= qr{(?i:((?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?))}; -our $Float_int	= qr{(?i:[0-9]+e-?[0-9]+[fl]?)}; +our $Float_hex	= qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; +our $Float_dec	= qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; +our $Float_int	= qr{(?i)[0-9]+e-?[0-9]+[fl]?};  our $Float	= qr{$Float_hex|$Float_dec|$Float_int}; -our $Constant	= qr{(?:$Float|(?i:(?:0x[0-9a-f]+|[0-9]+)[ul]*))}; -our $Assignment	= qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; +our $Constant	= qr{$Float|(?i)(?:0x[0-9a-f]+|[0-9]+)[ul]*}; +our $Assignment	= qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};  our $Compare    = qr{<=|>=|==|!=|<|>};  our $Operators	= qr{  			<=|>=|==|!=| diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index a210c8d7b4b..3b98159d964 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -108,13 +108,18 @@ if SND_IMX_SOC  config SND_SOC_IMX_SSI  	tristate -config SND_SOC_IMX_PCM_FIQ +config SND_SOC_IMX_PCM  	tristate + +config SND_SOC_IMX_PCM_FIQ +	bool  	select FIQ +	select SND_SOC_IMX_PCM  config SND_SOC_IMX_PCM_DMA -	tristate +	bool  	select SND_SOC_DMAENGINE_PCM +	select SND_SOC_IMX_PCM  config SND_SOC_IMX_AUDMUX  	tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index ec1457915d7..afd34794db5 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -41,10 +41,7 @@ endif  obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o  obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o -obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += snd-soc-imx-pcm-fiq.o -snd-soc-imx-pcm-fiq-y := imx-pcm-fiq.o imx-pcm.o -obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += snd-soc-imx-pcm-dma.o -snd-soc-imx-pcm-dma-y := imx-pcm-dma.o imx-pcm.o +obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o  # i.MX Machine Support  snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index bf363d8d044..500f8ce55d7 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -154,26 +154,7 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {  	.pcm_free	= imx_pcm_free,  }; -static int imx_soc_platform_probe(struct platform_device *pdev) +int imx_pcm_dma_init(struct platform_device *pdev)  {  	return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);  } - -static int imx_soc_platform_remove(struct platform_device *pdev) -{ -	snd_soc_unregister_platform(&pdev->dev); -	return 0; -} - -static struct platform_driver imx_pcm_driver = { -	.driver = { -			.name = "imx-pcm-audio", -			.owner = THIS_MODULE, -	}, -	.probe = imx_soc_platform_probe, -	.remove = imx_soc_platform_remove, -}; - -module_platform_driver(imx_pcm_driver); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-pcm-audio"); diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 5ec362ae4d0..920f945cb2f 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -281,7 +281,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {  	.pcm_free	= imx_pcm_fiq_free,  }; -static int imx_soc_platform_probe(struct platform_device *pdev) +int imx_pcm_fiq_init(struct platform_device *pdev)  {  	struct imx_ssi *ssi = platform_get_drvdata(pdev);  	int ret; @@ -314,23 +314,3 @@ failed_register:  	return ret;  } - -static int imx_soc_platform_remove(struct platform_device *pdev) -{ -	snd_soc_unregister_platform(&pdev->dev); -	return 0; -} - -static struct platform_driver imx_pcm_driver = { -	.driver = { -			.name = "imx-fiq-pcm-audio", -			.owner = THIS_MODULE, -	}, - -	.probe = imx_soc_platform_probe, -	.remove = imx_soc_platform_remove, -}; - -module_platform_driver(imx_pcm_driver); - -MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c index 0c9f188ddc6..0d0625bfcb6 100644 --- a/sound/soc/fsl/imx-pcm.c +++ b/sound/soc/fsl/imx-pcm.c @@ -31,6 +31,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,  			runtime->dma_bytes);  	return ret;  } +EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);  static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)  { @@ -79,6 +80,7 @@ int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)  out:  	return ret;  } +EXPORT_SYMBOL_GPL(imx_pcm_new);  void imx_pcm_free(struct snd_pcm *pcm)  { @@ -100,6 +102,39 @@ void imx_pcm_free(struct snd_pcm *pcm)  		buf->area = NULL;  	}  } +EXPORT_SYMBOL_GPL(imx_pcm_free); + +static int imx_pcm_probe(struct platform_device *pdev) +{ +	if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0) +		return imx_pcm_fiq_init(pdev); + +	return imx_pcm_dma_init(pdev); +} + +static int imx_pcm_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_device_id imx_pcm_devtype[] = { +	{ .name = "imx-pcm-audio", }, +	{ .name = "imx-fiq-pcm-audio", }, +	{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, imx_pcm_devtype); + +static struct platform_driver imx_pcm_driver = { +	.driver = { +			.name = "imx-pcm", +			.owner = THIS_MODULE, +	}, +	.id_table = imx_pcm_devtype, +	.probe = imx_pcm_probe, +	.remove = imx_pcm_remove, +}; +module_platform_driver(imx_pcm_driver);  MODULE_DESCRIPTION("Freescale i.MX PCM driver");  MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index 83c0ed7d55c..5ae13a13a35 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h @@ -30,4 +30,22 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,  int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);  void imx_pcm_free(struct snd_pcm *pcm); +#ifdef CONFIG_SND_SOC_IMX_PCM_DMA +int imx_pcm_dma_init(struct platform_device *pdev); +#else +static inline int imx_pcm_dma_init(struct platform_device *pdev) +{ +	return -ENODEV; +} +#endif + +#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ +int imx_pcm_fiq_init(struct platform_device *pdev); +#else +static inline int imx_pcm_fiq_init(struct platform_device *pdev) +{ +	return -ENODEV; +} +#endif +  #endif /* _IMX_PCM_H */ diff --git a/tools/vm/.gitignore b/tools/vm/.gitignore new file mode 100644 index 00000000000..44f095fa260 --- /dev/null +++ b/tools/vm/.gitignore @@ -0,0 +1,2 @@ +slabinfo +page-types  |