lantiq: copy Linux 5.10 files in preparation for Linux 5.15 support
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
This commit is contained in:
		 Martin Blumenstingl
					Martin Blumenstingl
				
			
				
					committed by
					
						 Hauke Mehrtens
						Hauke Mehrtens
					
				
			
			
				
	
			
			
			 Hauke Mehrtens
						Hauke Mehrtens
					
				
			
						parent
						
							3505933073
						
					
				
				
					commit
					c783073894
				
			
							
								
								
									
										25
									
								
								target/linux/lantiq/ase/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								target/linux/lantiq/ase/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | CONFIG_ADM6996_PHY=y | ||||||
|  | CONFIG_CPU_MIPS32_R1=y | ||||||
|  | # CONFIG_CPU_MIPS32_R2 is not set | ||||||
|  | CONFIG_CPU_MIPSR1=y | ||||||
|  | CONFIG_CRC16=y | ||||||
|  | CONFIG_CRYPTO_ACOMP2=y | ||||||
|  | CONFIG_CRYPTO_DEFLATE=y | ||||||
|  | CONFIG_FIRMWARE_MEMMAP=y | ||||||
|  | CONFIG_GENERIC_ALLOCATOR=y | ||||||
|  | CONFIG_GPIO_GENERIC=y | ||||||
|  | CONFIG_GPIO_GENERIC_PLATFORM=y | ||||||
|  | CONFIG_HW_RANDOM=y | ||||||
|  | # CONFIG_ISDN is not set | ||||||
|  | CONFIG_LANTIQ_ETOP=y | ||||||
|  | CONFIG_NLS=y | ||||||
|  | CONFIG_SGL_ALLOC=y | ||||||
|  | CONFIG_SOC_AMAZON_SE=y | ||||||
|  | CONFIG_SOC_TYPE_XWAY=y | ||||||
|  | CONFIG_SWCONFIG=y | ||||||
|  | CONFIG_TARGET_ISA_REV=1 | ||||||
|  | CONFIG_USB=y | ||||||
|  | CONFIG_USB_COMMON=y | ||||||
|  | CONFIG_USB_SUPPORT=y | ||||||
|  | CONFIG_ZLIB_DEFLATE=y | ||||||
|  | CONFIG_ZLIB_INFLATE=y | ||||||
							
								
								
									
										225
									
								
								target/linux/lantiq/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								target/linux/lantiq/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,225 @@ | |||||||
|  | CONFIG_ARCH_32BIT_OFF_T=y | ||||||
|  | CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||||
|  | CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y | ||||||
|  | CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y | ||||||
|  | CONFIG_ARCH_HAS_DMA_WRITE_COMBINE=y | ||||||
|  | CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||||
|  | CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||||
|  | CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y | ||||||
|  | CONFIG_ARCH_HAS_UNCACHED_SEGMENT=y | ||||||
|  | CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||||
|  | CONFIG_ARCH_MMAP_RND_BITS_MAX=15 | ||||||
|  | CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 | ||||||
|  | CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||||
|  | CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||||
|  | CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||||
|  | CONFIG_ARCH_USE_MEMREMAP_PROT=y | ||||||
|  | CONFIG_ARCH_USE_QUEUED_RWLOCKS=y | ||||||
|  | CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y | ||||||
|  | CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y | ||||||
|  | CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||||
|  | CONFIG_CEVT_R4K=y | ||||||
|  | CONFIG_CLKDEV_LOOKUP=y | ||||||
|  | CONFIG_CLONE_BACKWARDS=y | ||||||
|  | CONFIG_COMPAT_32BIT_TIME=y | ||||||
|  | CONFIG_CPU_BIG_ENDIAN=y | ||||||
|  | CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||||
|  | CONFIG_CPU_HAS_LOAD_STORE_LR=y | ||||||
|  | CONFIG_CPU_HAS_PREFETCH=y | ||||||
|  | CONFIG_CPU_HAS_RIXI=y | ||||||
|  | CONFIG_CPU_HAS_SYNC=y | ||||||
|  | CONFIG_CPU_MIPS32=y | ||||||
|  | # CONFIG_CPU_MIPS32_R1 is not set | ||||||
|  | CONFIG_CPU_MIPS32_R2=y | ||||||
|  | CONFIG_CPU_MIPSR2=y | ||||||
|  | CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||||
|  | CONFIG_CPU_R4K_CACHE_TLB=y | ||||||
|  | CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||||
|  | CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||||
|  | CONFIG_CPU_SUPPORTS_MSA=y | ||||||
|  | CONFIG_CRYPTO_BLAKE2S=y | ||||||
|  | CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y | ||||||
|  | CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 | ||||||
|  | CONFIG_CRYPTO_RNG2=y | ||||||
|  | CONFIG_CSRC_R4K=y | ||||||
|  | CONFIG_DMA_NONCOHERENT=y | ||||||
|  | CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y | ||||||
|  | CONFIG_DTC=y | ||||||
|  | # CONFIG_DT_EASY50712 is not set | ||||||
|  | CONFIG_EARLY_PRINTK=y | ||||||
|  | CONFIG_EFI_EARLYCON=y | ||||||
|  | CONFIG_FIXED_PHY=y | ||||||
|  | CONFIG_FONT_8x16=y | ||||||
|  | CONFIG_FONT_AUTOSELECT=y | ||||||
|  | CONFIG_FONT_SUPPORT=y | ||||||
|  | CONFIG_FW_LOADER_PAGED_BUF=y | ||||||
|  | CONFIG_GENERIC_ATOMIC64=y | ||||||
|  | CONFIG_GENERIC_CLOCKEVENTS=y | ||||||
|  | CONFIG_GENERIC_CMOS_UPDATE=y | ||||||
|  | CONFIG_GENERIC_CPU_AUTOPROBE=y | ||||||
|  | CONFIG_GENERIC_GETTIMEOFDAY=y | ||||||
|  | CONFIG_GENERIC_IOMAP=y | ||||||
|  | CONFIG_GENERIC_IRQ_CHIP=y | ||||||
|  | CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y | ||||||
|  | CONFIG_GENERIC_IRQ_SHOW=y | ||||||
|  | CONFIG_GENERIC_LIB_ASHLDI3=y | ||||||
|  | CONFIG_GENERIC_LIB_ASHRDI3=y | ||||||
|  | CONFIG_GENERIC_LIB_CMPDI2=y | ||||||
|  | CONFIG_GENERIC_LIB_LSHRDI3=y | ||||||
|  | CONFIG_GENERIC_LIB_UCMPDI2=y | ||||||
|  | CONFIG_GENERIC_PCI_IOMAP=y | ||||||
|  | CONFIG_GENERIC_PHY=y | ||||||
|  | CONFIG_GENERIC_SCHED_CLOCK=y | ||||||
|  | CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||||
|  | CONFIG_GENERIC_TIME_VSYSCALL=y | ||||||
|  | CONFIG_GPIO_MM_LANTIQ=y | ||||||
|  | CONFIG_GPIO_STP_XWAY=y | ||||||
|  | CONFIG_HANDLE_DOMAIN_IRQ=y | ||||||
|  | CONFIG_HARDWARE_WATCHPOINTS=y | ||||||
|  | CONFIG_HAS_DMA=y | ||||||
|  | CONFIG_HAS_IOMEM=y | ||||||
|  | CONFIG_HAS_IOPORT_MAP=y | ||||||
|  | CONFIG_HAVE_ARCH_COMPILER_H=y | ||||||
|  | CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||||
|  | CONFIG_HAVE_ARCH_KGDB=y | ||||||
|  | CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||||
|  | CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||||
|  | CONFIG_HAVE_ASM_MODVERSIONS=y | ||||||
|  | CONFIG_HAVE_CLK=y | ||||||
|  | CONFIG_HAVE_CONTEXT_TRACKING=y | ||||||
|  | CONFIG_HAVE_COPY_THREAD_TLS=y | ||||||
|  | CONFIG_HAVE_C_RECORDMCOUNT=y | ||||||
|  | CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||||
|  | CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||||
|  | CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||||
|  | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||||
|  | CONFIG_HAVE_FAST_GUP=y | ||||||
|  | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||||
|  | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||||
|  | CONFIG_HAVE_FUNCTION_TRACER=y | ||||||
|  | CONFIG_HAVE_GENERIC_VDSO=y | ||||||
|  | CONFIG_HAVE_IDE=y | ||||||
|  | CONFIG_HAVE_IOREMAP_PROT=y | ||||||
|  | CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||||
|  | CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||||
|  | CONFIG_HAVE_KVM=y | ||||||
|  | CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y | ||||||
|  | CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||||
|  | CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||||
|  | CONFIG_HAVE_NET_DSA=y | ||||||
|  | CONFIG_HAVE_OPROFILE=y | ||||||
|  | CONFIG_HAVE_PCI=y | ||||||
|  | CONFIG_HAVE_PERF_EVENTS=y | ||||||
|  | CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||||
|  | CONFIG_HAVE_RSEQ=y | ||||||
|  | CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||||
|  | CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||||
|  | CONFIG_HZ_PERIODIC=y | ||||||
|  | CONFIG_INITRAMFS_SOURCE="" | ||||||
|  | CONFIG_IRQCHIP=y | ||||||
|  | CONFIG_IRQ_DOMAIN=y | ||||||
|  | CONFIG_IRQ_DOMAIN_HIERARCHY=y | ||||||
|  | CONFIG_IRQ_FORCED_THREADING=y | ||||||
|  | CONFIG_IRQ_MIPS_CPU=y | ||||||
|  | CONFIG_IRQ_WORK=y | ||||||
|  | CONFIG_LANTIQ=y | ||||||
|  | CONFIG_LANTIQ_DT_NONE=y | ||||||
|  | # CONFIG_LANTIQ_ETOP is not set | ||||||
|  | CONFIG_LANTIQ_WDT=y | ||||||
|  | # CONFIG_LANTIQ_XRX200 is not set | ||||||
|  | CONFIG_LEDS_GPIO=y | ||||||
|  | CONFIG_LIBFDT=y | ||||||
|  | CONFIG_LOCK_DEBUGGING_SUPPORT=y | ||||||
|  | CONFIG_MDIO_BUS=y | ||||||
|  | CONFIG_MDIO_DEVICE=y | ||||||
|  | CONFIG_MDIO_DEVRES=y | ||||||
|  | CONFIG_MEMFD_CREATE=y | ||||||
|  | CONFIG_MFD_CORE=y | ||||||
|  | CONFIG_MFD_SYSCON=y | ||||||
|  | CONFIG_MIGRATION=y | ||||||
|  | CONFIG_MIPS=y | ||||||
|  | CONFIG_MIPS_ASID_BITS=8 | ||||||
|  | CONFIG_MIPS_ASID_SHIFT=0 | ||||||
|  | CONFIG_MIPS_CBPF_JIT=y | ||||||
|  | CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||||
|  | # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||||
|  | # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||||
|  | CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||||
|  | # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||||
|  | CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||||
|  | CONFIG_MIPS_LD_CAN_LINK_VDSO=y | ||||||
|  | # CONFIG_MIPS_MT_SMP is not set | ||||||
|  | # CONFIG_MIPS_NO_APPENDED_DTB is not set | ||||||
|  | CONFIG_MIPS_RAW_APPENDED_DTB=y | ||||||
|  | CONFIG_MIPS_SPRAM=y | ||||||
|  | # CONFIG_MIPS_VPE_LOADER is not set | ||||||
|  | CONFIG_MODULES_USE_ELF_REL=y | ||||||
|  | CONFIG_MTD_CFI_ADV_OPTIONS=y | ||||||
|  | CONFIG_MTD_CFI_GEOMETRY=y | ||||||
|  | CONFIG_MTD_CMDLINE_PARTS=y | ||||||
|  | CONFIG_MTD_JEDECPROBE=y | ||||||
|  | CONFIG_MTD_LANTIQ=y | ||||||
|  | CONFIG_MTD_SPI_NOR=y | ||||||
|  | CONFIG_MTD_SPLIT_BRNIMAGE_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_EVA_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_FIRMWARE=y | ||||||
|  | CONFIG_MTD_SPLIT_TPLINK_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||||
|  | CONFIG_NEED_DMA_MAP_STATE=y | ||||||
|  | CONFIG_NEED_PER_CPU_KM=y | ||||||
|  | CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||||
|  | CONFIG_NVMEM=y | ||||||
|  | CONFIG_OF=y | ||||||
|  | CONFIG_OF_ADDRESS=y | ||||||
|  | CONFIG_OF_EARLY_FLATTREE=y | ||||||
|  | CONFIG_OF_FLATTREE=y | ||||||
|  | CONFIG_OF_GPIO=y | ||||||
|  | CONFIG_OF_IRQ=y | ||||||
|  | CONFIG_OF_KOBJ=y | ||||||
|  | CONFIG_OF_MDIO=y | ||||||
|  | CONFIG_OF_NET=y | ||||||
|  | # CONFIG_PCIE_LANTIQ is not set | ||||||
|  | CONFIG_PCI_DRIVERS_LEGACY=y | ||||||
|  | CONFIG_PERF_USE_VMALLOC=y | ||||||
|  | CONFIG_PGTABLE_LEVELS=2 | ||||||
|  | CONFIG_PHYLIB=y | ||||||
|  | CONFIG_PHY_LANTIQ_RCU_USB2=y | ||||||
|  | # CONFIG_PHY_LANTIQ_VRX200_PCIE is not set | ||||||
|  | CONFIG_PINCTRL=y | ||||||
|  | CONFIG_PINCTRL_LANTIQ=y | ||||||
|  | # CONFIG_PINCTRL_SINGLE is not set | ||||||
|  | CONFIG_PINCTRL_XWAY=y | ||||||
|  | CONFIG_POWER_RESET=y | ||||||
|  | CONFIG_POWER_RESET_SYSCON=y | ||||||
|  | CONFIG_REGMAP=y | ||||||
|  | CONFIG_REGMAP_MMIO=y | ||||||
|  | CONFIG_RESET_CONTROLLER=y | ||||||
|  | CONFIG_RESET_LANTIQ=y | ||||||
|  | # CONFIG_SERIAL_8250 is not set | ||||||
|  | CONFIG_SERIAL_LANTIQ=y | ||||||
|  | CONFIG_SERIAL_LANTIQ_CONSOLE=y | ||||||
|  | # CONFIG_SOC_AMAZON_SE is not set | ||||||
|  | # CONFIG_SOC_FALCON is not set | ||||||
|  | # CONFIG_SOC_XWAY is not set | ||||||
|  | CONFIG_SPI=y | ||||||
|  | CONFIG_SPI_LANTIQ_SSC=y | ||||||
|  | CONFIG_SPI_MASTER=y | ||||||
|  | CONFIG_SPI_MEM=y | ||||||
|  | CONFIG_SRCU=y | ||||||
|  | CONFIG_SWAP_IO_SPACE=y | ||||||
|  | CONFIG_SWPHY=y | ||||||
|  | CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||||
|  | CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||||
|  | CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||||
|  | CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||||
|  | CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||||
|  | CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||||
|  | CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y | ||||||
|  | CONFIG_SYS_SUPPORTS_MIPS16=y | ||||||
|  | CONFIG_SYS_SUPPORTS_MULTITHREADING=y | ||||||
|  | CONFIG_SYS_SUPPORTS_VPE_LOADER=y | ||||||
|  | CONFIG_TARGET_ISA_REV=2 | ||||||
|  | CONFIG_TICK_CPU_ACCOUNTING=y | ||||||
|  | CONFIG_TINY_SRCU=y | ||||||
|  | CONFIG_USE_OF=y | ||||||
|  | CONFIG_WATCHDOG_CORE=y | ||||||
							
								
								
									
										9
									
								
								target/linux/lantiq/falcon/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								target/linux/lantiq/falcon/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | CONFIG_CPU_HAS_DIEI=y | ||||||
