diff --git a/config/Config-images.in b/config/Config-images.in index 5615141b750..6e43793ef53 100644 --- a/config/Config-images.in +++ b/config/Config-images.in @@ -37,11 +37,9 @@ menu "Target Images" bool "lzma" config TARGET_INITRAMFS_COMPRESSION_LZO - depends on !TARGET_ROOTFS_INITRAMFS_SEPARATE bool "lzo" config TARGET_INITRAMFS_COMPRESSION_LZ4 - depends on !TARGET_ROOTFS_INITRAMFS_SEPARATE bool "lz4" config TARGET_INITRAMFS_COMPRESSION_XZ diff --git a/include/image-commands.mk b/include/image-commands.mk index ff8acf96c4f..70055cc5764 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -277,7 +277,9 @@ endef define Build/initrd_compression $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),.bzip2) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),.gzip) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),.lz4) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZMA),.lzma) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),.lzo) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_XZ),.xz) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),.zstd) endef diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk index dcba319a0f2..127fa8563af 100644 --- a/include/kernel-defaults.mk +++ b/include/kernel-defaults.mk @@ -179,10 +179,10 @@ endif $(if $(SOURCE_DATE_EPOCH),touch -hcd "@$(SOURCE_DATE_EPOCH)" $(KERNEL_BUILD_DIR)/initrd.cpio) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),bzip2 -9 -c < $(KERNEL_BUILD_DIR)/initrd.cpio > $(KERNEL_BUILD_DIR)/initrd.cpio.bzip2) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),gzip -n -f -S .gzip -9n $(KERNEL_BUILD_DIR)/initrd.cpio) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),$(STAGING_DIR_HOST)/bin/lz4c -l -c1 -fz --favor-decSpeed $(KERNEL_BUILD_DIR)/initrd.cpio) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZMA),$(STAGING_DIR_HOST)/bin/lzma e -lc1 -lp2 -pb2 $(KERNEL_BUILD_DIR)/initrd.cpio $(KERNEL_BUILD_DIR)/initrd.cpio.lzma) -# ? $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),$(STAGING_DIR_HOST)/bin/lzop -9 -f $(KERNEL_BUILD_DIR)/initrd.cpio) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_XZ),$(STAGING_DIR_HOST)/bin/xz -T$(if $(filter 1,$(NPROC)),2,0) -9 -fz --check=crc32 $(KERNEL_BUILD_DIR)/initrd.cpio) -# ? $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),$(STAGING_DIR_HOST)/bin/zstd -T0 -f -o $(KERNEL_BUILD_DIR)/initrd.cpio.zstd $(KERNEL_BUILD_DIR)/initrd.cpio) endif +$(KERNEL_MAKE) $(KERNEL_MAKEOPTS_IMAGE) $(if $(KERNELNAME),$(KERNELNAME),all) modules diff --git a/package/kernel/lantiq/ltq-ifxos/Makefile b/package/kernel/lantiq/ltq-ifxos/Makefile index bc586faaf12..e8f41665dda 100644 --- a/package/kernel/lantiq/ltq-ifxos/Makefile +++ b/package/kernel/lantiq/ltq-ifxos/Makefile @@ -32,7 +32,7 @@ define KernelPackage/ltq-ifxos SUBMENU:=Libraries TITLE:=Lantiq OS abstraction library URL:=http://www.lantiq.com/ - DEPENDS:=@TARGET_lantiq + DEPENDS:=@(TARGET_lantiq||TARGET_ipq40xx) FILES:=$(PKG_BUILD_DIR)/src/drv_ifxos.ko AUTOLOAD:=$(call AutoLoad,10,drv_ifxos) endef @@ -44,13 +44,11 @@ CONFIGURE_ARGS += \ --enable-kernelincl="$(LINUX_DIR)/include" \ --with-kernel-module -ifdef CONFIG_TARGET_lantiq - define Build/InstallDev +define Build/InstallDev $(INSTALL_DIR) $(1)/usr/{lib,include/ifxos} $(CP) $(PKG_BUILD_DIR)/src/include/* $(1)/usr/include/ifxos mkdir -p $(1)/usr/lib $(CP) $(PKG_BUILD_DIR)/src/.libs/libifxos.a $(1)/usr/lib/libifxos.a - endef -endif +endef $(eval $(call KernelPackage,ltq-ifxos)) diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile b/package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile new file mode 100644 index 00000000000..990471a219a --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile @@ -0,0 +1,113 @@ +# Copyright (C) 2012 OpenWrt.org +# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-vdsl-vr11-mei +PKG_VERSION:=1.11.1 +PKG_RELEASE:=$(AUTORELEASE) +PKG_BASE_NAME:=dsl_cpe_mei + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=337614473d50ed64de010adaed99a16103e08eea8fc67fe9d6caf155bea33d1d +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=GPL-2.0 BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE +PKG_EXTMOD_SUBDIRS:=src + +PKG_FIXUP:=autoreconf +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-vdsl-vr11-mei + TITLE:=mei driver for vdsl + SECTION:=sys + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq40xx +kmod-ltq-ifxos +kmod-vrx518_tc + FILES:=$(PKG_BUILD_DIR)/src/drv_mei_cpe.ko + AUTOLOAD:=$(call AutoLoad,50,drv_mei_cpe) +endef + +define KernelPackage/ltq-vdsl-vr11-mei/description + Lantiq MEI CPE Kernel Module Driver +endef + + +define Package/ltq-vdsl-vr11-mei-test + SECTION:=net + CATEGORY:=Network + TITLE:=Lantiq mei driver test tool + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_ipq40xx +kmod-ltq-vdsl-vr11-mei +endef + +define Package/ltq-vdsl-vr11-mei-test/description + Userland tool to directly control the mei driver, this is only needed + for test and development purposes. +endef + +MAKE_FLAGS += \ + $(KERNEL_MAKE_FLAGS) \ + SHELL="$(BASH)" + +# ltq-vdsl-app uses a header provided by the MEI driver which has some +# conditionals. +# Define the conditionals here to have the same view on both sides. If you +# change them, you need to change them for the ltq-vdsl-app as well +MEI_DRV_CFLAGS = \ + -DMEI_DRV_ATM_PTM_INTERFACE_ENABLE=1 \ + -DMEI_SUPPORT_DEBUG_STREAMS=1 \ + -DMEI_SUPPORT_OPTIMIZED_FW_DL=1 + +#MEI_DRV_CFLAGS+= \ +# -DMEI_SUPPORT_OPTIMIZED_FW_DL=0 \ +# -DIRQ_POLLING_FORCE=99 + +CONFIGURE_ARGS += \ + --enable-debug-logger-support=no +# --enable-debug-stream-support=no + +# This looks weird, but it's necessary to address the right device. +# (pdev->dev.parent instead of pdev->dev) +MEI_DRV_CFLAGS+= \ + -DMEI_TARGET_x86=1 + +CONFIGURE_ARGS += \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-device=vr11 \ + --enable-debug \ + --enable-error_print \ + --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos/" \ + --enable-ifxos-library="-L$(STAGING_DIR)/usr/lib" \ + --enable-add_drv_cflags="$(MEI_DRV_CFLAGS)" \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-drv_test_appl=yes \ + ARCH=$(LINUX_KARCH) + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/vdsl + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_api_intern.h $(1)/usr/include/vdsl/ + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_api_atm_ptm_intern.h $(1)/usr/include/vdsl/ + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_interface.h $(1)/usr/include/vdsl + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_config.h $(1)/usr/include/vdsl/ + $(CP) $(PKG_BUILD_DIR)/src/cmv_message_format.h $(1)/usr/include/vdsl/ +endef + +$(eval $(call KernelPackage,ltq-vdsl-vr11-mei)) + +define Package/ltq-vdsl-vr11-mei-test/install + $(INSTALL_DIR) $(1)/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mei_cpe_drv_test $(1)/bin +endef + +$(eval $(call BuildPackage,ltq-vdsl-vr11-mei-test)) diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch new file mode 100644 index 00000000000..ff46b1f0886 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch @@ -0,0 +1,88 @@ +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -1534,7 +1534,7 @@ struct proc_entry { + char name[32]; + proc_rd_callback_t rd; + proc_wr_callback_t wr; +- struct file_operations ops; ++ struct proc_ops ops; + int entity; + }; + +@@ -2068,16 +2068,15 @@ static int mei_proc_single_open(struct i + static void mei_proc_entry_create(struct proc_dir_entry *parent_node, + struct proc_entry *proc_entry) + { +- memset(&proc_entry->ops, 0, sizeof(struct file_operations)); +- proc_entry->ops.owner = THIS_MODULE; ++ memset(&proc_entry->ops, 0, sizeof(struct proc_ops)); + +- proc_entry->ops.open = mei_proc_single_open; +- proc_entry->ops.release = single_release; ++ proc_entry->ops.proc_open = mei_proc_single_open; ++ proc_entry->ops.proc_release = single_release; + +- proc_entry->ops.read = seq_read; +- proc_entry->ops.llseek = seq_lseek; ++ proc_entry->ops.proc_read = seq_read; ++ proc_entry->ops.proc_lseek = seq_lseek; + if (proc_entry->wr) +- proc_entry->ops.write = proc_entry->wr; ++ proc_entry->ops.proc_write = proc_entry->wr; + + proc_create_data(proc_entry->name, + (S_IFREG | S_IRUGO), +--- a/src/drv_mei_cpe_linux.h ++++ b/src/drv_mei_cpe_linux.h +@@ -31,6 +31,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -122,7 +123,7 @@ typedef int (*MEI_RequestIrq_WrapLinux_t + /** + Function typedef for the Linux free_irq() + */ +-typedef void (*MEI_FreeIrq_WrapLinux_t)( unsigned int usedIrq, ++typedef const void *(*MEI_FreeIrq_WrapLinux_t)( unsigned int usedIrq, + void *usedDevId ); + + +--- a/src/drv_mei_cpe_linux_proc_config.c ++++ b/src/drv_mei_cpe_linux_proc_config.c +@@ -1277,13 +1277,12 @@ static int mei_proc_single_open(struct i + return single_open(file, mei_seq_single_show, PDE_DATA(inode)); + } + +-static struct file_operations proc_ops = { +- .owner = THIS_MODULE, +- .open = mei_proc_single_open, +- .release = single_release, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = MEI_ProcWriteConfig ++static struct proc_ops proc_ops = { ++ .proc_open = mei_proc_single_open, ++ .proc_release = single_release, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = MEI_ProcWriteConfig + }; + + /** +--- a/src/mei_cpe_appl_osmap.h ++++ b/src/mei_cpe_appl_osmap.h +@@ -38,10 +38,6 @@ extern "C" + #include + #include + #include +- +-extern int snprintf (char *__restrict __s, size_t __maxlen, +- __const char *__restrict __format, ...) +- __THROW __attribute__ ((__format__ (__printf__, 3, 4))); + #endif + + /* ========================================================================== diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch new file mode 100644 index 00000000000..f6ee2f7f8bb --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch @@ -0,0 +1,20 @@ +--- a/src/drv_mei_cpe_dbg_driver.c ++++ b/src/drv_mei_cpe_dbg_driver.c +@@ -309,7 +309,7 @@ MEI_STATIC IFX_void_t MEI_DbgMsgDumpLogW + IFX_int32_t i; + unsigned short paylSize; + union {IFX_uint8_t d8[2]; IFX_uint16_t d16;} temp16; +- union {IFX_uint8_t d8[4]; IFX_uint16_t d32;} temp32; ++ union {IFX_uint8_t d8[4]; IFX_uint32_t d32;} temp32; + + MEI_DbgMsgDumpLogLabel(pCmvMsg, fctOpCode); + +@@ -368,7 +368,7 @@ MEI_STATIC IFX_void_t MEI_DbgMsgDumpTrcW + IFX_int32_t i; + unsigned short paylSize; + union {IFX_uint8_t d8[2]; IFX_uint16_t d16;} temp16; +- union {IFX_uint8_t d8[4]; IFX_uint16_t d32;} temp32; ++ union {IFX_uint8_t d8[4]; IFX_uint32_t d32;} temp32; + + MEI_DbgMsgDumpTraceLabel(pCmvMsg, fctOpCode); + diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch new file mode 100644 index 00000000000..f6fb48ed6ea --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch @@ -0,0 +1,12 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -213,8 +213,7 @@ drv_mei_cpe_common_cflags = $(AM_CFLAGS) + else + + drv_mei_cpe_common_cflags = \ +- $(AM_CFLAGS) -D__KERNEL__ -DLINUX -D__linux__ -DMODULE -DEXPORT_SYMTAB \ +- -pipe -Wall -Wimplicit -Wunused -Wuninitialized -Wstrict-aliasing -Wno-date-time ++ -D__KERNEL__ -DLINUX -D__linux__ -DMODULE -DEXPORT_SYMTAB + + endif + diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch new file mode 100644 index 00000000000..a2e42ccb03f --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch @@ -0,0 +1,10 @@ +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -4530,7 +4530,6 @@ module_exit (MEI_module_exit); + #ifdef MODULE + MODULE_AUTHOR("www.lantiq.com"); + MODULE_DESCRIPTION("MEI CPE Driver - www.lantiq.com"); +-MODULE_SUPPORTED_DEVICE("MEI CPE Interface"); + MODULE_LICENSE ("GPL"); + #endif /* #ifdef MODULE*/ + diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch new file mode 100644 index 00000000000..18918b9956c --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch @@ -0,0 +1,13 @@ +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -1556,8 +1556,8 @@ static void MEI_GetVersionProc(struct se + } + + seq_printf(s, "%s" MEI_DRV_CRLF, &MEI_WHATVERSION[4]); +- seq_printf(s, "Compiled on %s, %s for Linux kernel %s (jiffies: %ld)" MEI_DRV_CRLF, +- __DATE__, __TIME__, UTS_RELEASE, jiffies); ++ seq_printf(s, "Compiled for Linux kernel %s (jiffies: %ld)" MEI_DRV_CRLF, ++ UTS_RELEASE, jiffies); + } + + /** diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch new file mode 100644 index 00000000000..f57b8f076fb --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch @@ -0,0 +1,12 @@ +--- a/src/drv_mei_cpe_api_atm_ptm_intern.c ++++ b/src/drv_mei_cpe_api_atm_ptm_intern.c +@@ -152,6 +152,9 @@ IFX_int32_t MEI_InternalXtmSwhowtimeExit + /* Get line number*/ + dslLineNum = pMeiDynCntrl->pMeiDev->meiDrvCntrl.dslLineNum; + ++ g_tx_link_rate[dslLineNum][0] = 0; ++ g_tx_link_rate[dslLineNum][1] = 0; ++ + #ifdef PPA_SUPPORTS_CALLBACKS + /* get NULL or function pointer */ + mei_showtime_exit = diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch new file mode 100644 index 00000000000..24db470c4ae --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch @@ -0,0 +1,10 @@ +--- a/src/drv_mei_cpe_mei_access_vrx.c ++++ b/src/drv_mei_cpe_mei_access_vrx.c +@@ -1691,7 +1691,6 @@ IFX_int32_t MEI_InterfaceDetect( + { + MEI_REG_ACCESS_ME_VERSION_SET(pMeiDrvCntrl, 0x00000000); + hwVers = MEI_REG_ACCESS_ME_VERSION_GET(pMeiDrvCntrl); +- printk ("hwVers=0x%08X\n", hwVers); + + if (MEI_DEVICE_CFG_IS_PLATFORM(e_MEI_DEV_PLATFORM_CONFIG_VR9)) + { diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/Makefile b/package/kernel/lantiq/ltq-vdsl-vr11/Makefile new file mode 100644 index 00000000000..64db4662ee5 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/Makefile @@ -0,0 +1,80 @@ +# Copyright (C) 2012 OpenWrt.org +# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-vdsl-vr11 +PKG_VERSION:=4.23.1 +PKG_RELEASE:=$(AUTORELEASE) +PKG_BASE_NAME:=dsl_cpe_api + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=5e8bbab841d67dc16e329d9b3774f6db4189dd1d01f575d0e921ccf2c426dd9f +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=GPL-2.0 BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +# TODO this driver depends on the vrx518 dsl firmware, add this dependency if +# that ever gets a compatible license +define KernelPackage/ltq-vdsl-vr11 + TITLE:=vdsl driver + SECTION:=sys + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq40xx +kmod-ltq-vdsl-vr11-mei + FILES:=$(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.ko + AUTOLOAD:=$(call AutoLoad,51,drv_dsl_cpe_api) +endef + +define Package/ltq-vdsl-vr11/description + This package contains the Lantiq DSL CPE API driver. + + Supported Devices: + - VRX500 Family +endef + +MAKE_FLAGS += \ + $(KERNEL_MAKE_FLAGS) \ + SHELL="$(BASH)" + +CONFIGURE_ARGS += \ + --enable-add-drv-cflags="" \ + --enable-add_ext_drv_cflags="-DDSL_DRV_ATM_PTM_INTERFACE_ENABLE=1" \ + --enable-debug-logger-support=no + +CONFIGURE_ARGS += --enable-kernel-include="$(LINUX_DIR)/include" \ + --enable-vrx \ + --enable-vrx-device=vr11 \ + --enable-ifxos \ + --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \ + --enable-driver-include="-I$(STAGING_DIR)/usr/include/vdsl" \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-debug-prints=no \ + ARCH=$(LINUX_KARCH) + +CONFIGURE_ARGS += \ + --enable-model=full \ + --enable-dsl-ceoc=no +#CONFIGURE_ARGS += --enable-model=lite +#CONFIGURE_ARGS += --enable-model=footprint +#CONFIGURE_ARGS += --enable-model=typical +#CONFIGURE_ARGS += --enable-model=debug + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/drv_vdsl_cpe_api + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe*.h $(1)/usr/include/drv_vdsl_cpe_api/ +endef + +$(eval $(call KernelPackage,ltq-vdsl-vr11)) diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch new file mode 100644 index 00000000000..709c3766ded --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch @@ -0,0 +1,84 @@ +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -36,6 +36,7 @@ + #endif + + #include ++#include + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +--- a/configure.in ++++ b/configure.in +@@ -422,7 +422,7 @@ AC_ARG_ENABLE(debug-prints, + AC_SUBST([DSL_DBG_MAX_LEVEL_SET],[no]) + + AC_SUBST([DSL_DBG_MAX_LEVEL_PRE],[n/a]) +- AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[no]) ++ AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[yes]) + ;; + no | none ) + AC_DEFINE(DSL_DEBUG_DISABLE,,[Disabled debug prints]) +@@ -433,7 +433,7 @@ AC_ARG_ENABLE(debug-prints, + AC_SUBST([DSL_DBG_MAX_LEVEL_SET],[no]) + + AC_SUBST([DSL_DBG_MAX_LEVEL_PRE],[n/a]) +- AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[yes]) ++ AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[no]) + ;; + prn | 0x1 ) + AC_SUBST([DSL_DEBUG_DISABLE],[no]) +--- a/src/common/drv_dsl_cpe_api.c ++++ b/src/common/drv_dsl_cpe_api.c +@@ -88,8 +88,12 @@ static DSL_uint32_t g_VRxPD_IOctlWhiteli + DSL_FIO_BAND_PLAN_STATUS_GET, + DSL_FIO_DBG_MODULE_LEVEL_GET, + DSL_FIO_DBG_MODULE_LEVEL_SET, ++#ifdef INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT ++#ifndef DSL_DEBUG_DISABLE + DSL_FIO_DBG_MODULE_DESTINATION_GET, + DSL_FIO_DBG_MODULE_DESTINATION_SET, ++#endif /* DSL_DEBUG_DISABLE*/ ++#endif /* INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT */ + DSL_FIO_OPERATOR_CONFIG_GET, + DSL_FIO_OPERATOR_CONFIG_SET, + /* Delimeter only. Keep it! */ +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c +@@ -625,7 +625,7 @@ DSL_void_t* DSL_DRV_VMalloc( + DSL_DRV_size_t nSize) + { + /* VRX500-BU: Better to use vmalloc or vzmalloc here?! */ +- return __vmalloc((unsigned long)nSize, GFP_KERNEL, PAGE_KERNEL); ++ return __vmalloc((unsigned long)nSize, GFP_KERNEL); + /* return vmalloc(nSize);*/ + } + +--- a/src/include/drv_dsl_cpe_debug.h ++++ b/src/include/drv_dsl_cpe_debug.h +@@ -99,6 +99,7 @@ DSL_void_t DSL_DRV_ErrorSet(DSL_void_t * + /** Terminate execution if assertion fails */ + #define DSL_ASSERT(exp) ((void)0) + ++ #define DSL_DEBUG_LIMIT(level, body) ((void)0) + #else + + #define DSL_DEBUG_SET_ERROR(code) DSL_DRV_ErrorSet(pContext, code); +--- a/src/pm/drv_dsl_cpe_pm_core.c ++++ b/src/pm/drv_dsl_cpe_pm_core.c +@@ -26,6 +26,7 @@ + #define DSL_DBG_BLOCK DSL_DBG_PM + + #ifdef __LINUX__ ++#ifndef DSL_DEBUG_DISABLE + #define DSL_PM_CORE_RATELIMIT_INTERVAL 20 * HZ /* for each 20 seconds */ + #define DSL_PM_CORE_RATELIMIT_BURST 1 /* 1 occurrence */ + /* struct ratelimit_state to be used in DSL_DEBUG_LIMIT */ +@@ -33,6 +34,7 @@ static DEFINE_RATELIMIT_STATE( + DSL_DBG_RATELIMIT_STRUCT_NAME(DSL_DBG_BLOCK), + DSL_PM_CORE_RATELIMIT_INTERVAL, + DSL_PM_CORE_RATELIMIT_BURST); ++#endif + #endif/* __LINUX__ */ + + DSL_boolean_t DSL_DRV_PM_IsPmReady( diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch new file mode 100644 index 00000000000..21fc0be18e2 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch @@ -0,0 +1,23 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -283,10 +283,7 @@ else + drv_dsl_cpe_api_common_mod_cflags = + endif + +-drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB \ +- -pipe -Wall -Wformat -Wimplicit -Wunused -Wswitch -Wcomment -Winline \ +- -Wuninitialized -Wparentheses -Wreturn-type \ +- -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common ++drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB + + if DSL_DBG_MAX_LEVEL_SET + drv_dsl_cpe_api_common_cflags += -DDSL_DBG_MAX_LEVEL=$(DSL_DBG_MAX_LEVEL_PRE) +@@ -296,7 +293,7 @@ endif + drv_dsl_cpe_api_target_cflags = $(ADD_DRV_CFLAGS) + + # compile cflags +-drv_dsl_cpe_api_compile_cflags = $(EXTRA_DRV_CFLAGS) ++drv_dsl_cpe_api_compile_cflags = + + if !KERNEL_2_6 + # the headerfile of linux kernels 2.6.x contain to much arithmetic diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch new file mode 100644 index 00000000000..eeda611d715 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch @@ -0,0 +1,18 @@ +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c +@@ -1051,12 +1051,11 @@ DSL_int32_t DSL_DRV_ThreadShutdown( + + DSL_uint32_t DSL_DRV_SysTimeGet(DSL_uint32_t nOffset) + { +- struct timeval tv; ++ struct timespec64 now; + DSL_uint32_t nTime = 0; + +- memset(&tv, 0, sizeof(tv)); +- do_gettimeofday(&tv); +- nTime = (DSL_uint32_t)tv.tv_sec; ++ ktime_get_real_ts64(&now); ++ nTime = (DSL_uint32_t)now.tv_sec; + + if ( (nOffset == 0) || (nOffset > nTime) ) + { diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch new file mode 100644 index 00000000000..2734415d15c --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch @@ -0,0 +1,122 @@ +--- a/src/include/drv_dsl_cpe_pm_core.h ++++ b/src/include/drv_dsl_cpe_pm_core.h +@@ -1554,9 +1554,9 @@ typedef struct + DSL_boolean_t bShowtimeProcessingStart; + /** Showtime reached flag*/ + DSL_boolean_t bShowtimeInvTrigger; +- /** Current Showtime synchronization time to be used, (msec) */ ++ /** Current Showtime synchronization time to be used, (sec) */ + DSL_uint32_t nCurrShowtimeTime; +- /** Showtime synchronization time to be used, (msec) */ ++ /** Showtime synchronization time to be used, (sec) */ + DSL_uint32_t nElapsedShowtimeTime; + /** Actual Line state*/ + DSL_LineStateValue_t nLineState; +--- a/src/pm/drv_dsl_cpe_api_pm.c ++++ b/src/pm/drv_dsl_cpe_api_pm.c +@@ -1633,7 +1633,7 @@ DSL_Error_t DSL_DRV_PM_ChannelCountersTo + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pChCounters = DSL_DRV_PM_PTR_CHANNEL_COUNTERS_TOTAL(pCounters->nChannel,pCounters->nDirection); + +@@ -1693,7 +1693,7 @@ DSL_Error_t DSL_DRV_PM_ChannelCountersEx + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pChCounters = DSL_DRV_PM_PTR_CHANNEL_COUNTERS_TOTAL_EXT(pCounters->nChannel); + +@@ -2764,7 +2764,7 @@ DSL_Error_t DSL_DRV_PM_DataPathCountersT + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pDpCounters = DSL_DRV_PM_PTR_DATAPATH_COUNTERS_TOTAL(pCounters->nChannel,pCounters->nDirection); + +@@ -3678,7 +3678,7 @@ DSL_Error_t DSL_DRV_PM_DataPathFailureCo + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pDpCounters = DSL_DRV_PM_PTR_DATAPATH_FAILURE_COUNTERS_TOTAL(pCounters->nChannel,pCounters->nDirection); + +@@ -4536,7 +4536,7 @@ DSL_Error_t DSL_DRV_PM_LineSecCountersTo + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pLineCounters = DSL_DRV_PM_PTR_LINE_SEC_COUNTERS_TOTAL(pCounters->nDirection); + +@@ -5273,7 +5273,7 @@ DSL_Error_t DSL_DRV_PM_LineInitCountersT + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pLinitCounters = DSL_DRV_PM_PTR_LINE_INIT_COUNTERS_TOTAL(); + +@@ -5774,7 +5774,7 @@ DSL_Error_t DSL_DRV_PM_LineEventShowtime + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pLfCounters = DSL_DRV_PM_PTR_LINE_EVENT_SHOWTIME_COUNTERS_TOTAL(pCounters->nDirection); + +@@ -6302,7 +6302,7 @@ DSL_Error_t DSL_DRV_PM_ReTxCountersTotal + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pReTxCounters = DSL_DRV_PM_PTR_RETX_COUNTERS_TOTAL(pCounters->nDirection); + +--- a/src/pm/drv_dsl_cpe_pm_core.c ++++ b/src/pm/drv_dsl_cpe_pm_core.c +@@ -78,6 +78,7 @@ static DSL_Error_t DSL_DRV_PM_SyncTimeUp + { + DSL_Error_t nErrCode = DSL_SUCCESS; + DSL_uint32_t msecTimeFrame = DSL_PM_COUNTER_POLLING_CYCLE, ++ secTimeFrame = DSL_PM_COUNTER_POLLING_CYCLE/DSL_PM_MSEC, + nCurrMsTime = 0; + #ifdef INCLUDE_DSL_CPE_PM_HISTORY + DSL_uint32_t nCurrSysTime = 0, nPrevElapsedTime = 0; +@@ -117,10 +118,13 @@ static DSL_Error_t DSL_DRV_PM_SyncTimeUp + { + /* Get elapsed time [msec] since the last entry*/ + msecTimeFrame = nCurrMsTime - DSL_DRV_PM_CONTEXT(pContext)->nLastMsTimeCheck; ++ ++ /* Get elapsed time [sec] since the last entry*/ ++ secTimeFrame = (nCurrMsTime/DSL_PM_MSEC) - (DSL_DRV_PM_CONTEXT(pContext)->nLastMsTimeCheck/DSL_PM_MSEC); + } + + /* Get Total Elapsed Time Since the PM module startup*/ +- DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime += msecTimeFrame; ++ DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime += secTimeFrame; + + /* Set last time check to the current time*/ + DSL_DRV_PM_CONTEXT(pContext)->nLastMsTimeCheck = nCurrMsTime; +@@ -158,7 +162,7 @@ static DSL_Error_t DSL_DRV_PM_SyncTimeUp + else + { + /* Update current showtime elapsed time*/ +- DSL_DRV_PM_CONTEXT(pContext)->nCurrShowtimeTime += (msecTimeFrame/DSL_PM_MSEC); ++ DSL_DRV_PM_CONTEXT(pContext)->nCurrShowtimeTime += secTimeFrame; + DSL_DRV_PM_CONTEXT(pContext)->nElapsedShowtimeTime = + DSL_DRV_PM_CONTEXT(pContext)->nCurrShowtimeTime; + } diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch new file mode 100644 index 00000000000..ad912605b68 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch @@ -0,0 +1,22 @@ +--- a/src/pm/drv_dsl_cpe_api_pm_vrx.c ++++ b/src/pm/drv_dsl_cpe_api_pm_vrx.c +@@ -1482,9 +1482,16 @@ DSL_Error_t DSL_DRV_PM_DEV_ReTxCountersG + /* ignore zero value*/ + if (nEftrMin) + { +- /* Fw Format: kBit/s */ +- /* API format: bit/s */ +- pCounters->nEftrMin = nEftrMin*1000; ++ if (nDirection == DSL_NEAR_END) ++ { ++ /* Fw Format: kBit/s */ ++ /* API format: bit/s */ ++ pCounters->nEftrMin = nEftrMin*1000; ++ } ++ else ++ { ++ pCounters->nEftrMin = nEftrMin; ++ } + } + } + else diff --git a/package/kernel/lantiq/vrx518_ep/Makefile b/package/kernel/lantiq/vrx518_ep/Makefile new file mode 100644 index 00000000000..1ed59d302ef --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/Makefile @@ -0,0 +1,57 @@ +# +# Copyright (C) 2019 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=vrx518_ep +PKG_VERSION:=2.1.0 +PKG_RELEASE:=$(AUTORELEASE) +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +# TODO this driver depends on the vrx518 aca firmware, add this dependency if +# that ever gets a compatible license +define KernelPackage/vrx518_ep + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=VRX518 EP Support + DEPENDS:=@TARGET_ipq40xx + AUTOLOAD:=$(call AutoLoad,26,vrx518) + FILES:=$(PKG_BUILD_DIR)/vrx518.ko +endef + +define KernelPackage/vrx518_ep/description + VRX518 endpoint driver +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/net/ + $(CP) $(PKG_BUILD_DIR)/include/net/dc_ep.h $(1)/usr/include/net/ +endef + +EXTRA_KCONFIG:= \ + CONFIG_VRX518=m +# CONFIG_TEST=m +# CONFIG_VRX518_PCIE_SWITCH_BONDING=y + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + -I$(PKG_BUILD_DIR)/include + +define Build/Compile + $(KERNEL_MAKE) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) \ + modules +endef + +$(eval $(call KernelPackage,vrx518_ep)) diff --git a/package/kernel/lantiq/vrx518_ep/patches/100-compat.patch b/package/kernel/lantiq/vrx518_ep/patches/100-compat.patch new file mode 100644 index 00000000000..f5b917e7078 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/patches/100-compat.patch @@ -0,0 +1,73 @@ +--- a/ep.c ++++ b/ep.c +@@ -373,23 +373,23 @@ int dc_ep_dev_info_req(int dev_idx, enum + + switch (module) { + case DC_EP_INT_PPE: +- dev->irq = priv->irq_base; ++ dev->irq = pci_irq_vector(priv->pdev, 0); + if (priv->msi_mode == DC_EP_8_MSI_MODE) { +- dev->aca_tx_irq = priv->irq_base + 7; +- dev->aca_rx_irq = priv->irq_base + 6; ++ dev->aca_tx_irq = pci_irq_vector(priv->pdev, 7); ++ dev->aca_rx_irq = pci_irq_vector(priv->pdev, 6); + } else if (priv->msi_mode == DC_EP_4_MSI_MODE) { +- dev->aca_tx_irq = priv->irq_base + 2; +- dev->aca_rx_irq = priv->irq_base + 3; ++ dev->aca_tx_irq = pci_irq_vector(priv->pdev, 2); ++ dev->aca_rx_irq = pci_irq_vector(priv->pdev, 3); + } else { + dev_err(dev->dev, "%s ACA should never occur\n", + __func__); + } + break; + case DC_EP_INT_MEI: +- dev->irq = priv->irq_base + 1; ++ dev->irq = pci_irq_vector(priv->pdev, 1); + break; + default: +- dev->irq = priv->irq_base; ++ dev->irq = pci_irq_vector(priv->pdev, 0); + break; + } + +@@ -466,8 +466,8 @@ static int dc_ep_msi_enable(struct pci_d + return -EIO; + } + +- err = pci_enable_msi_exact(pdev, nvec); +- if (err) { ++ err = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSI | PCI_IRQ_LEGACY); ++ if (err < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable MSI interrupts error code: %d\n", + __func__, err); +@@ -654,7 +654,7 @@ static int dc_ep_probe(struct pci_dev *p + goto err_iomap; + + spin_lock(&dc_ep_lock); +- priv->irq_base = pdev->irq; ++ priv->irq_base = pci_irq_vector(pdev, 0); + spin_unlock(&dc_ep_lock); + + #ifndef CONFIG_OF +@@ -715,7 +715,7 @@ static void dc_ep_remove(struct pci_dev + dc_ep_icu_disable(priv); + pci_iounmap(pdev, priv->mem); + pci_release_region(pdev, DC_EP_BAR_NUM); +- pci_disable_msi(pdev); ++ pci_free_irq_vectors(pdev); + wmb(); + pci_clear_master(pdev); + pci_disable_device(pdev); +--- a/aca.c ++++ b/aca.c +@@ -756,7 +756,7 @@ static void aca_hif_param_init_done(stru + addr = fw_param->init_addr; + dev_dbg(priv->dev, "init_addr: %x\n", addr); + memcpy_toio(priv->mem + addr, hif_params, sizeof(*hif_params)); +- kzfree(hif_params); ++ kfree(hif_params); + dev_dbg(priv->dev, "%s\n", __func__); + } + diff --git a/package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch b/package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch new file mode 100644 index 00000000000..b833c72bec3 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch @@ -0,0 +1,49 @@ +Fix double negation of bitmask in dc_ep_icu_disable andwr32_mask. +Also add locking to ensure the masking is applied atomically. + +--- a/misc.c ++++ b/misc.c +@@ -68,12 +68,22 @@ void dc_ep_icu_disable(struct dc_ep_priv + + void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits) + { +- wr32_mask(~bits, 0, ICU_IMER); ++ struct dc_aca *aca = to_aca(priv); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&aca->icu_lock, flags); ++ wr32_mask(bits, 0, ICU_IMER); ++ spin_unlock_irqrestore(&aca->icu_lock, flags); + } + + void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits) + { ++ struct dc_aca *aca = to_aca(priv); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&aca->icu_lock, flags); + wr32_mask(0, bits, ICU_IMER); ++ spin_unlock_irqrestore(&aca->icu_lock, flags); + } + + void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits) +--- a/aca.c ++++ b/aca.c +@@ -1158,6 +1158,7 @@ void dc_aca_info_init(struct dc_ep_priv + struct dc_aca *aca = to_aca(priv); + + aca->initialized = false; ++ spin_lock_init(&aca->icu_lock); + spin_lock_init(&aca->clk_lock); + spin_lock_init(&aca->rcu_lock); + mutex_init(&aca->pin_lock); +--- a/aca.h ++++ b/aca.h +@@ -470,6 +470,7 @@ struct aca_hif_params { + + struct dc_aca { + bool initialized; ++ spinlock_t icu_lock; + spinlock_t clk_lock; + spinlock_t rcu_lock; + struct mutex pin_lock; diff --git a/package/kernel/lantiq/vrx518_ep/src/Kconfig b/package/kernel/lantiq/vrx518_ep/src/Kconfig new file mode 100644 index 00000000000..296bc4c7aae --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/Kconfig @@ -0,0 +1,9 @@ +config TEST + tristate "Intel(R) VRX518 SmartPHY DSL Test Driver" + depends on VRX518 + ---help--- + This driver supports Intel(R) VRX518 DSL interrupt and ACA test. + + To compile this driver as a module, choose M here. The module + will be called vrx518. MSI interrupt support is required for + this driver to work correctly. diff --git a/package/kernel/lantiq/vrx518_ep/src/Makefile b/package/kernel/lantiq/vrx518_ep/src/Makefile new file mode 100644 index 00000000000..b79e74b3170 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/Makefile @@ -0,0 +1,33 @@ +################################################################################ +# +# Intel SmartPHY DSL PCIe EP/ACA Linux driver +# Copyright(c) 2016 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +################################################################################ + +# +# Makefile for the Intel(R) SmartPHY PCIe/ACA driver +# + +obj-$(CONFIG_VRX518) += vrx518.o + +vrx518-objs := ep.o aca.o misc.o + +obj-$(CONFIG_TEST) += test/ + diff --git a/package/kernel/lantiq/vrx518_ep/src/aca.c b/package/kernel/lantiq/vrx518_ep/src/aca.c new file mode 100644 index 00000000000..3fcf454884a --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/aca.c @@ -0,0 +1,1209 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ +#define DEBUG +#include +#include +#include +#include + +#include + +#include "regs.h" +#include "ep.h" +#include "misc.h" +#include "aca.h" + +#define ACA_FW_FILE "aca_fw.bin" + +#define set_mask_bit(val, set, mask, bits) \ + (val = (((val) & (~((mask) << (bits)))) \ + | (((set) & (mask)) << (bits)))) + +static char soc_str[128]; + +static const char *const aca_img_type_str[ACA_IMG_MAX] = { + "vrx518", + "vrx618", + "falcon-mx", + "pmua", +}; + +static void soc_type_to_str(u32 soc) +{ + memset(soc_str, 0, sizeof(soc_str)); + + if ((soc & ACA_SOC_XRX300)) + strcat(soc_str, "xrx300 "); + + if ((soc & ACA_SOC_XRX500)) + strcat(soc_str, "xrx500 "); + + if ((soc & ACA_SOC_PUMA)) + strcat(soc_str, "puma "); + + if ((soc & ACA_SOC_3RD_PARTY)) + strcat(soc_str, "third party SoC "); +} + +static const char *fw_id_to_str(u32 fw_id) +{ + switch (fw_id) { + case ACA_FW_TXIN: + return "txin"; + + case ACA_FW_TXOUT: + return "txout"; + + case ACA_FW_RXIN: + return "rxin"; + + case ACA_FW_RXOUT: + return "rxout"; + + case ACA_FW_GNRC: + return "Genrisc"; + + default: + return "unknow"; + } +} + +static const char * const sec_id_str[] = { + "Unknown", "HIF", "GenRisc", "MAC_HT", "TXIN", "TXIN_PDRING", "TXOUT", + "TXOUT_PDRING", "RXIN", "RXIN_PDRING", "RXOUT", "RXOUT_PDRING", "DMA", + "FW_INIT", +}; +static const char *sec_id_to_str(u32 sec_id) +{ + switch (sec_id) { + case ACA_SEC_HIF: + case ACA_SEC_GNR: + case ACA_SEC_MAC_HT: + case ACA_SEC_MEM_TXIN: + case ACA_SEC_MEM_TXIN_PDRING: + case ACA_SEC_MEM_TXOUT: + case ACA_SEC_MEM_TXOUT_PDRING: + case ACA_SEC_MEM_RXIN: + case ACA_SEC_MEM_RXIN_PDRING: + case ACA_SEC_MEM_RXOUT: + case ACA_SEC_MEM_RXOUT_PDRING: + case ACA_SEC_DMA: + case ACA_SEC_FW_INIT: + return sec_id_str[sec_id]; + case ACA_SEC_FW: + return "ACA FW"; + + default: + return "unknown"; + } +} + +static inline struct aca_fw_info *to_fw_info(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info; +} + +static inline struct aca_fw_dl_addr *to_fw_addr(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.fw_dl; +} + +static inline struct aca_mem_layout *to_mem_layout(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.mem_layout; +} + +static inline struct aca_pdmem_layout *to_pdmem_layout(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.pdmem_layout; +} + +static inline struct aca_fw_param *to_aca_fw_param(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.fw_param; +} + +static inline struct aca_hif_params *to_hif_params(struct dc_ep_priv *priv) +{ + return priv->aca.hif_params; +} + +static const struct firmware *aca_fetch_fw_file(struct dc_ep_priv *priv, + char *dir, const char *file) +{ + int ret; + char filename[100] = {0}; + const struct firmware *fw; + + if (file == NULL) + return ERR_PTR(-ENOENT); + + if (dir == NULL) + dir = "."; + + snprintf(filename, sizeof(filename), "%s/%s", dir, file); + ret = request_firmware(&fw, filename, priv->dev); + if (ret) + return ERR_PTR(ret); + + return fw; +} + +void dc_aca_free_fw_file(struct dc_ep_priv *priv) +{ + struct aca_fw_info *fw_info = to_fw_info(priv); + + if (fw_info->fw && !IS_ERR(fw_info->fw)) + release_firmware(fw_info->fw); + + fw_info->fw = NULL; + fw_info->fw_data = NULL; + fw_info->fw_len = 0; +} + +static void aca_dma_parse(struct dc_ep_priv *priv, const char *data, int chn) +{ + int i; + u32 cid, dbase; + struct aca_fw_dma *fw_dma; + struct aca_fw_info *fw_info = to_fw_info(priv); + + fw_info->chan_num = chn; + + for (i = 0; i < fw_info->chan_num; i++) { + fw_dma = (struct aca_fw_dma *)(data + i * sizeof(*fw_dma)); + cid = be32_to_cpu(fw_dma->cid); + dbase = be32_to_cpu(fw_dma->base); + fw_info->adma_desc_base[cid] = dbase; + dev_dbg(priv->dev, "dma channel %d desc base 0x%08x\n", + cid, dbase); + } +} + +static void aca_sram_desc_parse(struct dc_ep_priv *priv, const char *data, + u32 sid) +{ + u32 dbase, dnum; + struct aca_sram_desc *desc_base; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_pdmem_layout *pdmem = to_pdmem_layout(priv); + + desc_base = (struct aca_sram_desc *)data; + dbase = be32_to_cpu(desc_base->dbase); + dnum = be32_to_cpu(desc_base->dnum); + + dev_dbg(priv->dev, "Sec %s desc base 0x%08x, des_num: %d\n", + sec_id_to_str(sid), dbase, dnum); + + switch (sid) { + case ACA_SEC_MEM_TXIN: + mem_layout->txin_host_desc_base = dbase; + mem_layout->txin_host_dnum = dnum; + break; + + case ACA_SEC_MEM_TXOUT: + mem_layout->txout_host_desc_base = dbase; + mem_layout->txout_host_dnum = dnum; + break; + + case ACA_SEC_MEM_RXIN: + mem_layout->rxin_host_desc_base = dbase; + mem_layout->rxin_host_dnum = dnum; + break; + + case ACA_SEC_MEM_RXOUT: + mem_layout->rxout_host_desc_base = dbase; + mem_layout->rxout_host_dnum = dnum; + break; + case ACA_SEC_MEM_TXIN_PDRING: + pdmem->txin_pd_desc_base = dbase; + pdmem->txin_pd_dnum = dnum; + break; + case ACA_SEC_MEM_TXOUT_PDRING: + pdmem->txout_pd_desc_base = dbase; + pdmem->txout_pd_dnum = dnum; + break; + case ACA_SEC_MEM_RXIN_PDRING: + pdmem->rxin_pd_desc_base = dbase; + pdmem->rxin_pd_dnum = dnum; + break; + case ACA_SEC_MEM_RXOUT_PDRING: + pdmem->rxin_pd_desc_base = dbase; + pdmem->rxin_pd_dnum = dnum; + break; + default: + dev_err(priv->dev, "Unknow aca sram section %d\n", sid); + break; + } +} + +static void aca_init_parse(struct dc_ep_priv *priv, const char *data, + u32 sid) +{ + struct aca_fw_param *fw_param = to_aca_fw_param(priv); + struct aca_fw_param *param; + u32 hdr_sz, hdr_addr; + + param = (struct aca_fw_param *)data; + hdr_sz = be32_to_cpu(param->st_sz); + hdr_addr = be32_to_cpu(param->init_addr); + + fw_param->init_addr = hdr_addr; + fw_param->st_sz = hdr_sz; + dev_dbg(priv->dev, "init st size: %d, addr: 0x%x\n", + hdr_sz, hdr_addr); +} + +static void aca_fw_parse(struct dc_ep_priv *priv, const char *data, + const char *fw_base, int fw_num) +{ + int i; + size_t size; + u32 id, offset, addr; + struct aca_int_hdr *hdr; + struct aca_fw_dl_addr *fw_dl = to_fw_addr(priv); + + fw_dl->fw_num = fw_num; + + for (i = 0; i < fw_dl->fw_num; i++) { + hdr = (struct aca_int_hdr *)(data + i * sizeof(*hdr)); + id = be32_to_cpu(hdr->id); + offset = be32_to_cpu(hdr->offset); + size = be32_to_cpu(hdr->size); + addr = be32_to_cpu(hdr->load_addr); + + fw_dl->fw_addr[i].fw_id = id; + fw_dl->fw_addr[i].fw_load_addr = addr; + fw_dl->fw_addr[i].fw_size = size; + fw_dl->fw_addr[i].fw_base = fw_base + offset; + dev_dbg(priv->dev, + "aca %s fw offset 0x%x size %zd loc 0x%x fw base %p\n", + fw_id_to_str(id), offset, size, addr, fw_base + offset); + } +} + +/* -------------------------------------------------------- + | Fixed header (20Bytes) | + --------------------------------------------------------- + | Variable header | + | ie / payload | + |-------------------------------------------------------| + | Actual ACA FW | + --------------------------------------------------------- +*/ +static int aca_section_parse(struct dc_ep_priv *priv, const char *fw_data) +{ + int ret = 0; + u32 fixed_hlen; + u32 var_hlen; + u32 ie_id; + size_t ie_len, ie_hlen, ie_dlen; + u32 fw_hlen; + struct aca_fw_f_hdr *fw_f_hdr; + struct aca_fw_ie *ie_hdr; + struct aca_int_hdr *aca_hdr; + const char *data = fw_data; + const char *aca_fw_data; + struct device *dev = priv->dev; + + fw_f_hdr = (struct aca_fw_f_hdr *)data; + + fw_hlen = be32_to_cpu(fw_f_hdr->hdr_size); + fixed_hlen = sizeof(*fw_f_hdr); + var_hlen = fw_hlen - fixed_hlen; + ie_hlen = sizeof(*ie_hdr); + + /* Record actual ACA fw data pointer */ + aca_fw_data = data + fw_hlen; + + /* Point to variable header and parse them */ + data += fixed_hlen; + + while (var_hlen > ie_hlen) { + /* Variable header information element */ + ie_hdr = (struct aca_fw_ie *)data; + ie_id = be32_to_cpu(ie_hdr->id); + ie_len = be32_to_cpu(ie_hdr->len); + dev_dbg(dev, "Section %s ie_len %zd\n", sec_id_to_str(ie_id), + ie_len); + + /* Variable header data conents */ + data += ie_hlen; + var_hlen -= ie_hlen; + + switch (ie_id) { + case ACA_SEC_HIF: + case ACA_SEC_GNR: + case ACA_SEC_MAC_HT: + ie_dlen = ie_len * sizeof(struct aca_fw_reg); + data += ie_dlen; + var_hlen -= ie_dlen; + + break; + + case ACA_SEC_MEM_TXIN: + case ACA_SEC_MEM_TXOUT: + case ACA_SEC_MEM_RXIN: + case ACA_SEC_MEM_RXOUT: + case ACA_SEC_MEM_TXIN_PDRING: + case ACA_SEC_MEM_TXOUT_PDRING: + case ACA_SEC_MEM_RXIN_PDRING: + case ACA_SEC_MEM_RXOUT_PDRING: + aca_sram_desc_parse(priv, data, ie_id); + ie_dlen = ie_len * sizeof(struct aca_sram_desc); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + case ACA_SEC_DMA: + if (ie_len > ACA_DMA_CHAN_MAX) { + dev_err(dev, "invalid dma channel %d\n", + ie_len); + ret = -EINVAL; + goto done; + } + aca_dma_parse(priv, data, ie_len); + ie_dlen = ie_len * sizeof(struct aca_fw_dma); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + case ACA_SEC_FW_INIT: + aca_init_parse(priv, data, ie_id); + ie_dlen = ie_len * sizeof(struct aca_fw_param); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + case ACA_SEC_FW: + if (ie_len > ACA_FW_MAX) { + dev_err(dev, "Too many aca fws %d\n", ie_len); + ret = -EINVAL; + goto done; + } + aca_fw_parse(priv, data, aca_fw_data, ie_len); + ie_dlen = ie_len * sizeof(*aca_hdr); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + default: + dev_warn(dev, "Unknown Sec id: %u\n", ie_id); + break; + } + } +done: + return ret; +} + +static int aca_fetch_fw_api(struct dc_ep_priv *priv, const char *name) +{ + int ret; + size_t hdr_len; + const u8 *fw_data; + size_t fw_len; + char dir[8] = {0}; + union fw_ver ver; + union img_soc_type type; + struct device *dev = priv->dev; + struct aca_fw_f_hdr *fw_f_hdr; + struct aca_fw_info *fw_info = to_fw_info(priv); + + sprintf(dir, "%04x", priv->pdev->device); + fw_info->fw = aca_fetch_fw_file(priv, dir, name); + if (IS_ERR(fw_info->fw)) { + dev_err(dev, "Could not fetch firmware file '%s': %ld\n", + name, PTR_ERR(fw_info->fw)); + return PTR_ERR(fw_info->fw); + } + + fw_data = fw_info->fw->data; + fw_len = fw_info->fw->size; + + /* Parse the fixed header part */ + fw_f_hdr = (struct aca_fw_f_hdr *)fw_data; + ver.all = be32_to_cpu(fw_f_hdr->ver); + + dev_info(dev, "ACA fw build %d branch %d major 0x%2x minor 0x%04x\n", + ver.field.build, ver.field.branch, + ver.field.major, ver.field.minor); + + type.all = be32_to_cpu(fw_f_hdr->type); + + if (type.field.img_type > (ACA_IMG_MAX - 1) + || ((type.field.soc_type & ACA_SOC_MASK) == 0)) { + dev_err(dev, "Invalid aca fw img %d soc %d\n", + type.field.img_type, type.field.soc_type); + ret = -EINVAL; + goto err; + } + + soc_type_to_str(type.field.soc_type); + + dev_info(priv->dev, "ACA fw for %s supported SoC type %s\n", + aca_img_type_str[type.field.img_type], soc_str); + + hdr_len = be32_to_cpu(fw_f_hdr->hdr_size); + /* Sanity Check */ + if (fw_len < hdr_len) { + dev_err(dev, "Invalid aca fw hdr len %zd fw len %zd\n", + hdr_len, fw_len); + ret = -EINVAL; + goto err; + } + dev_dbg(dev, "Header size 0x%08x fw size 0x%08x\n", + hdr_len, be32_to_cpu(fw_f_hdr->fw_size)); + dev_dbg(dev, "section number %d\n", + be32_to_cpu(fw_f_hdr->num_section)); + + aca_section_parse(priv, fw_data); + return 0; +err: + dc_aca_free_fw_file(priv); + return ret; +} + +static int aca_fetch_fw(struct dc_ep_priv *priv) +{ + return aca_fetch_fw_api(priv, ACA_FW_FILE); +} + +static int aca_fw_download(struct dc_ep_priv *priv) +{ + int i, j; + u32 val; + size_t size; + u32 id, load_addr; + const char *fw_base; + struct aca_fw_dl_addr *fw_dl = to_fw_addr(priv); + + for (i = 0; i < fw_dl->fw_num; i++) { + id = fw_dl->fw_addr[i].fw_id; + load_addr = fw_dl->fw_addr[i].fw_load_addr; + size = fw_dl->fw_addr[i].fw_size; + fw_base = fw_dl->fw_addr[i].fw_base; + + if (size % 4) { + dev_err(priv->dev, + "aca %s fw size is not a multiple of 4\n", + fw_id_to_str(id)); + return -EINVAL; + } + + for (j = 0; j < size; j += 4) { + val = *((u32 *)(fw_base + j)); + wr32(cpu_to_be32(val), load_addr + j); + } + /* Write flush */ + rd32(load_addr); + #ifdef DEBUG + { + u32 src, dst; + + for (j = 0; j < size; j += 4) { + dst = rd32(load_addr + j); + src = *((u32 *)(fw_base + j)); + if (dst != cpu_to_be32(src)) { + dev_info(priv->dev, + "dst 0x%08x != src 0x%08x\n", dst, src); + return -EIO; + } + } + } + #endif /* DEBUG */ + } + return 0; +} + +static void aca_dma_ctrl_init(struct dc_ep_priv *priv) +{ + u32 val; + struct dc_aca *aca = to_aca(priv); + + /* Global software reset CDMA */ + wr32_mask(0, BIT(CTRL_RST), ADMA_CTRL); + while ((rd32(ADMA_CTRL) & BIT(CTRL_RST))) + ; + + val = rd32(ADMA_ID); + /* Record max dma channels for later usage */ + aca->adma_chans = MS(val, ADMA_ID_CHNR); + val = rd32(ADMA_CTRL); + /* + * Enable Packet Arbitration + * Enable Meta data copy + * Enable Dedicated Descriptor port + */ + val |= BIT(CTRL_PKTARB) | BIT(CTRL_MDC) | BIT(CTRL_DSRAM); + set_mask_bit(val, 1, 1, CTRL_ENBE); /* Enable byte enable */ + set_mask_bit(val, 1, 1, CTRL_DCNF); /* 2DW descriptor format */ + set_mask_bit(val, 1, 1, CTRL_DDBR); /* Descriptor read back */ + set_mask_bit(val, 1, 1, CTRL_DRB); /* Dynamic burst read */ + wr32(val, ADMA_CTRL); + + /* Polling cnt cfg */ + wr32(ADMA_CPOLL_EN | SM(ADMA_DEFAULT_POLL, ADMA_CPOLL_CNT), + ADMA_CPOLL); +} + +static void aca_dma_port_init(struct dc_ep_priv *priv) +{ + u32 val; + + /* Only one port /port 0 */ + wr32(0, ADMA_PS); + val = rd32(ADMA_PCTRL); + set_mask_bit(val, 1, 1, PCTRL_RXBL16); + set_mask_bit(val, 1, 1, PCTRL_TXBL16); + set_mask_bit(val, 0, 3, PCTRL_RXBL); + set_mask_bit(val, 0, 3, PCTRL_TXBL); + + set_mask_bit(val, 0, 3, PCTRL_TXENDI); + set_mask_bit(val, 0, 3, PCTRL_RXENDI); + wr32(val, ADMA_PCTRL); +} + +static void aca_dma_ch_init(struct dc_ep_priv *priv, u32 cid, + u32 dbase, u32 dlen) +{ + /* Select channel */ + wr32(cid, ADMA_CS); + + /* Reset Channel */ + wr32_mask(0, BIT(CCTRL_RST), ADMA_CCTRL); + while ((rd32(ADMA_CCTRL) & BIT(CCTRL_RST))) + ; + + /* Set descriptor list base and length */ + wr32(dbase, ADMA_CDBA); + wr32(dlen, ADMA_CDLEN); + + /*Clear Intr */ + wr32(ADMA_CI_ALL, ADMA_CIS); + /* Enable Intr */ + wr32(ADMA_CI_ALL, ADMA_CIE); + + /* Enable Channel */ + wr32_mask(0, BIT(CCTRL_ONOFF), ADMA_CCTRL); + mb(); +} + +static void aca_dma_ch_off(struct dc_ep_priv *priv) +{ + int i; + struct dc_aca *aca = to_aca(priv); + + /* Shared between OS and ACA FW. Stop ACA first */ + for (i = 0; i < aca->adma_chans; i++) { + wr32(i, ADMA_CS); + wr32_mask(BIT(CCTRL_ONOFF), 0, ADMA_CCTRL); + while (rd32(ADMA_CCTRL) & BIT(CCTRL_ONOFF)) + ; + } + dev_dbg(priv->dev, "aca dma channel done\n"); +} + +static void aca_xbar_ia_reject_set(struct dc_ep_priv *priv, int ia_id) +{ + u32 val; + int timeout = 1000; + struct device *dev = priv->dev; + + /* Set reject bit */ + wr32(XBAR_CTRL_REJECT, ACA_AGENT_CTRL(ia_id)); + + /* Poll burst, readex, resp_waiting, req_active */ + val = XBAR_STAT_REQ_ACTIVE | XBAR_STAT_RESP_WAITING + | XBAR_STAT_BURST | XBAR_STAT_READEX; + while (--timeout && !!(rd32(ACA_AGENT_STATUS(ia_id)) & val)) + udelay(1); + + if (timeout <= 0) { + dev_dbg(dev, + "ACA XBAR IA: %d reset timeout, pending on 0x%x\n", + ia_id, rd32(ACA_AGENT_STATUS(ia_id))); + return; + } +} + +static void aca_xbar_ia_reject_clr(struct dc_ep_priv *priv, int ia_id) +{ + u32 val; + + /* Check reject bit */ + val = rd32(ACA_AGENT_CTRL(ia_id)); + if ((val & XBAR_CTRL_REJECT) == 0) + return; + + /* Clear reject bit */ + val &= ~XBAR_CTRL_REJECT; + wr32(val, ACA_AGENT_CTRL(ia_id)); + rd32(ACA_AGENT_CTRL(ia_id)); +} + +static void aca_xbar_ia_reset(struct dc_ep_priv *priv, int ia_id) +{ + /* ACA IA reset */ + wr32(XBAR_CTRL_CORE_RESET, ACA_AGENT_CTRL(ia_id)); + + /* Read till status become 1 */ + while ((rd32(ACA_AGENT_STATUS(ia_id)) & XBAR_STAT_CORE_RESET) == 0) + ; + + /* Clear the IA Reset signal */ + wr32(0, ACA_AGENT_CTRL(ia_id)); + + /* Read till status become 0 */ + while ((rd32(ACA_AGENT_STATUS(ia_id)) & XBAR_STAT_CORE_RESET) == 1) + ; + + dev_dbg(priv->dev, "ACA XBAR IA(%d) reset done\n", ia_id); +} + +void dc_aca_shutdown(struct dc_ep_priv *priv) +{ + struct dc_aca *aca = to_aca(priv); + + if (aca->initialized) { + aca_xbar_ia_reset(priv, ACA_ACC_IA04); + aca_xbar_ia_reset(priv, ACA_M_IA06); + } +} + +static void aca_dma_init(struct dc_ep_priv *priv) +{ + int i; + struct aca_fw_info *fw_info = to_fw_info(priv); + + aca_dma_ctrl_init(priv); + aca_dma_port_init(priv); + + for (i = 0; i < fw_info->chan_num; i++) { + aca_dma_ch_init(priv, i, + fw_info->adma_desc_base[i] | priv->phymem, + DESC_NUM_PER_CH); + } + + dev_dbg(priv->dev, "aca dma init done\n"); +} + +static void aca_basic_init(struct dc_ep_priv *priv) +{ + u32 addr, mask; + + /* Low 32 is RX, High 32 is TX */ + wr32(0x1, UMT_ORDER_CFG); + /* TXIN/TXOUT/RXIN/RXOUT All Controlled by Genrisc */ + wr32(0xF, HOST_TYPE); + /* Enable Host Gate CLK */ + wr32(0x4000, HT_GCLK_ENABLE); + /* Host Page/MASK */ + mask = ~priv->memsize + 1; + addr = mask | ((priv->phymem & mask) >> 16); + wr32(addr, AHB_ARB_HP_REG); + wr32(addr, OCP_ARB_ACC_PAGE_REG); + /* Stop all functions first */ + wr32(0, GNRC_EN_TASK_BITMAP); + + /* Enable XBAR */ + aca_xbar_ia_reject_clr(priv, ACA_ACC_IA04); + aca_xbar_ia_reject_clr(priv, ACA_M_IA06); + + dev_dbg(priv->dev, "aca basic config done\n"); +} + +static int aca_hif_param_init(struct dc_ep_priv *priv) +{ + struct dc_aca *aca = to_aca(priv); + + aca->hif_params = kzalloc(sizeof(struct aca_hif_params), GFP_KERNEL); + if (!aca->hif_params) + return -ENOMEM; + aca->hif_params->task_mask = 0x0000000F; + dev_dbg(priv->dev, "%s\n", __func__); + return 0; +} + +static void aca_hif_param_init_done(struct dc_ep_priv *priv) +{ + u32 addr; + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_fw_param *fw_param = to_aca_fw_param(priv); + + /* wr32(ACA_HIF_PARAM_ADDR, ACA_HIF_LOC_POS);*/ + /* addr = rd32(ACA_HIF_LOC_POS);*/ + + addr = fw_param->init_addr; + dev_dbg(priv->dev, "init_addr: %x\n", addr); + memcpy_toio(priv->mem + addr, hif_params, sizeof(*hif_params)); + kzfree(hif_params); + dev_dbg(priv->dev, "%s\n", __func__); +} + +static bool aca_hif_param_init_check(struct dc_ep_priv *priv) +{ + u32 addr; + int timeout = ACA_LOOP_CNT; + u32 offset = offsetof(struct aca_hif_params, magic); + struct aca_fw_param *fw_param = to_aca_fw_param(priv); + + /* addr = rd32(ACA_HIF_LOC_POS);*/ + addr = fw_param->init_addr; + while (--timeout && (rd32(addr + offset) != ACA_MAGIC)) + udelay(1); + + if (timeout <= 0) { + dev_err(priv->dev, "aca hif params init failed\n"); + return false; + } + + return true; +} + +static void aca_txin_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_txin) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *txin_param = &hif_params->txin; + + if (aca_txin->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_txin->hd_size_in_dw - 1) + | SM((aca_txin->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, TXIN_CONV_CFG); + + /* SoC cumulative counter address */ + wr32(aca_txin->soc_cmlt_cnt_addr, GNRC_TXIN_CMLT_CNT_ADDR); + + + /* SoC descriptors */ + txin_param->soc_desc_base = aca_txin->soc_desc_base; + txin_param->soc_desc_num = aca_txin->soc_desc_num; + + /* Ping/pong buffer */ + txin_param->pp_buf_base = priv->phymem + + mem_layout->txin_host_desc_base; + + txin_param->pp_buf_num = mem_layout->txin_host_dnum; + + /* PD ring */ + txin_param->pd_desc_base = priv->phymem + + aca_txin->pd_desc_base; + txin_param->pd_desc_num = aca_txin->pd_desc_num; + + dev_dbg(priv->dev, "aca txin init done\n"); +} + +static void aca_txout_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_txout) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *txout_param = &hif_params->txout; + + if (aca_txout->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_txout->hd_size_in_dw - 1) + | SM((aca_txout->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, TXOUT_CONV_CFG); + + /* SoC Ring size */ + val = aca_txout->soc_desc_num; + wr32(val, TXOUT_RING_CFG); + + /* SoC cumulative counter address */ + wr32(aca_txout->soc_cmlt_cnt_addr, GNRC_TXOUT_CMLT_CNT_ADDR); + /* SoC descriptors */ + txout_param->soc_desc_base = aca_txout->soc_desc_base; + txout_param->soc_desc_num = aca_txout->soc_desc_num; + + /* Ping/pong buffer */ + txout_param->pp_buf_base = priv->phymem + +mem_layout->txout_host_desc_base; + + txout_param->pp_buf_num = mem_layout->txout_host_dnum; + + /* PD ring */ + txout_param->pd_desc_base = priv->phymem + + aca_txout->pd_desc_base; + txout_param->pd_desc_num = aca_txout->pd_desc_num; + + txout_param->pd_desc_threshold = aca_txout->pp_buf_desc_num; + + dev_dbg(priv->dev, "aca txout init done\n"); +} + +static void aca_rxin_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_rxin) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *rxin_param = &hif_params->rxin; + + if (aca_rxin->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_rxin->hd_size_in_dw - 1) + | SM((aca_rxin->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, RXIN_CONV_CFG); + + /* SoC cumulative counter address */ + wr32(aca_rxin->soc_cmlt_cnt_addr, GNRC_RXIN_CMLT_CNT_ADDR); + + /* RXIN may not be used */ + if (!(aca_rxin->soc_desc_base)) + goto __RXIN_DONE; + /* SoC descriptors */ + rxin_param->soc_desc_base = aca_rxin->soc_desc_base; + rxin_param->soc_desc_num = aca_rxin->soc_desc_num; + + /* Ping/pong buffer */ + rxin_param->pp_buf_base = (u32)priv->phymem + + mem_layout->rxin_host_desc_base; + + rxin_param->pp_buf_num = mem_layout->rxin_host_dnum; + + /* PD ring */ + rxin_param->pd_desc_base = (u32)priv->phymem + + aca_rxin->pd_desc_base; + rxin_param->pd_desc_num = aca_rxin->pd_desc_num; + + rxin_param->pd_desc_threshold = aca_rxin->pp_buf_desc_num; + +__RXIN_DONE: + dev_dbg(priv->dev, "aca rxin init done\n"); +} + +static void aca_rxout_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_rxout) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *rxout_param = &hif_params->rxout; + + if (aca_rxout->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_rxout->hd_size_in_dw - 1) + | SM((aca_rxout->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, RXOUT_CONV_CFG); + + /* SoC Ring size */ + val = aca_rxout->soc_desc_num; + wr32(val, RXOUT_RING_CFG); + + /* SoC cumulative counter address */ + wr32(aca_rxout->soc_cmlt_cnt_addr, GNRC_RXOUT_CMLT_CNT_ADDR); + /* SoC descriptors */ + rxout_param->soc_desc_base = aca_rxout->soc_desc_base; + rxout_param->soc_desc_num = aca_rxout->soc_desc_num; + + /* Ping/pong buffer */ + rxout_param->pp_buf_base = (u32)priv->phymem + + mem_layout->rxout_host_desc_base; + + rxout_param->pp_buf_num = mem_layout->rxout_host_dnum; + + /* PD ring */ + rxout_param->pd_desc_base = (u32)priv->phymem + + aca_rxout->pd_desc_base; + rxout_param->pd_desc_num = aca_rxout->pd_desc_num; + + rxout_param->pd_desc_threshold = aca_rxout->pp_buf_desc_num; + dev_dbg(priv->dev, "aca rxout init done\n"); +} + +static void aca_mdm_init(struct dc_ep_priv *priv, struct aca_modem_param *mdm) +{ + struct aca_proj_param *param; + + if (!mdm) + return; + + param = &mdm->mdm_txout; + wr32(param->stat | priv->phymem, GNRC_TXOUT_TGT_STAT); + wr32(param->pd | priv->phymem, GNRC_TXOUT_TGT_PD_OFF); + wr32(param->acc_cnt | priv->phymem, GNRC_TXOUT_TGT_ACCM_CNT); + + param = &mdm->mdm_rxin; + wr32(param->stat | priv->phymem, GNRC_RXIN_TGT_STAT); + wr32(param->pd | priv->phymem, GNRC_RXIN_TGT_PD_OFF); + wr32(param->acc_cnt | priv->phymem, GNRC_RXIN_TGT_ACCM_CNT); + + param = &mdm->mdm_rxout; + wr32(param->stat | priv->phymem, GNRC_RXOUT_TGT_STAT); + wr32(param->pd | priv->phymem, GNRC_RXOUT_TGT_PD_OFF); + wr32(param->acc_cnt | priv->phymem, GNRC_RXOUT_TGT_ACCM_CNT); + dev_dbg(priv->dev, "aca mdm init done\n"); +} + +static void dc_aca_clk_on(struct dc_ep_priv *priv) +{ + dc_ep_clk_on(priv, PMU_ADMA); +} + +static void dc_aca_clk_off(struct dc_ep_priv *priv) +{ + dc_ep_clk_off(priv, PMU_ADMA); +} + +static void dc_aca_reset(struct dc_ep_priv *priv) +{ + dc_ep_reset_device(priv, RST_ACA_DMA | RST_ACA_HOSTIF); +} + +static void aca_mem_clear(struct dc_ep_priv *priv) +{ + struct aca_fw_dl_addr *fw_dl = to_fw_addr(priv); + + memset_io(priv->mem + fw_dl->fw_addr[0].fw_load_addr, + 0, ACA_ACC_FW_SIZE); + memset_io(priv->mem + ACA_SRAM_BASE, 0, ACA_SRAM_SIZE); +} + +int dc_aca_start(struct dc_ep_priv *priv, u32 func, int start) +{ + if (!func) + return -EINVAL; + + wr32_mask(0, func, GNRC_EN_TASK_BITMAP); + + /* Only do if requested by caller */ + if (start) { + wr32(0x1, GNRC_START_OP); /* Any write will trigger */ + rd32(GNRC_START_OP); + if (!aca_hif_param_init_check(priv)) + return -EIO; + } + return 0; +} + +static void aca_sw_reset(struct dc_ep_priv *priv) +{ + u32 val = SW_RST_GENRISC | SW_RST_HOSTIF_REG | SW_RST_RXIN + | SW_RST_RXOUT | SW_RST_TXIN | SW_RST_TXOUT; + + wr32(val, HT_SW_RST_ASSRT); + udelay(1); + wr32(val, HT_SW_RST_RELEASE); + wmb(); +} + +int dc_aca_stop(struct dc_ep_priv *priv, u32 *func, int reset) +{ + u32 val = *func; + u32 reg; + + if (!val) + return 0; + + *func = 0; + + /* Only do it if reset is required. Otherwise, pending is fine */ + if (reset) { + if (val & ACA_TXIN_EN) { + reg = rd32(TXIN_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_TXIN_EN; + return -EBUSY; + } + } + + if (val & ACA_TXOUT_EN) { + reg = rd32(TXOUT_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_TXOUT_EN; + return -EBUSY; + } + } + + + if (val & ACA_RXIN_EN) { + reg = rd32(RXIN_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_RXIN_EN; + return -EBUSY; + } + } + + if (val & ACA_RXOUT_EN) { + reg = rd32(RXOUT_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_RXOUT_EN; + return -EBUSY; + } + } + } + + wr32_mask(val, 0, GNRC_EN_TASK_BITMAP); + + if (reset) { + aca_dma_ch_off(priv); + aca_xbar_ia_reject_set(priv, ACA_ACC_IA04); + aca_xbar_ia_reject_set(priv, ACA_M_IA06); + aca_sw_reset(priv); + } + return 0; +} + +#ifdef CONFIG_SOC_TYPE_XWAY +static void aca_grx330_init(struct dc_ep_priv *priv) +{ + wr32(0x0044001E, TXIN_CFG1); + wr32(0x0040041F, TXIN_CFG2); + wr32(0x007FE020, TXIN_CFG3); + + wr32(0x0044001F, TXOUT_CFG1); + wr32(0x0040041F, TXOUT_CFG2); + wr32(0x007BE020, TXOUT_CFG3); + + wr32(0x0044001F, RXOUT_CFG1); + wr32(0x0040041F, RXOUT_CFG2); + wr32(0x007BE020, RXOUT_CFG3); + + wr32(0x0044001E, RXIN_CFG1); + wr32(0x0040041F, RXIN_CFG2); + wr32(0x007FE020, RXIN_CFG3); + + wr32(0x1, TXIN_DST_OWWBIT_CFG4); + wr32(0x1, TXOUT_DST_OWWBIT_CFG4); + wr32(0x1, RXOUT_SRC_OWNBIT_CFG3); + wr32(0x1, RXIN_SRC_OWNBIT_CFG3); + + wr32(0x0, GNRC_TXIN_BUF_PREFILL); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x4); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x8); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0xc); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x10); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x14); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x18); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x1c); +} +#endif + +int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *param, + struct aca_modem_param *mdm) +{ + int ret; + struct dc_aca *aca = to_aca(priv); + + dc_aca_clk_on(priv); + dc_aca_reset(priv); + + ret = aca_fetch_fw(priv); + if (ret) { + dev_err(priv->dev, + "could not fetch firmware files %d\n", ret); + dc_aca_clk_off(priv); + return ret; + } + + aca_mem_clear(priv); + aca_dma_init(priv); + aca_basic_init(priv); + aca_fw_download(priv); + aca_hif_param_init(priv); + aca_txin_init(priv, ¶m->aca_txin); + aca_txout_init(priv, ¶m->aca_txout); + aca_rxout_init(priv, ¶m->aca_rxout); + aca_rxin_init(priv, ¶m->aca_rxin); + aca_hif_param_init_done(priv); + aca_mdm_init(priv, mdm); +#ifdef CONFIG_SOC_TYPE_XWAY + aca_grx330_init(priv); +#endif + aca->initialized = true; + dev_info(priv->dev, "aca init done\n"); + return 0; +} + +static int aca_max_gpio(struct dc_ep_priv *priv) +{ + return fls(rd32(PADC_AVAIL)); +} + +void dc_aca_info_init(struct dc_ep_priv *priv) +{ + struct dc_aca *aca = to_aca(priv); + + aca->initialized = false; + spin_lock_init(&aca->clk_lock); + spin_lock_init(&aca->rcu_lock); + mutex_init(&aca->pin_lock); + aca->max_gpio = aca_max_gpio(priv); +} + +#define ACA_ENDIAN_ADDR(addr, endian) \ +{ \ + if (endian == ACA_BIG_ENDIAN) \ + return addr##_BE; \ + else \ + return addr; \ +} + +u32 aca_umt_msg_addr(struct dc_ep_priv *priv, u32 endian, u32 type) +{ + switch (type) { + case ACA_TXIN: + ACA_ENDIAN_ADDR(TXIN_HD_ACCUM_ADD, endian); + case ACA_RXIN: + ACA_ENDIAN_ADDR(RXIN_HD_ACCUM_ADD, endian); + case ACA_TXOUT: + ACA_ENDIAN_ADDR(TXOUT_HD_ACCUM_SUB, endian); + case ACA_RXOUT: + ACA_ENDIAN_ADDR(RXOUT_HD_ACCUM_SUB, endian); + default: + ACA_ENDIAN_ADDR(RXIN_HD_ACCUM_ADD, endian); + }; +} + +void dc_aca_event_addr_get(struct dc_ep_priv *priv, + struct aca_event_reg_addr *regs) +{ + regs->txin_acc_sub = TXIN_ACA_ACCUM_SUB; + regs->txout_acc_add = TXOUT_ACA_ACCUM_ADD; + regs->rxin_acc_sub = RXIN_ACA_ACCUM_SUB; + regs->rxout_acc_add = RXOUT_ACA_ACCUM_ADD; +} + +void dc_aca_txin_sub_ack(struct dc_ep_priv *priv, u32 val) +{ + wr32(val, TXIN_ACA_ACCUM_SUB); +} + +u32 dc_aca_txin_hd_cnt(struct dc_ep_priv *priv) +{ + return rd32(TXIN_ACA_HD_ACC_CNT); +} + diff --git a/package/kernel/lantiq/vrx518_ep/src/aca.h b/package/kernel/lantiq/vrx518_ep/src/aca.h new file mode 100644 index 00000000000..10f2ecb4c16 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/aca.h @@ -0,0 +1,481 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef ACA_H +#define ACA_H + +#define HOST_IF_BASE 0x50000 +#define ACA_CORE_BASE 0x50800 +#define GENRISC_IRAM_BASE 0x58000 +#define GENRISC_SPRAM_BASE 0x5C000 +#define GENRISC_BASE 0x5D000 +#define MAC_HT_EXT_BASE 0x5D400 +#define ACA_SRAM_BASE 0x100000 +#define ACA_SRAM_SIZE 0x2000 /* Project specific */ +#define ACA_HOSTIF_ADDR_SHIFT 2 + +#define ACA_HOSTIF_ADDR(addr) ((addr) >> ACA_HOSTIF_ADDR_SHIFT) + +#define ACA_HIF_LOC_POS 0x100060 +#define ACA_HIF_PARAM_ADDR 0x100064 +#define ACA_ACC_FW_SIZE 0x400 +#define ACA_LOOP_CNT 1000 + +/* TODO: change name after karthik explained */ +#define TXIN_DST_OWNBIT 0xC4 +#define TXOUT_DST_OWNBIT 0x1C4 +#define RXOUT_SRC_OWNBIT 0x3C4 +#define RXIN_DST_OWNBIT 0x2C4 + +/* Genrisc Internal Host Descriptor(Ping/Pong) decided by ACA fw header */ +/* ACA Core */ +#define ACA_CORE_REG(X) (ACA_CORE_BASE + (X)) +#define TXIN_CFG1 ACA_CORE_REG(0x0) +#define TXIN_CFG2 ACA_CORE_REG(0x4) +#define TXIN_CFG3 ACA_CORE_REG(0x8) +#define TXIN_DST_OWWBIT_CFG4 ACA_CORE_REG(TXIN_DST_OWNBIT) + +#define TXOUT_CFG1 ACA_CORE_REG(0x100) +#define TXOUT_CFG2 ACA_CORE_REG(0x104) +#define TXOUT_CFG3 ACA_CORE_REG(0x108) +#define TXOUT_DST_OWWBIT_CFG4 ACA_CORE_REG(TXOUT_DST_OWNBIT) + +#define RXOUT_CFG1 ACA_CORE_REG(0x300) +#define RXOUT_CFG2 ACA_CORE_REG(0x304) +#define RXOUT_CFG3 ACA_CORE_REG(0x308) +#define RXOUT_SRC_OWNBIT_CFG3 ACA_CORE_REG(RXOUT_SRC_OWNBIT) + +#define RXIN_CFG1 ACA_CORE_REG(0x200) +#define RXIN_CFG2 ACA_CORE_REG(0x204) +#define RXIN_CFG3 ACA_CORE_REG(0x208) +#define RXIN_SRC_OWNBIT_CFG3 ACA_CORE_REG(RXIN_DST_OWNBIT) + +/* Genrisc */ +#define GNRC_REG(X) (GENRISC_BASE + (X)) +#define GNRC_STOP_OP GNRC_REG(0x60) +#define GNRC_CONTINUE_OP GNRC_REG(0x64) +#define GNRC_START_OP GNRC_REG(0x90) + +/* HOST Interface Register */ +#define HOST_IF_REG(X) (HOST_IF_BASE + (X)) +#define HD_DESC_IN_DW 0x7u +#define HD_DESC_IN_DW_S 0 +#define PD_DESC_IN_DW 0x70u +#define PD_DESC_IN_DW_S 4 +#define BYTE_SWAP_EN BIT(28) + +#define TXIN_CONV_CFG HOST_IF_REG(0x14) +#define TXOUT_CONV_CFG HOST_IF_REG(0x18) +#define RXIN_CONV_CFG HOST_IF_REG(0x1C) +#define RXOUT_CONV_CFG HOST_IF_REG(0x20) + +#define TXIN_COUNTERS HOST_IF_REG(0x44) +#define TXOUT_COUNTERS HOST_IF_REG(0x48) +#define RXIN_COUNTERS HOST_IF_REG(0x4c) +#define RXOUT_COUNTERS HOST_IF_REG(0x50) + +#define TXOUT_RING_CFG HOST_IF_REG(0x98) +#define RXOUT_RING_CFG HOST_IF_REG(0x9C) + +#define ACA_PENDING_JOB 0x00000300 +#define ACA_PENDING_JOB_S 8 +#define ACA_AVAIL_BUF 0x00030000 +#define ACA_AVAIL_BUF_S 16 +#define ACA_PP_BUFS 2 + +#define HOST_TYPE HOST_IF_REG(0xA0) +#define TXOUT_COUNTERS_UPDATE HOST_IF_REG(0xAC) +#define RXOUT_COUNTERS_UPDATE HOST_IF_REG(0xB4) +#define RXIN_HD_ACCUM_ADD HOST_IF_REG(0xC8) /* UMT Message trigger */ +#define TXIN_HD_ACCUM_ADD HOST_IF_REG(0xCC) /* UMT Message trigger */ +#define RXOUT_HD_ACCUM_ADD HOST_IF_REG(0xD0) +#define TXOUT_HD_ACCUM_ADD HOST_IF_REG(0xD4) +#define RXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE0) /* PPE FW tigger */ +#define TXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE4) /* PPE FW tigger */ +#define RXOUT_HD_ACCUM_SUB HOST_IF_REG(0xF8) +#define TXOUT_HD_ACCUM_SUB HOST_IF_REG(0xFC) +#define RXIN_ACA_ACCUM_SUB HOST_IF_REG(0x100) +#define TXIN_ACA_ACCUM_SUB HOST_IF_REG(0x104) +#define TXIN_ACA_HD_ACC_CNT HOST_IF_REG(0x11C) +#define UMT_ORDER_CFG HOST_IF_REG(0x234) +#define RXIN_HD_ACCUM_ADD_BE HOST_IF_REG(0x250) +#define TXIN_HD_ACCUM_ADD_BE HOST_IF_REG(0x254) +#define RXOUT_HD_ACCUM_SUB_BE HOST_IF_REG(0x268) +#define TXOUT_HD_ACCUM_SUB_BE HOST_IF_REG(0x26c) + +/* MAC_HT_EXTENSION Register */ +#define MAC_HT_EXT_REG(X) (MAC_HT_EXT_BASE + (X)) + +#define HT_GCLK_ENABLE MAC_HT_EXT_REG(0) +#define HT_SW_RST_RELEASE MAC_HT_EXT_REG(0x4) +#define HT_SW_RST_ASSRT MAC_HT_EXT_REG(0x1C) +#define SW_RST_GENRISC BIT(14) +#define SW_RST_RXOUT BIT(26) +#define SW_RST_RXIN BIT(27) +#define SW_RST_TXOUT BIT(28) +#define SW_RST_TXIN BIT(29) +#define SW_RST_HOSTIF_REG BIT(30) +#define OCP_ARB_ACC_PAGE_REG MAC_HT_EXT_REG(0x1C4) +#define AHB_ARB_HP_REG MAC_HT_EXT_REG(0x1C8) + +/* Genrisc FW Configuration */ +#define GNRC_SPRAM_REG(X) (GENRISC_SPRAM_BASE + (X)) + +/* TX IN */ +#define GNRC_TXIN_TGT_STAT GNRC_SPRAM_REG(0x04) +#define GNRC_TXIN_TGT_PD_OFF GNRC_SPRAM_REG(0x08) +#define GNRC_TXIN_TGT_ACCM_CNT GNRC_SPRAM_REG(0x0C) + +/* TX OUT */ +#define GNRC_TXOUT_TGT_STAT GNRC_SPRAM_REG(0x10) +#define GNRC_TXOUT_TGT_PD_OFF GNRC_SPRAM_REG(0x14) +#define GNRC_TXOUT_TGT_ACCM_CNT GNRC_SPRAM_REG(0x18) + +/* RX IN */ +#define GNRC_RXIN_TGT_STAT GNRC_SPRAM_REG(0x1C) +#define GNRC_RXIN_TGT_PD_OFF GNRC_SPRAM_REG(0x20) +#define GNRC_RXIN_TGT_ACCM_CNT GNRC_SPRAM_REG(0x24) + +/* RX OUT XXX not consistent */ +#define GNRC_RXOUT_TGT_STAT GNRC_SPRAM_REG(0x28) +#define GNRC_RXOUT_TGT_PD_OFF GNRC_SPRAM_REG(0x2C) +#define GNRC_RXOUT_TGT_ACCM_CNT GNRC_SPRAM_REG(0x30) + +/* 4 Ring 8 UMT case SoC cumulative counter address configuration */ +#define GNRC_TXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x34) +#define GNRC_TXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x38) +#define GNRC_RXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x3C) +#define GNRC_RXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x40) + + +#define GNRC_SOURCE_TXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x54) +#define GNRC_SOURCE_TXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x58) +#define GNRC_SOURCE_RXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x5c) +#define GNRC_SOURCE_RXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x60) + +/* Txin index prefill */ +#define GNRC_TXIN_BUF_PREFILL GNRC_SPRAM_REG(0x44) +/* Task enable bitmap */ +#define GNRC_EN_TASK_BITMAP GNRC_SPRAM_REG(0x64) + +#define ACA_SRAM_REG(X) (ACA_SRAM_BASE + (X)) +#define ACA_TXOUT_PING_BUFFER_START ACA_SRAM_REG(0x1528) + + +/* XBAR SSX0 */ +#define ACA_SSX0_BASE 0x180000 +#define ACA_SSX0_IA_BASE(id) (ACA_SSX0_BASE + (((id) - 1) << 10)) +#define ACA_AGENT_CTRL(id) (ACA_SSX0_IA_BASE(id) + 0x20) +#define ACA_AGENT_STATUS(id) (ACA_SSX0_IA_BASE(id) + 0x28) + +#define XBAR_CTRL_CORE_RESET BIT(0) +#define XBAR_CTRL_REJECT BIT(4) + +#define XBAR_STAT_CORE_RESET BIT(0) +#define XBAR_STAT_REQ_ACTIVE BIT(4) +#define XBAR_STAT_RESP_WAITING BIT(5) +#define XBAR_STAT_BURST BIT(6) +#define XBAR_STAT_READEX BIT(7) + +enum { + ACA_ACC_IA04 = 4, + ACA_M_IA06 = 6, +}; + +/* Should be passed from ACA FW header */ +#define DESC_NUM_PER_CH 1 + +/* ACA DMA REG */ +#define ACA_DMA_BASE 0x60000 + +#define ACA_DMA_REG(X) (ACA_DMA_BASE + (X)) +#define ADMA_CLC ACA_DMA_REG(0x0) +#define ADMA_ID ACA_DMA_REG(0x8) +#define ADMA_CTRL ACA_DMA_REG(0x10) +#define ADMA_CPOLL ACA_DMA_REG(0x14) + +#define ADMA_ID_REV 0x1Fu +#define ADMA_ID_REV_S 0 +#define ADMA_ID_ID 0xFF00u +#define ADMA_ID_ID_S 8 +#define ADMA_ID_PRTNR 0xF0000u +#define ADMA_ID_PRTNR_S 16 +#define ADMA_ID_CHNR 0x7F00000u +#define ADMA_ID_CHNR_S 20 + +#define ADMA_CPOLL_EN BIT(31) + +#define ADMA_CPOLL_CNT 0xFFF0u +#define ADMA_CPOLL_CNT_S 4 +#define ADMA_DEFAULT_POLL 24 +#define ADMA_CS ACA_DMA_REG(0x18) +#define ADMA_CCTRL ACA_DMA_REG(0x1C) +#define ADMA_CDBA ACA_DMA_REG(0x20) +#define ADMA_CDLEN ACA_DMA_REG(0x24) +#define ADMA_CIS ACA_DMA_REG(0x28) +#define ADMA_CIE ACA_DMA_REG(0x2C) + +#define ADMA_CI_EOP BIT(1) +#define ADMA_CI_DUR BIT(2) +#define ADMA_CI_DESCPT BIT(3) +#define ADMA_CI_CHOFF BIT(4) +#define ADMA_CI_RDERR BIT(5) +#define ADMA_CI_ALL (ADMA_CI_EOP | ADMA_CI_DUR | ADMA_CI_DESCPT\ + | ADMA_CI_CHOFF | ADMA_CI_RDERR) + +#define ADMA_CDPTNRD ACA_DMA_REG(0x34) +#define ADMA_PS ACA_DMA_REG(0x40) +#define ADMA_PCTRL ACA_DMA_REG(0x44) + +/* DMA CCTRL BIT */ +#define CCTRL_RST 1 /* Channel Reset */ +#define CCTRL_ONOFF 0 /* Channel On/Off */ + +/* DMA CTRL BIT */ +#define CTRL_PKTARB 31 /* Packet Arbitration */ +#define CTRL_MDC 15 /* Meta data copy */ +#define CTRL_DDBR 14 /* Dynamic Burst */ +#define CTRL_DCNF 13 /* Descriptor Length CFG*/ +#define CTRL_ENBE 9 /* Byte Enable */ +#define CTRL_DRB 8 /* Descriptor read back */ +#define CTRL_DSRAM 1 /* Dedicated Descriptor Access port Enable */ +#define CTRL_RST 0 /* Global Reset */ + +/* DMA PORT BIT */ +#define PCTRL_FLUSH 16 +#define PCTRL_TXENDI 10 /* TX DIR Endianess */ +#define PCTRL_RXENDI 8 /* RX DIR Endianess */ +#define PCTRL_TXBL 4 /* TX burst 2/4/8 */ +#define PCTRL_RXBL 2 /* RX burst 2/4/8 */ +#define PCTRL_TXBL16 1 /* TX burst of 16 */ +#define PCTRL_RXBL16 0 /* RX burst of 16 */ + +/*DMA ID BIT */ +#define ID_CHNR 20 /* Channel Number */ + +/*DMA POLLING BIT */ +#define POLL_EN 31 /* Polling Enable */ +#define POLL_CNT 4 /* Polling Counter */ + +#define ACA_DMA_CHAN_MAX 12 + +enum aca_sec_id { + ACA_SEC_HIF = 0x1, + ACA_SEC_GNR = 0x2, + ACA_SEC_MAC_HT = 0x3, + ACA_SEC_MEM_TXIN = 0x4, + ACA_SEC_MEM_TXIN_PDRING = 0x5, + ACA_SEC_MEM_TXOUT = 0x6, + ACA_SEC_MEM_TXOUT_PDRING = 0x7, + ACA_SEC_MEM_RXOUT = 0x8, + ACA_SEC_MEM_RXOUT_PDRING = 0x9, + ACA_SEC_MEM_RXIN = 0xa, + ACA_SEC_MEM_RXIN_PDRING = 0xb, + ACA_SEC_DMA = 0xc, + ACA_SEC_FW_INIT = 0xd, + ACA_SEC_FW = 0x88, +}; + +enum aca_fw_id { + ACA_FW_TXIN = 1, + ACA_FW_TXOUT = 2, + ACA_FW_RXIN = 3, + ACA_FW_RXOUT = 4, + ACA_FW_GNRC = 5, + ACA_FW_MAX = 5, +}; + +enum aca_img_type { + ACA_VRX518_IMG, + ACA_VRX618_IMG, + ACA_FALCON_IMG, + ACA_PUMA_IMG, + ACA_IMG_MAX, +}; + +enum aca_soc_type { + ACA_SOC_XRX300 = 1, + ACA_SOC_XRX500 = 2, + ACA_SOC_PUMA = 4, + ACA_SOC_3RD_PARTY = 8, +}; + +#define ACA_SOC_MASK 0xf + +/* Common information element, len has different variants */ +struct aca_fw_ie { + __be32 id; + __be32 len; +} __packed; + +struct aca_fw_reg { + __be32 offset; + __be32 value; +} __packed; + +struct aca_sram_desc { + __be32 dnum; + __be32 dbase; +} __packed; + +struct aca_fw_dma { + __be32 cid; + __be32 base; +} __packed; + +/* ACA internal header part */ +struct aca_int_hdr { + __be32 id; + __be32 offset; + __be32 size; + __be32 load_addr; +} __packed; + +struct aca_fw_param { + __be32 st_sz; + __be32 init_addr; +} __packed; + +struct aca_mem_layout { + u32 txin_host_desc_base; + u32 txin_host_dnum; + u32 txout_host_desc_base; + u32 txout_host_dnum; + u32 rxin_host_desc_base; + u32 rxin_host_dnum; + u32 rxout_host_desc_base; + u32 rxout_host_dnum; +}; + +struct aca_pdmem_layout { + u32 txin_pd_desc_base; + u32 txin_pd_dnum; + u32 txout_pd_desc_base; + u32 txout_pd_dnum; + u32 rxin_pd_desc_base; + u32 rxin_pd_dnum; + u32 rxout_pd_desc_base; + u32 rxout_pd_dnum; +}; + +struct aca_fw_addr_tuple { + u32 fw_id; + u32 fw_load_addr; + size_t fw_size; + const char *fw_base; +}; + +struct aca_fw_dl_addr { + u32 fw_num; + struct aca_fw_addr_tuple fw_addr[ACA_FW_MAX]; +}; + +struct aca_fw_info { + const struct firmware *fw; + const void *fw_data; + size_t fw_len; + struct aca_mem_layout mem_layout; + struct aca_pdmem_layout pdmem_layout; + struct aca_fw_param fw_param; + struct aca_fw_dl_addr fw_dl; + u32 chan_num; + u32 adma_desc_base[ACA_DMA_CHAN_MAX]; +}; + +union fw_ver { +#ifdef CONFIG_CPU_BIG_ENDIAN + struct { + u32 build:4; + u32 branch:4; + u32 major:8; + u32 minor:16; + } __packed field; +#else + struct { + u32 minor:16; + u32 major:8; + u32 branch:4; + u32 build:4; + } __packed field; +#endif /* CONFIG_CPU_BIG_ENDIAN */ + u32 all; +} __packed; + +union img_soc_type { +#ifdef CONFIG_CPU_BIG_ENDIAN + struct { + u32 img_type:16; + u32 soc_type:16; + } __packed field; +#else + struct { + u32 soc_type:16; + u32 img_type:16; + } __packed field; +#endif /* CONFIG_CPU_BIG_ENDIAN */ + u32 all; +} __packed; + +/* Fixed header part */ +struct aca_fw_f_hdr { + __be32 ver; + __be32 type; + __be32 hdr_size; + __be32 fw_size; + __be32 num_section; +} __packed; + +struct aca_hif_param { + u32 soc_desc_base; + u32 soc_desc_num; + u32 pp_buf_base; + u32 pp_buf_num; + u32 pd_desc_base; + u32 pd_desc_num; + u32 pd_desc_threshold; +} __packed; + +struct aca_hif_params { + u32 task_mask; + struct aca_hif_param txin; + struct aca_hif_param txout; + struct aca_hif_param rxin; + struct aca_hif_param rxout; + u32 dbg_base; + u32 dbg_size; + u32 magic; +} __packed; + +#define ACA_MAGIC 0x25062016 + +struct dc_aca { + bool initialized; + spinlock_t clk_lock; + spinlock_t rcu_lock; + struct mutex pin_lock; + struct aca_fw_info fw_info; + struct aca_hif_params *hif_params; + u32 max_gpio; + u32 adma_chans; +}; +#endif /* ACA_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/ep.c b/package/kernel/lantiq/vrx518_ep/src/ep.c new file mode 100644 index 00000000000..40fc9d36299 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/ep.c @@ -0,0 +1,770 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ep.h" +#include "aca.h" +#include "misc.h" + +#define DC_EP_DBG + +#define MAJ 2 +#define MIN 1 +#define BUILD 0 +#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ + __stringify(BUILD) "-k" + +static bool pcie_switch_exist; +module_param(pcie_switch_exist, bool, 0644); +MODULE_PARM_DESC(pcie_switch_exist, "pcie switch existed or not"); + +static const char dc_ep_driver_name[] = "vrx518"; +static const char dc_ep_driver_version[] = DRV_VERSION; +static const char dc_ep_driver_string[] = + "Intel(R) SmartPHY DSL(VRX518) PCIe EP/ACA Driver"; +static const char dc_ep_copyright[] = + "Copyright (c) 2016 Intel Corporation."; + +static struct dc_ep_info g_dc_ep_info; +static DEFINE_SPINLOCK(dc_ep_lock); + +static inline void reset_assert_device(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_assert_device(dev->priv, bits); +} + +static inline void reset_deassert_device(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_deassert_device(dev->priv, bits); +} + +static inline void icu_disable_intr(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_icu_dis_intr(dev->priv, bits); +} + +static inline void icu_enable_intr(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_icu_en_intr(dev->priv, bits); +} + +static inline int reset_device(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_reset_device(dev->priv, bits); +} + +static inline int clk_on(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_on(dev->priv, bits); +} + +static inline int clk_off(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_off(dev->priv, bits); +} + +static inline int clk_set(struct dc_ep_dev *dev, u32 sysclk, u32 ppeclk) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_set(dev->priv, sysclk, ppeclk); +} + +static inline int clk_get(struct dc_ep_dev *dev, u32 *sysclk, u32 *ppeclk) +{ + if (WARN_ON(!dev || !sysclk || !ppeclk)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_get(dev->priv, sysclk, ppeclk); +} + +static inline int gpio_dir(struct dc_ep_dev *dev, u32 gpio, int dir) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_dir(dev->priv, gpio, dir); +} + +static inline int gpio_set(struct dc_ep_dev *dev, u32 gpio, int val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_set(dev->priv, gpio, val); +} + +static inline int gpio_get(struct dc_ep_dev *dev, u32 gpio, int *val) +{ + if (WARN_ON(!dev || !val)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_get(dev->priv, gpio, val); +} + +static inline int pinmux_set(struct dc_ep_dev *dev, u32 gpio, int func) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_pinmux_set(dev->priv, gpio, func); +} + +static inline int pinmux_get(struct dc_ep_dev *dev, u32 gpio, int *func) +{ + if (WARN_ON(!dev || !func)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_pinmux_get(dev->priv, gpio, func); +} + +static inline int gpio_pupd_set(struct dc_ep_dev *dev, u32 gpio, u32 val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_pupd_set(dev->priv, gpio, val); +} + +static inline int gpio_od_set(struct dc_ep_dev *dev, u32 gpio, int val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_od_set(dev->priv, gpio, val); +} + +static inline int gpio_src_set(struct dc_ep_dev *dev, u32 gpio, int val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_src_set(dev->priv, gpio, val); +} + +static inline int gpio_dcc_set(struct dc_ep_dev *dev, u32 gpio, u32 val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_dcc_set(dev->priv, gpio, val); +} + +static inline int aca_start(struct dc_ep_dev *dev, u32 func, int start) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_start(dev->priv, func, start); +} + +static inline int aca_stop(struct dc_ep_dev *dev, u32 *func, int reset) +{ + if (WARN_ON(!dev || !func)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_stop(dev->priv, func, reset); +} + +static inline int aca_init(struct dc_ep_dev *dev, struct aca_param *aca, + struct aca_modem_param *mdm) +{ + if (WARN_ON(!dev || !aca)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_init(dev->priv, aca, mdm); +} + +static inline void aca_event_addr_get(struct dc_ep_dev *dev, + struct aca_event_reg_addr *regs) +{ + if (WARN_ON(!dev || !regs)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_aca_event_addr_get(dev->priv, regs); +} + +static inline u32 umt_msg_addr(struct dc_ep_dev *dev, u32 endian, u32 type) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return aca_umt_msg_addr(dev->priv, endian, type); +} + +static inline void aca_txin_sub_ack(struct dc_ep_dev *dev, u32 val) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_aca_txin_sub_ack(dev->priv, val); +} + +static inline u32 aca_txin_hd_cnt(struct dc_ep_dev *dev) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_txin_hd_cnt(dev->priv); +} + +static const struct aca_hw_ops dc_ep_hw_ops = { + .reset_assert = reset_assert_device, + .reset_deassert = reset_deassert_device, + .reset_device = reset_device, + .icu_en = icu_enable_intr, + .icu_mask = icu_disable_intr, + .clk_on = clk_on, + .clk_off = clk_off, + .clk_set = clk_set, + .clk_get = clk_get, + .gpio_dir = gpio_dir, + .gpio_set = gpio_set, + .gpio_get = gpio_get, + .pinmux_set = pinmux_set, + .pinmux_get = pinmux_get, + .gpio_pupd_set = gpio_pupd_set, + .gpio_od_set = gpio_od_set, + .gpio_src_set = gpio_src_set, + .gpio_dcc_set = gpio_dcc_set, + .aca_start = aca_start, + .aca_stop = aca_stop, + .aca_init = aca_init, + .aca_event_addr_get = aca_event_addr_get, + .umt_msg_addr = umt_msg_addr, + .aca_txin_ack_sub = aca_txin_sub_ack, + .aca_txin_hd_cnt = aca_txin_hd_cnt, +}; + +int dc_ep_dev_num_get(int *dev_num) +{ + if ((g_dc_ep_info.dev_num <= 0) + || (g_dc_ep_info.dev_num > DC_EP_MAX_NUM)) + return -EIO; + + *dev_num = g_dc_ep_info.dev_num; + return 0; +} +EXPORT_SYMBOL_GPL(dc_ep_dev_num_get); + +int dc_ep_dev_info_req(int dev_idx, enum dc_ep_int module, + struct dc_ep_dev *dev) +{ + int i; + struct dc_ep_priv *priv; + + if ((dev_idx < 0) || (dev_idx >= DC_EP_MAX_NUM)) { + dev_err(dev->dev, "%s invalid device index %d\n", + __func__, dev_idx); + return -EIO; + } + + priv = &g_dc_ep_info.pcie_ep[dev_idx]; + if (atomic_read(&priv->refcnt) >= DC_EP_MAX_REFCNT) { + dev_err(dev->dev, + "%s mismatch request/release module usage\n", __func__); + return -EIO; + } + + switch (module) { + case DC_EP_INT_PPE: + dev->irq = priv->irq_base; + if (priv->msi_mode == DC_EP_8_MSI_MODE) { + dev->aca_tx_irq = priv->irq_base + 7; + dev->aca_rx_irq = priv->irq_base + 6; + } else if (priv->msi_mode == DC_EP_4_MSI_MODE) { + dev->aca_tx_irq = priv->irq_base + 2; + dev->aca_rx_irq = priv->irq_base + 3; + } else { + dev_err(dev->dev, "%s ACA should never occur\n", + __func__); + } + break; + case DC_EP_INT_MEI: + dev->irq = priv->irq_base + 1; + break; + default: + dev->irq = priv->irq_base; + break; + } + + dev->dev = priv->dev; + dev->membase = priv->mem; + dev->phy_membase = priv->phymem; + dev->peer_num = priv->peer_num; + for (i = 0; i < dev->peer_num; i++) { + dev->peer_membase[i] = priv->peer_mem[i]; + dev->peer_phy_membase[i] = priv->peer_phymem[i]; + } + dev->switch_attached = priv->switch_attached; + dev->priv = priv; + dev->hw_ops = &dc_ep_hw_ops; + atomic_inc(&priv->refcnt); + return 0; +} +EXPORT_SYMBOL_GPL(dc_ep_dev_info_req); + +int dc_ep_dev_info_release(int dev_idx) +{ + struct dc_ep_priv *priv; + + if ((dev_idx < 0) || (dev_idx >= DC_EP_MAX_NUM)) { + pr_err("%s invalid device index %d\n", + __func__, dev_idx); + return -EIO; + } + + priv = &g_dc_ep_info.pcie_ep[dev_idx]; + if (atomic_read(&priv->refcnt) <= 0) { + pr_err("%s mismatch request/release module usage\n", + __func__); + return -EIO; + } + + atomic_dec(&priv->refcnt); + return 0; +} +EXPORT_SYMBOL_GPL(dc_ep_dev_info_release); + +static int pci_msi_vec_set(struct pci_dev *dev, int nvec) +{ + int pos; + u16 msgctl; + + if (!is_power_of_2(nvec)) + return -EINVAL; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) + return -EINVAL; + + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + msgctl &= ~PCI_MSI_FLAGS_QSIZE; + msgctl |= ((ffs(nvec) - 1) << 4); + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + return 0; +} + +static int dc_ep_msi_enable(struct pci_dev *pdev, int nvec) +{ + int err; + struct dc_ep_priv *priv = pci_get_drvdata(pdev); + + /* NB, ICU initailize first */ + dc_ep_icu_init(priv); + + err = pci_msi_vec_set(pdev, nvec); + if (err) { + dev_err(&pdev->dev, "%s: Failed to set maximum MSI vector\n", + __func__); + return -EIO; + } + + err = pci_enable_msi_exact(pdev, nvec); + if (err) { + dev_err(&pdev->dev, + "%s: Failed to enable MSI interrupts error code: %d\n", + __func__, err); + return -EIO; + } + return 0; +} + +static void dc_ep_info_xchange(struct pci_dev *pdev, int card_num) +{ + /* More cards supported, exchange address information + * For example, suppose three cards dected. + * 0, <1, 2> + * 1, <0, 2> + * 2, <0, 1> + * For four cards detected + * 0, <1, 2, 3> + * 1, <0, 2, 3> + * 2, <0, 1, 3> + * 3, <0, 1, 2> + * and etc + */ + int i, j, k; + int peer_num; +#ifdef DC_EP_DBG + struct dc_ep_priv *priv; +#endif /* DC_EP_DBG */ + spin_lock(&dc_ep_lock); + if (card_num > 1) { + peer_num = card_num - 1; + for (i = 0; i < card_num; i++) { + struct dc_ep_priv *ep = &g_dc_ep_info.pcie_ep[i]; + j = 0; + k = 0; + ep->peer_num = peer_num; + do { + struct dc_ep_priv *partner; + + if (j == i) { + j++; + continue; + } + partner = &g_dc_ep_info.pcie_ep[j]; + ep->peer_mem[k] = partner->mem; + ep->peer_phymem[k] = partner->phymem; + ep->peer_memsize[k] = partner->memsize; + k++; + j++; + } while ((k < peer_num) && (j < card_num)); + } + } + spin_unlock(&dc_ep_lock); + +#ifdef DC_EP_DBG + dev_dbg(&pdev->dev, "Total cards found %d\n", card_num); + /* Dump detailed debug information */ + for (i = 0; i < card_num; i++) { + priv = &g_dc_ep_info.pcie_ep[i]; + dev_dbg(&pdev->dev, "card %d attached\n", priv->ep_idx); + dev_dbg(&pdev->dev, "irq base %d irq numbers %d\n", + priv->irq_base, priv->irq_num); + dev_dbg(&pdev->dev, + "its own phymem 0x%08x mem 0x%p size 0x%08x\n", + priv->phymem, priv->mem, priv->memsize); + if (card_num > 1) { + for (j = 0; j < priv->peer_num; j++) + dev_dbg(&pdev->dev, + "its peer phymem 0x%08x mem 0x%p size 0x%08x\n", + priv->peer_phymem[j], + priv->peer_mem[j], priv->peer_memsize[j]); + } + } +#endif /* DC_EP_DBG */ +} + +static int pci_msi_vec_num(struct pci_dev *dev) +{ + int ret; + u16 msgctl; + + if (!dev->msi_cap) + return -EINVAL; + + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl); + ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); + + return ret; +} + +static int dc_ep_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret; + int nvec; + bool switch_exist; + int current_ep; + unsigned long phymem; + void __iomem *mem; + size_t memsize; + int msi_mode; + static int cards_found; +#ifndef CONFIG_OF + struct pcie_ep_adapter *adapter; +#endif + struct dc_ep_priv *priv; + + ret = pci_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "can't enable PCI device %d\n", ret); + goto err_pci; + } + + /* Physical address */ + ret = pci_request_region(pdev, DC_EP_BAR_NUM, dc_ep_driver_name); + if (ret) { + dev_err(&pdev->dev, "PCI MMIO reservation error: %d\n", ret); + goto err_device; + } + + /* Target structures have a limit of 32 bit DMA pointers. + * DMA pointers can be wider than 32 bits by default on some systems. + */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "32-bit DMA not available: %d\n", ret); + goto err_region; + } + + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "cannot enable 32-bit consistent DMA\n"); + goto err_region; + } + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + /* NB, some delay may need due to BME reset */ + udelay(1); + + /* Arrange for access to Target SoC registers. */ + mem = pci_iomap(pdev, DC_EP_BAR_NUM, 0); + if (!mem) { + dev_err(&pdev->dev, "PCI iomap error\n"); + ret = -EIO; + goto err_master; + } + phymem = pci_resource_start(pdev, DC_EP_BAR_NUM); + memsize = pci_resource_len(pdev, DC_EP_BAR_NUM); + + nvec = pci_msi_vec_num(pdev); + /* Overwrite maximum vector number according to + * the specific requirement + */ + if ((DC_PCIE_SWITCH_ATTACH > 0) || pcie_switch_exist) + switch_exist = true; + else + switch_exist = false; + /* Always use 4 vector mode */ + nvec = DC_EP_DEFAULT_MSI_VECTOR; + msi_mode = DC_EP_4_MSI_MODE; + + current_ep = cards_found++; + priv = &g_dc_ep_info.pcie_ep[current_ep]; + memset(priv, 0, sizeof(*priv)); + pci_set_drvdata(pdev, priv); + + /* Collect basic info for further operations */ + spin_lock(&dc_ep_lock); + g_dc_ep_info.dev_num = cards_found; + atomic_set(&priv->refcnt, 0); + priv->pdev = pdev; + priv->device_id = pdev->device; + priv->dev = &pdev->dev; + priv->ep_idx = current_ep; + priv->mem = mem; + priv->phymem = phymem; + priv->memsize = memsize; + priv->irq_num = nvec; + priv->switch_attached = switch_exist; + priv->msi_mode = msi_mode; + spin_unlock(&dc_ep_lock); + + ret = dc_ep_msi_enable(pdev, nvec); + if (ret) + goto err_iomap; + + spin_lock(&dc_ep_lock); + priv->irq_base = pdev->irq; + spin_unlock(&dc_ep_lock); + +#ifndef CONFIG_OF + adapter = kmalloc(sizeof(struct pcie_ep_adapter), GFP_KERNEL); + if (adapter == NULL) + goto err_iomap; + pci_set_drvdata(pdev, adapter); + adapter->mei_dev = platform_device_register_data(&pdev->dev, "mei_cpe", + PLATFORM_DEVID_AUTO, + NULL, 0); + if (IS_ERR(adapter->mei_dev)) { + dev_err(&pdev->dev, "can not register mei device, err: %li, ignore this\n", + PTR_ERR(adapter->mei_dev)); + goto err_msi; + } +#endif + dc_ep_info_xchange(pdev, cards_found); + /* Disable output clock to save power */ + dc_ep_clkod_disable(priv); + dc_aca_info_init(priv); + return 0; +#ifndef CONFIG_OF +err_msi: + kfree(adapter); +#endif +err_iomap: + pci_iounmap(pdev, mem); +err_master: + pci_clear_master(pdev); +err_region: + pci_release_region(pdev, DC_EP_BAR_NUM); +err_device: + pci_disable_device(pdev); +err_pci: + return ret; +} + +static void dc_ep_remove(struct pci_dev *pdev) +{ + struct dc_ep_priv *priv = pci_get_drvdata(pdev); + +#ifndef CONFIG_OF + struct pcie_ep_adapter *adapter = + (struct pcie_ep_adapter *) pci_get_drvdata(pdev); + + platform_device_unregister(adapter->mei_dev); +#endif + if (priv == NULL) + return; + + if (atomic_read(&priv->refcnt) != 0) { + dev_err(&pdev->dev, "%s still being used, can't remove\n", + __func__); + return; + } + dc_aca_free_fw_file(priv); + dc_aca_shutdown(priv); + dc_ep_icu_disable(priv); + pci_iounmap(pdev, priv->mem); + pci_release_region(pdev, DC_EP_BAR_NUM); + pci_disable_msi(pdev); + wmb(); + pci_clear_master(pdev); + pci_disable_device(pdev); +} + +static const struct pci_device_id dc_ep_id_table[] = { + {0x8086, 0x09a9, PCI_ANY_ID, PCI_ANY_ID}, /* VRX518 */ + {0}, +}; + +MODULE_DEVICE_TABLE(pci, dc_ep_id_table); + +static struct pci_driver dc_ep_driver = { + .name = (char *)dc_ep_driver_name, + .id_table = dc_ep_id_table, + .probe = dc_ep_probe, + .remove = dc_ep_remove, + .shutdown = dc_ep_remove, + /* PM not supported */ + /* AER is controlled by RC */ +}; + +static int __init dc_ep_init(void) +{ + pr_info("%s - version %s\n", + dc_ep_driver_string, dc_ep_driver_version); + + pr_info("%s\n", dc_ep_copyright); + memset(&g_dc_ep_info, 0, sizeof(struct dc_ep_info)); + + if (pci_register_driver(&dc_ep_driver) < 0) { + pr_err("%s: No devices found, driver not installed.\n", + __func__); + return -ENODEV; + } + return 0; +} +module_init(dc_ep_init); + +static void __exit dc_ep_exit(void) +{ + pci_unregister_driver(&dc_ep_driver); + + pr_info("%s: %s driver unloaded\n", __func__, + dc_ep_driver_name); +} +module_exit(dc_ep_exit); + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION("Intel(R) SmartPHY PCIe EP/ACA Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/package/kernel/lantiq/vrx518_ep/src/ep.h b/package/kernel/lantiq/vrx518_ep/src/ep.h new file mode 100644 index 00000000000..2e31008ec83 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/ep.h @@ -0,0 +1,127 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef EP_H +#define EP_H + +#include + +#include "aca.h" + +#define DC_EP_MAX_NUM (DC_EP_MAX_PEER + 1) +#define DC_EP_BAR_NUM 0 + +/* Maximum 8, if PCIe switch attached, 4 is used. 8 is also default one */ +#ifdef CONFIG_VRX518_PCIE_SWITCH_BONDING +#define DC_PCIE_SWITCH_ATTACH 1 +#else +#define DC_PCIE_SWITCH_ATTACH 0 +#endif /* CONFIG_VRX518_PCIE_SWITCH_BONDING */ + +#define DC_EP_DEFAULT_MSI_VECTOR 4 + +#define DC_EP_MAX_REFCNT DC_EP_INT_MAX + +#define MS(_v, _f) (((_v) & (_f)) >> _f##_S) +#define SM(_v, _f) (((_v) << _f##_S) & (_f)) + +enum dc_ep_msi_mode { + DC_EP_8_MSI_MODE = 0, + DC_EP_4_MSI_MODE, + DC_EP_1_MSI_MODE, +}; + +/* Structure used to extract attached EP detailed information for + * PPE/DSL_MEI driver/Bonding + */ +struct dc_ep_priv { + struct pci_dev *pdev; + struct device *dev; + u32 ep_idx; /*!< EP logical index, the first found one will be 0 + regardless of RC physical index + */ + u32 irq_base; /*!< The first MSI interrupt number */ + u32 irq_num; /*!< How many MSI interrupt supported */ + enum dc_ep_msi_mode msi_mode; + u8 __iomem *mem; /*!< The EP inbound memory base address + derived from BAR0, SoC virtual address + for PPE/DSL_MEI driver + */ + u32 phymem; /*!< The EP inbound memory base address + derived from BAR0, physical address for + PPE FW + */ + size_t memsize; /*!< The EP inbound memory window size */ + u32 peer_num; /*!< Bonding peer number available */ + /*!< The bonding peer EP inbound memory base address derived from + * its BAR0, SoC virtual address for PPE/DSL_MEI driver + */ + + u8 __iomem *peer_mem[DC_EP_MAX_PEER]; + + /*!< The bonding peer EP inbound memory base address derived from + * its BAR0, physical address for PPE FW + */ + u32 peer_phymem[DC_EP_MAX_PEER]; + + /*!< The bonding peer inbound memory window size */ + size_t peer_memsize[DC_EP_MAX_PEER]; + atomic_t refcnt; /*!< The EP mapping driver referenced times + by other modules + */ + u16 device_id; /* Potential usage for different EP */ + bool switch_attached; + struct dc_aca aca; +}; + +struct dc_ep_info { + int dev_num; + int msi_mode; + struct dc_ep_priv pcie_ep[DC_EP_MAX_NUM]; +}; + +static inline struct dc_aca *to_aca(struct dc_ep_priv *priv) +{ + return &priv->aca; +} + +void dc_aca_shutdown(struct dc_ep_priv *priv); +void dc_aca_info_init(struct dc_ep_priv *priv); +int dc_aca_start(struct dc_ep_priv *priv, u32 func, int start); +int dc_aca_stop(struct dc_ep_priv *priv, u32 *func, int reset); +int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *aca, + struct aca_modem_param *mdm); +void dc_aca_event_addr_get(struct dc_ep_priv *priv, + struct aca_event_reg_addr *regs); +void dc_aca_txin_sub_ack(struct dc_ep_priv *priv, u32 val); +u32 aca_umt_msg_addr(struct dc_ep_priv *priv, u32 endian, u32 type); +u32 dc_aca_txin_hd_cnt(struct dc_ep_priv *priv); +void dc_aca_free_fw_file(struct dc_ep_priv *priv); + +/* Card specific private data structure */ +struct pcie_ep_adapter { + struct platform_device *mei_dev; /* the mei driver */ +}; + +#endif /* EP_H */ + diff --git a/package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h b/package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h new file mode 100644 index 00000000000..f1142332e19 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h @@ -0,0 +1,349 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef DC_EP_H +#define DC_EP_H + +#include +#include +#include + +/* @{ */ +/*! \def DC_EP_MAX_PEER + * \brief how many EP partners existed. In most cases, this number should be + * one for bonding application. For the future extension, it could be bigger + * value. For example, multiple bonding + */ +#define DC_EP_MAX_PEER 1 + +/* Reset related module bit definition */ +#define RST_GPIO BIT(2) +#define RST_DSL_IF BIT(3) +#define RST_DFE BIT(7) +#define RST_PPE BIT(8) +#define RST_CDMA BIT(9) +#define RST_SPI BIT(10) +#define RST_IMCU BIT(11) +#define RST_ACA_DMA BIT(14) +#define RST_AFE BIT(16) +#define RST_ACA_HOSTIF BIT(17) +#define RST_PCIE BIT(22) +#define RST_PPE_ATM_TC BIT(23) +#define RST_FPI_SLAVE BIT(25) +#define RST_GLOBAL BIT(30) + +/* PMU related module definition */ +#define PMU_ADMA BIT(0) +#define PMU_CDMA BIT(2) +#define PMU_SPI BIT(8) +#define PMU_DSL BIT(9) +#define PMU_PPE_QSB BIT(18) +#define PMU_PPE_SLL01 BIT(19) +#define PMU_PPE_TC BIT(21) +#define PMU_EMA BIT(22) +#define PMU_PPM2 BIT(23) +#define PMU_PPE_TOP BIT(29) + +/* IMER bit definition */ +#define PPE2HOST_INT0 BIT(0) +#define PPE2HOST_INT1 BIT(1) +#define DYING_GASP_INT BIT(3) +#define MEI_IRQ BIT(8) +#define ACA_XBAR_INT BIT(9) +#define MODEM_XBAR_INT BIT(12) +#define LED0_INT BIT(13) +#define LED1_INT BIT(14) +#define NMI_PLL BIT(15) +#define DMA_TX BIT(16) +#define DMA_RX BIT(17) +#define ACA_HOSTIF_TX BIT(20) +#define ACA_HOSTIF_RX BIT(21) +#define ACA_RXOUT_PD_RING_FULL BIT(22) +#define ACA_TXOUT_PD_RING_FULL BIT(23) + +/* + * Structure used to specify available pin mux functions for gpio pinx + * It will be used in pinmux_set() function + */ +enum gpio_padc_func { + MUX_FUNC_GPIO = 0, + MUX_FUNC_ALT1, + MUX_FUNC_ALT2, + MUX_FUNC_RES, +}; + +/* + * Structure used to specify interrupt source so that EP can assign unique + * interruot to it +*/ +enum dc_ep_int { + DC_EP_INT_PPE, /*!< PPE2HOST_INT 0/1 */ + DC_EP_INT_MEI, /*!< DSL MEI_IRQ */ + DC_EP_INT_MAX, +}; + +/* Clock setting for system clock */ +enum { + SYS_CLK_36MHZ = 0, + SYS_CLK_288MHZ, + SYS_CLK_MAX, +}; + +/* Clock setting for PPE clock */ +enum { + PPE_CLK_36MHZ = 0, + PPE_CLK_576MHZ, + PPE_CLK_494MHZ, + PPE_CLK_432MHZ, + PPE_CLK_288MHZ, + PPE_CLK_MAX, +}; + +/* GPIO direction IN/OUT */ +enum { + GPIO_DIR_IN = 0, + GPIO_DIR_OUT, + GPIO_DIR_MAX, +}; + +/* GPIO Pullup/Pulldown setting */ +enum { + GPIO_PUPD_DISABLE = 0, + GPIO_PULL_UP, + GPIO_PULL_DOWN, + GPIO_PUPD_BOTH, +}; + +/* GPIO slew rate setting */ +enum { + GPIO_SLEW_RATE_SLOW = 0, + GPIO_SLEW_RATE_FAST, +}; + +/* GPIO driver current setting */ +enum { + GPIO_DRV_CUR_2MA = 0, + GPIO_DRV_CUR_4MA, + GPIO_DRV_CUR_8MA, + GPIO_DRV_CUR_12MA, + GPIO_DRV_CUR_MAX, +}; + +enum { + ACA_LITTLE_ENDIAN = 0, + ACA_BIG_ENDIAN, + ACA_ENDIAN_MAX, +}; + +enum { + ACA_TXIN = 0, + ACA_TXOUT, + ACA_RXIN, + ACA_RXOUT, + ACA_MAX, +}; + +/* ACA four major direction functions for start/stop */ +#define ACA_TXIN_EN BIT(0) +#define ACA_TXOUT_EN BIT(1) +#define ACA_RXIN_EN BIT(2) +#define ACA_RXOUT_EN BIT(3) +#define ACA_ALL_EN 0xF + +struct dc_ep_dev; + +/* + * ACA SoC specific parameters. The caller needs to fill up all necessary info + * according to specific SoC and specific project + * For each function, different parameters are needed. + */ +struct aca_cfg_param { + u32 soc_desc_base; /*!< SoC CBM or DDR descriptor base address */ + u32 soc_desc_num; /*!< SoC and HostIF (same) descriptor number */ + u32 soc_cmlt_cnt_addr; /*! SoC cumulative counter address */ + u32 pp_buf_desc_num; /*!< ACA ping pong buffer descriptor number */ + u32 pd_desc_base; /*!< Packet Descriptor base address in modem */ + u32 pd_desc_num; /*!< Packet Descriptor number in modem */ + u32 hd_size_in_dw; /*!< Host(SoC) descriptor size in dwords */ + u32 pd_size_in_dw; /*!< Packet descriptor size in dwords */ + u32 byteswap; /*!< Byte swap enabled or not in ACA FW */ + u32 prefill_cnt; /*!< Prefill counter special required for some platform */ +}; + +struct aca_param { + struct aca_cfg_param aca_txin; + struct aca_cfg_param aca_txout; + struct aca_cfg_param aca_rxin; + struct aca_cfg_param aca_rxout; +}; + +/* ACA project/modem specific parameters. It is only valid for VRX518 */ +struct aca_proj_param { + u32 stat; /*!< Target state */ + u32 pd; /*!< Target packet descripor */ + u32 acc_cnt; /*!< Target accumulate counter */ +}; + +/* Project specific configuration */ +struct aca_modem_param { + struct aca_proj_param mdm_txout; + struct aca_proj_param mdm_rxin; + struct aca_proj_param mdm_rxout; +}; + +/* Event trigger register address */ +struct aca_event_reg_addr { + u32 txin_acc_sub; + u32 txout_acc_add; + u32 rxin_acc_sub; + u32 rxout_acc_add; +}; + +/* + * ACA common hardware low level APIs, presented as callbacks instead of + * separate APIs to support mulitple instances + */ +struct aca_hw_ops { + /* RCU Callbacks */ + void (*reset_assert)(struct dc_ep_dev *pdev, u32 rd); + void (*reset_deassert)(struct dc_ep_dev *pdev, u32 rd); + /* For hardware self-clear reset, most apply except PCIe */ + int (*reset_device)(struct dc_ep_dev *pdev, u32 hd); + + /* PMU Callbacks */ + int (*clk_on)(struct dc_ep_dev *pdev, u32 cd); + int (*clk_off)(struct dc_ep_dev *pdev, u32 cd); + + /* CGU Callbacks */ + int (*clk_set)(struct dc_ep_dev *pdev, u32 sysclk, u32 ppeclk); + int (*clk_get)(struct dc_ep_dev *pdev, u32 *sysclk, u32 *ppeclk); + + /* GPIO Callbacks */ + int (*gpio_dir)(struct dc_ep_dev *pdev, u32 gpio, int dir); + int (*gpio_set)(struct dc_ep_dev *pdev, u32 gpio, int val); + int (*gpio_get)(struct dc_ep_dev *pdev, u32 gpio, int *val); + + /* PinMux Callbacks */ + int (*pinmux_set)(struct dc_ep_dev *pdev, u32 gpio, int func); + int (*pinmux_get)(struct dc_ep_dev *pdev, u32 gpio, int *func); + int (*gpio_pupd_set)(struct dc_ep_dev *pdev, u32 gpio, u32 val); + int (*gpio_od_set)(struct dc_ep_dev *pdev, u32 gpio, int val); + int (*gpio_src_set)(struct dc_ep_dev *pdev, u32 gpio, int val); + int (*gpio_dcc_set)(struct dc_ep_dev *pdev, u32 gpio, u32 val); + + /* ICU Callbacks */ + void (*icu_en)(struct dc_ep_dev *pdev, u32 bit); + void (*icu_mask)(struct dc_ep_dev *pdev, u32 bit); + + /* ACA related stuff */ + int (*aca_start)(struct dc_ep_dev *pdev, u32 func, int start); + int (*aca_stop)(struct dc_ep_dev *pdev, u32 *func, int reset); + /* If there is no project specific parameters, input NULL */ + int (*aca_init)(struct dc_ep_dev *pdev, struct aca_param *aca, + struct aca_modem_param *mdm); + void (*aca_event_addr_get)(struct dc_ep_dev *pdev, + struct aca_event_reg_addr *regs); + /* UMT address needed for SoC filled in to trigger UMT msg */ + u32 (*umt_msg_addr)(struct dc_ep_dev *pdev, u32 endian, u32 type); + /* TXIN accum sub to ack PPE already processed */ + void (*aca_txin_ack_sub)(struct dc_ep_dev *pdev, u32 val); + u32 (*aca_txin_hd_cnt)(struct dc_ep_dev *pdev); +}; + +/* + * Structure used to extract attached EP detailed information + * for PPE/DSL_MEI driver/Bonding + */ +struct dc_ep_dev { + struct device *dev; + u32 irq; /*!< MSI interrupt number for this device */ + u32 aca_tx_irq; /*!< ACA Non-empty TX irq number for PPE driver */ + u32 aca_rx_irq; /*!< ACA Non-empty RX irq number for PPE driver */ + /*!< The EP inbound memory base address derived from BAR0, SoC + virtual address for PPE/DSL_MEI driver + */ + bool switch_attached; /*!< EP attach switch */ + u8 __iomem *membase; /*!< virtual memory base address to access EP */ + u32 phy_membase; /*!< The EP inbound memory base address derived + from BAR0, physical address for PPE FW + */ + u32 peer_num; /*!< Bonding peer number available */ + /*!< The bonding peer EP inbound memory base address derived from + its BAR0, SoC virtual address for PPE/DSL_MEI driver + */ + u8 __iomem *peer_membase[DC_EP_MAX_PEER]; + /*!< The bonding peer EP inbound memory base address derived from + its BAR0, physical address for PPE FW + */ + u32 peer_phy_membase[DC_EP_MAX_PEER]; + const struct aca_hw_ops *hw_ops; + void *priv; /* Pointer to driver proprietary data for internal use */ +}; + +/* + * This function returns the total number of EPs attached. Normally, + * the number should be one or two . Extended case is also considered + + * \param[in/out] dev_num Pointer to detected EP numbers in total. + * \return -EIO Invalid total EP number which means this + * module is not initialized properly + * \return 0 Successfully return the detected EP numbers + */ +int dc_ep_dev_num_get(int *dev_num); + +/* + * This function returns detailed EP device information for PPE/DSL/Bonding + * partner by its logical index obtained + * by \ref dc_ep_dev_num_get and its interrupt module number + * \ref dc_ep_int + + * \param[in] dev_idx Logical device index referred to the related + * device + * \param[in] module EP interrupt module user + * \param[in/out] dev Pointer to returned detail device structure + * \ref dc_ep_dev + * \return -EIO Invalid logical device index or too many modules + * referred to this module + * \return 0 Successfully return required device information + + * \remarks This function normally will be called to trace the detailed device + * information after calling \ref dc_ep_dev_num_get + */ +int dc_ep_dev_info_req(int dev_idx, enum dc_ep_int module, + struct dc_ep_dev *dev); + +/* + * This function releases the usage of this module by PPE/DSL + + * \param[in] dev_idx Logical device index referred to the related device + * \return -EIO Invalid logical device index or release too many + * times to refer to this module + * \return 0 Successfully release the usage of this module + + * \remarks This function should be called once their reference is over. + * The reference usage must matches \ref dc_ep_dev_info_req + */ +int dc_ep_dev_info_release(int dev_idx); + +#endif /* DC_EP_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/misc.c b/package/kernel/lantiq/vrx518_ep/src/misc.c new file mode 100644 index 00000000000..9140fe79e4d --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/misc.c @@ -0,0 +1,325 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#include +#include + +#include "regs.h" +#include "ep.h" +#include "misc.h" + +#define padc_getbit(p, r) (!!(rd32(r) & (1 << p))) +#define padc_setbit(p, r) wr32_mask(0, BIT(p), r) +#define padc_clearbit(p, r) wr32_mask(BIT(p), 0, r) + +void dc_ep_clkod_disable(struct dc_ep_priv *priv) +{ + wr32_mask(0, IF_CLKOD_ALL, IF_CLK); +} + +void dc_ep_icu_init(struct dc_ep_priv *priv) +{ + /* Enable all interrupts in ICU level */ + wr32(ICU_DMA_TX_ALL, ICU_DMA_TX_IMER); + wr32(ICU_DMA_RX_ALL, ICU_DMA_RX_IMER); + wr32(ICU_TOP_ALL, ICU_IMER); + + if (priv->msi_mode == DC_EP_4_MSI_MODE) + wr32(PCI_MSI_4_MODE, RCU_MSI); + else + wr32(PCI_MSI_8_MODE, RCU_MSI); + + /* PCIe app has to enable all MSI interrupts regardless of MSI mode */ + wr32(PCIE_MSI_EN_ALL, PCIE_APPL_MSI_EN); +} + +void dc_ep_icu_disable(struct dc_ep_priv *priv) +{ + /* Disable all PCIe related interrupts */ + wr32(0, PCIE_APPL_MSI_EN); + + wr32(PCI_MSI_8_MODE, RCU_MSI); + + /* Disable all interrupts in ICU level */ + wr32(0, ICU_DMA_TX_IMER); + wr32(0, ICU_DMA_RX_IMER); + wr32(0, ICU_IMER); +} + +void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits) +{ + wr32_mask(~bits, 0, ICU_IMER); +} + +void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits) +{ + wr32_mask(0, bits, ICU_IMER); +} + +void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits) +{ + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->rcu_lock); + wr32_mask(0, bits, RCU_REQ); + spin_unlock(&aca->rcu_lock); +} + +void dc_ep_deassert_device(struct dc_ep_priv *priv, u32 bits) +{ + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->rcu_lock); + wr32_mask(bits, 0, RCU_REQ); + spin_unlock(&aca->rcu_lock); +} + +int dc_ep_reset_device(struct dc_ep_priv *priv, u32 bits) +{ + int retry = EP_TIMEOUT; + + wr32(bits, RCU_REQ); + do { } while (retry-- && (!(rd32(RCU_STAT) & bits))); + + if (retry == 0) { + dev_err(priv->dev, "%s failed to reset\n", __func__); + return -ETIME; + } + return 0; +} + +int dc_ep_clk_on(struct dc_ep_priv *priv, u32 bits) +{ + int retry = EP_TIMEOUT; + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->clk_lock); + wr32_mask(bits, 0, PMU_PWDCR); + spin_unlock(&aca->clk_lock); + + do { } while (--retry && (rd32(PMU_SR) & bits)); + + if (!retry) { + dev_err(priv->dev, "%s failed\n", __func__); + return -ETIME; + } + return 0; +} + +int dc_ep_clk_off(struct dc_ep_priv *priv, u32 bits) +{ + int retry = EP_TIMEOUT; + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->clk_lock); + wr32_mask(0, bits, PMU_PWDCR); + spin_unlock(&aca->clk_lock); + + do {} while (--retry + && (!(rd32(PMU_SR) & bits))); + if (!retry) { + dev_err(priv->dev, "%s failed\n", __func__); + return -ETIME; + } + return 0; +} + +int dc_ep_clk_set(struct dc_ep_priv *priv, u32 sysclk, u32 ppeclk) +{ + struct dc_aca *aca = to_aca(priv); + + if (sysclk > SYS_CLK_MAX || ppeclk > PPE_CLK_MAX) + return -EINVAL; + + spin_lock(&aca->clk_lock); + wr32_mask(PPE_CLK | SYS_CLK, + SM(sysclk, SYS_CLK) | SM(ppeclk, PPE_CLK), PLL_OMCFG); + spin_unlock(&aca->clk_lock); + return 0; +} + +int dc_ep_clk_get(struct dc_ep_priv *priv, u32 *sysclk, u32 *ppeclk) +{ + u32 val; + + val = rd32(PLL_OMCFG); + *sysclk = MS(val, SYS_CLK); + *ppeclk = MS(val, PPE_CLK); + return 0; +} + +int dc_ep_gpio_dir(struct dc_ep_priv *priv, u32 gpio, int dir) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + if ((dir != GPIO_DIR_IN) && (dir != GPIO_DIR_OUT)) + return -EINVAL; + + if (dir == GPIO_DIR_IN) + wr32(BIT(gpio), GPIO_DIRCLR); + else + wr32(BIT(gpio), GPIO_DIRSET); + return 0; +} + +int dc_ep_gpio_set(struct dc_ep_priv *priv, u32 gpio, int val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + dc_ep_gpio_dir(priv, gpio, GPIO_DIR_OUT); + + if (val) + wr32(BIT(gpio), GPIO_OUTSET); + else + wr32(BIT(gpio), GPIO_OUTCLR); + return 0; +} + +int dc_ep_gpio_get(struct dc_ep_priv *priv, u32 gpio, int *val) +{ + u32 dir; + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + dir = rd32(GPIO_DIR); + if ((dir >> gpio) & 0x1) + *val = (rd32(GPIO_OUT) >> gpio) & 0x1; + else + *val = (rd32(GPIO_IN) >> gpio) & 0x1; + return 0; +} + +int dc_ep_pinmux_set(struct dc_ep_priv *priv, u32 gpio, int func) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + if (func >= MUX_FUNC_RES) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + wr32_mask(PADC_MUX_M, func, PADC_MUX(gpio)); + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_pinmux_get(struct dc_ep_priv *priv, u32 gpio, int *func) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + *func = rd32(PADC_MUX(gpio)); + return 0; +} + +int dc_ep_gpio_pupd_set(struct dc_ep_priv *priv, u32 gpio, u32 val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + /* Not support for both enabled */ + if (val >= GPIO_PUPD_BOTH) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + switch (val) { + case GPIO_PUPD_DISABLE: + padc_clearbit(gpio, PADC_PUEN); + padc_clearbit(gpio, PADC_PDEN); + break; + case GPIO_PULL_UP: + padc_setbit(gpio, PADC_PUEN); + padc_clearbit(gpio, PADC_PDEN); + break; + case GPIO_PULL_DOWN: + padc_setbit(gpio, PADC_PDEN); + padc_clearbit(gpio, PADC_PUEN); + break; + default: + break; + } + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_gpio_od_set(struct dc_ep_priv *priv, u32 gpio, int val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + if (!!val) + padc_setbit(gpio, PADC_OD); + else + padc_clearbit(gpio, PADC_OD); + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_gpio_src_set(struct dc_ep_priv *priv, u32 gpio, int val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + if (!!val) + padc_setbit(gpio, PADC_SRC); + else + padc_clearbit(gpio, PADC_SRC); + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_gpio_dcc_set(struct dc_ep_priv *priv, u32 gpio, u32 val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + if (val >= GPIO_DRV_CUR_MAX) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + wr32_mask((0x3 << (gpio * 2)), (val << (gpio * 2)), PADC_DCC); + mutex_unlock(&aca->pin_lock); + return 0; +} diff --git a/package/kernel/lantiq/vrx518_ep/src/misc.h b/package/kernel/lantiq/vrx518_ep/src/misc.h new file mode 100644 index 00000000000..d92ea83e2fc --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/misc.h @@ -0,0 +1,51 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef MISC_H +#define MISC_H + +#define EP_TIMEOUT 10000 + +void dc_ep_clkod_disable(struct dc_ep_priv *priv); +void dc_ep_icu_init(struct dc_ep_priv *priv); +void dc_ep_icu_disable(struct dc_ep_priv *priv); +void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits); +void dc_ep_deassert_device(struct dc_ep_priv *priv, u32 bits); +int dc_ep_reset_device(struct dc_ep_priv *priv, u32 bits); +int dc_ep_clk_on(struct dc_ep_priv *priv, u32 bits); +int dc_ep_clk_off(struct dc_ep_priv *priv, u32 bits); +int dc_ep_clk_set(struct dc_ep_priv *priv, u32 sysclk, u32 ppeclk); +int dc_ep_clk_get(struct dc_ep_priv *priv, u32 *sysclk, u32 *ppeclk); +int dc_ep_gpio_dir(struct dc_ep_priv *priv, u32 gpio, int dir); +int dc_ep_gpio_set(struct dc_ep_priv *priv, u32 gpio, int val); +int dc_ep_gpio_get(struct dc_ep_priv *priv, u32 gpio, int *val); +int dc_ep_pinmux_set(struct dc_ep_priv *priv, u32 gpio, int func); +int dc_ep_pinmux_get(struct dc_ep_priv *priv, u32 gpio, int *func); +int dc_ep_gpio_pupd_set(struct dc_ep_priv *priv, u32 gpio, u32 val); +int dc_ep_gpio_od_set(struct dc_ep_priv *priv, u32 gpio, int val); +int dc_ep_gpio_src_set(struct dc_ep_priv *priv, u32 gpio, int val); +int dc_ep_gpio_dcc_set(struct dc_ep_priv *priv, u32 gpio, u32 val); +void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits); +void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits); + +#endif /* MISC_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/regs.h b/package/kernel/lantiq/vrx518_ep/src/regs.h new file mode 100644 index 00000000000..9236453a4f4 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/regs.h @@ -0,0 +1,138 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef REGS_H +#define REGS_H + +#include + +/* APPL defined */ +#define PCIE_APPL_BASE 0x00048000 +#define PCIE_APPL_REG(X) (PCIE_APPL_BASE + (X)) + +#define PCIE_APPL_PHY_CFG1 PCIE_APPL_REG(0x3C) +#define PCIE_APPL_PHY_CFG2 PCIE_APPL_REG(0x40) +#define PCIE_APPL_PHY_CFG3 PCIE_APPL_REG(0x58) +#define PCIE_APPL_PHY_CFG4 PCIE_APPL_REG(0x28) +#define PCIE_APPL_INTR_VEC PCIE_APPL_REG(0x48) +#define PCIE_APPL_MSI_EN PCIE_APPL_REG(0x4C) + +#define PCIE_MSI_EN_ALL 0xFF + +/* RCU defined */ +#define RCU_BASE 0x00008000 +#define RCU_REG(X) (RCU_BASE + (X)) +#define RCU_STAT RCU_REG(0x00) +#define RCU_REQ RCU_REG(0x10) + +#define RCU_MSI RCU_REG(0x80) +#define PCI_MSI_4_MODE 1 +#define PCI_MSI_8_MODE 0 + +/* CGU */ +#define CGU_BASE 0x00000000 +#define CGU_REG(X) (CGU_BASE + (X)) +#define PMU_PWDCR CGU_REG(0x011C) +#define PMU_SR CGU_REG(0x0120) +#define PMU_ALL 0x20ec0305 + +#define PLL_OMCFG CGU_REG(0x0064) + +#define SYS_CLK 0x3 +#define SYS_CLK_S 0 +#define PPE_CLK 0x700 +#define PPE_CLK_S 8 + +#define IF_CLK CGU_REG(0x0024) + +#define CLK_PD BIT(10) +#define CLK_OD BIT(11) +#define PCIE_CLKOD (BIT(12) | BIT(13)) +#define AFE_CLKOD BIT(14) + +#define IF_CLKOD_ALL (CLK_PD | CLK_OD | PCIE_CLKOD | AFE_CLKOD) + +/* GPIO */ +#define GPIO_BASE 0x00020000 +#define GPIO_REG(X) (GPIO_BASE + (X)) +#define GPIO_OUT GPIO_REG(0x00) +#define GPIO_IN GPIO_REG(0x04) +#define GPIO_DIR GPIO_REG(0x08) +#define GPIO_OUTSET GPIO_REG(0x40) +#define GPIO_OUTCLR GPIO_REG(0x44) +#define GPIO_DIRSET GPIO_REG(0x48) +#define GPIO_DIRCLR GPIO_REG(0x4c) + +/* PADC */ +#define PADC_BASE 0x00024000 +#define PADC_REG(X) (PADC_BASE + (X)) +#define PADC_MUX(pin) PADC_REG(((pin) << 2)) +#define PADC_PUEN PADC_REG(0x80) +#define PADC_PDEN PADC_REG(0x84) +#define PADC_SRC PADC_REG(0x88) +#define PADC_DCC PADC_REG(0x8c) +#define PADC_OD PADC_REG(0x94) +#define PADC_AVAIL PADC_REG(0x98) +#define PADC_MUX_M 0x7 + +/* ICU defined */ +#define ICU_BASE 0x00010000 +#define ICU_REG(X) (ICU_BASE + (X)) +#define ICU_IMSR ICU_REG(0x40) +#define ICU_IMER ICU_REG(0x44) +#define ICU_IMOSR ICU_REG(0x48) +#define ICU_DMA_TX_STATUS ICU_REG(0x50) +#define ICU_DMA_RX_STATUS ICU_REG(0x54) +#define ICU_DMA_TX_IMER ICU_REG(0x58) +#define ICU_DMA_RX_IMER ICU_REG(0x5C) +#define ICU_DMA_TX_IMOSR ICU_REG(0x60) +#define ICU_DMA_RX_IMOSR ICU_REG(0x64) + +#define PPE2HOST_INT0 BIT(0) +#define PPE2HOST_INT1 BIT(1) +#define DYING_GASP_INT BIT(3) +#define MEI_IRQ BIT(8) +#define ACA_XBAR_INT BIT(9) +#define MODEM_XBAR_INT BIT(12) +#define LED0_INT BIT(13) +#define LED1_INT BIT(14) +#define NMI_PLL BIT(15) +#define DMA_TX BIT(16) +#define DMA_RX BIT(17) +#define ACA_HOSTIF_TX BIT(20) +#define ACA_HOSTIF_RX BIT(21) +#define ACA_RXOUT_PD_RING_FULL BIT(22) +#define ACA_TXOUT_PD_RING_FULL BIT(23) + +#define ICU_TOP_ALL 0x0003f30B /* Except ACA related */ +#define ICU_DMA_TX_ALL 0x003f03FF +#define ICU_DMA_RX_ALL 0x003F03FF + +#define wr32(value, reg) (writel(value, (priv->mem + (reg)))) +#define rd32(reg) (readl(priv->mem + (reg))) +#define wrfl() ((void)rd32(RCU_STAT)) + +#define wr32_mask(clr, set, reg) \ + wr32(((rd32(reg) & ~(clr)) | (set)), (reg)) + +#endif /* REGS_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/test/Makefile b/package/kernel/lantiq/vrx518_ep/src/test/Makefile new file mode 100644 index 00000000000..d9e5d43e4aa --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/test/Makefile @@ -0,0 +1,2 @@ + +obj-$(CONFIG_TEST) += ep_test.o \ No newline at end of file diff --git a/package/kernel/lantiq/vrx518_ep/src/test/ep_test.c b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.c new file mode 100644 index 00000000000..ab6139b73ee --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.c @@ -0,0 +1,924 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux Test driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ep_test.h" + +#define DRV_VERSION "1.0.0" +static const char ep_test_driver_version[] = DRV_VERSION; +static struct dc_ep_dev pcie_dev[DC_EP_MAX_PEER + 1]; +static int ppe_irq_num; + +#define ep_wr32(value, reg) (writel(value, dev->membase + reg)) +#define ep_rd32(reg) (readl(dev->membase + reg)) + +#define ep_wr32_mask(clr, set, reg) \ + ep_wr32(((ep_rd32(reg) & ~(clr)) | (set)), (reg)) + +struct aca_hd_desc { + void *base; + dma_addr_t phy_base; + size_t size;/* in bytes */ +}; + +struct aca_hd_desc_cfg { + struct aca_hd_desc txin; + struct aca_hd_desc txout; + struct aca_hd_desc rxout; +}; + +static struct aca_hd_desc_cfg aca_soc_hd_desc[DC_EP_MAX_PEER + 1]; + +static void ep_mem_write(u8 __iomem *dst, const void *src, size_t len) +{ + int i; + const u32 *src_addr = src; + + if (len % 4) + pr_info("Warning!!: Copy len is not multiple of 4\n"); + + len = len >> 2; + + for (i = 0; i < len; i++) + writel(src_addr[i], (dst + (i << 2))); +} + +static irqreturn_t dc_ep_ppe_intr(int irq, void *dev_id) +{ + struct dc_ep_dev *dev = dev_id; + + ppe_irq_num++; + if (ep_rd32(MBOX_IGU0_ISR) == 0) { + pr_err("Fatal error, dummy interrupt\n"); + return IRQ_NONE; + } + + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_ISRC); + ep_rd32(MBOX_IGU0_ISR); + return IRQ_HANDLED; +} + +static void dc_ep_ppe_mbox_reg_dump(struct dc_ep_dev *dev) +{ + pr_info("MBOX_IGU0_ISRS addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_ISRS, + ep_rd32(MBOX_IGU0_ISRS)); + pr_info("MBOX_IGU0_ISRC addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_ISRC, + ep_rd32(MBOX_IGU0_ISRC)); + pr_info("MBOX_IGU0_ISR addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_ISR, + ep_rd32(MBOX_IGU0_ISR)); + pr_info("MBOX_IGU0_IER addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_IER, + ep_rd32(MBOX_IGU0_IER)); +} + +#define PPE_INT_TIMEOUT 10 +static int dc_ep_ppe_mbox_int_stress_test(struct dc_ep_dev *dev) +{ + int i; + int j; + int ret; + + /* Clear it first */ + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_ISRC); + + ret = request_irq(dev->irq, dc_ep_ppe_intr, 0, "PPE_MSI", dev); + if (ret) { + pr_err("%s request irq %d failed\n", __func__, dev->irq); + return -1; + } + pr_info("PPE test\n"); + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_IER); + ppe_irq_num = 0; + /* Purposely trigger interrupt */ + for (i = 0; i < PPE_MBOX_IRQ_TEST_NUM; i++) { + j = 0; + while ((ep_rd32(MBOX_IGU0_ISR) & PPE_MBOX_TEST_BIT)) { + j++; + if (j > PPE_INT_TIMEOUT) + break; + } + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_ISRS); + /* Write flush */ + ep_rd32(MBOX_IGU0_ISR); + } + mdelay(10); + pr_info("irq triggered %d expected %d\n", ppe_irq_num, + PPE_MBOX_IRQ_TEST_NUM); + dc_ep_ppe_mbox_reg_dump(dev); + ppe_irq_num = 0; + return 0; +} + +static void umt_txin_send(struct dc_ep_dev *dev, + u8 __iomem *soc_dbase, int num) +{ + int i; + struct aca_dma_desc desc; + + memset(&desc, 0, sizeof(desc)); + desc.own = 0; + desc.sop = 1; + desc.eop = 1; + desc.dic = 1; + desc.pdu_type = 1; + desc.data_len = 127; + desc.data_pointer = 0x26000000; + desc.dw1 = 0x700; + desc.dw0 = 0x0000007f; + + for (i = 0; i < num; i++) { + desc.data_pointer += roundup(desc.data_len, 4); + ep_mem_write(soc_dbase + i * sizeof(desc), + (void *)&desc, sizeof(desc)); + } + + ep_wr32(num, TXIN_HD_ACCUM_ADD); +} + +static void ppe_txout_send(struct dc_ep_dev *dev, + u8 __iomem *ppe_sb_base, int num) +{ + int i; + struct aca_dma_desc_2dw desc; + + memset(&desc, 0, sizeof(desc)); + desc.status.field.own = 1; + desc.status.field.sop = 1; + desc.status.field.eop = 1; + desc.status.field.data_len = 127; + desc.data_pointer = 0x26100000; + + for (i = 0; i < num; i++) { + desc.data_pointer += roundup(desc.status.field.data_len, 4); + ep_mem_write(ppe_sb_base + i * sizeof(desc), + (void *)&desc, sizeof(desc)); + } + + ep_wr32(num, TXOUT_ACA_ACCUM_ADD); +} + +static void ppe_rxout_send(struct dc_ep_dev *dev, + u8 __iomem *ppe_sb_base, int num) +{ + int i; + struct aca_dma_desc_2dw desc; + + memset(&desc, 0, sizeof(desc)); + desc.status.field.own = 0; + desc.status.field.sop = 1; + desc.status.field.eop = 1; + desc.status.field.meta_data0 = 0x3; + desc.status.field.meta_data1 = 0x7f; + desc.status.field.data_len = 127; + desc.data_pointer = 0x26200000; + + for (i = 0; i < num; i++) { + desc.data_pointer += roundup(desc.status.field.data_len, 4); + ep_mem_write(ppe_sb_base + i * sizeof(desc), + (void *)&desc, sizeof(desc)); + } + + ep_wr32(num, RXOUT_ACA_ACCUM_ADD); +} + +static void dc_aca_test_init(struct dc_ep_dev *dev, void *soc_base) +{ + umt_txin_send(dev, (u8 __iomem *)soc_base, 8); + ppe_txout_send(dev, (TXOUT_PD_DBASE + dev->membase), 8); + ppe_rxout_send(dev, (RXOUT_PD_DBASE + dev->membase), 8); +} + +static const char *sysclk_str[SYS_CLK_MAX] = { + "36MHz", + "288MHz", +}; + +static const char *ppeclk_str[PPE_CLK_MAX] = { + "36MHz", + "576MHz", + "494MHz", + "432MHz", + "288MHz", +}; + +#define ACA_PMU_CTRL 0x11C +#define ACA_PMU_DMA BIT(2) +#define ACA_PMU_EMA BIT(22) + +enum { + DMA_ENDIAN_TYPE0 = 0, + DMA_ENDIAN_TYPE1, /*!< Byte Swap(B0B1B2B3 => B1B0B3B2) */ + DMA_ENDIAN_TYPE2, /*!< Word Swap (B0B1B2B3 => B2B3B0B1) */ + DMA_ENDIAN_TYPE3, /*!< DWord Swap (B0B1B2B3 => B3B2B1B0) */ + DMA_ENDIAN_MAX, +}; + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define DMA_ENDIAN_DEFAULT DMA_ENDIAN_TYPE3 +#else +#define DMA_ENDIAN_DEFAULT DMA_ENDIAN_TYPE0 +#endif + +enum { + DMA_BURSTL_2DW = 1, /*!< 2 DWORD DMA burst length */ + DMA_BURSTL_4DW = 2, /*!< 4 DWORD DMA burst length */ + DMA_BURSTL_8DW = 3, /*!< 8 DWORD DMA burst length */ + DMA_BURSTL_16DW = 16, +}; + +#define DMA_BURSTL_DEFAULT DMA_BURSTL_16DW + +#define DMA_TX_PORT_DEFAULT_WEIGHT 1 +/** Default Port Transmit weight value */ +#define DMA_TX_CHAN_DEFAULT_WEIGHT 1 + +enum { + DMA_RX_CH = 0, /*!< Rx channel */ + DMA_TX_CH = 1, /*!< Tx channel */ +}; + +enum { + DMA_PKT_DROP_DISABLE = 0, + DMA_PKT_DROP_ENABLE, +}; + +#ifdef CONFIG_CPU_BIG_ENDIAN +/* 2 DWs format descriptor */ +struct rx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 meta:2; + u32 byte_offset:3; + u32 meta_data:7; + u32 data_len:16; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); + +struct tx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 meta:2; + u32 byte_offset:3; + u32 meta_data:7; + u32 data_len:16; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#else +/* 2 DWs format descriptor */ +struct rx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 data_len:16; + u32 meta_data:7; + u32 byte_offset:3; + u32 meta:2; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); + +struct tx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 data_len:16; + u32 meta_data:7; + u32 byte_offset:3; + u32 meta:2; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#endif + +enum { + SOC_TO_EP = 0, + EP_TO_SOC, +}; + +static int dma_pkt_size = 1024; +static int dma_mode = SOC_TO_EP; +static int dma_burst = 16; +static int desc_num = 32; + +module_param(dma_pkt_size, int, 0); +MODULE_PARM_DESC(dma_pkt_size, "Single packet length"); + +module_param(dma_mode, int, 0); +MODULE_PARM_DESC(dma_mode, "mode 0 -- Soc->EP, mode 1-- EP->SoC"); + + +static void dma_ctrl_rst(struct dc_ep_dev *dev) +{ + ep_wr32_mask(ACA_PMU_DMA | ACA_PMU_EMA, 0, ACA_PMU_CTRL); + + udelay(10); + ep_wr32_mask(0, 1, DMA_CTRL); + udelay(10); + ep_wr32(0, DMA_CLC); +} + +static void dma_chan_rst(struct dc_ep_dev *dev, int cn) +{ + ep_wr32(cn, DMA_CS); + ep_wr32(0x2, DMA_CCTRL); + while (ep_rd32(DMA_CCTRL) & 0x01) + udelay(10); +} + +static void dma_port_cfg(struct dc_ep_dev *dev) +{ + u32 reg = 0; + + reg |= (DMA_TX_PORT_DEFAULT_WEIGHT << 12); + reg |= (DMA_ENDIAN_TYPE0 << 10); + reg |= (DMA_ENDIAN_TYPE0 << 8); + reg |= (DMA_PKT_DROP_DISABLE << 6); + reg |= 0x3; + ep_wr32(0, DMA_PS); + ep_wr32(reg, DMA_PCTRL); +} + +static void dma_byte_enable(struct dc_ep_dev *dev, int enable) +{ + if (enable) + ep_wr32_mask(0, BIT(9), DMA_CTRL); + else + ep_wr32_mask(BIT(9), 0, DMA_CTRL); +} + +static void dma_tx_ch_cfg(struct dc_ep_dev *dev, int ch, u32 desc_base, + u32 desc_phys, dma_addr_t data_base, int desc_num) +{ + int i; + struct tx_desc_2dw *tx_desc; + + for (i = 0; i < desc_num; i++) { + tx_desc = (struct tx_desc_2dw *) + (desc_base + (i * sizeof(*tx_desc))); + tx_desc->data_pointer = (((u32)(data_base + + (i * dma_pkt_size))) & 0xfffffff8); + tx_desc->status.word = 0; + tx_desc->status.field.byte_offset = 0; + tx_desc->status.field.data_len = dma_pkt_size; + + tx_desc->status.field.sop = 1; + tx_desc->status.field.eop = 1; + tx_desc->status.field.own = 1; + wmb(); + #if 0 + pr_info("Tx desc num %d word 0x%08x data pointer 0x%08x\n", + i, tx_desc->status.word, tx_desc->data_pointer); + #endif + } + ep_wr32(ch, DMA_CS); + ep_wr32(desc_phys, DMA_CDBA); + ep_wr32(desc_num, DMA_CDLEN); + ep_wr32(0, DMA_CIE); +} + +static void dma_rx_ch_cfg(struct dc_ep_dev *dev, int ch, u32 desc_base, + u32 desc_phys, dma_addr_t data_base, int desc_num) +{ + int i; + struct rx_desc_2dw *rx_desc; + + for (i = 0; i < desc_num; i++) { + rx_desc = (struct rx_desc_2dw *)(desc_base + + (i * sizeof(*rx_desc))); + rx_desc->data_pointer = (((u32)(data_base + + (i * dma_pkt_size))) & 0xfffffff8); + + rx_desc->status.word = 0; + rx_desc->status.field.sop = 1; + rx_desc->status.field.eop = 1; + rx_desc->status.field.byte_offset = 0; + rx_desc->status.field.data_len = dma_pkt_size; + rx_desc->status.field.own = 1; /* DMA own the descriptor */ + wmb(); + #if 0 + pr_info("Rx desc num %d word 0x%08x data pointer 0x%08x\n", + i, rx_desc->status.word, rx_desc->data_pointer); + #endif + } + + ep_wr32(ch, DMA_CS); + ep_wr32(desc_phys, DMA_CDBA); + ep_wr32(desc_num, DMA_CDLEN); + ep_wr32(0, DMA_CIE); +} + +static void dma_chan_on(struct dc_ep_dev *dev, u8 cn) +{ + ep_wr32(cn, DMA_CS); + ep_wr32_mask(0, BIT(0), DMA_CCTRL); +} + +static void dma_chan_off(struct dc_ep_dev *dev, u8 cn) +{ + ep_wr32(cn, DMA_CS); + ep_wr32_mask(BIT(0), 0, DMA_CCTRL); + udelay(10); +} + +#define DEFAULT_TEST_PATTEN 0x12345678 + +#define REG32(addr) (*((volatile u32*)(addr))) + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define ___swab32(x) ((u32)( \ + (((u32)(x) & (u32)0x000000ffUL) << 24) | \ + (((u32)(x) & (u32)0x0000ff00UL) << 8) | \ + (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \ + (((u32)(x) & (u32)0xff000000UL) >> 24))) +#else +#define ___swab32(x) (x) +#endif + +static void dma_sdram_preload(void *sdram_data_tx_ptr, void *sdram_data_rx_ptr) +{ + int i; + int j; + + u32 testaddr = (u32)sdram_data_tx_ptr; + + for (i = 0; i < desc_num; i++) { + for (j = 0; j < dma_pkt_size; j = j + 4) { + REG32(testaddr + i * dma_pkt_size + j) + = DEFAULT_TEST_PATTEN; + } + } + pr_info("SDR Preload(0x55aa00ff) with data on TX location done\n"); + + testaddr = (u32)sdram_data_rx_ptr; + pr_info("RX Preload start address:0x%08x\n", (u32)(testaddr)); + + for (i = 0; i < desc_num; i++) { + for (j = 0; j < roundup(dma_pkt_size, + dma_burst << 2); j = j + 4) + REG32(testaddr + i * dma_pkt_size + j) = 0xcccccccc; + } + pr_info("SDR locations for Memcopy RX preset to 0xcccccccc done\n"); +} + +static void memcopy_data_check(u32 rx_data_addr) +{ + int i, j; + u32 read_data; + + for (i = 0; i < desc_num; i++) { + for (j = 0; j < dma_pkt_size; j = j + 4) { + read_data = REG32(rx_data_addr + i * dma_pkt_size + j); + if (read_data != ___swab32(DEFAULT_TEST_PATTEN)) + pr_info("Memcopy ERROR at addr 0x%08x data 0x%08x\n", + (rx_data_addr + j), read_data); + } + } +} + +static u32 plat_throughput_calc(u32 payload, int cycles) +{ + return (u32)((payload * 300) / cycles); +} + +#define DMA_CPOLL_CNT_MASK 0xFFF0u + +static void dma_ctrl_global_polling_enable(struct dc_ep_dev *dev, int interval) +{ + u32 reg = 0; + + reg |= (1 << 31); + reg |= (interval << 4); + + ep_wr32_mask(DMA_CPOLL_CNT_MASK, + reg, DMA_CPOLL); +} + +static void dma_controller_cfg(struct dc_ep_dev *dev) +{ + ep_wr32_mask(0, BIT(31), DMA_CTRL); + ep_wr32_mask(BIT(30), 0, DMA_CTRL); + ep_wr32_mask(0, BIT(1), DMA_CTRL); + ep_wr32_mask(0, BIT(13), DMA_CTRL); +} + +#define PDRAM_OFFSET 0x200200 +#define PDRAM_TX_DESC_OFFSET 0x200000 +#define PDRAM_RX_DESC_OFFSET 0x200100 +#define ACA_SRAM_OFFSET 0x100000 +#define PPE_SB_TX_DESC_OFFSET 0x280000 +#define PPE_SB_RX_DESC_OFFSET 0x281000 + +#define PPE_FPI_TX_DESC_OFFSET 0x320000 +#define PPE_FPI_RX_DESC_OFFSET 0x321000 + +static void dma_test(struct dc_ep_dev *dev, int mode, int rcn, int tcn) +{ + u32 loop = 0; + void *tx_data; + void *rx_data; + dma_addr_t tx_data_phys = 0; + dma_addr_t rx_data_phys = 0; + u32 start, end; + u32 cycles; + struct rx_desc_2dw *rx_desc; + struct tx_desc_2dw *tx_desc; + struct tx_desc_2dw *last_tx_desc; + struct rx_desc_2dw *last_rx_desc; + dma_addr_t tx_desc_phys; + dma_addr_t rx_desc_phys; + u32 membase = (u32)(dev->membase); + + rx_desc = (struct rx_desc_2dw *)(membase + PDRAM_RX_DESC_OFFSET); + rx_desc_phys = (dev->phy_membase + PDRAM_RX_DESC_OFFSET); + tx_desc = (struct tx_desc_2dw *)(membase + PDRAM_TX_DESC_OFFSET); + tx_desc_phys = (dev->phy_membase + PDRAM_TX_DESC_OFFSET); + last_rx_desc = rx_desc + (desc_num - 1); + last_tx_desc = tx_desc + (desc_num - 1); + + if (mode == SOC_TO_EP) { /* Read from SoC DDR to local PDBRAM */ + tx_data = dma_alloc_coherent(NULL, + desc_num * dma_pkt_size, &tx_data_phys, GFP_DMA); + rx_data_phys = (dma_addr_t)(dev->phy_membase + PDRAM_OFFSET); + rx_data = (void *)(membase + PDRAM_OFFSET); + } else { /* Write from local PDBRAM to remote DDR */ + tx_data_phys = (dma_addr_t)(dev->phy_membase + PDRAM_OFFSET); + tx_data = (void *)(membase + PDRAM_OFFSET); + rx_data = dma_alloc_coherent(NULL, desc_num * dma_pkt_size, + &rx_data_phys, GFP_DMA); + } + + pr_info("tx_desc_base %p tx_desc_phys 0x%08x tx_data %p tx_data_phys 0x%08x\n", + tx_desc, (u32)tx_desc_phys, tx_data, (u32)tx_data_phys); + + pr_info("rx_desc_base %p rx_desc_phys 0x%08x rx_data %p rx_data_phys 0x%08x\n", + rx_desc, (u32)rx_desc_phys, rx_data, (u32)rx_data_phys); + + pr_info("dma burst %d desc number %d packet size %d\n", + dma_burst, desc_num, dma_pkt_size); + + dma_ctrl_rst(dev); + dma_chan_rst(dev, rcn); + dma_chan_rst(dev, tcn); + dma_port_cfg(dev); + dma_controller_cfg(dev); + dma_byte_enable(dev, 1); + + dma_ctrl_global_polling_enable(dev, 24); + + dma_sdram_preload(tx_data, rx_data); + + dma_tx_ch_cfg(dev, tcn, (u32)tx_desc, tx_desc_phys, + tx_data_phys, desc_num); + dma_rx_ch_cfg(dev, rcn, (u32)rx_desc, rx_desc_phys, + rx_data_phys, desc_num); + + udelay(5); /* Make sure that RX descriptor prefetched */ + + start = get_cycles(); + dma_chan_on(dev, rcn); + dma_chan_on(dev, tcn); + + /* wait till tx chan desc own is 0 */ + while (last_tx_desc->status.field.own == 1) { + loop++; + udelay(1); + } + end = get_cycles(); + cycles = end - start; + pr_info("cylces %d throughput %dMb\n", cycles, + plat_throughput_calc(desc_num * dma_pkt_size * 8, cycles)); + pr_info("loop times %d\n", loop); + while (last_rx_desc->status.field.own == 1) { + loop++; + udelay(1); + } + + memcopy_data_check((u32)rx_data); + dma_chan_off(dev, rcn); + dma_chan_off(dev, tcn); + if (mode == SOC_TO_EP) { + dma_free_coherent(NULL, desc_num * dma_pkt_size, + tx_data, tx_data_phys); + } else { + dma_free_coherent(NULL, desc_num * dma_pkt_size, + rx_data, rx_data_phys); + } +} + +static int aca_soc_desc_alloc(int dev) +{ + dma_addr_t phy_addr; + void *base; + u32 size; + + if (dev < 0 || dev > (DC_EP_MAX_PEER + 1)) + return -EINVAL; + + /* TXIN */ + size = TXIN_SOC_DES_NUM * TXIN_HD_DES_SIZE * 4; + base = dma_alloc_coherent(NULL, size, &phy_addr, GFP_DMA); + if (!base) + goto txin; + aca_soc_hd_desc[dev].txin.base = base; + aca_soc_hd_desc[dev].txin.phy_base = phy_addr; + aca_soc_hd_desc[dev].txin.size = size; + pr_info("txin soc desc base %p phy 0x%08x size 0x%08x\n", + base, (u32)phy_addr, size); + + /* TXOUT */ + size = TXOUT_SOC_DES_NUM * TXOUT_HD_DES_SIZE * 4; + base = dma_alloc_coherent(NULL, size, &phy_addr, GFP_DMA); + if (!base) + goto txout; + aca_soc_hd_desc[dev].txout.base = base; + aca_soc_hd_desc[dev].txout.phy_base = phy_addr; + aca_soc_hd_desc[dev].txout.size = size; + pr_info("txout soc desc base %p phy 0x%08x size 0x%08x\n", + base, (u32)phy_addr, size); + /* RXOUT */ + size = RXOUT_SOC_DES_NUM * RXOUT_HD_DES_SIZE * 4; + base = dma_alloc_coherent(NULL, size, &phy_addr, GFP_DMA); + if (!base) + goto rxout; + aca_soc_hd_desc[dev].rxout.base = base; + aca_soc_hd_desc[dev].rxout.phy_base = phy_addr; + aca_soc_hd_desc[dev].rxout.size = size; + pr_info("rxout soc desc base %p phy 0x%08x size 0x%08x\n", + base, (u32)phy_addr, size); + return 0; +rxout: + dma_free_coherent(NULL, aca_soc_hd_desc[dev].txout.size, + aca_soc_hd_desc[dev].txout.base, + aca_soc_hd_desc[dev].txout.phy_base); +txout: + dma_free_coherent(NULL, aca_soc_hd_desc[dev].txin.size, + aca_soc_hd_desc[dev].txin.base, + aca_soc_hd_desc[dev].txin.phy_base); +txin: + return -ENOMEM; +} + +static int aca_soc_desc_free(int dev) +{ + dma_addr_t phy_addr; + void *base; + size_t size; + + if (dev < 0 || dev > (DC_EP_MAX_PEER + 1)) + return -EINVAL; + + /* TXIN */ + base = aca_soc_hd_desc[dev].txin.base; + phy_addr = aca_soc_hd_desc[dev].txin.phy_base; + size = aca_soc_hd_desc[dev].txin.size; + dma_free_coherent(NULL, size, base, phy_addr); + + /* TXOUT */ + base = aca_soc_hd_desc[dev].txout.base; + phy_addr = aca_soc_hd_desc[dev].txout.phy_base; + size = aca_soc_hd_desc[dev].txout.size; + dma_free_coherent(NULL, size, base, phy_addr); + + /* RXOUT */ + base = aca_soc_hd_desc[dev].rxout.base; + phy_addr = aca_soc_hd_desc[dev].rxout.phy_base; + size = aca_soc_hd_desc[dev].rxout.size; + dma_free_coherent(NULL, size, base, phy_addr); + return 0; +} + +static int __init dc_ep_test_init(void) +{ + int i, j; + int dev_num; + struct dc_ep_dev dev; + int func = 0; + u32 sysclk = 0; + u32 ppeclk = 0; + + if (dc_ep_dev_num_get(&dev_num)) { + pr_err("%s failed to get total device number\n", __func__); + return -EIO; + } + + pr_info("%s: total %d EPs found\n", __func__, dev_num); + + for (i = 0; i < dev_num; i++) + aca_soc_desc_alloc(i); + + for (i = 0; i < dev_num; i++) { + struct aca_param aca_cfg = { + .aca_txin = { + .soc_desc_base + = aca_soc_hd_desc[i].txin.phy_base, + .soc_desc_num = TXIN_SOC_DES_NUM, + .pp_buf_desc_num = 32, + .pd_desc_base = TXIN_PD_DBASE, + .pd_desc_num = TXIN_PD_DES_NUM, + .hd_size_in_dw = TXIN_HD_DES_SIZE, + .pd_size_in_dw = TXIN_PD_DES_SIZE, + .byteswap = 1, + }, + .aca_txout = { + .soc_desc_base + = aca_soc_hd_desc[i].txout.phy_base, + .soc_desc_num = TXOUT_SOC_DES_NUM, + .pp_buf_desc_num = 32, + .pd_desc_base = TXOUT_PD_DBASE, + .pd_desc_num = TXOUT_PD_DES_NUM, + .hd_size_in_dw = TXOUT_HD_DES_SIZE, + .pd_size_in_dw = TXOUT_PD_DES_SIZE, + .byteswap = 1, + }, + .aca_rxout = { + .soc_desc_base + = aca_soc_hd_desc[i].rxout.phy_base, + .soc_desc_num = RXOUT_SOC_DES_NUM, + .pp_buf_desc_num = 32, + .pd_desc_base = RXOUT_PD_DBASE, + .pd_desc_num = RXOUT_PD_DES_NUM, + .hd_size_in_dw = RXOUT_HD_DES_SIZE, + .pd_size_in_dw = RXOUT_PD_DES_SIZE, + .byteswap = 1, + }, + }; + struct aca_modem_param modem_cfg = { + .mdm_txout = { + .stat = SB_XBAR_ADDR(__TX_OUT_ACA_ACCUM_STATUS), + .pd = SB_XBAR_ADDR(__TX_OUT_QUEUE_PD_BASE_ADDR_OFFSET), + .acc_cnt = SB_XBAR_ADDR(__TX_OUT_ACA_ACCUM_COUNT), + }, + .mdm_rxout = { + .stat = SB_XBAR_ADDR(__RX_OUT_ACA_ACCUM_STATUS), + .pd = SB_XBAR_ADDR(__RX_OUT_QUEUE_PD_BASE_ADDR_OFFSET), + .acc_cnt = SB_XBAR_ADDR(__RX_OUT_ACA_ACCUM_COUNT), + }, + .mdm_rxin = { + .stat = SB_XBAR_ADDR(__RX_IN_ACA_ACCUM_STATUS), + .pd = SB_XBAR_ADDR(__RX_IN_QUEUE_PD_BASE_ADDR_OFFSET), + .acc_cnt = SB_XBAR_ADDR(__RX_IN_ACA_ACCUM_COUNT), + }, + }; + if (dc_ep_dev_info_req(i, DC_EP_INT_PPE, &dev)) + pr_info("%s failed to get pcie ep %d information\n", + __func__, i); + pr_info("irq %d\n", dev.irq); + pr_info("phyiscal membase 0x%08x virtual membase 0x%p\n", + dev.phy_membase, dev.membase); + if (dev_num > 1) { + for (j = 0; j < dev.peer_num; j++) { + pr_info("phyiscal peer membase 0x%08x virtual peer membase 0x%p\n", + dev.peer_phy_membase[j], dev.peer_membase[j]); + } + } + /* For module unload perpose */ + memcpy(&pcie_dev[i], &dev, sizeof(struct dc_ep_dev)); + dc_ep_ppe_mbox_int_stress_test(&pcie_dev[i]); + dev.hw_ops->clk_on(&dev, PMU_CDMA | PMU_EMA | PMU_PPM2); + dev.hw_ops->clk_set(&dev, SYS_CLK_288MHZ, PPE_CLK_576MHZ); + dev.hw_ops->pinmux_set(&dev, 14, MUX_FUNC_ALT1); + dev.hw_ops->pinmux_set(&dev, 15, MUX_FUNC_ALT2); + dev.hw_ops->pinmux_get(&dev, 15, &func); + pr_info("gpio 15 func %d\n", func); + dev.hw_ops->pinmux_set(&dev, 13, MUX_FUNC_GPIO); + dev.hw_ops->gpio_dir(&dev, 13, GPIO_DIR_OUT); + dev.hw_ops->gpio_set(&dev, 13, 1); + dev.hw_ops->gpio_get(&dev, 13, &func); + pr_info("gpio 13 value %d\n", func); + dev.hw_ops->gpio_pupd_set(&dev, 14, GPIO_PULL_DOWN); + dev.hw_ops->gpio_od_set(&dev, 0, 1); + dev.hw_ops->gpio_src_set(&dev, 0, GPIO_SLEW_RATE_FAST); + dev.hw_ops->gpio_dcc_set(&dev, 0, GPIO_DRV_CUR_8MA); + dev.hw_ops->clk_get(&dev, &sysclk, &ppeclk); + pr_info("ppe clk %s sys clk %s\n", ppeclk_str[ppeclk], + sysclk_str[sysclk]); + dev.hw_ops->aca_init(&dev, &aca_cfg, &modem_cfg); + dev.hw_ops->aca_start(&dev, ACA_ALL_EN, 1); + + pr_info("ACA test\n"); + dc_aca_test_init(&dev, aca_soc_hd_desc[i].txin.base); + + pr_info("DMA test\n"); + dma_pkt_size = 64; + dma_test(&dev, dma_mode, 0, 1); +#if 0 + dma_pkt_size = 128; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 256; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 512; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 1024; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 2048; + dma_test(&dev, dma_mode, 0, 1); + + dma_mode = EP_TO_SOC; + dma_pkt_size = 64; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 128; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 256; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 512; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 1024; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 2048; + dma_test(&dev, dma_mode, 0, 1); +#endif + } + + pr_info("Intel(R) SmartPHY DSL(VRX518) PCIe EP Test Driver - %s\n", + ep_test_driver_version); + return 0; +} + +static void __exit dc_ep_test_exit(void) +{ + int i; + int dev_num; + u32 func = ACA_ALL_EN; + struct dc_ep_dev *dev; + + if (dc_ep_dev_num_get(&dev_num)) { + pr_err("%s failed to get total device number\n", __func__); + return; + } + pr_info("%s: total %d EPs found\n", __func__, dev_num); + for (i = 0; i < dev_num; i++) { + dev = &pcie_dev[i]; + free_irq(dev->irq, dev); + dev->hw_ops->aca_stop(dev, &func, 1); + dev->hw_ops->clk_off(dev, PMU_EMA); + if (dc_ep_dev_info_release(i)) { + pr_info("%s failed to release pcie ep %d information\n", + __func__, i); + } + aca_soc_desc_free(i); + } +} + +module_init(dc_ep_test_init); +module_exit(dc_ep_test_exit); + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION("Intel(R) SmartPHY (VRX518) PCIe EP/ACA test driver"); +MODULE_LICENSE("GPL"); diff --git a/package/kernel/lantiq/vrx518_ep/src/test/ep_test.h b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.h new file mode 100644 index 00000000000..ef2b847bb26 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.h @@ -0,0 +1,273 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef EP_TEST_H +#define EP_TEST_H + +/* SB address on xBar */ +#define SB_XBAR_BASE 0x280000 +#define SB_XBAR_DES_RXBASE SB_XBAR_BASE +#define SB_XBAR_DES_TXBASE (SB_XBAR_BASE + 0x400) +#define SB_XBAR_DATA_BASE (SB_XBAR_BASE + 0x800) +#define SB_XBAR_ADDR(x) (SB_XBAR_BASE + ((((x) - 0xA000)) << 2)) + +/*---------------------------------------------------------- + * ACA Shadow Registers + * 3 * 4 = 12 + * *_STATUS need to be initialized to nonzero by PPE driver + *---------------------------------------------------------- + */ + +#define __ACA_SHADOW_REG_BASE 0xADF0 + +#define __TX_IN_ACA_ACCUM_COUNT 0xADF0 + +#define __TX_IN_ACA_ACCUM_STATUS 0xADF1 + +#define __TX_IN_QUEUE_PD_BASE_ADDR_OFFSET 0xADF2 + +#define __TX_OUT_ACA_ACCUM_COUNT 0xADF3 + +#define __TX_OUT_ACA_ACCUM_STATUS 0xADF4 + +#define __TX_OUT_QUEUE_PD_BASE_ADDR_OFFSET 0xADF5 + +#define __RX_IN_ACA_ACCUM_COUNT 0xADF6 + +#define __RX_IN_ACA_ACCUM_STATUS 0xADF7 + +#define __RX_IN_QUEUE_PD_BASE_ADDR_OFFSET 0xADF8 + +#define __RX_OUT_ACA_ACCUM_COUNT 0xADF9 + +#define __RX_OUT_ACA_ACCUM_STATUS 0xADFA + +#define __RX_OUT_QUEUE_PD_BASE_ADDR_OFFSET 0xADFB + +#define TXIN_PD_DES_NUM 64 +#define TXIN_PD_DBASE 0x105400 +#define TXIN_SOC_DES_NUM 32 +#define TXIN_SOC_DBASE 0x24000000 +#define TXIN_HOST_DES_NUM 32 +#define TXIN_HD_DES_SIZE 4 /* size in DWORD */ +#define TXIN_PD_DES_SIZE 2 /* size in DWORD */ + +#define TXOUT_PD_DES_NUM 32 +#define TXOUT_PD_DBASE 0x105700 +#define TXOUT_SOC_DES_NUM 32 +#define TXOUT_SOC_DBASE 0x24001000 +#define TXOUT_HOST_DES_NUM 32 +#define TXOUT_HD_DES_SIZE 1 /* size in DWORD */ +#define TXOUT_PD_DES_SIZE 2 /* size in DWORD */ + +#define RXOUT_PD_DES_NUM 32 +#define RXOUT_PD_DBASE 0x105C00 +#define RXOUT_SOC_DES_NUM 32 +#define RXOUT_SOC_DBASE 0x24002000 +#define RXOUT_HOST_DES_NUM 32 +#define RXOUT_HD_DES_SIZE 4 /* size in DWORD */ +#define RXOUT_PD_DES_SIZE 2 /* size in DWORD */ + +/* PPE interrupt */ +#define PPE_MBOX_TEST_BIT 0x1 +#define PPE_MBOX_IRQ_TEST_NUM 100 + +#define PPE_MBOX_BASE 0x334800 + +#define MBOX_REG(X) (PPE_MBOX_BASE + (X)) +#define MBOX_IGU0_ISRS MBOX_REG(0x0) +#define MBOX_IGU0_ISRC MBOX_REG(0x4) +#define MBOX_IGU0_ISR MBOX_REG(0x8) +#define MBOX_IGU0_IER MBOX_REG(0xc) + +#define HOST_IF_BASE 0x50000 +#define HOST_IF_REG(X) (HOST_IF_BASE + (X)) +#define TXIN_CONV_CFG HOST_IF_REG(0x14) +#define RXIN_HD_ACCUM_ADD HOST_IF_REG(0xC8) /* UMT Message trigger */ +#define TXIN_HD_ACCUM_ADD HOST_IF_REG(0xCC) /* UMT Message trigger */ +#define RXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE0) /* PPE FW tigger */ +#define TXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE4) /* PPE FW tigger */ + +#define CDMA_BASE 0x2D0000 +#define CDMA_REG(X) (CDMA_BASE + (X)) + +#define DMA_CLC CDMA_REG(0x00) +#define DMA_ID CDMA_REG(0x08) +#define DMA_CTRL CDMA_REG(0x10) + +#define DMA_CTRL_RST BIT(0) +#define DMA_CTRL_DSRAM_PATH BIT(1) +#define DMA_CTRL_CH_FL BIT(6) +#define DMA_CTRL_DS_FOD BIT(7) +#define DMA_CTRL_DRB BIT(8) +#define DMA_CTRL_ENBE BIT(9) +#define DMA_CTRL_PRELOAD_INT_S 10 +#define DMA_CTRL_PRELOAD_INT 0x0C00u +#define DMA_CTRL_PRELOAD_EN BIT(12) +#define DMA_CTRL_MBRST_CNT_S 16 +#define DMA_CTRL_MBRST_CNT 0x3FF0000u +#define DMA_CTRL_MBRSTARB BIT(30) +#define DMA_CTRL_PKTARB BIT(31) + +#define DMA_CPOLL CDMA_REG(0x14) +#define DMA_CPOLL_CNT_S 4 +#define DMA_CPOLL_CNT 0xFFF0u +#define DMA_CPOLL_EN BIT(31) + +#define DMA_CS CDMA_REG(0x18) +#define DMA_CCTRL CDMA_REG(0x1C) +#define DMA_CCTRL_ON BIT(0) +#define DMA_CCTRL_RST BIT(1) +#define DMA_CCTRL_DIR_TX BIT(8) +#define DMA_CCTRL_CLASS_S 9 +#define DMA_CCTRL_CLASS 0xE00u +#define DMA_CCTRL_PRTNR_S 12 +#define DMA_CCTRL_PRTNR 0xF000u +#define DMA_CCTRL_TXWGT_S 16 +#define DMA_CCTRL_TXWGT 0x30000u +#define DMA_CCTRL_CLASSH_S 18 +#define DMA_CCTRL_CLASSH 0xC0000u +#define DMA_CCTRL_PDEN BIT(23) +#define DMA_CCTRL_P2PCPY BIT(24) +#define DMA_CCTRL_LBEN BIT(25) +#define DMA_CCTRL_LBCHNR_S 26 +#define DMA_CCTRL_LBCHNR 0xFC000000u + +#define DMA_CDBA CDMA_REG(0x20) +#define DMA_CDLEN CDMA_REG(0x24) +#define DMA_CIS CDMA_REG(0x28) +#define DMA_CIE CDMA_REG(0x2C) + +#define DMA_CI_EOP BIT(1) +#define DMA_CI_DUR BIT(2) +#define DMA_CI_DESCPT BIT(3) +#define DMA_CI_CHOFF BIT(4) +#define DMA_CI_RDERR BIT(5) +#define DMA_CI_ALL (DMA_CI_EOP | DMA_CI_DUR | DMA_CI_DESCPT\ + | DMA_CI_CHOFF | DMA_CI_RDERR) + +#define DMA_CI_DEFAULT (DMA_CI_EOP | DMA_CI_DESCPT) +#define DMA_CDPTNRD CDMA_REG(0x34) + +#define DMA_PS CDMA_REG(0x40) +#define DMA_PCTRL CDMA_REG(0x44) +#define DMA_PCTRL_RXBL16 BIT(0) +#define DMA_PCTRL_TXBL16 BIT(1) +#define DMA_PCTRL_RXBL_S 2 +#define DMA_PCTRL_RXBL 0xCu +#define DMA_PCTRL_TXBL_S 4 +#define DMA_PCTRL_TXBL 0x30u +#define DMA_PCTRL_PDEN BIT(6) +#define DMA_PCTRL_PDEN_S 6 +#define DMA_PCTRL_RXENDI_S 8 +#define DMA_PCTRL_RXENDI 0x300u +#define DMA_PCTRL_TXENDI_S 10 +#define DMA_PCTRL_TXENDI 0xC00u +#define DMA_PCTRL_TXWGT_S 12 +#define DMA_PCTRL_TXWGT 0x7000u +#define DMA_PCTRL_MEM_FLUSH BIT(16) + +#define DMA_IRNEN CDMA_REG(0xF4) +#define DMA_IRNCR CDMA_REG(0xF8) +#define DMA_IRNICR CDMA_REG(0xFC) + +#ifdef CONFIG_CPU_BIG_ENDIAN +struct aca_dma_desc { + /* DW0 */ + u32 dw0; + /* DW1 */ + u32 dw1; + /* DW2 */ + u32 data_pointer; + /* DW3 */ + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 dic:1; + u32 pdu_type:1; + u32 byte_off:3; + u32 qid:4; + u32 mpoa_pt:1; + u32 mpoa_mode:2; + u32 data_len:16; +}__packed __aligned(16); + +/* 2 DWs format descriptor */ +struct aca_dma_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 meta_data0:2; + u32 byte_offset:3; + u32 meta_data1:7; + u32 data_len:16; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#else +struct aca_dma_desc { + /* DW0 */ + u32 dw0; + /* DW1 */ + u32 dw1; + /* DW2 */ + u32 data_pointer; + /* DW 3 */ + u32 data_len:16; + u32 mpoa_mode:2; + u32 mpoa_pt:1; + u32 qid:4; + u32 byte_off:3; + u32 pdu_type:1; + u32 dic:1; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; +}__packed __aligned(16); + +/* 2 DWs format descriptor */ +struct aca_dma_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 data_len:16; + u32 meta_data1:7; + u32 byte_offset:3; + u32 meta_data0:2; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#endif +#endif /* EP_TEST_H */ diff --git a/package/kernel/lantiq/vrx518_tc/Makefile b/package/kernel/lantiq/vrx518_tc/Makefile new file mode 100644 index 00000000000..fde4c07e448 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/Makefile @@ -0,0 +1,74 @@ +# +# Copyright (C) 2019 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=vrx518_tc +PKG_VERSION:=1.5.12.4 +PKG_RELEASE:=$(AUTORELEASE) +PKG_BASE_NAME:=vrx518_tc_drv + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=0c5bb0f9a06dc4cc4bbb8b930d01a673daba1b66615e8328818356d32c8f1548 +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/package.mk + +PLAT_DIR:=dcdp +PKG_EXTMOD_SUBDIRS:=$(PLAT_DIR) + +# TODO this driver depends on the vrx518 ppe firmware, add this dependency if +# that ever gets a compatible license +define KernelPackage/$(PKG_NAME) + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=VRX518 TC driver + KCONFIG:= \ + CONFIG_ATM_LANE=m \ + CONFIG_ATM_MPOA=m \ + CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT=y + DEPENDS:=@TARGET_ipq40xx +kmod-vrx518_ep +kmod-crypto-md5 +kmod-atm +kmod-ipoa +br2684ctl + AUTOLOAD:=$(call AutoLoad,27,vrx518_tc) + FILES:=$(PKG_BUILD_DIR)/$(PLAT_DIR)/$(PKG_NAME).ko +endef + +define KernelPackage/$(PKG_NAME)/description + VRX518 TC Driver +endef + +define Build/Prepare + $(PKG_UNPACK) + # eliminate all carriage returns / convert to unix encoding + (cd $(PKG_BUILD_DIR) && find . -type f -exec sed -i 's/\r//g' {} +) + $(Build/Patch) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/net/ + $(CP) $(PKG_BUILD_DIR)/$(PLAT_DIR)/inc/dsl_tc.h $(1)/usr/include/net/ +endef + +EXTRA_CFLAGS:= \ + -I$(STAGING_DIR)/usr/include + +define Build/Compile + $(KERNEL_MAKE) \ + M="$(PKG_BUILD_DIR)/$(PLAT_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + FEATURE_VRX518_CPU=y \ + modules +endef + +$(eval $(call KernelPackage,$(PKG_NAME))) diff --git a/package/kernel/lantiq/vrx518_tc/patches/100-compat.patch b/package/kernel/lantiq/vrx518_tc/patches/100-compat.patch new file mode 100644 index 00000000000..2c92912adef --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/100-compat.patch @@ -0,0 +1,859 @@ +--- a/dcdp/atm_tc.c ++++ b/dcdp/atm_tc.c +@@ -44,9 +44,9 @@ + #include + #include + #include "inc/dsl_tc.h" +-#include ++// #include + #include +-#include ++// #include + #include + #include + #include +@@ -730,20 +730,16 @@ static void atm_aca_init(struct atm_priv + ACA_TXOUT_EN | ACA_RXIN_EN | ACA_RXOUT_EN, 1); + } + +-static int print_datetime(char *buffer, const struct timespec *datetime) ++static int print_datetime(char *buffer, const struct timespec64 *datetime) + { +- struct timeval tv; + struct tm nowtm; + char tmbuf[64]; +- s64 nsec; + + if (buffer == NULL || datetime == NULL) { + pr_err("%s : Invalid arguments\n", __func__); + return -1; + } +- nsec = timespec_to_ns(datetime); +- tv = ns_to_timeval(nsec); +- time_to_tm(tv.tv_sec, 0, &nowtm); ++ time64_to_tm(datetime->tv_sec, 0, &nowtm); + memset(tmbuf, 0, 64); + + snprintf(tmbuf, sizeof(tmbuf), "%ld-%d-%d %d:%d:%d", +@@ -753,7 +749,7 @@ static int print_datetime(char *buffer, + nowtm.tm_hour, + nowtm.tm_min, + nowtm.tm_sec); +- snprintf(buffer, sizeof(buffer), "%s.%06d", tmbuf, (int)tv.tv_usec); ++ snprintf(buffer, sizeof(buffer), "%s.%06d", tmbuf, (int)datetime->tv_nsec / 1000); + + return 0; + } +@@ -1313,7 +1309,7 @@ static int ppe_send(struct atm_vcc *vcc, + /* assume LLC header + Ethernet ID: 6+2 */ + if ((priv->conn[conn].mpoa_type == MPOA_TYPE_EOA_WO_FCS) || + (priv->conn[conn].mpoa_type == MPOA_TYPE_EOA_W_FCS)) { +- if (__skb_put_padto(skb, ETH_ZLEN + 8)) ++ if (__skb_put_padto(skb, ETH_ZLEN + 8, false)) + goto CHECK_SHOWTIME_FAIL; + } + +@@ -1418,7 +1414,7 @@ int ppe_send_oam(struct atm_vcc *vcc, vo + struct atm_priv *priv = g_atm_tc; + struct sk_buff *skb; + unsigned int conn; +- dp_subif_t dp_id; ++// dp_subif_t dp_id; + #ifdef OAM_FIX_GRX750 + unsigned char *dest_cell; + #endif +@@ -1465,8 +1461,8 @@ int ppe_send_oam(struct atm_vcc *vcc, vo + priv->tc_priv->param.oam_prio = 0; + qid = priv->conn[conn].prio_queue_map[priv->tc_priv->param.oam_prio]; + vid = priv->conn[conn].subif_id; +- dp_id.subif = (vid & (~0x7f)) | +- ATM_DESC_SUBIF_ID(qid, mpoa_pt, mpoa_type); ++// dp_id.subif = (vid & (~0x7f)) | ++// ATM_DESC_SUBIF_ID(qid, mpoa_pt, mpoa_type); + #ifdef OAM_FIX_GRX750 + dest_cell = kmalloc(CELL_SIZE, GFP_KERNEL); + if (dest_cell == NULL) { +@@ -1494,18 +1490,18 @@ int ppe_send_oam(struct atm_vcc *vcc, vo + #else + memcpy(skb->data, cell, CELL_SIZE); + #endif +- /* SET SUBIFID */ +- skb->DW0 = (skb->DW0 & ~0x7FFF) | dp_id.subif; +- skb->dev = priv->conn[conn].dev; +- tc_dbg(priv->tc_priv, MSG_TX, "conn: %d, dev name: %s, qid: 0x%x len:%d\n", +- conn, skb->dev->name, dp_id.subif, skb->len); +- #ifdef OAM_FIX_GRX750 +- if (priv->tc_priv->tc_ops.send(NULL, +- skb, dp_id.subif, ATM_OAM_PKT) == 0) { +- #else ++// /* SET SUBIFID */ ++// skb->DW0 = (skb->DW0 & ~0x7FFF) | dp_id.subif; ++// skb->dev = priv->conn[conn].dev; ++// tc_dbg(priv->tc_priv, MSG_TX, "conn: %d, dev name: %s, qid: 0x%x len:%d\n", ++// conn, skb->dev->name, dp_id.subif, skb->len); ++// #ifdef OAM_FIX_GRX750 ++// if (priv->tc_priv->tc_ops.send(NULL, ++// skb, dp_id.subif, ATM_OAM_PKT) == 0) { ++// #else + if (priv->tc_priv->tc_ops.send(NULL, + skb, qid, ATM_OAM_PKT) == 0) { +- #endif ++// #endif + priv->stats.oam_tx_pkts++; + priv->stats.oam_tx_bytes += skb->len; + priv->conn[conn].stats.oam_tx_pkts++; +@@ -1604,7 +1600,7 @@ static void oam_push(struct atm_priv *pr + conn = -1; /* invalid */ + if (conn_valid(conn) && priv->conn[conn].vcc != NULL) { + vcc = priv->conn[conn].vcc; +- priv->conn[conn].access_time = current_kernel_time(); ++ ktime_get_coarse_ts64(&priv->conn[conn].access_time); + + tc_dbg(priv->tc_priv, MSG_OAM_RX, "conn=%d, vpi: %d, vci:%d\n", + conn, header->vpi, header->vci); +@@ -2547,30 +2543,29 @@ static void ppe_atm_fw_hw_init(struct at + static int atm_dev_init(struct atm_priv *atm_priv, int ep_id) + { + int i, err; +- struct atm_dev *dev; +- dev = atm_dev_register(g_atm_dev_name, +- atm_priv->tc_priv->ep_dev[ep_id].dev, +- &g_ppe_atm_ops, -1, NULL); +- if (!dev) { +- err = -EIO; +- goto ATM_DEV_REGISTER_FAIL; +- } +- dev->ci_range.vpi_bits = 8; +- dev->ci_range.vci_bits = 16; +- /* assume 3200 cell rate +- * before get real information +- */ +- dev->link_rate = +- DEFAULT_CELL_RATE; +- dev->dev_data = atm_priv; +- dev->phy_data = +- (void *)(unsigned long)0; + + for (i = 0; i < ATM_PORT_NUMBER; i++) { + if (atm_priv->port[i].dev) + continue; + atm_priv->port[i].tx_max_cell_rate = DEFAULT_CELL_RATE; +- atm_priv->port[i].dev = dev; ++ atm_priv->port[i].dev = atm_dev_register(g_atm_dev_name, ++ atm_priv->tc_priv->ep_dev[ep_id].dev, ++ &g_ppe_atm_ops, -1, NULL); ++ if (!atm_priv->port[i].dev) { ++ err = -EIO; ++ goto ATM_DEV_REGISTER_FAIL; ++ } else { ++ atm_priv->port[i].dev->ci_range.vpi_bits = 8; ++ atm_priv->port[i].dev->ci_range.vci_bits = 16; ++ /* assume 3200 cell rate ++ * before get real information ++ */ ++ atm_priv->port[i].dev->link_rate = ++ DEFAULT_CELL_RATE; ++ atm_priv->port[i].dev->dev_data = atm_priv; ++ atm_priv->port[i].dev->phy_data = ++ (void *)(unsigned long)i; ++ } + } + //TODO : check for SoC PMAC, current fix + #ifdef CONFIG_SOC_TYPE_XWAY +@@ -2985,7 +2980,8 @@ static unsigned int atm_get_pvc_id(struc + return -EINVAL; + } + +- return (skb->DW0 >> 3) & 0xF; ++// return (skb->DW0 >> 3) & 0xF; ++ return 1; + } + + static int atm_get_qid_by_vcc(struct net_device *dev, struct sk_buff *skb, +@@ -3292,7 +3288,7 @@ static void atm_push(struct net_device * + += skb->len; + } else + priv->stats.aal5_rx_errors++; +- priv->conn[conn].access_time = current_kernel_time(); ++ ktime_get_coarse_ts64(&priv->conn[conn].access_time); + spin_unlock_bh(&priv->atm_lock); + + vcc->push(vcc, skb); +--- a/dcdp/inc/atm_tc.h ++++ b/dcdp/inc/atm_tc.h +@@ -449,7 +449,7 @@ struct atm_port { + struct atm_pvc { + struct atm_vcc *vcc; /* opened VCC */ + struct net_device *dev; /* net device associated with atm VCC */ +- struct timespec access_time; /* time when last user cell arrived */ ++ struct timespec64 access_time; /* time when last user cell arrived */ + int prio_queue_map[ATM_PRIO_Q_NUM]; + unsigned int prio_tx_packets[ATM_PRIO_Q_NUM]; + struct atm_stats stats; +--- a/dcdp/inc/tc_api.h ++++ b/dcdp/inc/tc_api.h +@@ -196,19 +196,6 @@ static inline void aca_ring_addr_init(st + ring->aca_cnt_phyaddr = ep_dev->phy_membase + addr; + } + +-static inline int __skb_put_padto(struct sk_buff *skb, unsigned int len) +-{ +- unsigned int size = skb->len; +- +- if (unlikely(size < len)) { +- len -= size; +- if (skb_pad(skb, len)) +- return -ENOMEM; +- __skb_put(skb, len); +- } +- return 0; +-} +- + extern int showtime_stat(struct tc_priv *); + extern void dump_skb_info(struct tc_priv *, struct sk_buff *, u32); + extern void *tc_buf_alloc(void *, size_t, u32 *, +--- a/dcdp/inc/tc_proc.h ++++ b/dcdp/inc/tc_proc.h +@@ -23,6 +23,8 @@ + #ifndef __TC_PROC_H__ + #define __TC_PROC_H__ + ++#include ++ + #define TC_PROC_DIR "driver/vrx518" + #define TC_PROC_ATM_DIR "atm" + #define TC_PROC_PTM_DIR "ptm" +@@ -41,7 +43,7 @@ enum { + struct tc_proc_list { + char proc_name[32]; + umode_t mode; +- const struct file_operations *fops; ++ const struct proc_ops *fops; + int is_folder; + }; + +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -39,7 +39,7 @@ + #include + #include + #include +-#include ++// #include + + #include "inc/tc_main.h" + #include "inc/reg_addr.h" +@@ -182,8 +182,8 @@ static int ptm_get_qid(struct net_device + return qid; + } + +-static struct rtnl_link_stats64 *ptm_get_stats(struct net_device *dev, +- struct rtnl_link_stats64 *storage) ++static void ptm_get_stats(struct net_device *dev, ++ struct rtnl_link_stats64 *storage) + { + struct ptm_priv *ptm_tc = netdev_priv(dev); + +@@ -191,8 +191,6 @@ static struct rtnl_link_stats64 *ptm_get + memcpy(storage, &ptm_tc->stats64, sizeof(ptm_tc->stats64)); + else + storage->tx_errors += ptm_tc->stats64.tx_errors; +- +- return storage; + } + + static int ptm_set_mac_address(struct net_device *dev, void *p) +@@ -209,7 +207,7 @@ static int ptm_set_mac_address(struct ne + return 0; + } + +-static void ptm_tx_timeout(struct net_device *dev) ++static void ptm_tx_timeout(struct net_device *dev, unsigned int txqueue) + { + struct ptm_priv *ptm_tc = netdev_priv(dev); + +@@ -503,7 +501,7 @@ static int ptm_xmit(struct sk_buff *skb, + if (!showtime_stat(ptm_tc->tc_priv)) + goto PTM_XMIT_DROP; + +- if (__skb_put_padto(skb, ETH_ZLEN)) ++ if (__skb_put_padto(skb, ETH_ZLEN, false)) + goto PTM_XMIT_DROP; + + dump_skb_info(ptm_tc->tc_priv, skb, (MSG_TX | MSG_TXDATA)); +@@ -632,11 +630,8 @@ static int ptm_dev_init(struct tc_priv * + struct ptm_priv *ptm_tc; + const char macaddr[ETH_ALEN] + = {0xAC, 0x9A, 0x96, 0x11, 0x22, 0x33}; +-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) +- dev = alloc_netdev_mq(sizeof(*ptm_tc), "ptm%d", ptm_setup, 4); +-#else +- dev = alloc_netdev_mq(sizeof(*ptm_tc), "ptm%d", NET_NAME_ENUM, ptm_setup, 4); +-#endif ++ ++ dev = alloc_netdev_mq(sizeof(*ptm_tc), "dsl%d", NET_NAME_ENUM, ptm_setup, 4); + if (!dev) { + tc_dbg(tc_priv, MSG_INIT, "Cannot alloc net device\n"); + return -ENOMEM; +@@ -2103,7 +2098,6 @@ static int ptm_showtime_exit(const unsig + struct ptm_ep_priv *priv = tc_ep_priv(idx); + u32 stop = ACA_TXIN_EN; + struct dc_ep_dev *ep; +- int i = 0; + + tc_info(priv->tc_priv, MSG_EVENT, "Line[%d]: show time exit!\n", idx); + ep = priv->ep; +--- a/dcdp/tc_api.c ++++ b/dcdp/tc_api.c +@@ -52,18 +52,24 @@ static const char ppe_fw_name[] = "ppe_f + #define VRX518_PPE_FW_ID 0xB + #define MD5_LEN 16 + ++enum tc_multicast_groups { ++ TC_MCGRP, ++}; ++ ++/* TC message multicast group */ ++static const struct genl_multicast_group tc_ml_grps[] = { ++ [TC_MCGRP] = { .name = TC_MCAST_GRP_NAME, }, ++}; ++ + /* TC message genelink family */ + static struct genl_family tc_gnl_family = { +- .id = GENL_ID_GENERATE, /* To generate an id for the family*/ ++// .id = GENL_ID_GENERATE, /* To generate an id for the family*/ + .hdrsize = 0, + .name = TC_FAMILY_NAME, /*family name, used by userspace application*/ + .version = 1, /*version number */ + .maxattr = TC_A_MAX - 1, +-}; +- +-/* TC message multicast group */ +-static struct genl_multicast_group tc_ml_grp = { +- .name = TC_MCAST_GRP_NAME, ++ .mcgrps = tc_ml_grps, ++ .n_mcgrps = ARRAY_SIZE(tc_ml_grps), + }; + + /** +@@ -568,7 +574,8 @@ int tc_ntlk_msg_send(struct tc_priv *pri + nla_put_u32(skb, TC_A_LINENO, ln_no); + + genlmsg_end(skb, msg_head); +- ret = genlmsg_multicast(skb, pid, tc_ml_grp.id, GFP_KERNEL); ++ ret = genlmsg_multicast(&tc_gnl_family, skb, pid, TC_MCGRP, ++ GFP_KERNEL); + if (ret) { + tc_err(priv, MSG_EVENT, "Sent TC multicast message Fail!\n"); + goto err1; +@@ -590,21 +597,11 @@ int tc_gentlk_init(struct tc_priv *priv) + return ret; + } + +- ret = genl_register_mc_group(&tc_gnl_family, &tc_ml_grp); +- if (ret) { +- tc_err(priv, MSG_EVENT, "register mc group fail: %i, grp name: %s\n", +- ret, tc_ml_grp.name); +- genl_unregister_family(&tc_gnl_family); +- return ret; +- } +- + return 0; + } + + void tc_gentlk_exit(void) + { +- /* unregister mc groups */ +- genl_unregister_mc_group(&tc_gnl_family, &tc_ml_grp); + /*unregister the family*/ + genl_unregister_family(&tc_gnl_family); + } +@@ -666,7 +663,7 @@ void dump_skb_info(struct tc_priv *tcpri + (u32)skb->end, skb->len); + tc_dbg(tcpriv, type, + "skb: clone: %d, users: %d\n", +- skb->cloned, atomic_read(&skb->users)); ++ skb->cloned, refcount_read(&skb->users)); + tc_dbg(tcpriv, type, + "skb: nfrag: %d\n", skb_shinfo(skb)->nr_frags); + +@@ -936,7 +933,6 @@ static int fw_md5_check(struct tc_priv * + } + + desc->tfm = md5; +- desc->flags = 0; + + ret = crypto_shash_init(desc); + if (ret) { +--- a/dcdp/tc_proc.c ++++ b/dcdp/tc_proc.c +@@ -22,7 +22,9 @@ + *******************************************************************************/ + #include + #include +-#include ++// #include ++#include ++#include + #include + #include + #include "inc/tc_main.h" +@@ -353,7 +355,7 @@ static ssize_t mem_proc_write(struct fil + } + addr = set_val = repeat_cnt = 0; + +- if (!access_ok(VERIFY_READ, buf, count)) ++ if (!access_ok(buf, count)) + return -EFAULT; + + len = count < sizeof(str) ? count : sizeof(str) - 1; +@@ -450,13 +452,12 @@ static int proc_read_mem_seq_open(struct + return single_open(file, proc_read_mem, NULL); + } + +-static const struct file_operations mem_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_mem_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .write = mem_proc_write, ++static const struct proc_ops mem_proc_fops = { ++ .proc_open = proc_read_mem_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = mem_proc_write, + }; + + static ssize_t pp32_proc_write(struct file *file, const char __user *buf, +@@ -748,13 +749,12 @@ static int proc_read_pp32_seq_open(struc + return single_open(file, proc_read_pp32, PDE_DATA(inode)); + } + +-static const struct file_operations pp32_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_pp32_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .write = pp32_proc_write, ++static const struct proc_ops pp32_proc_fops = { ++ .proc_open = proc_read_pp32_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = pp32_proc_write, + }; + + static int proc_read_tc_cfg(struct seq_file *seq, void *v) +@@ -865,13 +865,12 @@ static int proc_read_tc_cfg_seq_open(str + return single_open(file, proc_read_tc_cfg, PDE_DATA(inode)); + } + +-static const struct file_operations tc_cfg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_tc_cfg_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .write = proc_write_cfg, ++static const struct proc_ops tc_cfg_proc_fops = { ++ .proc_open = proc_read_tc_cfg_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = proc_write_cfg, + }; + + static ssize_t proc_write_dbg(struct file *file, const char __user *buf, +@@ -951,13 +950,12 @@ static int proc_read_dbg_seq_open(struct + return single_open(file, proc_read_dbg, PDE_DATA(inode)); + } + +-static const struct file_operations tc_dbg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_dbg_seq_open, +- .read = seq_read, +- .write = proc_write_dbg, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops tc_dbg_proc_fops = { ++ .proc_open = proc_read_dbg_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_dbg, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static ssize_t proc_write_tc_switch(struct file *file, const char __user *buf, +@@ -1018,11 +1016,11 @@ proc_tc_switch_help: + return count; + } + +-static const struct file_operations tc_switch_proc_fops = { +- .owner = THIS_MODULE, +- .write = proc_write_tc_switch, +- .llseek = noop_llseek, ++static const struct proc_ops tc_switch_proc_fops = { ++ .proc_write = proc_write_tc_switch, ++ .proc_lseek = noop_llseek, + }; ++ + static ssize_t proc_write_show_time(struct file *file, const char __user *buf, + size_t count, loff_t *data) + { +@@ -1077,10 +1075,9 @@ proc_show_time_help: + return count; + } + +-static const struct file_operations tc_show_time_proc_fops = { +- .owner = THIS_MODULE, +- .write = proc_write_show_time, +- .llseek = noop_llseek, ++static const struct proc_ops tc_show_time_proc_fops = { ++ .proc_write = proc_write_show_time, ++ .proc_lseek = noop_llseek, + }; + + static int proc_read_ver(struct seq_file *seq, void *v) +@@ -1128,12 +1125,11 @@ static int proc_read_ver_seq_open(struct + return single_open(file, proc_read_ver, PDE_DATA(inode)); + } + +-static const struct file_operations tc_ver_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_ver_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops tc_ver_proc_fops = { ++ .proc_open = proc_read_ver_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_read_soc(struct seq_file *seq, void *v) +@@ -1142,20 +1138,18 @@ static int proc_read_soc(struct seq_file + + tcpriv = (struct tc_priv *)seq->private; + +-#if 0 + seq_printf(seq, "TXIN Base: 0x%08x, TXIN num: %d\n", +- tcpriv->cfg.txin_dbase, +- tcpriv->cfg.txin_dnum); ++ tcpriv->cfg.txin.soc_phydbase, ++ tcpriv->cfg.txin.soc_dnum); + seq_printf(seq, "TXOUT Base: 0x%08x, TXOUT num: %d\n", +- tcpriv->cfg.txout_dbase, +- tcpriv->cfg.txout_dnum); ++ tcpriv->cfg.txout.soc_phydbase, ++ tcpriv->cfg.txout.soc_dnum); + seq_printf(seq, "RXIN Base: 0x%08x, RXIN num: %d\n", +- tcpriv->cfg.rxin_dbase, +- tcpriv->cfg.rxin_dnum); ++ tcpriv->cfg.rxin.soc_phydbase, ++ tcpriv->cfg.rxin.soc_dnum); + seq_printf(seq, "RXOUT Base: 0x%08x, RXOUT num: %d\n", +- tcpriv->cfg.rxout_dbase, +- tcpriv->cfg.rxout_dnum); +-#endif ++ tcpriv->cfg.rxout.soc_phydbase, ++ tcpriv->cfg.rxout.soc_dnum); + + return 0; + } +@@ -1165,15 +1159,13 @@ static int proc_read_soc_seq_open(struct + return single_open(file, proc_read_soc, PDE_DATA(inode)); + } + +-static const struct file_operations tc_soc_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_soc_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops tc_soc_proc_fops = { ++ .proc_open = proc_read_soc_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + +- + static struct tc_proc_list tc_procs[] = { + {TC_PROC_DIR, 0, NULL, 1}, + {"cfg", 0644, &tc_cfg_proc_fops, 0}, +@@ -1241,13 +1233,12 @@ static int proc_read_ptm_wanmib_seq_open + return single_open(file, proc_read_ptm_wanmib, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_wanmib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_ptm_wanmib_seq_open, +- .read = seq_read, +- .write = proc_write_ptm_wanmib, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops ptm_wanmib_proc_fops = { ++ .proc_open = proc_read_ptm_wanmib_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_ptm_wanmib, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_ptm_read_cfg(struct seq_file *seq, void *v) +@@ -1300,7 +1291,7 @@ static ssize_t ptm_cfg_proc_write(struct + return -EINVAL; + } + +- if (!access_ok(VERIFY_READ, buf, count)) ++ if (!access_ok(buf, count)) + return -EFAULT; + + len = count < sizeof(str) ? count : sizeof(str) - 1; +@@ -1343,13 +1334,12 @@ proc_ptm_cfg_help: + } + + +-static const struct file_operations ptm_cfg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_cfg_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = ptm_cfg_proc_write, +- .release = single_release, ++static const struct proc_ops ptm_cfg_proc_fops = { ++ .proc_open = proc_read_cfg_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = ptm_cfg_proc_write, ++ .proc_release = single_release, + }; + + static ssize_t proc_ptm_write_prio(struct file *file, const char __user *buf, +@@ -1455,13 +1445,12 @@ static int proc_ptm_read_prio_seq_open(s + return single_open(file, proc_ptm_read_prio, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_prio_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_ptm_read_prio_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = proc_ptm_write_prio, +- .release = single_release, ++static const struct proc_ops ptm_prio_proc_fops = { ++ .proc_open = proc_ptm_read_prio_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = proc_ptm_write_prio, ++ .proc_release = single_release, + }; + + static int proc_ptm_read_bond_seq_open(struct inode *inode, struct file *file) +@@ -1469,12 +1458,11 @@ static int proc_ptm_read_bond_seq_open(s + return single_open(file, proc_ptm_read_bond, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_bond_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_ptm_read_bond_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops ptm_bond_proc_fops = { ++ .proc_open = proc_ptm_read_bond_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_ptm_read_bondmib_seq_open(struct inode *inode, +@@ -1483,13 +1471,12 @@ static int proc_ptm_read_bondmib_seq_ope + return single_open(file, proc_ptm_read_bondmib, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_bondmib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_ptm_read_bondmib_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = proc_ptm_write_bondmib, +- .release = single_release, ++static const struct proc_ops ptm_bondmib_proc_fops = { ++ .proc_open = proc_ptm_read_bondmib_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = proc_ptm_write_bondmib, ++ .proc_release = single_release, + }; + + struct fwdbg_t { +@@ -1910,14 +1897,14 @@ static int proc_read_fwdbg_seq_open(stru + { + return single_open(file, proc_read_fwdbg, NULL); + } +-static const struct file_operations fwdbg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_fwdbg_seq_open, +- .read = seq_read, +- .write = proc_write_fwdbg_seq, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops fwdbg_proc_fops = { ++ .proc_open = proc_read_fwdbg_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_fwdbg_seq, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; ++ + static struct tc_proc_list ptm_sl_procs[] = { + {TC_PROC_PTM_DIR, 0, NULL, 1}, + {"mem", 0644, &mem_proc_fops, 0}, +@@ -2077,7 +2064,7 @@ static ssize_t atm_cfg_proc_write(struct + + priv = (struct atm_priv *)PDE_DATA(file_inode(file)); + +- if (!access_ok(VERIFY_READ, buf, count)) ++ if (!access_ok(buf, count)) + return -EFAULT; + + len = count < sizeof(str) ? count : sizeof(str) - 1; +@@ -2119,13 +2106,12 @@ proc_atm_cfg_help: + return count; + } + +-static const struct file_operations atm_cfg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_atm_cfg_seq_open, +- .read = seq_read, +- .write = atm_cfg_proc_write, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops atm_cfg_proc_fops = { ++ .proc_open = proc_read_atm_cfg_seq_open, ++ .proc_read = seq_read, ++ .proc_write = atm_cfg_proc_write, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static ssize_t proc_write_atm_wanmib(struct file *file, const char __user *buf, +@@ -2173,13 +2159,12 @@ static int proc_read_atm_wanmib_seq_open + + + +-static const struct file_operations atm_wanmib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_atm_wanmib_seq_open, +- .read = seq_read, +- .write = proc_write_atm_wanmib, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops atm_wanmib_proc_fops = { ++ .proc_open = proc_read_atm_wanmib_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_atm_wanmib, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_read_htu_seq_open(struct inode *inode, struct file *file) +@@ -2187,12 +2172,11 @@ static int proc_read_htu_seq_open(struct + return single_open(file, proc_read_htu, PDE_DATA(inode)); + } + +-static const struct file_operations htu_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_htu_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops htu_proc_fops = { ++ .proc_open = proc_read_htu_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_read_queue_seq_open(struct inode *inode, struct file *file) +@@ -2200,12 +2184,11 @@ static int proc_read_queue_seq_open(stru + return single_open(file, proc_read_queue, PDE_DATA(inode)); + } + +-static const struct file_operations queue_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_queue_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops queue_proc_fops = { ++ .proc_open = proc_read_queue_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static void set_q_prio(struct atm_priv *priv, +@@ -2428,13 +2411,12 @@ static const struct seq_operations pvc_m + .show = pvc_mib_seq_show, + }; + +-static const struct file_operations atm_prio_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_atm_read_prio_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = proc_atm_write_prio, +- .release = single_release, ++static const struct proc_ops atm_prio_proc_fops = { ++ .proc_open = proc_atm_read_prio_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = proc_atm_write_prio, ++ .proc_release = single_release, + }; + + static int proc_read_pvc_mib_seq_open(struct inode *inode, struct file *file) +@@ -2447,12 +2429,11 @@ static int proc_read_pvc_mib_seq_open(st + return ret; + } + +-static const struct file_operations atm_pvc_mib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_pvc_mib_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = seq_release, ++static const struct proc_ops atm_pvc_mib_proc_fops = { ++ .proc_open = proc_read_pvc_mib_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = seq_release, + }; + + static ssize_t proc_write_cell(struct file *file, +@@ -2592,13 +2573,12 @@ static int proc_read_cell_seq_open(struc + return single_open(file, proc_read_cell, NULL); + } + +-static const struct file_operations atm_cell_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_cell_seq_open, +- .read = seq_read, +- .write = proc_write_cell, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops atm_cell_proc_fops = { ++ .proc_open = proc_read_cell_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_cell, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static struct tc_proc_list atm_procs[] = { diff --git a/package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch b/package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch new file mode 100644 index 00000000000..793adefdd65 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch @@ -0,0 +1,1356 @@ +The existing software receive and transmit path does not actually work. +This replaces it by a basic working implementation. + +--- a/dcdp/atm_tc.c ++++ b/dcdp/atm_tc.c +@@ -603,7 +603,11 @@ static void atm_aca_init(struct atm_priv + cfg = &priv->tc_priv->cfg; + + txin = ¶m.aca_txin; ++#if defined(__LITTLE_ENDIAN) ++ txin->byteswap = 0; ++#else + txin->byteswap = 1; ++#endif + txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; + txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); + txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; +@@ -625,7 +629,11 @@ static void atm_aca_init(struct atm_priv + txin->soc_cmlt_cnt_addr); + + txout = ¶m.aca_txout; ++#if defined(__LITTLE_ENDIAN) ++ txout->byteswap = 0; ++#else + txout->byteswap = 1; ++#endif + txout->hd_size_in_dw = cfg->txout.soc_desc_dwsz; + txout->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_OUT_PD_LIST_BASE); + txout->pd_desc_num = __ACA_TX_OUT_PD_LIST_NUM; +@@ -647,7 +655,11 @@ static void atm_aca_init(struct atm_priv + txout->soc_cmlt_cnt_addr); + + rxout = ¶m.aca_rxout; ++#if defined(__LITTLE_ENDIAN) ++ rxout->byteswap = 0; ++#else + rxout->byteswap = 1; ++#endif + rxout->hd_size_in_dw = cfg->rxout.soc_desc_dwsz; + rxout->pd_desc_base = SB_XBAR_ADDR(__ACA_RX_OUT_PD_LIST_BASE); + rxout->pd_desc_num = __ACA_RX_OUT_PD_LIST_NUM; +@@ -669,7 +681,11 @@ static void atm_aca_init(struct atm_priv + rxout->soc_cmlt_cnt_addr); + + rxin = ¶m.aca_rxin; ++#if defined(__LITTLE_ENDIAN) ++ rxin->byteswap = 0; ++#else + rxin->byteswap = 1; ++#endif + rxin->hd_size_in_dw = cfg->rxin.soc_desc_dwsz; + rxin->pd_desc_base = SB_XBAR_ADDR(__RX_IN_PD_DES_LIST_BASE); + rxin->pd_desc_num = __ACA_RX_IN_PD_LIST_NUM; +@@ -1261,7 +1277,7 @@ static int ppe_ioctl(struct atm_dev *dev + static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) + { + int ret, qid, mpoa_pt, mpoa_type, vid; +- unsigned int prio, conn; ++ unsigned int prio, conn, len; + struct atm_priv *priv; + + if (!vcc) { +@@ -1327,12 +1343,14 @@ static int ppe_send(struct atm_vcc *vcc, + tc_dbg(priv->tc_priv, MSG_TX, "vid: 0x%x, qid: 0x%x\n", + vid, qid); + ++ len = skb->len; ++ + if (priv->tc_priv->tc_ops.send(NULL, + skb, qid, ATM_SL_PKT) == 0) { + priv->stats.aal5_tx_pkts++; +- priv->stats.aal5_tx_bytes += skb->len; ++ priv->stats.aal5_tx_bytes += len; + priv->conn[conn].stats.aal5_tx_pkts++; +- priv->conn[conn].stats.aal5_tx_bytes += skb->len; ++ priv->conn[conn].stats.aal5_tx_bytes += len; + priv->conn[conn].prio_tx_packets[prio]++; + } else { + tc_dbg(priv->tc_priv, MSG_TX, "ATM: TX fail\n"); +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -497,6 +497,7 @@ static int ptm_xmit(struct sk_buff *skb, + struct ptm_priv *ptm_tc = netdev_priv(dev); + int qid; + enum tc_pkt_type type; ++ unsigned int len; + + if (!showtime_stat(ptm_tc->tc_priv)) + goto PTM_XMIT_DROP; +@@ -510,11 +511,13 @@ static int ptm_xmit(struct sk_buff *skb, + type = ptm_tc->tc_priv->tc_mode == TC_PTM_BND_MODE + ? PTM_BOND_PKT : PTM_SL_PKT; + ++ len = skb->len; ++ + if (ptm_tc->tc_priv->tc_ops.send(dev, skb, qid, type) < 0) + ptm_tc->stats64.tx_dropped++; + else { + ptm_tc->stats64.tx_packets++; +- ptm_tc->stats64.tx_bytes += skb->len; ++ ptm_tc->stats64.tx_bytes += len; + } + + return 0; +@@ -631,7 +634,7 @@ static int ptm_dev_init(struct tc_priv * + const char macaddr[ETH_ALEN] + = {0xAC, 0x9A, 0x96, 0x11, 0x22, 0x33}; + +- dev = alloc_netdev_mq(sizeof(*ptm_tc), "dsl%d", NET_NAME_ENUM, ptm_setup, 4); ++ dev = alloc_netdev(sizeof(*ptm_tc), "dsl%d", NET_NAME_ENUM, ptm_setup); + if (!dev) { + tc_dbg(tc_priv, MSG_INIT, "Cannot alloc net device\n"); + return -ENOMEM; +@@ -2324,7 +2327,11 @@ static void ptm_aca_init(struct ptm_ep_p + cfg = &priv->tc_priv->cfg; + + txin = ¶m.aca_txin; ++#if defined(__LITTLE_ENDIAN) ++ txin->byteswap = 0; ++#else + txin->byteswap = 1; ++#endif + txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; + txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); + txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; +@@ -2347,7 +2354,11 @@ static void ptm_aca_init(struct ptm_ep_p + txin->soc_cmlt_cnt_addr); + + txout = ¶m.aca_txout; ++#if defined(__LITTLE_ENDIAN) ++ txout->byteswap = 0; ++#else + txout->byteswap = 1; ++#endif + txout->hd_size_in_dw = cfg->txout.soc_desc_dwsz; + if (priv->tc_priv->param.cdma_desc_loc == LOC_IN_FPI) + txout->pd_desc_base = sb_r32(__TX_OUT_SHADOW_PTR) - phybase; +@@ -2373,7 +2384,11 @@ static void ptm_aca_init(struct ptm_ep_p + txout->soc_cmlt_cnt_addr); + + rxout = ¶m.aca_rxout; ++#if defined(__LITTLE_ENDIAN) ++ rxout->byteswap = 0; ++#else + rxout->byteswap = 1; ++#endif + rxout->hd_size_in_dw = cfg->rxout.soc_desc_dwsz; + if (priv->tc_priv->param.cdma_desc_loc == LOC_IN_FPI) + rxout->pd_desc_base = sb_r32(__RX_OUT_SHADOW_PTR) - phybase; +@@ -2399,7 +2414,11 @@ static void ptm_aca_init(struct ptm_ep_p + rxout->soc_cmlt_cnt_addr); + + rxin = ¶m.aca_rxin; ++#if defined(__LITTLE_ENDIAN) ++ rxin->byteswap = 0; ++#else + rxin->byteswap = 1; ++#endif + rxin->hd_size_in_dw = cfg->rxin.soc_desc_dwsz; + rxin->pd_desc_base = SB_XBAR_ADDR(__RX_IN_PD_DES_LIST_BASE); + rxin->pd_desc_num = __ACA_RX_IN_PD_LIST_NUM; +--- a/dcdp/platform/sw_plat.c ++++ b/dcdp/platform/sw_plat.c +@@ -36,10 +36,13 @@ + #include + #include + #include +-#include "inc/dsl_tc.h" ++#include "../inc/dsl_tc.h" + + #include "../inc/tc_main.h" + #include "../inc/reg_addr.h" ++#include "../inc/tc_common.h" ++ ++#include "../inc/fw/vrx518_addr_def.h" + + + #define PMAC_SIZE 8 +@@ -70,7 +73,7 @@ enum { + #define TXIN_DNUM 128 + #define TXOUT_DNUM 128 + #define RXOUT_DNUM 1024 +-#define RXIN_DNUM 1024 ++#define RXIN_DNUM 0 + + #define TXIN_CHECK_NUM 32 + +@@ -80,22 +83,32 @@ struct aca_ring { + void *umt_dst; + u32 umt_phydst; + u32 dnum; ++ u32 dsize; + int idx; /* SoC RX/TX index */ +- int cnt; +- void *cnt_addr; +- u32 cnt_phyaddr; + int ep_dev_idx; + }; + ++struct tx_list_item { ++ size_t len; ++ void *buf; ++ dma_addr_t phyaddr; ++}; ++ ++struct tx_list { ++ struct tx_list_item *data; ++ u32 dnum; ++}; ++ + struct aca_ring_grp { + struct aca_ring rxin; + struct aca_ring txin; + struct aca_ring rxout; + struct aca_ring txout; ++ struct tx_list txlist; + }; + +-#if 1 +-struct dma_desc { ++#if defined(__LITTLE_ENDIAN) ++struct dma_tx_desc { + /* DW 0 */ + u32 qid; + /* DW 1 */ +@@ -112,8 +125,26 @@ struct dma_desc { + u32 c:1; + u32 own:1; + }__packed; ++ ++struct dma_rx_desc { ++ /* DW 0 */ ++ u32 qid; ++ /* DW 1 */ ++ u32 res2; ++ /* DW 2 */ ++ u32 data_len:16; ++ u32 res0:7; ++ u32 byte_off:3; ++ u32 res1:2; ++ u32 eop:1; ++ u32 sop:1; ++ u32 c:1; ++ u32 own:1; ++ /* DW 3 */ ++ u32 data_ptr; ++}__packed; + #else +-struct dma_desc { ++struct dma_tx_desc { + /* DW 0 */ + u32 qid; + /* DW 1 */ +@@ -131,14 +162,25 @@ struct dma_desc { + u32 data_len:16; + }__packed; + ++struct dma_rx_desc { ++ /* DW 0 */ ++ u32 qid; ++ /* DW 1 */ ++ u32 res; ++ /* DW 2 */ ++ u32 own:1; ++ u32 c:1; ++ u32 sop:1; ++ u32 eop:1; ++ u32 res1:2; ++ u32 byte_off:3; ++ u32 res0:7; ++ u32 data_len:16; ++ /* DW 3 */ ++ u32 data_ptr; ++}__packed; + #endif + +-struct plat_dma { +- u32 chan; /* CHAN IID */ +- u32 dma_chan; /* CONTROLLER/PORT/CHAN ID */ +- u32 ds_dnum; /* DS descriptor number */ +-}; +- + struct plat_umt { + u32 id; + u32 cbm_id; +@@ -152,28 +194,28 @@ struct tc_req { + enum dsl_tc_mode tc_mode; + }; + +-#if 0 +-struct tc_coc { +- enum ltq_cpufreq_state coc_stat; +- struct tasklet_struct coc_task; ++struct mem_map_entry { ++ dma_addr_t phyaddr; ++ void *mem; ++ size_t size; ++ struct hlist_node node; + }; +-#endif + + struct plat_priv { + struct tc_priv *tc_priv; + struct plat_umt umt[EP_MAX_NUM]; +- struct plat_dma dma[EP_MAX_NUM]; + struct ltq_mei_atm_showtime_info dsl_ops; + struct tc_req req_work; + struct aca_ring_grp soc_rings; +- /* struct tc_coc coc;*/ ++ struct net_device *netdev; ++ DECLARE_HASHTABLE(mem_map, 8); + }; + + static struct plat_priv *g_plat_priv; + struct tasklet_struct txout_task; + struct tasklet_struct rxout_task; + +-static void txout_action(struct tc_priv *priv, struct aca_ring *txout); ++static DEFINE_SPINLOCK(tx_spinlock); + + void *ppa_callback_get(e_ltq_mei_cb_type type) + { +@@ -259,122 +301,65 @@ static inline struct tc_priv *plat_to_tc + return g_plat_priv->tc_priv; + } + +-static int32_t plat_rx(struct net_device *rxdev, struct net_device *txdev, +- struct sk_buff *skb, int32_t len) +-{ +- int32_t err; +- struct tc_priv *tc_priv = plat_to_tcpriv(); +- +- if (unlikely(!rxdev)) { +- if (txdev != NULL) +- tc_dbg(tc_priv, MSG_RX, +- "Recv undelivered packet from DP lib\n"); +- else +- tc_dbg(tc_priv, MSG_RX, "Recv unknown packet\n"); +- err = -ENODEV; +- goto err1; +- } +- +- tc_priv->tc_ops.recv(rxdev, skb); +- return 0; +- +-err1: +- dev_kfree_skb_any(skb); +- +- return err; +-} +- +-#if 0 +-static int32_t plat_get_subifid(struct net_device *dev, struct sk_buff *skb, +- void *subif_data, uint8_t dst_mac[MAX_ETH_ALEN], +- dp_subif_t *subif, uint32_t flags) +-{ +- int qid; +- struct tc_priv *priv = plat_to_tcpriv(); +- +- qid = priv->tc_ops.get_qid(dev, skb, subif_data, flags); +- if (qid < 0) +- return qid; +- else +- subif->subif = qid; +- +- return 0; +-} +-#endif +- +-#if 0 +-static void plat_coc_tasklet(unsigned long arg) +-{ +- /* change state to D0 */ +- if (g_plat_priv->coc.coc_stat == LTQ_CPUFREQ_PS_D0) +- return; +- +- g_plat_priv->coc.coc_stat = LTQ_CPUFREQ_PS_D0; +-} +- +-static void plat_coc_req(void) +-{ +- tasklet_schedule(&g_plat_priv->coc.coc_task); +-} ++static void *plat_mem_alloc(size_t size, enum tc_dir dir, u32 *phyaddr); ++static void *plat_mem_virt(u32 phyaddr); ++static void plat_mem_free(u32 phyaddr, enum tc_dir dir); + ++static void txlist_free(struct tx_list *list); + +-static int32_t plat_coc_stat(enum ltq_cpufreq_state new_state, +- enum ltq_cpufreq_state old_state, uint32_t flags) ++static int txlist_init(struct tx_list *list, u32 dnum) + { +- struct tc_priv *priv = plat_to_tcpriv(); +- tc_dbg(priv, MSG_COC, +- "COC current state: %d, new state: %d, old state: %d\n", +- g_plat_priv->coc.coc_stat, new_state, old_state); ++ struct tx_list_item *item; ++ int i; + +- if (g_plat_priv->coc.coc_stat != new_state) { +- g_plat_priv->coc.coc_stat = new_state; ++ list->dnum = dnum; + +- if (new_state == LTQ_CPUFREQ_PS_D3) { +- /* Enable interrupt for DS packet */ +- priv->tc_ops.irq_on(MBOX_PKT_RX); +- } else { +- /* Disable interrupt for DS packet */ +- priv->tc_ops.irq_off(MBOX_PKT_RX); ++ list->data = kcalloc(dnum, sizeof(struct tx_list_item), GFP_KERNEL); ++ if (!list->data) { ++ pr_err("Failed to allocate TX list!\n"); ++ goto err; ++ } ++ ++ for (i = 0; i < list->dnum; i++) { ++ item = &list->data[i]; ++ ++ // use plat_mem_alloc as these buffers will be mixed with buffers allocated in ptm_tc.c / atm_tc.c ++ item->buf = plat_mem_alloc(DMA_PACKET_SZ, US_DIR, &item->phyaddr); ++ if (!item->buf) { ++ pr_err("Failed to allocate TX buffer!\n"); ++ goto err; + } + } + + return 0; +-} +-#endif +- +-static inline int ring_dist(int idx1, int idx2, int size) +-{ +- if (idx1 >= idx2) +- return (idx1 - idx2); +- else +- return (idx1 + size - idx2); +-} + +-static inline int __ring_full(int idx, int cnt, u32 dnum) +-{ +- if (ring_dist(idx, cnt, dnum) < dnum - 1) +- return 0; +- else +- return 1; ++err: ++ txlist_free(list); ++ return -1; + } + +-static inline int ring_full(struct aca_ring *ring) ++static void txlist_free(struct tx_list *list) + { +- if (!__ring_full(ring->idx, ring->cnt, ring->dnum)) +- return 0; ++ struct tx_list_item *item; ++ int i; + +- /* if ring full, update cumulative counter and check again */ +- ring->cnt = readl(ring->cnt_addr) % ring->dnum; ++ if (list->data) { ++ for (i = 0; i < list->dnum; i++) { ++ item = &list->data[i]; ++ ++ if (item->buf) { ++ // use plat_mem_free as these buffers are mixed with buffers allocated in ptm_tc.c / atm_tc.c ++ plat_mem_free(item->phyaddr, US_DIR); ++ } ++ } ++ } + +- return __ring_full(ring->idx, ring->cnt, ring->dnum); ++ kfree(list->data); + } + +-#define ring_idx_inc(ring, idx) \ +- do { ring->idx = (ring->idx + 1) % ring->dnum; } while (0); +- +-static inline void ring_cnt_update(struct aca_ring *ring) ++static inline void ring_idx_inc(struct aca_ring *ring) + { +- ring->cnt = readl(ring->cnt_addr) % ring->dnum; ++ ring->idx = (ring->idx + 1) % ring->dnum; + } + + static struct sk_buff *txin_skb_prepare(struct sk_buff *skb) +@@ -399,252 +384,220 @@ static struct sk_buff *txin_skb_prepare( + return nskb; + } + +-static int ring_mmap(void *mem, int size, +- enum dma_data_direction dir, u32 *addr) +-{ +- struct device *pdev; +- dma_addr_t phy_addr; +- struct tc_priv *priv; +- u32 addr1; +- +- priv = g_plat_priv->tc_priv; +- pdev = priv->ep_dev[0].dev; +- +- phy_addr = dma_map_single(pdev, mem, size, dir); +- if (unlikely(dma_mapping_error(pdev, phy_addr))) { +- tc_err(priv, MSG_INIT, +- "DMA address mapping error: buf: 0x%x, size: %d, dir: %d\n", +- (u32)mem, size, dir); +- return -ENOMEM; +- } +- dma_unmap_single(pdev, phy_addr, size, dir); +- +- pr_info("vaddr: 0x%x, phyaddr: 0x%lx\n", (u32)mem, phy_addr); +- addr1 = (u32)phy_addr; +- +- if (addr) +- *addr = addr1; +- +- return 0; +-} +- +-static void txin_action(struct tc_priv *priv, struct aca_ring *txin, ++static int txin_action(struct tc_priv *priv, struct aca_ring *txin, + struct sk_buff *skb, int qid, enum tc_pkt_type type) + { +- struct dma_desc *desc, desc1; +- u32 phyaddr, *dst, *src; +- int i; ++ struct device *pdev = priv->ep_dev[0].dev; ++ struct aca_ring *txout = &g_plat_priv->soc_rings.txout; ++ struct tx_list *txlist = &g_plat_priv->soc_rings.txlist; ++ struct dma_tx_desc *desc; ++ struct tx_list_item *txlist_item; ++ unsigned long flags; ++ ++ if (!g_plat_priv->netdev) { ++ spin_lock_irqsave(&tx_spinlock, flags); ++ } + +- if (ring_full(txin)) { +- tc_dbg(priv, MSG_TX, +- "TXIN Ring Full!: idx: %d, cnt: %d\n", +- txin->idx, txin->cnt); ++ if ((txin->idx + 2) % txin->dnum == txout->idx) { ++ if (g_plat_priv->netdev) { ++ netif_stop_queue(g_plat_priv->netdev); ++ } ++ } else if ((txin->idx + 1) % txin->dnum == txout->idx) { ++ tc_err(priv, MSG_TX, "TXIN ring full: txin: %d, txout: %d\n", ++ txin->idx, txout->idx); + goto err1; + } + ++ desc = (struct dma_tx_desc *)txin->dbase_mem; ++ desc += txin->idx; ++ ++ txlist_item = &txlist->data[txin->idx]; ++ + skb = txin_skb_prepare(skb); + if (!skb) +- return; ++ goto err2; + +- if (ring_mmap(skb->data, skb->len, DMA_TO_DEVICE, &phyaddr) < 0) { +- tc_err(priv, MSG_TX, "TXIN data mmap failed: 0x%x\n", +- (unsigned int)skb->data); +- goto err1; +- } ++ /* ++ * Copy the data to a buffer in the driver. This is necessary because there doesn't seem to be a timely signal ++ * from the device when it has consumed a buffer, which would allow to safely free it. The data_ptr is only ++ * returned in TXOUT after another fixed number of packets (depending on the size of internal buffers) has been ++ * transmitted, which may not happen in the near future. Making a copy allows to free the SKB here. ++ */ ++ memcpy(txlist_item->buf, skb->data, skb->len); + +- /* init a new descriptor for the new skb */ +- desc = (struct dma_desc *)txin->dbase_mem; +- desc += txin->idx; ++ dma_sync_single_range_for_device(pdev, txlist_item->phyaddr, 0, skb->len, DMA_TO_DEVICE); + +- memset(desc, 0, sizeof(*desc)); +- memset(&desc1, 0, sizeof(desc1)); +- desc1.own = 1; +- desc1.c = 1; +- desc1.sop = 1; +- desc1.eop = 1; +- desc1.byte_off = phyaddr & 0x7; +- desc1.data_len = skb->len; +- +- desc1.data_ptr = phyaddr & (~(0x7)); +- desc1.qid = qid; +- +- dst = (u32 *)desc; +- src = (u32 *)&desc1; +- for (i = 0; i < DW_SZ(desc1); i++) +- dst[i] = cpu_to_be32(src[i]); +- +- pr_info("txin idx: %d\n", txin->idx); +- pr_info("descriptor dst val:(DW0-DW3): 0x%x, 0x%x, 0x%x, 0x%x\n", +- dst[0], dst[1], dst[2], dst[3]); +- pr_info("descriptor src val: (DW0-DW3): 0x%x, 0x%x, 0x%x, 0x%x\n", +- src[0], src[1], src[2], src[3]); +- +- if (ring_mmap(desc, sizeof(*desc), DMA_TO_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_TX, "TXIN descriptor mmap failed: 0x%x\n", +- (unsigned int)desc); ++ // this should never happen, the buffers are already aligned by kmalloc ++ if (WARN_ON((txlist_item->phyaddr & 0x7) != 0)) + goto err1; ++ ++ if (g_plat_priv->netdev) { ++ netdev_sent_queue(g_plat_priv->netdev, skb->len); + } ++ txlist_item->len = skb->len; ++ ++ memset(desc, 0, sizeof(*desc)); + +- ring_idx_inc(txin, idx); ++ desc->data_ptr = txlist_item->phyaddr; ++ desc->byte_off = 0; ++ desc->data_len = skb->len; ++ desc->qid = qid; ++ ++ desc->sop = 1; ++ desc->eop = 1; ++ desc->c = 0; ++ desc->own = 1; ++ ++ dev_consume_skb_any(skb); ++ ++ ring_idx_inc(txin); + + /* update TXIN UMT by 1 */ + writel(1, txin->umt_dst); +- pr_info("TXIN send txin packet 1 packet\n"); + +- /* Free skb */ +- dev_kfree_skb_any(skb); ++ if (!g_plat_priv->netdev) { ++ spin_unlock_irqrestore(&tx_spinlock, flags); ++ } + +- /* check txout for testing*/ +- //txout_action(plat_to_tcpriv(), &g_plat_priv->soc_rings.txout); +- return; ++ return 0; + + err1: +- //skb->delay_free = 0; + dev_kfree_skb_any(skb); ++ ++err2: ++ if (!g_plat_priv->netdev) { ++ spin_unlock_irqrestore(&tx_spinlock, flags); ++ } ++ ++ return -1; + } + + static void txout_action(struct tc_priv *priv, struct aca_ring *txout) + { +- int i, cnt; +- struct dma_desc *desc; +- u32 ptr; +- void *mem; +- +- ring_cnt_update(txout); +- cnt = ring_dist(txout->idx, txout->cnt, txout->dnum); ++ struct aca_ring *txin = &g_plat_priv->soc_rings.txin; ++ struct tx_list *txlist = &g_plat_priv->soc_rings.txlist; ++ struct tx_list_item *txlist_item; ++ int i, cnt, bytes; ++ u32 *desc; ++ unsigned long flags; ++ ++ cnt = 0; ++ bytes = 0; ++ ++ if (g_plat_priv->netdev) { ++ netif_tx_lock(g_plat_priv->netdev); ++ } else { ++ spin_lock_irqsave(&tx_spinlock, flags); ++ } + +- for (i = 0; i < cnt; i++) { ++ for (i = 0; i < txout->dnum; i++) { + desc = txout->dbase_mem; + desc += txout->idx; +- /* read from memory */ +- if (ring_mmap(desc, sizeof(*desc), DMA_FROM_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_TX, +- "map TXOUT DMA descriptor failed\n"); +- continue; ++ ++ // *desc seems to be a pointer to a QoSQ buffer or the data_ptr of some previously sent packet ++ if (*desc == 0) { ++ break; + } +- ptr = desc->data_ptr + desc->byte_off; +- mem = (void * __force)__va(ptr); +- kfree(mem); +- ring_idx_inc(txout, idx); +- } + +- if (cnt) +- writel(cnt, txout->umt_dst); +- pr_info("TXOUT received %d descriptors\n", cnt); +-} ++ if (txout->idx == txin->idx) { ++ tc_err(priv, MSG_TX, "TXOUT unexpected non-zero descriptor: txin: %d, txout: %d\n", ++ txin->idx, txout->idx); ++ break; ++ } + +-static void rxin_action(struct tc_priv *priv, +- struct aca_ring *rxin, int size, int cnt) +-{ +- int i, dist; +- struct dma_desc *desc; +- void *data_ptr; +- u32 phyaddr; +- +- if (ring_full(rxin)) { +- tc_dbg(priv, MSG_RX, +- "RXIN Ring Full!: idx: %d, cnt: %d\n", +- rxin->idx, rxin->cnt); +- return; +- } ++ txlist_item = &txlist->data[txout->idx]; + +- dist = ring_dist(rxin->idx, rxin->cnt, rxin->dnum); +- if (cnt > dist) { +- WARN_ONCE(1, "RXIN NO enough room for free buffers: free: %d, room: %d\n", +- cnt, dist); +- cnt = dist; ++ cnt++; ++ bytes += txlist_item->len; ++ ++ /* ++ * Reuse the returned buffer. The previous buffer should still be referenced by another descriptor. ++ * When the driver is unloaded, all buffers in the txlist as well as those referenced by the ++ * descriptors managed in ptm_tc.c or atm_tc.c will be freed. ++ */ ++ txlist_item->buf = plat_mem_virt(*desc); ++ txlist_item->phyaddr = *desc; ++ ++ *desc = 0; ++ ++ ring_idx_inc(txout); + } + +- for (i = 0; i < cnt; i++) { +- data_ptr = kmalloc(size, GFP_ATOMIC); +- if (!data_ptr) { +- tc_err(priv, MSG_RX, +- "RXIN kmalloc data buffer failed: %d\n", size); +- goto err1; +- } ++ if (cnt) { ++ writel(cnt, txout->umt_dst+0x28); // TXOUT_HD_ACCUM_SUB instead of TXOUT_HD_ACCUM_ADD + +- if (ring_mmap(data_ptr, size, DMA_FROM_DEVICE, &phyaddr) < 0) { +- tc_err(priv, MSG_RX, +- "RXIN kmalloc data buffer failed: %d\n", size); +- goto err2; ++ if (g_plat_priv->netdev) { ++ netdev_completed_queue(g_plat_priv->netdev, cnt, bytes); + } ++ } + +- desc = (struct dma_desc *)rxin->dbase_mem; +- desc += rxin->idx; +- memset(desc, 0, sizeof(*desc)); +- +- desc->data_len = size; +- desc->byte_off = phyaddr & 0x7; +- desc->eop = 1; +- desc->sop = 1; +- desc->own = 1; +- +- desc->data_ptr = phyaddr; +- +- +- if (ring_mmap(desc, sizeof(*desc), DMA_TO_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_RX, "RXIN descriptor mmap failed: 0x%x\n", +- (unsigned int)desc); +- goto err2; +- } +- +- ring_idx_inc(rxin, idx); ++ if (g_plat_priv->netdev) { ++ netif_tx_unlock(g_plat_priv->netdev); ++ } else { ++ spin_unlock_irqrestore(&tx_spinlock, flags); + } + +- /* update RXIN UMT*/ +- writel(i, rxin->umt_dst); +- pr_info("rxin refill %d descriptors\n", i); +- return; ++ if (cnt && g_plat_priv->netdev && netif_queue_stopped(g_plat_priv->netdev)) { ++ netif_wake_queue(g_plat_priv->netdev); ++ } ++} + +-err2: +- kfree(data_ptr); +-err1: +- if (i) +- writel(i, rxin->umt_dst); +- return; ++static void rxin_action(struct tc_priv *priv, ++ struct aca_ring *rxin, int size, int cnt) ++{ ++ /* update RXIN UMT*/ ++ writel(cnt, rxin->umt_dst); + } + + static int rxout_action(struct tc_priv *priv, struct aca_ring *rxout) + { ++ struct device *pdev = priv->ep_dev[0].dev; + int i, cnt; +- struct dma_desc *desc; +- u32 ptr; +- void *mem; ++ struct dma_rx_desc *desc; ++ dma_addr_t phyaddr; ++ void *ptr, *dst; ++ size_t len; + struct sk_buff *skb; + +- ring_cnt_update(rxout); +- cnt = ring_dist(rxout->idx, rxout->cnt, rxout->dnum); +- +- for (i = 0; i < cnt; i++) { ++ cnt = 0; ++ for (i = 0; i < rxout->dnum; i++) { + desc = rxout->dbase_mem; + desc += rxout->idx; + +- /* read from memory */ +- if (ring_mmap(desc, sizeof(*desc), DMA_FROM_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_RX, +- "map RXOUT DMA descriptor failed\n"); +- continue; ++ if (!desc->own) { ++ break; + } +- ptr = desc->data_ptr + desc->byte_off; +- mem = __va(ptr); +- skb = build_skb(mem, 0); +- if (!skb) { +- tc_err(priv, MSG_RX, +- "RXOUT build skb failed\n"); +- kfree(mem); +- continue; ++ ++ // this seems to be a pointer to a DS PKT buffer ++ phyaddr = desc->data_ptr + desc->byte_off; ++ ptr = plat_mem_virt(phyaddr); ++ ++ len = desc->data_len; ++ ++ dma_sync_single_range_for_cpu(pdev, phyaddr, 0, len, DMA_FROM_DEVICE); ++ ++ skb = netdev_alloc_skb(g_plat_priv->netdev, len); ++ if (unlikely(!skb)) { ++ tc_err(priv, MSG_RX, "RXOUT SKB allocation failed\n"); ++ break; + } +- priv->tc_ops.recv(NULL, skb); +- ring_idx_inc(rxout, idx); ++ ++ dst = skb_put(skb, len); ++ memcpy(dst, ptr, len); ++ ++ priv->tc_ops.recv(g_plat_priv->netdev, skb); ++ ++ desc->own = 0; ++ ++ cnt++; ++ ring_idx_inc(rxout); + } + + if (!cnt) +- tc_err(priv, MSG_RX, "RXOUT dummy interrupt: dbase: 0x%x, idx: %d, cnt: %d\n", +- (unsigned int)rxout->dbase_mem, rxout->idx, rxout->cnt); ++ tc_err(priv, MSG_RX, "RXOUT spurious interrupt\n"); + else +- writel(cnt, rxout->umt_dst); ++ writel(cnt, rxout->umt_dst+0x28); // RXOUT_HD_ACCUM_SUB instead of RXOUT_HD_ACCUM_ADD + +- pr_info("txout received %d packets\n", cnt); + return cnt; + } + +@@ -669,7 +622,6 @@ static void plat_rxout_tasklet(unsigned + struct aca_ring *rxin = &priv->soc_rings.rxin; + struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[rxout->ep_dev_idx]; + int cnt; +- + + cnt = rxout_action(tcpriv, rxout); + if (cnt) +@@ -687,68 +639,144 @@ static int plat_send(struct net_device * + { + struct plat_priv *priv = g_plat_priv; + struct aca_ring *txin = &priv->soc_rings.txin; ++ int res; + +- txin_action(priv->tc_priv, txin, skb, qid, type); ++ res = txin_action(priv->tc_priv, txin, skb, qid, type); + +- return 0; ++ return res; ++} ++ ++static void plat_mem_init(void) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ ++ hash_init(priv->mem_map); + } + + /* return virtual address */ +-static void *plat_mem_alloc(size_t size, enum tc_dir dir) ++static void *plat_mem_alloc(size_t size, enum tc_dir dir, u32 *phyaddr) + { +- return kmalloc(size, GFP_KERNEL); ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = priv->tc_priv; ++ struct device *pdev = tcpriv->ep_dev[0].dev; ++ enum dma_data_direction dma_dir; ++ struct mem_map_entry *entry; ++ ++ entry = kzalloc(sizeof(struct mem_map_entry), GFP_KERNEL); ++ if (!entry) ++ goto err; ++ ++ entry->size = size; ++ ++ entry->mem = kmalloc(size, GFP_KERNEL); ++ if (!entry->mem) ++ goto err_alloc; ++ ++ dma_dir = (dir == DS_DIR) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ ++ entry->phyaddr = dma_map_single(pdev, entry->mem, entry->size, dma_dir); ++ if (unlikely(dma_mapping_error(pdev, entry->phyaddr))) { ++ tc_err(priv, MSG_INIT, ++ "plat_mem_alloc: DMA mapping error: buf: 0x%x, size: %d, dir: %d\n", ++ (u32)entry->mem, size, dir); ++ ++ goto err_map; ++ } ++ ++ hash_add(g_plat_priv->mem_map, &entry->node, entry->phyaddr); ++ ++ *phyaddr = entry->phyaddr; ++ return entry->mem; ++ ++err_map: ++ kfree(entry->mem); ++ ++err_alloc: ++ kfree(entry); ++ ++err: ++ return NULL; + } + +-static void plat_mem_free(u32 phy_addr, enum tc_dir dir) ++static void *plat_mem_virt(u32 phyaddr) + { +- void *mem; ++ struct mem_map_entry *entry; ++ ++ hash_for_each_possible(g_plat_priv->mem_map, entry, node, phyaddr) ++ if (entry->phyaddr == phyaddr) ++ return entry->mem; ++ ++ WARN_ON(1); ++ return NULL; ++} ++ ++static struct mem_map_entry *plat_mem_entry(u32 phyaddr) ++{ ++ struct mem_map_entry *entry; ++ ++ hash_for_each_possible(g_plat_priv->mem_map, entry, node, phyaddr) ++ if (entry->phyaddr == phyaddr) ++ return entry; + +- mem = (void * __force)__va(phy_addr); +- kfree(mem); ++ return NULL; + } + +-static void aca_soc_ring_init(struct tc_priv *priv, +- struct aca_ring *ring, u32 dnum, u32 dsize) ++static void plat_mem_free(u32 phyaddr, enum tc_dir dir) + { ++ struct tc_priv *priv = g_plat_priv->tc_priv; ++ struct device *pdev = priv->ep_dev[0].dev; ++ enum dma_data_direction dma_dir; ++ struct mem_map_entry *entry; ++ ++ entry = plat_mem_entry(phyaddr); ++ if (WARN_ON(!entry)) ++ return; ++ ++ hash_del(&entry->node); ++ ++ dma_dir = (dir == DS_DIR) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ dma_unmap_single(pdev, entry->phyaddr, entry->size, dma_dir); ++ ++ kfree(entry->mem); ++ ++ kfree(entry); ++} ++ ++static int ring_init(struct tc_priv *priv, struct aca_ring *ring, u32 dnum, u32 dsize) ++{ ++ struct device *pdev = priv->ep_dev[0].dev; + int size; +- struct device *pdev; + + memset(ring, 0, sizeof(*ring)); + ring->dnum = dnum; ++ ring->dsize = dsize; ++ ++ if (ring->dnum == 0) { ++ return 0; ++ } ++ + size = dsize * dnum; +- pdev = priv->ep_dev[0].dev; + +- ring->dbase_mem = kmalloc(size, GFP_KERNEL); ++ ring->dbase_mem = dma_alloc_coherent(pdev, size, &(ring->dbase_phymem), GFP_KERNEL); + if (!ring->dbase_mem) { +- tc_err(priv, MSG_INIT, "Allocate SoC Ring fail: %d\n", dnum); +- return; ++ tc_err(priv, MSG_INIT, "Ring allocation failed: %d\n", dnum); ++ return -1; + } + +- ring_mmap(ring->dbase_mem, size, DMA_FROM_DEVICE, &(ring->dbase_phymem)); +- tc_dbg(priv, MSG_INIT, "ring: membase: 0x%x, phybase: 0x%x, dnum: %d\n", +- (u32)ring->dbase_mem, ring->dbase_phymem, ring->dnum); +- +- size = sizeof(u32); +- ring->cnt_addr = kzalloc(size, GFP_KERNEL); +- if (!ring->cnt_addr) { +- tc_err(priv, MSG_INIT, "Allocate cumulative counter fail!\n"); +- return; +- } ++ return 0; ++} + +- ring_mmap(ring->cnt_addr, size, DMA_TO_DEVICE, &(ring->cnt_phyaddr)); +- tc_dbg(priv, MSG_INIT, "ring: cumulative cnt addr: 0x%x, phy address: 0x%x\n", +- (u32)ring->cnt_addr, ring->cnt_phyaddr); ++#define ring_dnum(tcpriv, name1, name2) ((!tcpriv->param.name1##_dnum) ? name2##_DNUM : tcpriv->param.name1##_dnum) + +- return; +-} ++static void ring_free(struct tc_priv *priv, struct aca_ring *ring) ++{ ++ struct device *pdev = priv->ep_dev[0].dev; + +-#define ring_init(tcpriv, ring, name1, name2, num, size) \ +-{ \ +- if (!tcpriv->param.name1##_dnum) \ +- num = name2##_DNUM; \ +- else \ +- num = tcpriv->param.name1##_dnum; \ +- aca_soc_ring_init(tcpriv, ring, num, size); \ ++ if (ring->dnum == 0) { ++ return; ++ } ++ ++ dma_free_coherent(pdev, ring->dsize * ring->dnum, ring->dbase_mem, ring->dbase_phymem); + } + + static irqreturn_t aca_rx_irq_handler(int irq, void *dev_id) +@@ -777,39 +805,55 @@ static irqreturn_t aca_tx_irq_handler(in + return IRQ_HANDLED; + } + +-static void irq_init(struct tc_priv *priv, const char *dev_name) ++static void plat_irq_init(struct tc_priv *priv, const char *dev_name) + { + int ret; + int i; +- char name[IFNAMSIZ]; ++ //char name[IFNAMSIZ]; + + for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { +- sprintf(name, "%s%d", dev_name, i); ++ //snprintf(name, sizeof(name), "aca-rxo%d", i); + + ret = devm_request_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_rx_irq, +- aca_rx_irq_handler, 0, name, &priv->ep_dev[i]); ++ aca_rx_irq_handler, 0, "aca-rxo", &priv->ep_dev[i]); + + if (ret) { + tc_err(priv, MSG_INIT, + "ACA RX IRQ request Fail!: irq: %d, ep_id: %d\n", + priv->ep_dev[i].aca_rx_irq, i); + //return; +- } ++ } ++ ++ //snprintf(name, sizeof(name), "aca-txo%d", i); + + ret = devm_request_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_tx_irq, +- aca_tx_irq_handler, 0, name, &priv->ep_dev[i]); ++ aca_tx_irq_handler, 0, "aca-txo", &priv->ep_dev[i]); + + if (ret) { + tc_err(priv, MSG_INIT, + "ACA TX IRQ request Fail!: irq: %d, ep_id: %d\n", + priv->ep_dev[i].aca_tx_irq, i); + //return; +- } ++ } + } + + return; + } + ++static void plat_irq_free(struct tc_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ ++ /* Unregister RX irq handler */ ++ devm_free_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_rx_irq, &priv->ep_dev[i]); ++ ++ /* Unregister TX irq handler */ ++ devm_free_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_tx_irq, &priv->ep_dev[i]); ++ } ++} ++ + /** + * Decide txin/rxout queue size + * Create a tx/rx queue +@@ -819,29 +863,68 @@ static int plat_dp_init(struct plat_priv + struct tc_priv *tcpriv; + struct aca_ring_grp *soc_rings; + struct aca_ring *ring; +- int size; + u32 dnum; ++ int i; ++ int ret = 0; + + tcpriv = priv->tc_priv; + +- size = sizeof(struct dma_desc); ++ plat_mem_init(); ++ + soc_rings = &priv->soc_rings; + + /* txin ring */ + ring = &soc_rings->txin; +- ring_init(tcpriv, ring, txin, TXIN, dnum, size); ++ dnum = ring_dnum(tcpriv, txin, TXIN); ++ ret = txlist_init(&soc_rings->txlist, dnum); ++ if (ret < 0) ++ goto err5; ++ ret = ring_init(tcpriv, ring, dnum, sizeof(struct dma_tx_desc)); ++ if (ret < 0) ++ goto err4; + + /* txout ring */ + ring = &soc_rings->txout; +- ring_init(tcpriv, ring, txout, TXOUT, dnum, size); ++ dnum = ring_dnum(tcpriv, txout, TXOUT); ++ ret = ring_init(tcpriv, ring, dnum, sizeof(u32)); ++ if (ret < 0) ++ goto err3; ++ + /* rxin ring */ + ring = &soc_rings->rxin; +- ring_init(tcpriv, ring, rxin, RXIN, dnum, size); ++ dnum = ring_dnum(tcpriv, rxin, RXIN); ++ ret |= ring_init(tcpriv, ring, dnum, sizeof(struct dma_rx_desc)); ++ if (ret < 0) ++ goto err2; ++ + /* rxout ring */ + ring = &soc_rings->rxout; +- ring_init(tcpriv, ring, rxout, RXOUT, dnum, size); ++ dnum = ring_dnum(tcpriv, rxout, RXOUT); ++ ret = ring_init(tcpriv, ring, dnum, sizeof(struct dma_rx_desc)); ++ if (ret < 0) ++ goto err1; ++ ++ for (i = 0; i < EP_MAX_NUM && i < tcpriv->ep_num; i++) { ++ ++ /* Enable RX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_en(&tcpriv->ep_dev[i], ACA_HOSTIF_RX); ++ ++ /* Enable TX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_en(&tcpriv->ep_dev[i], ACA_HOSTIF_TX); ++ } + + return 0; ++ ++err1: ++ ring_free(tcpriv, &soc_rings->rxin); ++err2: ++ ring_free(tcpriv, &soc_rings->txout); ++err3: ++ ring_free(tcpriv, &soc_rings->txin); ++err4: ++ txlist_free(&soc_rings->txlist); ++err5: ++ return ret; + } + + /** +@@ -850,6 +933,26 @@ static int plat_dp_init(struct plat_priv + */ + static void plat_dp_exit(struct plat_priv *priv) + { ++ struct tc_priv *tcpriv = priv->tc_priv; ++ struct aca_ring_grp *soc_rings = &priv->soc_rings; ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < tcpriv->ep_num; i++) { ++ ++ /* Disable RX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_mask(&tcpriv->ep_dev[i], ACA_HOSTIF_RX); ++ ++ /* Disable TX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_mask(&tcpriv->ep_dev[i], ACA_HOSTIF_TX); ++ } ++ ++ ring_free(tcpriv, &soc_rings->txin); ++ ring_free(tcpriv, &soc_rings->txout); ++ ring_free(tcpriv, &soc_rings->rxin); ++ ring_free(tcpriv, &soc_rings->rxout); ++ ++ txlist_free(&soc_rings->txlist); ++ + return; + } + +@@ -858,45 +961,45 @@ static int plat_soc_cfg_get(struct soc_c + struct plat_priv *priv = g_plat_priv; + + /* TXIN */ +- cfg->txin_dbase = priv->soc_rings.txin.dbase_phymem; +- cfg->txin_dnum = priv->soc_rings.txin.dnum; +- cfg->txin_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->txin_cnt_phyaddr = priv->soc_rings.txin.cnt_phyaddr; ++ cfg->txin.soc_phydbase = priv->soc_rings.txin.dbase_phymem; ++ cfg->txin.soc_dnum = priv->soc_rings.txin.dnum; ++ cfg->txin.soc_desc_dwsz = DW_SZ(struct dma_tx_desc); + /* TXOUT */ +- cfg->txout_dbase = priv->soc_rings.txout.dbase_phymem; +- cfg->txout_dnum = priv->soc_rings.txout.dnum; +- cfg->txout_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->txout_cnt_phyaddr = priv->soc_rings.txout.cnt_phyaddr; ++ cfg->txout.soc_phydbase = priv->soc_rings.txout.dbase_phymem; ++ cfg->txout.soc_dnum = priv->soc_rings.txout.dnum; ++ cfg->txout.soc_desc_dwsz = DW_SZ(u32); + /* RXOUT */ +- cfg->rxout_dbase = priv->soc_rings.rxout.dbase_phymem; +- cfg->rxout_dnum = priv->soc_rings.rxout.dnum; +- cfg->rxout_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->rxout_cnt_phyaddr = priv->soc_rings.rxout.cnt_phyaddr; ++ cfg->rxout.soc_phydbase = priv->soc_rings.rxout.dbase_phymem; ++ cfg->rxout.soc_dnum = priv->soc_rings.rxout.dnum; ++ cfg->rxout.soc_desc_dwsz = DW_SZ(struct dma_rx_desc); + /* RXIN */ +- cfg->rxin_dbase = priv->soc_rings.rxin.dbase_phymem; +- cfg->rxin_dnum = priv->soc_rings.rxin.dnum; +- cfg->rxin_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->rxin_cnt_phyaddr = priv->soc_rings.rxin.cnt_phyaddr; ++ cfg->rxin.soc_phydbase = priv->soc_rings.rxin.dbase_phymem; ++ cfg->rxin.soc_dnum = priv->soc_rings.rxin.dnum; ++ cfg->rxin.soc_desc_dwsz = DW_SZ(struct dma_rx_desc); + + tc_info(priv->tc_priv, MSG_INIT, + "id: %d, txin(0x%x: %d, 0x%x), txout(0x%x: %d, 0x%x), rxin(0x%x: %d, 0x%x), rxout(0x%x: %d, 0x%x)\n", +- id, cfg->txin_dbase, cfg->txin_dnum, cfg->txin_cnt_phyaddr, +- cfg->txout_dbase, cfg->txout_dnum, cfg->txout_cnt_phyaddr, +- cfg->rxin_dbase, cfg->rxout_dnum, cfg->rxin_cnt_phyaddr, +- cfg->rxout_dbase, cfg->rxout_dnum, cfg->rxout_cnt_phyaddr); ++ id, cfg->txin.soc_phydbase, cfg->txin.soc_dnum, cfg->txin.soc_cnt_phyaddr, ++ cfg->txout.soc_phydbase, cfg->txout.soc_dnum, cfg->txout.soc_cnt_phyaddr, ++ cfg->rxin.soc_phydbase, cfg->rxin.soc_dnum, cfg->rxin.soc_cnt_phyaddr, ++ cfg->rxout.soc_phydbase, cfg->rxout.soc_dnum, cfg->rxout.soc_cnt_phyaddr); + + return 0; + } + +-static int plat_open(struct net_device *pdev, char *dev_name, +- int *subif, int flag) ++static int plat_open(struct net_device *pdev, const char *dev_name, ++ int id, int flag) + { ++ g_plat_priv->netdev = pdev; ++ + return 0; + } + +-static void plat_close(struct net_device *pdev, char *dev_name, +- int subif, int flag) ++static void plat_close(struct net_device *pdev, const char *dev_name, ++ int flag) + { ++ g_plat_priv->netdev = NULL; ++ + return; + } + +@@ -971,7 +1074,6 @@ static void plat_disable_us(int en) + static int plat_get_mib(struct net_device *pdev, + struct rtnl_link_stats64 *stat) + { +- pr_info("%s is not supported\n", __func__); + return -ENOTSUPP; + } + +@@ -1181,8 +1283,8 @@ int platform_init(struct tc_priv *tc_pri + INIT_WORK(&priv->req_work.work, plat_tc_req_workqueue); + tasklet_init(&txout_task, plat_txout_tasklet, 0); + tasklet_init(&rxout_task, plat_rxout_tasklet, 0); +- irq_init(tc_priv, drv_name); +- //tasklet_init(&priv->coc.coc_task, plat_coc_tasklet, 0); ++ plat_irq_init(tc_priv, drv_name); ++ + plat_tc_ops_setup(tc_priv); + plat_dsl_ops_setup(); + +@@ -1201,8 +1303,15 @@ void platform_dsl_exit(void) + + void platform_exit(void) + { +- //tasklet_kill(&g_plat_priv->coc.coc_task); ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ ++ tasklet_kill(&txout_task); ++ tasklet_kill(&rxout_task); ++ ++ plat_irq_free(tcpriv); ++ + plat_dp_exit(g_plat_priv); ++ + g_plat_priv = NULL; + } + diff --git a/package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch b/package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch new file mode 100644 index 00000000000..8b30914df96 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch @@ -0,0 +1,342 @@ +Port FEATURE_CONF_DESC_LENGTH from the grx500 variant of the driver. +This also reduces the default length of some descriptors, resulting in +significantly lower latencies when the line is saturated. + +--- a/dcdp/inc/tc_common.h ++++ b/dcdp/inc/tc_common.h +@@ -27,7 +27,11 @@ + #define UMT_DEF_PERIOD 400 /* microseconds */ + + #define MAX_MTU (DMA_PACKET_SZ - ETH_HLEN - HD_RSRV_SZ) ++#ifdef FEATURE_CONF_DESC_LENGTH ++#define QOSQ_NUM 8 ++#else + #define QOSQ_NUM 2 ++#endif + #define FW_STOP_TIMEOUT 20 /* millisecond */ + #define QOS_DISPATCH_OWN 0 + #define ACA_TXIN_POLL_INTVAL 10 /* millisecond */ +--- a/dcdp/inc/tc_main.h ++++ b/dcdp/inc/tc_main.h +@@ -30,6 +30,7 @@ + #define TCPRIV_ALIGN 32 + #define DMA_PACKET_SZ 2048 + ++#define FEATURE_CONF_DESC_LENGTH 1 + #define FEATURE_POWER_DOWN 1 + + enum { +@@ -157,6 +158,25 @@ struct tc_param { + unsigned int txout_dnum; + unsigned int rxin_dnum; + unsigned int rxout_dnum; ++ ++#ifdef FEATURE_CONF_DESC_LENGTH ++ /* __US_FAST_PATH_DES_LIST_NUM:64 ++ * __ACA_TX_IN_PD_LIST_NUM ++ * __ACA_TX_OUT_PD_LIST_NUM ++ * */ ++ u32 conf_us_fp_desq_len; ++ /* ++ * Number of queue per QoS queue: QOS_DES_NUM / QOSQ_NUM ++ * */ ++ u32 conf_us_qos_queue_len; ++ /* __US_OUTQ0_DES_LIST_NUM: 32 ++ * __US_OUTQ1_DES_LIST_NUM: 32 ++ * OUTQ_DESC_PER_Q ++ * */ ++ u32 conf_us_outq_len; ++ /**/ ++ u32 conf_us_local_q0_desq_len; ++#endif + }; + + struct cdma { +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -75,7 +75,11 @@ static const u32 tx_kvec[] = { + 0x30B1B233, 0xB43536B7, 0xB8393ABB, 0x3CBDBE3F, + 0xC04142C3, 0x44C5C647, 0x48C9CA4B, 0xCC4D4ECF + }; ++#ifndef FEATURE_CONF_DESC_LENGTH + static const u32 def_outq_map[OUTQ_PNUM] = {0x1, 0xFE}; ++#else ++static const u32 def_outq_map[OUTQ_PNUM] = {0x0, 0xFF}; ++#endif + static const char ptm_drv_name[] = "PTM SL"; + static const char ptm_bond_name[][IFNAMSIZ] = {"PTM US BOND", "PTM DS BOND"}; + +@@ -1005,6 +1009,10 @@ static void us_fp_desq_cfg_ctxt_init(str + int i; + u32 desc_addr; + rx_descriptor_t desc; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + memset(&desq_cfg, 0, sizeof(desq_cfg)); + /* Initialize US Fast-Path Descriptor Queue Config/Context */ +@@ -1012,7 +1020,11 @@ static void us_fp_desq_cfg_ctxt_init(str + desq_cfg.fast_path = 1; + desq_cfg.mbox_int_en = 0; + desq_cfg.des_sync_needed = 0; ++#ifndef FEATURE_CONF_DESC_LENGTH + desq_cfg.des_num = __US_FAST_PATH_DES_LIST_NUM; ++#else ++ desq_cfg.des_num = tc_priv->param.conf_us_fp_desq_len; ++#endif + desq_cfg.des_base_addr = __US_FAST_PATH_DES_LIST_BASE; + + tc_mem_write(priv, fpi_addr(__US_FP_INQ_DES_CFG_CTXT), +@@ -1036,12 +1048,20 @@ static void us_qos_desq_cfg_ctxt_init(st + int offset, i; + rx_descriptor_t desc; + u32 phy_addr; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + /* Setup QoSQ_CFG_CTXT */ + memset(&qosq_cfg_ctxt, 0, sizeof(qosq_cfg_ctxt)); + + qosq_cfg_ctxt.threshold = 8; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ qosq_cfg_ctxt.des_num = tc_priv->param.conf_us_qos_queue_len; ++#else + qosq_cfg_ctxt.des_num = QOS_DES_NUM / QOSQ_NUM; ++#endif + + offset = 0; + for (i = 0; i < QOSQ_NUM; i++) { +@@ -1080,6 +1100,10 @@ static void us_outq_desq_cfg_ctxt_init(s + u32 phy_addr; + int i; + u32 offset; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + /* Setup OUTQ_QoS_CFG_CTXT */ + /* NOTE: By default, Shaping & WFQ both are DISABLED!! */ +@@ -1108,7 +1132,11 @@ static void us_outq_desq_cfg_ctxt_init(s + desq_cfg.des_in_own_val = US_OUTQ_DES_OWN; + desq_cfg.mbox_int_en = 0; + desq_cfg.des_sync_needed = 0; +- desq_cfg.des_num = 32; ++#ifndef FEATURE_CONF_DESC_LENGTH ++ desq_cfg.des_num = OUTQ_DESC_PER_Q; ++#else ++ desq_cfg.des_num = tc_priv->param.conf_us_outq_len; ++#endif + /** + * Only BC0 is used in VRX518 + */ +@@ -1174,7 +1202,11 @@ static void us_qos_cfg_init(struct ptm_e + /* Set QoS NO DROP */ + sb_w32(1, __QOSQ_NO_DROP); + /* Enable Preemption function/Disable QoS by default */ ++#ifdef FEATURE_CONF_DESC_LENGTH ++ sb_w32(0, _CHK_PREEMP_MAP); ++#else + sb_w32(1, _CHK_PREEMP_MAP); ++#endif + /* By default, all qid mappint to non-preemption queue */ + sb_w32(0x0, _QID2PREEMP_MAP); + +@@ -1376,6 +1408,11 @@ static void ptm_local_desq_cfg_ctxt_init + u32 dcnt, addr, pdbram_base; + unsigned int us_des_alloc[] = { + __US_TC_LOCAL_Q0_DES_LIST_NUM, __US_TC_LOCAL_Q1_DES_LIST_NUM}; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++ us_des_alloc[0] = tc_priv->param.conf_us_local_q0_desq_len; ++#endif + + /* Setup the Local DESQ Configuration/Context for UpStream Queues */ + memset(&desq_cfg, 0, sizeof(desq_cfg)); +@@ -2321,6 +2358,10 @@ static void ptm_aca_init(struct ptm_ep_p + u32 phybase = priv->ep->phy_membase; + u32 start; + u32 type; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + priv->tc_priv->tc_ops.soc_cfg_get(&priv->tc_priv->cfg, ptm_id(priv)); + memset(¶m, 0, sizeof(param)); +@@ -2334,7 +2375,11 @@ static void ptm_aca_init(struct ptm_ep_p + #endif + txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; + txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); ++#ifndef FEATURE_CONF_DESC_LENGTH + txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; ++#else ++ txin->pd_desc_num = tc_priv->param.conf_us_fp_desq_len; ++#endif + txin->pd_size_in_dw = DESC_DWSZ; + txin->soc_desc_base = cfg->txin.soc_phydbase; + txin->soc_desc_num = cfg->txin.soc_dnum; +--- a/dcdp/tc_main.c ++++ b/dcdp/tc_main.c +@@ -182,6 +182,12 @@ static inline void init_local_param(stru + priv->param.txout_dnum = txout_num; + priv->param.rxin_dnum = rxin_num; + priv->param.rxout_dnum = rxout_num; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ priv->param.conf_us_fp_desq_len = 32; ++ priv->param.conf_us_qos_queue_len = 32; ++ priv->param.conf_us_outq_len = 32; ++ priv->param.conf_us_local_q0_desq_len = 16; ++#endif + priv->tc_mode = TC_NONE_MODE; + priv->tc_stat = NO_TC; + +--- a/dcdp/tc_proc.c ++++ b/dcdp/tc_proc.c +@@ -1114,6 +1114,9 @@ static int proc_read_ver(struct seq_file + (date >> 16) & 0xff, + (date & 0xffff)); + ++#ifdef FEATURE_CONF_DESC_LENGTH ++ seq_puts(seq, " + Support QoS and Configurable descriptor length\n"); ++#endif + #ifdef FEATURE_POWER_DOWN + seq_puts(seq, " + Support Power Down enhancement feature\n"); + #endif +@@ -1166,6 +1169,113 @@ static const struct proc_ops tc_soc_proc + .proc_release = single_release, + }; + ++#ifdef FEATURE_CONF_DESC_LENGTH ++static ssize_t proc_write_desc_conf(struct file *file, const char __user *buf, ++ size_t count, loff_t *data) ++{ ++ struct tc_priv *priv; ++ char str[32]; ++ int len, rlen, temp; ++ int num, temp_num; ++ char *param_list[20]; ++ len = count < sizeof(str) ? count : sizeof(str) - 1; ++ rlen = len - copy_from_user(str, buf, len); ++ str[rlen] = 0; ++ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ priv = (struct tc_priv *)PDE_DATA(file_inode(file)); ++ if (priv == NULL) ++ return count; ++ ++ num = vrx_split_buffer(str, param_list, ARRAY_SIZE(param_list)); ++ if (num < 1 || num > 4) ++ goto proc_dbg_desc_conf; ++ ++ temp_num = num; ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[0]); ++ if (temp < 1 || temp > 128) { ++ pr_info("Fastpath valid range: 1 -> 128\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[1]); ++ if (temp < 1 || temp > 63) { ++ pr_info("QoS valid range: 1 -> 63\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[2]); ++ if (temp < 1 || temp > 128) { ++ pr_info("OutQ valid range: 1 -> 128\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[3]); ++ if (temp < 4 || temp > 16) { ++ pr_info("Local Q0 valid range: 4 -> 16\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ num = temp_num; ++ if (num-- != 0) { ++ priv->param.conf_us_fp_desq_len = vrx_atoi(param_list[0]); ++ } ++ if (num-- != 0) { ++ priv->param.conf_us_qos_queue_len = vrx_atoi(param_list[1]); ++ } ++ if (num-- != 0) { ++ priv->param.conf_us_outq_len = vrx_atoi(param_list[2]); ++ } ++ if (num-- != 0) { ++ priv->param.conf_us_local_q0_desq_len = vrx_atoi(param_list[3]); ++ } ++ ++ return count; ++ ++proc_dbg_desc_conf: ++ pr_info("echo [FP] [QoS] [OutQ] [LocalQ0]> desc_conf\n"); ++ return count; ++} ++ ++static int proc_read_desc_conf(struct seq_file *seq, void *v) ++{ ++ struct tc_priv *priv; ++ priv = (struct tc_priv *)seq->private; ++ if (priv == NULL) ++ return -1; ++ seq_puts(seq, "Upstream descriptor length information:\n"); ++ seq_printf(seq, " - Fastpath: %d\n", ++ priv->param.conf_us_fp_desq_len); ++ seq_printf(seq, " - QoS: %d\n", ++ priv->param.conf_us_qos_queue_len); ++ seq_printf(seq, " - OutQ: %d\n", ++ priv->param.conf_us_outq_len); ++ seq_printf(seq, " - Local Q0: %d\n", ++ priv->param.conf_us_local_q0_desq_len); ++ seq_puts(seq, "\n"); ++ return 0; ++} ++ ++static int proc_read_desc_conf_seq_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_read_desc_conf, PDE_DATA(inode)); ++} ++#endif ++ ++static const struct proc_ops tc_desc_conf_proc_fops = { ++ .proc_open = proc_read_desc_conf_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_desc_conf, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++ + static struct tc_proc_list tc_procs[] = { + {TC_PROC_DIR, 0, NULL, 1}, + {"cfg", 0644, &tc_cfg_proc_fops, 0}, +@@ -1174,6 +1284,9 @@ static struct tc_proc_list tc_procs[] = + {"showtime", 0200, &tc_show_time_proc_fops, 0}, + {"ver", 0644, &tc_ver_proc_fops, 0}, + {"soc", 0644, &tc_soc_proc_fops, 0}, ++#ifdef FEATURE_CONF_DESC_LENGTH ++ {"desc_conf", 0644, &tc_desc_conf_proc_fops, 0}, ++#endif + }; + + int tc_proc_init(struct tc_priv *priv) +@@ -1333,7 +1446,6 @@ proc_ptm_cfg_help: + return count; + } + +- + static const struct proc_ops ptm_cfg_proc_fops = { + .proc_open = proc_read_cfg_seq_open, + .proc_read = seq_read, diff --git a/package/kernel/lantiq/vrx518_tc/patches/202-napi.patch b/package/kernel/lantiq/vrx518_tc/patches/202-napi.patch new file mode 100644 index 00000000000..55f0cc10667 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/202-napi.patch @@ -0,0 +1,423 @@ +--- a/dcdp/platform/sw_plat.c ++++ b/dcdp/platform/sw_plat.c +@@ -208,6 +208,8 @@ struct plat_priv { + struct tc_req req_work; + struct aca_ring_grp soc_rings; + struct net_device *netdev; ++ struct napi_struct *napi_tx; ++ struct napi_struct *napi_rx; + DECLARE_HASHTABLE(mem_map, 8); + }; + +@@ -472,7 +474,7 @@ err2: + return -1; + } + +-static void txout_action(struct tc_priv *priv, struct aca_ring *txout) ++static int txout_action(struct tc_priv *priv, struct aca_ring *txout, int budget) + { + struct aca_ring *txin = &g_plat_priv->soc_rings.txin; + struct tx_list *txlist = &g_plat_priv->soc_rings.txlist; +@@ -490,7 +492,10 @@ static void txout_action(struct tc_priv + spin_lock_irqsave(&tx_spinlock, flags); + } + +- for (i = 0; i < txout->dnum; i++) { ++ if (budget == 0 || budget > txout->dnum) ++ budget = txout->dnum; ++ ++ for (i = 0; i < budget; i++) { + desc = txout->dbase_mem; + desc += txout->idx; + +@@ -540,6 +545,8 @@ static void txout_action(struct tc_priv + if (cnt && g_plat_priv->netdev && netif_queue_stopped(g_plat_priv->netdev)) { + netif_wake_queue(g_plat_priv->netdev); + } ++ ++ return cnt; + } + + static void rxin_action(struct tc_priv *priv, +@@ -549,7 +556,7 @@ static void rxin_action(struct tc_priv * + writel(cnt, rxin->umt_dst); + } + +-static int rxout_action(struct tc_priv *priv, struct aca_ring *rxout) ++static int rxout_action(struct tc_priv *priv, struct aca_ring *rxout, int budget) + { + struct device *pdev = priv->ep_dev[0].dev; + int i, cnt; +@@ -559,8 +566,11 @@ static int rxout_action(struct tc_priv * + size_t len; + struct sk_buff *skb; + ++ if (budget == 0 || budget > rxout->dnum) ++ budget = rxout->dnum; ++ + cnt = 0; +- for (i = 0; i < rxout->dnum; i++) { ++ for (i = 0; i < budget; i++) { + desc = rxout->dbase_mem; + desc += rxout->idx; + +@@ -593,14 +603,30 @@ static int rxout_action(struct tc_priv * + ring_idx_inc(rxout); + } + +- if (!cnt) +- tc_err(priv, MSG_RX, "RXOUT spurious interrupt\n"); +- else ++ if (cnt) + writel(cnt, rxout->umt_dst+0x28); // RXOUT_HD_ACCUM_SUB instead of RXOUT_HD_ACCUM_ADD + + return cnt; + } + ++static int plat_txout_napi(struct napi_struct *napi, int budget) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *txout = &priv->soc_rings.txout; ++ struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[txout->ep_dev_idx]; ++ int cnt; ++ ++ cnt = txout_action(tcpriv, txout, budget); ++ ++ if (cnt < budget) { ++ if (napi_complete_done(napi, cnt)) ++ ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_TX); ++ } ++ ++ return cnt; ++} ++ + static void plat_txout_tasklet(unsigned long arg) + { + struct plat_priv *priv = g_plat_priv; +@@ -608,12 +634,33 @@ static void plat_txout_tasklet(unsigned + struct aca_ring *txout = &priv->soc_rings.txout; + struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[txout->ep_dev_idx]; + +- txout_action(tcpriv, txout); ++ txout_action(tcpriv, txout, 0); + + /* Enable interrupt */ + ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_TX); + } + ++static int plat_rxout_napi(struct napi_struct *napi, int budget) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *rxout = &priv->soc_rings.rxout; ++ struct aca_ring *rxin = &priv->soc_rings.rxin; ++ struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[rxout->ep_dev_idx]; ++ int cnt; ++ ++ cnt = rxout_action(tcpriv, rxout, budget); ++ if (cnt) ++ rxin_action(tcpriv, rxin, DMA_PACKET_SZ, cnt); ++ ++ if (cnt < budget) { ++ if (napi_complete_done(napi, cnt)) ++ ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_RX); ++ } ++ ++ return cnt; ++} ++ + static void plat_rxout_tasklet(unsigned long arg) + { + struct plat_priv *priv = g_plat_priv; +@@ -623,7 +670,7 @@ static void plat_rxout_tasklet(unsigned + struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[rxout->ep_dev_idx]; + int cnt; + +- cnt = rxout_action(tcpriv, rxout); ++ cnt = rxout_action(tcpriv, rxout, 0); + if (cnt) + rxin_action(tcpriv, rxin, DMA_PACKET_SZ, cnt); + +@@ -783,11 +830,22 @@ static irqreturn_t aca_rx_irq_handler(in + { + struct dc_ep_dev *ep_dev = dev_id; + +- /* Disable IRQ in IMCU */ +- ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_RX); ++ if (g_plat_priv->napi_rx) { ++ ++ if (napi_schedule_prep(g_plat_priv->napi_rx)) { ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_RX); ++ __napi_schedule(g_plat_priv->napi_rx); ++ } ++ ++ } else { ++ ++ /* Disable IRQ in IMCU */ ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_RX); + +- /* Start tasklet */ +- tasklet_schedule(&rxout_task); ++ /* Start tasklet */ ++ tasklet_schedule(&rxout_task); ++ ++ } + + return IRQ_HANDLED; + } +@@ -796,15 +854,62 @@ static irqreturn_t aca_tx_irq_handler(in + { + struct dc_ep_dev *ep_dev = dev_id; + +- /* Disable IRQ in IMCU */ +- ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_TX); ++ if (g_plat_priv->napi_tx) { + +- /* Start tasklet */ +- tasklet_schedule(&txout_task); ++ if (napi_schedule_prep(g_plat_priv->napi_tx)) { ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_TX); ++ __napi_schedule(g_plat_priv->napi_tx); ++ } ++ ++ } else { ++ ++ /* Disable IRQ in IMCU */ ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_TX); ++ ++ /* Start tasklet */ ++ tasklet_schedule(&txout_task); ++ ++ } + + return IRQ_HANDLED; + } + ++static void plat_net_open(void) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *rxout = &priv->soc_rings.rxout; ++ struct aca_ring *txout = &priv->soc_rings.txout; ++ struct dc_ep_dev *ep_dev_rx = &tcpriv->ep_dev[rxout->ep_dev_idx]; ++ struct dc_ep_dev *ep_dev_tx = &tcpriv->ep_dev[txout->ep_dev_idx]; ++ ++ if (priv->napi_rx) ++ napi_enable(priv->napi_rx); ++ ep_dev_rx->hw_ops->icu_en(ep_dev_rx, ACA_HOSTIF_RX); ++ ++ if (priv->napi_tx) ++ napi_enable(priv->napi_tx); ++ ep_dev_tx->hw_ops->icu_en(ep_dev_tx, ACA_HOSTIF_TX); ++} ++ ++static void plat_net_stop(void) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *rxout = &priv->soc_rings.rxout; ++ struct aca_ring *txout = &priv->soc_rings.txout; ++ struct dc_ep_dev *ep_dev_rx = &tcpriv->ep_dev[rxout->ep_dev_idx]; ++ struct dc_ep_dev *ep_dev_tx = &tcpriv->ep_dev[txout->ep_dev_idx]; ++ ++ if (priv->napi_tx) ++ napi_disable(priv->napi_tx); ++ ep_dev_tx->hw_ops->icu_mask(ep_dev_tx, ACA_HOSTIF_TX); ++ ++ if (priv->napi_rx) ++ napi_disable(priv->napi_rx); ++ ep_dev_rx->hw_ops->icu_mask(ep_dev_rx, ACA_HOSTIF_RX); ++} ++ + static void plat_irq_init(struct tc_priv *priv, const char *dev_name) + { + int ret; +@@ -988,17 +1093,49 @@ static int plat_soc_cfg_get(struct soc_c + } + + static int plat_open(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int id, int flag) + { ++ struct tc_priv *priv = g_plat_priv->tc_priv; ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ disable_irq(priv->ep_dev[i].aca_rx_irq); ++ disable_irq(priv->ep_dev[i].aca_tx_irq); ++ } ++ + g_plat_priv->netdev = pdev; ++ g_plat_priv->napi_tx = napi_tx; ++ g_plat_priv->napi_rx = napi_rx; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ enable_irq(priv->ep_dev[i].aca_rx_irq); ++ enable_irq(priv->ep_dev[i].aca_tx_irq); ++ } + + return 0; + } + + static void plat_close(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int flag) + { ++ struct tc_priv *priv = g_plat_priv->tc_priv; ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ disable_irq(priv->ep_dev[i].aca_rx_irq); ++ disable_irq(priv->ep_dev[i].aca_tx_irq); ++ } ++ + g_plat_priv->netdev = NULL; ++ g_plat_priv->napi_tx = NULL; ++ g_plat_priv->napi_rx = NULL; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ enable_irq(priv->ep_dev[i].aca_rx_irq); ++ enable_irq(priv->ep_dev[i].aca_tx_irq); ++ } + + return; + } +@@ -1084,6 +1221,10 @@ static void plat_tc_ops_setup(struct tc_ + priv->tc_ops.free = plat_mem_free; + priv->tc_ops.dev_reg = plat_open; + priv->tc_ops.dev_unreg = plat_close; ++ priv->tc_ops.net_open = plat_net_open; ++ priv->tc_ops.net_stop = plat_net_stop; ++ priv->tc_ops.napi_tx = plat_txout_napi; ++ priv->tc_ops.napi_rx = plat_rxout_napi; + priv->tc_ops.umt_init = plat_umt_init; + priv->tc_ops.umt_exit = plat_umt_exit; + priv->tc_ops.umt_start = plat_umt_start; +--- a/dcdp/atm_tc.c ++++ b/dcdp/atm_tc.c +@@ -3650,7 +3650,7 @@ static void atm_aca_ring_config_init(str + static int atm_ring_init(struct atm_priv *priv) + { + atm_aca_ring_config_init(priv); +- return priv->tc_priv->tc_ops.dev_reg(NULL, g_atm_dev_name, 0, 0); ++ return priv->tc_priv->tc_ops.dev_reg(NULL, g_atm_dev_name, NULL, NULL, 0, 0); + } + + static int atm_init(struct tc_priv *tcpriv, u32 ep_id) +@@ -4020,7 +4020,7 @@ void atm_tc_unload(void) + /* unregister device */ + if (priv->tc_priv->tc_ops.dev_unreg != NULL) + priv->tc_priv->tc_ops.dev_unreg(NULL, +- g_atm_dev_name, 0); ++ g_atm_dev_name, NULL, NULL, 0); + + /* atm_dev_deinit(priv); */ + /* modem module power off */ +--- a/dcdp/inc/tc_main.h ++++ b/dcdp/inc/tc_main.h +@@ -209,9 +209,15 @@ struct tc_hw_ops { + void (*subif_unreg)(struct net_device *pdev, const char *dev_name, + int subif_id, int flag); + int (*dev_reg)(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int id, int flag); + void (*dev_unreg)(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int flag); ++ void (*net_open)(void); ++ void (*net_stop)(void); ++ int (*napi_tx)(struct napi_struct *napi, int budget); ++ int (*napi_rx)(struct napi_struct *napi, int budget); + + /*umt init/exit including the corresponding DMA init/exit */ + int (*umt_init)(u32 umt_id, u32 umt_period, u32 umt_dst); +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -141,7 +141,11 @@ static int ptm_open(struct net_device *d + struct ptm_priv *ptm_tc = netdev_priv(dev); + + tc_info(ptm_tc->tc_priv, MSG_EVENT, "ptm open\n"); ++ ++ ptm_tc->tc_priv->tc_ops.net_open(); ++ + netif_tx_start_all_queues(dev); ++ + #ifdef CONFIG_SOC_TYPE_XWAY + xet_phy_wan_port(7, NULL, 1, 1); + if (ppa_hook_ppa_phys_port_add_fn) +@@ -158,7 +162,11 @@ static int ptm_stop(struct net_device *d + struct ptm_priv *ptm_tc = netdev_priv(dev); + + tc_info(ptm_tc->tc_priv, MSG_EVENT, "ptm stop\n"); ++ + netif_tx_stop_all_queues(dev); ++ ++ ptm_tc->tc_priv->tc_ops.net_stop(); ++ + #ifdef CONFIG_SOC_TYPE_XWAY + if (ppa_drv_datapath_mac_entry_setting) + ppa_drv_datapath_mac_entry_setting(dev->dev_addr, 0, 6, 10, 1, 2); +@@ -555,7 +563,7 @@ static void ptm_rx(struct net_device *de + ptm_tc->stats64.rx_packets++; + ptm_tc->stats64.rx_bytes += skb->len; + +- if (netif_rx(skb) == NET_RX_DROP) ++ if (netif_receive_skb(skb) == NET_RX_DROP) + ptm_tc->stats64.rx_dropped++; + + return; +@@ -651,6 +659,9 @@ static int ptm_dev_init(struct tc_priv * + memcpy(ptm_tc->outq_map, def_outq_map, sizeof(def_outq_map)); + SET_NETDEV_DEV(ptm_tc->dev, tc_priv->ep_dev[id].dev); + ++ netif_napi_add(ptm_tc->dev, &ptm_tc->napi_rx, tc_priv->tc_ops.napi_rx, NAPI_POLL_WEIGHT); ++ netif_tx_napi_add(ptm_tc->dev, &ptm_tc->napi_tx, tc_priv->tc_ops.napi_tx, NAPI_POLL_WEIGHT); ++ + err = register_netdev(ptm_tc->dev); + if (err) + goto err1; +@@ -2605,7 +2616,9 @@ static int ptm_ring_init(struct ptm_ep_p + { + ptm_aca_ring_config_init(priv, id, bonding); + return priv->tc_priv->tc_ops.dev_reg(priv->ptm_tc->dev, +- priv->ptm_tc->dev->name, id, bonding); ++ priv->ptm_tc->dev->name, ++ &priv->ptm_tc->napi_tx, &priv->ptm_tc->napi_rx, ++ id, bonding); + } + + /** +@@ -2960,7 +2973,9 @@ void ptm_tc_unload(enum dsl_tc_mode tc_m + /* unregister device */ + if (ptm_tc->tc_priv->tc_ops.dev_unreg != NULL) + ptm_tc->tc_priv->tc_ops.dev_unreg(ptm_tc->dev, +- ptm_tc->dev->name, 0); ++ ptm_tc->dev->name, ++ &priv->ptm_tc->napi_tx, &priv->ptm_tc->napi_rx, ++ 0); + + /* remove PTM callback function */ + ptm_cb_setup(ptm_tc, 0); +@@ -2978,6 +2993,10 @@ void ptm_exit(void) + + if (!priv) + return; ++ ++ netif_napi_del(&priv->napi_tx); ++ netif_napi_del(&priv->napi_rx); ++ + unregister_netdev(priv->dev); + free_netdev(priv->dev); + +--- a/dcdp/inc/ptm_tc.h ++++ b/dcdp/inc/ptm_tc.h +@@ -119,6 +119,8 @@ struct ptm_priv { + u32 ep_id; + struct ppe_fw fw; + struct net_device *dev; ++ struct napi_struct napi_tx; ++ struct napi_struct napi_rx; + spinlock_t ptm_lock; + struct rtnl_link_stats64 stats64; + int subif_id; diff --git a/package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch b/package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch new file mode 100644 index 00000000000..687e66f991e --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch @@ -0,0 +1,120 @@ +--- a/dcdp/platform/sw_plat.c ++++ b/dcdp/platform/sw_plat.c +@@ -85,6 +85,7 @@ struct aca_ring { + u32 dnum; + u32 dsize; + int idx; /* SoC RX/TX index */ ++ u64 cnt; + int ep_dev_idx; + }; + +@@ -210,6 +211,8 @@ struct plat_priv { + struct net_device *netdev; + struct napi_struct *napi_tx; + struct napi_struct *napi_rx; ++ u64 napi_tx_stats[NAPI_POLL_WEIGHT+1]; ++ u64 napi_rx_stats[NAPI_POLL_WEIGHT+1]; + DECLARE_HASHTABLE(mem_map, 8); + }; + +@@ -362,6 +365,7 @@ static void txlist_free(struct tx_list * + static inline void ring_idx_inc(struct aca_ring *ring) + { + ring->idx = (ring->idx + 1) % ring->dnum; ++ ring->cnt += 1; + } + + static struct sk_buff *txin_skb_prepare(struct sk_buff *skb) +@@ -619,6 +623,8 @@ static int plat_txout_napi(struct napi_s + + cnt = txout_action(tcpriv, txout, budget); + ++ priv->napi_tx_stats[cnt] += 1; ++ + if (cnt < budget) { + if (napi_complete_done(napi, cnt)) + ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_TX); +@@ -653,6 +659,8 @@ static int plat_rxout_napi(struct napi_s + if (cnt) + rxin_action(tcpriv, rxin, DMA_PACKET_SZ, cnt); + ++ priv->napi_rx_stats[cnt] += 1; ++ + if (cnt < budget) { + if (napi_complete_done(napi, cnt)) + ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_RX); +@@ -1092,6 +1100,56 @@ static int plat_soc_cfg_get(struct soc_c + return 0; + } + ++static struct proc_dir_entry *g_proc_entry; ++ ++static int proc_show(struct seq_file *m, void *p) ++{ ++ struct aca_ring *txin = &g_plat_priv->soc_rings.txin; ++ struct aca_ring *txout = &g_plat_priv->soc_rings.txout; ++ struct aca_ring *rxin = &g_plat_priv->soc_rings.rxin; ++ struct aca_ring *rxout = &g_plat_priv->soc_rings.rxout; ++ int i; ++ ++ seq_printf(m, "napi_tx_stats: "); ++ for (i = 0; i < sizeof(g_plat_priv->napi_tx_stats) / sizeof(g_plat_priv->napi_tx_stats[0]); i++) { ++ if (i == 0) { ++ seq_printf(m, "%llu", g_plat_priv->napi_tx_stats[i]); ++ } else { ++ seq_printf(m, ", %llu", g_plat_priv->napi_tx_stats[i]); ++ } ++ } ++ seq_printf(m, "\n"); ++ ++ seq_printf(m, "napi_rx_stats: "); ++ for (i = 0; i < sizeof(g_plat_priv->napi_rx_stats) / sizeof(g_plat_priv->napi_rx_stats[0]); i++) { ++ if (i == 0) { ++ seq_printf(m, "%llu", g_plat_priv->napi_rx_stats[i]); ++ } else { ++ seq_printf(m, ", %llu", g_plat_priv->napi_rx_stats[i]); ++ } ++ } ++ seq_printf(m, "\n"); ++ ++ seq_printf(m, "txin: %d/%u, %llu\n", txin->idx, txin->dnum, txin->cnt); ++ seq_printf(m, "txout: %d/%u, %llu\n", txout->idx, txout->dnum, txout->cnt); ++ seq_printf(m, "rxin: %d/%u, %llu\n", rxin->idx, rxin->dnum, rxin->cnt); ++ seq_printf(m, "rxout: %d/%u, %llu\n", rxout->idx, rxout->dnum, rxout->cnt); ++ ++ return 0; ++} ++ ++static int proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_show, NULL); ++} ++ ++static struct proc_ops proc_operations = { ++ .proc_open = proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ + static int plat_open(struct net_device *pdev, const char *dev_name, + struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int id, int flag) +@@ -1099,6 +1157,8 @@ static int plat_open(struct net_device * + struct tc_priv *priv = g_plat_priv->tc_priv; + int i; + ++ g_proc_entry = proc_create("swplat", 0600, priv->proc_dir, &proc_operations); ++ + for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { + disable_irq(priv->ep_dev[i].aca_rx_irq); + disable_irq(priv->ep_dev[i].aca_tx_irq); +@@ -1137,6 +1197,8 @@ static void plat_close(struct net_device + enable_irq(priv->ep_dev[i].aca_tx_irq); + } + ++ proc_remove(g_proc_entry); ++ + return; + } + diff --git a/package/network/config/ltq-vdsl-vr11-app/Makefile b/package/network/config/ltq-vdsl-vr11-app/Makefile new file mode 100644 index 00000000000..8639795458f --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/Makefile @@ -0,0 +1,92 @@ +# Copyright (C) 2010 OpenWrt.org +# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-vdsl-vr11-app +PKG_VERSION:=4.23.1 +PKG_RELEASE:=1 +PKG_BASE_NAME:=dsl_cpe_control + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=d21ec74ca30f7f3893a8aa26d2b74ec319652f6b112832efab6f1274c7e5d1fc +PKG_BUILD_DIR:=$(BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE + +PKG_BUILD_DEPENDS:=ltq-vdsl-vr11 + +PKG_FLAGS:=nonshared +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/ltq-vdsl-vr11-app + SECTION:=net + CATEGORY:=Network + TITLE:=Lantiq VDSL userland tool + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_ipq40xx +libpthread +librt +libubox +libubus +ltq-dsl-base +kmod-ltq-vdsl-vr11 + PROVIDES:=ltq-dsl-app +endef + +define Package/ltq-vdsl-vr11-app/description + Userland tool needed to control Lantiq VDSL CPE +endef + +# ltq-vdsl-vr11-app uses a header provided by the MEI driver which has some +# conditionals. +# +# Define them here with the default values they would get in the MEI driver, +# have the same view on both sides. +# +# If you change them, you need to change them for the ltq-vdsl-vr11-app as well +VDSL_APP_CFLAGS = \ + -DMAX_CLI_PIPES=1 \ + -DMEI_SUPPORT_DEBUG_STREAMS=1 \ + -DMEI_SUPPORT_OPTIMIZED_FW_DL=1 + +CONFIGURE_ARGS += \ + --enable-debug-logger-support=no + +CONFIGURE_ARGS += \ + --enable-vrx \ + --enable-vrx-device=vr11 \ + --enable-driver-include="-I$(STAGING_DIR)/usr/include/drv_vdsl_cpe_api" \ + --enable-device-driver-include="-I$(STAGING_DIR)/usr/include/vdsl/" \ + --enable-ifxos \ + --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \ + --enable-ifxos-library="-I$(STAGING_DIR)/usr/lib" \ + --enable-add-appl-cflags="$(VDSL_APP_CFLAGS)" \ + --enable-debug \ + --disable-dti + +CONFIGURE_ARGS += \ + --enable-model=full \ + --enable-dsl-ceoc=no +#CONFIGURE_ARGS += --enable-model=lite +#CONFIGURE_ARGS += --enable-model=footprint +#CONFIGURE_ARGS += --enable-model=typical +#CONFIGURE_ARGS += --enable-model=debug + +define Build/Prepare + $(call Build/Prepare/Default) + $(CP) ../ltq-vdsl-vr9-app/src/src/dsl_cpe_ubus.c $(PKG_BUILD_DIR)/src/ +endef + +define Package/ltq-vdsl-vr11-app/install + $(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl + $(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin/vdsl_cpe_control + $(INSTALL_BIN) ./files/dsl_cpe_pipe.sh $(1)/sbin/ +endef + +$(eval $(call BuildPackage,ltq-vdsl-vr11-app)) diff --git a/package/network/config/ltq-vdsl-vr11-app/files/dsl_control b/package/network/config/ltq-vdsl-vr11-app/files/dsl_control new file mode 100644 index 00000000000..d960a772618 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/files/dsl_control @@ -0,0 +1,264 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2012 OpenWrt.org + +START=97 +USE_PROCD=1 + +dslstat() { + ubus call dsl metrics +} + +extra_command "dslstat" "Get DSL status information" + +# +# ITU-T G.997.1 (06/2012) - Section 7.3.1.1.1 (xTU transmission system enabling (XTSE)) +# ITU-T G.997.1 Amendment 2 (04/2013) - Section 2.1 - (Vectoring mode enable (VECTORMODE_ENABLE)) +# +# G.992.1 Annex A +# G.992.2 Annex A +# G.992.3 Annex A / L-US1 / L_US-2 / M +# G.992.5 Annex A / M +# G.993.2 Annex A/B/C +# G.993.5 Annex A/B/C +xtse_xdsl_a="05_01_04_00_4C_01_04_07" + +# G.992.1 Annex B +# G.992.3 Annex B +# G.992.5 Annex B +# G.993.2 Annex A/B/C +# G.993.5 Annex A/B/C +xtse_xdsl_b="10_00_10_00_00_04_00_07" + +# G.992.1 Annex B +# G.992.3 Annex B +# G.992.3 Annex J +# G.992.5 Annex B +# G.992.5 Annex J +# G.993.2 Annex A/B/C +# G.993.5 Annex A/B/C +xtse_xdsl_j="10_00_10_40_00_04_01_07" + +# G.992.1 Annex B +xtse_xdsl_bdmt="10_00_00_00_00_00_00_00" + +# G.992.3 Annex B +xtse_xdsl_b2="00_00_10_00_00_00_00_00" + +# G.992.5 Annex B +xtse_xdsl_b2p="00_00_00_00_00_04_00_00" + +# ANSI T1.413 +xtse_xdsl_at1="01_00_00_00_00_00_00_00" + +# G.992.2 Annex A +xtse_xdsl_alite="00_01_00_00_00_00_00_00" + +# G.992.1 Annex A +xtse_xdsl_admt="04_00_00_00_00_00_00_00" + +# G.992.3 Annex A +xtse_xdsl_a2="00_00_04_00_00_00_00_00" + +# G.992.5 Annex A +xtse_xdsl_a2p="00_00_00_00_00_01_00_00" + +# G.992.3 Annex L +xtse_xdsl_l="00_00_00_00_0C_00_00_00" + +# G.992.3 Annex M +# G.992.5 Annex M +xtse_xdsl_m="00_00_00_00_40_00_04_00" + +# G.992.3 Annex M +xtse_xdsl_m2="00_00_00_00_40_00_00_00" + +# G.992.5 Annex M +xtse_xdsl_m2p="00_00_00_00_00_00_04_00" + +# +# ITU-T G.994.1 (06/2012) - Table 2 (Mandatory carrier sets) +# + +# A43 +tone_adsl_a="0x142" # A43C + J43 + A43 +tone_vdsl_a="0x142" # A43C + J43 + A43 + +# A43 + V43 +tone_adsl_av="0x142" # A43C + J43 + A43 +tone_vdsl_av="0x146" # A43C + J43 + A43 + V43 + +# B43 +tone_adsl_b="0x81" # B43 + B43c +tone_vdsl_b="0x1" # B43 + +# B43 + V43 +tone_adsl_bv="0x81" # B43 + B43c +tone_vdsl_bv="0x5" # B43 + V43 + +# create DSL autoboot script. Used for SNR margin tweak and to set MAC address for vectoring error reports +autoboot_script() { + echo "[WaitForConfiguration]={ +locs nLine=0 0 $1 +dsmmcs nLine=0 $2 +} + +[WaitForLinkActivate]={ +} + +[WaitForRestart]={ +} + +[Common]={ +}" > /tmp/dsl.scr +} + +lowlevel_cfg() { + echo "# VRX Low Level Configuration File +# +# Parameters must be separated by tabs or spaces. +# Empty lines and comments will be ignored. +# + +# nFilter +# +# NA = -1 +# OFF = 0 +# ISDN = 1 +# POTS = 2 +# POTS_2 = 3 +# POTS_3 = 4 +# +# (dec) + -1 + +# nHsToneGroupMode nHsToneGroup_A nHsToneGroup_V nHsToneGroup_AV +# +# NA = -1 NA = -1 see see +# AUTO = 0 VDSL2_B43 = 0x0001 nHsToneGroup_A nHsToneGroup_A +# MANUAL = 1 VDSL2_A43 = 0x0002 +# VDSL2_V43 = 0x0004 +# VDSL1_V43P = 0x0008 +# VDSL1_V43I = 0x0010 +# ADSL1_C43 = 0x0020 +# ADSL2_J43 = 0x0040 +# ADSL2_B43C = 0x0080 +# ADSL2_A43C = 0x0100 +# +# (dec) (hex) (hex) (hex) + 1 $1 $2 0x0 + +# nBaseAddr nIrqNum +# +# (hex) (dec) + 0x1e116000 63 + +# nUtopiaPhyAdr nUtopiaBusWidth nPosPhyParity +# default(16b) = 0 NA = -1 +# 8-bit = 1 ODD = 0 +# 16-bit = 2 +# +# +# (hex) (dec) (dec) + 0xFF 0 0 + +# bNtrEnable +# +# (dec) + 0" > /tmp/lowlevel.cfg +} + +get_macaddr() { + local name + config_get name $1 name + [ "$name" = "dsl0" ] && config_get $2 $1 macaddr +} + +service_triggers() { + procd_add_reload_trigger network +} + +start_service() { + local annex + local firmware + local tone + local tone_adsl + local tone_vdsl + local xtse + local xfer_mode + local line_mode + local tc_layer + local mode + local lowlevel + local snr + local macaddr + + config_load network + config_get tone dsl tone + config_get annex dsl annex + config_get firmware dsl firmware + config_get xfer_mode dsl xfer_mode + config_get line_mode dsl line_mode + config_get snr dsl ds_snr_offset + config_foreach get_macaddr device macaddr + + eval "xtse=\"\${xtse_xdsl_$annex}\"" + + case "${xfer_mode}" in + atm) + tc_layer="-T1:0x1:0x1_1:0x1:0x1" + ;; + ptm) + tc_layer="-T2:0x1:0x1_2:0x1:0x1" + ;; + esac + + case "${line_mode}" in + adsl) + mode="-M1" + + # mask out VDSL bits when ADSL is requested + xtse="${xtse%_*}_00" + ;; + vdsl) + mode="-M2" + + # mask out ADSL bits when VDSL is requested + xtse="00_00_00_00_00_00_00_${xtse##*_}" + ;; + esac + + [ -z "${firmware}" ] && firmware=/lib/firmware/vdsl.bin + [ -f "${firmware}" ] || { + echo failed to find $firmware + return 1 + } + + eval "tone_adsl=\"\${tone_adsl_$tone}\"" + eval "tone_vdsl=\"\${tone_vdsl_$tone}\"" + [ -n "${tone_adsl}" ] && [ -n "${tone_vdsl}" ] && { + lowlevel_cfg "${tone_adsl}" "${tone_vdsl}" + lowlevel="-l /tmp/lowlevel.cfg" + } + + [ -z "${snr}" ] && snr=0 + [ -z "${macaddr}" ] && macaddr="00:00:00:00:00:00" + autoboot_script "$snr" "$macaddr" + autoboot="-a /tmp/dsl.scr -A /tmp/dsl.scr" + + procd_open_instance + procd_set_param command /sbin/vdsl_cpe_control \ + -i$xtse \ + -n /sbin/dsl_notify.sh \ + -f ${firmware} \ + $lowlevel \ + ${mode} \ + ${tc_layer} \ + $autoboot + procd_close_instance +} + +stop_service() { + DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \ + DSL_INTERFACE_STATUS="DOWN" \ + /sbin/dsl_notify.sh +} diff --git a/package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh b/package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh new file mode 100755 index 00000000000..9002b7b3164 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +pipe_no=0 + +# use specified pipe no +case "$1" in +0|1|2) +pipe_no=$1; shift; ;; +esac + + +#echo "Call dsl_pipe with $*" +lock /var/lock/dsl_pipe +echo $* > /tmp/pipe/dsl_cpe${pipe_no}_cmd +result=$(cat /tmp/pipe/dsl_cpe${pipe_no}_ack) +lock -u /var/lock/dsl_pipe + +echo "$result" diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch b/package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch new file mode 100644 index 00000000000..6bc359c3cc9 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch @@ -0,0 +1,11 @@ +--- a/src/dsl_cpe_init_cfg.c ++++ b/src/dsl_cpe_init_cfg.c +@@ -38,7 +38,7 @@ DSL_InitData_t gInitCfgData = + DSL_DEV_HS_TONE_GROUP_CLEANED, \ + DSL_DEV_HS_TONE_GROUP_CLEANED, \ + DSL_DEV_HS_TONE_GROUP_CLEANED, \ +- 0x1E116000, 0x37, -1), ++ 0x1E116000, 0x3f, -1), + DSL_CPE_SIC_SET(DSL_TC_ATM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII, \ + DSL_TC_EFM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII), + DSL_CPE_MAC_CFG_SET(DSL_EFM_SPEED_100, DSL_EFM_DUPLEX_FULL, DSL_EFM_FLOWCTRL_ON, DSL_EFM_AUTONEG_OFF, \ diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch b/package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch new file mode 100644 index 00000000000..0c02bb17b75 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch @@ -0,0 +1,87 @@ +--- a/src/dsl_cpe_control.h ++++ b/src/dsl_cpe_control.h +@@ -13,6 +13,8 @@ + #ifndef _DSL_CPE_CONTROL_H + #define _DSL_CPE_CONTROL_H + ++#include ++ + /** \defgroup DSL_CPE_CONTROL Lantiq DSL CPE API Control Application + Lists the entire modules to the DSL CPE_API Control Application. + @{ */ +--- a/src/dsl_cpe_safec_wrapper.h ++++ b/src/dsl_cpe_safec_wrapper.h +@@ -23,7 +23,7 @@ + #define cpe_control_vsnprintf_s vsnprintf_s + + /* snprintf_s symbol is not exported in SafeC lib */ +-static int cpe_control_snprintf_s(char *dest, ++static inline int cpe_control_snprintf_s(char *dest, + size_t dmax, + const char *fmt, + ...) +@@ -40,7 +40,7 @@ static int cpe_control_snprintf_s(char * + + #else + +-#warning "Safe C library is not available!" ++//#warning "Safe C library is not available!" + + #include /* size_t */ + #include /* va_list */ +@@ -55,7 +55,7 @@ static __inline__ size_t safec_wrapper_m + #define cpe_control_memset_s(dest, destsz, src, srcsz) memset(dest, src, safec_wrapper_min(destsz,srcsz)) + #define cpe_control_strncpy_s(dest, destsz, src, srcsz) strncpy(dest, src, safec_wrapper_min(destsz,srcsz)) + +-static size_t cpe_control_strnlen_s(const char *str, ++static inline size_t cpe_control_strnlen_s(const char *str, + size_t smax) + { + /* preconditions */ +@@ -74,7 +74,7 @@ static size_t cpe_control_strnlen_s(cons + return size; + } + +-static char *cpe_control_strtok_s(char *dest, ++static inline char *cpe_control_strtok_s(char *dest, + size_t *dmax, + const char *delim, + char **ptr) +@@ -123,7 +123,7 @@ static char *cpe_control_strtok_s(char * + return pTmp; + } + +-static int cpe_control_pipe_strcat_s(char *dest, ++static inline int cpe_control_pipe_strcat_s(char *dest, + size_t destsz, + char *src) + { +@@ -157,7 +157,7 @@ static int cpe_control_pipe_strcat_s(cha + return 0; + } + +-static int cpe_control_snprintf_s(char *dest, ++static inline int cpe_control_snprintf_s(char *dest, + size_t dmax, + const char *fmt, + ...) +@@ -181,7 +181,7 @@ static int cpe_control_snprintf_s(char * + return retVal; + } + +-static int cpe_control_vsnprintf_s(char *dest, ++static inline int cpe_control_vsnprintf_s(char *dest, + size_t dmax, + const char *fmt, + va_list vlist) +--- a/tools/pipe/dsl_cpe_safec_wrapper.h ++++ b/tools/pipe/dsl_cpe_safec_wrapper.h +@@ -27,7 +27,7 @@ + + #else + +-#warning "Safe C library is not available!" ++//#warning "Safe C library is not available!" + + #include /* size_t */ + static __inline__ size_t safec_wrapper_min(size_t a, size_t b) diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch b/package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch new file mode 100644 index 00000000000..c3e9b966204 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch @@ -0,0 +1,85 @@ +This enables automatic connection after the control daemon is started, +and also changes the way the connection is stopped on termination. + +Using the autoboot restart command is necessary because the stop command +would stop the autoboot thread, and the driver offers no working way to +start it again later, short of unloading and reloading the module. + +--- a/src/dsl_cpe_init_cfg.c ++++ b/src/dsl_cpe_init_cfg.c +@@ -27,7 +27,7 @@ DSL_InitData_t gInitCfgData = + DSL_CPE_FW2_SET(DSL_NULL, 0x0), + DSL_CPE_XTU_SET(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7), + DSL_CPE_LINE_INV_NE_SET(DSL_NULL), +- DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_STOP), ++ DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_START), + DSL_CPE_AUTOBOOT_CFG_SET(DSL_FALSE, DSL_FALSE, DSL_FALSE), + DSL_CPE_TEST_MODE_CTRL_SET(DSL_TESTMODE_DISABLE), + DSL_CPE_LINE_ACTIVATE_CTRL_SET(DSL_G997_INHIBIT_LDSF, DSL_G997_INHIBIT_ACSF, DSL_G997_NORMAL_STARTUP), +--- a/src/dsl_cpe_control.c ++++ b/src/dsl_cpe_control.c +@@ -7338,6 +7338,7 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi + { + DSL_Error_t nRet = DSL_SUCCESS; + DSL_int_t nDevice = 0; ++ DSL_AutobootConfig_t sAutobootCfg; + DSL_AutobootControl_t sAutobootCtl; + DSL_CPE_Control_Context_t *pCtrlCtx = DSL_NULL; + +@@ -7349,8 +7350,32 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi + + for (nDevice = 0; nDevice < DSL_CPE_DSL_ENTITIES; ++nDevice) + { ++ g_bWaitBeforeConfigWrite[nDevice] = DSL_TRUE; ++ g_bWaitBeforeLinkActivation[nDevice] = DSL_TRUE; ++ g_bWaitBeforeRestart[nDevice] = DSL_TRUE; ++ ++ g_bAutoContinueWaitBeforeConfigWrite[nDevice] = DSL_FALSE; ++ g_bAutoContinueWaitBeforeLinkActivation[nDevice] = DSL_FALSE; ++ g_bAutoContinueWaitBeforeRestart[nDevice] = DSL_FALSE; ++ ++ memset(&sAutobootCfg, 0x0, sizeof(DSL_AutobootConfig_t)); ++ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeConfigWrite = DSL_TRUE; ++ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeLinkActivation = DSL_TRUE; ++ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeRestart = DSL_TRUE; ++ ++ nRet = (DSL_Error_t)DSL_CPE_Ioctl( ++ DSL_CPE_GetGlobalContext()->fd[nDevice], ++ DSL_FIO_AUTOBOOT_CONFIG_SET, (DSL_int_t)&sAutobootCfg); ++ ++ if (nRet < DSL_SUCCESS) ++ { ++ DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX ++ "Autoboot configuration for device (%d) failed!, nRet = %d!" ++ DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn)); ++ } ++ + memset(&sAutobootCtl, 0, sizeof(DSL_AutobootControl_t)); +- sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_STOP; ++ sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_RESTART; + + nRet = (DSL_Error_t)DSL_CPE_Ioctl( + DSL_CPE_GetGlobalContext()->fd[nDevice], +@@ -7359,13 +7384,13 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi + if (nRet < DSL_SUCCESS) + { + DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX +- "Autoboot stop for device (%d) failed!, nRet = %d!" ++ "Autoboot restart for device (%d) failed!, nRet = %d!" + DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn)); + } + } + + DSL_CCA_DEBUG(DSL_CCA_DBG_MSG, (DSL_CPE_PREFIX +- "Autoboot stop executed" DSL_CPE_CRLF)); ++ "Autoboot restart executed" DSL_CPE_CRLF)); + + DSL_CPE_DaemonExit(); + +@@ -8798,4 +8823,4 @@ DSL_CPE_STATIC DSL_Error_t DSL_CPE_Firmw + pDecimal)); + + return nErrCode; +-} +\ No newline at end of file ++} diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch b/package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch new file mode 100644 index 00000000000..fc0dd70bc1b --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch @@ -0,0 +1,50 @@ +--- a/src/dsl_cpe_control.c ++++ b/src/dsl_cpe_control.c +@@ -221,6 +221,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe + #endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/ + #endif + ++extern void ubus_init(); ++extern void ubus_deinit(); ++ + DSL_char_t *g_sFirmwareName1 = DSL_NULL; + DSL_FirmwareFeatures_t g_nFwFeatures1 = {DSL_FW_XDSLMODE_CLEANED, DSL_FW_XDSLFEATURE_CLEANED, + DSL_FW_XDSLFEATURE_CLEANED}; +@@ -7831,6 +7834,8 @@ DSL_int_t dsl_cpe_daemon ( + #endif /* defined(INCLUDE_DSL_JSON_PARSING) && (INCLUDE_DSL_JSON_PARSING == 1) */ + #endif /* RTEMS*/ + ++ ubus_init(); ++ + /* Open DSL_CPE_MAX_DSL_ENTITIES devices*/ + for (nDevice = 0; nDevice < DSL_CPE_DSL_ENTITIES; nDevice++) + { +@@ -8367,6 +8372,7 @@ DSL_int_t dsl_cpe_daemon ( + #endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */ + + DSL_CPE_CONTROL_EXIT: ++ ubus_deinit(); + + if (INCLUDE_DSL_BONDING) + { +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -17,7 +17,7 @@ else + dsl_cpe_control_common_ldflags = + endif + +-dsl_cpe_control_LDADD = -lpthread -lrt ++dsl_cpe_control_LDADD = -lpthread -lrt -lubox -lubus + + if INCLUDE_DSL_CPE_DTI_SUPPORT + dsl_cpe_control_LDADD += -ldti_agent +@@ -118,7 +118,8 @@ dsl_cpe_control_SOURCES = \ + dsl_cpe_control.c \ + dsl_cpe_init_cfg.c \ + dsl_cpe_linux.c \ +- dsl_cpe_debug.c ++ dsl_cpe_debug.c \ ++ dsl_cpe_ubus.c + + dsl_cpe_control_SOURCES += \ + $(dsl_cpe_control_dti_sources) diff --git a/package/network/utils/ltq-dsl-base/Makefile b/package/network/utils/ltq-dsl-base/Makefile index 2ff069ca4dc..b51851f076e 100644 --- a/package/network/utils/ltq-dsl-base/Makefile +++ b/package/network/utils/ltq-dsl-base/Makefile @@ -17,7 +17,7 @@ define Package/ltq-dsl-base CATEGORY:=Network TITLE:=DSL related files for Intel/Lantiq DSL Chipsets URL:=http://openwrt.org/ - DEPENDS:=@TARGET_lantiq +jshn + DEPENDS:=@(TARGET_lantiq||TARGET_ipq40xx) +jshn endef define Package/ltq-dsl-base/description diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile index 2eebe50a4fa..56aa9e0b358 100644 --- a/package/system/procd/Makefile +++ b/package/system/procd/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=procd -PKG_RELEASE:=$(AUTORELEASE) +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git -PKG_MIRROR_HASH:=d60b4aa9d47d75e906dfd812528a1bc28e91f5af72a9d9275056b71b19d99f04 -PKG_SOURCE_DATE:=2022-11-10 -PKG_SOURCE_VERSION:=039b88f75367203e540009cc97603b1bce3fafa6 +PKG_MIRROR_HASH:=75a92c01ef85f41dc7e0b77ac35f464fbe45942af02ca6847516c4ebf574c4a4 +PKG_SOURCE_DATE:=2023-01-16 +PKG_SOURCE_VERSION:=190f13a75e67e0bdb662188da79b8be31e0aae01 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 diff --git a/target/linux/archs38/Makefile b/target/linux/archs38/Makefile index fb00884a9af..42b4edad8a9 100644 --- a/target/linux/archs38/Makefile +++ b/target/linux/archs38/Makefile @@ -11,8 +11,7 @@ BOARDNAME:=Synopsys DesignWare ARC HS38 FEATURES:=source-only SUBTARGETS:=generic -KERNEL_PATCHVER:=5.10 -KERNEL_TESTING_PATCHVER:=5.15 +KERNEL_PATCHVER:=5.15 DEVICE_TYPE:=basic diff --git a/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch b/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch index aea6a605a90..c76a00eabd8 100644 --- a/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch +++ b/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch @@ -357,7 +357,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov h_source, h_dest, ntohs(l2->etype), - l2->vlan1, l2->vlan2, entry->ib1, ib2); + l2->vlan1, l2->vlan2, entry->ib1, ib2, -+ acct->packets, acct->bytes); ++ acct ? acct->packets : 0, acct ? acct->bytes : 0); } return 0; diff --git a/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/target/linux/ipq40xx/base-files/etc/board.d/01_leds index 2bcbd954824..3ba130cc909 100644 --- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds +++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds @@ -28,9 +28,8 @@ avm,fritzbox-4040) ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan" ucidef_set_led_switch "lan" "LAN" "green:lan" "switch0" "0x1e" ;; -avm,fritzbox-7530 |\ -glinet,gl-b1300 |\ -mikrotik,lhgg-60ad) +avm,fritzbox-7530) + ucidef_set_led_netdev "dsl" "DSL" "green:info" "dsl0" ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" ;; edgecore,oap100) @@ -56,6 +55,10 @@ engenius,ens620ext) glinet,gl-ap1300) ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" ;; +glinet,gl-b1300 |\ +mikrotik,lhgg-60ad) + ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" + ;; mikrotik,cap-ac) ucidef_set_led_default "power" "POWER" "blue:power" "1" ucidef_set_led_default "user" "USER" "green:user" "0" diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network index ced26b9dd3f..7d4806b6053 100644 --- a/target/linux/ipq40xx/base-files/etc/board.d/02_network +++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network @@ -98,6 +98,26 @@ ipq40xx_setup_interfaces() esac } +ipq40xx_setup_dsl() +{ + local board="$1" + local annex="j" + local tone="b" + local xfer_mode="" + + case "$board" in + avm,fritzbox-7530) + ;; + *) + return 0 + ;; + esac + + ucidef_add_atm_bridge "1" "32" "llc" "bridged" "dsl" + ucidef_add_vdsl_modem "$annex" "$tone" "$xfer_mode" + ucidef_set_interface_wan "dsl0" "pppoe" +} + ipq40xx_setup_macs() { local board="$1" @@ -117,6 +137,10 @@ ipq40xx_setup_macs() lan_mac=$(mtd_get_mac_binary_ubi Factory 0x5006) label_mac=$wan_mac ;; + avm,fritzbox-7530) + local tffsdev=$(find_mtd_chardev "nand-tffs") + wan_mac=$(/usr/bin/fritz_tffs_nand -b -d $tffsdev -n macdsl) + ;; cilab,meshpoint-one) label_mac=$(mtd_get_mac_binary "ART" 0x1006) ;; @@ -185,6 +209,7 @@ ipq40xx_setup_macs() board_config_update board=$(board_name) ipq40xx_setup_interfaces $board +ipq40xx_setup_dsl $board ipq40xx_setup_macs $board board_config_flush diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts index a0ceb299b49..336da52f272 100644 --- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts @@ -9,11 +9,15 @@ model = "AVM FRITZ!Box 7530"; compatible = "avm,fritzbox-7530"; + chosen { + bootargs-append = " coherent_pool=4M"; + }; + aliases { led-boot = &power_green; led-failsafe = &info_red; led-running = &power_green; - led-upgrade = &info_green; + led-upgrade = &info_red; }; soc { @@ -92,7 +96,7 @@ gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; }; - info_green: info { + info { label = "green:info"; gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; }; diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk index dcf0cb20aa2..deec544f658 100644 --- a/target/linux/ipq40xx/image/generic.mk +++ b/target/linux/ipq40xx/image/generic.mk @@ -274,7 +274,7 @@ define Device/avm_fritzbox-7530 DEVICE_ALT0_VENDOR := AVM DEVICE_ALT0_MODEL := FRITZ!Box 7520 SOC := qcom-ipq4019 - DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand + DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand ltq-vdsl-vr11-app endef TARGET_DEVICES += avm_fritzbox-7530 diff --git a/target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch b/target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch new file mode 100644 index 00000000000..c15a4b3ae3e --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch @@ -0,0 +1,43 @@ +From: John Crispin +Date: Fri, 3 Aug 2012 10:27:25 +0200 +Subject: [PATCH 04/36] MIPS: lantiq: add atm hack + +Signed-off-by: John Crispin +--- 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 */ +@@ -155,6 +161,9 @@ struct atm_trafprm { + unsigned int adtf :10; /* ACR Decrease Time Factor (10-bit) */ + unsigned int cdf :3; /* Cutoff Decrease Factor (3-bit) */ + unsigned int spare :9; /* spare bits */ ++ int scr; /* sustained rate in cells per second */ ++ int mbs; /* maximum burst size (MBS) in cells */ ++ int cdv; /* Cell delay variation */ + }; + + struct atm_qos { +--- 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 */ diff --git a/target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch b/target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch new file mode 100644 index 00000000000..b774fc39d8c --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch @@ -0,0 +1,137 @@ +From: Subhra Banerjee +Date: Fri, 31 Aug 2018 12:01:19 +0530 +Subject: [PATCH] UGW_SW-29163: ATM oam support + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2952,6 +2952,22 @@ char *ppp_dev_name(struct ppp_channel *c + return name; + } + ++/* ++ * Return the PPP device interface pointer ++ */ ++struct net_device *ppp_device(struct ppp_channel *chan) ++{ ++ struct channel *pch = chan->ppp; ++ struct net_device *dev = NULL; ++ ++ if (pch) { ++ read_lock_bh(&pch->upl); ++ if (pch->ppp && pch->ppp->dev) ++ dev = pch->ppp->dev; ++ read_unlock_bh(&pch->upl); ++ } ++ return dev; ++} + + /* + * Disconnect a channel from the generic layer. +@@ -3598,6 +3614,7 @@ EXPORT_SYMBOL(ppp_unregister_channel); + EXPORT_SYMBOL(ppp_channel_index); + EXPORT_SYMBOL(ppp_unit_number); + EXPORT_SYMBOL(ppp_dev_name); ++EXPORT_SYMBOL(ppp_device); + EXPORT_SYMBOL(ppp_input); + EXPORT_SYMBOL(ppp_input_error); + EXPORT_SYMBOL(ppp_output_wakeup); +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -74,6 +74,9 @@ extern int ppp_unit_number(struct ppp_ch + /* Get the device name associated with a channel, or NULL if none */ + extern char *ppp_dev_name(struct ppp_channel *); + ++/* Get the device pointer associated with a channel, or NULL if none */ ++extern struct net_device *ppp_device(struct ppp_channel *); ++ + /* + * SMP locking notes: + * The channel code must ensure that when it calls ppp_unregister_channel, +--- a/net/atm/Kconfig ++++ b/net/atm/Kconfig +@@ -56,6 +56,12 @@ config ATM_MPOA + subnetwork boundaries. These shortcut connections bypass routers + enhancing overall network performance. + ++config ATM_MPOA_INTEL_DSL_PHY_SUPPORT ++ bool "Intel DSL Phy MPOA support" ++ depends on ATM && INET && ATM_MPOA!=n ++ help ++ Add support for Intel DSL Phy ATM MPOA ++ + config ATM_BR2684 + tristate "RFC1483/2684 Bridged protocols" + depends on ATM && INET +--- a/net/atm/br2684.c ++++ b/net/atm/br2684.c +@@ -596,6 +596,11 @@ static int br2684_regvcc(struct atm_vcc + atmvcc->push = br2684_push; + atmvcc->pop = br2684_pop; + atmvcc->release_cb = br2684_release_cb; ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* IPoA or EoA w/o FCS */ ++ atm_hook_mpoa_setup(atmvcc, brdev->payload == p_routed ? 3 : 0, ++ brvcc->encaps == BR2684_ENCAPS_LLC ? 1 : 0, net_dev); ++#endif + atmvcc->owner = THIS_MODULE; + + /* initialize netdev carrier state */ +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -137,6 +137,11 @@ static struct proto vcc_proto = { + .release_cb = vcc_release_cb, + }; + ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *) = NULL; ++EXPORT_SYMBOL(atm_hook_mpoa_setup); ++#endif ++ + int vcc_create(struct net *net, struct socket *sock, int protocol, int family, int kern) + { + struct sock *sk; +--- a/net/atm/common.h ++++ b/net/atm/common.h +@@ -53,4 +53,6 @@ int svc_change_qos(struct atm_vcc *vcc,s + + void atm_dev_release_vccs(struct atm_dev *dev); + ++extern void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *); ++ + #endif +--- a/net/atm/mpc.c ++++ b/net/atm/mpc.c +@@ -31,6 +31,7 @@ + /* Modular too */ + #include + ++#include "common.h" + #include "lec.h" + #include "mpc.h" + #include "resources.h" +@@ -645,6 +646,10 @@ static int atm_mpoa_vcc_attach(struct at + vcc->proto_data = mpc->dev; + vcc->push = mpc_push; + ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* IPoA, LLC */ ++ atm_hook_mpoa_setup(vcc, 3, 1, mpc->dev); ++#endif + return 0; + } + +--- a/net/atm/pppoatm.c ++++ b/net/atm/pppoatm.c +@@ -422,6 +422,12 @@ static int pppoatm_assign_vcc(struct atm + atmvcc->user_back = pvcc; + atmvcc->push = pppoatm_push; + atmvcc->pop = pppoatm_pop; ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* PPPoA */ ++ atm_hook_mpoa_setup(atmvcc, 2, ++ pvcc->encaps == e_llc ? 1 : 0, ++ ppp_device(&pvcc->chan)); ++#endif + atmvcc->release_cb = pppoatm_release_cb; + __module_get(THIS_MODULE); + atmvcc->owner = THIS_MODULE; diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index c2808bc7368..93b202218a8 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -43,17 +43,20 @@ platform_do_upgrade() { case "$board" in bananapi,bpi-r3) - case "$(cmdline_get_var root)" in - /dev/mmc*) + local rootdev="$(cmdline_get_var root)" + rootdev="${rootdev##*/}" + rootdev="${rootdev%p[0-9]*}" + case "$rootdev" in + mmc*) CI_ROOTDEV="$rootdev" CI_KERNPART="production" emmc_do_upgrade "$1" ;; - /dev/mtdblock*) + mtdblock*) PART_NAME="fit" default_do_upgrade "$1" ;; - /dev/ubiblock*) + ubiblock*) CI_KERNPART="fit" nand_do_upgrade "$1" ;; diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh index e62eba7ef17..d3d503dd1ef 100755 --- a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh @@ -8,6 +8,7 @@ platform_do_upgrade() { bananapi,bpi-r64) local rootdev="$(cmdline_get_var root)" rootdev="${rootdev##*/}" + rootdev="${rootdev%p[0-9]*}" case "$rootdev" in mmc*) CI_ROOTDEV="$rootdev" diff --git a/tools/Makefile b/tools/Makefile index c7c7d007563..a8044dcf1fe 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -20,6 +20,12 @@ endif ifneq ($(CONFIG_SDK)$(CONFIG_PACKAGE_kmod-b43)$(CONFIG_BRCMSMAC_USE_FW_FROM_WL),) BUILD_B43_TOOLS = y endif +ifneq ($(CONFIG_SDK)$(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),) + BUILD_LZ4_TOOLS = y +endif +ifneq ($(CONFIG_SDK)$(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),) + BUILD_LZO_TOOLS = y +endif tools-y += autoconf tools-y += autoconf-archive @@ -59,8 +65,11 @@ tools-y += sstrip tools-y += zip tools-y += zlib tools-y += zstd +tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS),y) += liblzo tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_B43_TOOLS),y) += b43-tools tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_ISL),y) += isl +tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_LZ4_TOOLS),y) += lz4 +tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_LZO_TOOLS),y) += lzop tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_TOOLCHAIN),y) += gmp mpc mpfr tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_TARGET_apm821xx)$(CONFIG_TARGET_gemini),y) += genext2fs tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_TARGET_ath79),y) += lzma-old squashfs @@ -90,9 +99,11 @@ $(curdir)/gengetopt/compile := $(curdir)/libtool/compile $(curdir)/gmp/compile := $(curdir)/libtool/compile $(curdir)/isl/compile := $(curdir)/gmp/compile $(curdir)/libdeflate/compile := $(curdir)/cmake/compile +$(curdir)/liblzo/compile := $(curdir)/cmake/compile $(curdir)/libressl/compile := $(curdir)/pkgconf/compile $(curdir)/libtool/compile := $(curdir)/automake/compile $(curdir)/missing-macros/compile $(curdir)/lzma-old/compile := $(curdir)/zlib/compile +$(curdir)/lzop/compile := $(curdir)/cmake/compile $(curdir)/liblzo/compile $(curdir)/llvm-bpf/compile := $(curdir)/cmake/compile $(curdir)/make-ext4fs/compile := $(curdir)/zlib/compile $(curdir)/meson/compile := $(curdir)/ninja/compile diff --git a/tools/dosfstools/patches/source-date-epoch.patch b/tools/dosfstools/patches/100-source-date-epoch.patch similarity index 93% rename from tools/dosfstools/patches/source-date-epoch.patch rename to tools/dosfstools/patches/100-source-date-epoch.patch index fb46753f247..c758caa4c1d 100644 --- a/tools/dosfstools/patches/source-date-epoch.patch +++ b/tools/dosfstools/patches/100-source-date-epoch.patch @@ -19,8 +19,6 @@ Signed-off-by: Bjørn Forsman src/mkfs.fat.c | 19 ++++++++++++++++--- 3 files changed, 53 insertions(+), 7 deletions(-) -diff --git a/src/boot.c b/src/boot.c -index 4de450d..8f78e1c 100644 --- a/src/boot.c +++ b/src/boot.c @@ -33,6 +33,8 @@ @@ -32,7 +30,7 @@ index 4de450d..8f78e1c 100644 #include "common.h" #include "fsck.fat.h" -@@ -672,6 +674,7 @@ void write_volume_label(DOS_FS * fs, char *label) +@@ -672,6 +674,7 @@ void write_volume_label(DOS_FS * fs, cha { time_t now; struct tm *mtime; @@ -40,7 +38,7 @@ index 4de450d..8f78e1c 100644 off_t offset; int created; DIR_ENT de; -@@ -687,8 +690,24 @@ void write_volume_label(DOS_FS * fs, char *label) +@@ -687,8 +690,24 @@ void write_volume_label(DOS_FS * fs, cha if (de.name[0] == 0xe5) de.name[0] = 0x05; @@ -67,8 +65,6 @@ index 4de450d..8f78e1c 100644 if (mtime && mtime->tm_year >= 80 && mtime->tm_year <= 207) { de.time = htole16((unsigned short)((mtime->tm_sec >> 1) + (mtime->tm_min << 5) + -diff --git a/src/common.c b/src/common.c -index 6a2e396..4f1afcb 100644 --- a/src/common.c +++ b/src/common.c @@ -30,6 +30,7 @@ @@ -83,10 +79,9 @@ index 6a2e396..4f1afcb 100644 uint32_t generate_volume_id(void) { struct timeval now; -- -- if (gettimeofday(&now, NULL) != 0 || now.tv_sec == (time_t)-1 || now.tv_sec < 0) { + char *source_date_epoch = NULL; -+ + +- if (gettimeofday(&now, NULL) != 0 || now.tv_sec == (time_t)-1 || now.tv_sec < 0) { + source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + char *tmp = NULL; @@ -103,8 +98,6 @@ index 6a2e396..4f1afcb 100644 srand(getpid()); /* rand() returns int from [0,RAND_MAX], therefore only 31 bits */ return (((uint32_t)(rand() & 0xFFFF)) << 16) | ((uint32_t)(rand() & 0xFFFF)); -diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c -index 37fc8ff..1948635 100644 --- a/src/mkfs.fat.c +++ b/src/mkfs.fat.c @@ -1074,7 +1074,7 @@ static void setup_tables(void) @@ -154,4 +147,4 @@ index 37fc8ff..1948635 100644 + volume_id = generate_volume_id(); check_atari(); - \ No newline at end of file + diff --git a/tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch b/tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch new file mode 100644 index 00000000000..ba2d00bf84b --- /dev/null +++ b/tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch @@ -0,0 +1,28 @@ +From e7671c2a3be03d790cbc225cd3e784b5434fb5da Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 16 Jan 2023 01:29:22 +0100 +Subject: [PATCH] config: switch to AC_CHECK_LIB + +This fixes spurious build-errors on OpenWrt, where the AM_ICONV macro +is undefined while invoking autoconfig. Later in the build, the ICONV +LDOPTIONS are set to @LIBICONV@, failing the build. + +Signed-off-by: David Bauer +--- + configure.ac | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -70,10 +70,7 @@ AC_CHECK_DECLS([getmntent], [], [], [[#i + AC_CHECK_DECLS([getmntinfo], [], [], [[#include ]]) + + # optional iconv support +-AC_ARG_WITH([iconv], AS_HELP_STRING([--without-iconv], [build without iconv support])) +-if test "x$with_iconv" != "xno"; then +- AM_ICONV +-fi ++AC_CHECK_LIB(iconv, iconv_open) + + # xxd (distributed with vim) is used in the testsuite + AC_CHECK_PROG([XXD_FOUND], [xxd], [yes]) diff --git a/tools/liblzo/Makefile b/tools/liblzo/Makefile new file mode 100644 index 00000000000..4ebda0c3336 --- /dev/null +++ b/tools/liblzo/Makefile @@ -0,0 +1,42 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lzo +PKG_VERSION:=2.10 +PKG_RELEASE:=4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.oberhumer.com/opensource/lzo/download/ +PKG_HASH:=c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +CMAKE_BINARY_SUBDIR:=openwrt-build + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/cmake.mk + +CMAKE_HOST_OPTIONS += \ + -DENABLE_SHARED=ON \ + -DENABLE_TESTS=OFF \ + -DENABLE_EXAMPLES=OFF \ + -DENABLE_DOCS=ON \ + -DBUILD_TESTING=OFF + +define Host/Uninstall + rm -rf $(HOST_BUILD_PREFIX)/include/lzo + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.a + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.so.2.0.0 + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.so.2 + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.so + rm -f $(HOST_BUILD_PREFIX)/lib/pkgconfig/lzo2.pc +endef + +$(eval $(call HostBuild)) diff --git a/tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch b/tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch new file mode 100644 index 00000000000..9ab27fc924a --- /dev/null +++ b/tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch @@ -0,0 +1,68 @@ +--- a/CMakeLists.txt 2022-11-28 06:34:39.171209779 -0800 ++++ b/CMakeLists.txt 2022-11-28 06:33:13.368239757 -0800 +@@ -51,8 +51,11 @@ + project(lzo VERSION 2.10 LANGUAGES C) + + # configuration options +-option(ENABLE_STATIC "Build static LZO library." ON) +-option(ENABLE_SHARED "Build shared LZO library." OFF) ++option(ENABLE_STATIC "Build static LZO library." ON) ++option(ENABLE_SHARED "Build shared LZO library." OFF) ++option(ENABLE_TESTS "Build tests." ON) ++option(ENABLE_EXAMPLES "Build examples." ON) ++option(ENABLE_DOCS "Install documentation." ON) + if(NOT ENABLE_STATIC AND NOT ENABLE_SHARED) + set(ENABLE_STATIC ON) + endif() +@@ -127,14 +130,20 @@ + endif() + endmacro() + # main test driver ++if(ENABLE_TESTS OR ENABLE_EXAMPLES) + lzo_add_executable(lzotest lzotest/lzotest.c) ++endif() + # examples ++if(ENABLE_EXAMPLES) + lzo_add_executable(dict examples/dict.c) + lzo_add_executable(lzopack examples/lzopack.c) + lzo_add_executable(overlap examples/overlap.c) + lzo_add_executable(precomp examples/precomp.c) + lzo_add_executable(precomp2 examples/precomp2.c) ++endif() ++if(ENABLE_TESTS OR ENABLE_EXAMPLES) + lzo_add_executable(simple examples/simple.c) ++endif() + # some boring internal test programs + if(0) + lzo_add_executable(align tests/align.c) +@@ -144,7 +153,7 @@ + endif() + + # miniLZO +-if(1) ++if(ENABLE_TESTS) + add_executable(testmini minilzo/testmini.c minilzo/minilzo.c) + target_include_directories(testmini PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/lzo") # needed for "lzoconf.h" + endif() +@@ -263,8 +272,10 @@ + + if(DEFINED CMAKE_INSTALL_FULL_LIBDIR) + +-set(f AUTHORS COPYING NEWS THANKS doc/LZO.FAQ doc/LZO.TXT doc/LZOAPI.TXT) +-install(FILES ${f} DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}") ++if(ENABLE_DOCS) ++ set(f AUTHORS COPYING NEWS THANKS doc/LZO.FAQ doc/LZO.TXT doc/LZOAPI.TXT) ++ install(FILES ${f} DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}") ++endif() + + set(f include/lzo/lzo1.h include/lzo/lzo1a.h include/lzo/lzo1b.h + include/lzo/lzo1c.h include/lzo/lzo1f.h include/lzo/lzo1x.h +@@ -285,7 +296,7 @@ + ) + endif() + +-if(1) ++if(ENABLE_EXAMPLES) + set(f lzopack lzotest simple testmini) # examples + install(TARGETS ${f} DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/lzo/examples") + endif() diff --git a/tools/lz4/Makefile b/tools/lz4/Makefile new file mode 100644 index 00000000000..c5d4f6f16b2 --- /dev/null +++ b/tools/lz4/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lz4 +PKG_VERSION:=1.9.4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/lz4/lz4/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=0b0e3aa07c8c063ddf40b082bdf7e37a1562bda40a0ff5272957f3e987e0e54b + +PKG_LICENSE:=BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE lib/LICENSE + +HOST_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/host-build.mk + +# Always optimize for speed +HOST_CFLAGS := $(filter-out -O%,$(HOST_CFLAGS)) -O3 + +HOST_MAKE_FLAGS+=PREFIX=$(HOST_BUILD_PREFIX) \ + ENABLE_DOCS=1 + +define Host/Configure +endef + +define Host/Compile + $(call Host/Compile/Default,default) +endef + +define Host/Install + $(call Host/Compile/Default,install) +endef + +define Host/Uninstall + $(call Host/Compile/Default,uninstall) + $(call Host/Compile/Default,clean) +endef + +define Host/Clean +endef + +$(eval $(call HostBuild)) diff --git a/tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch b/tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch new file mode 100644 index 00000000000..5d6dca33f31 --- /dev/null +++ b/tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch @@ -0,0 +1,60 @@ ++++ a/programs/Makefile 2022-08-15 15:45:31.000000000 -0700 +--- b/programs/Makefile 2022-11-28 16:34:21.315593784 -0800 +@@ -66,6 +66,7 @@ + MD2ROFF = ronn + MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="lz4 $(LZ4_VERSION)" + ++ENABLE_DOCS ?= 1 + + default: lz4-release + +@@ -120,6 +121,7 @@ + lz4c32 : $(SRCFILES) + $(CC) $(FLAGS) $^ -o $@$(EXT) + ++ifeq ($(ENABLE_DOCS),1) + lz4.1: lz4.1.md $(LIBVER_SRC) + cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | $(SED) -n '/^\.\\\".*/!p' > $@ + +@@ -130,6 +132,7 @@ + + preview-man: clean-man man + man ./lz4.1 ++endif + + clean: + ifeq ($(WINBASED),yes) +@@ -172,16 +175,19 @@ + + install: lz4 + @echo Installing binaries in $(DESTDIR)$(bindir) +- $(INSTALL_DIR) $(DESTDIR)$(bindir)/ $(DESTDIR)$(man1dir)/ ++ $(INSTALL_DIR) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) lz4$(EXT) $(DESTDIR)$(bindir)/lz4$(EXT) + $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4c$(EXT) + $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4cat$(EXT) + $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/unlz4$(EXT) ++ifeq ($(ENABLE_DOCS),1) + @echo Installing man pages in $(DESTDIR)$(man1dir) ++ $(INSTALL_DIR) $(DESTDIR)$(man1dir)/ + $(INSTALL_DATA) lz4.1 $(DESTDIR)$(man1dir)/lz4.1 + $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4c.1 + $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4cat.1 + $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/unlz4.1 ++endif + @echo lz4 installation completed + + uninstall: +@@ -189,10 +195,12 @@ + $(RM) $(DESTDIR)$(bindir)/unlz4$(EXT) + $(RM) $(DESTDIR)$(bindir)/lz4$(EXT) + $(RM) $(DESTDIR)$(bindir)/lz4c$(EXT) ++ifeq ($(ENABLE_DOCS),1) + $(RM) $(DESTDIR)$(man1dir)/lz4.1 + $(RM) $(DESTDIR)$(man1dir)/lz4c.1 + $(RM) $(DESTDIR)$(man1dir)/lz4cat.1 + $(RM) $(DESTDIR)$(man1dir)/unlz4.1 ++endif + @echo lz4 programs successfully uninstalled + + endif diff --git a/tools/lz4/patches/002-makefile-install-links-from-same-dir.patch b/tools/lz4/patches/002-makefile-install-links-from-same-dir.patch new file mode 100644 index 00000000000..159dc67f1af --- /dev/null +++ b/tools/lz4/patches/002-makefile-install-links-from-same-dir.patch @@ -0,0 +1,71 @@ +diff -ur a/lib/Makefile b/lib/Makefile +--- a/lib/Makefile 2022-12-04 23:49:06.336839263 -0800 ++++ b/lib/Makefile 2022-12-05 00:00:59.172307488 -0800 +@@ -195,8 +195,8 @@ + $(INSTALL_PROGRAM) dll/$(LIBLZ4_EXP) $(DESTDIR)$(libdir) + else + $(INSTALL_PROGRAM) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir) +- $(LN_SF) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT_MAJOR) +- $(LN_SF) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT) ++ (cd $(DESTDIR)$(libdir) && $(LN_SF) liblz4.$(SHARED_EXT_VER) liblz4.$(SHARED_EXT_MAJOR)) ++ (cd $(DESTDIR)$(libdir) && $(LN_SF) liblz4.$(SHARED_EXT_MAJOR) liblz4.$(SHARED_EXT)) + endif + endif + @echo Installing headers in $(DESTDIR)$(includedir) +diff -ur a/Makefile b/Makefile +--- a/Makefile 2022-12-04 23:49:06.336839263 -0800 ++++ b/Makefile 2022-12-04 23:42:09.693836654 -0800 +@@ -77,12 +77,12 @@ + + .PHONY: clean + clean: +- $(MAKE) -C $(LZ4DIR) $@ > $(VOID) +- $(MAKE) -C $(PRGDIR) $@ > $(VOID) +- $(MAKE) -C $(TESTDIR) $@ > $(VOID) +- $(MAKE) -C $(EXDIR) $@ > $(VOID) +- $(MAKE) -C $(FUZZDIR) $@ > $(VOID) +- $(MAKE) -C contrib/gen_manual $@ > $(VOID) ++ $(MAKE) -C $(LZ4DIR) $@ ++ $(MAKE) -C $(PRGDIR) $@ ++ $(MAKE) -C $(TESTDIR) $@ ++ $(MAKE) -C $(EXDIR) $@ ++ $(MAKE) -C $(FUZZDIR) $@ ++ $(MAKE) -C contrib/gen_manual $@ + $(RM) lz4$(EXT) + $(RM) -r $(CMAKE_BUILD_DIR) + @echo Cleaning completed +diff -ur a/programs/Makefile b/programs/Makefile +--- a/programs/Makefile 2022-12-04 23:49:06.336839263 -0800 ++++ b/programs/Makefile 2022-12-04 23:42:30.849582910 -0800 +@@ -138,7 +138,7 @@ + ifeq ($(WINBASED),yes) + $(RM) *.rc + endif +- $(MAKE) -C $(LZ4DIR) $@ > $(VOID) ++ $(MAKE) -C $(LZ4DIR) $@ + $(RM) core *.o *.test tmp* \ + lz4$(EXT) lz4c$(EXT) lz4c32$(EXT) lz4-wlib$(EXT) \ + unlz4$(EXT) lz4cat$(EXT) +@@ -177,16 +177,16 @@ + @echo Installing binaries in $(DESTDIR)$(bindir) + $(INSTALL_DIR) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) lz4$(EXT) $(DESTDIR)$(bindir)/lz4$(EXT) +- $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4c$(EXT) +- $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4cat$(EXT) +- $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/unlz4$(EXT) ++ (cd $(DESTDIR)$(bindir) && $(LN_SF) lz4$(EXT) lz4c$(EXT)) ++ (cd $(DESTDIR)$(bindir) && $(LN_SF) lz4$(EXT) lz4cat$(EXT)) ++ (cd $(DESTDIR)$(bindir) && $(LN_SF) lz4$(EXT) unlz4$(EXT)) + ifeq ($(ENABLE_DOCS),1) + @echo Installing man pages in $(DESTDIR)$(man1dir) + $(INSTALL_DIR) $(DESTDIR)$(man1dir)/ + $(INSTALL_DATA) lz4.1 $(DESTDIR)$(man1dir)/lz4.1 +- $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4c.1 +- $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4cat.1 +- $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/unlz4.1 ++ (cd $(DESTDIR)$(man1dir) && $(LN_SF) lz4.1 lz4c.1) ++ (cd $(DESTDIR)$(man1dir) && $(LN_SF) lz4.1 lz4cat.1) ++ (cd $(DESTDIR)$(man1dir) && $(LN_SF) lz4.1 unlz4.1) + endif + @echo lz4 installation completed + diff --git a/tools/lzop/Makefile b/tools/lzop/Makefile new file mode 100644 index 00000000000..65bd7fe67c1 --- /dev/null +++ b/tools/lzop/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lzop +PKG_VERSION:=1.04 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.lzop.org/download/ +PKG_HASH:=7e72b62a8a60aff5200a047eea0773a8fb205caf7acbe1774d95147f305a2f41 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +CMAKE_BINARY_SUBDIR:=openwrt-build + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/cmake.mk + +CMAKE_HOST_OPTIONS += \ + -DENABLE_DOCS=ON \ + -DBUILD_TESTING=OFF + +define Host/Uninstall + rm -f $(STAGING_DIR_HOST)/bin/lzop +endef + +$(eval $(call HostBuild)) diff --git a/tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch b/tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch new file mode 100644 index 00000000000..01ebd33a399 --- /dev/null +++ b/tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch @@ -0,0 +1,24 @@ +--- a/CMakeLists.txt 2017-08-10 04:19:45.000000000 -0700 ++++ b/CMakeLists.txt 2022-11-28 17:21:03.453548350 -0800 +@@ -50,6 +50,9 @@ + + project(lzop VERSION 1.04 LANGUAGES C) + ++# configuration options ++option(ENABLE_DOCS "Install documentation." ON) ++ + # install directories + if(NOT CMAKE_INSTALL_PREFIX) + message(FATAL_ERROR "ERROR: CMAKE_INSTALL_PREFIX is not defined.") +@@ -186,9 +189,11 @@ + + install(TARGETS lzop DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") + ++if(ENABLE_DOCS) + set(f AUTHORS COPYING NEWS README THANKS doc/lzop.html doc/lzop.man doc/lzop.pod doc/lzop.ps doc/lzop.tex doc/lzop.txt) + install(FILES ${f} DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}") + install(FILES doc/lzop.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1") ++endif() # ENABLE_DOCS + + endif() # CMAKE_INSTALL_FULL_LIBDIR +