|  | CONFIG_MTD_NAND_CORE=y | ||||||
|  | CONFIG_MTD_NAND_ECC=y | ||||||
|  | CONFIG_MTD_NAND_ECC_SW_HAMMING=y | ||||||
|  | CONFIG_MTD_RAW_NAND=y | ||||||
|  | CONFIG_MTD_SPLIT_FIRMWARE_NAME="linux" | ||||||
|  | CONFIG_PINCTRL_FALCON=y | ||||||
|  | CONFIG_SOC_FALCON=y | ||||||
|  | CONFIG_SPI_FALCON=y | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,482 @@ | |||||||
|  | From 9afadf01b1be371ee88491819aa67364684461f9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Fri, 3 Aug 2012 10:27:25 +0200 | ||||||
|  | Subject: [PATCH 04/36] MIPS: lantiq: add atm hack | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  arch/mips/include/asm/mach-lantiq/lantiq_atm.h |  196 +++++++++++++++++++++++ | ||||||
|  |  arch/mips/include/asm/mach-lantiq/lantiq_ptm.h |  203 ++++++++++++++++++++++++ | ||||||
|  |  arch/mips/lantiq/irq.c                         |    2 + | ||||||
|  |  arch/mips/mm/cache.c                           |    4 + | ||||||
|  |  include/uapi/linux/atm.h                       |    6 + | ||||||
|  |  net/atm/common.c                               |    6 + | ||||||
|  |  net/atm/proc.c                                 |    2 +- | ||||||
|  |  7 files changed, 416 insertions(+), 1 deletion(-) | ||||||
|  |  create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_atm.h | ||||||
|  |  create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_ptm.h | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/lantiq_atm.h | ||||||
|  | @@ -0,0 +1,196 @@ | ||||||
|  | +/****************************************************************************** | ||||||
|  | +** | ||||||
|  | +** FILE NAME    : ifx_atm.h | ||||||
|  | +** PROJECT      : UEIP | ||||||
|  | +** MODULES      : ATM | ||||||
|  | +** | ||||||
|  | +** DATE         : 17 Jun 2009 | ||||||
|  | +** AUTHOR       : Xu Liang | ||||||
|  | +** DESCRIPTION  : Global ATM driver header file | ||||||
|  | +** COPYRIGHT    :       Copyright (c) 2006 | ||||||
|  | +**                      Infineon Technologies AG | ||||||
|  | +**                      Am Campeon 1-12, 85579 Neubiberg, Germany | ||||||
|  | +** | ||||||
|  | +**    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 Free Software Foundation; either version 2 of the License, or | ||||||
|  | +**    (at your option) any later version. | ||||||
|  | +** | ||||||
|  | +** HISTORY | ||||||
|  | +** $Date        $Author         $Comment | ||||||
|  | +** 07 JUL 2009  Xu Liang        Init Version | ||||||
|  | +*******************************************************************************/ | ||||||
|  | + | ||||||
|  | +#ifndef IFX_ATM_H | ||||||
|  | +#define IFX_ATM_H | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_ATM UEIP Project - ATM driver module | ||||||
|  | +  \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_ATM_IOCTL IOCTL Commands | ||||||
|  | +  \ingroup IFX_ATM | ||||||
|  | +  \brief IOCTL Commands used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_ATM_STRUCT Structures | ||||||
|  | +  \ingroup IFX_ATM | ||||||
|  | +  \brief Structures used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \file ifx_atm.h | ||||||
|  | +  \ingroup IFX_ATM | ||||||
|  | +  \brief ATM driver header file | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *              Definition | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_ATM_STRUCT | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ATM MIB | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_cell_ifEntry_t | ||||||
|  | +  \brief Structure used for Cell Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  User application use this structure to call IOCTL command "PPE_ATM_MIB_CELL". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	__u32	ifHCInOctets_h;     /*!< byte counter of ingress cells (upper 32 bits, total 64 bits)   */ | ||||||
|  | +	__u32	ifHCInOctets_l;     /*!< byte counter of ingress cells (lower 32 bits, total 64 bits)   */ | ||||||
|  | +	__u32	ifHCOutOctets_h;    /*!< byte counter of egress cells (upper 32 bits, total 64 bits)    */ | ||||||
|  | +	__u32	ifHCOutOctets_l;    /*!< byte counter of egress cells (lower 32 bits, total 64 bits)    */ | ||||||
|  | +	__u32	ifInErrors;         /*!< counter of error ingress cells     */ | ||||||
|  | +	__u32	ifInUnknownProtos;  /*!< counter of unknown ingress cells   */ | ||||||
|  | +	__u32	ifOutErrors;        /*!< counter of error egress cells      */ | ||||||
|  | +} atm_cell_ifEntry_t; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_aal5_ifEntry_t | ||||||
|  | +  \brief Structure used for AAL5 Frame Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  User application use this structure to call IOCTL command "PPE_ATM_MIB_AAL5". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	__u32	ifHCInOctets_h;     /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */ | ||||||
|  | +	__u32	ifHCInOctets_l;     /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */ | ||||||
|  | +	__u32	ifHCOutOctets_h;    /*!< byte counter of egress packets (upper 32 bits, total 64 bits)  */ | ||||||
|  | +	__u32	ifHCOutOctets_l;    /*!< byte counter of egress packets (lower 32 bits, total 64 bits)  */ | ||||||
|  | +	__u32	ifInUcastPkts;      /*!< counter of ingress packets         */ | ||||||
|  | +	__u32	ifOutUcastPkts;     /*!< counter of egress packets          */ | ||||||
|  | +	__u32	ifInErrors;         /*!< counter of error ingress packets   */ | ||||||
|  | +	__u32	ifInDiscards;       /*!< counter of dropped ingress packets */ | ||||||
|  | +	__u32	ifOutErros;         /*!< counter of error egress packets    */ | ||||||
|  | +	__u32	ifOutDiscards;      /*!< counter of dropped egress packets  */ | ||||||
|  | +} atm_aal5_ifEntry_t; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_aal5_vcc_t | ||||||
|  | +  \brief Structure used for per PVC AAL5 Frame Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  This structure is a part of structure "atm_aal5_vcc_x_t". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	__u32	aal5VccCrcErrors;       /*!< counter of ingress packets with CRC error  */ | ||||||
|  | +	__u32	aal5VccSarTimeOuts;     /*!< counter of ingress packets with Re-assemble timeout    */  //no timer support yet | ||||||
|  | +	__u32	aal5VccOverSizedSDUs;   /*!< counter of oversized ingress packets       */ | ||||||
|  | +} atm_aal5_vcc_t; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_aal5_vcc_x_t | ||||||
|  | +  \brief Structure used for per PVC AAL5 Frame Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  User application use this structure to call IOCTL command "PPE_ATM_MIB_VCC". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	int             vpi;        /*!< VPI of the VCC to get MIB counters */ | ||||||
|  | +	int             vci;        /*!< VCI of the VCC to get MIB counters */ | ||||||
|  | +	atm_aal5_vcc_t  mib_vcc;    /*!< structure to get MIB counters      */ | ||||||
|  | +} atm_aal5_vcc_x_t; | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                IOCTL | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_ATM_IOCTL | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ioctl Command | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Magic Number | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_IOC_MAGIC       'o' | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Command - Get Cell Level MIB Counters | ||||||
|  | + | ||||||
|  | +   This command is obsolete. User can get cell level MIB from DSL API. | ||||||
|  | +   This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_MIB_CELL        _IOW(PPE_ATM_IOC_MAGIC,  0, atm_cell_ifEntry_t) | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Command - Get AAL5 Level MIB Counters | ||||||
|  | + | ||||||
|  | +   Get AAL5 packet counters. | ||||||
|  | +   This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_MIB_AAL5        _IOW(PPE_ATM_IOC_MAGIC,  1, atm_aal5_ifEntry_t) | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Command - Get Per PVC MIB Counters | ||||||
|  | + | ||||||
|  | +   Get AAL5 packet counters for each PVC. | ||||||
|  | +   This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_MIB_VCC         _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t) | ||||||
|  | +/*! | ||||||
|  | +  \brief Total Number of ATM IOCTL Commands | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_IOC_MAXNR       3 | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                 API | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#ifdef __KERNEL__ | ||||||
|  | +struct port_cell_info { | ||||||
|  | +    unsigned int    port_num; | ||||||
|  | +    unsigned int    tx_link_rate[2]; | ||||||
|  | +}; | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +#endif  //  IFX_ATM_H | ||||||
|  | + | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/lantiq_ptm.h | ||||||
|  | @@ -0,0 +1,203 @@ | ||||||
|  | +/****************************************************************************** | ||||||
|  | +** | ||||||
|  | +** FILE NAME    : ifx_ptm.h | ||||||
|  | +** PROJECT      : UEIP | ||||||
|  | +** MODULES      : PTM | ||||||
|  | +** | ||||||
|  | +** DATE         : 17 Jun 2009 | ||||||
|  | +** AUTHOR       : Xu Liang | ||||||
|  | +** DESCRIPTION  : Global PTM driver header file | ||||||
|  | +** COPYRIGHT    :       Copyright (c) 2006 | ||||||
|  | +**                      Infineon Technologies AG | ||||||
|  | +**                      Am Campeon 1-12, 85579 Neubiberg, Germany | ||||||
|  | +** | ||||||
|  | +**    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 Free Software Foundation; either version 2 of the License, or | ||||||
|  | +**    (at your option) any later version. | ||||||
|  | +** | ||||||
|  | +** HISTORY | ||||||
|  | +** $Date        $Author         $Comment | ||||||
|  | +** 07 JUL 2009  Xu Liang        Init Version | ||||||
|  | +*******************************************************************************/ | ||||||
|  | + | ||||||
|  | +#ifndef IFX_PTM_H | ||||||
|  | +#define IFX_PTM_H | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_PTM UEIP Project - PTM driver module | ||||||
|  | +  \brief UEIP Project - PTM driver module, support Danube, Amazon-SE, AR9, VR9. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_PTM_IOCTL IOCTL Commands | ||||||
|  | +  \ingroup IFX_PTM | ||||||
|  | +  \brief IOCTL Commands used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_PTM_STRUCT Structures | ||||||
|  | +  \ingroup IFX_PTM | ||||||
|  | +  \brief Structures used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \file ifx_ptm.h | ||||||
|  | +  \ingroup IFX_PTM | ||||||
|  | +  \brief PTM driver header file | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *              Definition | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                IOCTL | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_PTM_IOCTL | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ioctl Command | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Get codeword MIB counters. | ||||||
|  | + | ||||||
|  | +  This command uses structure "PTM_CW_IF_ENTRY_T" to get codeword level MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_MIB_CW_GET              SIOCDEVPRIVATE + 1 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Get packet MIB counters. | ||||||
|  | + | ||||||
|  | +  This command uses structure "PTM_FRAME_MIB_T" to get packet level MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_MIB_FRAME_GET           SIOCDEVPRIVATE + 2 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Get firmware configuration (CRC). | ||||||
|  | + | ||||||
|  | +  This command uses structure "IFX_PTM_CFG_T" to get firmware configuration (CRC). | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_CFG_GET                 SIOCDEVPRIVATE + 3 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Set firmware configuration (CRC). | ||||||
|  | + | ||||||
|  | +  This command uses structure "IFX_PTM_CFG_T" to set firmware configuration (CRC). | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_CFG_SET                 SIOCDEVPRIVATE + 4 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Program priority value to TX queue mapping. | ||||||
|  | + | ||||||
|  | +  This command uses structure "IFX_PTM_PRIO_Q_MAP_T" to program priority value to TX queue mapping. | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_MAP_PKT_PRIO_TO_Q       SIOCDEVPRIVATE + 14 | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_PTM_STRUCT | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ioctl Data Type | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef PTM_CW_IF_ENTRY_T | ||||||
|  | +  \brief Wrapping of structure "ptm_cw_ifEntry_t". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ptm_cw_ifEntry_t | ||||||
|  | +  \brief Structure used for CodeWord level MIB counters. | ||||||
|  | + */ | ||||||
|  | +typedef struct ptm_cw_ifEntry_t { | ||||||
|  | +    uint32_t    ifRxNoIdleCodewords;    /*!< output, number of ingress user codeword */ | ||||||
|  | +    uint32_t    ifRxIdleCodewords;      /*!< output, number of ingress idle codeword */ | ||||||
|  | +    uint32_t    ifRxCodingViolation;    /*!< output, number of error ingress codeword */ | ||||||
|  | +    uint32_t    ifTxNoIdleCodewords;    /*!< output, number of egress user codeword */ | ||||||
|  | +    uint32_t    ifTxIdleCodewords;      /*!< output, number of egress idle codeword */ | ||||||
|  | +} PTM_CW_IF_ENTRY_T; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef PTM_FRAME_MIB_T | ||||||
|  | +  \brief Wrapping of structure "ptm_frame_mib_t". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ptm_frame_mib_t | ||||||
|  | +  \brief Structure used for packet level MIB counters. | ||||||
|  | + */ | ||||||
|  | +typedef struct ptm_frame_mib_t { | ||||||
|  | +    uint32_t    RxCorrect;      /*!< output, number of ingress packet */ | ||||||
|  | +    uint32_t    TC_CrcError;    /*!< output, number of egress packet with CRC error */ | ||||||
|  | +    uint32_t    RxDropped;      /*!< output, number of dropped ingress packet */ | ||||||
|  | +    uint32_t    TxSend;         /*!< output, number of egress packet */ | ||||||
|  | +} PTM_FRAME_MIB_T; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef IFX_PTM_CFG_T | ||||||
|  | +  \brief Wrapping of structure "ptm_cfg_t". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ptm_cfg_t | ||||||
|  | +  \brief Structure used for ETH/TC CRC configuration. | ||||||
|  | + */ | ||||||
|  | +typedef struct ptm_cfg_t { | ||||||
|  | +    uint32_t    RxEthCrcPresent;    /*!< input/output, ingress packet has ETH CRC */ | ||||||
|  | +    uint32_t    RxEthCrcCheck;      /*!< input/output, check ETH CRC of ingress packet */ | ||||||
|  | +    uint32_t    RxTcCrcCheck;       /*!< input/output, check TC CRC of ingress codeword */ | ||||||
|  | +    uint32_t    RxTcCrcLen;         /*!< input/output, length of TC CRC of ingress codeword */ | ||||||
|  | +    uint32_t    TxEthCrcGen;        /*!< input/output, generate ETH CRC for egress packet */ | ||||||
|  | +    uint32_t    TxTcCrcGen;         /*!< input/output, generate TC CRC for egress codeword */ | ||||||
|  | +    uint32_t    TxTcCrcLen;         /*!< input/output, length of TC CRC of egress codeword */ | ||||||
|  | +} IFX_PTM_CFG_T; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef IFX_PTM_PRIO_Q_MAP_T | ||||||
|  | +  \brief Wrapping of structure "ppe_prio_q_map". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ppe_prio_q_map | ||||||
|  | +  \brief Structure used for Priority Value to TX Queue mapping. | ||||||
|  | + */ | ||||||
|  | +typedef struct ppe_prio_q_map { | ||||||
|  | +    int             pkt_prio; | ||||||
|  | +    int             qid; | ||||||
|  | +    int             vpi;    //  ignored in eth interface | ||||||
|  | +    int             vci;    //  ignored in eth interface | ||||||
|  | +} IFX_PTM_PRIO_Q_MAP_T; | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                 API | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#ifdef __KERNEL__ | ||||||
|  | +struct port_cell_info { | ||||||
|  | +    unsigned int    port_num; | ||||||
|  | +    unsigned int    tx_link_rate[2]; | ||||||
|  | +}; | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +#endif  //  IFX_PTM_H | ||||||
|  | + | ||||||
|  | --- a/arch/mips/lantiq/irq.c | ||||||
|  | +++ b/arch/mips/lantiq/irq.c | ||||||
|  | @@ -12,6 +12,7 @@ | ||||||
|  |  #include <linux/of_platform.h> | ||||||
|  |  #include <linux/of_address.h> | ||||||
|  |  #include <linux/of_irq.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  |   | ||||||
|  |  #include <asm/bootinfo.h> | ||||||
|  |  #include <asm/irq_cpu.h> | ||||||
|  | @@ -91,6 +92,7 @@ void ltq_disable_irq(struct irq_data *d) | ||||||
|  |  	} | ||||||
|  |  	raw_spin_unlock_irqrestore(<q_icu_lock, flags); | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL(ltq_mask_and_ack_irq); | ||||||
|  |   | ||||||
|  |  void ltq_mask_and_ack_irq(struct irq_data *d) | ||||||
|  |  { | ||||||
|  | --- a/arch/mips/mm/cache.c | ||||||
|  | +++ b/arch/mips/mm/cache.c | ||||||
|  | @@ -61,6 +61,10 @@ void (*_dma_cache_wback_inv)(unsigned lo | ||||||
|  |  void (*_dma_cache_wback)(unsigned long start, unsigned long size); | ||||||
|  |  void (*_dma_cache_inv)(unsigned long start, unsigned long size); | ||||||
|  |   | ||||||
|  | +EXPORT_SYMBOL(_dma_cache_wback_inv); | ||||||
|  | +EXPORT_SYMBOL(_dma_cache_wback); | ||||||
|  | +EXPORT_SYMBOL(_dma_cache_inv); | ||||||
|  | + | ||||||
|  |  #endif /* CONFIG_DMA_NONCOHERENT */ | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | --- a/include/uapi/linux/atm.h | ||||||
|  | +++ b/include/uapi/linux/atm.h | ||||||
|  | @@ -131,8 +131,14 @@ | ||||||
|  |  #define ATM_ABR		4 | ||||||
|  |  #define ATM_ANYCLASS	5		/* compatible with everything */ | ||||||
|  |   | ||||||
|  | +#define ATM_VBR_NRT     ATM_VBR | ||||||
|  | +#define ATM_VBR_RT      6 | ||||||
|  | +#define ATM_UBR_PLUS    7 | ||||||
|  | +#define ATM_GFR         8 | ||||||
|  | + | ||||||
|  |  #define ATM_MAX_PCR	-1		/* maximum available PCR */ | ||||||
|  |   | ||||||
|  | + | ||||||
|  |  struct atm_trafprm { | ||||||
|  |  	unsigned char	traffic_class;	/* traffic class (ATM_UBR, ...) */ | ||||||
|  |  	int		max_pcr;	/* maximum PCR in cells per second */ | ||||||
|  | --- a/net/atm/proc.c | ||||||
|  | +++ b/net/atm/proc.c | ||||||
|  | @@ -141,7 +141,7 @@ static void *vcc_seq_next(struct seq_fil | ||||||
|  |  static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc) | ||||||
|  |  { | ||||||
|  |  	static const char *const class_name[] = { | ||||||
|  | -		"off", "UBR", "CBR", "VBR", "ABR"}; | ||||||
|  | +		"off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"}; | ||||||
|  |  	static const char *const aal_name[] = { | ||||||
|  |  		"---",	"1",	"2",	"3/4",	/*  0- 3 */ | ||||||
|  |  		"???",	"5",	"???",	"???",	/*  4- 7 */ | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | From 997a8965db8417266bea3fbdcfa3e5655a1b52fa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Tue, 9 Sep 2014 23:12:15 +0200 | ||||||
|  | Subject: [PATCH 18/36] MTD: nand: lots of xrx200 fixes | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/nand/raw/xway_nand.c |   63 ++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 63 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/nand/raw/xway_nand.c | ||||||
|  | +++ b/drivers/mtd/nand/raw/xway_nand.c | ||||||
|  | @@ -61,6 +61,24 @@ | ||||||
|  |  #define NAND_CON_CSMUX		(1 << 1) | ||||||
|  |  #define NAND_CON_NANDM		1 | ||||||
|  |   | ||||||
|  | +#define DANUBE_PCI_REG32( addr )    (*(volatile u32 *)(addr)) | ||||||
|  | +#define PCI_CR_PR_OFFSET	    (KSEG1+0x1E105400) | ||||||
|  | +#define PCI_CR_PC_ARB		    (PCI_CR_PR_OFFSET + 0x0080) | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * req_mask provides a mechanism to prevent interference between | ||||||
|  | + * nand and pci (probably only relevant for the BT Home Hub 2B). | ||||||
|  | + * Setting it causes the corresponding pci req pins to be masked | ||||||
|  | + * during nand access, and also moves ebu locking from the read/write | ||||||
|  | + * functions to the chip select function to ensure that the whole | ||||||
|  | + * operation runs with interrupts disabled. | ||||||
|  | + * In addition it switches on some extra waiting in xway_cmd_ctrl(). | ||||||
|  | + * This seems to be necessary if the ebu_cs1 pin has open-drain disabled, | ||||||
|  | + * which in turn seems to be necessary for the nor chip to be recognised | ||||||
|  | + * reliably, on a board (Home Hub 2B again) which has both nor and nand. | ||||||
|  | + */ | ||||||
|  | +static __be32 req_mask = 0; | ||||||
|  | + | ||||||
|  |  struct xway_nand_data { | ||||||
|  |  	struct nand_controller	controller; | ||||||
|  |  	struct nand_chip	chip; | ||||||
|  | @@ -92,10 +110,22 @@ static void xway_select_chip(struct nand | ||||||
|  |  	case -1: | ||||||
|  |  		ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON); | ||||||
|  |  		ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON); | ||||||
|  | + | ||||||
|  | +		if (req_mask) { | ||||||
|  | +			/* Unmask all external PCI request */ | ||||||
|  | +			DANUBE_PCI_REG32(PCI_CR_PC_ARB) &= ~(req_mask << 16); | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		spin_unlock_irqrestore(&ebu_lock, data->csflags); | ||||||
|  |  		break; | ||||||
|  |  	case 0: | ||||||
|  |  		spin_lock_irqsave(&ebu_lock, data->csflags); | ||||||
|  | + | ||||||
|  | +		if (req_mask) { | ||||||
|  | +			/* Mask all external PCI request */ | ||||||
|  | +			DANUBE_PCI_REG32(PCI_CR_PC_ARB) |= (req_mask << 16); | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON); | ||||||
|  |  		ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON); | ||||||
|  |  		break; | ||||||
|  | @@ -108,6 +138,11 @@ static void xway_cmd_ctrl(struct nand_ch | ||||||
|  |  { | ||||||
|  |  	struct mtd_info *mtd = nand_to_mtd(chip); | ||||||
|  |   | ||||||
|  | +	if (req_mask) { | ||||||
|  | +		if (cmd != NAND_CMD_STATUS) | ||||||
|  | +			ltq_ebu_w32(0, EBU_NAND_WAIT); /* Clear nand ready */ | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	if (cmd == NAND_CMD_NONE) | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  | @@ -118,6 +153,24 @@ static void xway_cmd_ctrl(struct nand_ch | ||||||
|  |   | ||||||
|  |  	while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0) | ||||||
|  |  		; | ||||||
|  | + | ||||||
|  | +	if (req_mask) { | ||||||
|  | +	       /* | ||||||
|  | +		* program and erase have their own busy handlers | ||||||
|  | +		* status and sequential in needs no delay | ||||||
|  | +		*/ | ||||||
|  | +		switch (cmd) { | ||||||
|  | +			case NAND_CMD_ERASE1: | ||||||
|  | +			case NAND_CMD_SEQIN: | ||||||
|  | +			case NAND_CMD_STATUS: | ||||||
|  | +			case NAND_CMD_READID: | ||||||
|  | +			return; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		/* wait until command is processed */ | ||||||
|  | +		while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD) == 0) | ||||||
|  | +			; | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int xway_dev_ready(struct nand_chip *chip) | ||||||
|  | @@ -170,6 +223,7 @@ static int xway_nand_probe(struct platfo | ||||||
|  |  	int err; | ||||||
|  |  	u32 cs; | ||||||
|  |  	u32 cs_flag = 0; | ||||||
|  | +	const __be32 *req_mask_ptr; | ||||||
|  |   | ||||||
|  |  	/* Allocate memory for the device structure (and zero it) */ | ||||||
|  |  	data = devm_kzalloc(&pdev->dev, sizeof(struct xway_nand_data), | ||||||
|  | @@ -206,6 +260,15 @@ static int xway_nand_probe(struct platfo | ||||||
|  |  	if (!err && cs == 1) | ||||||
|  |  		cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; | ||||||
|  |   | ||||||
|  | +	req_mask_ptr = of_get_property(pdev->dev.of_node, | ||||||
|  | +					"req-mask", NULL); | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Load the PCI req lines to mask from the device tree. If the | ||||||
|  | +	 * property is not present, setting req_mask to 0 disables masking. | ||||||
|  | +	 */ | ||||||
|  | +	req_mask = (req_mask_ptr ? *req_mask_ptr : 0); | ||||||
|  | + | ||||||
|  |  	/* setup the EBU to run in NAND mode on our base addr */ | ||||||
|  |  	ltq_ebu_w32(CPHYSADDR(data->nandaddr) | ||||||
|  |  		    | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1); | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | From e3b20f04e9f9cae1babe091fdc1d08d7703ae344 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Thu, 7 Aug 2014 18:18:00 +0200 | ||||||
|  | Subject: [PATCH 20/36] MTD: lantiq: handle NO_XIP on cfi0001 flash | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/maps/lantiq-flash.c |    6 +++++- | ||||||
|  |  1 file changed, 5 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | +++ b/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | @@ -129,7 +129,11 @@ ltq_mtd_probe(struct platform_device *pd | ||||||
|  |  	if (!ltq_mtd->map) | ||||||
|  |  		return -ENOMEM; | ||||||
|  |   | ||||||
|  | -	ltq_mtd->map->phys = ltq_mtd->res->start; | ||||||
|  | +	if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) | ||||||
|  | +		ltq_mtd->map->phys = NO_XIP; | ||||||
|  | +	else | ||||||
|  | +		ltq_mtd->map->phys = ltq_mtd->res->start; | ||||||
|  | +	ltq_mtd->res->start; | ||||||
|  |  	ltq_mtd->map->size = resource_size(ltq_mtd->res); | ||||||
|  |  	ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res); | ||||||
|  |  	if (IS_ERR(ltq_mtd->map->virt)) | ||||||
| @@ -0,0 +1,294 @@ | |||||||
|  | From 0a63ab263725c427051a8bbaa0732b749627da27 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Thu, 7 Aug 2014 18:15:36 +0200 | ||||||
|  | Subject: [PATCH 23/36] NET: PHY: adds driver for lantiq PHY11G | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/phy/Kconfig  |    5 + | ||||||
|  |  drivers/net/phy/Makefile |    1 + | ||||||
|  |  drivers/net/phy/lantiq.c |  231 ++++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 237 insertions(+) | ||||||
|  |  create mode 100644 drivers/net/phy/lantiq.c | ||||||
|  |  | ||||||
|  | --- a/drivers/net/phy/intel-xway.c | ||||||
|  | +++ b/drivers/net/phy/intel-xway.c | ||||||
|  | @@ -157,6 +157,51 @@ | ||||||
|  |  #define PHY_ID_PHY11G_VR9_1_2		0xD565A409 | ||||||
|  |  #define PHY_ID_PHY22F_VR9_1_2		0xD565A419 | ||||||
|  |   | ||||||
|  | +#if IS_ENABLED(CONFIG_OF_MDIO) | ||||||
|  | +static int vr9_gphy_of_reg_init(struct phy_device *phydev) | ||||||
|  | +{ | ||||||
|  | +	u32 tmp; | ||||||
|  | + | ||||||
|  | +	/* store the led values if one was passed by the devicetree */ | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,ledch", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCH, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,ledcl", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCL, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led0h", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0H, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led0l", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0L, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led1h", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1H, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led1l", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1L, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led2h", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H,  tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led2l", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led3h", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED3H, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led3l", &tmp)) | ||||||
|  | +		phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED3L, tmp); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +#else | ||||||
|  | +static int vr9_gphy_of_reg_init(struct phy_device *phydev) | ||||||
|  | +{ | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +#endif /* CONFIG_OF_MDIO */ | ||||||
|  | + | ||||||
|  |  static int xway_gphy_config_init(struct phy_device *phydev) | ||||||
|  |  { | ||||||
|  |  	int err; | ||||||
|  | @@ -204,6 +249,7 @@ static int xway_gphy_config_init(struct | ||||||
|  |  	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh); | ||||||
|  |  	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl); | ||||||
|  |   | ||||||
|  | +	vr9_gphy_of_reg_init(phydev); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/Documentation/devicetree/bindings/phy/phy-lanitq.txt | ||||||
|  | @@ -0,0 +1,216 @@ | ||||||
|  | +Lanitq PHY binding | ||||||
|  | +============================================ | ||||||
|  | + | ||||||
|  | +This devicetree binding controls the lantiq ethernet phys led functionality. | ||||||
|  | + | ||||||
|  | +Example: | ||||||
|  | +	mdio@0 { | ||||||
|  | +		#address-cells = <1>; | ||||||
|  | +		#size-cells = <0>; | ||||||
|  | +		compatible = "lantiq,xrx200-mdio"; | ||||||
|  | +			phy5: ethernet-phy@5 { | ||||||
|  | +			reg = <0x1>; | ||||||
|  | +			compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +		}; | ||||||
|  | +		phy11: ethernet-phy@11 { | ||||||
|  | +			reg = <0x11>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led2h = <0x00>; | ||||||
|  | +			lantiq,led2l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +		phy12: ethernet-phy@12 { | ||||||
|  | +			reg = <0x12>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led1h = <0x00>; | ||||||
|  | +			lantiq,led1l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +		phy13: ethernet-phy@13 { | ||||||
|  | +			reg = <0x13>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led2h = <0x00>; | ||||||
|  | +			lantiq,led2l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +		phy14: ethernet-phy@14 { | ||||||
|  | +			reg = <0x14>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led1h = <0x00>; | ||||||
|  | +			lantiq,led1l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +	}; | ||||||
|  | + | ||||||
|  | +Register Description | ||||||
|  | +============================================ | ||||||
|  | + | ||||||
|  | +LEDCH: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LEDCH	0x00C5 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|   FBF   |   SBF   |RES |     NACS     | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +FBF	7:6	RW	Fast Blink Frequency | ||||||
|  | +			--- | ||||||
|  | +			0x0 (00b) F02HZ 2 Hz blinking frequency | ||||||
|  | +			0x1 (01b) F04HZ 4 Hz blinking frequency | ||||||
|  | +			0x2 (10b) F08HZ 8 Hz blinking frequency | ||||||
|  | +			0x3 (11b) F16HZ 16 Hz blinking frequency | ||||||
|  | + | ||||||
|  | +SBF	5:4	RW	Slow Blink Frequency | ||||||
|  | +			--- | ||||||
|  | +			0x0 (00b) F02HZ 2 Hz blinking frequency | ||||||
|  | +			0x1 (01b) F04HZ 4 Hz blinking frequency | ||||||
|  | +			0x2 (10b) F08HZ 8 Hz blinking frequency | ||||||
|  | +			0x3 (11b) F16HZ 16 Hz blinking frequency | ||||||
|  | + | ||||||
|  | +NACS	2:0	RW	Inverse of Scan Function | ||||||
|  | +			--- | ||||||
|  | +			0x0 (000b) NONE No Function | ||||||
|  | +			0x1 (001b) LINK Complex function enabled when link is up | ||||||
|  | +			0x2 (010b) PDOWN Complex function enabled when device is powered-down | ||||||
|  | +			0x3 (011b) EEE Complex function enabled when device is in EEE mode | ||||||
|  | +			0x4 (100b) ANEG Complex function enabled when auto-negotiation is running | ||||||
|  | +			0x5 (101b) ABIST Complex function enabled when analog self-test is running | ||||||
|  | +			0x6 (110b) CDIAG Complex function enabled when cable diagnostics are running | ||||||
|  | +			0x7 (111b) TEST Complex function enabled when test mode is running | ||||||
|  | + | ||||||
|  | +LEDCL: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LEDCL	0x0067 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|RES |     SCAN     |RES |    CBLINK    | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +SCAN	6:4	RW	Complex Scan Configuration | ||||||
|  | +			--- | ||||||
|  | +			000 B NONE No Function | ||||||
|  | +			001 B LINK Complex function enabled when link is up | ||||||
|  | +			010 B PDOWN Complex function enabled when device is powered-down | ||||||
|  | +			011 B EEE Complex function enabled when device is in EEE mode | ||||||
|  | +			100 B ANEG Complex function enabled when auto-negotiation is running | ||||||
|  | +			101 B ABIST Complex function enabled when analog self-test is running | ||||||
|  | +			110 B CDIAG Complex function enabled when cable diagnostics are running | ||||||
|  | +			111 B TEST Complex function enabled when test mode is running | ||||||
|  | + | ||||||
|  | +CBLINK	2:0	RW	Complex Blinking Configuration | ||||||
|  | +			--- | ||||||
|  | +			000 B NONE No Function | ||||||
|  | +			001 B LINK Complex function enabled when link is up | ||||||
|  | +			010 B PDOWN Complex function enabled when device is powered-down | ||||||
|  | +			011 B EEE Complex function enabled when device is in EEE mode | ||||||
|  | +			100 B ANEG Complex function enabled when auto-negotiation is running | ||||||
|  | +			101 B ABIST Complex function enabled when analog self-test is running | ||||||
|  | +			110 B CDIAG Complex function enabled when cable diagnostics are running | ||||||
|  | +			111 B TEST Complex function enabled when test mode is running | ||||||
|  | + | ||||||
|  | +LEDxH: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LED0H	0x0070 | ||||||
|  | +LED1H	0x0020 | ||||||
|  | +LED2H	0x0040 | ||||||
|  | +LED3H	0x0040 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|        CON        |       BLINKF      | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +CON	7:4	RW	Constant On Configuration | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE LED does not light up constantly | ||||||
|  | +			0x1 (0001b) LINK10 LED is on when link is 10 Mbit/s | ||||||
|  | +			0x2 (0010b) LINK100 LED is on when link is 100 Mbit/s | ||||||
|  | +			0x3 (0011b) LINK10X LED is on when link is 10/100 Mbit/s | ||||||
|  | +			0x4 (0100b) LINK1000 LED is on when link is 1000 Mbit/s | ||||||
|  | +			0x5 (0101b) LINK10_0 LED is on when link is 10/1000 Mbit/s | ||||||
|  | +			0x6 (0110b) LINK100X LED is on when link is 100/1000 Mbit/s | ||||||
|  | +			0x7 (0111b) LINK10XX LED is on when link is 10/100/1000 Mbit/s | ||||||
|  | +			0x8 (1000b) PDOWN LED is on when device is powered-down | ||||||
|  | +			0x9 (1001b) EEE LED is on when device is in EEE mode | ||||||
|  | +			0xA (1010b) ANEG LED is on when auto-negotiation is running | ||||||
|  | +			0xB (1011b) ABIST LED is on when analog self-test is running | ||||||
|  | +			0xC (1100b) CDIAG LED is on when cable diagnostics are running | ||||||
|  | + | ||||||
|  | +BLINKF	3:0	RW	Fast Blinking Configuration | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE No Blinking | ||||||
|  | +			0x1 (0001b) LINK10 Blink when link is 10 Mbit/s | ||||||
|  | +			0x2 (0010b) LINK100 Blink when link is 100 Mbit/s | ||||||
|  | +			0x3 (0011b) LINK10X Blink when link is 10/100 Mbit/s | ||||||
|  | +			0x4 (0100b) LINK1000 Blink when link is 1000 Mbit/s | ||||||
|  | +			0x5 (0101b) LINK10_0 Blink when link is 10/1000 Mbit/s | ||||||
|  | +			0x6 (0110b) LINK100X Blink when link is 100/1000 Mbit/s | ||||||
|  | +			0x7 (0111b) LINK10XX Blink when link is 10/100/1000 Mbit/s | ||||||
|  | +			0x8 (1000b) PDOWN Blink when device is powered-down | ||||||
|  | +			0x9 (1001b) EEE Blink when device is in EEE mode | ||||||
|  | +			0xA (1010b) ANEG Blink when auto-negotiation is running | ||||||
|  | +			0xB (1011b) ABIST Blink when analog self-test is running | ||||||
|  | +			0xC (1100b) CDIAG Blink when cable diagnostics are running | ||||||
|  | + | ||||||
|  | +LEDxL: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LED0L	0x0003 | ||||||
|  | +LED1L	0x0000 | ||||||
|  | +LED2L	0x0000 | ||||||
|  | +LED3L	0x0020 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|      BLINKS       |       PULSE       | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +BLINKS	7:4	RW	Slow Blinkin Configuration | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE No Blinking | ||||||
|  | +			0x1 (0001b) LINK10 Blink when link is 10 Mbit/s | ||||||
|  | +			0x2 (0010b) LINK100 Blink when link is 100 Mbit/s | ||||||
|  | +			0x3 (0011b) LINK10X Blink when link is 10/100 Mbit/s | ||||||
|  | +			0x4 (0100b) LINK1000 Blink when link is 1000 Mbit/s | ||||||
|  | +			0x5 (0101b) LINK10_0 Blink when link is 10/1000 Mbit/s | ||||||
|  | +			0x6 (0110b) LINK100X Blink when link is 100/1000 Mbit/s | ||||||
|  | +			0x7 (0111b) LINK10XX Blink when link is 10/100/1000 Mbit/s | ||||||
|  | +			0x8 (1000b) PDOWN Blink when device is powered-down | ||||||
|  | +			0x9 (1001b) EEE Blink when device is in EEE mode | ||||||
|  | +			0xA (1010b) ANEG Blink when auto-negotiation is running | ||||||
|  | +			0xB (1011b) ABIST Blink when analog self-test is running | ||||||
|  | +			0xC (1100b) CDIAG Blink when cable diagnostics are runningning | ||||||
|  | + | ||||||
|  | +PULSE	3:0	RW	Pulsing Configuration | ||||||
|  | +			The pulse field is a mask field by which certain events can be combined | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE No pulsing | ||||||
|  | +			0x1 (0001b) TXACT Transmit activity | ||||||
|  | +			0x2 (0010b) RXACT Receive activity | ||||||
|  | +			0x4 (0100b) COL Collision | ||||||
|  | +			0x8 (1000b) RES Reserved | ||||||
| @@ -0,0 +1,865 @@ | |||||||
|  | From 870ed9cae083ff8a60a739ef7e74c5a1800533be Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Tue, 9 Sep 2014 22:45:34 +0200 | ||||||
|  | Subject: [PATCH 28/36] NET: lantiq: various etop fixes | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_etop.c |  555 +++++++++++++++++++++++++----------- | ||||||
|  |  1 file changed, 389 insertions(+), 166 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -1,7 +1,7 @@ | ||||||
|  |  // SPDX-License-Identifier: GPL-2.0-only | ||||||
|  |  /* | ||||||
|  |   * | ||||||
|  | - *   Copyright (C) 2011 John Crispin <blogic@openwrt.org> | ||||||
|  | + *   Copyright (C) 2011-12 John Crispin <blogic@openwrt.org> | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include <linux/kernel.h> | ||||||
|  | @@ -20,11 +20,16 @@ | ||||||
|  |  #include <linux/mm.h> | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <linux/ethtool.h> | ||||||
|  | +#include <linux/if_vlan.h> | ||||||
|  |  #include <linux/init.h> | ||||||
|  |  #include <linux/delay.h> | ||||||
|  |  #include <linux/io.h> | ||||||
|  |  #include <linux/dma-mapping.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  | +#include <linux/clk.h> | ||||||
|  | +#include <linux/of_net.h> | ||||||
|  | +#include <linux/of_irq.h> | ||||||
|  | +#include <linux/of_platform.h> | ||||||
|  |   | ||||||
|  |  #include <asm/checksum.h> | ||||||
|  |   | ||||||
|  | @@ -32,7 +37,7 @@ | ||||||
|  |  #include <xway_dma.h> | ||||||
|  |  #include <lantiq_platform.h> | ||||||
|  |   | ||||||
|  | -#define LTQ_ETOP_MDIO		0x11804 | ||||||
|  | +#define LTQ_ETOP_MDIO_ACC	0x11804 | ||||||
|  |  #define MDIO_REQUEST		0x80000000 | ||||||
|  |  #define MDIO_READ		0x40000000 | ||||||
|  |  #define MDIO_ADDR_MASK		0x1f | ||||||
|  | @@ -41,44 +46,91 @@ | ||||||
|  |  #define MDIO_REG_OFFSET		0x10 | ||||||
|  |  #define MDIO_VAL_MASK		0xffff | ||||||
|  |   | ||||||
|  | -#define PPE32_CGEN		0x800 | ||||||
|  | -#define LQ_PPE32_ENET_MAC_CFG	0x1840 | ||||||
|  | +#define LTQ_ETOP_MDIO_CFG       0x11800 | ||||||
|  | +#define MDIO_CFG_MASK           0x6 | ||||||
|  | + | ||||||
|  | +#define LTQ_ETOP_CFG            0x11808 | ||||||
|  | +#define LTQ_ETOP_IGPLEN         0x11820 | ||||||
|  | +#define LTQ_ETOP_MAC_CFG	0x11840 | ||||||
|  |   | ||||||
|  |  #define LTQ_ETOP_ENETS0		0x11850 | ||||||
|  |  #define LTQ_ETOP_MAC_DA0	0x1186C | ||||||
|  |  #define LTQ_ETOP_MAC_DA1	0x11870 | ||||||
|  | -#define LTQ_ETOP_CFG		0x16020 | ||||||
|  | -#define LTQ_ETOP_IGPLEN		0x16080 | ||||||
|  | + | ||||||
|  | +#define MAC_CFG_MASK		0xfff | ||||||
|  | +#define MAC_CFG_CGEN		(1 << 11) | ||||||
|  | +#define MAC_CFG_DUPLEX		(1 << 2) | ||||||
|  | +#define MAC_CFG_SPEED		(1 << 1) | ||||||
|  | +#define MAC_CFG_LINK		(1 << 0) | ||||||
|  |   | ||||||
|  |  #define MAX_DMA_CHAN		0x8 | ||||||
|  |  #define MAX_DMA_CRC_LEN		0x4 | ||||||
|  |  #define MAX_DMA_DATA_LEN	0x600 | ||||||
|  |   | ||||||
|  |  #define ETOP_FTCU		BIT(28) | ||||||
|  | -#define ETOP_MII_MASK		0xf | ||||||
|  | -#define ETOP_MII_NORMAL		0xd | ||||||
|  | -#define ETOP_MII_REVERSE	0xe | ||||||
|  |  #define ETOP_PLEN_UNDER		0x40 | ||||||
|  | -#define ETOP_CGEN		0x800 | ||||||
|  | +#define ETOP_CFG_MII0		0x01 | ||||||
|  |   | ||||||
|  | -/* use 2 static channels for TX/RX */ | ||||||
|  | -#define LTQ_ETOP_TX_CHANNEL	1 | ||||||
|  | -#define LTQ_ETOP_RX_CHANNEL	6 | ||||||
|  | -#define IS_TX(x)		(x == LTQ_ETOP_TX_CHANNEL) | ||||||
|  | -#define IS_RX(x)		(x == LTQ_ETOP_RX_CHANNEL) | ||||||
|  | +#define ETOP_CFG_MASK           0xfff | ||||||
|  | +#define ETOP_CFG_FEN0		(1 << 8) | ||||||
|  | +#define ETOP_CFG_SEN0		(1 << 6) | ||||||
|  | +#define ETOP_CFG_OFF1		(1 << 3) | ||||||
|  | +#define ETOP_CFG_REMII0		(1 << 1) | ||||||
|  | +#define ETOP_CFG_OFF0		(1 << 0) | ||||||
|  | + | ||||||
|  | +#define LTQ_GBIT_MDIO_CTL	0xCC | ||||||
|  | +#define LTQ_GBIT_MDIO_DATA	0xd0 | ||||||
|  | +#define LTQ_GBIT_GCTL0		0x68 | ||||||
|  | +#define LTQ_GBIT_PMAC_HD_CTL	0x8c | ||||||
|  | +#define LTQ_GBIT_P0_CTL		0x4 | ||||||
|  | +#define LTQ_GBIT_PMAC_RX_IPG	0xa8 | ||||||
|  | +#define LTQ_GBIT_RGMII_CTL	0x78 | ||||||
|  | + | ||||||
|  | +#define PMAC_HD_CTL_AS		(1 << 19) | ||||||
|  | +#define PMAC_HD_CTL_RXSH	(1 << 22) | ||||||
|  | + | ||||||
|  | +/* Switch Enable (0=disable, 1=enable) */ | ||||||
|  | +#define GCTL0_SE		0x80000000 | ||||||
|  | +/* Disable MDIO auto polling (0=disable, 1=enable) */ | ||||||
|  | +#define PX_CTL_DMDIO		0x00400000 | ||||||
|  | + | ||||||
|  | +/* MDC clock divider, clock = 25MHz/((MDC_CLOCK + 1) * 2) */ | ||||||
|  | +#define MDC_CLOCK_MASK		0xff000000 | ||||||
|  | +#define MDC_CLOCK_OFFSET	24 | ||||||
|  | + | ||||||
|  | +/* register information for the gbit's MDIO bus */ | ||||||
|  | +#define MDIO_XR9_REQUEST	0x00008000 | ||||||
|  | +#define MDIO_XR9_READ		0x00000800 | ||||||
|  | +#define MDIO_XR9_WRITE		0x00000400 | ||||||
|  | +#define MDIO_XR9_REG_MASK	0x1f | ||||||
|  | +#define MDIO_XR9_ADDR_MASK	0x1f | ||||||
|  | +#define MDIO_XR9_RD_MASK	0xffff | ||||||
|  | +#define MDIO_XR9_REG_OFFSET	0 | ||||||
|  | +#define MDIO_XR9_ADDR_OFFSET	5 | ||||||
|  | +#define MDIO_XR9_WR_OFFSET	16 | ||||||
|  |   | ||||||
|  | +#define LTQ_DMA_ETOP	((of_machine_is_compatible("lantiq,ase")) ? \ | ||||||
|  | +			(INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0)) | ||||||
|  | + | ||||||
|  | +/* the newer xway socks have a embedded 3/7 port gbit multiplexer */ | ||||||
|  |  #define ltq_etop_r32(x)		ltq_r32(ltq_etop_membase + (x)) | ||||||
|  |  #define ltq_etop_w32(x, y)	ltq_w32(x, ltq_etop_membase + (y)) | ||||||
|  |  #define ltq_etop_w32_mask(x, y, z)	\ | ||||||
|  |  		ltq_w32_mask(x, y, ltq_etop_membase + (z)) | ||||||
|  |   | ||||||
|  | -#define DRV_VERSION	"1.0" | ||||||
|  | +#define ltq_gbit_r32(x)		ltq_r32(ltq_gbit_membase + (x)) | ||||||
|  | +#define ltq_gbit_w32(x, y)	ltq_w32(x, ltq_gbit_membase + (y)) | ||||||
|  | +#define ltq_gbit_w32_mask(x, y, z)	\ | ||||||
|  | +		ltq_w32_mask(x, y, ltq_gbit_membase + (z)) | ||||||
|  | + | ||||||
|  | +#define DRV_VERSION	"1.2" | ||||||
|  |   | ||||||
|  |  static void __iomem *ltq_etop_membase; | ||||||
|  | +static void __iomem *ltq_gbit_membase; | ||||||
|  |   | ||||||
|  |  struct ltq_etop_chan { | ||||||
|  | -	int idx; | ||||||
|  |  	int tx_free; | ||||||
|  | +	int irq; | ||||||
|  |  	struct net_device *netdev; | ||||||
|  |  	struct napi_struct napi; | ||||||
|  |  	struct ltq_dma_channel dma; | ||||||
|  | @@ -88,23 +140,36 @@ struct ltq_etop_chan { | ||||||
|  |  struct ltq_etop_priv { | ||||||
|  |  	struct net_device *netdev; | ||||||
|  |  	struct platform_device *pdev; | ||||||
|  | -	struct ltq_eth_data *pldata; | ||||||
|  |  	struct resource *res; | ||||||
|  |   | ||||||
|  |  	struct mii_bus *mii_bus; | ||||||
|  |   | ||||||
|  | -	struct ltq_etop_chan ch[MAX_DMA_CHAN]; | ||||||
|  | -	int tx_free[MAX_DMA_CHAN >> 1]; | ||||||
|  | +	struct ltq_etop_chan txch; | ||||||
|  | +	struct ltq_etop_chan rxch; | ||||||
|  |   | ||||||
|  | -	spinlock_t lock; | ||||||
|  | +	int tx_irq; | ||||||
|  | +	int rx_irq; | ||||||
|  | + | ||||||
|  | +	unsigned char mac[6]; | ||||||
|  | +	phy_interface_t mii_mode; | ||||||
|  | +  | ||||||
|  | + 	spinlock_t lock; | ||||||
|  | + | ||||||
|  | +	struct clk *clk_ppe; | ||||||
|  | +	struct clk *clk_switch; | ||||||
|  | +	struct clk *clk_ephy; | ||||||
|  | +	struct clk *clk_ephycgu; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, | ||||||
|  | +				int phy_reg, u16 phy_data); | ||||||
|  | + | ||||||
|  |  static int | ||||||
|  |  ltq_etop_alloc_skb(struct ltq_etop_chan *ch) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(ch->netdev); | ||||||
|  |   | ||||||
|  | -	ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN); | ||||||
|  | +	ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN); | ||||||
|  |  	if (!ch->skb[ch->dma.desc]) | ||||||
|  |  		return -ENOMEM; | ||||||
|  |  	ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(&priv->pdev->dev, | ||||||
|  | @@ -139,8 +204,11 @@ ltq_etop_hw_receive(struct ltq_etop_chan | ||||||
|  |  	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |   | ||||||
|  |  	skb_put(skb, len); | ||||||
|  | +	skb->dev = ch->netdev; | ||||||
|  |  	skb->protocol = eth_type_trans(skb, ch->netdev); | ||||||
|  |  	netif_receive_skb(skb); | ||||||
|  | +	ch->netdev->stats.rx_packets++; | ||||||
|  | +	ch->netdev->stats.rx_bytes += len; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | @@ -148,7 +216,9 @@ ltq_etop_poll_rx(struct napi_struct *nap | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_chan *ch = container_of(napi, | ||||||
|  |  				struct ltq_etop_chan, napi); | ||||||
|  | +	struct ltq_etop_priv *priv = netdev_priv(ch->netdev); | ||||||
|  |  	int work_done = 0; | ||||||
|  | +	unsigned long flags; | ||||||
|  |   | ||||||
|  |  	while (work_done < budget) { | ||||||
|  |  		struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; | ||||||
|  | @@ -160,7 +230,9 @@ ltq_etop_poll_rx(struct napi_struct *nap | ||||||
|  |  	} | ||||||
|  |  	if (work_done < budget) { | ||||||
|  |  		napi_complete_done(&ch->napi, work_done); | ||||||
|  | +		spin_lock_irqsave(&priv->lock, flags); | ||||||
|  |  		ltq_dma_ack_irq(&ch->dma); | ||||||
|  | +		spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |  	} | ||||||
|  |  	return work_done; | ||||||
|  |  } | ||||||
|  | @@ -172,12 +244,14 @@ ltq_etop_poll_tx(struct napi_struct *nap | ||||||
|  |  		container_of(napi, struct ltq_etop_chan, napi); | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(ch->netdev); | ||||||
|  |  	struct netdev_queue *txq = | ||||||
|  | -		netdev_get_tx_queue(ch->netdev, ch->idx >> 1); | ||||||
|  | +		netdev_get_tx_queue(ch->netdev, ch->dma.nr >> 1); | ||||||
|  |  	unsigned long flags; | ||||||
|  |   | ||||||
|  |  	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  |  	while ((ch->dma.desc_base[ch->tx_free].ctl & | ||||||
|  |  			(LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) { | ||||||
|  | +		ch->netdev->stats.tx_packets++; | ||||||
|  | +		ch->netdev->stats.tx_bytes += ch->skb[ch->tx_free]->len; | ||||||
|  |  		dev_kfree_skb_any(ch->skb[ch->tx_free]); | ||||||
|  |  		ch->skb[ch->tx_free] = NULL; | ||||||
|  |  		memset(&ch->dma.desc_base[ch->tx_free], 0, | ||||||
|  | @@ -190,7 +264,9 @@ ltq_etop_poll_tx(struct napi_struct *nap | ||||||
|  |  	if (netif_tx_queue_stopped(txq)) | ||||||
|  |  		netif_tx_start_queue(txq); | ||||||
|  |  	napi_complete(&ch->napi); | ||||||
|  | +	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  |  	ltq_dma_ack_irq(&ch->dma); | ||||||
|  | +	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |  	return 1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -198,9 +274,10 @@ static irqreturn_t | ||||||
|  |  ltq_etop_dma_irq(int irq, void *_priv) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = _priv; | ||||||
|  | -	int ch = irq - LTQ_DMA_CH0_INT; | ||||||
|  | - | ||||||
|  | -	napi_schedule(&priv->ch[ch].napi); | ||||||
|  | +	if (irq == priv->txch.dma.irq) | ||||||
|  | +		napi_schedule(&priv->txch.napi); | ||||||
|  | +	else | ||||||
|  | +		napi_schedule(&priv->rxch.napi); | ||||||
|  |  	return IRQ_HANDLED; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -212,7 +289,7 @@ ltq_etop_free_channel(struct net_device | ||||||
|  |  	ltq_dma_free(&ch->dma); | ||||||
|  |  	if (ch->dma.irq) | ||||||
|  |  		free_irq(ch->dma.irq, priv); | ||||||
|  | -	if (IS_RX(ch->idx)) { | ||||||
|  | +	if (ch == &priv->txch) { | ||||||
|  |  		int desc; | ||||||
|  |  		for (desc = 0; desc < LTQ_DESC_NUM; desc++) | ||||||
|  |  			dev_kfree_skb_any(ch->skb[ch->dma.desc]); | ||||||
|  | @@ -223,66 +300,135 @@ static void | ||||||
|  |  ltq_etop_hw_exit(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  |   | ||||||
|  | -	ltq_pmu_disable(PMU_PPE); | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) | ||||||
|  | -		if (IS_TX(i) || IS_RX(i)) | ||||||
|  | -			ltq_etop_free_channel(dev, &priv->ch[i]); | ||||||
|  | +	clk_disable(priv->clk_ppe); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) | ||||||
|  | +		clk_disable(priv->clk_switch); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +		clk_disable(priv->clk_ephy); | ||||||
|  | +		clk_disable(priv->clk_ephycgu); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ltq_etop_free_channel(dev, &priv->txch); | ||||||
|  | +	ltq_etop_free_channel(dev, &priv->rxch); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +ltq_etop_gbit_init(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | + | ||||||
|  | +	clk_enable(priv->clk_switch); | ||||||
|  | + | ||||||
|  | +	/* enable gbit port0 on the SoC */ | ||||||
|  | +	ltq_gbit_w32_mask((1 << 17), (1 << 18), LTQ_GBIT_P0_CTL); | ||||||
|  | + | ||||||
|  | +	ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0); | ||||||
|  | +	/* disable MDIO auto polling mode */ | ||||||
|  | +	ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL); | ||||||
|  | +	/* set 1522 packet size */ | ||||||
|  | +	ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0); | ||||||
|  | +	/* disable pmac & dmac headers */ | ||||||
|  | +	ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0, | ||||||
|  | +		LTQ_GBIT_PMAC_HD_CTL); | ||||||
|  | +	/* Due to traffic halt when burst length 8, | ||||||
|  | +		replace default IPG value with 0x3B */ | ||||||
|  | +	ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG); | ||||||
|  | +	/* set mdc clock to 2.5 MHz */ | ||||||
|  | +	ltq_gbit_w32_mask(MDC_CLOCK_MASK, 4 << MDC_CLOCK_OFFSET, | ||||||
|  | +		LTQ_GBIT_RGMII_CTL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  ltq_etop_hw_init(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  | +	phy_interface_t mii_mode = priv->mii_mode; | ||||||
|  |   | ||||||
|  | -	ltq_pmu_enable(PMU_PPE); | ||||||
|  | +	clk_enable(priv->clk_ppe); | ||||||
|  |   | ||||||
|  | -	switch (priv->pldata->mii_mode) { | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		ltq_etop_gbit_init(dev); | ||||||
|  | +		/* force the etops link to the gbit to MII */ | ||||||
|  | +		mii_mode = PHY_INTERFACE_MODE_MII; | ||||||
|  | +	} | ||||||
|  | +	ltq_etop_w32_mask(MDIO_CFG_MASK, 0, LTQ_ETOP_MDIO_CFG); | ||||||
|  | +	ltq_etop_w32_mask(MAC_CFG_MASK, MAC_CFG_CGEN | MAC_CFG_DUPLEX | | ||||||
|  | +			MAC_CFG_SPEED | MAC_CFG_LINK, LTQ_ETOP_MAC_CFG); | ||||||
|  | + | ||||||
|  | +	switch (mii_mode) { | ||||||
|  |  	case PHY_INTERFACE_MODE_RMII: | ||||||
|  | -		ltq_etop_w32_mask(ETOP_MII_MASK, | ||||||
|  | -			ETOP_MII_REVERSE, LTQ_ETOP_CFG); | ||||||
|  | +		ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_REMII0 | ETOP_CFG_OFF1 | | ||||||
|  | +			ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG); | ||||||
|  |  		break; | ||||||
|  |   | ||||||
|  |  	case PHY_INTERFACE_MODE_MII: | ||||||
|  | -		ltq_etop_w32_mask(ETOP_MII_MASK, | ||||||
|  | -			ETOP_MII_NORMAL, LTQ_ETOP_CFG); | ||||||
|  | +		ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_OFF1 | | ||||||
|  | +			ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG); | ||||||
|  |  		break; | ||||||
|  |   | ||||||
|  |  	default: | ||||||
|  | +		if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +			clk_enable(priv->clk_ephy); | ||||||
|  | +			/* disable external MII */ | ||||||
|  | +			ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG); | ||||||
|  | +			/* enable clock for internal PHY */ | ||||||
|  | +			clk_enable(priv->clk_ephycgu); | ||||||
|  | +			/* we need to write this magic to the internal phy to | ||||||
|  | +			   make it work */ | ||||||
|  | +			ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020); | ||||||
|  | +			pr_info("Selected EPHY mode\n"); | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  |  		netdev_err(dev, "unknown mii mode %d\n", | ||||||
|  | -			priv->pldata->mii_mode); | ||||||
|  | +			mii_mode); | ||||||
|  |  		return -ENOTSUPP; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	/* enable crc generation */ | ||||||
|  | -	ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +ltq_etop_dma_init(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | +	int tx = priv->tx_irq - LTQ_DMA_ETOP; | ||||||
|  | +	int rx = priv->rx_irq - LTQ_DMA_ETOP; | ||||||
|  | +	int err; | ||||||
|  |   | ||||||
|  |  	ltq_dma_init_port(DMA_PORT_ETOP); | ||||||
|  |   | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		int irq = LTQ_DMA_CH0_INT + i; | ||||||
|  | -		struct ltq_etop_chan *ch = &priv->ch[i]; | ||||||
|  | - | ||||||
|  | -		ch->idx = ch->dma.nr = i; | ||||||
|  | -		ch->dma.dev = &priv->pdev->dev; | ||||||
|  | - | ||||||
|  | -		if (IS_TX(i)) { | ||||||
|  | -			ltq_dma_alloc_tx(&ch->dma); | ||||||
|  | -			request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv); | ||||||
|  | -		} else if (IS_RX(i)) { | ||||||
|  | -			ltq_dma_alloc_rx(&ch->dma); | ||||||
|  | -			for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM; | ||||||
|  | -					ch->dma.desc++) | ||||||
|  | -				if (ltq_etop_alloc_skb(ch)) | ||||||
|  | -					return -ENOMEM; | ||||||
|  | -			ch->dma.desc = 0; | ||||||
|  | -			request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv); | ||||||
|  | +	priv->txch.dma.nr = tx; | ||||||
|  | +	priv->txch.dma.dev = &priv->pdev->dev; | ||||||
|  | +	ltq_dma_alloc_tx(&priv->txch.dma); | ||||||
|  | +	err = request_irq(priv->tx_irq, ltq_etop_dma_irq, 0, "eth_tx", priv); | ||||||
|  | +	if (err) { | ||||||
|  | +		netdev_err(dev, "failed to allocate tx irq\n"); | ||||||
|  | +		goto err_out; | ||||||
|  | +	} | ||||||
|  | +	priv->txch.dma.irq = priv->tx_irq; | ||||||
|  | + | ||||||
|  | +	priv->rxch.dma.nr = rx; | ||||||
|  | +	priv->rxch.dma.dev = &priv->pdev->dev; | ||||||
|  | +	ltq_dma_alloc_rx(&priv->rxch.dma); | ||||||
|  | +	for (priv->rxch.dma.desc = 0; priv->rxch.dma.desc < LTQ_DESC_NUM; | ||||||
|  | +			priv->rxch.dma.desc++) { | ||||||
|  | +		if (ltq_etop_alloc_skb(&priv->rxch)) { | ||||||
|  | +			netdev_err(dev, "failed to allocate skbs\n"); | ||||||
|  | +			err = -ENOMEM; | ||||||
|  | +			goto err_out; | ||||||
|  |  		} | ||||||
|  | -		ch->dma.irq = irq; | ||||||
|  |  	} | ||||||
|  | -	return 0; | ||||||
|  | +	priv->rxch.dma.desc = 0; | ||||||
|  | +	err = request_irq(priv->rx_irq, ltq_etop_dma_irq, 0, "eth_rx", priv); | ||||||
|  | +	if (err) | ||||||
|  | +		netdev_err(dev, "failed to allocate rx irq\n"); | ||||||
|  | +	else | ||||||
|  | +		priv->rxch.dma.irq = priv->rx_irq; | ||||||
|  | +err_out: | ||||||
|  | +	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void | ||||||
|  | @@ -301,6 +447,39 @@ static const struct ethtool_ops ltq_etop | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | +ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr, | ||||||
|  | +		int phy_reg, u16 phy_data) | ||||||
|  | +{ | ||||||
|  | +	u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE | | ||||||
|  | +		(phy_data << MDIO_XR9_WR_OFFSET) | | ||||||
|  | +		((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) | | ||||||
|  | +		((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET); | ||||||
|  | + | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL); | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg) | ||||||
|  | +{ | ||||||
|  | +	u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ | | ||||||
|  | +		((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) | | ||||||
|  | +		((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET); | ||||||
|  | + | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL); | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK; | ||||||
|  | +	return val; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  |  ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data) | ||||||
|  |  { | ||||||
|  |  	u32 val = MDIO_REQUEST | | ||||||
|  | @@ -308,9 +487,9 @@ ltq_etop_mdio_wr(struct mii_bus *bus, in | ||||||
|  |  		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) | | ||||||
|  |  		phy_data; | ||||||
|  |   | ||||||
|  | -	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) | ||||||
|  | +	while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) | ||||||
|  |  		; | ||||||
|  | -	ltq_etop_w32(val, LTQ_ETOP_MDIO); | ||||||
|  | +	ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -321,12 +500,12 @@ ltq_etop_mdio_rd(struct mii_bus *bus, in | ||||||
|  |  		((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) | | ||||||
|  |  		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET); | ||||||
|  |   | ||||||
|  | -	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) | ||||||
|  | +	while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) | ||||||
|  |  		; | ||||||
|  | -	ltq_etop_w32(val, LTQ_ETOP_MDIO); | ||||||
|  | -	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) | ||||||
|  | +	ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC); | ||||||
|  | +	while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) | ||||||
|  |  		; | ||||||
|  | -	val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK; | ||||||
|  | +	val = ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_VAL_MASK; | ||||||
|  |  	return val; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -342,7 +521,10 @@ ltq_etop_mdio_probe(struct net_device *d | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  |  	struct phy_device *phydev; | ||||||
|  |   | ||||||
|  | -	phydev = phy_find_first(priv->mii_bus); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase")) | ||||||
|  | +		phydev = mdiobus_get_phy(priv->mii_bus, 8); | ||||||
|  | +	else | ||||||
|  | +		phydev = mdiobus_get_phy(priv->mii_bus, 0); | ||||||
|  |   | ||||||
|  |  	if (!phydev) { | ||||||
|  |  		netdev_err(dev, "no PHY found\n"); | ||||||
|  | @@ -350,14 +532,17 @@ ltq_etop_mdio_probe(struct net_device *d | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	phydev = phy_connect(dev, phydev_name(phydev), | ||||||
|  | -			     <q_etop_mdio_link, priv->pldata->mii_mode); | ||||||
|  | +			     <q_etop_mdio_link, priv->mii_mode); | ||||||
|  |   | ||||||
|  |  	if (IS_ERR(phydev)) { | ||||||
|  |  		netdev_err(dev, "Could not attach to PHY\n"); | ||||||
|  |  		return PTR_ERR(phydev); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	phy_set_max_speed(phydev, SPEED_100); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) | ||||||
|  | +		phy_set_max_speed(phydev, SPEED_1000); | ||||||
|  | +	else | ||||||
|  | +		phy_set_max_speed(phydev, SPEED_100); | ||||||
|  |   | ||||||
|  |  	phy_attached_info(phydev); | ||||||
|  |   | ||||||
|  | @@ -378,8 +563,13 @@ ltq_etop_mdio_init(struct net_device *de | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	priv->mii_bus->priv = dev; | ||||||
|  | -	priv->mii_bus->read = ltq_etop_mdio_rd; | ||||||
|  | -	priv->mii_bus->write = ltq_etop_mdio_wr; | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		priv->mii_bus->read = ltq_etop_mdio_rd_xr9; | ||||||
|  | +		priv->mii_bus->write = ltq_etop_mdio_wr_xr9; | ||||||
|  | +	} else { | ||||||
|  | +		priv->mii_bus->read = ltq_etop_mdio_rd; | ||||||
|  | +		priv->mii_bus->write = ltq_etop_mdio_wr; | ||||||
|  | +	} | ||||||
|  |  	priv->mii_bus->name = "ltq_mii"; | ||||||
|  |  	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", | ||||||
|  |  		priv->pdev->name, priv->pdev->id); | ||||||
|  | @@ -416,18 +606,21 @@ static int | ||||||
|  |  ltq_etop_open(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  | +	unsigned long flags; | ||||||
|  |   | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		struct ltq_etop_chan *ch = &priv->ch[i]; | ||||||
|  | +	napi_enable(&priv->txch.napi); | ||||||
|  | +	napi_enable(&priv->rxch.napi); | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  | +	ltq_dma_open(&priv->txch.dma); | ||||||
|  | +	ltq_dma_enable_irq(&priv->txch.dma); | ||||||
|  | +	ltq_dma_open(&priv->rxch.dma); | ||||||
|  | +	ltq_dma_enable_irq(&priv->rxch.dma); | ||||||
|  | +	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  | + | ||||||
|  | +	if (dev->phydev) | ||||||
|  | +		phy_start(dev->phydev); | ||||||
|  |   | ||||||
|  | -		if (!IS_TX(i) && (!IS_RX(i))) | ||||||
|  | -			continue; | ||||||
|  | -		ltq_dma_open(&ch->dma); | ||||||
|  | -		ltq_dma_enable_irq(&ch->dma); | ||||||
|  | -		napi_enable(&ch->napi); | ||||||
|  | -	} | ||||||
|  | -	phy_start(dev->phydev); | ||||||
|  |  	netif_tx_start_all_queues(dev); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -436,18 +629,19 @@ static int | ||||||
|  |  ltq_etop_stop(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  | +	unsigned long flags; | ||||||
|  |   | ||||||
|  |  	netif_tx_stop_all_queues(dev); | ||||||
|  | -	phy_stop(dev->phydev); | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		struct ltq_etop_chan *ch = &priv->ch[i]; | ||||||
|  | - | ||||||
|  | -		if (!IS_RX(i) && !IS_TX(i)) | ||||||
|  | -			continue; | ||||||
|  | -		napi_disable(&ch->napi); | ||||||
|  | -		ltq_dma_close(&ch->dma); | ||||||
|  | -	} | ||||||
|  | +	if (dev->phydev) | ||||||
|  | +		phy_stop(dev->phydev); | ||||||
|  | +	napi_disable(&priv->txch.napi); | ||||||
|  | +	napi_disable(&priv->rxch.napi); | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  | +	ltq_dma_close(&priv->txch.dma); | ||||||
|  | +	ltq_dma_close(&priv->rxch.dma); | ||||||
|  | +	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -457,16 +651,16 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |  	int queue = skb_get_queue_mapping(skb); | ||||||
|  |  	struct netdev_queue *txq = netdev_get_tx_queue(dev, queue); | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1]; | ||||||
|  | -	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; | ||||||
|  | -	int len; | ||||||
|  | +	struct ltq_dma_desc *desc = | ||||||
|  | +		&priv->txch.dma.desc_base[priv->txch.dma.desc]; | ||||||
|  |  	unsigned long flags; | ||||||
|  |  	u32 byte_offset; | ||||||
|  | +	int len; | ||||||
|  |   | ||||||
|  |  	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; | ||||||
|  |   | ||||||
|  | -	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) { | ||||||
|  | -		dev_kfree_skb_any(skb); | ||||||
|  | +	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || | ||||||
|  | +			priv->txch.skb[priv->txch.dma.desc]) { | ||||||
|  |  		netdev_err(dev, "tx ring full\n"); | ||||||
|  |  		netif_tx_stop_queue(txq); | ||||||
|  |  		return NETDEV_TX_BUSY; | ||||||
|  | @@ -474,7 +668,7 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |   | ||||||
|  |  	/* dma needs to start on a 16 byte aligned address */ | ||||||
|  |  	byte_offset = CPHYSADDR(skb->data) % 16; | ||||||
|  | -	ch->skb[ch->dma.desc] = skb; | ||||||
|  | +	priv->txch.skb[priv->txch.dma.desc] = skb; | ||||||
|  |   | ||||||
|  |  	netif_trans_update(dev); | ||||||
|  |   | ||||||
|  | @@ -484,11 +678,11 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |  	wmb(); | ||||||
|  |  	desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP | | ||||||
|  |  		LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK); | ||||||
|  | -	ch->dma.desc++; | ||||||
|  | -	ch->dma.desc %= LTQ_DESC_NUM; | ||||||
|  | +	priv->txch.dma.desc++; | ||||||
|  | +	priv->txch.dma.desc %= LTQ_DESC_NUM; | ||||||
|  |  	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |   | ||||||
|  | -	if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN) | ||||||
|  | +	if (priv->txch.dma.desc_base[priv->txch.dma.desc].ctl & LTQ_DMA_OWN) | ||||||
|  |  		netif_tx_stop_queue(txq); | ||||||
|  |   | ||||||
|  |  	return NETDEV_TX_OK; | ||||||
|  | @@ -499,11 +693,14 @@ ltq_etop_change_mtu(struct net_device *d | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  |  	unsigned long flags; | ||||||
|  | +	int max; | ||||||
|  |   | ||||||
|  |  	dev->mtu = new_mtu; | ||||||
|  |   | ||||||
|  | +	max = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN; | ||||||
|  | + | ||||||
|  |  	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  | -	ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, LTQ_ETOP_IGPLEN); | ||||||
|  | +	ltq_etop_w32((ETOP_PLEN_UNDER << 16) | max, LTQ_ETOP_IGPLEN); | ||||||
|  |  	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  | @@ -556,6 +753,9 @@ ltq_etop_init(struct net_device *dev) | ||||||
|  |  	if (err) | ||||||
|  |  		goto err_hw; | ||||||
|  |  	ltq_etop_change_mtu(dev, 1500); | ||||||
|  | +	err = ltq_etop_dma_init(dev); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_hw; | ||||||
|  |   | ||||||
|  |  	memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr)); | ||||||
|  |  	if (!is_valid_ether_addr(mac.sa_data)) { | ||||||
|  | @@ -573,9 +773,10 @@ ltq_etop_init(struct net_device *dev) | ||||||
|  |  		dev->addr_assign_type = NET_ADDR_RANDOM; | ||||||
|  |   | ||||||
|  |  	ltq_etop_set_multicast_list(dev); | ||||||
|  | -	err = ltq_etop_mdio_init(dev); | ||||||
|  | -	if (err) | ||||||
|  | -		goto err_netdev; | ||||||
|  | +	if (!ltq_etop_mdio_init(dev)) | ||||||
|  | +		dev->ethtool_ops = <q_etop_ethtool_ops; | ||||||
|  | +	else | ||||||
|  | +		pr_warn("etop: mdio probe failed\n");; | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  |  err_netdev: | ||||||
|  | @@ -595,6 +796,9 @@ ltq_etop_tx_timeout(struct net_device *d | ||||||
|  |  	err = ltq_etop_hw_init(dev); | ||||||
|  |  	if (err) | ||||||
|  |  		goto err_hw; | ||||||
|  | +	err = ltq_etop_dma_init(dev); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_hw; | ||||||
|  |  	netif_trans_update(dev); | ||||||
|  |  	netif_wake_queue(dev); | ||||||
|  |  	return; | ||||||
|  | @@ -618,14 +822,18 @@ static const struct net_device_ops ltq_e | ||||||
|  |  	.ndo_tx_timeout = ltq_etop_tx_timeout, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -static int __init | ||||||
|  | -ltq_etop_probe(struct platform_device *pdev) | ||||||
|  | +static int ltq_etop_probe(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  |  	struct net_device *dev; | ||||||
|  |  	struct ltq_etop_priv *priv; | ||||||
|  | -	struct resource *res; | ||||||
|  | +	struct resource *res, *gbit_res, irqres[2]; | ||||||
|  |  	int err; | ||||||
|  | -	int i; | ||||||
|  | + | ||||||
|  | +	err = of_irq_to_resource_table(pdev->dev.of_node, irqres, 2); | ||||||
|  | +	if (err != 2) { | ||||||
|  | +		dev_err(&pdev->dev, "failed to get etop irqs\n"); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  |  	if (!res) { | ||||||
|  | @@ -651,31 +859,62 @@ ltq_etop_probe(struct platform_device *p | ||||||
|  |  		goto err_out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4); | ||||||
|  | -	if (!dev) { | ||||||
|  | -		err = -ENOMEM; | ||||||
|  | -		goto err_out; | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||||||
|  | +		if (!gbit_res) { | ||||||
|  | +			dev_err(&pdev->dev, "failed to get gbit resource\n"); | ||||||
|  | +			err = -ENOENT; | ||||||
|  | +			goto err_out; | ||||||
|  | +		} | ||||||
|  | +		ltq_gbit_membase = devm_ioremap(&pdev->dev, | ||||||
|  | +			gbit_res->start, resource_size(gbit_res)); | ||||||
|  | +		if (!ltq_gbit_membase) { | ||||||
|  | +			dev_err(&pdev->dev, "failed to remap gigabit switch %d\n", | ||||||
|  | +				pdev->id); | ||||||
|  | +			err = -ENOMEM; | ||||||
|  | +			goto err_out; | ||||||
|  | +		} | ||||||
|  |  	} | ||||||
|  | + | ||||||
|  | +	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4); | ||||||
|  |  	strcpy(dev->name, "eth%d"); | ||||||
|  |  	dev->netdev_ops = <q_eth_netdev_ops; | ||||||
|  | -	dev->ethtool_ops = <q_etop_ethtool_ops; | ||||||
|  |  	priv = netdev_priv(dev); | ||||||
|  |  	priv->res = res; | ||||||
|  |  	priv->pdev = pdev; | ||||||
|  | -	priv->pldata = dev_get_platdata(&pdev->dev); | ||||||
|  |  	priv->netdev = dev; | ||||||
|  | +	priv->tx_irq = irqres[0].start; | ||||||
|  | +	priv->rx_irq = irqres[1].start; | ||||||
|  | +	err = of_get_phy_mode(pdev->dev.of_node, &priv->mii_mode); | ||||||
|  | +	if (err) | ||||||
|  | +		pr_err("Can't find phy-mode for port\n"); | ||||||
|  | + | ||||||
|  | +	of_get_mac_address(pdev->dev.of_node, priv->mac); | ||||||
|  | + | ||||||
|  | +	priv->clk_ppe = clk_get(&pdev->dev, NULL); | ||||||
|  | +	if (IS_ERR(priv->clk_ppe)) | ||||||
|  | +		return PTR_ERR(priv->clk_ppe); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		priv->clk_switch = clk_get(&pdev->dev, "switch"); | ||||||
|  | +		if (IS_ERR(priv->clk_switch)) | ||||||
|  | +			return PTR_ERR(priv->clk_switch); | ||||||
|  | +	} | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +		priv->clk_ephy = clk_get(&pdev->dev, "ephy"); | ||||||
|  | +		if (IS_ERR(priv->clk_ephy)) | ||||||
|  | +			return PTR_ERR(priv->clk_ephy); | ||||||
|  | +		priv->clk_ephycgu = clk_get(&pdev->dev, "ephycgu"); | ||||||
|  | +		if (IS_ERR(priv->clk_ephycgu)) | ||||||
|  | +			return PTR_ERR(priv->clk_ephycgu); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	spin_lock_init(&priv->lock); | ||||||
|  |  	SET_NETDEV_DEV(dev, &pdev->dev); | ||||||
|  |   | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		if (IS_TX(i)) | ||||||
|  | -			netif_napi_add(dev, &priv->ch[i].napi, | ||||||
|  | -				ltq_etop_poll_tx, 8); | ||||||
|  | -		else if (IS_RX(i)) | ||||||
|  | -			netif_napi_add(dev, &priv->ch[i].napi, | ||||||
|  | -				ltq_etop_poll_rx, 32); | ||||||
|  | -		priv->ch[i].netdev = dev; | ||||||
|  | -	} | ||||||
|  | +	netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8); | ||||||
|  | +	netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32); | ||||||
|  | +	priv->txch.netdev = dev; | ||||||
|  | +	priv->rxch.netdev = dev; | ||||||
|  |   | ||||||
|  |  	err = register_netdev(dev); | ||||||
|  |  	if (err) | ||||||
|  | @@ -704,31 +943,22 @@ ltq_etop_remove(struct platform_device * | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static const struct of_device_id ltq_etop_match[] = { | ||||||
|  | +	{ .compatible = "lantiq,etop-xway" }, | ||||||
|  | +	{}, | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, ltq_etop_match); | ||||||
|  | + | ||||||
|  |  static struct platform_driver ltq_mii_driver = { | ||||||
|  | +	.probe = ltq_etop_probe, | ||||||
|  |  	.remove = ltq_etop_remove, | ||||||
|  |  	.driver = { | ||||||
|  |  		.name = "ltq_etop", | ||||||
|  | +		.of_match_table = ltq_etop_match, | ||||||
|  |  	}, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -int __init | ||||||
|  | -init_ltq_etop(void) | ||||||
|  | -{ | ||||||
|  | -	int ret = platform_driver_probe(<q_mii_driver, ltq_etop_probe); | ||||||
|  | - | ||||||
|  | -	if (ret) | ||||||
|  | -		pr_err("ltq_etop: Error registering platform driver!"); | ||||||
|  | -	return ret; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static void __exit | ||||||
|  | -exit_ltq_etop(void) | ||||||
|  | -{ | ||||||
|  | -	platform_driver_unregister(<q_mii_driver); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -module_init(init_ltq_etop); | ||||||
|  | -module_exit(exit_ltq_etop); | ||||||
|  | +module_platform_driver(ltq_mii_driver); | ||||||
|  |   | ||||||
|  |  MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||||||
|  |  MODULE_DESCRIPTION("Lantiq SoC ETOP"); | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,218 @@ | |||||||
|  | From f8c5db89e793a4bc6c1e87bd7b3a5cec16b75bc3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Wed, 10 Sep 2014 22:42:14 +0200 | ||||||
|  | Subject: [PATCH 35/36] owrt: lantiq: wifi and ethernet eeprom handling | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   3 + | ||||||
|  |  arch/mips/lantiq/xway/Makefile                     |   3 + | ||||||
|  |  arch/mips/lantiq/xway/ath5k_eep.c                  | 136 +++++++++++++++++++++ | ||||||
|  |  arch/mips/lantiq/xway/eth_mac.c                    |  25 ++++ | ||||||
|  |  drivers/net/ethernet/lantiq_etop.c                 |   6 +- | ||||||
|  |  5 files changed, 172 insertions(+), 1 deletion(-) | ||||||
|  |  create mode 100644 arch/mips/lantiq/xway/ath5k_eep.c | ||||||
|  |  create mode 100644 arch/mips/lantiq/xway/eth_mac.c | ||||||
|  |  | ||||||
|  | --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | ||||||
|  | @@ -102,5 +102,8 @@ int xrx200_gphy_boot(struct device *dev, | ||||||
|  |  extern void ltq_pmu_enable(unsigned int module); | ||||||
|  |  extern void ltq_pmu_disable(unsigned int module); | ||||||
|  |   | ||||||
|  | +/* allow the ethernet driver to load a flash mapped mac addr */ | ||||||
|  | +const u8* ltq_get_eth_mac(void); | ||||||
|  | + | ||||||
|  |  #endif /* CONFIG_SOC_TYPE_XWAY */ | ||||||
|  |  #endif /* _LTQ_XWAY_H__ */ | ||||||
|  | --- a/arch/mips/lantiq/xway/Makefile | ||||||
|  | +++ b/arch/mips/lantiq/xway/Makefile | ||||||
|  | @@ -8,3 +8,6 @@ obj-y += timer.o | ||||||
|  |  endif | ||||||
|  |   | ||||||
|  |  obj-y += vmmc.o | ||||||
|  | + | ||||||
|  | +obj-y += eth_mac.o | ||||||
|  | +obj-$(CONFIG_PCI) += ath5k_eep.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/lantiq/xway/ath5k_eep.c | ||||||
|  | @@ -0,0 +1,136 @@ | ||||||
|  | +/* | ||||||
|  | + *  Copyright (C) 2011 Luca Olivetti <luca@ventoso.org> | ||||||
|  | + *  Copyright (C) 2011 John Crispin <blogic@openwrt.org> | ||||||
|  | + *  Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com> | ||||||
|  | + *  Copyright (C) 2013 Álvaro Fernández Rojas <noltari@gmail.com> | ||||||
|  | + *  Copyright (C) 2013 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us> | ||||||
|  | + *  Copyright (C) 2015 Vittorio Gambaletta <openwrt@vittgam.net> | ||||||
|  | + * | ||||||
|  | + *  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. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/etherdevice.h> | ||||||
|  | +#include <linux/ath5k_platform.h> | ||||||
|  | +#include <linux/pci.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/mtd/mtd.h> | ||||||
|  | +#include <lantiq_soc.h> | ||||||
|  | + | ||||||
|  | +extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev); | ||||||
|  | +struct ath5k_platform_data ath5k_pdata; | ||||||
|  | +static u8 athxk_eeprom_mac[6]; | ||||||
|  | + | ||||||
|  | +static int ath5k_pci_plat_dev_init(struct pci_dev *dev) | ||||||
|  | +{ | ||||||
|  | +	dev->dev.platform_data = &ath5k_pdata; | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ath5k_eep_load; | ||||||
|  | +int __init of_ath5k_eeprom_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct device_node *np = pdev->dev.of_node, *mtd_np = NULL; | ||||||
|  | +	int mac_offset; | ||||||
|  | +	u32 mac_inc = 0; | ||||||
|  | +	int i; | ||||||
|  | +	struct mtd_info *the_mtd; | ||||||
|  | +	size_t flash_readlen; | ||||||
|  | +	const __be32 *list; | ||||||
|  | +	const char *part; | ||||||
|  | +	phandle phandle; | ||||||
|  | + | ||||||
|  | +	list = of_get_property(np, "ath,eep-flash", &i); | ||||||
|  | +	if (!list || (i != (2 * sizeof(*list)))) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	phandle = be32_to_cpup(list++); | ||||||
|  | +	if (phandle) | ||||||
|  | +		mtd_np = of_find_node_by_phandle(phandle); | ||||||
|  | + | ||||||
|  | +	if (!mtd_np) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	part = of_get_property(mtd_np, "label", NULL); | ||||||
|  | +	if (!part) | ||||||
|  | +		part = mtd_np->name; | ||||||
|  | + | ||||||
|  | +	the_mtd = get_mtd_device_nm(part); | ||||||
|  | +	if (IS_ERR(the_mtd)) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	ath5k_pdata.eeprom_data = kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1, GFP_KERNEL); | ||||||
|  | + | ||||||
|  | +	i = mtd_read(the_mtd, be32_to_cpup(list), ATH5K_PLAT_EEP_MAX_WORDS << 1, | ||||||
|  | +		&flash_readlen, (void *) ath5k_pdata.eeprom_data); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) { | ||||||
|  | +		size_t mac_readlen; | ||||||
|  | +		mtd_read(the_mtd, mac_offset, 6, &mac_readlen, | ||||||
|  | +			(void *) athxk_eeprom_mac); | ||||||
|  | +	} | ||||||
|  | +	put_mtd_device(the_mtd); | ||||||
|  | + | ||||||
|  | +	if (((ATH5K_PLAT_EEP_MAX_WORDS<<1) != flash_readlen) || i) { | ||||||
|  | +		dev_err(&pdev->dev, "failed to load eeprom from mtd\n"); | ||||||
|  | +		return -ENODEV; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (of_find_property(np, "ath,eep-swap", NULL)) | ||||||
|  | +		for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS; i++) | ||||||
|  | +			ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]); | ||||||
|  | + | ||||||
|  | +	if (!is_valid_ether_addr(athxk_eeprom_mac) && ltq_get_eth_mac()) | ||||||
|  | +		ether_addr_copy(athxk_eeprom_mac, ltq_get_eth_mac()); | ||||||
|  | + | ||||||
|  | +	if (!is_valid_ether_addr(athxk_eeprom_mac)) { | ||||||
|  | +		dev_warn(&pdev->dev, "using random mac\n"); | ||||||
|  | +		random_ether_addr(athxk_eeprom_mac); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc)) | ||||||
|  | +		athxk_eeprom_mac[5] += mac_inc; | ||||||
|  | + | ||||||
|  | +	ath5k_pdata.macaddr = athxk_eeprom_mac; | ||||||
|  | +	ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init; | ||||||
|  | + | ||||||
|  | +	dev_info(&pdev->dev, "loaded ath5k eeprom\n"); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct of_device_id ath5k_eeprom_ids[] = { | ||||||
|  | +	{ .compatible = "ath5k,eeprom" }, | ||||||
|  | +	{ } | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct platform_driver ath5k_eeprom_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name		= "ath5k,eeprom", | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +		.of_match_table	= of_match_ptr(ath5k_eeprom_ids), | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int __init of_ath5k_eeprom_init(void) | ||||||
|  | +{ | ||||||
|  | +	int ret = platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe); | ||||||
|  | + | ||||||
|  | +	if (ret) | ||||||
|  | +		ath5k_eep_load = 1; | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init of_ath5k_eeprom_init_late(void) | ||||||
|  | +{ | ||||||
|  | +	if (!ath5k_eep_load) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe); | ||||||
|  | +} | ||||||
|  | +late_initcall(of_ath5k_eeprom_init_late); | ||||||
|  | +subsys_initcall(of_ath5k_eeprom_init); | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/lantiq/xway/eth_mac.c | ||||||
|  | @@ -0,0 +1,25 @@ | ||||||
|  | +/* | ||||||
|  | + *  Copyright (C) 2012 John Crispin <blogic@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. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/if_ether.h> | ||||||
|  | + | ||||||
|  | +static u8 eth_mac[6]; | ||||||
|  | +static int eth_mac_set; | ||||||
|  | + | ||||||
|  | +const u8* ltq_get_eth_mac(void) | ||||||
|  | +{ | ||||||
|  | +	return eth_mac; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init setup_ethaddr(char *str) | ||||||
|  | +{ | ||||||
|  | +	eth_mac_set = mac_pton(str, eth_mac); | ||||||
|  | +	return !eth_mac_set; | ||||||
|  | +} | ||||||
|  | +early_param("ethaddr", setup_ethaddr); | ||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -757,7 +757,11 @@ ltq_etop_init(struct net_device *dev) | ||||||
|  |  	if (err) | ||||||
|  |  		goto err_hw; | ||||||
|  |   | ||||||
|  | -	memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr)); | ||||||
|  | +	memcpy(&mac.sa_data, ltq_get_eth_mac(), ETH_ALEN); | ||||||
|  | + | ||||||
|  | +	if (priv->mac && !is_valid_ether_addr(mac.sa_data)) | ||||||
|  | +		memcpy(&mac.sa_data, priv->mac, ETH_ALEN); | ||||||
|  | + | ||||||
|  |  	if (!is_valid_ether_addr(mac.sa_data)) { | ||||||
|  |  		pr_warn("etop: invalid MAC, using random\n"); | ||||||
|  |  		eth_random_addr(mac.sa_data); | ||||||
| @@ -0,0 +1,24 @@ | |||||||
|  | From 9807eb80a1b3bad7a4a89aa6566497bb1cadd6ef Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Fri, 3 Jun 2016 13:12:20 +0200 | ||||||
|  | Subject: [PATCH] arch: mips: increase io_space_limit | ||||||
|  |  | ||||||
|  | this value comes from x86 and breaks some pci devices | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  arch/mips/include/asm/mach-lantiq/spaces.h | 8 ++++++++ | ||||||
|  |  1 file changed, 8 insertions(+) | ||||||
|  |  create mode 100644 arch/mips/include/asm/mach-lantiq/spaces.h | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/spaces.h | ||||||
|  | @@ -0,0 +1,8 @@ | ||||||
|  | +/* SPDX-License-Identifier: GPL-2.0 */ | ||||||
|  | +#ifndef __ASM_MACH_LANTIQ_SPACES_H_ | ||||||
|  | +#define __ASM_MACH_LANTIQ_SPACES_H_ | ||||||
|  | + | ||||||
|  | +#define IO_SPACE_LIMIT  0xffffffff | ||||||
|  | + | ||||||
|  | +#include <asm/mach-generic/spaces.h> | ||||||
|  | +#endif | ||||||
| @@ -0,0 +1,78 @@ | |||||||
|  | From de2cad82c4d0872066f83ce59462603852b47f03 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Date: Fri, 6 Jan 2017 17:55:24 +0100 | ||||||
|  | Subject: [PATCH 2/2] usb: dwc2:  add support for other Lantiq SoCs | ||||||
|  |  | ||||||
|  | The size of the internal RAM of the DesignWare USB controller changed | ||||||
|  | between the different Lantiq SoCs. We have the following sizes: | ||||||
|  |  | ||||||
|  | Amazon + Danube: 8 KByte | ||||||
|  | Amazon SE + arx100: 2 KByte | ||||||
|  | xrx200 + xrx300: 2.5 KByte | ||||||
|  |  | ||||||
|  | For Danube SoC we do not provide the params and let the driver decide | ||||||
|  | to use sane defaults, for the Amazon SE and arx100 we use small fifos | ||||||
|  | and for the xrx200 and xrx300 SCs a little bit bigger periodic fifo. | ||||||
|  | The auto detection of max_transfer_size and max_packet_count should | ||||||
|  | work, so remove it. | ||||||
|  |  | ||||||
|  | Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | --- | ||||||
|  |  drivers/usb/dwc2/platform.c | 46 ++++++++++++++++++++++++++++++++++++++------- | ||||||
|  |  1 file changed, 39 insertions(+), 7 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/usb/dwc2/params.c | ||||||
|  | +++ b/drivers/usb/dwc2/params.c | ||||||
|  | @@ -92,7 +92,14 @@ static void dwc2_set_rk_params(struct dw | ||||||
|  |  	p->power_down = DWC2_POWER_DOWN_PARAM_NONE; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) | ||||||
|  | +static void dwc2_set_ltq_danube_params(struct dwc2_hsotg *hsotg) | ||||||
|  | +{ | ||||||
|  | +	struct dwc2_core_params *p = &hsotg->params; | ||||||
|  | + | ||||||
|  | +	p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void dwc2_set_ltq_ase_params(struct dwc2_hsotg *hsotg) | ||||||
|  |  { | ||||||
|  |  	struct dwc2_core_params *p = &hsotg->params; | ||||||
|  |   | ||||||
|  | @@ -100,12 +107,20 @@ static void dwc2_set_ltq_params(struct d | ||||||
|  |  	p->host_rx_fifo_size = 288; | ||||||
|  |  	p->host_nperio_tx_fifo_size = 128; | ||||||
|  |  	p->host_perio_tx_fifo_size = 96; | ||||||
|  | -	p->max_transfer_size = 65535; | ||||||
|  | -	p->max_packet_count = 511; | ||||||
|  |  	p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << | ||||||
|  |  		GAHBCFG_HBSTLEN_SHIFT; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void dwc2_set_ltq_xrx200_params(struct dwc2_hsotg *hsotg) | ||||||
|  | +{ | ||||||
|  | +	struct dwc2_core_params *p = &hsotg->params; | ||||||
|  | + | ||||||
|  | +	p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; | ||||||
|  | +	p->host_rx_fifo_size = 288; | ||||||
|  | +	p->host_nperio_tx_fifo_size = 128; | ||||||
|  | +	p->host_perio_tx_fifo_size = 136; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg) | ||||||
|  |  { | ||||||
|  |  	struct dwc2_core_params *p = &hsotg->params; | ||||||
|  | @@ -196,8 +211,11 @@ const struct of_device_id dwc2_of_match_ | ||||||
|  |  	{ .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params }, | ||||||
|  |  	{ .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params  }, | ||||||
|  |  	{ .compatible = "rockchip,rk3066-usb", .data = dwc2_set_rk_params }, | ||||||
|  | -	{ .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params }, | ||||||
|  | -	{ .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, | ||||||
|  | +	{ .compatible = "lantiq,danube-usb", .data = &dwc2_set_ltq_danube_params }, | ||||||
|  | +	{ .compatible = "lantiq,ase-usb", .data = &dwc2_set_ltq_ase_params }, | ||||||
|  | +	{ .compatible = "lantiq,arx100-usb", .data = &dwc2_set_ltq_ase_params }, | ||||||
|  | +	{ .compatible = "lantiq,xrx200-usb", .data = &dwc2_set_ltq_xrx200_params }, | ||||||
|  | +	{ .compatible = "lantiq,xrx300-usb", .data = &dwc2_set_ltq_xrx200_params }, | ||||||
|  |  	{ .compatible = "snps,dwc2" }, | ||||||
|  |  	{ .compatible = "samsung,s3c6400-hsotg", | ||||||
|  |  	  .data = dwc2_set_s3c6400_params }, | ||||||
| @@ -0,0 +1,49 @@ | |||||||
|  | From 14909c4e4e836925668e74fc6e0e85ba0283cbf9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Date: Fri, 6 Jan 2017 17:40:12 +0100 | ||||||
|  | Subject: [PATCH 2/2] MIPS: lantiq: improve USB initialization | ||||||
|  |  | ||||||
|  | This adds code to initialize the USB controller and PHY also on Danube, | ||||||
|  | Amazon SE and AR10. This code is based on the Vendor driver from | ||||||
|  | different UGW versions and compared to the hardware documentation. | ||||||
|  |  | ||||||
|  | Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | --- | ||||||
|  |  arch/mips/lantiq/xway/sysctrl.c |  20 +++++++ | ||||||
|  |  2 files changed, 110 insertions(+), 30 deletions(-) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | @@ -248,6 +248,25 @@ static void pmu_disable(struct clk *clk) | ||||||
|  |  		pr_warn("deactivating PMU module failed!"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void usb_set_clock(void) | ||||||
|  | +{ | ||||||
|  | +	unsigned int val = ltq_cgu_r32(ifccr); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar10") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,grx390")) { | ||||||
|  | +		val &= ~0x03; /* XTAL divided by 3 */ | ||||||
|  | +	} else if (of_machine_is_compatible("lantiq,ar9") || | ||||||
|  | +		   of_machine_is_compatible("lantiq,vr9")) { | ||||||
|  | +		/* TODO: this depends on the XTAL frequency */ | ||||||
|  | +		val |= 0x03; /* XTAL divided by 3 */ | ||||||
|  | +	} else if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +		val |= 0x20; /* from XTAL */ | ||||||
|  | +	} else if (of_machine_is_compatible("lantiq,danube")) { | ||||||
|  | +		val |= 0x30; /* 12 MHz, generated from 36 MHz */ | ||||||
|  | +	} | ||||||
|  | +	ltq_cgu_w32(val, ifccr); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* the pci enable helper */ | ||||||
|  |  static int pci_enable(struct clk *clk) | ||||||
|  |  { | ||||||
|  | @@ -585,4 +604,5 @@ void __init ltq_soc_init(void) | ||||||
|  |  		clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); | ||||||
|  |  		clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0); | ||||||
|  |  	} | ||||||
|  | +	usb_set_clock(); | ||||||
|  |  } | ||||||
							
								
								
									
										93
									
								
								target/linux/lantiq/patches-5.15/0101-find_active_root.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								target/linux/lantiq/patches-5.15/0101-find_active_root.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | --- a/drivers/mtd/parsers/ofpart_core.c | ||||||
|  | +++ b/drivers/mtd/parsers/ofpart_core.c | ||||||
|  | @@ -38,6 +38,38 @@ static bool node_has_compatible(struct d | ||||||
|  |  	return of_get_property(pp, "compatible", NULL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static uint8_t * brnboot_get_selected_root_part(struct mtd_info *master, | ||||||
|  | +						loff_t offset) | ||||||
|  | +{ | ||||||
|  | +	static uint8_t root_id; | ||||||
|  | +	int err, len; | ||||||
|  | + | ||||||
|  | +	err = mtd_read(master, offset, 0x01, &len, &root_id); | ||||||
|  | + | ||||||
|  | +	if (mtd_is_bitflip(err) || !err) | ||||||
|  | +		return &root_id; | ||||||
|  | + | ||||||
|  | +	return NULL; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void brnboot_set_active_root_part(struct mtd_partition *pparts, | ||||||
|  | +					 struct device_node **part_nodes, | ||||||
|  | +					 int nr_parts, | ||||||
|  | +					 uint8_t *root_id) | ||||||
|  | +{ | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < nr_parts; i++) { | ||||||
|  | +		int part_root_id; | ||||||
|  | + | ||||||
|  | +		if (!of_property_read_u32(part_nodes[i], "brnboot,root-id", &part_root_id) | ||||||
|  | +		    && part_root_id == *root_id) { | ||||||
|  | +			pparts[i].name = "firmware"; | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int parse_fixed_partitions(struct mtd_info *master, | ||||||
|  |  				  const struct mtd_partition **pparts, | ||||||
|  |  				  struct mtd_part_parser_data *data) | ||||||
|  | @@ -51,6 +83,8 @@ static int parse_fixed_partitions(struct | ||||||
|  |  	struct device_node *pp; | ||||||
|  |  	int nr_parts, i, ret = 0; | ||||||
|  |  	bool dedicated = true; | ||||||
|  | +	uint8_t *proot_id = NULL; | ||||||
|  | +	struct device_node **part_nodes; | ||||||
|  |   | ||||||
|  |  	/* Pull of_node from the master device node */ | ||||||
|  |  	mtd_node = mtd_get_of_node(master); | ||||||
|  | @@ -95,7 +129,9 @@ static int parse_fixed_partitions(struct | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  |  	parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); | ||||||
|  | -	if (!parts) | ||||||
|  | +	part_nodes = kcalloc(nr_parts, sizeof(*part_nodes), GFP_KERNEL); | ||||||
|  | + | ||||||
|  | +	if (!parts || !part_nodes) | ||||||
|  |  		return -ENOMEM; | ||||||
|  |   | ||||||
|  |  	i = 0; | ||||||
|  | @@ -147,6 +183,11 @@ static int parse_fixed_partitions(struct | ||||||
|  |  		if (of_property_read_bool(pp, "slc-mode")) | ||||||
|  |  			parts[i].add_flags |= MTD_SLC_ON_MLC_EMULATION; | ||||||
|  |   | ||||||
|  | +		if (!proot_id && of_device_is_compatible(pp, "brnboot,root-selector")) | ||||||
|  | +			proot_id = brnboot_get_selected_root_part(master, parts[i].offset); | ||||||
|  | + | ||||||
|  | +		part_nodes[i] = pp; | ||||||
|  | + | ||||||
|  |  		i++; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | @@ -156,6 +197,11 @@ static int parse_fixed_partitions(struct | ||||||
|  |  	if (quirks && quirks->post_parse) | ||||||
|  |  		quirks->post_parse(master, parts, nr_parts); | ||||||
|  |   | ||||||
|  | +	if (proot_id) | ||||||
|  | +		brnboot_set_active_root_part(parts, part_nodes, nr_parts, proot_id); | ||||||
|  | + | ||||||
|  | +	kfree(part_nodes); | ||||||
|  | + | ||||||
|  |  	*pparts = parts; | ||||||
|  |  	return nr_parts; | ||||||
|  |   | ||||||
|  | @@ -166,6 +212,7 @@ ofpart_fail: | ||||||
|  |  ofpart_none: | ||||||
|  |  	of_node_put(pp); | ||||||
|  |  	kfree(parts); | ||||||
|  | +	kfree(part_nodes); | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @@ -0,0 +1,387 @@ | |||||||
|  | --- a/arch/mips/pci/ifxmips_pcie.c | ||||||
|  | +++ b/arch/mips/pci/ifxmips_pcie.c | ||||||
|  | @@ -16,8 +16,15 @@ | ||||||
|  |  #include <asm/paccess.h> | ||||||
|  |  #include <linux/pci.h> | ||||||
|  |  #include <linux/pci_regs.h> | ||||||
|  | +#include <linux/phy/phy.h> | ||||||
|  | +#include <linux/regmap.h> | ||||||
|  | +#include <linux/reset.h> | ||||||
|  | +#include <linux/mfd/syscon.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  |   | ||||||
|  | +#include <linux/of_gpio.h> | ||||||
|  | +#include <linux/of_platform.h> | ||||||
|  | + | ||||||
|  |  #include "ifxmips_pcie.h" | ||||||
|  |  #include "ifxmips_pcie_reg.h" | ||||||
|  |   | ||||||
|  | @@ -40,6 +47,10 @@ | ||||||
|  |  static DEFINE_SPINLOCK(ifx_pcie_lock); | ||||||
|  |   | ||||||
|  |  u32 g_pcie_debug_flag = PCIE_MSG_ANY & (~PCIE_MSG_CFG); | ||||||
|  | +static int pcie_reset_gpio; | ||||||
|  | +static struct phy *ltq_pcie_phy; | ||||||
|  | +static struct reset_control *ltq_pcie_reset; | ||||||
|  | +static struct regmap *ltq_rcu_regmap; | ||||||
|  |   | ||||||
|  |  static ifx_pcie_irq_t pcie_irqs[IFX_PCIE_CORE_NR] = { | ||||||
|  |      { | ||||||
|  | @@ -82,6 +93,22 @@ void ifx_pcie_debug(const char *fmt, ... | ||||||
|  |  	printk("%s", buf); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static inline void pcie_ep_gpio_rst_init(int pcie_port) | ||||||
|  | +{ | ||||||
|  | +	gpio_direction_output(pcie_reset_gpio, 1); | ||||||
|  | +	gpio_set_value(pcie_reset_gpio, 1); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void pcie_device_rst_assert(int pcie_port) | ||||||
|  | +{ | ||||||
|  | +	gpio_set_value(pcie_reset_gpio, 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void pcie_device_rst_deassert(int pcie_port) | ||||||
|  | +{ | ||||||
|  | +	mdelay(100); | ||||||
|  | +	gpio_direction_output(pcie_reset_gpio, 1); | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  static inline int pcie_ltssm_enable(int pcie_port) | ||||||
|  |  { | ||||||
|  | @@ -988,10 +1015,22 @@ int  ifx_pcie_bios_plat_dev_init(struct | ||||||
|  |  static int | ||||||
|  |  pcie_rc_initialize(int pcie_port) | ||||||
|  |  { | ||||||
|  | -	int i; | ||||||
|  | +	int i, ret; | ||||||
|  |  #define IFX_PCIE_PHY_LOOP_CNT  5 | ||||||
|  |   | ||||||
|  | -	pcie_rcu_endian_setup(pcie_port); | ||||||
|  | +	regmap_update_bits(ltq_rcu_regmap, 0x4c, IFX_RCU_AHB_BE_PCIE_M, | ||||||
|  | +			   IFX_RCU_AHB_BE_PCIE_M); | ||||||
|  | + | ||||||
|  | +#ifdef CONFIG_IFX_PCIE_HW_SWAP | ||||||
|  | +	regmap_update_bits(ltq_rcu_regmap, 0x4c, IFX_RCU_AHB_BE_PCIE_S, | ||||||
|  | +			   IFX_RCU_AHB_BE_PCIE_S); | ||||||
|  | +#else | ||||||
|  | +	regmap_update_bits(ltq_rcu_regmap, 0x4c, IFX_RCU_AHB_BE_PCIE_S, | ||||||
|  | +			   0x0); | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  | +	regmap_update_bits(ltq_rcu_regmap, 0x4c, IFX_RCU_AHB_BE_XBAR_M, | ||||||
|  | +			   0x0); | ||||||
|  |   | ||||||
|  |  	pcie_ep_gpio_rst_init(pcie_port); | ||||||
|  |   | ||||||
|  | @@ -1000,26 +1039,21 @@ pcie_rc_initialize(int pcie_port) | ||||||
|  |  	* reset PCIe PHY will solve this issue  | ||||||
|  |  	*/ | ||||||
|  |  	for (i = 0; i < IFX_PCIE_PHY_LOOP_CNT; i++) { | ||||||
|  | -		/* Disable PCIe PHY Analog part for sanity check */ | ||||||
|  | -		pcie_phy_pmu_disable(pcie_port); | ||||||
|  | - | ||||||
|  | -		pcie_phy_rst_assert(pcie_port); | ||||||
|  | -		pcie_phy_rst_deassert(pcie_port); | ||||||
|  | - | ||||||
|  | -		/* Make sure PHY PLL is stable */ | ||||||
|  | -		udelay(20); | ||||||
|  | - | ||||||
|  | -		/* PCIe Core reset enabled, low active, sw programmed */ | ||||||
|  | -		pcie_core_rst_assert(pcie_port); | ||||||
|  | +		ret = phy_init(ltq_pcie_phy); | ||||||
|  | +		if (ret) | ||||||
|  | +			continue; | ||||||
|  |   | ||||||
|  |  		/* Put PCIe EP in reset status */ | ||||||
|  |  		pcie_device_rst_assert(pcie_port); | ||||||
|  |   | ||||||
|  | -		/* PCI PHY & Core reset disabled, high active, sw programmed */ | ||||||
|  | -		pcie_core_rst_deassert(pcie_port); | ||||||
|  | +		udelay(1); | ||||||
|  | +		reset_control_deassert(ltq_pcie_reset); | ||||||
|  |   | ||||||
|  | -		/* Already in a quiet state, program PLL, enable PHY, check ready bit */ | ||||||
|  | -		pcie_phy_clock_mode_setup(pcie_port); | ||||||
|  | +		ret = phy_power_on(ltq_pcie_phy); | ||||||
|  | +		if (ret) { | ||||||
|  | +			phy_exit(ltq_pcie_phy); | ||||||
|  | +			continue; | ||||||
|  | +		} | ||||||
|  |   | ||||||
|  |  		/* Enable PCIe PHY and Clock */ | ||||||
|  |  		pcie_core_pmu_setup(pcie_port); | ||||||
|  | @@ -1035,6 +1069,10 @@ pcie_rc_initialize(int pcie_port) | ||||||
|  |  		/* Once link is up, break out */ | ||||||
|  |  		if (pcie_app_loigc_setup(pcie_port) == 0) | ||||||
|  |  			break; | ||||||
|  | + | ||||||
|  | +		phy_power_off(ltq_pcie_phy); | ||||||
|  | +		reset_control_assert(ltq_pcie_reset); | ||||||
|  | +		phy_exit(ltq_pcie_phy); | ||||||
|  |  	} | ||||||
|  |  	if (i >= IFX_PCIE_PHY_LOOP_CNT) { | ||||||
|  |  		printk(KERN_ERR "%s link up failed!!!!!\n", __func__); | ||||||
|  | @@ -1045,17 +1083,67 @@ pcie_rc_initialize(int pcie_port) | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int __init ifx_pcie_bios_init(void) | ||||||
|  | +static int ifx_pcie_bios_probe(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  | +    struct device_node *node = pdev->dev.of_node; | ||||||
|  |      void __iomem *io_map_base; | ||||||
|  |      int pcie_port; | ||||||
|  |      int startup_port; | ||||||
|  | +    struct device_node *np; | ||||||
|  | +    struct pci_bus *bus; | ||||||
|  | + | ||||||
|  | +    /* | ||||||
|  | +     * In case a PCI device is physical present, the Lantiq PCI driver need | ||||||
|  | +     * to be loaded prior to the Lantiq PCIe driver. Otherwise none of them | ||||||
|  | +     * will work. | ||||||
|  | +     * | ||||||
|  | +     * In case the lantiq PCI driver is enabled in the device tree, check if | ||||||
|  | +     * a PCI bus (hopefully the one of the Lantiq PCI driver one) is already | ||||||
|  | +     * registered. | ||||||
|  | +     * | ||||||
|  | +     * It will fail if there is another PCI controller, this controller is | ||||||
|  | +     * registered before the Lantiq PCIe driver is probe and the lantiq PCI | ||||||
|  | +     */ | ||||||
|  | +    np = of_find_compatible_node(NULL, NULL, "lantiq,pci-xway"); | ||||||
|  | + | ||||||
|  | +    if (of_device_is_available(np)) { | ||||||
|  | +        bus = pci_find_next_bus(bus); | ||||||
|  | + | ||||||
|  | +        if (!bus) | ||||||
|  | +	     return -EPROBE_DEFER; | ||||||
|  | +    } | ||||||
|  |   | ||||||
|  |      /* Enable AHB Master/ Slave */ | ||||||
|  |      pcie_ahb_pmu_setup(); | ||||||
|  |   | ||||||
|  |      startup_port = IFX_PCIE_PORT0; | ||||||
|  | -     | ||||||
|  | + | ||||||
|  | +    ltq_pcie_phy = devm_phy_get(&pdev->dev, "pcie"); | ||||||
|  | +    if (IS_ERR(ltq_pcie_phy)) { | ||||||
|  | +        dev_err(&pdev->dev, "failed to get the PCIe PHY\n"); | ||||||
|  | +        return PTR_ERR(ltq_pcie_phy); | ||||||
|  | +    } | ||||||
|  | + | ||||||
|  | +    ltq_pcie_reset = devm_reset_control_get_shared(&pdev->dev, NULL); | ||||||
|  | +    if (IS_ERR(ltq_pcie_reset)) { | ||||||
|  | +        dev_err(&pdev->dev, "failed to get the PCIe reset line\n"); | ||||||
|  | +        return PTR_ERR(ltq_pcie_reset); | ||||||
|  | +    } | ||||||
|  | + | ||||||
|  | +    ltq_rcu_regmap = syscon_regmap_lookup_by_phandle(node, "lantiq,rcu"); | ||||||
|  | +    if (IS_ERR(ltq_rcu_regmap)) | ||||||
|  | +        return PTR_ERR(ltq_rcu_regmap); | ||||||
|  | + | ||||||
|  | +    pcie_reset_gpio = of_get_named_gpio(node, "gpio-reset", 0); | ||||||
|  | +    if (gpio_is_valid(pcie_reset_gpio)) { | ||||||
|  | +        int ret = devm_gpio_request(&pdev->dev, pcie_reset_gpio, "pcie-reset"); | ||||||
|  | +        if (ret) { | ||||||
|  | +            dev_err(&pdev->dev, "failed to request gpio %d\n", pcie_reset_gpio); | ||||||
|  | +            return ret; | ||||||
|  | +        } | ||||||
|  | +        gpio_direction_output(pcie_reset_gpio, 1); | ||||||
|  | +    } | ||||||
|  | + | ||||||
|  |      for (pcie_port = startup_port; pcie_port < IFX_PCIE_CORE_NR; pcie_port++){ | ||||||
|  |  	if (pcie_rc_initialize(pcie_port) == 0) { | ||||||
|  |  	    IFX_PCIE_PRINT(PCIE_MSG_INIT, "%s: ifx_pcie_cfg_base 0x%p\n",  | ||||||
|  | @@ -1067,6 +1155,7 @@ static int __init ifx_pcie_bios_init(voi | ||||||
|  |                  return -ENOMEM; | ||||||
|  |              } | ||||||
|  |              ifx_pcie_controller[pcie_port].pcic.io_map_base = (unsigned long)io_map_base; | ||||||
|  | +            pci_load_of_ranges(&ifx_pcie_controller[pcie_port].pcic, node); | ||||||
|  |   | ||||||
|  |              register_pci_controller(&ifx_pcie_controller[pcie_port].pcic); | ||||||
|  |              /* XXX, clear error status */ | ||||||
|  | @@ -1083,6 +1172,30 @@ static int __init ifx_pcie_bios_init(voi | ||||||
|  |   | ||||||
|  |      return 0; | ||||||
|  |  } | ||||||
|  | + | ||||||
|  | +static const struct of_device_id ifxmips_pcie_match[] = { | ||||||
|  | +        { .compatible = "lantiq,pcie-xrx200" }, | ||||||
|  | +        {}, | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, ifxmips_pcie_match); | ||||||
|  | + | ||||||
|  | +static struct platform_driver ltq_pci_driver = { | ||||||
|  | +        .probe = ifx_pcie_bios_probe, | ||||||
|  | +        .driver = { | ||||||
|  | +                .name = "pcie-xrx200", | ||||||
|  | +                .owner = THIS_MODULE, | ||||||
|  | +                .of_match_table = ifxmips_pcie_match, | ||||||
|  | +        }, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +int __init ifx_pcie_bios_init(void) | ||||||
|  | +{ | ||||||
|  | +        int ret = platform_driver_register(<q_pci_driver); | ||||||
|  | +        if (ret) | ||||||
|  | +                pr_info("pcie-xrx200: Error registering platform driver!"); | ||||||
|  | +        return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  arch_initcall(ifx_pcie_bios_init); | ||||||
|  |   | ||||||
|  |  MODULE_LICENSE("GPL"); | ||||||
|  | --- a/arch/mips/pci/ifxmips_pcie_vr9.h | ||||||
|  | +++ b/arch/mips/pci/ifxmips_pcie_vr9.h | ||||||
|  | @@ -22,8 +22,6 @@ | ||||||
|  |  #include <linux/gpio.h> | ||||||
|  |  #include <lantiq_soc.h> | ||||||
|  |   | ||||||
|  | -#define IFX_PCIE_GPIO_RESET  494 | ||||||
|  | - | ||||||
|  |  #define IFX_REG_R32    ltq_r32 | ||||||
|  |  #define IFX_REG_W32    ltq_w32 | ||||||
|  |  #define CONFIG_IFX_PCIE_HW_SWAP | ||||||
|  | @@ -53,21 +51,6 @@ | ||||||
|  |  #define OUT			((volatile u32*)(IFX_GPIO + 0x0070)) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -static inline void pcie_ep_gpio_rst_init(int pcie_port) | ||||||
|  | -{ | ||||||
|  | - | ||||||
|  | -	gpio_request(IFX_PCIE_GPIO_RESET, "pcie-reset"); | ||||||
|  | -	gpio_direction_output(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | -	gpio_set_value(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | - | ||||||
|  | -/*    ifx_gpio_pin_reserve(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_output_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_dir_out_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_altsel0_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_altsel1_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_open_drain_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id);*/ | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static inline void pcie_ahb_pmu_setup(void)  | ||||||
|  |  { | ||||||
|  |  	/* Enable AHB bus master/slave */ | ||||||
|  | @@ -79,24 +62,6 @@ static inline void pcie_ahb_pmu_setup(vo | ||||||
|  |      //AHBS_PMU_SETUP(IFX_PMU_ENABLE); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static inline void pcie_rcu_endian_setup(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    u32 reg; | ||||||
|  | - | ||||||
|  | -    reg = IFX_REG_R32(IFX_RCU_AHB_ENDIAN); | ||||||
|  | -#ifdef CONFIG_IFX_PCIE_HW_SWAP | ||||||
|  | -    reg |= IFX_RCU_AHB_BE_PCIE_M; | ||||||
|  | -    reg |= IFX_RCU_AHB_BE_PCIE_S; | ||||||
|  | -    reg &= ~IFX_RCU_AHB_BE_XBAR_M; | ||||||
|  | -#else  | ||||||
|  | -    reg |= IFX_RCU_AHB_BE_PCIE_M; | ||||||
|  | -    reg &= ~IFX_RCU_AHB_BE_PCIE_S; | ||||||
|  | -    reg &= ~IFX_RCU_AHB_BE_XBAR_M; | ||||||
|  | -#endif /* CONFIG_IFX_PCIE_HW_SWAP */ | ||||||
|  | -    IFX_REG_W32(reg, IFX_RCU_AHB_ENDIAN); | ||||||
|  | -    IFX_PCIE_PRINT(PCIE_MSG_REG, "%s IFX_RCU_AHB_ENDIAN: 0x%08x\n", __func__, IFX_REG_R32(IFX_RCU_AHB_ENDIAN)); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static inline void pcie_phy_pmu_enable(int pcie_port) | ||||||
|  |  { | ||||||
|  |  	struct clk *clk; | ||||||
|  | @@ -115,17 +80,6 @@ static inline void pcie_phy_pmu_disable( | ||||||
|  |  //    PCIE_PHY_PMU_SETUP(IFX_PMU_DISABLE); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static inline void pcie_pdi_big_endian(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    u32 reg; | ||||||
|  | - | ||||||
|  | -    /* SRAM2PDI endianness control. */ | ||||||
|  | -    reg = IFX_REG_R32(IFX_RCU_AHB_ENDIAN); | ||||||
|  | -    /* Config AHB->PCIe and PDI endianness */ | ||||||
|  | -    reg |= IFX_RCU_AHB_BE_PCIE_PDI; | ||||||
|  | -    IFX_REG_W32(reg, IFX_RCU_AHB_ENDIAN); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static inline void pcie_pdi_pmu_enable(int pcie_port) | ||||||
|  |  { | ||||||
|  |      /* Enable PDI to access PCIe PHY register */ | ||||||
|  | @@ -135,65 +89,6 @@ static inline void pcie_pdi_pmu_enable(i | ||||||
|  |      //PDI_PMU_SETUP(IFX_PMU_ENABLE); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static inline void pcie_core_rst_assert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    u32 reg; | ||||||
|  | - | ||||||
|  | -    reg = IFX_REG_R32(IFX_RCU_RST_REQ); | ||||||
|  | - | ||||||
|  | -    /* Reset PCIe PHY & Core, bit 22, bit 26 may be affected if write it directly  */ | ||||||
|  | -    reg |= 0x00400000; | ||||||
|  | -    IFX_REG_W32(reg, IFX_RCU_RST_REQ); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static inline void pcie_core_rst_deassert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    u32 reg; | ||||||
|  | - | ||||||
|  | -    /* Make sure one micro-second delay */ | ||||||
|  | -    udelay(1); | ||||||
|  | - | ||||||
|  | -    /* Reset PCIe PHY & Core, bit 22 */ | ||||||
|  | -    reg = IFX_REG_R32(IFX_RCU_RST_REQ); | ||||||
|  | -    reg &= ~0x00400000; | ||||||
|  | -    IFX_REG_W32(reg, IFX_RCU_RST_REQ); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static inline void pcie_phy_rst_assert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    u32 reg; | ||||||
|  | - | ||||||
|  | -    reg = IFX_REG_R32(IFX_RCU_RST_REQ); | ||||||
|  | -    reg |= 0x00001000; /* Bit 12 */ | ||||||
|  | -    IFX_REG_W32(reg, IFX_RCU_RST_REQ); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static inline void pcie_phy_rst_deassert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    u32 reg; | ||||||
|  | - | ||||||
|  | -    /* Make sure one micro-second delay */ | ||||||
|  | -    udelay(1); | ||||||
|  | - | ||||||
|  | -    reg = IFX_REG_R32(IFX_RCU_RST_REQ); | ||||||
|  | -    reg &= ~0x00001000; /* Bit 12 */ | ||||||
|  | -    IFX_REG_W32(reg, IFX_RCU_RST_REQ); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static inline void pcie_device_rst_assert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -	gpio_set_value(IFX_PCIE_GPIO_RESET, 0); | ||||||
|  | -//    ifx_gpio_output_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static inline void pcie_device_rst_deassert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    mdelay(100); | ||||||
|  | -	gpio_direction_output(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | -//    gpio_set_value(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | -    //ifx_gpio_output_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static inline void pcie_core_pmu_setup(int pcie_port) | ||||||
|  |  { | ||||||
|  |  	struct clk *clk; | ||||||
|  | --- a/arch/mips/pci/Makefile | ||||||
|  | +++ b/arch/mips/pci/Makefile | ||||||
|  | @@ -43,7 +43,7 @@ obj-$(CONFIG_PCI_LANTIQ)	+= pci-lantiq.o | ||||||
|  |  obj-$(CONFIG_SOC_MT7620)	+= pci-mt7620.o | ||||||
|  |  obj-$(CONFIG_SOC_RT288X)	+= pci-rt2880.o | ||||||
|  |  obj-$(CONFIG_SOC_RT3883)	+= pci-rt3883.o | ||||||
|  | -obj-$(CONFIG_PCIE_LANTIQ)	+= ifxmips_pcie_phy.o ifxmips_pcie.o fixup-lantiq-pcie.o | ||||||
|  | +obj-$(CONFIG_PCIE_LANTIQ)	+= ifxmips_pcie.o fixup-lantiq-pcie.o | ||||||
|  |  obj-$(CONFIG_PCIE_LANTIQ_MSI)	+= pcie-lantiq-msi.o | ||||||
|  |  obj-$(CONFIG_TANBAC_TB0219)	+= fixup-tb0219.o | ||||||
|  |  obj-$(CONFIG_TANBAC_TB0226)	+= fixup-tb0226.o | ||||||
							
								
								
									
										180
									
								
								target/linux/lantiq/patches-5.15/0152-lantiq-VPE.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								target/linux/lantiq/patches-5.15/0152-lantiq-VPE.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | |||||||
|  | --- a/arch/mips/Kconfig | ||||||
|  | +++ b/arch/mips/Kconfig | ||||||
|  | @@ -2434,6 +2434,12 @@ config MIPS_VPE_LOADER | ||||||
|  |  	  Includes a loader for loading an elf relocatable object | ||||||
|  |  	  onto another VPE and running it. | ||||||
|  |   | ||||||
|  | +config IFX_VPE_EXT | ||||||
|  | +	bool "IFX APRP Extensions" | ||||||
|  | +	depends on MIPS_VPE_LOADER | ||||||
|  | +	help | ||||||
|  | +	  IFX included extensions in APRP | ||||||
|  | + | ||||||
|  |  config MIPS_VPE_LOADER_CMP | ||||||
|  |  	bool | ||||||
|  |  	default "y" | ||||||
|  | --- a/arch/mips/include/asm/vpe.h | ||||||
|  | +++ b/arch/mips/include/asm/vpe.h | ||||||
|  | @@ -127,4 +127,13 @@ void cleanup_tc(struct tc *tc); | ||||||
|  |   | ||||||
|  |  int __init vpe_module_init(void); | ||||||
|  |  void __exit vpe_module_exit(void); | ||||||
|  | + | ||||||
|  | +/* For the explanation of the APIs please refer the section "MT APRP Kernel | ||||||
|  | + * Programming" in AR9 SW Architecture Specification | ||||||
|  | + */ | ||||||
|  | +int32_t vpe1_sw_start(void *sw_start_addr, uint32_t tcmask, uint32_t flags); | ||||||
|  | +int32_t vpe1_sw_stop(uint32_t flags); | ||||||
|  | +uint32_t vpe1_get_load_addr(uint32_t flags); | ||||||
|  | +uint32_t vpe1_get_max_mem(uint32_t flags); | ||||||
|  | + | ||||||
|  |  #endif /* _ASM_VPE_H */ | ||||||
|  | --- a/arch/mips/kernel/vpe-mt.c | ||||||
|  | +++ b/arch/mips/kernel/vpe-mt.c | ||||||
|  | @@ -29,6 +29,7 @@ int vpe_run(struct vpe *v) | ||||||
|  |  	struct vpe_notifications *notifier; | ||||||
|  |  	unsigned int vpeflags; | ||||||
|  |  	struct tc *t; | ||||||
|  | +	unsigned long physical_memsize = 0L; | ||||||
|  |   | ||||||
|  |  	/* check we are the Master VPE */ | ||||||
|  |  	local_irq_save(flags); | ||||||
|  | @@ -417,6 +418,8 @@ int __init vpe_module_init(void) | ||||||
|  |  			} | ||||||
|  |   | ||||||
|  |  			v->ntcs = hw_tcs - aprp_cpu_index(); | ||||||
|  | +			write_tc_c0_tcbind((read_tc_c0_tcbind() & | ||||||
|  | +						~TCBIND_CURVPE) | 1); | ||||||
|  |   | ||||||
|  |  			/* add the tc to the list of this vpe's tc's. */ | ||||||
|  |  			list_add(&t->tc, &v->tc); | ||||||
|  | @@ -519,3 +522,47 @@ void __exit vpe_module_exit(void) | ||||||
|  |  			release_vpe(v); | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  | + | ||||||
|  | +#ifdef CONFIG_IFX_VPE_EXT | ||||||
|  | +int32_t vpe1_sw_start(void *sw_start_addr, uint32_t tcmask, uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	enum vpe_state state; | ||||||
|  | +	struct vpe *v = get_vpe(tclimit); | ||||||
|  | +	struct vpe_notifications *not; | ||||||
|  | + | ||||||
|  | +	if (tcmask || flags) { | ||||||
|  | +		pr_warn("Currently tcmask and flags should be 0. Other values are not supported\n"); | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	state = xchg(&v->state, VPE_STATE_INUSE); | ||||||
|  | +	if (state != VPE_STATE_UNUSED) { | ||||||
|  | +		vpe_stop(v); | ||||||
|  | + | ||||||
|  | +		list_for_each_entry(not, &v->notify, list) { | ||||||
|  | +			not->stop(tclimit); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	v->__start = (unsigned long)sw_start_addr; | ||||||
|  | + | ||||||
|  | +	if (!vpe_run(v)) { | ||||||
|  | +		pr_debug("VPE loader: VPE1 running successfully\n"); | ||||||
|  | +		return 0; | ||||||
|  | +	} | ||||||
|  | +	return -1; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_start); | ||||||
|  | + | ||||||
|  | +int32_t vpe1_sw_stop(uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	struct vpe *v = get_vpe(tclimit); | ||||||
|  | + | ||||||
|  | +	if (!vpe_free(v)) { | ||||||
|  | +		pr_debug("RP Stopped\n"); | ||||||
|  | +		return 0; | ||||||
|  | +	} else | ||||||
|  | +		return -1; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_stop); | ||||||
|  | +#endif | ||||||
|  | --- a/arch/mips/kernel/vpe.c | ||||||
|  | +++ b/arch/mips/kernel/vpe.c | ||||||
|  | @@ -49,6 +49,41 @@ struct vpe_control vpecontrol = { | ||||||
|  |  	.tc_list	= LIST_HEAD_INIT(vpecontrol.tc_list) | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +#ifdef CONFIG_IFX_VPE_EXT | ||||||
|  | +unsigned int vpe1_load_addr; | ||||||
|  | + | ||||||
|  | +static int __init load_address(char *str) | ||||||
|  | +{ | ||||||
|  | +	get_option(&str, &vpe1_load_addr); | ||||||
|  | +	return 1; | ||||||
|  | +} | ||||||
|  | +__setup("vpe1_load_addr=", load_address); | ||||||
|  | + | ||||||
|  | +static unsigned int vpe1_mem; | ||||||
|  | +static int __init vpe1mem(char *str) | ||||||
|  | +{ | ||||||
|  | +	vpe1_mem = memparse(str, &str); | ||||||
|  | +	return 1; | ||||||
|  | +} | ||||||
|  | +__setup("vpe1_mem=", vpe1mem); | ||||||
|  | + | ||||||
|  | +uint32_t vpe1_get_load_addr(uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	return vpe1_load_addr; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_get_load_addr); | ||||||
|  | + | ||||||
|  | +uint32_t vpe1_get_max_mem(uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	if (!vpe1_mem) | ||||||
|  | +		return P_SIZE; | ||||||
|  | +	else | ||||||
|  | +		return vpe1_mem; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_get_max_mem); | ||||||
|  | + | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  /* get the vpe associated with this minor */ | ||||||
|  |  struct vpe *get_vpe(int minor) | ||||||
|  |  { | ||||||
|  | --- a/arch/mips/lantiq/prom.c | ||||||
|  | +++ b/arch/mips/lantiq/prom.c | ||||||
|  | @@ -34,10 +34,14 @@ unsigned long physical_memsize = 0L; | ||||||
|  |   */ | ||||||
|  |  static struct ltq_soc_info soc_info; | ||||||
|  |   | ||||||
|  | +/* for Multithreading (APRP), vpe.c will use it */ | ||||||
|  | +unsigned long cp0_memsize; | ||||||
|  | + | ||||||
|  |  const char *get_system_type(void) | ||||||
|  |  { | ||||||
|  |  	return soc_info.sys_type; | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL(ltq_soc_type); | ||||||
|  |   | ||||||
|  |  int ltq_soc_type(void) | ||||||
|  |  { | ||||||
|  | --- a/arch/mips/include/asm/mipsmtregs.h | ||||||
|  | +++ b/arch/mips/include/asm/mipsmtregs.h | ||||||
|  | @@ -32,6 +32,9 @@ | ||||||
|  |  #define read_c0_vpeconf1()		__read_32bit_c0_register($1, 3) | ||||||
|  |  #define write_c0_vpeconf1(val)		__write_32bit_c0_register($1, 3, val) | ||||||
|  |   | ||||||
|  | +#define read_c0_vpeopt()		__read_32bit_c0_register($1, 7) | ||||||
|  | +#define write_c0_vpeopt(val)		__write_32bit_c0_register($1, 7, val) | ||||||
|  | + | ||||||
|  |  #define read_c0_tcstatus()		__read_32bit_c0_register($2, 1) | ||||||
|  |  #define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val) | ||||||
|  |   | ||||||
|  | @@ -378,6 +381,8 @@ do {									\ | ||||||
|  |  #define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val) | ||||||
|  |  #define read_vpe_c0_vpeconf1()		mftc0(1, 3) | ||||||
|  |  #define write_vpe_c0_vpeconf1(val)	mttc0(1, 3, val) | ||||||
|  | +#define read_vpe_c0_vpeopt()		mftc0(1, 7) | ||||||
|  | +#define write_vpe_c0_vpeopt(val)	mttc0(1, 7, val) | ||||||
|  |  #define read_vpe_c0_count()		mftc0(9, 0) | ||||||
|  |  #define write_vpe_c0_count(val)		mttc0(9, 0, val) | ||||||
|  |  #define read_vpe_c0_status()		mftc0(12, 0) | ||||||
| @@ -0,0 +1,22 @@ | |||||||
|  | --- a/arch/mips/pci/pci-lantiq.c | ||||||
|  | +++ b/arch/mips/pci/pci-lantiq.c | ||||||
|  | @@ -59,6 +59,8 @@ | ||||||
|  |  #define ltq_pci_cfg_w32(x, y)	ltq_w32((x), ltq_pci_mapped_cfg + (y)) | ||||||
|  |  #define ltq_pci_cfg_r32(x)	ltq_r32(ltq_pci_mapped_cfg + (x)) | ||||||
|  |   | ||||||
|  | +extern u32 max_low_pfn; | ||||||
|  | + | ||||||
|  |  __iomem void *ltq_pci_mapped_cfg; | ||||||
|  |  static __iomem void *ltq_pci_membase; | ||||||
|  |   | ||||||
|  | @@ -84,8 +86,8 @@ static inline u32 ltq_calc_bar11mask(voi | ||||||
|  |  	u32 mem, bar11mask; | ||||||
|  |   | ||||||
|  |  	/* BAR11MASK value depends on available memory on system. */ | ||||||
|  | -	mem = get_num_physpages() * PAGE_SIZE; | ||||||
|  | -	bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8; | ||||||
|  | +	mem = max_low_pfn << PAGE_SHIFT; | ||||||
|  | +	bar11mask = ((-roundup_pow_of_two(mem)) & 0x0F000000) | 8; | ||||||
|  |   | ||||||
|  |  	return bar11mask; | ||||||
|  |  } | ||||||
							
								
								
									
										14
									
								
								target/linux/lantiq/patches-5.15/0155-lantiq-VPE-nosmp.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								target/linux/lantiq/patches-5.15/0155-lantiq-VPE-nosmp.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | --- a/arch/mips/kernel/vpe-mt.c | ||||||
|  | +++ b/arch/mips/kernel/vpe-mt.c | ||||||
|  | @@ -132,7 +132,10 @@ int vpe_run(struct vpe *v) | ||||||
|  |  	 * kernels need to turn it on, even if that wasn't the pre-dvpe() state. | ||||||
|  |  	 */ | ||||||
|  |  #ifdef CONFIG_SMP | ||||||
|  | -	evpe(vpeflags); | ||||||
|  | +	if (!setup_max_cpus) /* nosmp is set */ | ||||||
|  | +		evpe(EVPE_ENABLE); | ||||||
|  | +	else | ||||||
|  | +		evpe(vpeflags); | ||||||
|  |  #else | ||||||
|  |  	evpe(EVPE_ENABLE); | ||||||
|  |  #endif | ||||||
| @@ -0,0 +1,220 @@ | |||||||
|  | --- a/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | +++ b/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | @@ -17,6 +17,7 @@ | ||||||
|  |  #include <linux/mtd/cfi.h> | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <linux/mtd/physmap.h> | ||||||
|  | +#include <linux/mtd/concat.h> | ||||||
|  |  #include <linux/of.h> | ||||||
|  |   | ||||||
|  |  #include <lantiq_soc.h> | ||||||
|  | @@ -36,13 +37,16 @@ enum { | ||||||
|  |  	LTQ_NOR_NORMAL | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +#define MAX_RESOURCES		4 | ||||||
|  | + | ||||||
|  |  struct ltq_mtd { | ||||||
|  | -	struct resource *res; | ||||||
|  | -	struct mtd_info *mtd; | ||||||
|  | -	struct map_info *map; | ||||||
|  | +	struct mtd_info *mtd[MAX_RESOURCES]; | ||||||
|  | +	struct mtd_info	*cmtd; | ||||||
|  | +	struct map_info map[MAX_RESOURCES]; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const char ltq_map_name[] = "ltq_nor"; | ||||||
|  | +static const char * const ltq_probe_types[] = { "cmdlinepart", "ofpart", NULL }; | ||||||
|  |   | ||||||
|  |  static map_word | ||||||
|  |  ltq_read16(struct map_info *map, unsigned long adr) | ||||||
|  | @@ -106,11 +110,43 @@ ltq_copy_to(struct map_info *map, unsign | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | +ltq_mtd_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	if (ltq_mtd == NULL) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	if (ltq_mtd->cmtd) { | ||||||
|  | +		mtd_device_unregister(ltq_mtd->cmtd); | ||||||
|  | +		if (ltq_mtd->cmtd != ltq_mtd->mtd[0]) | ||||||
|  | +			mtd_concat_destroy(ltq_mtd->cmtd); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < MAX_RESOURCES; i++) { | ||||||
|  | +		if (ltq_mtd->mtd[i] != NULL) | ||||||
|  | +			map_destroy(ltq_mtd->mtd[i]); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	kfree(ltq_mtd); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  |  ltq_mtd_probe(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_mtd *ltq_mtd; | ||||||
|  |  	struct cfi_private *cfi; | ||||||
|  | -	int err; | ||||||
|  | +	int err = 0; | ||||||
|  | +	int i; | ||||||
|  | +	int devices_found = 0; | ||||||
|  | + | ||||||
|  | +	static const char *rom_probe_types[] = { | ||||||
|  | +		"cfi_probe", "jedec_probe", NULL | ||||||
|  | +	}; | ||||||
|  | +	const char **type; | ||||||
|  |   | ||||||
|  |  	ltq_mtd = devm_kzalloc(&pdev->dev, sizeof(struct ltq_mtd), GFP_KERNEL); | ||||||
|  |  	if (!ltq_mtd) | ||||||
|  | @@ -118,75 +154,89 @@ ltq_mtd_probe(struct platform_device *pd | ||||||
|  |   | ||||||
|  |  	platform_set_drvdata(pdev, ltq_mtd); | ||||||
|  |   | ||||||
|  | -	ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | -	if (!ltq_mtd->res) { | ||||||
|  | -		dev_err(&pdev->dev, "failed to get memory resource\n"); | ||||||
|  | -		return -ENOENT; | ||||||
|  | +	for (i = 0; i < pdev->num_resources; i++) { | ||||||
|  | +		printk(KERN_NOTICE "lantiq nor flash device: %.8llx at %.8llx\n", | ||||||
|  | +		       (unsigned long long)resource_size(&pdev->resource[i]), | ||||||
|  | +		       (unsigned long long)pdev->resource[i].start); | ||||||
|  | +	 | ||||||
|  | +		if (!devm_request_mem_region(&pdev->dev, | ||||||
|  | +			pdev->resource[i].start, | ||||||
|  | +			resource_size(&pdev->resource[i]), | ||||||
|  | +			dev_name(&pdev->dev))) { | ||||||
|  | +			dev_err(&pdev->dev, "Could not reserve memory region\n"); | ||||||
|  | +			return -ENOMEM; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ltq_mtd->map[i].name = ltq_map_name; | ||||||
|  | +		ltq_mtd->map[i].bankwidth = 2; | ||||||
|  | +		ltq_mtd->map[i].read = ltq_read16; | ||||||
|  | +		ltq_mtd->map[i].write = ltq_write16; | ||||||
|  | +		ltq_mtd->map[i].copy_from = ltq_copy_from; | ||||||
|  | +		ltq_mtd->map[i].copy_to = ltq_copy_to; | ||||||
|  | + | ||||||
|  | +		if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) | ||||||
|  | +			ltq_mtd->map[i].phys = NO_XIP; | ||||||
|  | +		else | ||||||
|  | +			ltq_mtd->map[i].phys = pdev->resource[i].start; | ||||||
|  | +		ltq_mtd->map[i].size = resource_size(&pdev->resource[i]); | ||||||
|  | +		ltq_mtd->map[i].virt = devm_ioremap(&pdev->dev, pdev->resource[i].start, | ||||||
|  | +						 ltq_mtd->map[i].size); | ||||||
|  | +		if (IS_ERR(ltq_mtd->map[i].virt)) | ||||||
|  | +			return PTR_ERR(ltq_mtd->map[i].virt); | ||||||
|  | + | ||||||
|  | +		if (ltq_mtd->map[i].virt == NULL) { | ||||||
|  | +			dev_err(&pdev->dev, "Failed to ioremap flash region\n"); | ||||||
|  | +			err = PTR_ERR(ltq_mtd->map[i].virt); | ||||||
|  | +			goto err_out; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ltq_mtd->map[i].map_priv_1 = LTQ_NOR_PROBING; | ||||||
|  | +		for (type = rom_probe_types; !ltq_mtd->mtd[i] && *type; type++) | ||||||
|  | +			ltq_mtd->mtd[i] = do_map_probe(*type, <q_mtd->map[i]); | ||||||
|  | +		ltq_mtd->map[i].map_priv_1 = LTQ_NOR_NORMAL; | ||||||
|  | + | ||||||
|  | +		if (!ltq_mtd->mtd[i]) { | ||||||
|  | +			dev_err(&pdev->dev, "probing failed\n"); | ||||||
|  | +			return -ENXIO; | ||||||
|  | +		} else { | ||||||
|  | +			devices_found++; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ltq_mtd->mtd[i]->owner = THIS_MODULE; | ||||||
|  | +		ltq_mtd->mtd[i]->dev.parent = &pdev->dev; | ||||||
|  | + | ||||||
|  | +		cfi = ltq_mtd->map[i].fldrv_priv; | ||||||
|  | +		cfi->addr_unlock1 ^= 1; | ||||||
|  | +		cfi->addr_unlock2 ^= 1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ltq_mtd->map = devm_kzalloc(&pdev->dev, sizeof(struct map_info), | ||||||
|  | -				    GFP_KERNEL); | ||||||
|  | -	if (!ltq_mtd->map) | ||||||
|  | -		return -ENOMEM; | ||||||
|  | - | ||||||
|  | -	if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) | ||||||
|  | -		ltq_mtd->map->phys = NO_XIP; | ||||||
|  | -	else | ||||||
|  | -		ltq_mtd->map->phys = ltq_mtd->res->start; | ||||||
|  | -	ltq_mtd->res->start; | ||||||
|  | -	ltq_mtd->map->size = resource_size(ltq_mtd->res); | ||||||
|  | -	ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res); | ||||||
|  | -	if (IS_ERR(ltq_mtd->map->virt)) | ||||||
|  | -		return PTR_ERR(ltq_mtd->map->virt); | ||||||
|  | - | ||||||
|  | -	ltq_mtd->map->name = ltq_map_name; | ||||||
|  | -	ltq_mtd->map->bankwidth = 2; | ||||||
|  | -	ltq_mtd->map->read = ltq_read16; | ||||||
|  | -	ltq_mtd->map->write = ltq_write16; | ||||||
|  | -	ltq_mtd->map->copy_from = ltq_copy_from; | ||||||
|  | -	ltq_mtd->map->copy_to = ltq_copy_to; | ||||||
|  | - | ||||||
|  | -	ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING; | ||||||
|  | -	ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map); | ||||||
|  | -	ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL; | ||||||
|  | - | ||||||
|  | -	if (!ltq_mtd->mtd) { | ||||||
|  | -		dev_err(&pdev->dev, "probing failed\n"); | ||||||
|  | -		return -ENXIO; | ||||||
|  | +	if (devices_found == 1) { | ||||||
|  | +		ltq_mtd->cmtd = ltq_mtd->mtd[0]; | ||||||
|  | +	} else if (devices_found > 1) { | ||||||
|  | +		/* | ||||||
|  | +		 * We detected multiple devices. Concatenate them together. | ||||||
|  | +		 */ | ||||||
|  | +		ltq_mtd->cmtd = mtd_concat_create(ltq_mtd->mtd, devices_found, dev_name(&pdev->dev)); | ||||||
|  | +		if (ltq_mtd->cmtd == NULL) | ||||||
|  | +			err = -ENXIO; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ltq_mtd->mtd->dev.parent = &pdev->dev; | ||||||
|  | -	mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node); | ||||||
|  | - | ||||||
|  | -	cfi = ltq_mtd->map->fldrv_priv; | ||||||
|  | -	cfi->addr_unlock1 ^= 1; | ||||||
|  | -	cfi->addr_unlock2 ^= 1; | ||||||
|  | +	ltq_mtd->cmtd->dev.parent = &pdev->dev; | ||||||
|  | +	mtd_set_of_node(ltq_mtd->cmtd, pdev->dev.of_node); | ||||||
|  |   | ||||||
|  | -	err = mtd_device_register(ltq_mtd->mtd, NULL, 0); | ||||||
|  | +	err = mtd_device_register(ltq_mtd->cmtd, NULL, 0); | ||||||
|  |  	if (err) { | ||||||
|  |  		dev_err(&pdev->dev, "failed to add partitions\n"); | ||||||
|  | -		goto err_destroy; | ||||||
|  | +		goto err_out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  | -err_destroy: | ||||||
|  | -	map_destroy(ltq_mtd->mtd); | ||||||
|  | +err_out: | ||||||
|  | +	ltq_mtd_remove(pdev); | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int | ||||||
|  | -ltq_mtd_remove(struct platform_device *pdev) | ||||||
|  | -{ | ||||||
|  | -	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); | ||||||
|  | - | ||||||
|  | -	if (ltq_mtd && ltq_mtd->mtd) { | ||||||
|  | -		mtd_device_unregister(ltq_mtd->mtd); | ||||||
|  | -		map_destroy(ltq_mtd->mtd); | ||||||
|  | -	} | ||||||
|  | -	return 0; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static const struct of_device_id ltq_mtd_match[] = { | ||||||
|  |  	{ .compatible = "lantiq,nor" }, | ||||||
|  |  	{}, | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | --- a/drivers/mtd/chips/cfi_cmdset_0001.c | ||||||
|  | +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | ||||||
|  | @@ -39,7 +39,7 @@ | ||||||
|  |  /* #define CMDSET0001_DISABLE_WRITE_SUSPEND */ | ||||||
|  |   | ||||||
|  |  // debugging, turns off buffer write mode if set to 1 | ||||||
|  | -#define FORCE_WORD_WRITE 0 | ||||||
|  | +#define FORCE_WORD_WRITE 1 | ||||||
|  |   | ||||||
|  |  /* Intel chips */ | ||||||
|  |  #define I82802AB	0x00ad | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | --- a/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | @@ -440,6 +440,20 @@ static void clkdev_add_clkout(void) | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void set_phy_clock_source(struct device_node *np_cgu) | ||||||
|  | +{ | ||||||
|  | +	u32 phy_clk_src, ifcc; | ||||||
|  | + | ||||||
|  | +	if (!np_cgu) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (of_property_read_u32(np_cgu, "lantiq,phy-clk-src", &phy_clk_src)) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	ifcc = ltq_cgu_r32(ifccr) & ~(0x1c); | ||||||
|  | +	ltq_cgu_w32(ifcc | (phy_clk_src << 2), ifccr); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* bring up all register ranges that we need for basic system control */ | ||||||
|  |  void __init ltq_soc_init(void) | ||||||
|  |  { | ||||||
|  | @@ -605,4 +619,6 @@ void __init ltq_soc_init(void) | ||||||
|  |  		clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0); | ||||||
|  |  	} | ||||||
|  |  	usb_set_clock(); | ||||||
|  | + | ||||||
|  | +	set_phy_clock_source(np_cgu); | ||||||
|  |  } | ||||||
| @@ -0,0 +1,86 @@ | |||||||
|  | From 49293bbc50cb7d44223eb49e0f7cb38e7dac2361 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 14 Sep 2021 23:21:01 +0200 | ||||||
|  | Subject: [PATCH 4/5] MIPS: lantiq: dma: make the burst length configurable by | ||||||
|  |  the drivers | ||||||
|  |  | ||||||
|  | Make the burst length configurable by the drivers. | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Acked-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  .../include/asm/mach-lantiq/xway/xway_dma.h   |  2 +- | ||||||
|  |  arch/mips/lantiq/xway/dma.c                   | 38 ++++++++++++++++--- | ||||||
|  |  2 files changed, 34 insertions(+), 6 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | ||||||
|  | @@ -45,6 +45,6 @@ extern void ltq_dma_close(struct ltq_dma | ||||||
|  |  extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch); | ||||||
|  |  extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch); | ||||||
|  |  extern void ltq_dma_free(struct ltq_dma_channel *ch); | ||||||
|  | -extern void ltq_dma_init_port(int p); | ||||||
|  | +extern void ltq_dma_init_port(int p, int tx_burst, int rx_burst); | ||||||
|  |   | ||||||
|  |  #endif | ||||||
|  | --- a/arch/mips/lantiq/xway/dma.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/dma.c | ||||||
|  | @@ -181,7 +181,7 @@ ltq_dma_free(struct ltq_dma_channel *ch) | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_free); | ||||||
|  |   | ||||||
|  |  void | ||||||
|  | -ltq_dma_init_port(int p) | ||||||
|  | +ltq_dma_init_port(int p, int tx_burst, int rx_burst) | ||||||
|  |  { | ||||||
|  |  	ltq_dma_w32(p, LTQ_DMA_PS); | ||||||
|  |  	switch (p) { | ||||||
|  | @@ -190,16 +190,44 @@ ltq_dma_init_port(int p) | ||||||
|  |  		 * Tell the DMA engine to swap the endianness of data frames and | ||||||
|  |  		 * drop packets if the channel arbitration fails. | ||||||
|  |  		 */ | ||||||
|  | -		ltq_dma_w32_mask(0, DMA_ETOP_ENDIANNESS | DMA_PDEN, | ||||||
|  | +		ltq_dma_w32_mask(0, (DMA_ETOP_ENDIANNESS | DMA_PDEN), | ||||||
|  |  			LTQ_DMA_PCTRL); | ||||||
|  |  		break; | ||||||
|  |   | ||||||
|  | -	case DMA_PORT_DEU: | ||||||
|  | -		ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) | | ||||||
|  | -			(DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT), | ||||||
|  | +	default: | ||||||
|  | +		break; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	switch (rx_burst) { | ||||||
|  | +	case 8: | ||||||
|  | +		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_8W_BURST << DMA_RX_BURST_SHIFT), | ||||||
|  |  			LTQ_DMA_PCTRL); | ||||||
|  |  		break; | ||||||
|  | +	case 4: | ||||||
|  | +		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_4W_BURST << DMA_RX_BURST_SHIFT), | ||||||
|  | +			LTQ_DMA_PCTRL); | ||||||
|  | +		break; | ||||||
|  | +	case 2: | ||||||
|  | +		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT), | ||||||
|  | +			LTQ_DMA_PCTRL); | ||||||
|  | +		break; | ||||||
|  | +	default: | ||||||
|  | +		break; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | +	switch (tx_burst) { | ||||||
|  | +	case 8: | ||||||
|  | +		ltq_dma_w32_mask(0x30, (DMA_PCTRL_8W_BURST << DMA_TX_BURST_SHIFT), | ||||||
|  | +			LTQ_DMA_PCTRL); | ||||||
|  | +		break; | ||||||
|  | +	case 4: | ||||||
|  | +		ltq_dma_w32_mask(0x30, (DMA_PCTRL_4W_BURST << DMA_TX_BURST_SHIFT), | ||||||
|  | +			LTQ_DMA_PCTRL); | ||||||
|  | +		break; | ||||||
|  | +	case 2: | ||||||
|  | +		ltq_dma_w32_mask(0x30, (DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT), | ||||||
|  | +			LTQ_DMA_PCTRL); | ||||||
|  | +		break; | ||||||
|  |  	default: | ||||||
|  |  		break; | ||||||
|  |  	} | ||||||
| @@ -0,0 +1,86 @@ | |||||||
|  | From 2025bc9c3a949b65bfd0601f727678b37962c6c5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Fri, 4 Jun 2021 18:27:58 +0200 | ||||||
|  | Subject: [PATCH] MIPS: lantiq: enable all hardware interrupts on second VPE | ||||||
|  |  | ||||||
|  | This patch is needed to handle interrupts by the second VPE on the Lantiq | ||||||
|  | ARX100, xRX200, xRX300 and xRX330 SoCs. Switching some ICU interrupts to | ||||||
|  | the second VPE results in a hang. Currently, the vsmp_init_secondary() | ||||||
|  | function is responsible for enabling these interrupts. It only enables | ||||||
|  | Malta-specific interrupts (SW0, SW1, HW4 and HW5). | ||||||
|  |  | ||||||
|  | The MIPS core has 8 interrupts defined. On Lantiq SoCs, hardware | ||||||
|  | interrupts are wired to an ICU instance. Each VPE has an independent | ||||||
|  | instance of the ICU. The mapping of the ICU interrupts is shown below: | ||||||
|  | SW0(IP0) - IPI call, | ||||||
|  | SW1(IP1) - IPI resched, | ||||||
|  | HW0(IP2) - ICU 0-31, | ||||||
|  | HW1(IP3) - ICU 32-63, | ||||||
|  | HW2(IP4) - ICU 64-95, | ||||||
|  | HW3(IP5) - ICU 96-127, | ||||||
|  | HW4(IP6) - ICU 128-159, | ||||||
|  | HW5(IP7) - timer. | ||||||
|  |  | ||||||
|  | This patch enables all interrupt lines on the second VPE. | ||||||
|  |  | ||||||
|  | This problem affects multithreaded SoCs with a custom interrupt controller. | ||||||
|  | SOCs with 1004Kc core and newer use the MIPS GIC. At this point, I am aware | ||||||
|  | that the Realtek RTL839x and RTL930x SoCs may need a similar fix. In the | ||||||
|  | future, this may be replaced with some generic solution. | ||||||
|  |  | ||||||
|  | Tested on Lantiq xRX200. | ||||||
|  |  | ||||||
|  | Suggested-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | --- | ||||||
|  |  arch/mips/lantiq/prom.c | 26 ++++++++++++++++++++++++-- | ||||||
|  |  1 file changed, 24 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/prom.c | ||||||
|  | +++ b/arch/mips/lantiq/prom.c | ||||||
|  | @@ -37,6 +37,14 @@ static struct ltq_soc_info soc_info; | ||||||
|  |  /* for Multithreading (APRP), vpe.c will use it */ | ||||||
|  |  unsigned long cp0_memsize; | ||||||
|  |   | ||||||
|  | +/* | ||||||
|  | + * These structs are used to override vsmp_init_secondary() | ||||||
|  | + */ | ||||||
|  | +#if defined(CONFIG_MIPS_MT_SMP) | ||||||
|  | +extern const struct plat_smp_ops vsmp_smp_ops; | ||||||
|  | +static struct plat_smp_ops lantiq_smp_ops; | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  const char *get_system_type(void) | ||||||
|  |  { | ||||||
|  |  	return soc_info.sys_type; | ||||||
|  | @@ -100,6 +108,17 @@ void __init device_tree_init(void) | ||||||
|  |  	unflatten_and_copy_device_tree(); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +#if defined(CONFIG_MIPS_MT_SMP) | ||||||
|  | +static void lantiq_init_secondary(void) | ||||||
|  | +{ | ||||||
|  | +	/* | ||||||
|  | +	 * MIPS CPU startup function vsmp_init_secondary() will only | ||||||
|  | +	 * enable some of the interrupts for the second CPU/VPE. | ||||||
|  | +	 */ | ||||||
|  | +	set_c0_status(ST0_IM); | ||||||
|  | +} | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  void __init prom_init(void) | ||||||
|  |  { | ||||||
|  |  	/* call the soc specific detetcion code and get it to fill soc_info */ | ||||||
|  | @@ -111,7 +130,10 @@ void __init prom_init(void) | ||||||
|  |  	prom_init_cmdline(); | ||||||
|  |   | ||||||
|  |  #if defined(CONFIG_MIPS_MT_SMP) | ||||||
|  | -	if (register_vsmp_smp_ops()) | ||||||
|  | -		panic("failed to register_vsmp_smp_ops()"); | ||||||
|  | +	if (cpu_has_mipsmt) { | ||||||
|  | +		lantiq_smp_ops = vsmp_smp_ops; | ||||||
|  | +		lantiq_smp_ops.init_secondary = lantiq_init_secondary; | ||||||
|  | +		register_smp_ops(&lantiq_smp_ops); | ||||||
|  | +	} | ||||||
|  |  #endif | ||||||
|  |  } | ||||||
| @@ -0,0 +1,37 @@ | |||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -30,6 +30,7 @@ | ||||||
|  |  #include <linux/of_net.h> | ||||||
|  |  #include <linux/of_irq.h> | ||||||
|  |  #include <linux/of_platform.h> | ||||||
|  | +#include <linux/of_mdio.h> | ||||||
|  |   | ||||||
|  |  #include <asm/checksum.h> | ||||||
|  |   | ||||||
|  | @@ -553,7 +554,8 @@ static int | ||||||
|  |  ltq_etop_mdio_init(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int err; | ||||||
|  | +	struct device_node *mdio_np = NULL; | ||||||
|  | +	int err, ret; | ||||||
|  |   | ||||||
|  |  	priv->mii_bus = mdiobus_alloc(); | ||||||
|  |  	if (!priv->mii_bus) { | ||||||
|  | @@ -573,7 +575,15 @@ ltq_etop_mdio_init(struct net_device *de | ||||||
|  |  	priv->mii_bus->name = "ltq_mii"; | ||||||
|  |  	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", | ||||||
|  |  		priv->pdev->name, priv->pdev->id); | ||||||
|  | -	if (mdiobus_register(priv->mii_bus)) { | ||||||
|  | + | ||||||
|  | +	mdio_np = of_get_child_by_name(priv->pdev->dev.of_node, "mdio-bus"); | ||||||
|  | + | ||||||
|  | +	if (mdio_np) | ||||||
|  | +		ret = of_mdiobus_register(priv->mii_bus, mdio_np); | ||||||
|  | +	else | ||||||
|  | +		ret = mdiobus_register(priv->mii_bus); | ||||||
|  | + | ||||||
|  | +	if (ret) { | ||||||
|  |  		err = -ENXIO; | ||||||
|  |  		goto err_out_free_mdiobus; | ||||||
|  |  	} | ||||||
| @@ -0,0 +1,145 @@ | |||||||
|  | From 998ac358019e491217e752bc6dcbb3afb2a6fa3e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Sun, 19 Sep 2021 20:24:28 +0200 | ||||||
|  | Subject: [PATCH] net: lantiq: add support for jumbo frames | ||||||
|  |  | ||||||
|  | Add support for jumbo frames. Full support for jumbo frames requires | ||||||
|  | changes in the DSA switch driver (lantiq_gswip.c). | ||||||
|  |  | ||||||
|  | Tested on BT Hone Hub 5A. | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 64 +++++++++++++++++++++++++--- | ||||||
|  |  1 file changed, 57 insertions(+), 7 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -14,13 +14,15 @@ | ||||||
|  |  #include <linux/clk.h> | ||||||
|  |  #include <linux/delay.h> | ||||||
|  |   | ||||||
|  | +#include <linux/if_vlan.h> | ||||||
|  | + | ||||||
|  |  #include <linux/of_net.h> | ||||||
|  |  #include <linux/of_platform.h> | ||||||
|  |   | ||||||
|  |  #include <xway_dma.h> | ||||||
|  |   | ||||||
|  |  /* DMA */ | ||||||
|  | -#define XRX200_DMA_DATA_LEN	0x600 | ||||||
|  | +#define XRX200_DMA_DATA_LEN	(SZ_64K - 1) | ||||||
|  |  #define XRX200_DMA_RX		0 | ||||||
|  |  #define XRX200_DMA_TX		1 | ||||||
|  |   | ||||||
|  | @@ -106,7 +108,8 @@ static void xrx200_flush_dma(struct xrx2 | ||||||
|  |  			break; | ||||||
|  |   | ||||||
|  |  		desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | | ||||||
|  | -			    XRX200_DMA_DATA_LEN; | ||||||
|  | +			    (ch->priv->net_dev->mtu + VLAN_ETH_HLEN + | ||||||
|  | +			     ETH_FCS_LEN); | ||||||
|  |  		ch->dma.desc++; | ||||||
|  |  		ch->dma.desc %= LTQ_DESC_NUM; | ||||||
|  |  	} | ||||||
|  | @@ -154,19 +157,20 @@ static int xrx200_close(struct net_devic | ||||||
|  |   | ||||||
|  |  static int xrx200_alloc_skb(struct xrx200_chan *ch) | ||||||
|  |  { | ||||||
|  | +	int len = ch->priv->net_dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; | ||||||
|  |  	struct sk_buff *skb = ch->skb[ch->dma.desc]; | ||||||
|  |  	dma_addr_t mapping; | ||||||
|  |  	int ret = 0; | ||||||
|  |   | ||||||
|  |  	ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev, | ||||||
|  | -							  XRX200_DMA_DATA_LEN); | ||||||
|  | +							  len); | ||||||
|  |  	if (!ch->skb[ch->dma.desc]) { | ||||||
|  |  		ret = -ENOMEM; | ||||||
|  |  		goto skip; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data, | ||||||
|  | -				 XRX200_DMA_DATA_LEN, DMA_FROM_DEVICE); | ||||||
|  | +				 len, DMA_FROM_DEVICE); | ||||||
|  |  	if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) { | ||||||
|  |  		dev_kfree_skb_any(ch->skb[ch->dma.desc]); | ||||||
|  |  		ch->skb[ch->dma.desc] = skb; | ||||||
|  | @@ -179,8 +183,7 @@ static int xrx200_alloc_skb(struct xrx20 | ||||||
|  |  	wmb(); | ||||||
|  |  skip: | ||||||
|  |  	ch->dma.desc_base[ch->dma.desc].ctl = | ||||||
|  | -		LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | | ||||||
|  | -		XRX200_DMA_DATA_LEN; | ||||||
|  | +		LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | len; | ||||||
|  |   | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  | @@ -340,10 +343,57 @@ err_drop: | ||||||
|  |  	return NETDEV_TX_OK; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int | ||||||
|  | +xrx200_change_mtu(struct net_device *net_dev, int new_mtu) | ||||||
|  | +{ | ||||||
|  | +	struct xrx200_priv *priv = netdev_priv(net_dev); | ||||||
|  | +	struct xrx200_chan *ch_rx = &priv->chan_rx; | ||||||
|  | +	int old_mtu = net_dev->mtu; | ||||||
|  | +	bool running = false; | ||||||
|  | +	struct sk_buff *skb; | ||||||
|  | +	int curr_desc; | ||||||
|  | +	int ret = 0; | ||||||
|  | + | ||||||
|  | +	net_dev->mtu = new_mtu; | ||||||
|  | + | ||||||
|  | +	if (new_mtu <= old_mtu) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	running = netif_running(net_dev); | ||||||
|  | +	if (running) { | ||||||
|  | +		napi_disable(&ch_rx->napi); | ||||||
|  | +		ltq_dma_close(&ch_rx->dma); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	xrx200_poll_rx(&ch_rx->napi, LTQ_DESC_NUM); | ||||||
|  | +	curr_desc = ch_rx->dma.desc; | ||||||
|  | + | ||||||
|  | +	for (ch_rx->dma.desc = 0; ch_rx->dma.desc < LTQ_DESC_NUM; | ||||||
|  | +	     ch_rx->dma.desc++) { | ||||||
|  | +		skb = ch_rx->skb[ch_rx->dma.desc]; | ||||||
|  | +		ret = xrx200_alloc_skb(ch_rx); | ||||||
|  | +		if (ret) { | ||||||
|  | +			net_dev->mtu = old_mtu; | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | +		dev_kfree_skb_any(skb); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ch_rx->dma.desc = curr_desc; | ||||||
|  | +	if (running) { | ||||||
|  | +		napi_enable(&ch_rx->napi); | ||||||
|  | +		ltq_dma_open(&ch_rx->dma); | ||||||
|  | +		ltq_dma_enable_irq(&ch_rx->dma); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static const struct net_device_ops xrx200_netdev_ops = { | ||||||
|  |  	.ndo_open		= xrx200_open, | ||||||
|  |  	.ndo_stop		= xrx200_close, | ||||||
|  |  	.ndo_start_xmit		= xrx200_start_xmit, | ||||||
|  | +	.ndo_change_mtu		= xrx200_change_mtu, | ||||||
|  |  	.ndo_set_mac_address	= eth_mac_addr, | ||||||
|  |  	.ndo_validate_addr	= eth_validate_addr, | ||||||
|  |  }; | ||||||
|  | @@ -454,7 +504,7 @@ static int xrx200_probe(struct platform_ | ||||||
|  |  	net_dev->netdev_ops = &xrx200_netdev_ops; | ||||||
|  |  	SET_NETDEV_DEV(net_dev, dev); | ||||||
|  |  	net_dev->min_mtu = ETH_ZLEN; | ||||||
|  | -	net_dev->max_mtu = XRX200_DMA_DATA_LEN; | ||||||
|  | +	net_dev->max_mtu = XRX200_DMA_DATA_LEN - VLAN_ETH_HLEN - ETH_FCS_LEN; | ||||||
|  |   | ||||||
|  |  	/* load the memory ranges */ | ||||||
|  |  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
| @@ -0,0 +1,122 @@ | |||||||
|  | From 1488fc204568f707fe2a42a913788c00a95af30e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Fri, 17 Dec 2021 01:07:40 +0100 | ||||||
|  | Subject: [PATCH] net: lantiq_xrx200: increase buffer reservation | ||||||
|  |  | ||||||
|  | If the user sets a lower mtu on the CPU port than on the switch, | ||||||
|  | then DMA inserts a few more bytes into the buffer than expected. | ||||||
|  | In the worst case, it may exceed the size of the buffer. The | ||||||
|  | experiments showed that the buffer should be a multiple of the | ||||||
|  | burst length value. This patch rounds the length of the rx buffer | ||||||
|  | upwards and fixes this bug. The reservation of FCS space in the | ||||||
|  | buffer has been removed as PMAC strips the FCS. | ||||||
|  |  | ||||||
|  | Fixes: 998ac358019e ("net: lantiq: add support for jumbo frames") | ||||||
|  | Reported-by: Thomas Nixon <tom@tomn.co.uk> | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 34 ++++++++++++++++++++-------- | ||||||
|  |  1 file changed, 24 insertions(+), 10 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -70,6 +70,8 @@ struct xrx200_priv { | ||||||
|  |  	struct xrx200_chan chan_tx; | ||||||
|  |  	struct xrx200_chan chan_rx; | ||||||
|  |   | ||||||
|  | +	u16 rx_buf_size; | ||||||
|  | + | ||||||
|  |  	struct net_device *net_dev; | ||||||
|  |  	struct device *dev; | ||||||
|  |   | ||||||
|  | @@ -96,6 +98,16 @@ static void xrx200_pmac_mask(struct xrx2 | ||||||
|  |  	xrx200_pmac_w32(priv, val, offset); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int xrx200_max_frame_len(int mtu) | ||||||
|  | +{ | ||||||
|  | +	return VLAN_ETH_HLEN + mtu; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int xrx200_buffer_size(int mtu) | ||||||
|  | +{ | ||||||
|  | +	return round_up(xrx200_max_frame_len(mtu), 4 * XRX200_DMA_BURST_LEN); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* drop all the packets from the DMA ring */ | ||||||
|  |  static void xrx200_flush_dma(struct xrx200_chan *ch) | ||||||
|  |  { | ||||||
|  | @@ -108,8 +120,7 @@ static void xrx200_flush_dma(struct xrx2 | ||||||
|  |  			break; | ||||||
|  |   | ||||||
|  |  		desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | | ||||||
|  | -			    (ch->priv->net_dev->mtu + VLAN_ETH_HLEN + | ||||||
|  | -			     ETH_FCS_LEN); | ||||||
|  | +			    ch->priv->rx_buf_size; | ||||||
|  |  		ch->dma.desc++; | ||||||
|  |  		ch->dma.desc %= LTQ_DESC_NUM; | ||||||
|  |  	} | ||||||
|  | @@ -157,21 +168,21 @@ static int xrx200_close(struct net_devic | ||||||
|  |   | ||||||
|  |  static int xrx200_alloc_skb(struct xrx200_chan *ch) | ||||||
|  |  { | ||||||
|  | -	int len = ch->priv->net_dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; | ||||||
|  |  	struct sk_buff *skb = ch->skb[ch->dma.desc]; | ||||||
|  | +	struct xrx200_priv *priv = ch->priv; | ||||||
|  |  	dma_addr_t mapping; | ||||||
|  |  	int ret = 0; | ||||||
|  |   | ||||||
|  | -	ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev, | ||||||
|  | -							  len); | ||||||
|  | +	ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(priv->net_dev, | ||||||
|  | +							  priv->rx_buf_size); | ||||||
|  |  	if (!ch->skb[ch->dma.desc]) { | ||||||
|  |  		ret = -ENOMEM; | ||||||
|  |  		goto skip; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data, | ||||||
|  | -				 len, DMA_FROM_DEVICE); | ||||||
|  | -	if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) { | ||||||
|  | +	mapping = dma_map_single(priv->dev, ch->skb[ch->dma.desc]->data, | ||||||
|  | +				 priv->rx_buf_size, DMA_FROM_DEVICE); | ||||||
|  | +	if (unlikely(dma_mapping_error(priv->dev, mapping))) { | ||||||
|  |  		dev_kfree_skb_any(ch->skb[ch->dma.desc]); | ||||||
|  |  		ch->skb[ch->dma.desc] = skb; | ||||||
|  |  		ret = -ENOMEM; | ||||||
|  | @@ -183,7 +194,7 @@ static int xrx200_alloc_skb(struct xrx20 | ||||||
|  |  	wmb(); | ||||||
|  |  skip: | ||||||
|  |  	ch->dma.desc_base[ch->dma.desc].ctl = | ||||||
|  | -		LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | len; | ||||||
|  | +		LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | priv->rx_buf_size; | ||||||
|  |   | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  | @@ -355,6 +366,7 @@ xrx200_change_mtu(struct net_device *net | ||||||
|  |  	int ret = 0; | ||||||
|  |   | ||||||
|  |  	net_dev->mtu = new_mtu; | ||||||
|  | +	priv->rx_buf_size = xrx200_buffer_size(new_mtu); | ||||||
|  |   | ||||||
|  |  	if (new_mtu <= old_mtu) | ||||||
|  |  		return ret; | ||||||
|  | @@ -374,6 +386,7 @@ xrx200_change_mtu(struct net_device *net | ||||||
|  |  		ret = xrx200_alloc_skb(ch_rx); | ||||||
|  |  		if (ret) { | ||||||
|  |  			net_dev->mtu = old_mtu; | ||||||
|  | +			priv->rx_buf_size = xrx200_buffer_size(old_mtu); | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  |  		dev_kfree_skb_any(skb); | ||||||
|  | @@ -504,7 +517,8 @@ static int xrx200_probe(struct platform_ | ||||||
|  |  	net_dev->netdev_ops = &xrx200_netdev_ops; | ||||||
|  |  	SET_NETDEV_DEV(net_dev, dev); | ||||||
|  |  	net_dev->min_mtu = ETH_ZLEN; | ||||||
|  | -	net_dev->max_mtu = XRX200_DMA_DATA_LEN - VLAN_ETH_HLEN - ETH_FCS_LEN; | ||||||
|  | +	net_dev->max_mtu = XRX200_DMA_DATA_LEN - xrx200_max_frame_len(0); | ||||||
|  | +	priv->rx_buf_size = xrx200_buffer_size(ETH_DATA_LEN); | ||||||
|  |   | ||||||
|  |  	/* load the memory ranges */ | ||||||
|  |  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
| @@ -0,0 +1,104 @@ | |||||||
|  | From c3e6b2c35b34214c58c1e90d65dab5f5393608e7 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Mon, 3 Jan 2022 20:43:16 +0100 | ||||||
|  | Subject: [PATCH] net: lantiq_xrx200: add ingress SG DMA support | ||||||
|  |  | ||||||
|  | This patch adds support for scatter gather DMA. DMA in PMAC splits | ||||||
|  | the packet into several buffers when the MTU on the CPU port is | ||||||
|  | less than the MTU of the switch. The first buffer starts at an | ||||||
|  | offset of NET_IP_ALIGN. In subsequent buffers, dma ignores the | ||||||
|  | offset. Thanks to this patch, the user can still connect to the | ||||||
|  | device in such a situation. For normal configurations, the patch | ||||||
|  | has no effect on performance. | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 47 +++++++++++++++++++++++----- | ||||||
|  |  1 file changed, 40 insertions(+), 7 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -26,6 +26,9 @@ | ||||||
|  |  #define XRX200_DMA_RX		0 | ||||||
|  |  #define XRX200_DMA_TX		1 | ||||||
|  |   | ||||||
|  | +#define XRX200_DMA_PACKET_COMPLETE	0 | ||||||
|  | +#define XRX200_DMA_PACKET_IN_PROGRESS	1 | ||||||
|  | + | ||||||
|  |  /* cpu port mac */ | ||||||
|  |  #define PMAC_RX_IPG		0x0024 | ||||||
|  |  #define PMAC_RX_IPG_MASK	0xf | ||||||
|  | @@ -61,6 +64,9 @@ struct xrx200_chan { | ||||||
|  |  	struct ltq_dma_channel dma; | ||||||
|  |  	struct sk_buff *skb[LTQ_DESC_NUM]; | ||||||
|  |   | ||||||
|  | +	struct sk_buff *skb_head; | ||||||
|  | +	struct sk_buff *skb_tail; | ||||||
|  | + | ||||||
|  |  	struct xrx200_priv *priv; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | @@ -204,7 +210,8 @@ static int xrx200_hw_receive(struct xrx2 | ||||||
|  |  	struct xrx200_priv *priv = ch->priv; | ||||||
|  |  	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; | ||||||
|  |  	struct sk_buff *skb = ch->skb[ch->dma.desc]; | ||||||
|  | -	int len = (desc->ctl & LTQ_DMA_SIZE_MASK); | ||||||
|  | +	u32 ctl = desc->ctl; | ||||||
|  | +	int len = (ctl & LTQ_DMA_SIZE_MASK); | ||||||
|  |  	struct net_device *net_dev = priv->net_dev; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  | @@ -220,12 +227,36 @@ static int xrx200_hw_receive(struct xrx2 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	skb_put(skb, len); | ||||||
|  | -	skb->protocol = eth_type_trans(skb, net_dev); | ||||||
|  | -	netif_receive_skb(skb); | ||||||
|  | -	net_dev->stats.rx_packets++; | ||||||
|  | -	net_dev->stats.rx_bytes += len; | ||||||
|  |   | ||||||
|  | -	return 0; | ||||||
|  | +	/* add buffers to skb via skb->frag_list */ | ||||||
|  | +	if (ctl & LTQ_DMA_SOP) { | ||||||
|  | +		ch->skb_head = skb; | ||||||
|  | +		ch->skb_tail = skb; | ||||||
|  | +	} else if (ch->skb_head) { | ||||||
|  | +		if (ch->skb_head == ch->skb_tail) | ||||||
|  | +			skb_shinfo(ch->skb_tail)->frag_list = skb; | ||||||
|  | +		else | ||||||
|  | +			ch->skb_tail->next = skb; | ||||||
|  | +		ch->skb_tail = skb; | ||||||
|  | +		skb_reserve(ch->skb_tail, -NET_IP_ALIGN); | ||||||
|  | +		ch->skb_head->len += skb->len; | ||||||
|  | +		ch->skb_head->data_len += skb->len; | ||||||
|  | +		ch->skb_head->truesize += skb->truesize; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (ctl & LTQ_DMA_EOP) { | ||||||
|  | +		ch->skb_head->protocol = eth_type_trans(ch->skb_head, net_dev); | ||||||
|  | +		netif_receive_skb(ch->skb_head); | ||||||
|  | +		net_dev->stats.rx_packets++; | ||||||
|  | +		net_dev->stats.rx_bytes += ch->skb_head->len; | ||||||
|  | +		ch->skb_head = NULL; | ||||||
|  | +		ch->skb_tail = NULL; | ||||||
|  | +		ret = XRX200_DMA_PACKET_COMPLETE; | ||||||
|  | +	} else { | ||||||
|  | +		ret = XRX200_DMA_PACKET_IN_PROGRESS; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int xrx200_poll_rx(struct napi_struct *napi, int budget) | ||||||
|  | @@ -240,7 +271,9 @@ static int xrx200_poll_rx(struct napi_st | ||||||
|  |   | ||||||
|  |  		if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) { | ||||||
|  |  			ret = xrx200_hw_receive(ch); | ||||||
|  | -			if (ret) | ||||||
|  | +			if (ret == XRX200_DMA_PACKET_IN_PROGRESS) | ||||||
|  | +				continue; | ||||||
|  | +			if (ret != XRX200_DMA_PACKET_COMPLETE) | ||||||
|  |  				return ret; | ||||||
|  |  			rx++; | ||||||
|  |  		} else { | ||||||
| @@ -0,0 +1,275 @@ | |||||||
|  | From a09d042b086202735c4ed64573cdd79933020001 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Mon, 22 Mar 2021 21:37:15 +0100 | ||||||
|  | Subject: [PATCH] net: dsa: lantiq: allow to use all GPHYs on xRX300 and xRX330 | ||||||
|  |  | ||||||
|  | This patch allows to use all PHYs on GRX300 and GRX330. The ARX300 | ||||||
|  | has 3 and the GRX330 has 4 integrated PHYs connected to different | ||||||
|  | ports compared to VRX200. Each integrated PHY can work as single | ||||||
|  | Gigabit Ethernet PHY (GMII) or as double Fast Ethernet PHY (MII). | ||||||
|  |  | ||||||
|  | Allowed port configurations: | ||||||
|  |  | ||||||
|  | xRX200: | ||||||
|  | GMAC0: RGMII, MII, REVMII or RMII port | ||||||
|  | GMAC1: RGMII, MII, REVMII or RMII port | ||||||
|  | GMAC2: GPHY0 (GMII) | ||||||
|  | GMAC3: GPHY0 (MII) | ||||||
|  | GMAC4: GPHY1 (GMII) | ||||||
|  | GMAC5: GPHY1 (MII) or RGMII port | ||||||
|  |  | ||||||
|  | xRX300: | ||||||
|  | GMAC0: RGMII port | ||||||
|  | GMAC1: GPHY2 (GMII) | ||||||
|  | GMAC2: GPHY0 (GMII) | ||||||
|  | GMAC3: GPHY0 (MII) | ||||||
|  | GMAC4: GPHY1 (GMII) | ||||||
|  | GMAC5: GPHY1 (MII) or RGMII port | ||||||
|  |  | ||||||
|  | xRX330: | ||||||
|  | GMAC0: RGMII, GMII or RMII port | ||||||
|  | GMAC1: GPHY2 (GMII) | ||||||
|  | GMAC2: GPHY0 (GMII) | ||||||
|  | GMAC3: GPHY0 (MII) or GPHY3 (GMII) | ||||||
|  | GMAC4: GPHY1 (GMII) | ||||||
|  | GMAC5: GPHY1 (MII), RGMII or RMII port | ||||||
|  |  | ||||||
|  | Tested on D-Link DWR966 (xRX330) with OpenWRT. | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Acked-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/dsa/lantiq_gswip.c | 142 ++++++++++++++++++++++++++------- | ||||||
|  |  1 file changed, 113 insertions(+), 29 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/dsa/lantiq_gswip.c | ||||||
|  | +++ b/drivers/net/dsa/lantiq_gswip.c | ||||||
|  | @@ -1,6 +1,6 @@ | ||||||
|  |  // SPDX-License-Identifier: GPL-2.0 | ||||||
|  |  /* | ||||||
|  | - * Lantiq / Intel GSWIP switch driver for VRX200 SoCs | ||||||
|  | + * Lantiq / Intel GSWIP switch driver for VRX200, xRX300 and xRX330 SoCs | ||||||
|  |   * | ||||||
|  |   * Copyright (C) 2010 Lantiq Deutschland | ||||||
|  |   * Copyright (C) 2012 John Crispin <john@phrozen.org> | ||||||
|  | @@ -104,6 +104,7 @@ | ||||||
|  |  #define  GSWIP_MII_CFG_MODE_RMIIP	0x2 | ||||||
|  |  #define  GSWIP_MII_CFG_MODE_RMIIM	0x3 | ||||||
|  |  #define  GSWIP_MII_CFG_MODE_RGMII	0x4 | ||||||
|  | +#define  GSWIP_MII_CFG_MODE_GMII	0x9 | ||||||
|  |  #define  GSWIP_MII_CFG_MODE_MASK	0xf | ||||||
|  |  #define  GSWIP_MII_CFG_RATE_M2P5	0x00 | ||||||
|  |  #define  GSWIP_MII_CFG_RATE_M25	0x10 | ||||||
|  | @@ -241,6 +242,7 @@ | ||||||
|  |  struct gswip_hw_info { | ||||||
|  |  	int max_ports; | ||||||
|  |  	int cpu_port; | ||||||
|  | +	const struct dsa_switch_ops *ops; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct xway_gphy_match_data { | ||||||
|  | @@ -1438,12 +1440,42 @@ static int gswip_port_fdb_dump(struct ds | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void gswip_phylink_validate(struct dsa_switch *ds, int port, | ||||||
|  | -				   unsigned long *supported, | ||||||
|  | -				   struct phylink_link_state *state) | ||||||
|  | +static void gswip_phylink_set_capab(unsigned long *supported, | ||||||
|  | +				    struct phylink_link_state *state) | ||||||
|  |  { | ||||||
|  |  	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; | ||||||
|  |   | ||||||
|  | +	/* Allow all the expected bits */ | ||||||
|  | +	phylink_set(mask, Autoneg); | ||||||
|  | +	phylink_set_port_modes(mask); | ||||||
|  | +	phylink_set(mask, Pause); | ||||||
|  | +	phylink_set(mask, Asym_Pause); | ||||||
|  | + | ||||||
|  | +	/* With the exclusion of MII, Reverse MII and Reduced MII, we | ||||||
|  | +	 * support Gigabit, including Half duplex | ||||||
|  | +	 */ | ||||||
|  | +	if (state->interface != PHY_INTERFACE_MODE_MII && | ||||||
|  | +	    state->interface != PHY_INTERFACE_MODE_REVMII && | ||||||
|  | +	    state->interface != PHY_INTERFACE_MODE_RMII) { | ||||||
|  | +		phylink_set(mask, 1000baseT_Full); | ||||||
|  | +		phylink_set(mask, 1000baseT_Half); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	phylink_set(mask, 10baseT_Half); | ||||||
|  | +	phylink_set(mask, 10baseT_Full); | ||||||
|  | +	phylink_set(mask, 100baseT_Half); | ||||||
|  | +	phylink_set(mask, 100baseT_Full); | ||||||
|  | + | ||||||
|  | +	bitmap_and(supported, supported, mask, | ||||||
|  | +		   __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  | +	bitmap_and(state->advertising, state->advertising, mask, | ||||||
|  | +		   __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, | ||||||
|  | +					  unsigned long *supported, | ||||||
|  | +					  struct phylink_link_state *state) | ||||||
|  | +{ | ||||||
|  |  	switch (port) { | ||||||
|  |  	case 0: | ||||||
|  |  	case 1: | ||||||
|  | @@ -1470,38 +1502,54 @@ static void gswip_phylink_validate(struc | ||||||
|  |  		return; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	/* Allow all the expected bits */ | ||||||
|  | -	phylink_set(mask, Autoneg); | ||||||
|  | -	phylink_set_port_modes(mask); | ||||||
|  | -	phylink_set(mask, Pause); | ||||||
|  | -	phylink_set(mask, Asym_Pause); | ||||||
|  | +	gswip_phylink_set_capab(supported, state); | ||||||
|  |   | ||||||
|  | -	/* With the exclusion of MII, Reverse MII and Reduced MII, we | ||||||
|  | -	 * support Gigabit, including Half duplex | ||||||
|  | -	 */ | ||||||
|  | -	if (state->interface != PHY_INTERFACE_MODE_MII && | ||||||
|  | -	    state->interface != PHY_INTERFACE_MODE_REVMII && | ||||||
|  | -	    state->interface != PHY_INTERFACE_MODE_RMII) { | ||||||
|  | -		phylink_set(mask, 1000baseT_Full); | ||||||
|  | -		phylink_set(mask, 1000baseT_Half); | ||||||
|  | +	return; | ||||||
|  | + | ||||||
|  | +unsupported: | ||||||
|  | +	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  | +	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", | ||||||
|  | +		phy_modes(state->interface), port); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port, | ||||||
|  | +					  unsigned long *supported, | ||||||
|  | +					  struct phylink_link_state *state) | ||||||
|  | +{ | ||||||
|  | +	switch (port) { | ||||||
|  | +	case 0: | ||||||
|  | +		if (!phy_interface_mode_is_rgmii(state->interface) && | ||||||
|  | +		    state->interface != PHY_INTERFACE_MODE_GMII && | ||||||
|  | +		    state->interface != PHY_INTERFACE_MODE_RMII) | ||||||
|  | +			goto unsupported; | ||||||
|  | +		break; | ||||||
|  | +	case 1: | ||||||
|  | +	case 2: | ||||||
|  | +	case 3: | ||||||
|  | +	case 4: | ||||||
|  | +		if (state->interface != PHY_INTERFACE_MODE_INTERNAL) | ||||||
|  | +			goto unsupported; | ||||||
|  | +		break; | ||||||
|  | +	case 5: | ||||||
|  | +		if (!phy_interface_mode_is_rgmii(state->interface) && | ||||||
|  | +		    state->interface != PHY_INTERFACE_MODE_INTERNAL && | ||||||
|  | +		    state->interface != PHY_INTERFACE_MODE_RMII) | ||||||
|  | +			goto unsupported; | ||||||
|  | +		break; | ||||||
|  | +	default: | ||||||
|  | +		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  | +		dev_err(ds->dev, "Unsupported port: %i\n", port); | ||||||
|  | +		return; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	phylink_set(mask, 10baseT_Half); | ||||||
|  | -	phylink_set(mask, 10baseT_Full); | ||||||
|  | -	phylink_set(mask, 100baseT_Half); | ||||||
|  | -	phylink_set(mask, 100baseT_Full); | ||||||
|  | +	gswip_phylink_set_capab(supported, state); | ||||||
|  |   | ||||||
|  | -	bitmap_and(supported, supported, mask, | ||||||
|  | -		   __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  | -	bitmap_and(state->advertising, state->advertising, mask, | ||||||
|  | -		   __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  |  	return; | ||||||
|  |   | ||||||
|  |  unsupported: | ||||||
|  |  	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  |  	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", | ||||||
|  |  		phy_modes(state->interface), port); | ||||||
|  | -	return; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void gswip_port_set_link(struct gswip_priv *priv, int port, bool link) | ||||||
|  | @@ -1636,6 +1684,9 @@ static void gswip_phylink_mac_config(str | ||||||
|  |  	case PHY_INTERFACE_MODE_RGMII_TXID: | ||||||
|  |  		miicfg |= GSWIP_MII_CFG_MODE_RGMII; | ||||||
|  |  		break; | ||||||
|  | +	case PHY_INTERFACE_MODE_GMII: | ||||||
|  | +		miicfg |= GSWIP_MII_CFG_MODE_GMII; | ||||||
|  | +		break; | ||||||
|  |  	default: | ||||||
|  |  		dev_err(ds->dev, | ||||||
|  |  			"Unsupported interface: %d\n", state->interface); | ||||||
|  | @@ -1762,7 +1813,7 @@ static int gswip_get_sset_count(struct d | ||||||
|  |  	return ARRAY_SIZE(gswip_rmon_cnt); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static const struct dsa_switch_ops gswip_switch_ops = { | ||||||
|  | +static const struct dsa_switch_ops gswip_xrx200_switch_ops = { | ||||||
|  |  	.get_tag_protocol	= gswip_get_tag_protocol, | ||||||
|  |  	.setup			= gswip_setup, | ||||||
|  |  	.port_enable		= gswip_port_enable, | ||||||
|  | @@ -1778,7 +1829,31 @@ static const struct dsa_switch_ops gswip | ||||||
|  |  	.port_fdb_add		= gswip_port_fdb_add, | ||||||
|  |  	.port_fdb_del		= gswip_port_fdb_del, | ||||||
|  |  	.port_fdb_dump		= gswip_port_fdb_dump, | ||||||
|  | -	.phylink_validate	= gswip_phylink_validate, | ||||||
|  | +	.phylink_validate	= gswip_xrx200_phylink_validate, | ||||||
|  | +	.phylink_mac_config	= gswip_phylink_mac_config, | ||||||
|  | +	.phylink_mac_link_down	= gswip_phylink_mac_link_down, | ||||||
|  | +	.phylink_mac_link_up	= gswip_phylink_mac_link_up, | ||||||
|  | +	.get_strings		= gswip_get_strings, | ||||||
|  | +	.get_ethtool_stats	= gswip_get_ethtool_stats, | ||||||
|  | +	.get_sset_count		= gswip_get_sset_count, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct dsa_switch_ops gswip_xrx300_switch_ops = { | ||||||
|  | +	.get_tag_protocol	= gswip_get_tag_protocol, | ||||||
|  | +	.setup			= gswip_setup, | ||||||
|  | +	.port_enable		= gswip_port_enable, | ||||||
|  | +	.port_disable		= gswip_port_disable, | ||||||
|  | +	.port_bridge_join	= gswip_port_bridge_join, | ||||||
|  | +	.port_bridge_leave	= gswip_port_bridge_leave, | ||||||
|  | +	.port_fast_age		= gswip_port_fast_age, | ||||||
|  | +	.port_vlan_filtering	= gswip_port_vlan_filtering, | ||||||
|  | +	.port_vlan_add		= gswip_port_vlan_add, | ||||||
|  | +	.port_vlan_del		= gswip_port_vlan_del, | ||||||
|  | +	.port_stp_state_set	= gswip_port_stp_state_set, | ||||||
|  | +	.port_fdb_add		= gswip_port_fdb_add, | ||||||
|  | +	.port_fdb_del		= gswip_port_fdb_del, | ||||||
|  | +	.port_fdb_dump		= gswip_port_fdb_dump, | ||||||
|  | +	.phylink_validate	= gswip_xrx300_phylink_validate, | ||||||
|  |  	.phylink_mac_config	= gswip_phylink_mac_config, | ||||||
|  |  	.phylink_mac_link_down	= gswip_phylink_mac_link_down, | ||||||
|  |  	.phylink_mac_link_up	= gswip_phylink_mac_link_up, | ||||||
|  | @@ -2042,7 +2117,7 @@ static int gswip_probe(struct platform_d | ||||||
|  |  	priv->ds->dev = dev; | ||||||
|  |  	priv->ds->num_ports = priv->hw_info->max_ports; | ||||||
|  |  	priv->ds->priv = priv; | ||||||
|  | -	priv->ds->ops = &gswip_switch_ops; | ||||||
|  | +	priv->ds->ops = priv->hw_info->ops; | ||||||
|  |  	priv->dev = dev; | ||||||
|  |  	version = gswip_switch_r(priv, GSWIP_VERSION); | ||||||
|  |   | ||||||
|  | @@ -2126,10 +2201,19 @@ static int gswip_remove(struct platform_ | ||||||
|  |  static const struct gswip_hw_info gswip_xrx200 = { | ||||||
|  |  	.max_ports = 7, | ||||||
|  |  	.cpu_port = 6, | ||||||
|  | +	.ops = &gswip_xrx200_switch_ops, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct gswip_hw_info gswip_xrx300 = { | ||||||
|  | +	.max_ports = 7, | ||||||
|  | +	.cpu_port = 6, | ||||||
|  | +	.ops = &gswip_xrx300_switch_ops, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const struct of_device_id gswip_of_match[] = { | ||||||
|  |  	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 }, | ||||||
|  | +	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 }, | ||||||
|  | +	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 }, | ||||||
|  |  	{}, | ||||||
|  |  }; | ||||||
|  |  MODULE_DEVICE_TABLE(of, gswip_of_match); | ||||||
| @@ -0,0 +1,127 @@ | |||||||
|  | From c40bb4fedcd6b8b6a714da5dd466eb88ed2652d1 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Wed, 9 Mar 2022 00:04:57 +0100 | ||||||
|  | Subject: net: dsa: lantiq_gswip: enable jumbo frames on GSWIP | ||||||
|  |  | ||||||
|  | This enables non-standard MTUs on a per-port basis, with the overall | ||||||
|  | frame size set based on the CPU port. | ||||||
|  |  | ||||||
|  | When the MTU is not changed, this should have no effect. | ||||||
|  |  | ||||||
|  | Long packets crash the switch with MTUs of greater than 2526, so the | ||||||
|  | maximum is limited for now. Medium packets are sometimes dropped (e.g. | ||||||
|  | TCP over 2477, UDP over 2516-2519, ICMP over 2526), Hence an MTU value | ||||||
|  | of 2400 seems safe. | ||||||
|  |  | ||||||
|  | Signed-off-by: Thomas Nixon <tom@tomn.co.uk> | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Link: https://lore.kernel.org/r/20220308230457.1599237-1-olek2@wp.pl | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/dsa/lantiq_gswip.c | 53 ++++++++++++++++++++++++++++++++++++++---- | ||||||
|  |  1 file changed, 49 insertions(+), 4 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/dsa/lantiq_gswip.c | ||||||
|  | +++ b/drivers/net/dsa/lantiq_gswip.c | ||||||
|  | @@ -213,6 +213,7 @@ | ||||||
|  |  #define  GSWIP_MAC_CTRL_0_GMII_MII	0x0001 | ||||||
|  |  #define  GSWIP_MAC_CTRL_0_GMII_RGMII	0x0002 | ||||||
|  |  #define GSWIP_MAC_CTRL_2p(p)		(0x905 + ((p) * 0xC)) | ||||||
|  | +#define GSWIP_MAC_CTRL_2_LCHKL		BIT(2) /* Frame Length Check Long Enable */ | ||||||
|  |  #define GSWIP_MAC_CTRL_2_MLEN		BIT(3) /* Maximum Untagged Frame Lnegth */ | ||||||
|  |   | ||||||
|  |  /* Ethernet Switch Fetch DMA Port Control Register */ | ||||||
|  | @@ -239,6 +240,15 @@ | ||||||
|  |   | ||||||
|  |  #define XRX200_GPHY_FW_ALIGN	(16 * 1024) | ||||||
|  |   | ||||||
|  | +/* Maximum packet size supported by the switch. In theory this should be 10240, | ||||||
|  | + * but long packets currently cause lock-ups with an MTU of over 2526. Medium | ||||||
|  | + * packets are sometimes dropped (e.g. TCP over 2477, UDP over 2516-2519, ICMP | ||||||
|  | + * over 2526), hence an MTU value of 2400 seems safe. This issue only affects | ||||||
|  | + * packet reception. This is probably caused by the PPA engine, which is on the | ||||||
|  | + * RX part of the device. Packet transmission works properly up to 10240. | ||||||
|  | + */ | ||||||
|  | +#define GSWIP_MAX_PACKET_LENGTH	2400 | ||||||
|  | + | ||||||
|  |  struct gswip_hw_info { | ||||||
|  |  	int max_ports; | ||||||
|  |  	int cpu_port; | ||||||
|  | @@ -858,10 +868,6 @@ static int gswip_setup(struct dsa_switch | ||||||
|  |  	gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS, | ||||||
|  |  			  GSWIP_PCE_PCTRL_0p(cpu_port)); | ||||||
|  |   | ||||||
|  | -	gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN, | ||||||
|  | -			  GSWIP_MAC_CTRL_2p(cpu_port)); | ||||||
|  | -	gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8 + ETH_FCS_LEN, | ||||||
|  | -		       GSWIP_MAC_FLEN); | ||||||
|  |  	gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD, | ||||||
|  |  			  GSWIP_BM_QUEUE_GCTRL); | ||||||
|  |   | ||||||
|  | @@ -878,6 +884,8 @@ static int gswip_setup(struct dsa_switch | ||||||
|  |  		return err; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	ds->mtu_enforcement_ingress = true; | ||||||
|  | + | ||||||
|  |  	gswip_port_enable(ds, cpu_port, NULL); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -1472,6 +1480,39 @@ static void gswip_phylink_set_capab(unsi | ||||||
|  |  		   __ETHTOOL_LINK_MODE_MASK_NBITS); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int gswip_port_max_mtu(struct dsa_switch *ds, int port) | ||||||
|  | +{ | ||||||
|  | +	/* Includes 8 bytes for special header. */ | ||||||
|  | +	return GSWIP_MAX_PACKET_LENGTH - VLAN_ETH_HLEN - ETH_FCS_LEN; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int gswip_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) | ||||||
|  | +{ | ||||||
|  | +	struct gswip_priv *priv = ds->priv; | ||||||
|  | +	int cpu_port = priv->hw_info->cpu_port; | ||||||
|  | + | ||||||
|  | +	/* CPU port always has maximum mtu of user ports, so use it to set | ||||||
|  | +	 * switch frame size, including 8 byte special header. | ||||||
|  | +	 */ | ||||||
|  | +	if (port == cpu_port) { | ||||||
|  | +		new_mtu += 8; | ||||||
|  | +		gswip_switch_w(priv, VLAN_ETH_HLEN + new_mtu + ETH_FCS_LEN, | ||||||
|  | +			       GSWIP_MAC_FLEN); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Enable MLEN for ports with non-standard MTUs, including the special | ||||||
|  | +	 * header on the CPU port added above. | ||||||
|  | +	 */ | ||||||
|  | +	if (new_mtu != ETH_DATA_LEN) | ||||||
|  | +		gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN, | ||||||
|  | +				  GSWIP_MAC_CTRL_2p(port)); | ||||||
|  | +	else | ||||||
|  | +		gswip_switch_mask(priv, GSWIP_MAC_CTRL_2_MLEN, 0, | ||||||
|  | +				  GSWIP_MAC_CTRL_2p(port)); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, | ||||||
|  |  					  unsigned long *supported, | ||||||
|  |  					  struct phylink_link_state *state) | ||||||
|  | @@ -1829,6 +1870,8 @@ static const struct dsa_switch_ops gswip | ||||||
|  |  	.port_fdb_add		= gswip_port_fdb_add, | ||||||
|  |  	.port_fdb_del		= gswip_port_fdb_del, | ||||||
|  |  	.port_fdb_dump		= gswip_port_fdb_dump, | ||||||
|  | +	.port_change_mtu	= gswip_port_change_mtu, | ||||||
|  | +	.port_max_mtu		= gswip_port_max_mtu, | ||||||
|  |  	.phylink_validate	= gswip_xrx200_phylink_validate, | ||||||
|  |  	.phylink_mac_config	= gswip_phylink_mac_config, | ||||||
|  |  	.phylink_mac_link_down	= gswip_phylink_mac_link_down, | ||||||
|  | @@ -1853,6 +1896,8 @@ static const struct dsa_switch_ops gswip | ||||||
|  |  	.port_fdb_add		= gswip_port_fdb_add, | ||||||
|  |  	.port_fdb_del		= gswip_port_fdb_del, | ||||||
|  |  	.port_fdb_dump		= gswip_port_fdb_dump, | ||||||
|  | +	.port_change_mtu	= gswip_port_change_mtu, | ||||||
|  | +	.port_max_mtu		= gswip_port_max_mtu, | ||||||
|  |  	.phylink_validate	= gswip_xrx300_phylink_validate, | ||||||
|  |  	.phylink_mac_config	= gswip_phylink_mac_config, | ||||||
|  |  	.phylink_mac_link_down	= gswip_phylink_mac_link_down, | ||||||
| @@ -0,0 +1,126 @@ | |||||||
|  | From 14d4e308e0aa0b78dc7a059716861a4380de3535 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 14 Sep 2021 23:21:02 +0200 | ||||||
|  | Subject: [PATCH 5/5] net: lantiq: configure the burst length in ethernet | ||||||
|  |  drivers | ||||||
|  |  | ||||||
|  | Configure the burst length in Ethernet drivers. This improves | ||||||
|  | Ethernet performance by 58%. According to the vendor BSP, | ||||||
|  | 8W burst length is supported by ar9 and newer SoCs. | ||||||
|  |  | ||||||
|  | The NAT benchmark results on xRX200 (Down/Up): | ||||||
|  | * 2W: 330 Mb/s | ||||||
|  | * 4W: 432 Mb/s    372 Mb/s | ||||||
|  | * 8W: 520 Mb/s    389 Mb/s | ||||||
|  |  | ||||||
|  | Tested on xRX200 and xRX330. | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_etop.c   | 21 ++++++++++++++++++--- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 21 ++++++++++++++++++--- | ||||||
|  |  2 files changed, 36 insertions(+), 6 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -148,6 +148,9 @@ struct ltq_etop_priv { | ||||||
|  |  	struct ltq_etop_chan txch; | ||||||
|  |  	struct ltq_etop_chan rxch; | ||||||
|  |   | ||||||
|  | +	int tx_burst_len; | ||||||
|  | +	int rx_burst_len; | ||||||
|  | + | ||||||
|  |  	int tx_irq; | ||||||
|  |  	int rx_irq; | ||||||
|  |   | ||||||
|  | @@ -399,7 +402,7 @@ ltq_etop_dma_init(struct net_device *dev | ||||||
|  |  	int rx = priv->rx_irq - LTQ_DMA_ETOP; | ||||||
|  |  	int err; | ||||||
|  |   | ||||||
|  | -	ltq_dma_init_port(DMA_PORT_ETOP); | ||||||
|  | +	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, rx_burst_len); | ||||||
|  |   | ||||||
|  |  	priv->txch.dma.nr = tx; | ||||||
|  |  	priv->txch.dma.dev = &priv->pdev->dev; | ||||||
|  | @@ -676,8 +679,8 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |  		return NETDEV_TX_BUSY; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	/* dma needs to start on a 16 byte aligned address */ | ||||||
|  | -	byte_offset = CPHYSADDR(skb->data) % 16; | ||||||
|  | +	/* dma needs to start on a burst length value aligned address */ | ||||||
|  | +	byte_offset = CPHYSADDR(skb->data) % (priv->tx_burst_len * 4); | ||||||
|  |  	priv->txch.skb[priv->txch.dma.desc] = skb; | ||||||
|  |   | ||||||
|  |  	netif_trans_update(dev); | ||||||
|  | @@ -925,6 +928,18 @@ static int ltq_etop_probe(struct platfor | ||||||
|  |  	spin_lock_init(&priv->lock); | ||||||
|  |  	SET_NETDEV_DEV(dev, &pdev->dev); | ||||||
|  |   | ||||||
|  | +	err = device_property_read_u32(&pdev->dev, "lantiq,tx-burst-length", &priv->tx_burst_len); | ||||||
|  | +	if (err < 0) { | ||||||
|  | +		dev_err(&pdev->dev, "unable to read tx-burst-length property\n"); | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	err = device_property_read_u32(&pdev->dev, "lantiq,rx-burst-length", &priv->rx_burst_len); | ||||||
|  | +	if (err < 0) { | ||||||
|  | +		dev_err(&pdev->dev, "unable to read rx-burst-length property\n"); | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8); | ||||||
|  |  	netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32); | ||||||
|  |  	priv->txch.netdev = dev; | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -81,6 +81,9 @@ struct xrx200_priv { | ||||||
|  |  	struct net_device *net_dev; | ||||||
|  |  	struct device *dev; | ||||||
|  |   | ||||||
|  | +	int tx_burst_len; | ||||||
|  | +	int rx_burst_len; | ||||||
|  | + | ||||||
|  |  	__iomem void *pmac_reg; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | @@ -363,8 +366,8 @@ static netdev_tx_t xrx200_start_xmit(str | ||||||
|  |  	if (unlikely(dma_mapping_error(priv->dev, mapping))) | ||||||
|  |  		goto err_drop; | ||||||
|  |   | ||||||
|  | -	/* dma needs to start on a 16 byte aligned address */ | ||||||
|  | -	byte_offset = mapping % 16; | ||||||
|  | +	/* dma needs to start on a burst length value aligned address */ | ||||||
|  | +	byte_offset = mapping % (priv->tx_burst_len * 4); | ||||||
|  |   | ||||||
|  |  	desc->addr = mapping - byte_offset; | ||||||
|  |  	/* Make sure the address is written before we give it to HW */ | ||||||
|  | @@ -465,7 +468,7 @@ static int xrx200_dma_init(struct xrx200 | ||||||
|  |  	int ret = 0; | ||||||
|  |  	int i; | ||||||
|  |   | ||||||
|  | -	ltq_dma_init_port(DMA_PORT_ETOP); | ||||||
|  | +	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, rx_burst_len); | ||||||
|  |   | ||||||
|  |  	ch_rx->dma.nr = XRX200_DMA_RX; | ||||||
|  |  	ch_rx->dma.dev = priv->dev; | ||||||
|  | @@ -584,6 +587,18 @@ static int xrx200_probe(struct platform_ | ||||||
|  |  	if (err) | ||||||
|  |  		eth_hw_addr_random(net_dev); | ||||||
|  |   | ||||||
|  | +	err = device_property_read_u32(dev, "lantiq,tx-burst-length", &priv->tx_burst_len); | ||||||
|  | +	if (err < 0) { | ||||||
|  | +		dev_err(dev, "unable to read tx-burst-length property\n"); | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	err = device_property_read_u32(dev, "lantiq,rx-burst-length", &priv->rx_burst_len); | ||||||
|  | +	if (err < 0) { | ||||||
|  | +		dev_err(dev, "unable to read rx-burst-length property\n"); | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	/* bring up the dma engine and IP core */ | ||||||
|  |  	err = xrx200_dma_init(priv); | ||||||
|  |  	if (err) | ||||||
| @@ -0,0 +1,73 @@ | |||||||
|  | From 7e553c44f09a8f536090904c6db5b8c9dbafa03b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 26 Oct 2021 22:59:01 +0200 | ||||||
|  | Subject: [PATCH] net: lantiq_xrx200: Hardcode the burst length value | ||||||
|  |  | ||||||
|  | All SoCs with this IP core support 8 burst length. Hauke | ||||||
|  | suggested to hardcode this value and simplify the driver. | ||||||
|  |  | ||||||
|  | Link: https://lkml.org/lkml/2021/9/14/1533 | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 21 ++++----------------- | ||||||
|  |  1 file changed, 4 insertions(+), 17 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -25,6 +25,7 @@ | ||||||
|  |  #define XRX200_DMA_DATA_LEN	(SZ_64K - 1) | ||||||
|  |  #define XRX200_DMA_RX		0 | ||||||
|  |  #define XRX200_DMA_TX		1 | ||||||
|  | +#define XRX200_DMA_BURST_LEN	8 | ||||||
|  |   | ||||||
|  |  #define XRX200_DMA_PACKET_COMPLETE	0 | ||||||
|  |  #define XRX200_DMA_PACKET_IN_PROGRESS	1 | ||||||
|  | @@ -81,9 +82,6 @@ struct xrx200_priv { | ||||||
|  |  	struct net_device *net_dev; | ||||||
|  |  	struct device *dev; | ||||||
|  |   | ||||||
|  | -	int tx_burst_len; | ||||||
|  | -	int rx_burst_len; | ||||||
|  | - | ||||||
|  |  	__iomem void *pmac_reg; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | @@ -367,7 +365,7 @@ static netdev_tx_t xrx200_start_xmit(str | ||||||
|  |  		goto err_drop; | ||||||
|  |   | ||||||
|  |  	/* dma needs to start on a burst length value aligned address */ | ||||||
|  | -	byte_offset = mapping % (priv->tx_burst_len * 4); | ||||||
|  | +	byte_offset = mapping % (XRX200_DMA_BURST_LEN * 4); | ||||||
|  |   | ||||||
|  |  	desc->addr = mapping - byte_offset; | ||||||
|  |  	/* Make sure the address is written before we give it to HW */ | ||||||
|  | @@ -468,7 +466,8 @@ static int xrx200_dma_init(struct xrx200 | ||||||
|  |  	int ret = 0; | ||||||
|  |  	int i; | ||||||
|  |   | ||||||
|  | -	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, rx_burst_len); | ||||||
|  | +	ltq_dma_init_port(DMA_PORT_ETOP, XRX200_DMA_BURST_LEN, | ||||||
|  | +			  XRX200_DMA_BURST_LEN); | ||||||
|  |   | ||||||
|  |  	ch_rx->dma.nr = XRX200_DMA_RX; | ||||||
|  |  	ch_rx->dma.dev = priv->dev; | ||||||
|  | @@ -587,18 +586,6 @@ static int xrx200_probe(struct platform_ | ||||||
|  |  	if (err) | ||||||
|  |  		eth_hw_addr_random(net_dev); | ||||||
|  |   | ||||||
|  | -	err = device_property_read_u32(dev, "lantiq,tx-burst-length", &priv->tx_burst_len); | ||||||
|  | -	if (err < 0) { | ||||||
|  | -		dev_err(dev, "unable to read tx-burst-length property\n"); | ||||||
|  | -		return err; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	err = device_property_read_u32(dev, "lantiq,rx-burst-length", &priv->rx_burst_len); | ||||||
|  | -	if (err < 0) { | ||||||
|  | -		dev_err(dev, "unable to read rx-burst-length property\n"); | ||||||
|  | -		return err; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  |  	/* bring up the dma engine and IP core */ | ||||||
|  |  	err = xrx200_dma_init(priv); | ||||||
|  |  	if (err) | ||||||
| @@ -0,0 +1,26 @@ | |||||||
|  | From 68eabc348148ae051631e8dab13c3b1a85c82896 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 9 Nov 2021 23:23:54 +0100 | ||||||
|  | Subject: [PATCH] net: ethernet: lantiq_etop: Fix compilation error | ||||||
|  |  | ||||||
|  | This fixes the error detected when compiling the driver. | ||||||
|  |  | ||||||
|  | Fixes: 14d4e308e0aa ("net: lantiq: configure the burst length in ethernet drivers") | ||||||
|  | Reported-by: kernel test robot <lkp@intel.com> | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_etop.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -402,7 +402,7 @@ ltq_etop_dma_init(struct net_device *dev | ||||||
|  |  	int rx = priv->rx_irq - LTQ_DMA_ETOP; | ||||||
|  |  	int err; | ||||||
|  |   | ||||||
|  | -	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, rx_burst_len); | ||||||
|  | +	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, priv->rx_burst_len); | ||||||
|  |   | ||||||
|  |  	priv->txch.dma.nr = tx; | ||||||
|  |  	priv->txch.dma.dev = &priv->pdev->dev; | ||||||
| @@ -0,0 +1,28 @@ | |||||||
|  | From 5112e9234bbb89f8dd15c983206bd9107b8436d5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 4 Jan 2022 16:11:42 +0100 | ||||||
|  | Subject: [PATCH 713/715] MIPS: lantiq: dma: increase descritor count | ||||||
|  |  | ||||||
|  | NAT Performance results on BT Home Hub 5A (kernel 5.10.89, mtu 1500): | ||||||
|  |  | ||||||
|  | 	Down		Up | ||||||
|  | Before	539 Mbps	599 Mbps | ||||||
|  | After	545 Mbps	625 Mbps | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | ||||||
|  | @@ -8,7 +8,7 @@ | ||||||
|  |  #define LTQ_DMA_H__ | ||||||
|  |   | ||||||
|  |  #define LTQ_DESC_SIZE		0x08	/* each descriptor is 64bit */ | ||||||
|  | -#define LTQ_DESC_NUM		0x40	/* 64 descriptors / channel */ | ||||||
|  | +#define LTQ_DESC_NUM		0xC0	/* 192 descriptors / channel */ | ||||||
|  |   | ||||||
|  |  #define LTQ_DMA_OWN		BIT(31) /* owner bit */ | ||||||
|  |  #define LTQ_DMA_C		BIT(30) /* complete bit */ | ||||||
| @@ -0,0 +1,32 @@ | |||||||
|  | From 768818d772d5d4ddc0c7eb2e62848929270ab7a3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 4 Jan 2022 16:11:43 +0100 | ||||||
|  | Subject: [PATCH 714/715] net: lantiq_xrx200: increase napi poll weigth | ||||||
|  |  | ||||||
|  | NAT Performance results on BT Home Hub 5A (kernel 5.10.89, mtu 1500): | ||||||
|  |  | ||||||
|  | 	Down		Up | ||||||
|  | Before	545 Mbps	625 Mbps | ||||||
|  | After	577 Mbps	648 Mbps | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 6 ++++-- | ||||||
|  |  1 file changed, 4 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -606,8 +606,10 @@ static int xrx200_probe(struct platform_ | ||||||
|  |  			 PMAC_HD_CTL); | ||||||
|  |   | ||||||
|  |  	/* setup NAPI */ | ||||||
|  | -	netif_napi_add(net_dev, &priv->chan_rx.napi, xrx200_poll_rx, 32); | ||||||
|  | -	netif_tx_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, 32); | ||||||
|  | +	netif_napi_add(net_dev, &priv->chan_rx.napi, xrx200_poll_rx, | ||||||
|  | +		       NAPI_POLL_WEIGHT); | ||||||
|  | +	netif_tx_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, | ||||||
|  | +			  NAPI_POLL_WEIGHT); | ||||||
|  |   | ||||||
|  |  	platform_set_drvdata(pdev, priv); | ||||||
|  |   | ||||||
| @@ -0,0 +1,206 @@ | |||||||
|  | From e015593573b3e3f74bd8a63c05fa92902194a354 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Tue, 4 Jan 2022 16:11:44 +0100 | ||||||
|  | Subject: [PATCH 715/715] net: lantiq_xrx200: convert to build_skb | ||||||
|  |  | ||||||
|  | We can increase the efficiency of rx path by using buffers to receive | ||||||
|  | packets then build SKBs around them just before passing into the network | ||||||
|  | stack. In contrast, preallocating SKBs too early reduces CPU cache | ||||||
|  | efficiency. | ||||||
|  |  | ||||||
|  | NAT Performance results on BT Home Hub 5A (kernel 5.10.89, mtu 1500): | ||||||
|  |  | ||||||
|  | 	Down		Up | ||||||
|  | Before	577 Mbps	648 Mbps | ||||||
|  | After	624 Mbps	695 Mbps | ||||||
|  |  | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 56 ++++++++++++++++++---------- | ||||||
|  |  1 file changed, 36 insertions(+), 20 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -63,7 +63,11 @@ struct xrx200_chan { | ||||||
|  |   | ||||||
|  |  	struct napi_struct napi; | ||||||
|  |  	struct ltq_dma_channel dma; | ||||||
|  | -	struct sk_buff *skb[LTQ_DESC_NUM]; | ||||||
|  | + | ||||||
|  | +	union { | ||||||
|  | +		struct sk_buff *skb[LTQ_DESC_NUM]; | ||||||
|  | +		void *rx_buff[LTQ_DESC_NUM]; | ||||||
|  | +	}; | ||||||
|  |   | ||||||
|  |  	struct sk_buff *skb_head; | ||||||
|  |  	struct sk_buff *skb_tail; | ||||||
|  | @@ -78,6 +82,7 @@ struct xrx200_priv { | ||||||
|  |  	struct xrx200_chan chan_rx; | ||||||
|  |   | ||||||
|  |  	u16 rx_buf_size; | ||||||
|  | +	u16 rx_skb_size; | ||||||
|  |   | ||||||
|  |  	struct net_device *net_dev; | ||||||
|  |  	struct device *dev; | ||||||
|  | @@ -115,6 +120,12 @@ static int xrx200_buffer_size(int mtu) | ||||||
|  |  	return round_up(xrx200_max_frame_len(mtu), 4 * XRX200_DMA_BURST_LEN); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int xrx200_skb_size(u16 buf_size) | ||||||
|  | +{ | ||||||
|  | +	return SKB_DATA_ALIGN(buf_size + NET_SKB_PAD + NET_IP_ALIGN) + | ||||||
|  | +		SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* drop all the packets from the DMA ring */ | ||||||
|  |  static void xrx200_flush_dma(struct xrx200_chan *ch) | ||||||
|  |  { | ||||||
|  | @@ -173,30 +184,29 @@ static int xrx200_close(struct net_devic | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int xrx200_alloc_skb(struct xrx200_chan *ch) | ||||||
|  | +static int xrx200_alloc_buf(struct xrx200_chan *ch, void *(*alloc)(unsigned int size)) | ||||||
|  |  { | ||||||
|  | -	struct sk_buff *skb = ch->skb[ch->dma.desc]; | ||||||
|  | +	void *buf = ch->rx_buff[ch->dma.desc]; | ||||||
|  |  	struct xrx200_priv *priv = ch->priv; | ||||||
|  |  	dma_addr_t mapping; | ||||||
|  |  	int ret = 0; | ||||||
|  |   | ||||||
|  | -	ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(priv->net_dev, | ||||||
|  | -							  priv->rx_buf_size); | ||||||
|  | -	if (!ch->skb[ch->dma.desc]) { | ||||||
|  | +	ch->rx_buff[ch->dma.desc] = alloc(priv->rx_skb_size); | ||||||
|  | +	if (!ch->rx_buff[ch->dma.desc]) { | ||||||
|  |  		ret = -ENOMEM; | ||||||
|  |  		goto skip; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	mapping = dma_map_single(priv->dev, ch->skb[ch->dma.desc]->data, | ||||||
|  | +	mapping = dma_map_single(priv->dev, ch->rx_buff[ch->dma.desc], | ||||||
|  |  				 priv->rx_buf_size, DMA_FROM_DEVICE); | ||||||
|  |  	if (unlikely(dma_mapping_error(priv->dev, mapping))) { | ||||||
|  | -		dev_kfree_skb_any(ch->skb[ch->dma.desc]); | ||||||
|  | -		ch->skb[ch->dma.desc] = skb; | ||||||
|  | +		skb_free_frag(ch->rx_buff[ch->dma.desc]); | ||||||
|  | +		ch->rx_buff[ch->dma.desc] = buf; | ||||||
|  |  		ret = -ENOMEM; | ||||||
|  |  		goto skip; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ch->dma.desc_base[ch->dma.desc].addr = mapping; | ||||||
|  | +	ch->dma.desc_base[ch->dma.desc].addr = mapping + NET_SKB_PAD + NET_IP_ALIGN; | ||||||
|  |  	/* Make sure the address is written before we give it to HW */ | ||||||
|  |  	wmb(); | ||||||
|  |  skip: | ||||||
|  | @@ -210,13 +220,14 @@ static int xrx200_hw_receive(struct xrx2 | ||||||
|  |  { | ||||||
|  |  	struct xrx200_priv *priv = ch->priv; | ||||||
|  |  	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; | ||||||
|  | -	struct sk_buff *skb = ch->skb[ch->dma.desc]; | ||||||
|  | +	void *buf = ch->rx_buff[ch->dma.desc]; | ||||||
|  |  	u32 ctl = desc->ctl; | ||||||
|  |  	int len = (ctl & LTQ_DMA_SIZE_MASK); | ||||||
|  |  	struct net_device *net_dev = priv->net_dev; | ||||||
|  | +	struct sk_buff *skb; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  | -	ret = xrx200_alloc_skb(ch); | ||||||
|  | +	ret = xrx200_alloc_buf(ch, napi_alloc_frag); | ||||||
|  |   | ||||||
|  |  	ch->dma.desc++; | ||||||
|  |  	ch->dma.desc %= LTQ_DESC_NUM; | ||||||
|  | @@ -227,19 +238,21 @@ static int xrx200_hw_receive(struct xrx2 | ||||||
|  |  		return ret; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	skb = build_skb(buf, priv->rx_skb_size); | ||||||
|  | +	skb_reserve(skb, NET_SKB_PAD); | ||||||
|  |  	skb_put(skb, len); | ||||||
|  |   | ||||||
|  |  	/* add buffers to skb via skb->frag_list */ | ||||||
|  |  	if (ctl & LTQ_DMA_SOP) { | ||||||
|  |  		ch->skb_head = skb; | ||||||
|  |  		ch->skb_tail = skb; | ||||||
|  | +		skb_reserve(skb, NET_IP_ALIGN); | ||||||
|  |  	} else if (ch->skb_head) { | ||||||
|  |  		if (ch->skb_head == ch->skb_tail) | ||||||
|  |  			skb_shinfo(ch->skb_tail)->frag_list = skb; | ||||||
|  |  		else | ||||||
|  |  			ch->skb_tail->next = skb; | ||||||
|  |  		ch->skb_tail = skb; | ||||||
|  | -		skb_reserve(ch->skb_tail, -NET_IP_ALIGN); | ||||||
|  |  		ch->skb_head->len += skb->len; | ||||||
|  |  		ch->skb_head->data_len += skb->len; | ||||||
|  |  		ch->skb_head->truesize += skb->truesize; | ||||||
|  | @@ -395,12 +408,13 @@ xrx200_change_mtu(struct net_device *net | ||||||
|  |  	struct xrx200_chan *ch_rx = &priv->chan_rx; | ||||||
|  |  	int old_mtu = net_dev->mtu; | ||||||
|  |  	bool running = false; | ||||||
|  | -	struct sk_buff *skb; | ||||||
|  | +	void *buff; | ||||||
|  |  	int curr_desc; | ||||||
|  |  	int ret = 0; | ||||||
|  |   | ||||||
|  |  	net_dev->mtu = new_mtu; | ||||||
|  |  	priv->rx_buf_size = xrx200_buffer_size(new_mtu); | ||||||
|  | +	priv->rx_skb_size = xrx200_skb_size(priv->rx_buf_size); | ||||||
|  |   | ||||||
|  |  	if (new_mtu <= old_mtu) | ||||||
|  |  		return ret; | ||||||
|  | @@ -416,14 +430,15 @@ xrx200_change_mtu(struct net_device *net | ||||||
|  |   | ||||||
|  |  	for (ch_rx->dma.desc = 0; ch_rx->dma.desc < LTQ_DESC_NUM; | ||||||
|  |  	     ch_rx->dma.desc++) { | ||||||
|  | -		skb = ch_rx->skb[ch_rx->dma.desc]; | ||||||
|  | -		ret = xrx200_alloc_skb(ch_rx); | ||||||
|  | +		buff = ch_rx->rx_buff[ch_rx->dma.desc]; | ||||||
|  | +		ret = xrx200_alloc_buf(ch_rx, netdev_alloc_frag); | ||||||
|  |  		if (ret) { | ||||||
|  |  			net_dev->mtu = old_mtu; | ||||||
|  |  			priv->rx_buf_size = xrx200_buffer_size(old_mtu); | ||||||
|  | +			priv->rx_skb_size = xrx200_skb_size(priv->rx_buf_size); | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  | -		dev_kfree_skb_any(skb); | ||||||
|  | +		skb_free_frag(buff); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ch_rx->dma.desc = curr_desc; | ||||||
|  | @@ -476,7 +491,7 @@ static int xrx200_dma_init(struct xrx200 | ||||||
|  |  	ltq_dma_alloc_rx(&ch_rx->dma); | ||||||
|  |  	for (ch_rx->dma.desc = 0; ch_rx->dma.desc < LTQ_DESC_NUM; | ||||||
|  |  	     ch_rx->dma.desc++) { | ||||||
|  | -		ret = xrx200_alloc_skb(ch_rx); | ||||||
|  | +		ret = xrx200_alloc_buf(ch_rx, netdev_alloc_frag); | ||||||
|  |  		if (ret) | ||||||
|  |  			goto rx_free; | ||||||
|  |  	} | ||||||
|  | @@ -511,7 +526,7 @@ rx_ring_free: | ||||||
|  |  	/* free the allocated RX ring */ | ||||||
|  |  	for (i = 0; i < LTQ_DESC_NUM; i++) { | ||||||
|  |  		if (priv->chan_rx.skb[i]) | ||||||
|  | -			dev_kfree_skb_any(priv->chan_rx.skb[i]); | ||||||
|  | +			skb_free_frag(priv->chan_rx.rx_buff[i]); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  rx_free: | ||||||
|  | @@ -528,7 +543,7 @@ static void xrx200_hw_cleanup(struct xrx | ||||||
|  |   | ||||||
|  |  	/* free the allocated RX ring */ | ||||||
|  |  	for (i = 0; i < LTQ_DESC_NUM; i++) | ||||||
|  | -		dev_kfree_skb_any(priv->chan_rx.skb[i]); | ||||||
|  | +		skb_free_frag(priv->chan_rx.rx_buff[i]); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int xrx200_probe(struct platform_device *pdev) | ||||||
|  | @@ -554,6 +569,7 @@ static int xrx200_probe(struct platform_ | ||||||
|  |  	net_dev->min_mtu = ETH_ZLEN; | ||||||
|  |  	net_dev->max_mtu = XRX200_DMA_DATA_LEN - xrx200_max_frame_len(0); | ||||||
|  |  	priv->rx_buf_size = xrx200_buffer_size(ETH_DATA_LEN); | ||||||
|  | +	priv->rx_skb_size = xrx200_skb_size(priv->rx_buf_size); | ||||||
|  |   | ||||||
|  |  	/* load the memory ranges */ | ||||||
|  |  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | From dd830aed23c6e07cd8e2a163742bf3d63c9add08 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Sat, 5 Mar 2022 12:20:39 +0100 | ||||||
|  | Subject: net: lantiq_xrx200: fix use after free bug | ||||||
|  |  | ||||||
|  | The skb->len field is read after the packet is sent to the network | ||||||
|  | stack. In the meantime, skb can be freed. This patch fixes this bug. | ||||||
|  |  | ||||||
|  | Fixes: c3e6b2c35b34 ("net: lantiq_xrx200: add ingress SG DMA support") | ||||||
|  | Reported-by: Eric Dumazet <eric.dumazet@gmail.com> | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Acked-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -260,9 +260,9 @@ static int xrx200_hw_receive(struct xrx2 | ||||||
|  |   | ||||||
|  |  	if (ctl & LTQ_DMA_EOP) { | ||||||
|  |  		ch->skb_head->protocol = eth_type_trans(ch->skb_head, net_dev); | ||||||
|  | -		netif_receive_skb(ch->skb_head); | ||||||
|  |  		net_dev->stats.rx_packets++; | ||||||
|  |  		net_dev->stats.rx_bytes += ch->skb_head->len; | ||||||
|  | +		netif_receive_skb(ch->skb_head); | ||||||
|  |  		ch->skb_head = NULL; | ||||||
|  |  		ch->skb_tail = NULL; | ||||||
|  |  		ret = XRX200_DMA_PACKET_COMPLETE; | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | From c8b043702dc0894c07721c5b019096cebc8c798f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Wed, 24 Aug 2022 23:54:06 +0200 | ||||||
|  | Subject: [PATCH] net: lantiq_xrx200: confirm skb is allocated before using | ||||||
|  |  | ||||||
|  | xrx200_hw_receive() assumes build_skb() always works and goes straight | ||||||
|  | to skb_reserve(). However, build_skb() can fail under memory pressure. | ||||||
|  |  | ||||||
|  | Add a check in case build_skb() failed to allocate and return NULL. | ||||||
|  |  | ||||||
|  | Fixes: e015593573b3 ("net: lantiq_xrx200: convert to build_skb") | ||||||
|  | Reported-by: Eric Dumazet <edumazet@google.com> | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 6 ++++++ | ||||||
|  |  1 file changed, 6 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -239,6 +239,12 @@ static int xrx200_hw_receive(struct xrx2 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	skb = build_skb(buf, priv->rx_skb_size); | ||||||
|  | +	if (!skb) { | ||||||
|  | +		skb_free_frag(buf); | ||||||
|  | +		net_dev->stats.rx_dropped++; | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	skb_reserve(skb, NET_SKB_PAD); | ||||||
|  |  	skb_put(skb, len); | ||||||
|  |   | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | From c4b6e9341f930e4dd089231c0414758f5f1f9dbd Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Wed, 24 Aug 2022 23:54:07 +0200 | ||||||
|  | Subject: [PATCH] net: lantiq_xrx200: fix lock under memory pressure | ||||||
|  |  | ||||||
|  | When the xrx200_hw_receive() function returns -ENOMEM, the NAPI poll | ||||||
|  | function immediately returns an error. | ||||||
|  | This is incorrect for two reasons: | ||||||
|  | * the function terminates without enabling interrupts or scheduling NAPI, | ||||||
|  | * the error code (-ENOMEM) is returned instead of the number of received | ||||||
|  | packets. | ||||||
|  |  | ||||||
|  | After the first memory allocation failure occurs, packet reception is | ||||||
|  | locked due to disabled interrupts from DMA.. | ||||||
|  |  | ||||||
|  | Fixes: fe1a56420cf2 ("net: lantiq: Add Lantiq / Intel VRX200 Ethernet driver") | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -294,7 +294,7 @@ static int xrx200_poll_rx(struct napi_st | ||||||
|  |  			if (ret == XRX200_DMA_PACKET_IN_PROGRESS) | ||||||
|  |  				continue; | ||||||
|  |  			if (ret != XRX200_DMA_PACKET_COMPLETE) | ||||||
|  | -				return ret; | ||||||
|  | +				break; | ||||||
|  |  			rx++; | ||||||
|  |  		} else { | ||||||
|  |  			break; | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | From c9c3b1775f80fa21f5bff874027d2ccb10f5d90c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Date: Wed, 24 Aug 2022 23:54:08 +0200 | ||||||
|  | Subject: [PATCH] net: lantiq_xrx200: restore buffer if memory allocation | ||||||
|  |  failed | ||||||
|  |  | ||||||
|  | In a situation where memory allocation fails, an invalid buffer address | ||||||
|  | is stored. When this descriptor is used again, the system panics in the | ||||||
|  | build_skb() function when accessing memory. | ||||||
|  |  | ||||||
|  | Fixes: 7ea6cd16f159 ("lantiq: net: fix duplicated skb in rx descriptor ring") | ||||||
|  | Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_xrx200.c | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_xrx200.c | ||||||
|  | @@ -193,6 +193,7 @@ static int xrx200_alloc_buf(struct xrx20 | ||||||
|  |   | ||||||
|  |  	ch->rx_buff[ch->dma.desc] = alloc(priv->rx_skb_size); | ||||||
|  |  	if (!ch->rx_buff[ch->dma.desc]) { | ||||||
|  | +		ch->rx_buff[ch->dma.desc] = buf; | ||||||
|  |  		ret = -ENOMEM; | ||||||
|  |  		goto skip; | ||||||
|  |  	} | ||||||
							
								
								
									
										93
									
								
								target/linux/lantiq/xrx200/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								target/linux/lantiq/xrx200/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | CONFIG_AT803X_PHY=y | ||||||
|  | CONFIG_BLK_MQ_PCI=y | ||||||
|  | CONFIG_CPU_HAS_DIEI=y | ||||||
|  | CONFIG_CPU_MIPSR2_IRQ_EI=y | ||||||
|  | CONFIG_CPU_MIPSR2_IRQ_VI=y | ||||||
|  | CONFIG_CPU_RMAP=y | ||||||
|  | CONFIG_CRC16=y | ||||||
|  | CONFIG_CRYPTO_ACOMP2=y | ||||||
|  | CONFIG_CRYPTO_DEFLATE=y | ||||||
|  | CONFIG_CRYPTO_HASH_INFO=y | ||||||
|  | CONFIG_CRYPTO_LZO=y | ||||||
|  | CONFIG_CRYPTO_ZSTD=y | ||||||
|  | CONFIG_EXTRA_FIRMWARE="lantiq/xrx200_phy11g_a14.bin lantiq/xrx200_phy11g_a22.bin lantiq/xrx200_phy22f_a14.bin lantiq/xrx200_phy22f_a22.bin" | ||||||
|  | CONFIG_EXTRA_FIRMWARE_DIR="firmware" | ||||||
|  | CONFIG_GENERIC_ALLOCATOR=y | ||||||
|  | CONFIG_GRO_CELLS=y | ||||||
|  | CONFIG_HWMON=y | ||||||
|  | CONFIG_HW_RANDOM=y | ||||||
|  | CONFIG_ICPLUS_PHY=y | ||||||
|  | CONFIG_IFX_VPE_EXT=y | ||||||
|  | CONFIG_INPUT=y | ||||||
|  | CONFIG_INPUT_EVDEV=y | ||||||
|  | CONFIG_INPUT_POLLDEV=y | ||||||
|  | CONFIG_INTEL_XWAY_PHY=y | ||||||
|  | # CONFIG_ISDN is not set | ||||||
|  | CONFIG_LANTIQ_XRX200=y | ||||||
|  | CONFIG_LZO_COMPRESS=y | ||||||
|  | CONFIG_LZO_DECOMPRESS=y | ||||||
|  | CONFIG_MIPS_MT=y | ||||||
|  | # CONFIG_MIPS_MT_FPAFF is not set | ||||||
|  | CONFIG_MIPS_MT_SMP=y | ||||||
|  | CONFIG_MIPS_NR_CPU_NR_MAP=2 | ||||||
|  | CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y | ||||||
|  | CONFIG_MIPS_VPE_APSP_API=y | ||||||
|  | CONFIG_MIPS_VPE_APSP_API_MT=y | ||||||
|  | CONFIG_MIPS_VPE_LOADER=y | ||||||
|  | CONFIG_MIPS_VPE_LOADER_MT=y | ||||||
|  | CONFIG_MIPS_VPE_LOADER_TOM=y | ||||||
|  | CONFIG_MTD_NAND_CORE=y | ||||||
|  | CONFIG_MTD_NAND_ECC=y | ||||||
|  | CONFIG_MTD_NAND_ECC_SW_HAMMING=y | ||||||
|  | CONFIG_MTD_NAND_PLATFORM=y | ||||||
|  | CONFIG_MTD_NAND_XWAY=y | ||||||
|  | CONFIG_MTD_RAW_NAND=y | ||||||
|  | CONFIG_MTD_UBI=y | ||||||
|  | CONFIG_MTD_UBI_BEB_LIMIT=20 | ||||||
|  | CONFIG_MTD_UBI_BLOCK=y | ||||||
|  | CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||||||
|  | CONFIG_NET_DEVLINK=y | ||||||
|  | CONFIG_NET_DSA=y | ||||||
|  | CONFIG_NET_DSA_LANTIQ_GSWIP=y | ||||||
|  | CONFIG_NET_DSA_TAG_GSWIP=y | ||||||
|  | CONFIG_NET_FLOW_LIMIT=y | ||||||
|  | CONFIG_NET_SWITCHDEV=y | ||||||
|  | CONFIG_NLS=y | ||||||
|  | CONFIG_NR_CPUS=2 | ||||||
|  | CONFIG_PADATA=y | ||||||
|  | CONFIG_PCI=y | ||||||
|  | CONFIG_PCIEPORTBUS=y | ||||||
|  | CONFIG_PCIE_LANTIQ=y | ||||||
|  | CONFIG_PCI_DOMAINS=y | ||||||
|  | CONFIG_PCI_LANTIQ=y | ||||||
|  | CONFIG_PHY_LANTIQ_VRX200_PCIE=y | ||||||
|  | CONFIG_POWER_RESET_GPIO=y | ||||||
|  | CONFIG_POWER_SUPPLY=y | ||||||
|  | CONFIG_POWER_SUPPLY_HWMON=y | ||||||
|  | CONFIG_QUEUED_RWLOCKS=y | ||||||
|  | CONFIG_QUEUED_SPINLOCKS=y | ||||||
|  | CONFIG_REGULATOR=y | ||||||
|  | CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||||||
|  | CONFIG_RFS_ACCEL=y | ||||||
|  | CONFIG_RPS=y | ||||||
|  | CONFIG_SENSORS_LTQ_CPUTEMP=y | ||||||
|  | CONFIG_SGL_ALLOC=y | ||||||
|  | CONFIG_SMP=y | ||||||
|  | CONFIG_SMP_UP=y | ||||||
|  | CONFIG_SOC_TYPE_XWAY=y | ||||||
|  | CONFIG_SOC_XWAY=y | ||||||
|  | CONFIG_SYNC_R4K=y | ||||||
|  | CONFIG_SYS_SUPPORTS_SCHED_SMT=y | ||||||
|  | CONFIG_SYS_SUPPORTS_SMP=y | ||||||
|  | CONFIG_TREE_RCU=y | ||||||
|  | CONFIG_TREE_SRCU=y | ||||||
|  | CONFIG_UBIFS_FS=y | ||||||
|  | CONFIG_USB=y | ||||||
|  | CONFIG_USB_COMMON=y | ||||||
|  | CONFIG_USB_SUPPORT=y | ||||||
|  | CONFIG_XPS=y | ||||||
|  | CONFIG_XXHASH=y | ||||||
|  | CONFIG_ZLIB_DEFLATE=y | ||||||
|  | CONFIG_ZLIB_INFLATE=y | ||||||
|  | CONFIG_ZSTD_COMPRESS=y | ||||||
|  | CONFIG_ZSTD_DECOMPRESS=y | ||||||
							
								
								
									
										46
									
								
								target/linux/lantiq/xway/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								target/linux/lantiq/xway/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | CONFIG_ADM6996_PHY=y | ||||||
|  | CONFIG_AR8216_PHY=y | ||||||
|  | CONFIG_AT803X_PHY=y | ||||||
|  | CONFIG_BLK_MQ_PCI=y | ||||||
|  | CONFIG_CPU_HAS_DIEI=y | ||||||
|  | CONFIG_CRC16=y | ||||||
|  | CONFIG_CRYPTO_ACOMP2=y | ||||||
|  | CONFIG_CRYPTO_HASH_INFO=y | ||||||
|  | CONFIG_CRYPTO_LZO=y | ||||||
|  | CONFIG_ETHERNET_PACKET_MANGLE=y | ||||||
|  | CONFIG_GENERIC_ALLOCATOR=y | ||||||
|  | CONFIG_HW_RANDOM=y | ||||||
|  | CONFIG_INPUT=y | ||||||
|  | CONFIG_INPUT_EVDEV=y | ||||||
|  | CONFIG_INPUT_POLLDEV=y | ||||||
|  | # CONFIG_ISDN is not set | ||||||
|  | CONFIG_LANTIQ_ETOP=y | ||||||
|  | CONFIG_LZO_COMPRESS=y | ||||||
|  | CONFIG_LZO_DECOMPRESS=y | ||||||
|  | CONFIG_MTD_NAND_CORE=y | ||||||
|  | CONFIG_MTD_NAND_ECC=y | ||||||
|  | CONFIG_MTD_NAND_ECC_SW_HAMMING=y | ||||||
|  | CONFIG_MTD_NAND_XWAY=y | ||||||
|  | CONFIG_MTD_RAW_NAND=y | ||||||
|  | CONFIG_MTD_UBI=y | ||||||
|  | CONFIG_MTD_UBI_BEB_LIMIT=20 | ||||||
|  | CONFIG_MTD_UBI_BLOCK=y | ||||||
|  | CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||||||
|  | CONFIG_NLS=y | ||||||
|  | CONFIG_PCI=y | ||||||
|  | CONFIG_PCI_DOMAINS=y | ||||||
|  | CONFIG_PCI_LANTIQ=y | ||||||
|  | CONFIG_PSB6970_PHY=y | ||||||
|  | CONFIG_REGULATOR=y | ||||||
|  | CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||||||
|  | CONFIG_RTL8306_PHY=y | ||||||
|  | CONFIG_RTL8366RB_PHY=y | ||||||
|  | CONFIG_RTL8366_SMI=y | ||||||
|  | CONFIG_SGL_ALLOC=y | ||||||
|  | CONFIG_SOC_TYPE_XWAY=y | ||||||
|  | CONFIG_SOC_XWAY=y | ||||||
|  | CONFIG_SWCONFIG=y | ||||||
|  | CONFIG_UBIFS_FS=y | ||||||
|  | CONFIG_USB=y | ||||||
|  | CONFIG_USB_COMMON=y | ||||||
|  | CONFIG_USB_SUPPORT=y | ||||||
							
								
								
									
										33
									
								
								target/linux/lantiq/xway_legacy/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								target/linux/lantiq/xway_legacy/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | CONFIG_ADM6996_PHY=y | ||||||
|  | CONFIG_BLK_MQ_PCI=y | ||||||
|  | CONFIG_CPU_HAS_DIEI=y | ||||||
|  | CONFIG_CRC16=y | ||||||
|  | CONFIG_CRYPTO_ACOMP2=y | ||||||
|  | CONFIG_CRYPTO_DEFLATE=y | ||||||
|  | CONFIG_CRYPTO_LZO=y | ||||||
|  | CONFIG_GENERIC_ALLOCATOR=y | ||||||
|  | # CONFIG_GPIO_SYSFS is not set | ||||||
|  | CONFIG_INPUT=y | ||||||
|  | CONFIG_INPUT_EVDEV=y | ||||||
|  | CONFIG_INPUT_POLLDEV=y | ||||||
|  | # CONFIG_ISDN is not set | ||||||
|  | CONFIG_LANTIQ_ETOP=y | ||||||
|  | # CONFIG_LEDS_TRIGGER_TIMER is not set | ||||||
|  | CONFIG_LZO_COMPRESS=y | ||||||
|  | CONFIG_LZO_DECOMPRESS=y | ||||||
|  | CONFIG_NLS=y | ||||||
|  | CONFIG_PCI=y | ||||||
|  | CONFIG_PCI_DOMAINS=y | ||||||
|  | CONFIG_PCI_LANTIQ=y | ||||||
|  | CONFIG_REGULATOR=y | ||||||
|  | CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||||||
|  | CONFIG_RTL8306_PHY=y | ||||||
|  | CONFIG_SGL_ALLOC=y | ||||||
|  | CONFIG_SOC_TYPE_XWAY=y | ||||||
|  | CONFIG_SOC_XWAY=y | ||||||
|  | CONFIG_SWCONFIG=y | ||||||
|  | CONFIG_USB=y | ||||||
|  | CONFIG_USB_COMMON=y | ||||||
|  | CONFIG_USB_SUPPORT=y | ||||||
|  | CONFIG_ZLIB_DEFLATE=y | ||||||
|  | CONFIG_ZLIB_INFLATE=y | ||||||
		Reference in New Issue
	
	Block a user