diff --git a/.circleci/config.yml b/.circleci/config.yml index 978c02fa..4f0eb3c3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,16 +21,28 @@ jobs: echo "${TARGET_DIR}" - run: name: Build - command: make + command: make MAINTARGET=ath79 SUBTARGET=generic no_output_timeout: 2h - run: name: Build - command: make SUBTARGET=mikrotik + command: make MAINTARGET=ath79 SUBTARGET=tiny no_output_timeout: 1h - run: name: Build - command: make MAINTARGET=ath79 + command: make MAINTARGET=ath79 SUBTARGET=mikrotik no_output_timeout: 1h + - run: + name: Build + command: make MAINTARGET=ath79 SUBTARGET=mikrotik ALTTARGET=ath10k + no_output_timeout: 1h + - run: + name: Build + command: make MAINTARGET=ath79 SUBTARGET=nand + no_output_timeout: 1h + - run: + name: Build + command: make MAINTARGET=ipq40xx SUBTARGET=mikrotik + no_output_timeout: 2h - run: name: Compress build files command: tar -cjf ~/${CIRCLE_BRANCH}_${ARTIFACTS_FILE} -C ${MY_WORKING_DIRECTORY}/${ARTIFACTS_DIR} . diff --git a/.gitignore b/.gitignore index ce024300..6ca4b151 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,8 @@ # Files created during make .stamp* firmware -openwrt/ \ No newline at end of file +openwrt/ + +# Other +.DS_Store +._.DS_Store diff --git a/Makefile b/Makefile index c8b6b15c..52261985 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ include openwrt.mk # get main- and subtarget name from TARGET MAINTARGET=$(word 1, $(subst -, ,$(TARGET))) SUBTARGET=$(word 2, $(subst -, ,$(TARGET))) +ALTTARGET=$(word 3, $(subst -, ,$(TARGET))) GIT_BRANCH=$(shell git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,') GIT_COMMIT=$(shell git rev-parse --short HEAD) @@ -11,7 +12,7 @@ GIT_COMMIT=$(shell git rev-parse --short HEAD) # set dir and file names TOP_DIR=$(shell pwd) OPENWRT_DIR=$(TOP_DIR)/openwrt -TARGET_CONFIG=$(TOP_DIR)/configs/common.config $(TOP_DIR)/configs/$(MAINTARGET)-$(SUBTARGET).config +TARGET_CONFIG=$(TOP_DIR)/configs/common.config $(TOP_DIR)/configs/$(MAINTARGET)-$(SUBTARGET)$(patsubst %,-%,$(ALTTARGET)).config UMASK=umask 022 # set variables based on private or CircleCI build @@ -57,6 +58,7 @@ openwrt-clean: stamp-clean-openwrt-cleaned .stamp-openwrt-cleaned ln -sf $(TOP_DIR)/patches $(OPENWRT_DIR)/ ln -sf $(TOP_DIR)/files $(OPENWRT_DIR)/ sed -i "s/^.*freifunk.*$$//" $(OPENWRT_DIR)/feeds.conf.default + sed -i "s/luci.git$$/luci.git;openwrt-22.03/" $(OPENWRT_DIR)/feeds.conf.default touch $@ # update openwrt and checkout specified commit @@ -76,6 +78,7 @@ feeds-update: stamp-clean-feeds-updated .stamp-feeds-updated .stamp-feeds-updated: $(OPENWRT_DIR)/feeds.conf cd $(OPENWRT_DIR); ./scripts/feeds uninstall -a cd $(OPENWRT_DIR); ./scripts/feeds update -a + cd $(OPENWRT_DIR); ./scripts/feeds install libpam cd $(OPENWRT_DIR); ./scripts/feeds install libcap cd $(OPENWRT_DIR); ./scripts/feeds install jansson cd $(OPENWRT_DIR); ./scripts/feeds install libidn2 @@ -84,22 +87,21 @@ feeds-update: stamp-clean-feeds-updated .stamp-feeds-updated cd $(OPENWRT_DIR); ./scripts/feeds install libidn cd $(OPENWRT_DIR); ./scripts/feeds install libopenldap cd $(OPENWRT_DIR); ./scripts/feeds install libgnutls - cd $(OPENWRT_DIR); ./scripts/feeds install libpam cd $(OPENWRT_DIR); ./scripts/feeds install libnetsnmp cd $(OPENWRT_DIR); ./scripts/feeds install -p arednpackages olsrd - cd $(OPENWRT_DIR); ./scripts/feeds install perl cd $(OPENWRT_DIR); ./scripts/feeds install -p arednpackages vtun - cd $(OPENWRT_DIR); ./scripts/feeds install -a -p arednpackages + cd $(OPENWRT_DIR); ./scripts/feeds install -p arednpackages dd-wrt-ath10k-firmware cd $(OPENWRT_DIR); ./scripts/feeds install snmpd + cd $(OPENWRT_DIR); ./scripts/feeds install curl cd $(OPENWRT_DIR); ./scripts/feeds install ntpclient cd $(OPENWRT_DIR); ./scripts/feeds install socat - cd $(OPENWRT_DIR); ./scripts/feeds install xinetd cd $(OPENWRT_DIR); ./scripts/feeds install luci-base cd $(OPENWRT_DIR); ./scripts/feeds install luci-lib-nixio cd $(OPENWRT_DIR); ./scripts/feeds install luci-lib-ip cd $(OPENWRT_DIR); ./scripts/feeds install luci-lib-jsonc - cd $(OPENWRT_DIR); ./scripts/feeds install luaposix cd $(OPENWRT_DIR); ./scripts/feeds install luasocket + cd $(OPENWRT_DIR); ./scripts/feeds install iperf3 + cd $(OPENWRT_DIR); ./scripts/feeds install mii-tool cd $(OPENWRT_DIR); ./scripts/feeds install mmc-utils touch $@ @@ -145,11 +147,26 @@ compile: stamp-clean-compiled .stamp-compiled $(TOP_DIR)/scripts/tests-prebuild.sh $(UMASK); \ $(MAKE) -C $(OPENWRT_DIR) $(MAKE_ARGS) - for FILE in `find $(TOP_DIR)/firmware/targets/ -path "*packages" -prune -o \( -type f -a \ + for FILE in `find $(TOP_DIR)/firmware/targets/$(MAINTARGET)/$(SUBTARGET) -path "*packages" -prune -o \( -type f -a \ ! \( -name "*factory.bin" -o -name "*sysupgrade.bin" -o -name "*initramfs.elf" -o \ - -name sha256sums -o -name "*.buildinfo" -o -name "*.json" \) \ + -name "*kernel.bin" -o -name sha256sums -o -name "*.buildinfo" -o -name "*.json" \) \ -print \)`; do rm $$FILE; \ done; + for FILE in `find $(TOP_DIR)/firmware/targets/$(MAINTARGET)/$(SUBTARGET) -type f -a \ + \( -name "*ath79-generic-*" \ + -o -name "*ath79-tiny-*" \ + -o -name "*ath79-mikrotik-*" \ + -o -name "*ath79-nand-*" \ + -o -name "*ipq40xx-mikrotik*squashfs*" \ + \) -print`; do \ + NEWNAME="$${FILE/generic-/}"; \ + NEWNAME="$${NEWNAME/squashfs-/}"; \ + NEWNAME="$${NEWNAME/-nand-glinet/}"; \ + NEWNAME="$${NEWNAME/-nand/}"; \ + NEWNAME="$${NEWNAME/-ath79-mikrotik/}"; \ + NEWNAME="$${NEWNAME/_routerboard/}"; \ + [ "$$FILE" = "$$NEWNAME" ] || mv "$$FILE" "$$NEWNAME"; \ + done; $(TOP_DIR)/scripts/tests-postbuild.sh $(TOP_DIR)/firmware: diff --git a/README.md b/README.md index af166a55..13d16a6d 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ to no pre-planning or IT expertise. A user can deploy a 'node' anywhere to connect in and extend an AREDN network. Device hardware options exist to provide sector coverage, build point-to-point links, and connect end point services to the network. High speed link rates are routinely achieved -over long distances, e.g. 60Mbps+ on 10MHz channels over 80km links. +over long distances, e.g. 60Mbps+ on 10MHz channels over 80km links. For further information on obtaining an Amateur Radio Technician Class license, please refer to http://www.arrl.org/getting-your-technician-license @@ -46,71 +46,98 @@ turned into a release. Please refer to https://github.com/aredn/aredn/issues for a list of outstanding defects. - ### Images built -Device | target | Image to Use | RAM | Stability ------- | ------ | ------------ | --- | --------- -AirGrid XM | ar71xx | bullet-m | 32Mb | stable -AirGrid XW | ar71xx | loco-m-xw | 32Mb | stable -AirRouter | ath79 | airrouter | 32Mb | stable -AirRouter HP | ath79 | airrouter | 32Mb | stable -Bullet M2Ti/M5/M5Ti | ar71xx | bullet-m | 32Mb | stable -Bullet M2 | ath79 | bullet-m | 32Mb | stable -Bullet M2 XW | ath79 | bullet-m-xw | 64Mb | stable -LiteBeam M5 | ar71xx | lbe-m5 | 64Mb | stable -NanoBeam M2-13/M5-16/M5-19 | ar71xx | loco-m-xw | 32Mb | stable -NanoBridge 2G18 | ar71xx | bullet-m | 32Mb | stable -NanoBridge 5G22/25 | ar71xx | bullet-m | 32Mb | stable -NanoBridge M9 | ar71xx | bullet-m | 32Mb | stable -NanoStation Loco M2/M5/M9 XM | ar71xx | bullet-m | 32Mb | stable -NanoStation Loco M2 XW | ar71xx | loco-m-xw | 64Mb | stable -NanoStation Loco M5 XW with test date before ~Nov 2017| ar71xx | loco-m-xw | 64Mb | stable -NanoStation Loco M5 XW with test date on or after ~Nov 2017 | ar71xx | rocket-m-xw | 64Mb | stable -NanoStation M2/M3/M5 XM | ath79 | nanostation-m | 32Mb | stable -NanoStation M2/M5 XW | ath79 | nanostation-m-xw | 64Mb | stable -PicoStation M2 | ar71xx | bullet-m | 32Mb | stable -PowerBeam-M2-400 | ar71xx | loco-m-xw | 64Mb | stable -PowerBeam-M5-300 | ar71xx | loco-m-xw | 64Mb | stable -PowerBeam-M5-400/400ISO/620 | ar71xx | rocket-m-xw | 64Mb | stable -PowerBridge | ar71xx | nano-m | 64Mb | stable -Rocket M9/M2/M3/M5/M5GPS XM | ath79 | rocket-m | 64Mb | stable -Rocket M2/M5 XM with USB port | ar71xx | rocket-m | 64Mb | stable -Rocket M2 XW | ar71xx | loco-m-xw | 64Mb | stable -Rocket M5 XW | ar71xx | rocket-m-xw | 64Mb | stable -Rocket M2 Titanium TI | ar71xx | rocket-m-ti | 64Mb | unknown -Rocket M2 Titanium XW | ar71xx | rocket-m-xw | 64Mb | unknown -Rocket M5 Titanium TI | ar71xx | rocket-m-ti | 64Mb | stable -Rocket M5 Titanium XW | ar71xx | rocket-m-xw | 64Mb | stable -TPLink CPE210 v1.0/v1.1 | ath79 | cpe210-v1 | 64Mb | stable -TPLink CPE210 v2.0 | ath79 | cpe210-v2 | 64Mb | stable -TPLink CPE210 v3.0 | ath79 | cpe210-v3 | 64Mb | stable -TPLink CPE220 v2.0 | ath79 | cpe220-v2 | 64Mb | stable -TPLink CPE220 v3.0 | ath79 | cpe220-v3 | 64Mb | stable -TPLink CPE510 v1.0/v1.1 | ath79 | cpe510-v1 | 64Mb | stable -TPLink CPE510 v2.0 | ath79 | cpe510-v2 | 64Mb | stable -TPLink CPE510 v3.0 | ath79 | cpe510-v3 | 64Mb | stable -TPLink CPE610 v1.0 | ath79 | cpe610-v1 | 64Mb | stable -TPLink CPE610 v2.0 | ath79 | cpe610-v2 | 64Mb | stable -TPLink WBS210 v1.0 | ath79 | wbs210-v1 | 64mb | stable -TPLink WBS210 v2.0 | ath79 | wbs210-v2 | 64mb | stable -TPLink WBS510 v1.0 | ath79 | wbs510-v1 | 64mb | stable -TPLink WBS510 v2.0 | ath79 | wbs510-v2 | 64mb | stable -Mikrotik Basebox RB912UAG-5HPnD/2HPnD | ar71xx | mikrotik-nand-large | 64Mb | stable -Mikrotik hAP ac lite 952Ui-5ac2nD | ar71xx | mikrotik-rb-nor-flash-16M-ac | 64Mb | stable -Mikrotik RBLHG-2nD/5nD | ar71xx | mikrotik-rb-nor-flash-16M | 64Mb | stable -Mikrotik RBLHG-5HPnD | ar71xx | mikrotik-rb-nor-flash-16M | 64Mb | stable -Mikrotik RBLHG-2nD-XL/5HPnD-XL | ar71xx | mikrotik-rb-nor-flash-16M | 64Mb | stable -Mikrotik RBLDF-2nD/5nD | ar71xx | mikrotik-rb-nor-flash-16M | 64Mb | stable -Mikrotik QRT5 RB911G-5HPnD-QRT | ar71xx | mikrotik-nand-large | 64Mb | stable -Mikrotik mAntbox RB911G-2HPnD/5HPnD | ar71xx | mikrotik-nand-large | 64Mb | stable -Mikrotik SXTsq 5HPnD/5nD/2nD | ar71xx | mikrotik-rb-nor-flash-16M | 64Mb | stable -GL.iNet GL-AR150 | ath79 | gl-ar150 | 64Mb | stable -GL.iNet GL-USB150 | ar71xx | gl-usb150 | 64Mb | stable -GL.iNet GL-AR300M16 | ar71xx | gl-ar300m | 64Mb | stable -GL.iNet GL-AR300M w/ 128Mb NAND | None | None | 64Mb | Not compatible -GL.iNet GL-AR750 | ar71xx | gl-ar750 | 128Mb | stable -Meraki MR-16 | ar71xx | mr16 | 64mb | stable +Device | Target | Image | RAM | Stability +------ | ------ | ----- | --- | --------- +AirGrid XM | ath79 | ubnt_bullet-m-ar7241 | 32MB | untested sunset +AirGrid XW | ath79 | ubnt_bullet-m-xw | 32MB | untested sunset +AirRouter | ath79 | ubnt_airrouter | 32MB | untested sunset +AirRouter HP | ath79 | ubnt_airrouter | 32MB | untested sunset +Bullet M2Ti/M5/M5Ti | ath79 | - | 32MB | untested sunset +Bullet M2 | ath79 | ubnt_bullet-m-ar7241 | 32MB | stable sunset +Bullet M2 XW | ath79 | ubnt_bullet-m-xw | 64MB | untested +LiteBeam AC5 Gen2 | ath79 | ubnt_litebeam-ac-gen2 | 64MB | stable new +LiteBeam M5 | ath79 | - | 64MB | untested +NanoBeam AC 5 | ath79 | ubnt_nanobeam-ac | 64MB | untested new +NanoBeam AC 5 Gen 2 | ath79 | ubnt_nanobeam-ac-gen2 | 128MB | stable new +NanoBeam M2-13/M5-16/M5-19 | ath79 | - | 32MB | untested sunset +NanoBridge 2G18 | ath79 | ubnt_nanobridge-m | 32MB | untested sunset +NanoBridge 5G22/25 | ath79 | ubnt_nanobridge-m | 32MB | untested sunset +NanoBridge M9 | ath79 | ubnt_nanobridge-m | 32MB | untested sunset +NanoStation AC 5 | ath79 | ubnt_nanostation-ac | 64MB | untested new +NanoStation Loco M2/M5/M9 XM | ath79 | ubnt_nanostation-loco-m | 32MB | untested sunset +NanoStation Loco M2 XW | ath79 | ubnt_nanostation-loco-m-xw | 64MB | untested +NanoStation Loco M5 XW | ath79 | ubnt_nanostation-loco-m-xw | 64MB | stable +NanoStation M2/M3/M5 XM | ath79 | ubnt_nanostation-m | 32MB | stable sunset +NanoStation M2/M5 XW | ath79 | ubnt_nanostation-m-xw | 64MB | stable +PicoStation M2 | ath79 | ubnt_picostation-m | 32MB | untested sunset +PowerBeam AC 5 500 | ath79 | ubnt_powerbeam-5ac-500 | 128MB | stable new +PowerBeam-M2-400 | ath79 | ubnt_powerbeam-m2-xw | 64MB | untested +PowerBeam-M5-300 | ath79 | ubnt_powerbeam-m5-300 | 64MB | stable +PowerBeam-M5-400/400ISO/620 | ath79 | ubnt_powerbeam-m5-xw | 64MB | stable +PowerBridge | ath79 | ubnt_powerbridge-m | 64MB | untested +Rocket AC Lite 5 | ath79 | ubnt_rocket-5ac-lite | 128MB | stable new +Rocket M9/M2/M3/M5/M5GPS XM | ath79 | ubnt_rocket-m | 64MB | stable +Rocket M2/M5 XM with USB port | ath79 | ubnt_rocket-m | 64MB | untested +Rocket M2 XW | ath79 | ubnt_rocket-m-xw | 64MB | untested +Rocket M5 XW | ath79 | ubnt_rocket-m-xw | 64MB | stable +Rocket M2 Titanium TI | ath79 | - | 64MB | untested +Rocket M2 Titanium XW | ath79 | ubnt_rocket-m-xw | 64MB | untested +Rocket M5 Titanium TI | ath79 | - | 64MB | untested +Rocket M5 Titanium XW | ath79 | ubnt_rocket-m-xw | 64MB | stable +TPLink CPE210 v1.X | ath79 | tplink_cpe210-v1 | 64MB | stable +TPLink CPE210 v2.0 | ath79 | tplink_cpe210-v2 | 64MB | stable +TPLink CPE210 v3.0 | ath79 | tplink_cpe210-v3 | 64MB | untested +TPLink CPE220 v2.0 | ath79 | tplink_cpe220-v2 | 64MB | untested +TPLink CPE220 v3.0 | ath79 | tplink_cpe220-v3 | 64MB | untested +TPLink CPE510 v1.X | ath79 | tplink_cpe510-v1 | 64MB | untested +TPLink CPE510 v2.0 | ath79 | tplink_cpe510-v2 | 64MB | stable +TPLink CPE510 v3.0 | ath79 | tplink_cpe510-v3 | 64MB | stable +TPLink CPE605 v1.0 | ath79 | tplink_cpe605-v1 | 64MB | untested +TPLink CPE610 v1.0 | ath79 | tplink_cpe610-v1 | 64MB | untested +TPLink CPE610 v2.0 | ath79 | tplink_cpe610-v2 | 64MB | untested +TPLink CPE710 v1.0 | ath79 | tplink_cpe710-v1 | 128MB | stable new +TPLink WBS210 v1.0 | ath79 | tplink_wbs210-v1 | 64MB | untested +TPLink WBS210 v2.0 | ath79 | tplink_wbs210-v2 | 64MB | untested +TPLink WBS510 v1.0 | ath79 | tplink_wbs510-v1 | 64MB | untested +TPLink WBS510 v2.0 | ath79 | tplink_wbs510-v2 | 64MB | untested +Mikrotik Basebox RB912UAG-2HPnD | ath79 | mikrotik_routerboard-912uag-2hpnd | 64MB | untested +Mikrotik Basebox RB912UAG-5HPnD | ath79 | - | 64MB | untested +Mikrotik hAP ac lite 952Ui-5ac2nD | ath79 | mikrotik_routerboard-952ui-5ac2nd | 64MB | stable +Mikrotik RBLHG-2nD(-XL) | ath79 | mikrotik_routerboard-lhg-2nd | 64MB | stable +Mikrotik RBLHG-5nD | ath79 | mikrotik_routerboard-lhg-5nd | 64MB | stable +Mikrotik RBLHG-5HPnD(-XL) | ath79 | mikrotik_routerboard-lhg-5nd | 64MB | stable +MikroTik RBLHGG-5acD(-XL) | ipq40xx | mikrotik_lhgg-5acd | 256MB | stable new +Mikrotik RBLDF-2nD | ath79 | - | 64MB | untested +Mikrotik RBLDF-5nD | ath79 | - | 64MB | untested +Mikrotik QRT5 RB911G-5HPnD-QRT | ath79 | - | 64MB | untested +Mikrotik mANTBox RB911G-2HPnD | ath79 | - | 64MB | untested +Mikrotik mANTBox RB911G-5HPnD | ath79 | - | 64MB | untested +Mikrotik mANTBox RB912UAG-2HPnD | ath79 | mikrotik_routerboard-912uag-2hpnd | 128MB | untested +Mikrotik mANTBox RB912UAG-5HPnD | ath79 | - | 128MB | untested +Mikrotik mANTBox RB921GS-5HPacD 15s | ath79 | mikrotik_routerboard-921gs-5hpacd-15s | 128MB | stable new +Mikrotik mANTBox RB921GS-5HPacD 19s | ath79 | mikrotik_routerboard-921gs-5hpacd-19s | 128MB | stable new +Mikrotik SXTsq 5HPnD | ath79 | mikrotik_routerboard-sxt-5nd | 64MB | stable +Mikrotik SXTsq 5nD | ath79 | mikrotik_routerboard-sxt-5nd | 64MB | stable +Mikrotik SXTsq 2nD | ath79 | - | 64MB | untested +MikroTik RouterBOARD D52G-5HacD2HnD | ipq40xx | mikrotik_hap-ac2 | 128MB | stable new +MikroTik RouterBOARD D53iG-5HacD2HnD | ipq40xx | mikrotik_hap-ac3 | 256MB | stable new +MikroTik RouterBOARD SXTsqG-5acD | ipq40xx | mikrotik_sxtsq-5-ac | 256MB | stable new +GL.iNet GL-AR150 | ath79 | glinet_gl-ar150 | 64MB | stable +GL.iNet GL-USB150 | ath79 | glinet_gl-usb150 | 64MB | stable +GL.iNet GL-AR300M16 | ath79 | glinet_gl-ar300m | 64MB | stable +GL.iNet GL-AR300M w/ 128MB NAND | ath79 | - | 64MB | untested +GL.iNet GL-AR750 | ath79 | glinet_gl-ar750 | 128MB | stable +Meraki MR-16 | ath79 | - | 64MB | brick + +#### Stability + +* *brick* - this image has been tested and will currently brick your hardware. Avoid for now. +* *untested* - this image has not been tested on hardware. It may or may not work. +* *stable* - this image has been tested on hardware. There may still be bugs. +* *sunset* - this device has been sunsetted and support will be deprecated at some point. +* *new* - this device is newly supported. The 'target' is a directory to find the image on at http://downloads.arednmesh.org @@ -191,7 +218,7 @@ docker run -it --name builder arednmesh/builder To pull an image (or any other file) out of the docker container: ``` -docker cp builder:/opt/aredn/aredn/firmware/targets/ar71xx/generic/.bin +docker cp builder:/opt/aredn/aredn/firmware/targets/ath79/generic/.bin ``` ### Build Prerequisites @@ -229,9 +256,9 @@ bash git clone https://github.com/aredn/aredn.git cd aredn vi config.mk # enter your callsign, etc. -# build default legacy ar71xx target ubnt and tplink images +# build default legacy ath79 target ubnt and tplink images make -# build and add legacy ar71xx target mikrotik images +# build and add legacy ath79 target mikrotik images make SUBTARGET=mikrotik # build and add ath79 target (latest linux kernel) ubnt, tplink, and gl images make MAINTARGET=ath79 @@ -239,7 +266,7 @@ make MAINTARGET=ath79 Building the images may take minutes or hours depending on the machine. For more details see [build options](https://openwrt.org/docs/guide-developer/build-system/use-buildsystem). -Review the build options in config.mk: `-j `. +Review the build options in config.mk: `-j `. `V=s` will give more verbose error messages. An internet connection is required during the build process. A good internet @@ -252,6 +279,12 @@ You need approximately 10GB of space for the build. Prior AREDN images can be rebuilt. Replace one of the following after the "cd aredn" command above: +AREDN release 3.22.12.0 + +``` +git checkout 3.22.12.0 +``` + AREDN release 3.22.8.0 ``` @@ -264,6 +297,12 @@ AREDN release 3.22.6.0 git checkout 3.22.6.0 ``` +AREDN release 3.22.1.0 + +``` +git checkout 3.22.1.0 +``` + AREDN release 3.21.4.0 ``` diff --git a/config.mk b/config.mk index a8a7be5e..dca8854b 100644 --- a/config.mk +++ b/config.mk @@ -12,8 +12,8 @@ MAKE_ARGS=-j3 # Where will the installed image find add-on Packages to download? # This URL must contain the packages from this build # downloading packages within the AREDN UI uses signatures -PRIVATE_BUILD_PACKAGES=http://downloads.arednmesh.org/releases/3/22/3.22.12.0 +PRIVATE_BUILD_PACKAGES=http://downloads.arednmesh.org/snapshots # These options are for more complex changes SHELL:=$(shell which bash) -TARGET=ar71xx-generic +TARGET=ath79-generic diff --git a/configs/README b/configs/README new file mode 100644 index 00000000..9dbb95e4 --- /dev/null +++ b/configs/README @@ -0,0 +1,16 @@ +How to update AREDN config files + +1) do (or start) an AREDN build, e.g. "make MAINTARGET=ipq40xx SUBTARGET=mikrotik" +2) from ./openwrt directory, "make menuconfig" +3) update config options via the menu and save +4) capture the updated config, from ./openwrt directory, e.g.: + "./scripts/diffconfig.sh > ../configs/ipq40xx-mikrotik.config" + +Notes: +1) adding the same option to every MAINTARGET-SUBTARGET.config file is + done one at a time. +2) It can be very difficult to manually determine compatible dependencies + of config options. +3) Not recommended to manually update the MAINTARGET-SUBTARGET.config + file. If you do, append the setting at the end (will take + precendent). diff --git a/configs/ar71xx-generic.config b/configs/ar71xx-generic.config deleted file mode 100644 index a6f46f3c..00000000 --- a/configs/ar71xx-generic.config +++ /dev/null @@ -1,21 +0,0 @@ -CONFIG_TARGET_ar71xx=y -CONFIG_TARGET_ar71xx_generic=y -CONFIG_TARGET_MULTI_PROFILE=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-bullet-m=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-loco-m-xw=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-nano-m=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-rocket-m-ti=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-rocket-m-xw=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-rocket-m=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_ubnt-lbe-m5=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_gl-ar300m=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_gl-usb150=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_gl-ar750=y -CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_mr16=y -CONFIG_HAS_SUBTARGETS=y -CONFIG_HAS_DEVICES=y -CONFIG_TARGET_BOARD="ar71xx" -CONFIG_TARGET_SUBTARGET="generic" -CONFIG_TARGET_ARCH_PACKAGES="mips_24kc" -CONFIG_DEFAULT_TARGET_OPTIMIZATION="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc" -CONFIG_CPU_TYPE="24kc" diff --git a/configs/ar71xx-mikrotik.config b/configs/ar71xx-mikrotik.config deleted file mode 100644 index 5e5ca98d..00000000 --- a/configs/ar71xx-mikrotik.config +++ /dev/null @@ -1,14 +0,0 @@ -CONFIG_TARGET_ar71xx=y -CONFIG_TARGET_ar71xx_mikrotik=y -CONFIG_TARGET_MULTI_PROFILE=y -CONFIG_TARGET_SUBTARGET=mikrotik -CONFIG_TARGET_DEVICE_ar71xx_mikrotik_DEVICE_nand-large=y -CONFIG_TARGET_DEVICE_ar71xx_mikrotik_DEVICE_rb-nor-flash-16M-ac=y -CONFIG_TARGET_DEVICE_ar71xx_mikrotik_DEVICE_rb-nor-flash-16M=y -CONFIG_DEFAULT_ath10k-firmware-qca9887=y -CONFIG_DEFAULT_ath10k-firmware-qca988x=y -CONFIG_DEFAULT_kmod-ath10k=y -CONFIG_DEFAULT_kmod-ledtrig-gpio=y -CONFIG_DEFault_kmod-usb-ehci=y -CONFIG_DEFAULT_rssileds=y -CONFIG_PACKAGE_rbcfg=y diff --git a/configs/ath79-generic.config b/configs/ath79-generic.config index 1c1fc7bf..b84c705b 100644 --- a/configs/ath79-generic.config +++ b/configs/ath79-generic.config @@ -1,32 +1,41 @@ CONFIG_TARGET_ath79=y CONFIG_TARGET_ath79_generic=y -CONFIG_TARGET_MULTI_PROFILE=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_glinet_gl-ar150=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs210-v1=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs210-v2=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs510-v1=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs510-v2=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe510-v1=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe510-v2=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe510-v3=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe610-v1=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe610-v2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_glinet_gl-ar300m16=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_glinet_gl-ar750=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_glinet_gl-usb150=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe210-v1=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe210-v2=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe210-v3=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe220-v2=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe220-v3=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_airrouter=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_bullet-m=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe510-v1=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe510-v2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe510-v3=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe605-v1=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe610-v1=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe610-v2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_cpe710-v1=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs210-v1=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs210-v2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs510-v1=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_tplink_wbs510-v2=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_bullet-m-xw=y -CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanostation-m=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_bullet-ac=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_bullet-m-xw=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_litebeam-ac-gen2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanobeam-ac-gen2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanobeam-ac=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanobeam-m5-xw=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanostation-ac=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanostation-loco-m-xw=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_nanostation-m-xw=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_powerbeam-m5-300=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_powerbeam-m2-xw=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_powerbeam-m5-xw=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_powerbeam-5ac-500=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_powerbeam-5ac-gen2=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_powerbridge-m=y +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_rocket-5ac-lite=y CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_rocket-m=y -CONFIG_HAS_SUBTARGETS=y -CONFIG_HAS_DEVICES=y -CONFIG_TARGET_BOARD="ath79" -CONFIG_TARGET_SUBTARGET="generic" -CONFIG_TARGET_ARCH_PACKAGES="mips_24kc" -CONFIG_DEFAULT_TARGET_OPTIMIZATION="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc" -CONFIG_CPU_TYPE="24kc" -CONFIG_PACKAGE_sysfsutils=m +CONFIG_TARGET_DEVICE_ath79_generic_DEVICE_ubnt_rocket-m-xw=y diff --git a/configs/ath79-mikrotik-ath10k.config b/configs/ath79-mikrotik-ath10k.config new file mode 100755 index 00000000..da6d7dfc --- /dev/null +++ b/configs/ath79-mikrotik-ath10k.config @@ -0,0 +1,12 @@ +CONFIG_TARGET_ath79=y +CONFIG_TARGET_ath79_mikrotik=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-921gs-5hpacd-15s=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-921gs-5hpacd-19s=y +# +# DEVICE_PACKAGES are not included in the initramfs, but for these devices we need +# extra packages pre-installed to successfully install sysupgrade. +# +CONFIG_PACKAGE_ath10k-board-qca988x=y +CONFIG_PACKAGE_ath10k-firmware-qca988x-ct=y +CONFIG_PACKAGE_kmod-ath10k-ct=y +CONFIG_PACKAGE_nand-utils=y diff --git a/configs/ath79-mikrotik.config b/configs/ath79-mikrotik.config new file mode 100644 index 00000000..8c7d1a33 --- /dev/null +++ b/configs/ath79-mikrotik.config @@ -0,0 +1,8 @@ +CONFIG_TARGET_ath79=y +CONFIG_TARGET_ath79_mikrotik=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-912uag-2hpnd=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-952ui-5ac2nd=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-lhg-2nd=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-lhg-5nd=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-sxt-5nd=y +CONFIG_TARGET_DEVICE_ath79_mikrotik_DEVICE_mikrotik_routerboard-sxt-5nd-r2=y diff --git a/configs/ath79-nand.config b/configs/ath79-nand.config new file mode 100644 index 00000000..7c95b3b4 --- /dev/null +++ b/configs/ath79-nand.config @@ -0,0 +1,7 @@ +CONFIG_TARGET_ath79=y +CONFIG_TARGET_ath79_nand=y +CONFIG_TARGET_DEVICE_ath79_nand_DEVICE_glinet_gl-ar300m-nand=y +CONFIG_TARGET_DEVICE_ath79_nand_DEVICE_glinet_gl-ar300m-nor=y +CONFIG_TARGET_DEVICE_ath79_nand_DEVICE_glinet_gl-ar750s-nor-nand=y +CONFIG_TARGET_DEVICE_ath79_nand_DEVICE_glinet_gl-ar750s-nor=y +CONFIG_TARGET_DEVICE_ath79_nand_DEVICE_glinet_gl-e750=y diff --git a/configs/ath79-tiny.config b/configs/ath79-tiny.config new file mode 100644 index 00000000..338bce5e --- /dev/null +++ b/configs/ath79-tiny.config @@ -0,0 +1,19 @@ +CONFIG_TARGET_ath79=y +CONFIG_TARGET_ath79_tiny=y +CONFIG_TARGET_DEVICE_ath79_tiny_DEVICE_ubnt_airrouter=y +CONFIG_TARGET_DEVICE_ath79_tiny_DEVICE_ubnt_bullet-m-ar7241=y +CONFIG_TARGET_DEVICE_ath79_tiny_DEVICE_ubnt_nanostation-loco-m=y +CONFIG_TARGET_DEVICE_ath79_tiny_DEVICE_ubnt_nanobridge-m=y +CONFIG_TARGET_DEVICE_ath79_tiny_DEVICE_ubnt_nanostation-m=y +CONFIG_TARGET_DEVICE_ath79_tiny_DEVICE_ubnt_picostation-m=y + +# Overrides to save as much space as we can +CONFIG_KERNEL_CC_STACKPROTECTOR_NONE=y +CONFIG_KERNEL_PRINTK=n +CONFIG_PACKAGE_ATH_SPECTRAL=n +CONFIG_PACKAGE_wpad-mini=m +CONFIG_PACKAGE_vtun=m +CONFIG_PACKAGE_ethtool=m +CONFIG_PACKAGE_iperf3=m +CONFIG_PKG_CC_STACKPROTECTOR_NONE=y +CONFIG_PKG_FORTIFY_SOURCE_NONE=y diff --git a/configs/common.config b/configs/common.config index 7463a212..2690d6e5 100644 --- a/configs/common.config +++ b/configs/common.config @@ -1,127 +1,177 @@ -CONFIG_KERNEL_CRASHLOG=n -CONFIG_KERNEL_SWAP=n -CONFIG_KERNEL_KALLSYMS=n -CONFIG_KERNEL_DEBUG_INFO=n -CONFIG_KERNEL_ELF_CORE=n -CONFIG_KERNEL_MAGIC_SYSRQ=n -CONFIG_PACKAGE_MAC80211_MESH=n -CONFIG_STRIP_KERNEL_EXPORTS=y -CONFIG_USE_MKLIBS=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_LOG_CPU_MAX_BUF_SHIFT=16 -CONFIG_KERNEL_IPV6=n -CONFIG_KERNEL_IPV6_MULTIPLE_TABLES=n -CONFIG_KERNEL_IPV6_SUBTREES=n -CONFIG_KERNEL_IPV6_MROUTE=n -CONFIG_IPV6=n CONFIG_ATH_USER_REGD=y -CONFIG_PACKAGE_bridge=y -CONFIG_PACKAGE_busybox=y -CONFIG_BUSYBOX_CUSTOM=y -CONFIG_BUSYBOX_DEFAULT_FEATURE_IPV6=n -CONFIG_BUSYBOX_CONFIG_FEATURE_IPV6=n -CONFIG_BUSYBOX_CONFIG_TELNETD=y -CONFIG_BUSYBOX_DEFAULT_MKSWAP=n -CONFIG_BUSYBOX_CONFIG_MKSWAP=n -CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_INTERACTIVE=y CONFIG_BUSYBOX_CONFIG_ARPING=y -CONFIG_PACKAGE_dnsmasq=y -CONFIG_PACKAGE_dropbear=y -CONFIG_PACKAGE_iperf3=y -CONFIG_PACKAGE_iptables=y -CONFIG_PACKAGE_kmod-ipt-nathelper=y -CONFIG_PACKAGE_kmod-usb-core=m -CONFIG_PACKAGE_kmod-usb-ehci=m -CONFIG_PACKAGE_kmod-usb-ohci=m -CONFIG_PACKAGE_kmod-usb-uhci=m -CONFIG_PACKAGE_kmod-usb2=m -CONFIG_PACKAGE_kmod-usb3=m -CONFIG_PACKAGE_block-mount=m -CONFIG_PACKAGE_kmod-fs-vfat=m -CONFIG_PACKAGE_kmod-fs-ntfs=m -CONFIG_PACKAGE_kmod-fs-ext4=m -CONFIG_PACKAGE_e2fsprogs=m -CONFIG_PACKAGE_kmod-usb-storage=m -CONFIG_PACKAGE_kmod-usb-storage-extras=m -CONFIG_PACKAGE_kmod-usb-storage-uas=m -CONFIG_PACKAGE_kmod-mmc=m -CONFIG_PACKAGE_mmc-utils=m -CONFIG_PACKAGE_kmod-sdhci=m -CONFIG_PACKAGE_kmod-sdhci-mt7620=m -CONFIG_PACKAGE_libgcc=y -CONFIG_PACKAGE_mtd=y -CONFIG_PACKAGE_ppp=n -CONFIG_PACKAGE_ppp-mod-pppoe=n -CONFIG_PACKAGE_odhcp6c=n -CONFIG_PACKAGE_odhcpd=n -CONFIG_PACKAGE_odhcpd-ipv6only=n -CONFIG_PACKAGE_kmod-ppp=n -CONFIG_PACKAGE_kmod-pppoe=n -CONFIG_PACKAGE_kmod-pppox=n -CONFIG_PACKAGE_uhttpd=y -CONFIG_PACKAGE_olsrd=y -CONFIG_PACKAGE_perl=m -CONFIG_PACKAGE_olsrd-mod-arprefresh=y -CONFIG_PACKAGE_olsrd-mod-dyn-gw=y -CONFIG_PACKAGE_olsrd-mod-nameservice=y -CONFIG_PACKAGE_olsrd-mod-txtinfo=y -CONFIG_PACKAGE_olsrd-mod-jsoninfo=y -CONFIG_PACKAGE_olsrd-mod-dot-draw=y -CONFIG_PACKAGE_olsrd-mod-watchdog=y -CONFIG_PACKAGE_olsrd-mod-secure=m -CONFIG_PACKAGE_perlbase-essential=m -CONFIG_PACKAGE_perlbase-xsloader=m -CONFIG_PACKAGE_perlbase-file=m -CONFIG_PACKAGE_perlbase-perlio=m -CONFIG_PACKAGE_libpcap=m -CONFIG_PACKAGE_tcpdump-mini=m -CONFIG_PACKAGE_ntpclient=m -CONFIG_PACKAGE_xinetd=m -CONFIG_PACKAGE_kmod-ipv6=n -CONFIG_PACKAGE_ip6tables=n -CONFIG_PACKAGE_kmod-ip6tables=n -CONFIG_PACKAGE_libip6tc=n -CONFIG_PACKAGE_ip=y -CONFIG_PACKAGE_iptables-mod-ipopt=y -CONFIG_PACKAGE_iwinfo=y -CONFIG_PACKAGE_libiwinfo=y -CONFIG_PACKAGE_socat=y -CONFIG_PACKAGE_curl=y -CONFIG_PACKAGE_libnetsnmp=m -CONFIG_PACKAGE_snmpd=m -CONFIG_PACKAGE_lua=y -CONFIG_PACKAGE_liblua=y -CONFIG_PACKAGE_libuci-lua=y -CONFIG_PACKAGE_libubus-lua=y -CONFIG_PACKAGE_luci-base=y -CONFIG_PACKAGE_luci-lib-nixio=y -CONFIG_PACKAGE_luci-lib-ip=y -CONFIG_PACKAGE_luci-lib-jsonc=y -CONFIG_PACKAGE_libc=y -CONFIG_PACKAGE_libjson-c=y -CONFIG_PACKAGE_libnl_tiny=y -CONFIG_PACKAGE_libiwinfo-lua=y -CONFIG_PACKAGE_luaposix=y -CONFIG_PACKAGE_luasocket=y -CONFIG_PACKAGE_vtun=y -CONFIG_PACKAGE_kmod-ipip=y +CONFIG_BUSYBOX_CONFIG_CROND=n +CONFIG_BUSYBOX_CONFIG_FEATURE_IPV6=n +CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_INTERACTIVE=y +CONFIG_BUSYBOX_CONFIG_MKSWAP=n +CONFIG_BUSYBOX_CONFIG_NTPD=y +CONFIG_BUSYBOX_CONFIG_SETSID=y +CONFIG_BUSYBOX_CONFIG_TELNETD=y +CONFIG_BUSYBOX_CUSTOM=y +CONFIG_DROPBEAR_AGENTFORWARD=n +CONFIG_DROPBEAR_CURVE25519=n +CONFIG_DROPBEAR_CHACHA20POLY1305=n +CONFIG_DROPBEAR_DBCLIENT_AGENTFORWARD=n +CONFIG_DROPBEAR_ECC=y +CONFIG_DROPBEAR_ED25519=n CONFIG_IMAGEOPT=y -CONFIG_VERSIONOPT=y -CONFIG_VERSION_DIST="AREDN" -CONFIG_PACKAGE_ATH_DYNACK=y +CONFIG_IPV6=n +CONFIG_JSON_OVERVIEW_IMAGE_INFO=y +CONFIG_KERNEL_AIO=n +CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KERNEL_CGROUPS=n +CONFIG_KERNEL_CRASHLOG=n +CONFIG_KERNEL_DEBUG_INFO=n +CONFIG_KERNEL_DEVPTS_MULTIPLE_INSTANCES=n +CONFIG_KERNEL_ELF_CORE=n +CONFIG_KERNEL_IO_URING=n +CONFIG_KERNEL_IP_MROUTE=n +CONFIG_KERNEL_IPV6=n +CONFIG_KERNEL_KALLSYMS=n +CONFIG_KERNEL_KEYS=n +CONFIG_KERNEL_MAGIC_SYSRQ=n +CONFIG_KERNEL_NAMESPACES=n +CONFIG_KERNEL_POSIX_MQUEUE=n +CONFIG_KERNEL_RELAY=y +CONFIG_KERNEL_SECCOMP=n +CONFIG_KERNEL_SWAP=n +CONFIG_LIBCURL_COOKIES=y +CONFIG_LIBCURL_FILE=y +CONFIG_LIBCURL_FTP=y +CONFIG_LIBCURL_HTTP=y +CONFIG_LIBCURL_NGHTTP2=n +CONFIG_LIBCURL_NO_SMB=y +CONFIG_LIBCURL_NOSSL=y +CONFIG_LIBCURL_PROXY=y +CONFIG_LIBCURL_NO_RTSP=n CONFIG_PACKAGE_ATH_DEBUG=y +CONFIG_PACKAGE_ATH_DYNACK=y CONFIG_PACKAGE_ATH_SPECTRAL=y CONFIG_PACKAGE_blockknownencryption=m -CONFIG_PACKAGE_kmod-udptunnel4=m -CONFIG_PACKAGE_libmnl0=m -CONFIG_PACKAGE_libssp=m +CONFIG_PACKAGE_block-mount=m +CONFIG_PACKAGE_cgi-io=n +CONFIG_PACKAGE_curl=y +CONFIG_PACKAGE_e2fsprogs=m +CONFIG_PACKAGE_ethtool=y +CONFIG_PACKAGE_firewall4=y +CONFIG_PACKAGE_iperf3=y +CONFIG_PACKAGE_jansson=n +CONFIG_PACKAGE_kmod-crypto-crc32c=m +CONFIG_PACKAGE_kmod-fs-ext4=m +CONFIG_PACKAGE_kmod-fs-ntfs=m +CONFIG_PACKAGE_kmod-fs-vfat=m +CONFIG_PACKAGE_kmod-ipip=y +CONFIG_PACKAGE_kmod-iptunnel4=y +CONFIG_PACKAGE_kmod-iptunnel=y +CONFIG_PACKAGE_kmod-lib-crc16=m +CONFIG_PACKAGE_kmod-lib-crc-ccitt=m +CONFIG_PACKAGE_kmod-nft-core=y +CONFIG_PACKAGE_kmod-nft-fib=y +CONFIG_PACKAGE_kmod-nft-nat=y +CONFIG_PACKAGE_kmod-nft-offload=y +CONFIG_PACKAGE_kmod-nls-cp437=m +CONFIG_PACKAGE_kmod-nls-iso8859-1=m +CONFIG_PACKAGE_kmod-nls-utf8=m +CONFIG_PACKAGE_kmod-ppp=m +CONFIG_PACKAGE_kmod-pppoe=m +CONFIG_PACKAGE_kmod-pppox=m +CONFIG_PACKAGE_kmod-scsi-core=m +CONFIG_PACKAGE_kmod-slhc=m +CONFIG_PACKAGE_kmod-tun=m +CONFIG_PACKAGE_kmod-usb2=m +CONFIG_PACKAGE_kmod-usb3=m +CONFIG_PACKAGE_kmod-usb-ohci=m +CONFIG_PACKAGE_kmod-usb-storage-extras=m +CONFIG_PACKAGE_kmod-usb-storage=m +CONFIG_PACKAGE_kmod-usb-storage-uas=m +CONFIG_PACKAGE_kmod-usb-uhci=m +CONFIG_PACKAGE_kmod-usb-xhci-hcd=m CONFIG_PACKAGE_kmod-wireguard=m +CONFIG_PACKAGE_libblkid=m +CONFIG_PACKAGE_libcomerr=m +CONFIG_PACKAGE_libcurl=y +CONFIG_PACKAGE_libext2fs=m +CONFIG_PACKAGE_libiwinfo-lua=y +CONFIG_PACKAGE_liblua=y +CONFIG_PACKAGE_liblucihttp-lua=y +CONFIG_PACKAGE_liblucihttp=y +CONFIG_PACKAGE_liblzo=m +CONFIG_PACKAGE_libnetsnmp=m +CONFIG_PACKAGE_libnftnl=y +CONFIG_PACKAGE_libnghttp2=n +CONFIG_PACKAGE_libpcap=m +CONFIG_PACKAGE_libpci=m +CONFIG_PACKAGE_libpcre=m +CONFIG_PACKAGE_librt=y +CONFIG_PACKAGE_libss=m +CONFIG_PACKAGE_libsysfs=m +CONFIG_PACKAGE_libubus-lua=y +CONFIG_PACKAGE_libuci-lua=y +CONFIG_PACKAGE_libustream-wolfssl=n +CONFIG_PACKAGE_libuuid=m +CONFIG_PACKAGE_libwolfssl=n +CONFIG_PACKAGE_libxtables=y +CONFIG_PACKAGE_lua-bit32=y +CONFIG_PACKAGE_luaposix=n +CONFIG_PACKAGE_luasocket=y +CONFIG_PACKAGE_lua=y +CONFIG_PACKAGE_luci-base=n +CONFIG_PACKAGE_luci-lib-base=y +CONFIG_PACKAGE_luci-lib-ip=y +CONFIG_PACKAGE_luci-lib-jsonc=y +CONFIG_PACKAGE_luci-lib-nixio=y +CONFIG_PACKAGE_mii-tool=m +CONFIG_PACKAGE_nftables-json=y +CONFIG_PACKAGE_nftables=y +CONFIG_PACKAGE_odhcp6c=n +CONFIG_PACKAGE_odhcpd-ipv6only=n +CONFIG_PACKAGE_odhcpd=n +CONFIG_PACKAGE_olsrd-mod-arprefresh=y +CONFIG_PACKAGE_olsrd-mod-dot-draw=y +CONFIG_PACKAGE_olsrd-mod-dyn-gw=y +CONFIG_PACKAGE_olsrd-mod-jsoninfo=y +CONFIG_PACKAGE_olsrd-mod-nameservice=y +CONFIG_PACKAGE_olsrd-mod-secure=m +CONFIG_PACKAGE_olsrd-mod-txtinfo=y +CONFIG_PACKAGE_olsrd-mod-watchdog=y +CONFIG_PACKAGE_olsrd=y +CONFIG_PACKAGE_ppp=m +CONFIG_PACKAGE_ppp-mod-pppoe=m +CONFIG_PACKAGE_procd-seccomp=n +CONFIG_PACKAGE_procd-ujail=n +CONFIG_PACKAGE_rpcd-mod-file=y +CONFIG_PACKAGE_rpcd-mod-luci=y +CONFIG_PACKAGE_rpcd=y +CONFIG_PACKAGE_snmpd=m +CONFIG_PACKAGE_socat=m +CONFIG_PACKAGE_sysfsutils=m +CONFIG_PACKAGE_tcpdump-mini=m +CONFIG_PACKAGE_ubi-utils=y +CONFIG_PACKAGE_uhttpd=y +CONFIG_PACKAGE_vtun=y CONFIG_PACKAGE_wireguard=m CONFIG_PACKAGE_wireguard-tools=m +CONFIG_PACKAGE_wpad-mini=y +CONFIG_PACKAGE_xinetd=n +CONFIG_PACKAGE_zlib=m +CONFIG_PACKAGE_zram-swap=n CONFIG_PREINITOPT=y +CONFIG_SECCOMP=n +CONFIG_STRIP_KERNEL_EXPORTS=y +CONFIG_TARGET_MULTI_PROFILE=y +CONFIG_TARGET_PER_DEVICE_ROOTFS=y CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE=y +CONFIG_VERSION_BUG_URL="https://github.com/aredn/aredn/issues" +CONFIG_VERSION_CODE="" +CONFIG_VERSION_DIST="AREDN" +CONFIG_VERSION_FILENAMES=y +CONFIG_VERSION_HOME_URL="" +CONFIG_VERSION_HWREV="" +CONFIG_VERSION_MANUFACTURER="" +CONFIG_VERSION_MANUFACTURER_URL="" +CONFIG_VERSIONOPT=y +CONFIG_VERSION_PRODUCT="" +CONFIG_VERSION_REPO="http://downloads.arednmesh.org/snapshots" +CONFIG_VERSION_SUPPORT_URL="https://arednmesh.org" +CONFIG_VTUN_LZO=y CONFIG_VTUN_SSL=n -CONFIG_PACKAGE_ethtool=y -CONFIG_JSON_OVERVIEW_IMAGE_INFO=y -CONFIG_PACKAGE_kmod-rtc-ds1307=m -CONFIG_DROPBEAR_ECC=y diff --git a/configs/ipq40xx-mikrotik.config b/configs/ipq40xx-mikrotik.config new file mode 100644 index 00000000..ccc2d5b0 --- /dev/null +++ b/configs/ipq40xx-mikrotik.config @@ -0,0 +1,6 @@ +CONFIG_TARGET_ipq40xx=y +CONFIG_TARGET_ipq40xx_mikrotik=y +CONFIG_TARGET_DEVICE_ipq40xx_mikrotik_DEVICE_mikrotik_hap-ac2=y +CONFIG_TARGET_DEVICE_ipq40xx_mikrotik_DEVICE_mikrotik_hap-ac3=y +CONFIG_TARGET_DEVICE_ipq40xx_mikrotik_DEVICE_mikrotik_lhgg-5acd=y +CONFIG_TARGET_DEVICE_ipq40xx_mikrotik_DEVICE_mikrotik_sxtsq-5-ac=y diff --git a/feeds.conf b/feeds.conf index c4e5ef47..31ceef3d 100644 --- a/feeds.conf +++ b/feeds.conf @@ -1 +1 @@ -src-git arednpackages https://github.com/aredn/aredn_packages;develop +src-git arednpackages https://github.com/kn6plv/aredn_packages;openwrt-22.3.0-lua diff --git a/files/etc/arednsysupgrade.conf b/files/etc/arednsysupgrade.conf index e74c26e9..ca33ec81 100644 --- a/files/etc/arednsysupgrade.conf +++ b/files/etc/arednsysupgrade.conf @@ -15,6 +15,12 @@ /etc/config.mesh/xlink /etc/aredn_include/swconfig.user /etc/aredn_include/static_routes +/etc/aredn_include/fixedmac.lan +/etc/aredn_include/fixedmac.wan +/etc/aredn_include/fixedmac.dtdlink +/etc/aredn_include/lan.network.user +/etc/aredn_include/wan.network.user +/etc/aredn_include/dtdlink.network.user /etc/dropbear/dropbear_dss_host_key /etc/dropbear/dropbear_rsa_host_key /etc/dropbear/dropbear_ecdsa_host_key diff --git a/files/etc/config.mesh/_setup b/files/etc/config.mesh/_setup index 005a7735..a6f20c77 100644 --- a/files/etc/config.mesh/_setup +++ b/files/etc/config.mesh/_setup @@ -44,3 +44,5 @@ time_zone = UTC ntp_server = us.pool.ntp.org description_node = + +compat_version = 1.0 diff --git a/files/etc/config.mesh/_setup.default b/files/etc/config.mesh/_setup.default index b5b6bc5d..2adbef5b 100644 --- a/files/etc/config.mesh/_setup.default +++ b/files/etc/config.mesh/_setup.default @@ -45,3 +45,5 @@ time_zone_name = UTC ntp_server = us.pool.ntp.org description_node = + +compat_version = 1.0 diff --git a/files/etc/config.mesh/firewall b/files/etc/config.mesh/firewall index f350288f..75b3ed39 100644 --- a/files/etc/config.mesh/firewall +++ b/files/etc/config.mesh/firewall @@ -81,11 +81,12 @@ config rule option target ACCEPT config include - option path /usr/local/bin/mesh-firewall - option reload 1 + option path /usr/local/bin/mesh-firewall + option fw4_compatible 1 config include - option path /etc/firewall.user + option path /etc/firewall.user + option fw4_compatible 1 config rule option src wan diff --git a/files/etc/config.mesh/firewall.user b/files/etc/config.mesh/firewall.user index 1ccbd016..62a6d726 100755 --- a/files/etc/config.mesh/firewall.user +++ b/files/etc/config.mesh/firewall.user @@ -1,4 +1,4 @@ # This file is interpreted as shell script. -# Put your custom iptables rules here, they will +# Put your custom nft rules here, they will # be executed with each firewall (re-)start. diff --git a/files/etc/config.mesh/network b/files/etc/config.mesh/network index 56fc4a4a..fe15ebc9 100644 --- a/files/etc/config.mesh/network +++ b/files/etc/config.mesh/network @@ -1,46 +1,62 @@ #### Loopback configuration config interface loopback - option ifname "lo" + option device "lo" option proto static option ipaddr 127.0.0.1 option netmask 255.0.0.0 #### LAN configuration -config interface lan - option ifname "" +config device + option name "br-lan" option type "bridge" +include /etc/aredn_include/fixedmac.lan +include /etc/aredn_include/lan.network.config + +config interface lan + option device "br-lan" option proto option ipaddr option netmask option dns " " option gateway -include /etc/aredn_include/ethmacfixup #### WAN configuration +config device + option name "br-wan" + option type "bridge" +include /etc/aredn_include/fixedmac.wan +include /etc/aredn_include/wan.network.config + config interface wan - option ifname "" -include /etc/aredn_include/bridge_ports + option device "br-wan" option proto option ipaddr option netmask option gateway - #### WIFI configuration +config device + option name "" + config interface wifi - option ifname "" + option device "" option proto option ipaddr option netmask #### device to device configuration +config device + option name "br-dtdlink" + option type "bridge" +include /etc/aredn_include/fixedmac.dtdlink +include /etc/aredn_include/dtdlink.network.config + config interface dtdlink - option ifname "" -include /etc/aredn_include/bridge_ports - option proto static - option ipaddr - option netmask 255.0.0.0 + option device "br-dtdlink" + option proto static + option ipaddr + option netmask 255.0.0.0 config interface wifi_mon option proto none diff --git a/files/etc/config.mesh/system b/files/etc/config.mesh/system index 1fa15832..136440e4 100644 --- a/files/etc/config.mesh/system +++ b/files/etc/config.mesh/system @@ -2,6 +2,7 @@ config 'system' option 'hostname' '' option 'timezone' '' option 'description' '' + option 'compat_version' '' config 'timeserver' 'ntp' list 'server' '' diff --git a/files/etc/config/firewall b/files/etc/config/firewall index ddba3806..21f43a4b 100644 --- a/files/etc/config/firewall +++ b/files/etc/config/firewall @@ -47,8 +47,8 @@ config rule option target ACCEPT config include - option path /etc/firewall.user - + option path '/etc/firewall.user' + option fw4_compatible 1 config rule option src wan diff --git a/files/etc/config/system b/files/etc/config/system index d3d4d1ee..03c774b8 100644 --- a/files/etc/config/system +++ b/files/etc/config/system @@ -1,6 +1,7 @@ config 'system' option 'hostname' 'NOCALL' option 'timezone' 'UTC' + option 'compat_version' '1.0' config 'timeserver' 'ntp' list 'server' 'us.pool.ntp.org' diff --git a/files/etc/dnsmasq.conf b/files/etc/dnsmasq.conf index cec5eb55..1262a371 100644 --- a/files/etc/dnsmasq.conf +++ b/files/etc/dnsmasq.conf @@ -5,7 +5,6 @@ filterwin2k localise-queries # allow /etc/hosts and dhcp lookups via *.lan -#local=/lan/ domain=local.mesh expand-hosts no-negcache @@ -25,5 +24,8 @@ read-ethers # default route(s): dhcp-option=3,192.168.1.1,192.168.1.2 # dns server(s): dhcp-option=6,192.168.1.1,192.168.1.2 +# Make sure clients use our domain +dhcp-option=option:domain-search,local.mesh + strict-order log-facility=/dev/null diff --git a/files/etc/firewall.natmode b/files/etc/firewall.natmode index ee6a52f1..29eb14e2 100644 --- a/files/etc/firewall.natmode +++ b/files/etc/firewall.natmode @@ -9,10 +9,9 @@ ip rule del pref 20010 fwmark 0x15 lookup 29 > /dev/null 2>&1 ip rule add pref 20010 fwmark 0x15 lookup 29 #tag traffic for use later in iprule's -iptables -t mangle -I PREROUTING -d $wifiip/32 -j MARK --set-xmark 0x15/0xffffffff -iptables -t mangle -I PREROUTING -d $dtdlinkip/32 -j MARK --set-xmark 0x15/0xffffffff +nft insert rule ip fw4 mangle_prerouting ip daddr $wifiip counter meta mark set 0x15 +nft insert rule ip fw4 mangle_prerouting ip daddr $dtdlinkip counter meta mark set 0x15 # Mark and masq local traffic going out the dtdlink interface. -iptables -t nat -A zone_lan_prerouting -j MARK --set-xmark 0xe/0xffffffff -iptables -t nat -A zone_dtdlink_postrouting -m mark --mark 0xe -j MASQUERADE - +nft add rule ip fw4 helper_lan counter meta mark set 0xe +nft add rule ip fw4 srcnat mark 0xe mark 0xe counter masquerade diff --git a/files/etc/hotplug.d/iface/11-meshrouting b/files/etc/hotplug.d/iface/11-meshrouting index 050b3215..6c942bc8 100755 --- a/files/etc/hotplug.d/iface/11-meshrouting +++ b/files/etc/hotplug.d/iface/11-meshrouting @@ -77,7 +77,7 @@ if [ "$ACTION" = "ifup" ] ; then if [ $bridge = "bridge" ] ; then lan_ifname="br-lan" else - lan_ifname=$(uci -q get network.lan.ifname | cut -f1) + lan_ifname=$(uci -q get network.lan.device | cut -f1) fi if [ "$lan_ifname" != "" ] && [ "$lan_ipaddr" != "" ] && [ "$lan_netmask" != "" ] ; then lan_networkip=$(ipcalc.sh $lan_ipaddr $lan_netmask|grep NETWORK|cut -d'=' -f2) diff --git a/files/etc/init.d/local b/files/etc/init.d/local index 3c2fb76b..8b83764a 100755 --- a/files/etc/init.d/local +++ b/files/etc/init.d/local @@ -4,45 +4,6 @@ START=99 boot() { - if [ ! -f /etc/aredn_include/ethmacfixup ] - then - mkdir -p /etc/aredn_include - touch /etc/aredn_include/ethmacfixup - local lanintf="$(uci -q get 'network.lan.ifname')" - lanintf=${lanintf%% *} - local wifiintf="$(uci -q get 'network.wifi.ifname')" - local lanmac=`ifconfig $lanintf | grep -o -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}'` - local wifimac=`ifconfig $wifiintf | grep -o -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}'` - - local intlanmac=${lanmac//:/} - local intwanmac=${wifimac//:/} - local macdelta=$((0x$intwanmac - 0x$intlanmac)) - - # Deal with lan and wifi having same mac address (common on TP-Link) - # Deal with lan mac + ~10 = wifi mac address (common on Microtik and - # breaks OLSR if using derived IP addresses) - # Deal with lan on AR300M always having the same mac address. - if [ $macdelta -le 10 -o $lanmac = "00:03:7F:11:23:C6" ] - then - local wifimacdigit=`printf "%X" $(((0x${wifimac:9:2} + 1) % 256))` - local newmac=${wifimac:0:9}${wifimacdigit}${wifimac:11} - lanintf=${lanintf%%.*} - echo "" > /etc/aredn_include/ethmacfixup - echo "config interface 'setethmac'" >> /etc/aredn_include/ethmacfixup - echo -e "\toption\tifname\t'$lanintf'" >> /etc/aredn_include/ethmacfixup - echo -e "\toption\tproto\t'none'" >> /etc/aredn_include/ethmacfixup - echo -e "\toption\tmacaddr\t$newmac" >> /etc/aredn_include/ethmacfixup - uci set "network.setethmac=interface" - uci set "network.setethmac.ifname=$lanintf" - uci set "network.setethmac.proto=none" - uci set "network.setethmac.macaddr=$newmac" - uci commit - /etc/init.d/network reload - /etc/init.d/network restart - fi - fi - - [ -x /usr/local/bin/aredn_postupgrade ] && /usr/local/bin/aredn_postupgrade # setup nvram variables @@ -96,6 +57,17 @@ boot() { shift done + # did the ethernet come up? we get one reboot to try to fix it. + pkt_lan=$(ifconfig br-lan | grep "RX packets" | sed "s/^.*RX packets:\(\d*\).*$/\1/") + pkt_dtd=$(ifconfig br-dtdlink | grep "RX packets" | sed "s/^.*RX packets:\(\d*\).*$/\1/") + pkt_wan=$(ifconfig br-wan | grep "RX packets" | sed "s/^.*RX packets:\(\d*\).*$/\1/") + if [ ! -f /did_ether_reboot -a "$pkt_lan" = "0" -a "$pkt_dtd" = "0" -a "$pkt_wan" = "0" ]; then + touch /did_ether_reboot + reboot + exit + fi + rm -f /did_ether_reboot + if [ -z "$(uci -q get aredn.@alerts[0])" ]; then uci -q add aredn alerts uci -q commit aredn diff --git a/files/etc/init.d/vtund b/files/etc/init.d/vtund index a2e9d39c..e2b6d382 100755 --- a/files/etc/init.d/vtund +++ b/files/etc/init.d/vtund @@ -44,7 +44,7 @@ options_config() { config_get ppp "$cfg" ppp "/usr/sbin/pppd" config_get ifconfig "$cfg" ifconfig "/sbin/ifconfig" config_get route "$cfg" route "/sbin/route" - config_get firewall "$cfg" firewall "/usr/sbin/iptables" + config_get firewall "$cfg" firewall "/usr/sbin/nft" config_get ip "$cfg" ip "/sbin/ip" echo "options {" >> $new_file diff --git a/files/etc/init.d/vtundsrv b/files/etc/init.d/vtundsrv index 3b6f77c8..8d5bb042 100755 --- a/files/etc/init.d/vtundsrv +++ b/files/etc/init.d/vtundsrv @@ -29,7 +29,7 @@ options_config() { config_get ppp "$cfg" ppp "/usr/sbin/pppd" config_get ifconfig "$cfg" ifconfig "/sbin/ifconfig" config_get route "$cfg" route "/sbin/route" - config_get firewall "$cfg" firewall "/usr/sbin/iptables" + config_get firewall "$cfg" firewall "/usr/sbin/nft" config_get ip "$cfg" ip "/sbin/ip" echo "options {" >> $new_file diff --git a/files/etc/local/mesh-firewall/01-tunnels b/files/etc/local/mesh-firewall/01-tunnels index a6ba809f..1e39d32b 100755 --- a/files/etc/local/mesh-firewall/01-tunnels +++ b/files/etc/local/mesh-firewall/01-tunnels @@ -39,62 +39,59 @@ if [ "$MESHFW_TUNNELS_ENABLED" != "1" ]; then fi # In all cases - restart, flush, clear -- it is necessary to clean up any remenant rules to ensure chain order is correct - -iptables -D FORWARD -i tun+ -j zone_vpn_forward 2>/dev/null -iptables -D INPUT -i tun+ -j zone_vpn_input 2>/dev/null -iptables -D OUTPUT -o tun+ -j zone_vpn_ACCEPT 2>/dev/null -iptables -F forwarding_vpn_rule 2>/dev/null -iptables -F zone_vpn_input 2>/dev/null -iptables -F zone_vpn_ACCEPT 2>/dev/null -iptables -F zone_vpn_REJECT 2>/dev/null -iptables -F zone_vpn_forward 2>/dev/null -iptables -F zone_vpn_dest_ACCEPT 2>/dev/null -iptables -F zone_vpn_dest_REJECT 2>/dev/null -iptables -X forwarding_vpn_rule 2>/dev/null -iptables -X zone_vpn_input 2>/dev/null -iptables -X zone_vpn_ACCEPT 2>/dev/null -iptables -X zone_vpn_REJECT 2>/dev/null -iptables -X zone_vpn_forward 2>/dev/null -iptables -X zone_vpn_dest_ACCEPT 2>/dev/null -iptables -X zone_vpn_dest_REJECT 2>/dev/null +nft flush chain ip fw4 forwarding_vpn_rule 2>/dev/null +nft flush chain ip fw4 input_vpn 2>/dev/null +nft flush chain ip fw4 accept_vpn 2>/dev/null +nft flush chain ip fw4 reject_vpn 2>/dev/null +nft flush chain ip fw4 forward_vpn 2>/dev/null +nft flush chain ip fw4 accept_to_vpn 2>/dev/null +nft flush chain ip fw4 reject_to_vpn 2>/dev/null +nft delete chain ip fw4 forwarding_vpn_rule 2>/dev/null +nft delete chain ip fw4 input_vpn 2>/dev/null +nft delete chain ip fw4 accept_vpn 2>/dev/null +nft delete chain ip fw4 reject_vpn 2>/dev/null +nft delete chain ip fw4 forward_vpn 2>/dev/null +nft delete chain ip fw4 accept_to_vpn 2>/dev/null +nft delete chain ip fw4 reject_to_vpn 2>/dev/null echo " * Adding vtun firewall rules..." -iptables -N forwarding_vpn_rule -iptables -N zone_vpn_input -iptables -N zone_vpn_ACCEPT -iptables -N zone_vpn_REJECT -iptables -N zone_vpn_forward -iptables -N zone_vpn_dest_ACCEPT -iptables -N zone_vpn_dest_REJECT -iptables -I FORWARD 3 -i tun+ -j zone_vpn_forward -iptables -I INPUT 5 -i tun+ -j zone_vpn_input -iptables -I OUTPUT 4 -o tun+ -j zone_vpn_ACCEPT # instead of creating a zone_vpn_output chain -iptables -A zone_vpn_input -p icmp -m icmp --icmp-type 8 -j ACCEPT -iptables -A zone_vpn_input -p tcp -m tcp --dport 2222 -j ACCEPT -iptables -A zone_vpn_input -p tcp -m tcp --dport 8080 -j ACCEPT -iptables -A zone_vpn_input -p tcp -m tcp --dport 80 -j ACCEPT -iptables -A zone_vpn_input -p udp -m udp --dport 698 -j ACCEPT -iptables -A zone_vpn_input -p tcp -m tcp --dport 23 -j ACCEPT -iptables -A zone_vpn_input -p tcp -m tcp --dport 9090 -j ACCEPT -iptables -A zone_vpn_input -p udp -m udp --dport 161 -j ACCEPT -iptables -A zone_vpn_input -m conntrack --ctstate DNAT -m comment --comment "!vtun: Accept port redirections" -j ACCEPT -iptables -A zone_vpn_input -j zone_vpn_REJECT -iptables -I zone_vpn_forward -j forwarding_vpn_rule -iptables -A zone_vpn_forward -j zone_vpn_dest_ACCEPT -if [ "$MESHFW_MESHGW" -eq 1 ] ; then - iptables -I zone_vpn_forward -j zone_wan_dest_ACCEPT +nft add chain ip fw4 forwarding_vpn_rule +nft add chain ip fw4 input_vpn +nft add chain ip fw4 accept_vpn +nft add chain ip fw4 reject_vpn +nft add chain ip fw4 forward_vpn +nft add chain ip fw4 accept_to_vpn +nft add chain ip fw4 reject_to_vpn + +nft insert rule ip fw4 forward iifname "tun*" counter jump forward_vpn +nft insert rule ip fw4 input iifname "tun*" counter jump input_vpn +nft insert rule ip fw4 output oifname "tun*" counter jump accept_vpn # instead of creating a output_vpn chain +nft add rule ip fw4 input_vpn icmp type echo-request counter accept +nft add rule ip fw4 input_vpn tcp dport 2222 counter accept +nft add rule ip fw4 input_vpn tcp dport 8080 counter accept +nft add rule ip fw4 input_vpn tcp dport 80 counter accept +nft add rule ip fw4 input_vpn udp dport 698 counter accept +nft add rule ip fw4 input_vpn tcp dport 23 counter accept +nft add rule ip fw4 input_vpn tcp dport 9090 counter accept +nft add rule ip fw4 input_vpn udp dport 161 counter accept +nft add rule ip fw4 input_vpn ct status dnat counter accept comment \"!vtun: Accept port redirections\" +nft add rule ip fw4 input_vpn counter jump reject_vpn +nft insert rule ip fw4 forward_vpn counter jump forwarding_vpn_rule +nft add rule ip fw4 forward_vpn counter jump accept_to_vpn +if [ "$MESHFW_MESHGW" = "1" ] ; then + nft insert rule ip fw4 forward_vpn counter jump accept_to_wan fi -iptables -A zone_vpn_forward -m conntrack --ctstate DNAT -m comment --comment "!vtun: Accept port forwards" -j ACCEPT -iptables -A zone_vpn_forward -j zone_dtdlink_dest_ACCEPT -iptables -A zone_vpn_forward -j zone_lan_dest_ACCEPT -iptables -A zone_vpn_forward -j zone_wifi_dest_ACCEPT -iptables -A zone_vpn_forward -j zone_vpn_dest_REJECT -iptables -A zone_vpn_ACCEPT -o tun+ -j ACCEPT -iptables -A zone_vpn_ACCEPT -i tun+ -j ACCEPT -iptables -A zone_vpn_REJECT -o tun+ -j reject -iptables -A zone_vpn_REJECT -i tun+ -j reject -iptables -A zone_vpn_dest_ACCEPT -o tun+ -j ACCEPT -iptables -A zone_vpn_dest_REJECT -o tun+ -j reject -iptables -I zone_dtdlink_forward 5 -j zone_vpn_dest_ACCEPT -iptables -I zone_wifi_forward 6 -j zone_vpn_dest_ACCEPT -iptables -I zone_lan_forward 5 -j zone_vpn_dest_ACCEPT +nft add rule ip fw4 forward_vpn ct status dnat counter accept comment \"!vtun: Accept port forwards\" +nft add rule ip fw4 forward_vpn counter jump accept_to_dtdlink +nft add rule ip fw4 forward_vpn counter jump accept_to_lan +nft add rule ip fw4 forward_vpn counter jump accept_to_wifi +nft add rule ip fw4 forward_vpn counter jump reject_to_vpn +nft add rule ip fw4 accept_vpn oifname "tun*" counter accept +nft add rule ip fw4 accept_vpn iifname "tun*" counter accept +nft add rule ip fw4 reject_vpn oifname "tun*" counter reject +nft add rule ip fw4 reject_vpn iifname "tun*" counter reject +nft add rule ip fw4 accept_to_vpn oifname "tun*" counter accept +nft add rule ip fw4 reject_to_vpn oifname "tun*" counter reject +nft insert rule ip fw4 forward_dtdlink counter jump accept_to_vpn +nft insert rule ip fw4 forward_wifi counter jump accept_to_vpn +nft insert rule ip fw4 forward_lan counter jump accept_to_vpn diff --git a/files/etc/local/mesh-firewall/05-xlink b/files/etc/local/mesh-firewall/05-xlink index c6765ac4..5bd06f9e 100755 --- a/files/etc/local/mesh-firewall/05-xlink +++ b/files/etc/local/mesh-firewall/05-xlink @@ -39,32 +39,42 @@ require("nixio") require("uci") if nixio.fs.stat("/etc/config.mesh/xlink") then + function nft_delete(list, query) + for line in io.popen("/usr/sbin/nft -a list chain ip fw4 " .. list):lines() + do + local handle = line:match(query .. "%s*# handle (%d+)") + if handle then + os.execute("/usr/sbin/nft delete rule ip fw4 " .. list .. " handle " .. handle) + return + end + end + end uci.cursor("/etc/config.mesh"):foreach("xlink", "interface", function(section) local ifname = section.ifname - os.execute("/usr/sbin/iptables -D FORWARD -i " .. ifname .. " -j zone_dtdlink_forward") - os.execute("/usr/sbin/iptables -D INPUT -i " .. ifname .. " -j zone_dtdlink_input") - os.execute("/usr/sbin/iptables -D OUTPUT -o " .. ifname .. " -j zone_dtdlink_output") - os.execute("/usr/sbin/iptables -D zone_dtdlink_dest_ACCEPT -o " .. ifname .. " -j ACCEPT") - os.execute("/usr/sbin/iptables -D zone_dtdlink_dest_REJECT -o " .. ifname .. " -j reject") - os.execute("/usr/sbin/iptables -D zone_dtdlink_src_REJECT -i " .. ifname .. " -j reject") + nft_delete("forward", "iifname \"" .. ifname .. "\".*jump forward_dtdlink") + nft_delete("input", "iifname \"" .. ifname .. "\".*jump input_dtdlink") + nft_delete("output", "oifname \"" .. ifname .. "\".*jump accept_dtdlink") + nft_delete("accept_to_dtdlink", "oifname \"" .. ifname .. "\".*accept") + nft_delete("reject_to_dtdlink", "oifname \"" .. ifname .. "\".*reject") + nft_delete("reject_from_dtdlink", "iifname \"" .. ifname .. "\".*reject") end ) - os.execute("/usr/sbin/iptables -D zone_dtdlink_forward -j zone_dtdlink_dest_ACCEPT") - local addrule = false + nft_delete("forward_dtdlink", "jump accept_to_dtdlink") + local addrule = false uci.cursor("/etc/config.mesh"):foreach("xlink", "interface", function(section) local ifname = section.ifname - os.execute("/usr/sbin/iptables -I FORWARD -i " .. ifname .. " -j zone_dtdlink_forward") - os.execute("/usr/sbin/iptables -A INPUT -i " .. ifname .. " -j zone_dtdlink_input") - os.execute("/usr/sbin/iptables -A OUTPUT -o " .. ifname .. " -j zone_dtdlink_output") - os.execute("/usr/sbin/iptables -A zone_dtdlink_dest_ACCEPT -o " .. ifname .. " -j ACCEPT") - os.execute("/usr/sbin/iptables -A zone_dtdlink_dest_REJECT -o " .. ifname .. " -j reject") - os.execute("/usr/sbin/iptables -A zone_dtdlink_src_REJECT -i " .. ifname .. " -j reject") - addrule = true + os.execute("/usr/sbin/nft insert rule ip fw4 forward iifname \"" .. ifname .. "\" counter jump forward_dtdlink") + os.execute("/usr/sbin/nft insert rule ip fw4 input iifname \"" .. ifname .. "\" counter jump input_dtdlink") + os.execute("/usr/sbin/nft insert rule ip fw4 output oifname \"" .. ifname .. "\" counter jump accept_dtdlink") + os.execute("/usr/sbin/nft add rule ip fw4 accept_to_dtdlink oifname \"" .. ifname .. "\" counter accept") + os.execute("/usr/sbin/nft add rule ip fw4 reject_to_dtdlink oifname \"" .. ifname .. "\" counter reject") + os.execute("/usr/sbin/nft add rule ip fw4 reject_from_dtdlink iifname \"" .. ifname .. "\" counter reject") + addrule = true end ) - if addrule then - os.execute("/usr/sbin/iptables -I zone_dtdlink_forward -j zone_dtdlink_dest_ACCEPT") - end + if addrule then + os.execute("/usr/sbin/nft add rule ip fw4 forward_dtdlink counter jump accept_to_dtdlink") + end end diff --git a/files/etc/local/mesh-firewall/10-lan-to-wan b/files/etc/local/mesh-firewall/10-lan-to-wan index 5881c201..bd5b1727 100755 --- a/files/etc/local/mesh-firewall/10-lan-to-wan +++ b/files/etc/local/mesh-firewall/10-lan-to-wan @@ -43,10 +43,10 @@ case "${lan_dhcp_route}" in # Block traffic forwarding between LAN and local WAN (need this rule if WAN happens to be 10.X or 172.16.X) # Allow traffic for mesh-IPs and tun-IPs # Block traffic to all other IPs - iptables -I zone_lan_forward -j REJECT - iptables -I zone_lan_forward -d 172.16.0.0/12 -j ACCEPT - iptables -I zone_lan_forward -d 10.0.0.0/8 -j ACCEPT - iptables -I zone_lan_forward -o ${wan} -j REJECT + nft insert rule ip fw4 forward_lan counter reject + nft insert rule ip fw4 forward_lan ip daddr 172.16.0.0/12 counter accept + nft insert rule ip fw4 forward_lan ip daddr 10.0.0.0/8 counter accept + nft insert rule ip fw4 forward_lan oifname "${wan}" counter reject ;; *) # LAN to WAN okay diff --git a/files/etc/local/mesh-firewall/21-lqm b/files/etc/local/mesh-firewall/21-lqm index 000fddb0..b5edaae6 100755 --- a/files/etc/local/mesh-firewall/21-lqm +++ b/files/etc/local/mesh-firewall/21-lqm @@ -33,8 +33,11 @@ LICENSE -/usr/sbin/iptables -F input_lqm 2> /dev/null -/usr/sbin/iptables -X input_lqm 2> /dev/null -/usr/sbin/iptables -N input_lqm 2> /dev/null -/usr/sbin/iptables -D INPUT -j input_lqm -m comment --comment 'block low quality links' 2> /dev/null -/usr/sbin/iptables -I INPUT -j input_lqm -m comment --comment 'block low quality links' 2> /dev/null +nft flush chain ip fw4 input_lqm 2> /dev/null +nft delete chain ip fw4 input_lqm 2> /dev/null +nft add chain ip fw4 input_lqm 2> /dev/null +handle=$(nft -n -a list chain ip fw4 input | grep "jump input_lqm" | sed "s/^.* handle //") +if [ "$handle" != "" ]; then + nft delete rule ip fw4 input handle $handle 2> /dev/null +fi +nft insert rule ip fw4 input counter jump input_lqm comment \"block low quality links\" 2> /dev/null diff --git a/files/etc/local/mesh-firewall/59-custom-rules b/files/etc/local/mesh-firewall/59-custom-rules index f3ddbd37..92adfbc8 100755 --- a/files/etc/local/mesh-firewall/59-custom-rules +++ b/files/etc/local/mesh-firewall/59-custom-rules @@ -8,7 +8,6 @@ # on home network use the IP address of the WAN assigned to the mesh node # to access the ipcam, e.g. http://192.168.1.59:8082 -#iptables -t nat -A zone_wan_prerouting -p tcp -m tcp --dport 8082 -j DNAT --to -m comment --comment "my mesh ipCam" -#iptables -t nat -A zone_wifi_postrouting -p tcp -m tcp -d -j SNAT --dport 80 --to-source -m comment --comment "my mesh ipCam" -#iptables -t nat -A zone_dtdlink_postrouting -p tcp -m tcp -d -j SNAT --dport 80 --to-source -m comment --comment "my mesh ipCam" - +#nft add rule ip fw4 prerouting_wan tcp dport 8082 counter dnat to +#nft add rule ip fw4 postrouting_wan ip daddr tcp dport 80 counter snat to comment \"my mesh ipCam\" +#nft add rule ip fw4 postrouting_dtdlink ip daddr tcp dport 80 counter snat to comment \"my mesh ipCam\" diff --git a/files/etc/mesh-release b/files/etc/mesh-release index 5595717a..3c4d8506 100644 --- a/files/etc/mesh-release +++ b/files/etc/mesh-release @@ -1 +1 @@ -3.1.1TUNNEL +KN6PLV-openwrt-22.3.0-lua-1461feb diff --git a/files/etc/permpkg b/files/etc/permpkg index 10e3510b..3e2167c3 100644 --- a/files/etc/permpkg +++ b/files/etc/permpkg @@ -7,8 +7,7 @@ firewall hotplug2 ip iperf3 -iptables -iptables-mod-ipopt +nftables iw iwinfo jshn diff --git a/files/etc/radios.json b/files/etc/radios.json index 09d22fc2..41f76adc 100644 --- a/files/etc/radios.json +++ b/files/etc/radios.json @@ -26,6 +26,15 @@ "usechains" : true, "rfband" : "2400" }, + "GL.iNet GL-AR300M16" : { + "name" : "GL.iNet GL-AR300M16", + "comment" : "", + "supported" : "1", + "maxpower" : "23", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "2400" + }, "GL.iNet GL-USB150" : { "name" : "GL.iNet GL-USB150", "comment" : "", @@ -64,6 +73,16 @@ "rfband" : "2400", "chanpower" : { "1" : "27", "2" : "28", "9" : "29", "14" : "27" } }, + "TP-Link CPE210 v2" : { + "name" : "TP-Link CPE210 v2", + "comment" : "", + "supported" : "1", + "maxpower" : "29", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "2400", + "chanpower" : { "1" : "27", "2" : "28", "9" : "29", "14" : "27" } + }, "TP-LINK CPE210 v3" : { "name" : "TP-LINK CPE210 v3", "comment" : "", @@ -124,6 +143,16 @@ "rfband" : "5800ubntus", "chanpower" : { "140" : "17", "184" : "26" } }, + "TP-Link CPE605 v1" : { + "name" : "TP-Link CPE605 v1", + "comment" : "", + "supported" : "1", + "maxpower" : "30", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus", + "chanpower" : { "133" : "30", "141" : "30", "143" : "30" , "149" : "30" , "165" : "30", "166" : "30" } + }, "TP-Link CPE610 v1" : { "name" : "TP-Link CPE610 v1", "comment" : "", @@ -144,6 +173,16 @@ "rfband" : "5800ubntus", "chanpower" : { "133" : "15", "141" : "26", "143" : "25" , "149" : "15" , "165" : "14", "166" : "25" } }, + "TP-Link CPE710 v1" : { + "name" : "TP-Link CPE710 v1", + "comment" : "", + "supported" : "1", + "maxpower" : "30", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus", + "chanpower" : { "133" : "30", "141" : "30", "143" : "30" , "149" : "30" , "165" : "30", "166" : "30" } + }, "TP-Link WBS210 v1" : { "name" : "TP-Link WBS210 v1", "comment" : "", @@ -220,6 +259,24 @@ "usechains" : true, "rfband" : "5800ubntus" }, + "MikroTik RouterBOARD 921GS-5HPacD-15s" : { + "name" : "MikroTik RouterBOARD 921GS-5HPacD-15s", + "comment" : "", + "supported" : "1", + "maxpower" : "31", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, + "MikroTik RouterBOARD 921GS-5HPacD-19s" : { + "name" : "MikroTik RouterBOARD 921GS-5HPacD-19s", + "comment" : "", + "supported" : "1", + "maxpower" : "31", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, "MikroTik RouterBOARD 952Ui-5ac2nD" : { "name" : "MikroTik RouterBOARD 952Ui-5ac2nD", "comment" : "", @@ -238,6 +295,15 @@ "usechains" : true, "rfband" : "2400" }, + "MikroTik RouterBOARD 952Ui-5ac2nD (hAP ac lite)" : { + "name" : "MikroTik RouterBOARD 952Ui-5ac2nD (hAP ac lite)", + "comment" : "", + "supported" : "1", + "maxpower" : "22", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "2400" + }, "Mikrotik RouterBOARD 912UAG-2HPnD" : { "name" : "Mikrotik RouterBOARD 912UAG-2HPnD", "comment" : "", @@ -409,6 +475,15 @@ "usechains" : true, "rfband" : "5800ubntus" }, + "MikroTik LHG 5 ac (RBLHGG-5acD)": { + "name" : "MikroTik LHG 5 ac (RBLHGG-5acD)", + "comment" : "", + "supported" : "1", + "maxpower" : "25", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, "MikroTik RouterBOARD SXTsq 5nD" : { "name" : "MikroTik RouterBOARD SXTsq 5nD", "comment" : "", @@ -463,6 +538,46 @@ "usechains" : true, "rfband" : "5800ubntus" }, + "MikroTik RouterBOARD SXT 5nD (SXT Lite5)": { + "name" : "MikroTik RouterBOARD SXT 5nD (SXT Lite5)", + "comment" : "", + "supported" : "1", + "maxpower" : "28", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, + "MikroTik SXTsq 5 ac (RBSXTsqG-5acD)": { + "name" : "MikroTik SXTsq 5 ac (RBSXTsqG-5acD)", + "comment" : "", + "supported" : "1", + "maxpower" : "25", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, + "MikroTik hAP ac2" : { + "name" : "MikroTik RouterBOARD RBD52G-5HacD2HnD", + "comment" : "", + "supported" : "1", + "maxpower" : "27", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "2400", + "rfbandwidths" : [ 10, 20 ], + "rfblocked" : [ -4, -3, -2, -1 ] + }, + "MikroTik hAP ac3" : { + "name" : "MikroTik RouterBOARD RBD53iG-5HacD2HnD", + "comment" : "", + "supported" : "1", + "maxpower" : "27", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "2400", + "rfbandwidths" : [ 10, 20 ], + "rfblocked" : [ -4, -3, -2, -1 ] + }, "0xe005" : { "name" : "Ubiquiti NanoStation M5", "comment" : "", @@ -598,6 +713,15 @@ "usechains" : true, "rfband" : "5800ubntus" }, + "0xe1f5" : { + "name" : "Ubiquiti Rocket 5AC Lite", + "comment" : "", + "supported" : "1", + "maxpower" : "27", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, "0xe202" : { "name" : "Ubiquiti Bullet M2 HP", "comment" : "", @@ -760,6 +884,15 @@ "usechains" : false, "rfband" : "2400" }, + "0xe3d5": { + "name" : "Ubiquiti PowerBeam 5AC 500", + "comment" : "", + "supported" : "1", + "maxpower" : "24", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, "0xe3e5" : { "name" : "Ubiquiti PowerBeam M5 XW 300", "comment" : "", @@ -823,6 +956,33 @@ "usechains" : true, "rfband" : "5800ubntus" }, + "0xe7fb": { + "name" : "Ubiquiti NanoStation AC (WA)", + "comment" : "", + "supported" : "1", + "maxpower" : "27", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, + "0xe7fc": { + "name" : "Ubiquiti NanoBeam AC Gen2 (WA)", + "comment" : "", + "supported" : "1", + "maxpower" : "27", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, + "0xe7f9": { + "name" : "Ubiquiti LiteBeam 5AC Gen2", + "comment" : "", + "supported" : "1", + "maxpower" : "25", + "pwroffset" : "0", + "usechains" : true, + "rfband" : "5800ubntus" + }, "0xe805" : { "name" : "Ubiquiti NanoStation M5", "comment" : "", diff --git a/files/etc/uci-defaults/11_compat_version b/files/etc/uci-defaults/11_compat_version new file mode 100644 index 00000000..74581ce7 --- /dev/null +++ b/files/etc/uci-defaults/11_compat_version @@ -0,0 +1,14 @@ +#! /bin/sh +case "$(/usr/local/bin/get_boardid)" in + MikroTik\ hAP\ ac2|\ + MikroTik\ hAP\ ac3|\ + MikroTik\ SXTsq\ 5\ ac*|\ + MikroTik\ LHG\ 5\ ac*) + sed -i "s/^compat_version = 1.0/compat_version = 1.1/" /etc/config.mesh/_setup + sed -i "s/^compat_version = 1.0/compat_version = 1.1/" /etc/config.mesh/_setup.default + /sbin/uci -q set system.@system[0].compat_version=1.1 + /sbin/uci -q commit system + ;; + *) + ;; +esac diff --git a/files/etc/uci-defaults/94_fix_mac_addresses b/files/etc/uci-defaults/94_fix_mac_addresses new file mode 100644 index 00000000..b298eeae --- /dev/null +++ b/files/etc/uci-defaults/94_fix_mac_addresses @@ -0,0 +1,41 @@ +#!/bin/sh +# Fix mac addresses as necessary + +fix="" + +eth0=$(ifconfig eth0 2> /dev/null | grep HWaddr | sed s/^.*HWaddr\ // | sed s/\ //g) +wlan0=$(ifconfig wlan0 2> /dev/null | grep HWaddr | sed s/^.*HWaddr\ // | sed s/\ //g) +brlan=$(ifconfig br-lan 2> /dev/null | grep HWaddr | sed s/^.*HWaddr\ // | sed s/\ //g) +boardid=$(/usr/local/bin/get_boardid) +mfg=$(/usr/local/bin/get_hardware_mfg) + +if [ "$eth0" = "$wlan0" -a "$eth0" != "" ]; then + fix="lan wan dtdlink" +elif [ "$wlan0" = "" ]; then + fix="lan" +elif [ "$brlan" = "00:03:7F:11:23:C6" ]; then # Fix AR300M + fix="lan" +elif [ "$mfg" = "MikroTik" ]; then # Fix all MikroTiks + fix="lan wan dtdlink" +fi + +mkdir -p /etc/aredn_include + +list="" +for i in $fix +do + if [ ! -s /etc/aredn_include/fixedmac.$i ]; then + # Some mac addresses are stored in /etc/board.json + mac=$(jsonfilter -i /etc/board.json -e @.network.$i.macaddr 2> /dev/null | awk '{print toupper($0)}') + if [[ "$list" =~ "#$mac#" ]]; then + # Dont allow reuse + mac="" + fi + if [ "$mac" = "" ]; then + # Generate a safe mac address + mac=$(hexdump -n5 -e'/5 "02" 5/1 ":%02X"' /dev/random) + fi + echo -e "\toption\tmacaddr\t$mac" > /etc/aredn_include/fixedmac.$i + list="$list#$mac#" + fi +done diff --git a/files/etc/uci-defaults/99_setup_aredn_include b/files/etc/uci-defaults/99_setup_aredn_include index eaab695f..a7eadf81 100755 --- a/files/etc/uci-defaults/99_setup_aredn_include +++ b/files/etc/uci-defaults/99_setup_aredn_include @@ -1,14 +1,16 @@ #!/bin/sh # extract auto-generated first boot switch config settings # and store them for future use. Support advanced user overrides. +ainclude="/etc/aredn_include" +mkdir -p $ainclude + if [ -f /etc/aredn_include/swconfig.user ] then cp /etc/aredn_include/swconfig.user /etc/aredn_include/swconfig fi if [ ! -f /etc/aredn_include/swconfig ] then - mkdir -p /etc/aredn_include - touch /etc/aredn_include/swconfig + touch $ainclude/swconfig i=0 while true; do uci -q get network.\@switch\[$i\] > /dev/null @@ -17,11 +19,11 @@ then then break fi - echo "config switch" >> /etc/aredn_include/swconfig - echo " option name '`uci -q get network.\@switch\[$i\].name`'" >> /etc/aredn_include/swconfig - echo " option reset '`uci -q get network.\@switch\[$i\].reset`'" >> /etc/aredn_include/swconfig - echo " option enable_vlan '`uci -q get network.\@switch\[$i\].enable_vlan`'" >> /etc/aredn_include/swconfig - echo "" >> /etc/aredn_include/swconfig + echo "config switch" >> $ainclude/swconfig + echo " option name '`uci -q get network.\@switch\[$i\].name`'" >> $ainclude/swconfig + echo " option reset '`uci -q get network.\@switch\[$i\].reset`'" >> $ainclude/swconfig + echo " option enable_vlan '`uci -q get network.\@switch\[$i\].enable_vlan`'" >> $ainclude/swconfig + echo "" >> $ainclude/swconfig let i++ done @@ -33,11 +35,11 @@ then then break fi - echo "config switch_vlan" >> /etc/aredn_include/swconfig - echo " option device '`uci -q get network.\@switch_vlan\[$i\].device`'" >> /etc/aredn_include/swconfig - echo " option vlan '`uci -q get network.\@switch_vlan\[$i\].vlan`'" >> /etc/aredn_include/swconfig - echo " option ports '`uci -q get network.\@switch_vlan\[$i\].ports`'" >> /etc/aredn_include/swconfig - echo "" >> /etc/aredn_include/swconfig + echo "config switch_vlan" >> $ainclude/swconfig + echo " option device '`uci -q get network.\@switch_vlan\[$i\].device`'" >> $ainclude/swconfig + echo " option vlan '`uci -q get network.\@switch_vlan\[$i\].vlan`'" >> $ainclude/swconfig + echo " option ports '`uci -q get network.\@switch_vlan\[$i\].ports`'" >> $ainclude/swconfig + echo "" >> $ainclude/swconfig let i++ done @@ -49,29 +51,68 @@ then then break fi - echo "config switch_port" >> /etc/aredn_include/swconfig - echo " option device '`uci -q get network.\@switch_port\[$i\].device`'" >> /etc/aredn_include/swconfig - echo " option port '`uci -q get network.\@switch_port\[$i\].port`'" >> /etc/aredn_include/swconfig - echo " option pvid '`uci -q get network.\@switch_port\[$i\].pvid`'" >> /etc/aredn_include/swconfig - echo "" >> /etc/aredn_include/swconfig + echo "config switch_port" >> $ainclude/swconfig + echo " option device '`uci -q get network.\@switch_port\[$i\].device`'" >> $ainclude/swconfig + echo " option port '`uci -q get network.\@switch_port\[$i\].port`'" >> $ainclude/swconfig + echo " option pvid '`uci -q get network.\@switch_port\[$i\].pvid`'" >> $ainclude/swconfig + echo "" >> $ainclude/swconfig let i++ done fi +# extract and store lan, wan, and dtdlink interfaces +rm -f $ainclude/*.network.config +for i in lan wan dtdlink +do + #is 1 or 2+ devices (1 device has 'option device', multiple has 'list ports' in board.json)? + device=`jsonfilter -i /etc/board.json -e @.network.$i.device 2>/dev/null` + if [ $? -eq 0 ]; then + echo " list ports '$device'" > $ainclude/$i.network.config + else + ports=`jsonfilter -q -i /etc/board.json -e @.network.$i.ports` + if [ $? -eq 0 ]; then + for j in `echo $ports | grep -o "[a-z0-9\.]\+" 2>/dev/null` + do + echo " list ports '$j'" >> $ainclude/$i.network.config + done + fi + fi +done + +#apply any user overrides +for i in lan wan dtdlink +do + if [ -f $ainclude/$i.network.user ]; then + cp $ainclude/$i.network.user $ainclude/$i.network.config + fi +done + +#if unable to create *.network.config includes, put in a default in hopes the device ports +#will function. The correction to board.json is made in the image, in 02_networks +# +if [ ! -f $ainclude/lan.network.config ]; then + echo " list ports 'eth0'" > $ainclude/lan.network.config +fi +if [ ! -f $ainclude/wan.network.config ]; then + echo " list ports 'eth0.1'" > $ainclude/wan.network.config +fi +if [ ! -f $ainclude/dtdlink.network.config ]; then + echo " list ports 'eth0.2'" > $ainclude/dtdlink.network.config +fi + # Save system NET LED settings -if [ ! -f /etc/aredn_include/system_netled ] +if [ ! -f $ainclude/system_netled ] then - mkdir -p /etc/aredn_include - touch /etc/aredn_include/system_netled + touch $ainclude/system_netled -CFG=/etc/board.json + CFG=/etc/board.json -. /usr/share/libubox/jshn.sh + . /usr/share/libubox/jshn.sh -[ -s $CFG ] || /bin/board_detect || exit 1 + [ -s $CFG ] || /bin/board_detect || exit 1 -generate_led() { + generate_led() { local key="$1" local cfg="led_$key" @@ -89,13 +130,13 @@ generate_led() { netdev) local device mode json_get_vars device mode - echo "config led 'led_$1'" >> /etc/aredn_include/system_netled - echo " option name '$name'" >> /etc/aredn_include/system_netled - echo " option sysfs '$sysfs'" >> /etc/aredn_include/system_netled - echo " option trigger 'netdev'" >> /etc/aredn_include/system_netled - echo " option mode '$mode'" >> /etc/aredn_include/system_netled - echo " option dev '$device'" >> /etc/aredn_include/system_netled - echo "" >> /etc/aredn_include/system_netled + echo "config led 'led_$1'" >> $ainclude/system_netled + echo " option name '$name'" >> $ainclude/system_netled + echo " option sysfs '$sysfs'" >> $ainclude/system_netled + echo " option trigger 'netdev'" >> $ainclude/system_netled + echo " option mode '$mode'" >> $ainclude/system_netled + echo " option dev '$device'" >> $ainclude/system_netled + echo "" >> $ainclude/system_netled ;; usb) @@ -116,12 +157,12 @@ generate_led() { switch) local port_mask speed_mask json_get_vars port_mask speed_mask - echo "config led 'led_$1'" >> /etc/aredn_include/system_netled - echo " option name '$name'" >> /etc/aredn_include/system_netled - echo " option sysfs '$sysfs'" >> /etc/aredn_include/system_netled - echo " option trigger '$trigger'" >> /etc/aredn_include/system_netled - echo " option port_mask '$port_mask'" >> /etc/aredn_include/system_netled - echo "" >> /etc/aredn_include/system_netled + echo "config led 'led_$1'" >> $ainclude/system_netled + echo " option name '$name'" >> $ainclude/system_netled + echo " option sysfs '$sysfs'" >> $ainclude/system_netled + echo " option trigger '$trigger'" >> $ainclude/system_netled + echo " option port_mask '$port_mask'" >> $ainclude/system_netled + echo "" >> $ainclude/system_netled ;; portstate) @@ -137,25 +178,19 @@ generate_led() { json_select .. json_select .. -} + } -json_init -json_load "$(cat ${CFG})" + json_init + json_load "$(cat ${CFG})" -if [ ! -s /etc/aredn_include/system_netled ]; then - touch /etc/aredn_include/system_netled + if [ ! -s $ainclude/system_netled ]; then + touch $ainclude/system_netled json_get_keys keys led for key in $keys; do generate_led $key; done -fi -fi - -hwtype="$('/usr/local/bin/get_hardwaretype')" -touch /etc/aredn_include/bridge_ports -if [ "$hwtype" = "nanostation-m" -o "$hwtype" = "cpe220-v2" -o "$hwtype" = "cpe220-v3" -o "$hwtype" = "cpe210-v1" -o "$hwtype" = "cpe510-v1" -o "$hwtype" = "wbs210-v1" -o "$hwtype" = "wbs210-v2" -o "$hwtype" = "wbs510-v1" -o "$hwtype" = "wbs510-v2" ]; then - echo " option type 'bridge'" > /etc/aredn_include/bridge_ports + fi fi exit 0 diff --git a/files/usr/lib/lua/aredn/hardware.lua b/files/usr/lib/lua/aredn/hardware.lua index 0b70422a..5857116a 100644 --- a/files/usr/lib/lua/aredn/hardware.lua +++ b/files/usr/lib/lua/aredn/hardware.lua @@ -42,6 +42,8 @@ local hardware = {} local radio_json = nil local board_json = nil +local rf_channel_map = nil + function hardware.get_board() if not board_json then local f = io.open("/etc/board.json") @@ -123,6 +125,22 @@ function hardware.get_board_type() return hardware.get_board().model.id end +function hardware.get_board_network_ifname(type) + local network = hardware.get_board().network[type] + if network then + if network.ifname then + return network.ifname + end + if network.device then + return network.device + end + if network.ports then + return table.concat(network.ports, " ") + end + end + return "" +end + function hardware.get_type() local id = hardware.get_board().model.id local type = id:match(",(.*)") @@ -151,6 +169,10 @@ function hardware.get_iface_name(name) if intfname then return intfname:match("^(%S+)") end + local device = cursor:get("network", name, "device") + if device then + return device + end -- Now we guess if name == "lan" then return "eth0" @@ -213,19 +235,31 @@ function hardware.get_link_led() end function hardware.has_poe() - local err, result = xpcall( - function() return hardware.get_board().gpioswitch.poe_passthrough.pin or true end, - function() return false end - ) - return result + local board = hardware.get_board() + if board and board.gpioswitch and board.gpioswitch.poe_passthrough and board.gpioswitch.poe_passthrough.pin then + return true + end + -- Handle typo in various config files + if board and board.gpioswitch and board.gpioswitch.poe_passtrough and board.gpioswitch.poe_passtrough.pin then + return true + end + local _, count = nixio.fs.glob("/sys/class/gpio/enable-poe:*") + if count > 0 then + return true + end + return false end function hardware.has_usb() - local err, result = xpcall( - function() return hardware.get_board().gpioswitch.usb_power_switch.pin or true end, - function() return false end - ) - return result + local board = hardware.get_board() + if board and board.gpioswitch and board.gpioswitch.usb_power_switch and board.gpioswitch.usb_power_switch.pin then + return true + end + local _, count = nixio.fs.glob("/sys/class/gpio/usb-power") + if count > 0 then + return true + end + return false end function hardware.get_rfband() @@ -237,21 +271,120 @@ function hardware.get_rfband() end end +function hardware.get_rfbandwidths() + local radio = hardware.get_radio() + if radio.rfbandwidths then + return radio.rfbandwidths + else + return { 5, 10, 20 } + end +end + function hardware.get_default_channel() local radio = hardware.get_radio() if radio.rfband == "900" then return { channel = 5, bandwidth = 5 } - elseif radio.rfband == "2400" then - return { channel = -2, bandwidth = 10 } + end + local w = {} + for _, width in ipairs(hardware.get_rfbandwidths()) + do + w[width] = true + end + local width = w[10] and 10 or w[5] and 5 or 20 + if radio.rfband == "2400" then + local c = {} + for _, chan in ipairs(hardware.get_rfchannels()) + do + c[chan.number] = chan + end + local chan = c[-2] and -2 or 1 + return { channel = chan, bandwidth = width } elseif radio.rfband == "3400" then - return { channel = 84, bandwidth = 10 } + return { channel = 84, bandwidth = width } elseif radio.rfband == "5800ubntus" then - return { channel = 149, bandwidth = 10 } + return { channel = 149, bandwidth = width } else return nil end end +function hardware.get_rfchannels(wifiintf) + if not rf_channel_map then + rf_channel_map = { + ["900"] = {}, + ["2400"] = {}, + ["3400"] = {}, + ["5500"] = {}, + ["5800ubntus"] = {} + } + for i = 4,7 + do + rf_channel_map["900"][i - 3] = { label = i .. " (" .. (887 + i * 5) .. ")", number = i, frequency = 887 + i * 5 } + end + for i = -4,11 + do + rf_channel_map["2400"][i + (i <= 0 and 5 or 4)] = { label = i .. " (" .. (2407 + i * 5) .. ")", number = i, frequency = 2407 + i * 5 } + end + for i = 76,99 + do + rf_channel_map["3400"][i - 75] = { label = i .. " (" .. (3000 + i * 5) .. ")", number = i, frequency = 3000 + i * 5 } + end + for i = 36,64,4 + do + rf_channel_map["5500"][(i - 32) / 4] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } + end + for i = 100,140,4 + do + rf_channel_map["5500"][(i - 64) / 4] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } + end + for i = 149,165,4 + do + rf_channel_map["5500"][(i - 69) / 4] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } + end + for i = 131,184 + do + rf_channel_map["5800ubntus"][i - 130] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } + end + end + local channels = {} + local rfband = hardware.get_rfband() + if rfband and rf_channel_map[rfband] then + channels = rf_channel_map[rfband] + else + local f = io.popen("iwinfo " .. wifiintf .. " freqlist") + if f then + for line in f:lines() + do + local freq, num = line:match("(%d+%.%d+) GHz %(Channel (%d+)%)") + if freq and not line:match("restricted") then + freq = freq:gsub("%.", "") + num = num:gsub("^0+", "") + channels[#channels + 1] = { + label = num .. " (" .. freq .. ")", + number = tonumber(num), + frequency = freq + } + end + end + f:close() + end + end + local radio = hardware.get_radio() + if radio.rfblocked then + for _, chan in ipairs(radio.rfblocked) + do + for idx, channel in ipairs(channels) + do + if channel.number == chan then + table.remove(channels, idx) + break + end + end + end + end + return channels +end + function hardware.supported() local radio = hardware.get_radio() if radio then diff --git a/files/usr/lib/lua/aredn/info.lua b/files/usr/lib/lua/aredn/info.lua index f6434208..c6f9df39 100755 --- a/files/usr/lib/lua/aredn/info.lua +++ b/files/usr/lib/lua/aredn/info.lua @@ -189,6 +189,7 @@ function model.getSSID() for pos, t in pairs(wif) do if wif[pos]['network']=="wifi" then myssid=wif[pos]['ssid'] + break end end return myssid @@ -205,6 +206,7 @@ function model.getMeshRadioDevice() for pos,i in pairs(wifiinterfaces) do if wifiinterfaces[pos]['mode']=="adhoc" then radio=wifiinterfaces[pos]['device'] + break end end return radio @@ -218,6 +220,7 @@ function model.isMeshRadioEnabled(radio) for pos,i in pairs(wifidevice) do if wifidevice[pos]['.name']==radio then disabled=wifidevice[pos]['disabled'] + break end end @@ -237,6 +240,7 @@ function model.getMeshRadioDistance(radio) for pos,i in pairs(wifidevice) do if wifidevice[pos]['.name']==radio then distance=wifidevice[pos]['distance'] + break end end return distance diff --git a/files/usr/lib/lua/aredn/log.lua b/files/usr/lib/lua/aredn/log.lua index f708dc00..e9bfea23 100644 --- a/files/usr/lib/lua/aredn/log.lua +++ b/files/usr/lib/lua/aredn/log.lua @@ -42,6 +42,7 @@ function log.open(name, maxsize) l.logfile = name l.logmax = maxsize l.logf = nil + l.prefix = nil return l end @@ -49,7 +50,11 @@ function log:write(str) if not self.logf then self.logf = io.open(self.logfile, "a") end - self.logf:write(string.format("%s: %s\n", os.date("%m/%d %H:%M:%S", os.time()), str)) + local pstr = "" + if self.prefix then + pstr = self.prefix .. ": " + end + self.logf:write(string.format("%s: %s%s\n", os.date("%m/%d %H:%M:%S", os.time()), pstr, str)) if self.logf:seek() > self.logmax then self:flush(true) end diff --git a/files/usr/lib/lua/aredn/nettools.lua b/files/usr/lib/lua/aredn/nettools.lua index 5e74de95..481c7303 100755 --- a/files/usr/lib/lua/aredn/nettools.lua +++ b/files/usr/lib/lua/aredn/nettools.lua @@ -35,7 +35,6 @@ --]] require("aredn.utils") -require("luci.sys") local tools = {} @@ -125,7 +124,7 @@ function tools.getIperf3(target, protocol) local summary = { protocol = protocol, client = {}, server = {}, sender = {}, receiver = {} } local trace = {} -- start remote server - luci.sys.httpget("http://" .. target .. ":8080/cgi-bin/iperf?server=") + os.execute("wget -q 'http://" .. target .. ":8080/cgi-bin/iperf?server=' > /dev/null 2>&1") local output = capture("/usr/bin/iperf3 -b 0 -c " .. target .. (protocol == "udp" and " -u" or "") .. " 2>&1") for _, line in ipairs(output:splitNewLine()) do diff --git a/files/usr/lib/lua/aredn/utils.lua b/files/usr/lib/lua/aredn/utils.lua index ff9f181b..36bb8071 100755 --- a/files/usr/lib/lua/aredn/utils.lua +++ b/files/usr/lib/lua/aredn/utils.lua @@ -156,6 +156,9 @@ end function get_ifname(ifn) local u=uci.cursor() local iface=u:get("network",ifn,"ifname") + if not iface then + iface=u:get("network",ifn,"device") + end return iface end @@ -260,6 +263,9 @@ function iplookup(host) end local nso=capture("nslookup "..host) local ip=nso:match("Address 1: (.*)%c") + if not ip then + ip=nso:match("Address: ([%d%.]+)") + end return ip end diff --git a/files/usr/lib/lua/luci/template/parser.lua b/files/usr/lib/lua/luci/template/parser.lua new file mode 100644 index 00000000..abfd1a1c --- /dev/null +++ b/files/usr/lib/lua/luci/template/parser.lua @@ -0,0 +1 @@ +-- Fake diff --git a/files/usr/local/bin/aredn_message.sh b/files/usr/local/bin/aredn_message.sh index 8612b244..c7cd13de 100755 --- a/files/usr/local/bin/aredn_message.sh +++ b/files/usr/local/bin/aredn_message.sh @@ -41,7 +41,7 @@ ping -q -W10 -c1 downloads.arednmesh.org > /dev/null && nodename=$(echo "$HOSTNAME" | tr 'A-Z' 'a-z') -if [ $online = "true" ] +if [ "$online" = "true" ] then # fetch node specific message file wget -q -O aredn_message -P /tmp http://downloads.arednmesh.org/messages/"${nodename}".txt && diff --git a/files/usr/local/bin/aredn_postupgrade b/files/usr/local/bin/aredn_postupgrade index 5609473c..7b2015a2 100755 --- a/files/usr/local/bin/aredn_postupgrade +++ b/files/usr/local/bin/aredn_postupgrade @@ -37,7 +37,6 @@ require("aredn.utils") local aredn_info = require("aredn.info") require("aredn.hardware") -require("luci.sys") require("uci") local needsrun = aredn_info.get_nvram("nodeupgraded") @@ -127,4 +126,4 @@ os.execute("/usr/local/bin/node-setup -a mesh") aredn_info.set_nvram("nodeupgraded", "0") print "Rebooting node" -luci.sys.reboot() +os.execute("reboot >/dev/null 2>&1") diff --git a/files/usr/local/bin/fccid b/files/usr/local/bin/aredn_sysupgrade similarity index 70% rename from files/usr/local/bin/fccid rename to files/usr/local/bin/aredn_sysupgrade index ad28b04a..35d4e2f7 100755 --- a/files/usr/local/bin/fccid +++ b/files/usr/local/bin/aredn_sysupgrade @@ -1,10 +1,7 @@ -#!/bin/sh -<<'LICENSE' +true <<'LICENSE' Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks - Copyright (C) 2015 Conrad Lara - See Contributors file for additional contributors - - Copyright (c) 2013 David Rivenburg et al. BroadBand-HamNet + Copyright (C) 2022 Tim Wilkinson + See Contributors file for additional contributors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,12 +32,21 @@ LICENSE -[ -f /etc/config/run-fccid ] || exit +# +# Pre-upgrade special cases +# +case "$(/usr/local/bin/get_boardid)" in + MikroTik\ hAP\ ac3) + # If we're running from RAM we must now format the flash otherwise + # the install will fail + if [ "$(cat /proc/mounts | grep overlay)" = "" ]; then + ubidetach -m 1 + ubiformat /dev/mtd1 -y + ubiattach -m 1 + fi + ;; + *) + ;; +esac -wifiif=$(uci -q get 'network.wifi.ifname') - -# stagger the beacons between nodes -N=$(ifconfig "$wifiif" | grep "inet addr" | cut -f4 -d. | cut -c1-3) -sleep "$N" - -echo "ID: $(uname -n)" | socat - udp4:10.255.255.255:4919,broadcast,so-bindtodevice="$wifiif" +/sbin/sysupgrade $* diff --git a/files/usr/local/bin/clean_zombie.sh b/files/usr/local/bin/clean_zombie.sh deleted file mode 100755 index 261ad280..00000000 --- a/files/usr/local/bin/clean_zombie.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh -true <<'LICENSE' - Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks - Copyright (C) 2018 Joe Ayers AE6XE - See Contributors file for additional contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation version 3 of the License. - - This program is distributed in the hope that 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, see . - - Additional Terms: - - Additional use restrictions exist on the AREDN(TM) trademark and logo. - See AREDNLicense.txt for more info. - - Attributions to the AREDN Project must be retained in the source code. - If importing this code into a new or existing project attribution - to the AREDN project must be added to the source code. - - You must not misrepresent the origin of the material contained within. - - Modified versions must be modified to attribute to the original source - and be marked in reasonable ways as differentiate it from the original - version. - -LICENSE - -# Look for hung 'iw' zombie processes prone to hang -# when available memory is low. - -# if Mesh RF is disabled, then nothing to do -iface=$(uci -q get 'network.wifi.ifname') -if [ "$iface" = "${iface##wlan*}" ]; then - exit -fi - -zombiepid="/tmp/clean_zombie.pid" - -[ -e $zombiepid ] && [ -d "/proc/$(cat $zombiepid)" ] && exit - -echo "$$" > $zombiepid - -# wait for rssi_monitor and snrlog to run -sleep 20; - -for pid in $(ps | grep -E "^\s*\d+\s+root\s+\d+\s+Z\s+\[iw\]"| sed -e "s/^\s*//"| cut -f1 -d\ ) -do - - # found an "iw" zombie - sleep 10 # in case process is naturally closing and needs more time - if [ -d "/proc/$pid" ] ; then - date >> /tmp/zombie.log - ps | grep -E "^\s*${pid}\s+" | grep -v grep | tail -1 >> /tmp/zombie.log - ppid="$(grep -i ppid < /proc/"$pid"/status | cut -f2)" - if [ -d "/proc/$ppid" ] ; then - ps | grep -E "^\s*${ppid}\s+" | grep -v grep | tail -1 >> /tmp/zombie.log - grep crond /proc/"$ppid"/status 2>&1 > /dev/null - if [ $? -ne 0 -a "$ppid" -gt 1 ]; then - - # kill the zombie's parent process to free up resources - kill -9 "$ppid" 2>&1 >> /tmp/zombie.log - echo "Killed $ppid" >> /tmp/zombie.log - if [ "$(wc -l /tmp/zombie.log | cut -f1 -d\ )" -gt 300 ] ; then - - # keep file size in check - cp /tmp/zombie.log /tmp/zombie.tmp - tail -275 /tmp/zombie.tmp > /tmp/zombie.log - rm -f /tmp/zombie.tmp - fi - fi - fi - echo "" >> /tmp/zombie.log - fi -done - -rm $zombiepid diff --git a/files/usr/local/bin/manager.lua b/files/usr/local/bin/manager.lua index f84a4a45..07b044fb 100755 --- a/files/usr/local/bin/manager.lua +++ b/files/usr/local/bin/manager.lua @@ -57,18 +57,18 @@ function exit_app() coroutine.yield('exit') end +mainlog = aredn.log.open("/tmp/manager.log", 8000) + -- Load management tasks local tasks = {} for name in nixio.fs.dir("/usr/local/bin/mgr") do local task = name:match("^(.+)%.lua$") if task then - tasks[#tasks + 1] = { app = require("mgr." .. task) } + tasks[#tasks + 1] = { name = task, app = require("mgr." .. task) } end end -local log = aredn.log.open("/tmp/manager.log", 8000) - for i, task in ipairs(tasks) do task.routine = coroutine.create(task.app) @@ -80,10 +80,11 @@ do for i, task in ipairs(tasks) do if task.time <= os.time() then + mainlog.prefix = task.name local status, newdelay = coroutine.resume(task.routine) if not status then - log:write(newdelay) -- error message - log:flush() + mainlog:write(newdelay) -- error message + mainlog:flush() task.routine = coroutine.create(task.app) task.time = 120 + os.time() -- 2 minute restart delay elseif not newdelay then @@ -91,9 +92,12 @@ do elseif newdelay == "exit" then task.routine = null task.time = math.huge + mainlog:write("Terminating manager task: " .. task.name) + mainlog:flush() else task.time = newdelay + os.time() end + mainlog.prefix = nil end end table.sort(tasks, function(a,b) return a.time < b.time end) diff --git a/files/usr/local/bin/mgr/aredn_message.lua b/files/usr/local/bin/mgr/aredn_message.lua index 61afcb61..3bd3eba6 100755 --- a/files/usr/local/bin/mgr/aredn_message.lua +++ b/files/usr/local/bin/mgr/aredn_message.lua @@ -37,7 +37,8 @@ function aredn_message() while true do os.execute("/usr/local/bin/aredn_message.sh") - local pollrate = tonumber(uci.cursor():get("aredn", "@alerts[0]", "pollrate")) + local pollrate = uci.cursor():get("aredn", "@alerts[0]", "pollrate") + pollrate = tonumber(pollrate) if not pollrate or pollrate <= 0 then pollrate = 12 -- 12 hour default end diff --git a/files/usr/local/bin/mgr/fccid.lua b/files/usr/local/bin/mgr/fccid.lua index a5df2a7d..1f1e8599 100644 --- a/files/usr/local/bin/mgr/fccid.lua +++ b/files/usr/local/bin/mgr/fccid.lua @@ -42,11 +42,11 @@ function fccid() local udp = socket.udp() udp:setoption("broadcast", true) udp:setsockname(ip, 4919) - udp:setpeername("10.255.255.255", 4919) + --udp:setpeername("10.255.255.255", 4919) while true do if nixio.fs.stat("/etc/config/run-fccid") then - udp:send(id) + udp:sendto(id, "10.255.255.255", 4919) end wait_for_ticks(5 * 60) -- 5 minutes end diff --git a/files/usr/local/bin/mgr/lqm.lua b/files/usr/local/bin/mgr/lqm.lua index 0e5edd67..a965f703 100755 --- a/files/usr/local/bin/mgr/lqm.lua +++ b/files/usr/local/bin/mgr/lqm.lua @@ -46,7 +46,7 @@ local tx_quality_run_avg = 0.8 -- tx quality running average local ping_timeout = 1.0 -- timeout before ping gives a qualtiy penalty local dtd_distance = 50 -- distance (meters) after which nodes connected with DtD links are considered different sites -local IPTABLES = "/usr/sbin/iptables" +local NFT = "/usr/sbin/nft" local IW = "/usr/sbin/iw" local ARPING = "/usr/sbin/arping" @@ -115,30 +115,43 @@ function should_ping(track) end end +function nft_handle(list, query) + for line in io.popen(NFT .. " -a list chain ip fw4 " .. list):lines() + do + local handle = line:match(query .. "%s*# handle (%d+)") + if handle then + return handle + end + end + return nil +end + function update_block(track) if should_block(track) then track.blocked = true if track.type == "Tunnel" then - if os.execute(IPTABLES .. " -C input_lqm -p udp --destination-port 698 --in-interface " .. track.device .. " -j DROP 2> /dev/null") ~= 0 then - os.execute(IPTABLES .. " -I input_lqm -p udp --destination-port 698 --in-interface " .. track.device .. " -j DROP 2> /dev/null") + if not nft_handle("input_lqm", "iifname \\\"" .. trace.device .. "\\\" udp dport 698 .* drop") then + os.execute(NFT .. " insert rule ip fw4 input_lqm iifname \\\"" .. track.device .. "\\\" udp dport 698 counter drop 2> /dev/null") return "blocked" end else - if os.execute(IPTABLES .. " -C input_lqm -p udp --destination-port 698 -m mac --mac-source " .. track.mac .. " -j DROP 2> /dev/null") ~= 0 then - os.execute(IPTABLES .. " -I input_lqm -p udp --destination-port 698 -m mac --mac-source " .. track.mac .. " -j DROP 2> /dev/null") + if not nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac:lower() .. " .* drop") then + os.execute(NFT .. " insert rule ip fw4 input_lqm udp dport 698 ether saddr " .. track.mac .. " counter drop 2> /dev/null") return "blocked" end end else track.blocked = false if track.type == "Tunnel" then - if os.execute(IPTABLES .. " -C input_lqm -p udp --destination-port 698 --in-interface " .. track.device .. " -j DROP 2> /dev/null") == 0 then - os.execute(IPTABLES .. " -D input_lqm -p udp --destination-port 698 --in-interface " .. track.device .. " -j DROP 2> /dev/null") - return "blocked" + local handle = nft_handle("input_lqm", "iifname \\\"" .. track.device .. "\\\" udp dport 698 .* drop") + if handle then + os.execute(NFT .. " delete rule ip fw4 input_lqm handle " .. handle) + return "unblocked" end else - if os.execute(IPTABLES .. " -C input_lqm -p udp --destination-port 698 -m mac --mac-source " .. track.mac .. " -j DROP 2> /dev/null") == 0 then - os.execute(IPTABLES .. " -D input_lqm -p udp --destination-port 698 -m mac --mac-source " .. track.mac .. " -j DROP 2> /dev/null") + local handle = nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac:lower() .. " .* drop") + if handle then + os.execute(NFT .. " delete rule ip fw4 input_lqm handle " .. handle) return "unblocked" end end @@ -148,8 +161,14 @@ end function force_remove_block(track) track.blocked = false - os.execute(IPTABLES .. " -D input_lqm -p udp --destination-port 698 -m mac --mac-source " .. track.mac .. " -j DROP 2> /dev/null") - os.execute(IPTABLES .. " -D input_lqm -p udp --destination-port 698 --in-interface " .. track.device .. " -j DROP 2> /dev/null") + local handle = nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac:lower() .. " .* drop") + if handle then + os.execute(NFT .. " delete rule ip fw4 input_lqm handle " .. handle) + end + handle = nft_handle("input_lqm", "iifname \\\"" .. track.device .. "\\\" udp dport 698 .* drop") + if handle then + os.execute(NFT .. " delete rule ip fw4 input_lqm handle " .. handle) + end end -- Distance in meters between two points @@ -179,7 +198,7 @@ do end end local phy = "phy" .. radioname:match("radio(%d+)") -local wlan = cursor:get("network", "wifi", "ifname") +local wlan = aredn.hardware.get_board_network_ifname("wifi") function lqm() @@ -192,14 +211,17 @@ function lqm() wait_for_ticks(math.max(1, 30 - nixio.sysinfo().uptime)) -- Create filters (cannot create during install as they disappear on reboot) - os.execute(IPTABLES .. " -F input_lqm 2> /dev/null") - os.execute(IPTABLES .. " -X input_lqm 2> /dev/null") - os.execute(IPTABLES .. " -N input_lqm 2> /dev/null") - os.execute(IPTABLES .. " -D INPUT -j input_lqm -m comment --comment 'block low quality links' 2> /dev/null") - os.execute(IPTABLES .. " -I INPUT -j input_lqm -m comment --comment 'block low quality links' 2> /dev/null") + os.execute(NFT .. " flush chain ip fw4 input_lqm 2> /dev/null") + os.execute(NFT .. " delete chain ip fw4 input_lqm 2> /dev/null") + os.execute(NFT .. " add chain ip fw4 input_lqm 2> /dev/null") + local handle = nft_handle("input", "jump input_lqm comment") + if handle then + os.execute(NFT .. " delete rule ip fw4 input handle " .. handle) + end + os.execute(NFT .. " insert rule ip fw4 input counter jump input_lqm comment \\\"block low quality links\\\"") -- We dont know any distances yet - os.execute(IW .. " " .. phy .. " set distance auto") + os.execute(IW .. " " .. phy .. " set distance auto > /dev/null 2>&1") -- Setup a first_run timeout if this is our first every run if cursor:get("aredn", "@lqm[0]", "first_run") == "0" then @@ -208,6 +230,7 @@ function lqm() first_run_timeout = first_run_timeout + nixio.sysinfo().uptime end + local noise = -95 local tracker = {} local dtdlinks = {} while true @@ -216,8 +239,10 @@ function lqm() local config = get_config() - local lat = tonumber(cursor:get("aredn", "@location[0]", "lat")) - local lon = tonumber(cursor:get("aredn", "@location[0]", "lon")) + local lat = cursor:get("aredn", "@location[0]", "lat") + local lon = cursor:get("aredn", "@location[0]", "lon") + lat = tonumber(lat) + lon = tonumber(lon) local arps = {} arptable( @@ -247,7 +272,10 @@ function lqm() ["tx failed:"] = "tx_fail" } local station = {} - local noise = iwinfo.nl80211.noise(wlan) or -95 + local cnoise = iwinfo.nl80211.noise(wlan) + if cnoise and cnoise < -70 then + noise = math.ceil(noise * 0.9 + cnoise * 0.1) + end for line in io.popen(IW .. " " .. wlan .. " station dump"):lines() do local mac = line:match("^Station ([0-9a-f:]+) ") @@ -463,7 +491,7 @@ function lqm() end end if track.type == "RF" then - if info.lqm and info.lqm.enabled then + if info.lqm and info.lqm.enabled and info.lqm.info.trackers then for _, rtrack in pairs(info.lqm.info.trackers) do if myhostname == rtrack.hostname and (not rtrack.type or rtrack.type == "RF") then @@ -776,14 +804,14 @@ function lqm() -- Update the wifi distance if distance > 0 then coverage = math.min(255, math.floor((distance * 2 * 0.0033) / 3)) -- airtime - os.execute(IW .. " " .. phy .. " set coverage " .. coverage) + os.execute(IW .. " " .. phy .. " set coverage " .. coverage .. " > /dev/null 2>&1") elseif alt_distance > 1 then coverage = math.min(255, math.floor((alt_distance * 2 * 0.0033) / 3)) - os.execute(IW .. " " .. phy .. " set coverage " .. coverage) + os.execute(IW .. " " .. phy .. " set coverage " .. coverage .. " > /dev/null 2>&1") elseif config.auto_distance > 0 then - os.execute(IW .. " " .. phy .. " set distance " .. config.auto_distance) + os.execute(IW .. " " .. phy .. " set distance " .. config.auto_distance .. " > /dev/null 2>&1") else - os.execute(IW .. " " .. phy .. " set distance auto") + os.execute(IW .. " " .. phy .. " set distance auto > /dev/null 2>&1") end -- Save this for the UI diff --git a/files/usr/local/bin/mgr/rssi_monitor_ath10k.lua b/files/usr/local/bin/mgr/rssi_monitor_ath10k.lua new file mode 100644 index 00000000..cf701149 --- /dev/null +++ b/files/usr/local/bin/mgr/rssi_monitor_ath10k.lua @@ -0,0 +1,89 @@ +--[[ + + Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks + Copyright (C) 2022 Tim Wilkinson + See Contributors file for additional contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + This program is distributed in the hope that 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, see . + + Additional Terms: + + Additional use restrictions exist on the AREDN(TM) trademark and logo. + See AREDNLicense.txt for more info. + + Attributions to the AREDN Project must be retained in the source code. + If importing this code into a new or existing project attribution + to the AREDN project must be added to the source code. + + You must not misrepresent the origin of the material contained within. + + Modified versions must be modified to attribute to the original source + and be marked in reasonable ways as differentiate it from the original + version + +--]] + +local wifiiface + +function rssi_monitor_10k() + if string.match(get_ifname("wifi"), "^eth.") then + exit_app() + else + wait_for_ticks(math.max(1, 120 - nixio.sysinfo().uptime)) + + wifiiface = get_ifname("wifi") + + -- ath10k only + local phy = iwinfo.nl80211.phyname(wifiiface) + if not nixio.fs.stat("/sys/kernel/debug/ieee80211/" .. phy .. "/ath10k") then + exit_app() + return + end + + while true + do + run_monitor_10k() + wait_for_ticks(60) -- 1 minute + end + end +end + +local logfile = "/tmp/rssi_ath10k.log" + +if not file_exists(logfile) then + io.open(logfile, "w+"):close() +end + +local last_station_count = 0 +local log = aredn.log.open(logfile, 16000) + +function run_monitor_10k() + + local station_count = 0 + local stations = iwinfo.nl80211.assoclist(wifiiface) + for mac, station in pairs(stations) + do + station_count = station_count + 1 + end + + if station_count == 0 and last_station_count ~= 0 then + -- reset + os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1") + wait_for_ticks(5) + log:write("No stations detected") + log:flush() + end + last_station_count = station_count +end + +return rssi_monitor_10k diff --git a/files/usr/local/bin/mgr/rssi_monitor.lua b/files/usr/local/bin/mgr/rssi_monitor_ath9k.lua similarity index 91% rename from files/usr/local/bin/mgr/rssi_monitor.lua rename to files/usr/local/bin/mgr/rssi_monitor_ath9k.lua index a874a7d0..ae505008 100644 --- a/files/usr/local/bin/mgr/rssi_monitor.lua +++ b/files/usr/local/bin/mgr/rssi_monitor_ath9k.lua @@ -34,14 +34,32 @@ --]] -function rssi_monitor() +local wifiiface +local phy +local multiple_ant = false + +function rssi_monitor_9k() if string.match(get_ifname("wifi"), "^eth.") then exit_app() else wait_for_ticks(math.max(1, 120 - nixio.sysinfo().uptime)) + + wifiiface = get_ifname("wifi") + phy = iwinfo.nl80211.phyname(wifiiface) + + -- Supports ath9k + if not nixio.fs.stat("/sys/kernel/debug/ieee80211/" .. phy .. "/ath9k") then + exit_app() + return + end + + if read_all("/sys/kernel/debug/ieee80211/" .. phy .. "/ath9k/tx_chainmask"):chomp() ~= "1" then + multiple_ant = true + end + while true do - run_monitor() + run_monitor_9k() wait_for_ticks(60) -- 1 minute end end @@ -57,21 +75,13 @@ if not file_exists(logfile) then io.open(logfile, "w+"):close() end -local multiple_ant = false local last_station_count = 0 - local log = aredn.log.open(logfile, 16000) -function run_monitor() +function run_monitor_9k() local now = nixio.sysinfo().uptime - local wifiiface = get_ifname("wifi") - - if read_all("/sys/kernel/debug/ieee80211/" .. iwinfo.nl80211.phyname(wifiiface) .. "/ath9k/tx_chainmask"):chomp() ~= "1" then - multiple_ant = true - end - -- load history local rssi_hist = {} for line in io.lines(datfile) do @@ -87,7 +97,7 @@ function run_monitor() end local ofdm_level = 0 - for i, line in ipairs(read_all("/sys/kernel/debug/ieee80211/" .. iwinfo.nl80211.phyname(wifiiface) .. "/ath9k/ani"):splitNewLine()) + for i, line in ipairs(read_all("/sys/kernel/debug/ieee80211/" .. phy .. "/ath9k/ani"):splitNewLine()) do ofdm_level = tonumber(string.match(line, "OFDM LEVEL: (.*)")) if ofdm_level then @@ -99,7 +109,7 @@ function run_monitor() -- avoid node going deaf while trying to obtain 'normal' statistics of neighbor strength -- in first few minutes after boot if now > 119 and now < 750 then - os.execute("/usr/sbin/iw " .. wifiiface .. " scan") + os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1") end local station_count = 0 @@ -157,7 +167,7 @@ function run_monitor() if amac then -- reset - os.execute("/usr/sbin/iw " .. wifiiface .. " scan") + os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1") wait_for_ticks(5) -- update time now = nixio.sysinfo().uptime @@ -193,7 +203,7 @@ function run_monitor() end elseif station_count == 0 and last_station_count ~= 0 then -- reset - os.execute("/usr/sbin/iw " .. wifiiface .. " scan") + os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1") wait_for_ticks(5) log:write("No stations detected") end @@ -253,4 +263,4 @@ function get_rssi(wifiiface) end end -return rssi_monitor +return rssi_monitor_9k diff --git a/files/usr/local/bin/mgr/snrlog.lua b/files/usr/local/bin/mgr/snrlog.lua index eef9ab72..d19ddc16 100644 --- a/files/usr/local/bin/mgr/snrlog.lua +++ b/files/usr/local/bin/mgr/snrlog.lua @@ -69,7 +69,7 @@ function run_snrlog() -- get radio noise floor local nf = iwinfo.nl80211.noise(wifiiface) - if not nf or nf < -101 or nf > -50 then + if not nf or nf < -110 or nf > -50 then nf = defnoise end diff --git a/files/usr/local/bin/node-setup b/files/usr/local/bin/node-setup index 5cd24887..ba776a89 100755 --- a/files/usr/local/bin/node-setup +++ b/files/usr/local/bin/node-setup @@ -81,7 +81,7 @@ if not (config == "mesh" and nixio.fs.access("/etc/config.mesh/_setup", "r")) th return -1 end -local lanintf = aredn.hardware.get_board().network.lan.ifname +local lanintf = aredn.hardware.get_board_network_ifname("lan") local node = aredn_info.get_nvram("node") local tactical = aredn_info.get_nvram("tactical") local mac2 = mac_to_ip(aredn.hardware.get_interface_mac(aredn.hardware.get_iface_name("wifi")), 0) @@ -90,7 +90,7 @@ local dtdmac = mac_to_ip(aredn.hardware.get_interface_mac(lanintf:match("^(%S+)" local deleteme = {} local cfg = { lan_intf = lanintf, - wan_intf = aredn.hardware.get_board().network.wan.ifname, + wan_intf = aredn.hardware.get_board_network_ifname("wan"), dtdlink_intf = aredn.hardware.get_bridge_iface_names('dtdlink') } @@ -112,7 +112,7 @@ do end if cfg.wifi_enable == "1" then - cfg.wifi_intf = aredn.hardware.get_board().network.wifi.ifname:match("^(%S+)") + cfg.wifi_intf = aredn.hardware.get_board_network_ifname("wifi"):match("^(%S+)") else cfg.wifi_intf = lanintf:match("^([^%.%s]+).*$") .. ".3975" end @@ -206,6 +206,17 @@ end -- basic configuration if do_basic then + + -- support wan vlan override + if not nixio.fs.stat("/etc/aredn_include/wan.network.user") then + local ports = "" + for _, port in ipairs(cfg.wan_intf:split(" ")) + do + ports = ports .. " list ports '" .. port .. "'\n" + end + write_all("/etc/aredn_include/wan.network.config", ports) + end + remove_all("/tmp/new_config") nixio.fs.mkdir("/tmp/new_config") diff --git a/files/usr/local/bin/olsrd-config b/files/usr/local/bin/olsrd-config index 14363d10..2db71b58 100755 --- a/files/usr/local/bin/olsrd-config +++ b/files/usr/local/bin/olsrd-config @@ -137,17 +137,19 @@ end -- add a name for the dtdlink and xlink interfaces if name then local dtdip = aredn.hardware.get_interface_ip4(aredn.hardware.get_iface_name("dtdlink")) - hosts[#hosts + 1] = { ip = dtdip, host = "dtdlink." .. name .. ".local.mesh" } - if nixio.fs.stat("/etc/config.mesh/xlink") then - local count = 0 - uci.cursor("/etc/config.mesh"):foreach("xlink", "interface", - function(section) - if section.ipaddr then - hosts[#hosts + 1] = { ip = section.ipaddr, host = "xlink" .. count .. "." .. name .. ".local.mesh" } - count = count + 1 + if dtdip then + hosts[#hosts + 1] = { ip = dtdip, host = "dtdlink." .. name .. ".local.mesh" } + if nixio.fs.stat("/etc/config.mesh/xlink") then + local count = 0 + uci.cursor("/etc/config.mesh"):foreach("xlink", "interface", + function(section) + if section.ipaddr then + hosts[#hosts + 1] = { ip = section.ipaddr, host = "xlink" .. count .. "." .. name .. ".local.mesh" } + count = count + 1 + end end - end - ) + ) + end end end @@ -273,7 +275,7 @@ print([[{]]) print([[ PlParam "sighup-pid-file" "/var/run/dnsmasq/dnsmasq.pid"]]) print([[ PlParam "interval" "30"]]) print([[ PlParam "timeout" "300"]]) -print([[ PlParam "name-change-script" "touch /tmp/namechange; cp /var/run/hosts_olsr /var/run/hosts_olsr.snapshot; mv -f /var/run/hosts_olsr.snapshot /var/run/hosts_olsr.stable"]]) +print([[ PlParam "name-change-script" "cp /var/run/hosts_olsr /var/run/hosts_olsr.snapshot; mv -f /var/run/hosts_olsr.snapshot /var/run/hosts_olsr.stable; touch /tmp/namechange /var/run/hosts_olsr.stable"]]) for _, name in ipairs(names) do print([[ PlParam "name" "]] .. name .. [["]]) @@ -290,6 +292,7 @@ print([[}]]) -- add the ACTIVE tunnel interfaces if #tunnels > 0 then + local tun_weight = tonumber(cursor:get("aredn", "@tunnel[0]", "weight")) local tuns = "" for _, tunnel in ipairs(tunnels) do @@ -299,7 +302,11 @@ if #tunnels > 0 then print([[Interface]] .. tuns) print([[{]]) print([[ Ip4Broadcast 255.255.255.255]]) - print([[ Mode "ether"]]) + if not tun_weight or tun_weight < 1 then + print([[ Mode "ether"]]) + elseif tun_weight > 1 then + print([[ LinkQualityMult default ]] .. (1 / tun_weight)) + end print([[}]]) end diff --git a/files/usr/local/bin/poe_passthrough b/files/usr/local/bin/poe_passthrough index a38b0932..d97dc7f8 100755 --- a/files/usr/local/bin/poe_passthrough +++ b/files/usr/local/bin/poe_passthrough @@ -34,24 +34,35 @@ LICENSE export newval=$1 -if [ -z "$newval" ]; then +if [ -z "${newval}" ]; then echo "Syntax: $0 1 - turns POE on" echo " $0 0 - turns POE off" exit 2 fi - -export pinnum=$(jsonfilter -e '@.gpioswitch.poe_passthrough.pin' < /etc/board.json) -if [ -z "$pinnum" ]; then - echo "There are NO PoE Passthrough ports defined for this device" - exit 1 -else - export pin="gpio${pinnum}" - if [ ! -d "/sys/class/gpio/${pin}" ]; then +pinnum=$(jsonfilter -e '@.gpioswitch.poe_passthrough.pin' < /etc/board.json) +if [ "${pinnum}" = "" ]; then + pinnum=$(jsonfilter -e '@.gpioswitch.poe_passtrough.pin' < /etc/board.json) +fi +if [ "${pinnum}" != "" ]; then + pin="/sys/class/gpio/gpio${pinnum}" + if [ ! -d "${pin}" ]; then echo "${pinnum}" > /sys/class/gpio/export fi - if [ -e "/sys/class/gpio/${pin}/direction" ]; then - echo "out" > /sys/class/gpio/${pin}/direction +else + pin=$(echo /sys/class/gpio/enable-poe:*) + if [ "${pin}" = "/sys/class/gpio/enable-poe:*" ]; then + echo "There are NO PoE Passthrough ports defined for this device" + exit 1 fi - echo "${newval}" > /sys/class/gpio/${pin}/value - exit 0 fi + +active_low=$(cat ${pin}/active_low 2> /dev/null) +if [ "${active_low}" = "1" ]; then + newval=$((1 - ${newval})) +fi + +if [ -e "${pin}/direction" ]; then + echo "out" > ${pin}/direction +fi +echo "${newval}" > ${pin}/value +exit 0 diff --git a/files/usr/local/bin/upgrade_prepare.sh b/files/usr/local/bin/upgrade_prepare.sh index 7220674f..e7eb1153 100755 --- a/files/usr/local/bin/upgrade_prepare.sh +++ b/files/usr/local/bin/upgrade_prepare.sh @@ -37,7 +37,7 @@ LICENSE # ServiceName[:ServiceDaemon] pairs. # If ServiceDaemon is omitted, we wont first kill the daemon # -SERVICES="dnsmasq:dnsmasq dropbear:dropbear urngd:urngd rpcd:rpcd telnet:telnetd manager:manager.lua log:logd" +SERVICES="dnsmasq:dnsmasq dropbear:dropbear urngd:urngd rpcd:rpcd telnet:telnetd manager:manager.lua log:logd wpad:hostapd" # # We unceremoniously kill services, and then stop them to prevent diff --git a/files/usr/local/bin/usb_passthrough b/files/usr/local/bin/usb_passthrough index 78802135..824e15b1 100755 --- a/files/usr/local/bin/usb_passthrough +++ b/files/usr/local/bin/usb_passthrough @@ -40,15 +40,27 @@ if [ -z "$newval" ]; then exit 2 fi -export pinnum=$(jsonfilter -e '@.gpioswitch.usb_power_switch.pin' < /etc/board.json) -if [ -z "$pinnum" ]; then - echo "There are NO controllable USB ports defined for this device" - exit 1 +pinnum=$(jsonfilter -e '@.gpioswitch.usb_power_switch.pin' < /etc/board.json) +if [ "${pinnum}" != "" ]; then + pin="/sys/class/gpio/gpio${pinnum}" + if [ ! -d "${pin}" ]; then + echo "${pinnum}" > /sys/class/gpio/export + fi else - export pin=$(echo "gpio${pinnum}") - if [ ! -d /sys/class/gpio/$pin ]; then - echo ${pinnum} > /sys/class/gpio/export - fi - echo ${newval} > /sys/class/gpio/${pin}/value - exit 0 + pin=$(echo /sys/class/gpio/usb-powe*) + if [ "${pin}" = "/sys/class/gpio/usb-powe*" ]; then + echo "There are NO controllable USB ports defined for this device" + exit 1 + fi fi + +active_low=$(cat ${pin}/active_low) +if [ "${active_low}" = "1" ]; then + newval=$((1 - ${newval})) +fi + +if [ -e "${pin}/direction" ]; then + echo "out" > ${pin}/direction +fi +echo "${newval}" > ${pin}/value +exit 0 diff --git a/files/usr/local/bin/wifi-setup b/files/usr/local/bin/wifi-setup index d4b009a3..c371b650 100755 --- a/files/usr/local/bin/wifi-setup +++ b/files/usr/local/bin/wifi-setup @@ -52,9 +52,20 @@ done < $configfile # get mesh RF dev master setting in /etc/config/network -meshif="$(uci -q get network.wifi.ifname)" +meshif="$(uci -q get network.@device[2].name)" meshphy="phy${meshif#wlan}" +# Configure WAN interface, which may be wireless or Ethernet +if [ $wifi3_enable -eq 1 ]; then + # switch WAN network config from Ethernet to Wireless interface + for i in `cat /etc/aredn_include/wan.network.config | cut -f3 -d' ' | sed -e "s/'//g"`; do + uci -q del_list network.@device[1].ports=$i + done + uci -q delete network.@device[1].type + # adding the wireless interface done later-below + uci -q commit network +fi + rm -f "${dropdir}/wireless" touch "${dropdir}/wireless" @@ -110,7 +121,7 @@ for _dev in /sys/class/ieee80211/*; do encryption="none" key="" network="wifi" - elif [[ $wifi2_enable -eq 1 -a \( $ifacecount -eq 1 -o \( \( $ifacecount -gt 1 \) -a \( "$hwmode" = "$wifi2_hwmode" \) \) \) ]]; then + elif [ $wifi2_enable -eq 1 -a \( $ifacecount -eq 1 -o \( \( $ifacecount -gt 1 \) -a \( "$hwmode" = "$wifi2_hwmode" \) \) \) ]; then # LAN AP interface channel="${wifi2_channel}" ssid=$(echo "${wifi2_ssid}" | sed -e 's/\(..\)/\\x\1/g') @@ -122,7 +133,7 @@ for _dev in /sys/class/ieee80211/*; do key=$(echo -e "${key}") key=${key//\"/\\\"} network="lan" - elif [[ $wifi3_enable -eq 1 -a \( $ifacecount -eq 1 -o \( \( $ifacecount -gt 1 \) -a \( "$hwmode" = "$wifi3_hwmode" \) \) \) ]]; then + elif [ $wifi3_enable -eq 1 -a \( $ifacecount -eq 1 -o \( \( $ifacecount -gt 1 \) -a \( "$hwmode" = "$wifi3_hwmode" \) \) \) ]; then # WAN Client disabled="0" channel="" @@ -142,7 +153,8 @@ for _dev in /sys/class/ieee80211/*; do network="wan" htmode="" uci -c ${dropdir} -q batch > /dev/null <<-EOF -set network.wan.ifname=$wlan +set network.@device[1].name=$wlan +set network.wan.device=$wlan EOF uci -c ${dropdir} -q commit network else @@ -162,11 +174,12 @@ EOF set wireless.${radio}.htmode=${htmode} ${dev_id} add wireless wifi-iface - set wireless.@wifi-iface[${ifacenum}].device=${radio} - set wireless.@wifi-iface[${ifacenum}].network=${network} - set wireless.@wifi-iface[${ifacenum}].mode=${mode} - set wireless.@wifi-iface[${ifacenum}].ssid="${ssid}" - set wireless.@wifi-iface[${ifacenum}].encryption=${encryption} + set wireless.@wifi-iface[${ifacenum}].ifname=${wlan} + set wireless.@wifi-iface[${ifacenum}].device=${radio} + set wireless.@wifi-iface[${ifacenum}].network=${network} + set wireless.@wifi-iface[${ifacenum}].mode=${mode} + set wireless.@wifi-iface[${ifacenum}].ssid="${ssid}" + set wireless.@wifi-iface[${ifacenum}].encryption=${encryption} set wireless.@wifi-iface[${ifacenum}].key="${key}" EOF uci -c ${dropdir} -q commit wireless @@ -176,6 +189,7 @@ EOF ifacenum=$((ifacenum + 1)) uci -c ${dropdir} -q batch > /dev/null <<-EOF add wireless wifi-iface + set wireless.@wifi-iface[${ifacenum}].ifname=${wlan}-1 set wireless.@wifi-iface[${ifacenum}].device=${radio} set wireless.@wifi-iface[${ifacenum}].network=wifi_mon set wireless.@wifi-iface[${ifacenum}].mode=monitor diff --git a/files/www/aredn.css b/files/www/aredn.css index c64e7aab..5ed197d0 100644 --- a/files/www/aredn.css +++ b/files/www/aredn.css @@ -1,7 +1,7 @@ body { font-family:Verdana,arial,sans-serif; background:rgb(231,231,231); color:black } -a:link { background:rgb(231,231,231); color:rgb(190,30,44) } -a:visited { background:rgb(231,231,231); color:rgb(190,30,44) } -a:active { background:rgb(231,231,231); color:rgb(190,30,44) } +a:link { background:transparent; color:rgb(190,30,44) } +a:visited { background:transparent; color:rgb(190,30,44) } +a:active { background:transparent; color:rgb(190,30,44) } h1 { font-family:Verdana,arial,sans-serif; color:rgb(190,30,44); text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black } hr { @@ -31,7 +31,7 @@ body table { .navbar_select a:active { background:black; color:white } .TopBanner { width:100%; } -.LogoDiv { position:absolute left:0px; width:100%; height:95; } +.LogoDiv { left:0px; width:100%; height:95; } .AREDNLogo { background:rgb(231,231,231); position:absolute; left:10%; width:175; height:95; border-style: none;} .PartOfAREDN { font-family:Verdana,arial,sans-serif; font-size:xx-small; text-align:center; } diff --git a/files/www/black_on_white.css b/files/www/black_on_white.css index 1d21eddf..9f31fda2 100644 --- a/files/www/black_on_white.css +++ b/files/www/black_on_white.css @@ -29,7 +29,7 @@ body table { .navbar_select a:active { background:white; color:black } .TopBanner { width:100%; } -.LogoDiv { position:absolute left:0px; width:100%; height:95; } +.LogoDiv { left:0px; width:100%; height:95; } .AREDNLogo { background: white; position:absolute; left:10%; width:175; height:95; } .PartOfAREDN { font-family:Verdana,arial,sans-serif; font-size:xx-small; text-align:center; } diff --git a/files/www/cgi-bin/admin b/files/www/cgi-bin/admin index 4aeb0468..ea644e58 100755 --- a/files/www/cgi-bin/admin +++ b/files/www/cgi-bin/admin @@ -43,7 +43,6 @@ aredn.html = require("aredn.html") require("uci") aredn.info = require("aredn.info") require("ubus") -require("luci.sys") local html = aredn.html @@ -160,7 +159,7 @@ function reboot() end html.print("") http_footer() - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") os.exit() end @@ -191,7 +190,7 @@ local parms = {} local firmfile = "" if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -201,30 +200,28 @@ if os.getenv("REQUEST_METHOD") == "POST" then end ) -- only allow file uploading without active tunnels - if not active_tunnel then - local fp - request:setfilehandler( - function(meta, chunk, eof) - if not fp then - if meta and meta.file then - firmfile = meta.file - if firmfile:match("sysupgrade%.bin$") then - -- Uploading a system upgrade - clear out memory early - os.execute("/usr/local/bin/upgrade_prepare.sh > /dev/null 2>&1") - end + local fp + request:setfilehandler( + function(meta, chunk, eof) + if not fp then + if meta and meta.file then + firmfile = meta.file + if firmfile:match("sysupgrade%.bin$") then + -- Uploading a system upgrade - clear out memory early + os.execute("/usr/local/bin/upgrade_prepare.sh > /dev/null 2>&1") end - nixio.fs.mkdir("/tmp/web/upload") - fp = io.open("/tmp/web/upload/file", "w") - end - if chunk then - fp:write(chunk) - end - if eof then - fp:close() - end + end + nixio.fs.mkdir("/tmp/web/upload") + fp = io.open("/tmp/web/upload/file", "w") end - ) - end + if chunk then + fp:write(chunk) + end + if eof then + fp:close() + end + end + ) parms = request:formvalue() end @@ -289,6 +286,8 @@ elseif mfgprefix == "cpe" then hardwaretypev = "510-v3" -- v3.0 elseif hwmodel:match("CPE510") then hardwaretypev = "510-520-v1" -- CPE510 V1.0/v1.1 + elseif hwmodel:match("CPE605") then + hardwaretypev = "605-v1" -- CPE605 V1.0 elseif hwmodel:match("CPE610 v2%.0") then hardwaretypev = "610-v2" -- CPE610 V2.0 elseif hwmodel:match("CPE610") then @@ -460,7 +459,7 @@ if fw_install and nixio.fs.stat(tmpdir .. "/firmware") then html.print("") - html.print("") + html.print("") html.print("") html.print("
") html.print("

The firmware is being updated.

") @@ -491,7 +490,7 @@ if fw_install and nixio.fs.stat(tmpdir .. "/firmware") then html.print("") http_footer() aredn.info.set_nvram("nodeupgraded", "0") - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") else html.print([[

Firmware will be written in the background.

@@ -501,12 +500,12 @@ if fw_install and nixio.fs.stat(tmpdir .. "/firmware") then When the node has finished booting you should ensure your computer has
received a new IP address and reconnect with
http://]] .. node .. [[.local.mesh:8080/
- (This page will automatically reload in 3 minutes) + (This page will automatically reload in 5 minutes)
]]) http_footer() nixio.fs.remove("/tmp/sysupgradefilelist") - upgradecmd = "/sbin/sysupgrade -f /tmp/arednsysupgradebackup.tgz -q " .. tmpdir .. "/firmware 2>&1 &" + upgradecmd = "/usr/local/bin/aredn_sysupgrade -f /tmp/arednsysupgradebackup.tgz -q " .. tmpdir .. "/firmware 2>&1 &" end else fin:close() @@ -520,7 +519,7 @@ if fw_install and nixio.fs.stat(tmpdir .. "/firmware") then html.footer() html.print("") http_footer() - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") end else html.print([[ @@ -532,11 +531,11 @@ if fw_install and nixio.fs.stat(tmpdir .. "/firmware") then received a new IP address and reconnect with
http://192.168.1.1:8080/
and continue setup of the node in firstboot state.
- (This page will automatically reload in 3 minutes) + (This page will automatically reload in 5 minutes)
]]) http_footer() - upgradecmd = "/sbin/sysupgrade -q -n " .. tmpdir .. "/firmware 2>&1 &" + upgradecmd = "/usr/local/bin/aredn_sysupgrade -q -n " .. tmpdir .. "/firmware 2>&1 &" end if upgradecmd then os.execute(upgradecmd) diff --git a/files/www/cgi-bin/advancedconfig b/files/www/cgi-bin/advancedconfig index d8672445..96196927 100755 --- a/files/www/cgi-bin/advancedconfig +++ b/files/www/cgi-bin/advancedconfig @@ -42,7 +42,6 @@ require("aredn.utils") aredn.html = require("aredn.html") require("uci") aredn.info = require("aredn.info") -require("luci.sys") local html = aredn.html @@ -63,8 +62,8 @@ function defaultPackageRepos(repo) target = m end end - if release:match("%.") then - local a, b = release:match("^(%d+)%.(%d+)%.") + local a, b = release:match("^(%d+)%.(%d+)%.") + if a and b then urlprefix = urlprefix .. "/releases/" .. a .. "/" .. b .. "/" .. release else -- nightly @@ -471,7 +470,7 @@ function reboot() end html.print("") http_footer() - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") os.exit() end @@ -614,12 +613,12 @@ end function currentWANVLAN() for line in io.lines("/etc/config.mesh/_setup") do - local vlan = line:match("^wan_intf = %w+%d+%.(%d+)") + local vlan = line:match("^wan_intf = %w+%.(%d+)") if vlan then return vlan end end - local vlan = aredn.hardware.get_board().network.wan.ifname:match("^%w+%.(%d+)") + local vlan = aredn.hardware.get_board_network_ifname("wan"):match("^%w+%.(%d+)") if vlan then return vlan end @@ -636,7 +635,7 @@ function changeWANVLAN() end if newval ~= "" then local wan_intf = "" - for dev in aredn.hardware.get_board().network.wan.ifname:gmatch("%S+") + for dev in aredn.hardware.get_board_network_ifname("wan"):gmatch("%S+") do wan_intf = wan_intf .. " " .. dev:match("^([^%.]+)") .. "." .. newval end @@ -663,7 +662,7 @@ end local parms = {} if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then diff --git a/files/www/cgi-bin/fwinfo b/files/www/cgi-bin/fwinfo index d60e275f..13013a33 100755 --- a/files/www/cgi-bin/fwinfo +++ b/files/www/cgi-bin/fwinfo @@ -49,5 +49,5 @@ else end print("Active firewall rules:") -print(capture("/usr/sbin/iptables -L")) +print(capture("nft list ruleset")) diff --git a/files/www/cgi-bin/iperf b/files/www/cgi-bin/iperf index b17ea7ed..5fe7b8ce 100755 --- a/files/www/cgi-bin/iperf +++ b/files/www/cgi-bin/iperf @@ -35,7 +35,6 @@ --]] require("uci") -require("luci.sys") require("nixio") local info = require("aredn.info") @@ -69,6 +68,6 @@ else if not server:match("%.") then server = server .. ".local.mesh" end - luci.sys.httpget("http://" .. server .. ":8080/cgi-bin/iperf?server=") + os.execute("wget -q 'http://" .. server .. ":8080/cgi-bin/iperf?server=' > /dev/null 2>&1") print("iperf
" .. io.popen("/usr/bin/iperf3 -b 0 -c " .. server .. (protocol == "udp" and " -u" or "") .. " 2>&1"):read("*a") .. "
") end diff --git a/files/www/cgi-bin/mesh b/files/www/cgi-bin/mesh index 73e2231b..26aaf267 100755 --- a/files/www/cgi-bin/mesh +++ b/files/www/cgi-bin/mesh @@ -67,7 +67,8 @@ local rateL = { MCS12 = 78, MCS13 = 104, MCS14 = 117, - MCS15 = 130 + MCS15 = 130, + ["54.0M"] = 54 } local rateS = { MCS0 = 7.2, @@ -129,8 +130,7 @@ end if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - require('luci.sys') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -217,6 +217,7 @@ arptable(function(a) arpcache[a["IP address"]] = a end) +local iwrates local prefix = "/sys/kernel/debug/ieee80211/" .. phy .. "/netdev:" .. wifiif .. "/stations/" for i, node in ipairs(aredn.olsr.getOLSRLinks()) do @@ -233,9 +234,9 @@ do if gi and ewma then -- 802.11b/n if gi == "SGI" then - links[node.remoteIP].mbps = string.format("%.1f", rateS[rate] * ewma / 100 / chanbw) + links[node.remoteIP].mbps = string.format("%.1f", (rateS[rate] or 0) * ewma / 100 / chanbw) else - links[node.remoteIP].mbps = string.format("%.1f", rateL[rate] * ewma / 100 / chanbw) + links[node.remoteIP].mbps = string.format("%.1f", (rateL[rate] or 0) * ewma / 100 / chanbw) end else rate, ewma = line:match("^A[^,]*,([^,]*),[^,]*,[^,]*,([^,]*,)") @@ -248,6 +249,27 @@ do end end f:close() + else -- fallback (rates without error accounting) + if not iwrates then + iwrates = {} + local station = {} + for line in io.popen("iw " .. wifiif .. " station dump"):lines() + do + local mac = line:match("^Station (%S+) ") + if mac then + station = {} + iwrates[mac] = station + end + local txbitrate = line:match("tx bitrate:%s+([%d%.]+) MBit/s") + if txbitrate then + station.txbitrate = txbitrate + end + end + end + local station = iwrates[mac["HW address"]] + if station then + links[node.remoteIP].mbps = string.format("%.1f", station.txbitrate) + end end end end @@ -499,7 +521,7 @@ html.print("Help    if nixio.fs.stat("/tmp/web/automesh") then html.print("") else - html.print("") + html.print("") html.print("  ") html.print("") end diff --git a/files/www/cgi-bin/ports b/files/www/cgi-bin/ports index 77e90e0c..ebadcd8e 100755 --- a/files/www/cgi-bin/ports +++ b/files/www/cgi-bin/ports @@ -42,7 +42,6 @@ require("aredn.utils") aredn.html = require("aredn.html") require("uci") aredn.info = require("aredn.info") -require("luci.sys") local html = aredn.html @@ -62,7 +61,7 @@ end local parms = {} if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -833,13 +832,12 @@ if parms.button_save and not (#port_err > 0 or #dhcp_err > 0 or #dmz_err > 0 or if os.execute("/usr/local/bin/node-setup -a -p mesh") ~= 0 then err("problem with configuration") end - if not luci.sys.init.reload("dnsmasq") then + if os.execute("/etc/init.d/dnsmasq restart") ~= 0 then err("problem with dnsmasq") end - if not luci.sys.init.reload("firewall") then + if os.execute("/etc/init.d/firewall restart") ~= 0 then err("problem with port setup") end - -- This "luci.sys.init.restart("olsrd")" doesnt do the same thing so we have to call restart directly if os.execute("/etc/init.d/olsrd restart") ~= 0 then err("problem with olsr setup") end @@ -863,7 +861,7 @@ html.print([[         -  +   ]]) hide("") diff --git a/files/www/cgi-bin/scan b/files/www/cgi-bin/scan index d13e4a90..729d45ce 100755 --- a/files/www/cgi-bin/scan +++ b/files/www/cgi-bin/scan @@ -128,8 +128,7 @@ end if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - require('luci.sys') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -177,7 +176,7 @@ html.print("

" .. node .. " WiFi scan


") if autoscan then html.print("") else - html.print("") + html.print("") html.print("   ") html.print("") end diff --git a/files/www/cgi-bin/setup b/files/www/cgi-bin/setup index 4e5e587a..0ad540a2 100755 --- a/files/www/cgi-bin/setup +++ b/files/www/cgi-bin/setup @@ -42,7 +42,6 @@ require("aredn.utils") require("aredn.hardware") require("uci") require('luci.http') -require('luci.sys') local html = require("aredn.html") local aredn_info = require("aredn.info") @@ -55,42 +54,6 @@ local cursor = uci.cursor() -- helpers start -local rf_channel_map = { - ["900"] = {}, - ["2400"] = {}, - ["3400"] = {}, - ["5500"] = {}, - ["5800ubntus"] = {} -} -for i = 4,7 -do - rf_channel_map["900"][i - 3] = { label = i .. " (" .. (887 + i * 5) .. ")", number = i, frequency = 887 + i * 5 } -end -for i = -4,11 -do - rf_channel_map["2400"][i + (i <= 0 and 5 or 4)] = { label = i .. " (" .. (2407 + i * 5) .. ")", number = i, frequency = 2407 + i * 5 } -end -for i = 76,99 -do - rf_channel_map["3400"][i - 75] = { label = i .. " (" .. (3000 + i * 5) .. ")", number = i, frequency = 3000 + i * 5 } -end -for i = 36,64,4 -do - rf_channel_map["5500"][(i - 32) / 4] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } -end -for i = 100,140,4 -do - rf_channel_map["5500"][(i - 64) / 4] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } -end -for i = 149,165,4 -do - rf_channel_map["5500"][(i - 69) / 4] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } -end -for i = 131,184 -do - rf_channel_map["5800ubntus"][i - 130] = { label = i .. " (" .. (5000 + i * 5) .. ")", number = i, frequency = 5000 + i * 5 } -end - function capture_and_match(cmd, pattern) local f = io.popen(cmd) if f then @@ -106,33 +69,6 @@ function capture_and_match(cmd, pattern) end end -function rf_channels_list(wifiintf) - local channels = {} - local rfband = aredn.hardware.get_rfband() - if rfband and rf_channel_map[rfband] then - return rf_channel_map[rfband] - else - local f = io.popen("iwinfo " .. wifiintf .. " freqlist") - if f then - for line in f:lines() - do - local freq, num = line:match("(%d+%.%d+) GHz %(Channel (%d+)%)") - if freq and not line:match("restricted") then - freq = freq:gsub("%.", "") - num = num:gsub("^0+", "") - channels[#channels + 1] = { - label = num .. " (" .. freq .. ")", - number = tonumber(num), - frequency = freq - } - end - end - f:close() - end - end - return channels -end - function reboot() local node = aredn_info.get_nvram("node") if node == "" then @@ -181,7 +117,7 @@ function reboot() end html.print("") http_footer() - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") os.exit() end @@ -194,7 +130,7 @@ function out(str) end function is_channel_valid(channel) - local list = rf_channels_list(aredn.hardware.get_iface_name("wifi")) + local list = aredn.hardware.get_rfchannels(aredn.hardware.get_iface_name("wifi")) for _, c in ipairs(list) do if c.number == channel then @@ -265,7 +201,7 @@ local phycount = tonumber(capture("ls -1d /sys/class/ieee80211/* | wc -l"):chomp local parms = {} local has_parms = false if os.getenv("REQUEST_METHOD") == "POST" then - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -803,7 +739,7 @@ if parms.button_save then if f then for k, v in pairs(parms) do - if k:match("^aprs_") or k:match("^dhcp_") or k:match("^dmz_") or k:match("^lan_") or k:match("^olsrd_") or k:match("^wan_") or k:match("^wifi_") or k:match("^wifi2_") or k:match("^wifi3_") or k:match("^dtdlink_") or k:match("^ntp_") or k:match("^time_") or k:match("^description_") then + if k:match("^aprs_") or k:match("^dhcp_") or k:match("^dmz_") or k:match("^lan_") or k:match("^olsrd_") or k:match("^wan_") or k:match("^wifi_") or k:match("^wifi2_") or k:match("^wifi3_") or k:match("^dtdlink_") or k:match("^ntp_") or k:match("^time_") or k:match("^description_") or k:match("^compat_version") then f:write(k .. " = " .. v .. "\n") end end @@ -1102,6 +1038,7 @@ html.print([[ ]]) hidden[#hidden + 1] = "" +hidden[#hidden + 1] = "" html.print([[ Verify Password @@ -1114,11 +1051,7 @@ html.print([[ -- mesh rf settings html.print("") -if phycount > 1 then - html.print("") -else - html.print("") -end +html.print("") hidden[#hidden + 1] = "" -- add enable/disable @@ -1141,7 +1074,7 @@ if wifi_enable == "1" then html.print("") hidden[#hidden + 1] = "" html.print("") html.print("") hidden[#hidden + 1] = "" @@ -1274,8 +1208,9 @@ end html.print("") +local APokay = nixio.fs.stat("/usr/sbin/wpad") local M39model = aredn.hardware.get_board_id():match("M[39]") -if (phycount > 1 and (wifi_enable ~= "1" or wifi3_enable ~= "1")) or (phycount == 1 and wifi_enable ~= "1" and wifi3_enable ~= "1") and not M39model then +if APokay and ((phycount > 1 and (wifi_enable ~= "1" or wifi3_enable ~= "1")) or (phycount == 1 and wifi_enable ~= "1" and wifi3_enable ~= "1") and not M39model) then -- lan ap shows as an option -- determine hardware options and set band ahd channels accordingly if phycount == 1 then @@ -1379,7 +1314,7 @@ html.print("") -- wan wifi client -if (phycount > 1 and (wifi_enable ~= "1" or wifi2_enable ~= "1")) or (phycount == 1 and wifi_enable ~= "1" and wifi2_enable ~= "1") and not M39model then +if APokay and ((phycount > 1 and (wifi_enable ~= "1" or wifi2_enable ~= "1")) or (phycount == 1 and wifi_enable ~= "1" and wifi2_enable ~= "1")) and not M39model then -- wifi client shows as an option -- determine hardware options and set band accordingly diff --git a/files/www/cgi-bin/status b/files/www/cgi-bin/status index d6dd5de5..98ec28f1 100755 --- a/files/www/cgi-bin/status +++ b/files/www/cgi-bin/status @@ -179,11 +179,12 @@ local wifi_channel local wifi_chanbw local wifi_ssid if not wifi_disabled then - wifi_channel = tonumber(cursor:get("wireless", radio, "channel")) + wifi_channel = cursor:get("wireless", radio, "channel") + wifi_channel = tonumber(wifi_channel) or 0 if wifi_channel >= 76 and wifi_channel <= 99 then wifi_channel = wifi_channel * 5 + 3000 end - wifi_chanbw = cursor:get("wireless", radio, "chanbw") + wifi_chanbw = cursor:get("wireless", radio, "chanbw") or "20" wifi_ssid = "none" cursor:foreach("wireless", "wifi-iface", function (section) @@ -222,8 +223,7 @@ end if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - require('luci.sys') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -265,7 +265,7 @@ html.print("
") html.print("") html.print("Help") html.print("  ") -html.print("") +html.print("") if config == "mesh" then html.print("  ") html.print("") @@ -290,8 +290,20 @@ html.print("") if config == "not set" then html.print("

This node is not yet configured.
") - html.print("Go to the setup page and set your node name and password.
") - html.print("Click Save Changes, even if you didn't make any changes, then the node will reboot.
") + local overlay = false + for line in io.lines("/proc/mounts") + do + if line:match("overlay") then + overlay = true + break + end + end + if overlay then + html.print("Go to the setup page and set your node name and password.
") + html.print("Click Save Changes, even if you didn't make any changes, then the node will reboot.") + else + html.print("Go the the administration page and upload new firmware.
") + end html.print("

") html.print("
") html.print("

This device can be configured to either permit or prohibit known encrypted traffic on its RF link. It is up to the user to decide which is appropriate based on how it will be used and the license under which it will be operated. These rules vary by country, frequency, and intended use. You are encouraged to read and understand these rules before going further.

") diff --git a/files/www/cgi-bin/supporttool b/files/www/cgi-bin/supporttool index b74846b4..b0f9c3a3 100755 --- a/files/www/cgi-bin/supporttool +++ b/files/www/cgi-bin/supporttool @@ -41,7 +41,7 @@ require("uci") require("iwinfo") -local wifiif = uci.cursor():get("network", "wifi", "ifname") +local wifiif = uci.cursor():get("network", "wifi", "device") local phy = iwinfo.nl80211.phyname(wifiif) local mfg = capture("/usr/local/bin/get_hardware_mfg"):chomp() @@ -51,13 +51,14 @@ local files = { "/etc/config.mesh/", "/etc/local/", "/etc/mesh-release", + "/etc/os-release", "/tmp/etc/", "/var/run/hosts_olsr", "/var/run/hosts_olsr.stable", "/var/run/services_olsr", "/tmp/rssi.dat", "/tmp/rssi.log", - "/tmp/zombie.log", + "/tmp/rssi_ath10k.log", "/tmp/olsrd.log", "/tmp/manager.log", "/tmp/manager.log.0", @@ -78,9 +79,11 @@ local cmds = { "df -k", "dmesg", "ifconfig", - "iptables -t filter -L -v", - "iptables -t nat -L -v", - "iptables -t mangle -L -v", + "ethtool eth0", + "ethtool eth1", + "ip link", + "ip addr", + "ip neigh", "ip route list", "ip route list table 29", "ip route list table 30", @@ -95,7 +98,7 @@ local cmds = { "iw dev " .. wifiif .. " info", "iw dev " .. wifiif .. " scan", "iw dev " .. wifiif .. " station dump", - "logread", + "nft list ruleset", "md5sum /www/cgi-bin/*", "echo /all | nc 127.0.0.1 2006", "opkg list-installed", @@ -104,6 +107,7 @@ local cmds = { "/usr/local/bin/get_boardid", "/usr/local/bin/get_model", "/usr/local/bin/get_hardware_mfg", + "logread", } local cmds_ubnt = { "cat /dev/mtd0|grep 'U-Boot'|head -n1" @@ -148,28 +152,26 @@ os.execute("sed -i -e 's/_key =.*$/_key =/' /tmp/sd/etc/config.mesh/_setup") local f = io.open("/tmp/sd/data.txt", "w") if f then - for _, cmd in ipairs(cmds) - do - local p = io.popen(cmd) - if p then - f:write("========== " .. cmd .. " ==========\n") - f:write(p:read("*a")) - p:close() - end - end - if mfg == "Ubiquiti" then for _, cmd in ipairs(cmds_ubnt) do local p = io.popen(cmd) if p then - f:write("========== " .. cmd .. " (UBNT only) ==========\n") + f:write("\n========== " .. cmd .. " (UBNT only) ==========\n") f:write(p:read("*a")) p:close() end end end - + for _, cmd in ipairs(cmds) + do + local p = io.popen(cmd) + if p then + f:write("\n========== " .. cmd .. " ==========\n") + f:write(p:read("*a")) + p:close() + end + end f:close() end diff --git a/files/www/cgi-bin/vpn b/files/www/cgi-bin/vpn index 0e2aa367..09fc3862 100755 --- a/files/www/cgi-bin/vpn +++ b/files/www/cgi-bin/vpn @@ -42,7 +42,6 @@ require("aredn.html") require("aredn.hardware") aredn.info = require("aredn.info") require("uci") -require("luci.sys") local html = aredn.html @@ -59,7 +58,7 @@ local VPNVER = "1.1" local parms = {} if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -168,7 +167,7 @@ function get_client_info() end if parms.button_reboot then - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") os.exit() end @@ -391,12 +390,18 @@ html.print("Help") html.print("   ") html.print(" ") html.print(" ") -html.print(" ") +html.print(" ") html.print("
") hide("") +-- unsupported tunnels +local notunnels = not nixio.fs.stat("/usr/sbin/vtund") +if notunnels then + html.print("") + config = "notunnels" + cli_err = {} -- low memory warning -if isLowMemNode() then +elseif isLowMemNode() then html.print("") end diff --git a/files/www/cgi-bin/vpnc b/files/www/cgi-bin/vpnc index 2fd91898..116fb99b 100755 --- a/files/www/cgi-bin/vpnc +++ b/files/www/cgi-bin/vpnc @@ -42,7 +42,6 @@ require("aredn.html") require("aredn.hardware") aredn.info = require("aredn.info") require("uci") -require("luci.sys") local html = aredn.html @@ -63,7 +62,7 @@ local VPNVER = "1.0" local parms = {} if os.getenv("REQUEST_METHOD") == "POST" then require('luci.http') - local request = luci.http.Request(luci.sys.getenv(), + local request = luci.http.Request(nixio.getenv(), function() local v = io.read(1024) if not v then @@ -152,7 +151,7 @@ function get_connection_info() end if parms.button_reboot then - luci.sys.reboot() + os.execute("reboot >/dev/null 2>&1") os.exit() end @@ -367,12 +366,16 @@ html.print("Help") html.print("   ") html.print(" ") html.print(" ") -html.print(" ") +html.print(" ") html.print("") hide("") +local notunnels = not nixio.fs.stat("/usr/sbin/vtund") +if notunnels then + html.print("") + config = "notunnels" -- low memory warning -if isLowMemNode() then +elseif isLowMemNode() then html.print("") end diff --git a/files/www/red_on_black.css b/files/www/red_on_black.css index 75c66b7f..65ef1b33 100644 --- a/files/www/red_on_black.css +++ b/files/www/red_on_black.css @@ -29,7 +29,7 @@ body table { .navbar_select a:active { background:black; color:red } .TopBanner { width:100%; } -.LogoDiv { position:absolute left:0px; width:100%; height:95; } +.LogoDiv { left:0px; width:100%; height:95; } .AREDNLogo { background: white; position:absolute; left:10%; width:175; height:95; } .PartOfAREDN { font-family:Verdana,arial,sans-serif; font-size:xx-small; text-align:center; } diff --git a/files/www/white_on_black.css b/files/www/white_on_black.css index 1549f9f3..86cf9243 100644 --- a/files/www/white_on_black.css +++ b/files/www/white_on_black.css @@ -29,7 +29,7 @@ body table { .navbar_select a:active { background:black; color:white } .TopBanner { width:100%; } -.LogoDiv { position:absolute left:0px; width:100%; height:95; } +.LogoDiv { left:0px; width:100%; height:95; } .AREDNLogo { background: white; position:absolute; left:10%; width:175; height:95; } .PartOfAREDN { font-family:Verdana,arial,sans-serif; font-size:xx-small; text-align:center; } diff --git a/files/www/yellow_on_black.css b/files/www/yellow_on_black.css index 8d13c317..ef36878f 100644 --- a/files/www/yellow_on_black.css +++ b/files/www/yellow_on_black.css @@ -29,7 +29,7 @@ body table { .navbar_select a:active { background:black; color:yellow } .TopBanner { width:100%; } -.LogoDiv { position:absolute left:0px; width:100%; height:95; } +.LogoDiv { left:0px; width:100%; height:95; } .AREDNLogo { background: white; position:absolute; left:10%; width:175; height:95; } .PartOfAREDN { font-family:Verdana,arial,sans-serif; font-size:xx-small; text-align:center; } diff --git a/openwrt.mk b/openwrt.mk index b168732a..6ca77b6d 100644 --- a/openwrt.mk +++ b/openwrt.mk @@ -2,5 +2,5 @@ OPENWRT_SRC=https://github.com/openwrt/openwrt.git # what branch, tag or commit in this repo? -OPENWRT_COMMIT=v19.07.10 +OPENWRT_COMMIT=v22.03.2 diff --git a/patches/0001-ath79-add-support-for-TP-Link-CPE605-v1.patch b/patches/0001-ath79-add-support-for-TP-Link-CPE605-v1.patch new file mode 100644 index 00000000..c100db61 --- /dev/null +++ b/patches/0001-ath79-add-support-for-TP-Link-CPE605-v1.patch @@ -0,0 +1,189 @@ +From d51e261e893451f9d0958a5ac39989d10b275e86 Mon Sep 17 00:00:00 2001 +From: Andrew Cameron +Date: Sun, 6 Nov 2022 14:43:37 +0000 +Subject: [PATCH 1/1] ath79: add support for TP-Link CPE605-v1 TP-Link + CPE605-v1 is an outdoor wireless CPE for 5 GHz with one Ethernet port based + on Atheros AR9344 + +Specifications: + - 560/450/225 MHz (CPU/DDR/AHB) + - 1x 10/100 Mbps Ethernet + - 64 MB of DDR2 RAM + - 8 MB of SPI-NOR Flash + - 23dBi high-gain directional antenna and a dedicated metal reflector + - Power, LAN, WLAN5G green LEDs + - 3x green RSSI LEDs + +Flashing instructions: + Flash factory image through stock firmware WEB UI or through TFTP + To get to TFTP recovery just hold reset button while powering on for + around 4-5 seconds and release. + Rename factory image to recovery.bin + Stock TFTP server IP:192.168.0.100 + Stock device TFTP adress:192.168.0.254 + +Signed-off-by: Andrew Cameron +--- + .../ath79/dts/ar9344_tplink_cpe605-v1.dts | 33 +++++++++++++++++++ + .../generic/base-files/etc/board.d/01_leds | 1 + + .../generic/base-files/etc/board.d/02_network | 1 + + target/linux/ath79/image/generic-tp-link.mk | 10 ++++++ + 4 files changed, 45 insertions(+) + create mode 100644 target/linux/ath79/dts/ar9344_tplink_cpe605-v1.dts + +diff --git a/target/linux/ath79/dts/ar9344_tplink_cpe605-v1.dts b/target/linux/ath79/dts/ar9344_tplink_cpe605-v1.dts +new file mode 100644 +index 0000000000..0c6eee7ba6 +--- /dev/null ++++ b/target/linux/ath79/dts/ar9344_tplink_cpe605-v1.dts +@@ -0,0 +1,33 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++#include "ar9344_tplink_cpe.dtsi" ++ ++/ { ++ model = "TP-Link CPE605 v1"; ++ compatible = "tplink,cpe605-v1", "qca,ar9344"; ++ ++ aliases { ++ led-boot = &led_lan; ++ led-failsafe = &led_lan; ++ led-upgrade = &led_lan; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_lan: lan { ++ label = "green:lan"; ++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wlan5g { ++ label = "green:wlan5g"; ++ gpios = <&gpio 13 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "phy0tpt"; ++ }; ++ }; ++}; ++ ++ð1 { ++ compatible = "syscon", "simple-mfd"; ++}; +diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds +index 606a194f7e..54d764f907 100644 +--- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds ++++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds +@@ -18,6 +18,7 @@ glinet,6416|\ + glinet,gl-ar300m-lite|\ + glinet,gl-ar300m16|\ + pcs,cap324|\ ++tplink,cpe605-v1|\ + tplink,cpe610-v1|\ + tplink,cpe610-v2|\ + tplink,tl-wa1201-v2) +diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network +index e47f66c2f2..2fa0487981 100644 +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -76,6 +76,7 @@ ath79_setup_interfaces() + tplink,cpe210-v3|\ + tplink,cpe510-v2|\ + tplink,cpe510-v3|\ ++ tplink,cpe605-v1|\ + tplink,cpe610-v1|\ + tplink,cpe610-v2|\ + tplink,cpe710-v1|\ +diff --git a/target/linux/ath79/image/generic-tp-link.mk b/target/linux/ath79/image/generic-tp-link.mk +index 598085e50b..314ece1e03 100644 +--- a/target/linux/ath79/image/generic-tp-link.mk ++++ b/target/linux/ath79/image/generic-tp-link.mk +@@ -350,6 +350,16 @@ define Device/tplink_cpe510-v3 + endef + TARGET_DEVICES += tplink_cpe510-v3 + ++define Device/tplink_cpe605-v1 ++ $(Device/tplink-safeloader-okli) ++ SOC := ar9344 ++ IMAGE_SIZE := 7680k ++ DEVICE_MODEL := CPE605 ++ DEVICE_VARIANT := v1 ++ TPLINK_BOARD_ID := CPE605V1 ++endef ++TARGET_DEVICES += tplink_cpe605-v1 ++ + define Device/tplink_cpe610-v1 + $(Device/tplink-safeloader-okli) + SOC := ar9344 +-- +2.30.2 + +Index: openwrt/tools/firmware-utils/patches/0001-tplink-safeloader-add-TP-Link-CPE605-v1-Support.patch +=================================================================== +--- /dev/null ++++ openwrt/tools/firmware-utils/patches/0001-tplink-safeloader-add-TP-Link-CPE605-v1-Support.patch +@@ -0,0 +1,64 @@ ++From 2b43d1376a6945d07b2a87e48e3645eaa4f24d5a Mon Sep 17 00:00:00 2001 ++From: Andrew Cameron ++Date: Wed, 9 Nov 2022 13:07:11 +0000 ++Subject: [PATCH 1/1] tplink-safeloader: add TP-Link CPE605 v1 Support ++ ++Enable creating images compatible with the TP-Link CPE605 v1 Router ++ ++Signed-off-by: Andrew Cameron ++--- ++ src/tplink-safeloader.c | 38 ++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 38 insertions(+) ++ ++diff --git a/src/tplink-safeloader.c b/src/tplink-safeloader.c ++index 7f9081d..b920191 100644 ++--- a/src/tplink-safeloader.c +++++ b/src/tplink-safeloader.c ++@@ -468,6 +468,44 @@ static struct device_info boards[] = { ++ .last_sysupgrade_partition = "support-list", ++ }, ++ +++ /** Firmware layout for the CPE605V1 */ +++ { +++ .id = "CPE605V1", +++ .vendor = "CPE605(TP-LINK|UN|N150-5):1.0\r\n", +++ .support_list = +++ "SupportList:\r\n" +++ "CPE605(TP-LINK|UN|N150-5|00000000):1.0\r\n" +++ "CPE605(TP-LINK|EU|N150-5|45550000):1.0\r\n" +++ "CPE605(TP-LINK|US|N150-5|55530000):1.0\r\n" +++ "CPE605(TP-LINK|UN|N150-5):1.0\r\n" +++ "CPE605(TP-LINK|EU|N150-5):1.0\r\n" +++ "CPE605(TP-LINK|US|N150-5):1.0\r\n", +++ .part_trail = 0xff, +++ .soft_ver = SOFT_VER_DEFAULT, +++ +++ .partitions = { +++ {"fs-uboot", 0x00000, 0x20000}, +++ {"partition-table", 0x20000, 0x02000}, +++ {"default-mac", 0x30000, 0x00020}, +++ {"serial-number", 0x30100, 0x00020}, +++ {"product-info", 0x31100, 0x00100}, +++ {"device-info", 0x31400, 0x00400}, +++ {"signature", 0x32000, 0x00400}, +++ {"device-id", 0x33000, 0x00100}, +++ {"firmware", 0x40000, 0x770000}, +++ {"soft-version", 0x7b0000, 0x00100}, +++ {"support-list", 0x7b1000, 0x01000}, +++ {"user-config", 0x7c0000, 0x10000}, +++ {"default-config", 0x7d0000, 0x10000}, +++ {"log", 0x7e0000, 0x10000}, +++ {"radio", 0x7f0000, 0x10000}, +++ {NULL, 0, 0} +++ }, +++ +++ .first_sysupgrade_partition = "os-image", +++ .last_sysupgrade_partition = "support-list", +++ }, +++ ++ /** Firmware layout for the CPE610V1 */ ++ { ++ .id = "CPE610V1", ++-- ++2.30.2 ++ diff --git a/patches/001-add_support_for_GL-iNet_GL-AR150.patch b/patches/001-add_support_for_GL-iNet_GL-AR150.patch deleted file mode 100644 index 401fa317..00000000 --- a/patches/001-add_support_for_GL-iNet_GL-AR150.patch +++ /dev/null @@ -1,15 +0,0 @@ -Index: openwrt/target/linux/ar71xx/base-files/etc/board.d/01_leds -=================================================================== ---- openwrt.orig/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ openwrt/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -435,8 +435,8 @@ gl-mifi) - ;; - gl-ar150) - ucidef_set_led_wlan "wlan" "WLAN" "$board:orange:wlan" "phy0tpt" -- ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" -- ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" -+ ucidef_set_led_netdev "wan" "WAN" "$board:green:lan" "eth0" -+ ucidef_set_led_netdev "lan" "LAN" "$board:green:wan" "eth1" - ;; - gl-ar300) - ucidef_set_led_wlan "wlan" "WLAN" "$board:wlan" "phy0tpt" diff --git a/patches/001-add_support_for_TP-Link_ATH79_CPE210_v1.patch b/patches/001-add_support_for_TP-Link_ATH79_CPE210_v1.patch deleted file mode 100644 index 00e24ff7..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_CPE210_v1.patch +++ /dev/null @@ -1,71 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -148,6 +148,7 @@ tplink,archer-d50-v1) - ucidef_set_led_switch "wan_link" "WAN Link" "tp-link:white:wan" "switch0" "0x02" "" "link" - ;; - tplink,cpe510-v1|\ -+tplink,cpe210-v1|\ - tplink,cpe220-v2|\ - tplink,cpe220-v3) - ucidef_set_led_netdev "lan0" "LAN0" "tp-link:green:lan0" "eth1" ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -120,6 +120,7 @@ ath79_setup_interfaces() - comfast,cf-e110n-v2|\ - comfast,cf-e120a-v3|\ - tplink,cpe510-v1|\ -+ tplink,cpe210-v1|\ - tplink,cpe220-v2|\ - tplink,cpe220-v3|\ - ubnt,nanostation-m|\ ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -28,6 +28,7 @@ tplink,archer-c25-v1) - ucidef_add_gpio_switch "led_reset" "LED reset" "19" "1" - ;; - tplink,cpe510-v1|\ -+tplink,cpe210-v1|\ - tplink,cpe220-v2|\ - tplink,cpe220-v3) - ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "20" ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe210-v1.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,cpe210-v1", "qca,ar9344"; -+ model = "TP-Link CPE210 v1"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -153,6 +153,22 @@ define Device/tplink_archer-c7-v5 - endef - TARGET_DEVICES += tplink_archer-c7-v5 - -+define Device/tplink_cpe210-v1 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE210 v1 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE210 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe210 -+endef -+TARGET_DEVICES += tplink_cpe210-v1 -+ - define Device/tplink_cpe210-v2 - $(Device/tplink-safeloader) - ATH_SOC := qca9533 diff --git a/patches/001-add_support_for_TP-Link_ATH79_CPE220_v2.patch b/patches/001-add_support_for_TP-Link_ATH79_CPE220_v2.patch deleted file mode 100644 index b63e6f06..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_CPE220_v2.patch +++ /dev/null @@ -1,147 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -147,6 +147,7 @@ tplink,archer-d50-v1) - ucidef_set_led_switch "wan_data" "WAN Data" "tp-link:white:internet" "switch0" "0x02" "" "tx rx" - ucidef_set_led_switch "wan_link" "WAN Link" "tp-link:white:wan" "switch0" "0x02" "" "link" - ;; -+tplink,cpe220-v2|\ - tplink,cpe220-v3) - ucidef_set_led_netdev "lan0" "LAN0" "tp-link:green:lan0" "eth1" - ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -119,6 +119,7 @@ ath79_setup_interfaces() - ;; - comfast,cf-e110n-v2|\ - comfast,cf-e120a-v3|\ -+ tplink,cpe220-v2|\ - tplink,cpe220-v3|\ - ubnt,nanostation-m|\ - ubnt,routerstation) ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -27,6 +27,7 @@ tplink,archer-c25-v1) - ucidef_add_gpio_switch "led_control" "LED control" "21" "0" - ucidef_add_gpio_switch "led_reset" "LED reset" "19" "1" - ;; -+tplink,cpe220-v2|\ - tplink,cpe220-v3) - ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "20" - ;; ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe220-v2.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,cpe220-v2", "qca,ar9344"; -+ model = "TP-Link CPE220 v2"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>; -+}; ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe_2port.dtsi -@@ -0,0 +1,73 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+ -+#include "ar9344_tplink_cpe.dtsi" -+ -+/ { -+ aliases { -+ led-boot = &led_link4; -+ led-failsafe = &led_link4; -+ led-running = &led_link4; -+ led-upgrade = &led_link4; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ lan0 { -+ label = "tp-link:green:lan0"; -+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; -+ }; -+ -+ lan1 { -+ label = "tp-link:green:lan1"; -+ gpios = <&gpio 12 GPIO_ACTIVE_LOW>; -+ }; -+ -+ link1 { -+ label = "tp-link:green:link1"; -+ gpios = <&gpio 13 GPIO_ACTIVE_LOW>; -+ }; -+ -+ link2 { -+ label = "tp-link:green:link2"; -+ gpios = <&gpio 14 GPIO_ACTIVE_LOW>; -+ }; -+ -+ link3 { -+ label = "tp-link:green:link3"; -+ gpios = <&gpio 15 GPIO_ACTIVE_LOW>; -+ }; -+ -+ led_link4: link4 { -+ label = "tp-link:green:link4"; -+ }; -+ }; -+}; -+ -+&gpio { -+ gpio_ext_lna0 { -+ gpio-hog; -+ gpios = <18 0>; -+ output-high; -+ line-name = "tp-link:ext:lna0"; -+ }; -+ -+ gpio_ext_lna1 { -+ gpio-hog; -+ gpios = <19 0>; -+ output-high; -+ line-name = "tp-link:ext:lna1"; -+ }; -+}; -+ -+ð1 { -+ status = "okay"; -+ -+ mtd-mac-address = <&info 0x8>; -+ -+ gmac-config { -+ device = <&gmac>; -+ switch-phy-swap = <0>; -+ switch-only-mode = <1>; -+ }; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -177,6 +177,22 @@ define Device/tplink_cpe210-v3 - endef - TARGET_DEVICES += tplink_cpe210-v3 - -+define Device/tplink_cpe220-v2 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE220 v2 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE210 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe220-v2 -+endef -+TARGET_DEVICES += tplink_cpe220-v2 -+ - define Device/tplink_cpe220-v3 - $(Device/tplink-safeloader) - ATH_SOC := qca9533 diff --git a/patches/001-add_support_for_TP-Link_ATH79_CPE510_v1.patch b/patches/001-add_support_for_TP-Link_ATH79_CPE510_v1.patch deleted file mode 100644 index de176149..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_CPE510_v1.patch +++ /dev/null @@ -1,71 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -147,6 +147,7 @@ tplink,archer-d50-v1) - ucidef_set_led_switch "wan_data" "WAN Data" "tp-link:white:internet" "switch0" "0x02" "" "tx rx" - ucidef_set_led_switch "wan_link" "WAN Link" "tp-link:white:wan" "switch0" "0x02" "" "link" - ;; -+tplink,cpe510-v1|\ - tplink,cpe220-v2|\ - tplink,cpe220-v3) - ucidef_set_led_netdev "lan0" "LAN0" "tp-link:green:lan0" "eth1" ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -119,6 +119,7 @@ ath79_setup_interfaces() - ;; - comfast,cf-e110n-v2|\ - comfast,cf-e120a-v3|\ -+ tplink,cpe510-v1|\ - tplink,cpe220-v2|\ - tplink,cpe220-v3|\ - ubnt,nanostation-m|\ ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -27,6 +27,7 @@ tplink,archer-c25-v1) - ucidef_add_gpio_switch "led_control" "LED control" "21" "0" - ucidef_add_gpio_switch "led_reset" "LED reset" "19" "1" - ;; -+tplink,cpe510-v1|\ - tplink,cpe220-v2|\ - tplink,cpe220-v3) - ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "20" ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe510-v1.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,cpe510-v1", "qca,ar9344"; -+ model = "TP-Link CPE510 v1"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -204,6 +204,22 @@ define Device/tplink_cpe220-v3 - endef - TARGET_DEVICES += tplink_cpe220-v3 - -+define Device/tplink_cpe510-v1 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE510 v1 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE510 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe510 -+endef -+TARGET_DEVICES += tplink_cpe510-v1 -+ - define Device/tplink_cpe510-v2 - $(Device/tplink-safeloader) - ATH_SOC := ar9344 diff --git a/patches/001-add_support_for_TP-Link_ATH79_CPE510_v2_v3.patch b/patches/001-add_support_for_TP-Link_ATH79_CPE510_v2_v3.patch deleted file mode 100644 index 7e33b350..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_CPE510_v2_v3.patch +++ /dev/null @@ -1,261 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -165,6 +165,15 @@ tplink,cpe210-v3) - ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "60" "100" - ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "80" "100" - ;; -+tplink,cpe510-v2|\ -+tplink,cpe510-v3) -+ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" -+ ucidef_set_rssimon "wlan0" "200000" "1" -+ ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:link1" "wlan0" "1" "100" "0" "13" -+ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:link2" "wlan0" "26" "100" "-25" "13" -+ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13" -+ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13" -+ ;; - tplink,re450-v2) - ucidef_set_led_netdev "lan_data" "LAN Data" "tp-link:green:lan_data" "eth0" "tx rx" - ucidef_set_led_netdev "lan_link" "LAN Link" "tp-link:green:lan_link" "eth0" "link" ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -26,6 +26,8 @@ ath79_setup_interfaces() - pqi,air-pen|\ - tplink,cpe210-v2|\ - tplink,cpe210-v3|\ -+ tplink,cpe510-v2|\ -+ tplink,cpe510-v3|\ - tplink,re350k-v1|\ - tplink,re450-v2|\ - tplink,tl-mr10u|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe.dtsi -@@ -0,0 +1,112 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+ -+#include -+#include -+ -+#include "ar9344.dtsi" -+ -+/ { -+ aliases { -+ label-mac-device = &wmac; -+ }; -+ -+ keys { -+ compatible = "gpio-keys"; -+ -+ reset { -+ linux,code = ; -+ gpios = <&gpio 4 GPIO_ACTIVE_LOW>; -+ debounce-interval = <60>; -+ }; -+ }; -+}; -+ -+&ref { -+ clock-frequency = <40000000>; -+}; -+ -+&uart { -+ status = "okay"; -+}; -+ -+&spi { -+ status = "okay"; -+ -+ num-cs = <1>; -+ -+ flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <25000000>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uboot: partition@0 { -+ label = "u-boot"; -+ reg = <0x000000 0x020000>; -+ read-only; -+ }; -+ -+ partition@20000 { -+ label = "partition-table"; -+ reg = <0x020000 0x010000>; -+ read-only; -+ }; -+ -+ info: partition@30000 { -+ label = "info"; -+ reg = <0x030000 0x010000>; -+ read-only; -+ }; -+ -+ partition@40000 { -+ label = "firmware"; -+ reg = <0x040000 0x780000>; -+ -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "kernel"; -+ reg = <0x000000 0x1c0000>; -+ }; -+ -+ partition@1c0000 { -+ label = "rootfs"; -+ reg = <0x1c0000 0x5c0000>; -+ }; -+ }; -+ -+ partition@7c0000 { -+ label = "config"; -+ reg = <0x7c0000 0x030000>; -+ read-only; -+ }; -+ -+ art: partition@7f0000 { -+ label = "art"; -+ reg = <0x7f0000 0x010000>; -+ read-only; -+ }; -+ }; -+ }; -+}; -+ -+&wmac { -+ status = "okay"; -+ -+ mtd-cal-data = <&art 0x1000>; -+ mtd-mac-address = <&info 0x08>; -+}; -+ -+ð0 { -+ status = "okay"; -+ -+ phy-handle = <&swphy4>; -+ -+ mtd-mac-address = <&info 0x8>; -+}; ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe510-v2.dts -@@ -0,0 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_1port.dtsi" -+ -+/ { -+ compatible = "tplink,cpe510-v2", "qca,ar9344"; -+ model = "TP-Link CPE510 v2"; -+}; -+ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe510-v3.dts -@@ -0,0 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_1port.dtsi" -+ -+/ { -+ compatible = "tplink,cpe510-v3", "qca,ar9344"; -+ model = "TP-Link CPE510 v3"; -+}; -+ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe_1port.dtsi -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+ -+#include "ar9344_tplink_cpe.dtsi" -+ -+/ { -+ aliases { -+ led-boot = &led_system; -+ led-failsafe = &led_system; -+ led-running = &led_system; -+ led-upgrade = &led_system; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ lan { -+ label = "tp-link:green:lan"; -+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; -+ }; -+ -+ link1 { -+ label = "tp-link:green:link1"; -+ gpios = <&gpio 13 GPIO_ACTIVE_LOW>; -+ }; -+ -+ link2 { -+ label = "tp-link:green:link2"; -+ gpios = <&gpio 14 GPIO_ACTIVE_LOW>; -+ }; -+ -+ link3 { -+ label = "tp-link:green:link3"; -+ gpios = <&gpio 15 GPIO_ACTIVE_LOW>; -+ }; -+ -+ led_system: link4 { -+ label = "tp-link:green:link4"; -+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; -+ -+ð1 { -+ status = "okay"; -+ -+ compatible = "syscon", "simple-mfd"; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -188,6 +188,38 @@ define Device/tplink_cpe220-v3 - endef - TARGET_DEVICES += tplink_cpe220-v3 - -+define Device/tplink_cpe510-v2 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE510 v2 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE510V2 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe510-v2 -+endef -+TARGET_DEVICES += tplink_cpe510-v2 -+ -+define Device/tplink_cpe510-v3 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE510 v3 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE510V2 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe510-v3 -+endef -+TARGET_DEVICES += tplink_cpe510-v3 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 diff --git a/patches/001-add_support_for_TP-Link_ATH79_CPE610_v1.patch b/patches/001-add_support_for_TP-Link_ATH79_CPE610_v1.patch deleted file mode 100644 index 609b31c6..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_CPE610_v1.patch +++ /dev/null @@ -1,124 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -174,6 +174,9 @@ tplink,cpe510-v3) - ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13" - ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13" - ;; -+tplink,cpe610-v1) -+ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" -+ ;; - tplink,re450-v2) - ucidef_set_led_netdev "lan_data" "LAN Data" "tp-link:green:lan_data" "eth0" "tx rx" - ucidef_set_led_netdev "lan_link" "LAN Link" "tp-link:green:lan_link" "eth0" "link" ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -28,6 +28,7 @@ ath79_setup_interfaces() - tplink,cpe210-v3|\ - tplink,cpe510-v2|\ - tplink,cpe510-v3|\ -+ tplink,cpe610-v1|\ - tplink,re350k-v1|\ - tplink,re450-v2|\ - tplink,tl-mr10u|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe610-v1.dts -@@ -0,0 +1,36 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe.dtsi" -+ -+/ { -+ model = "TP-Link CPE610 v1"; -+ compatible = "tplink,cpe610-v1", "qca,ar9344"; -+ -+ aliases { -+ led-boot = &led_lan; -+ led-failsafe = &led_lan; -+ led-upgrade = &led_lan; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_lan: lan { -+ label = "tp-link:green:lan"; -+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; -+ }; -+ -+ wlan5g { -+ label = "tp-link:green:wlan5g"; -+ gpios = <&gpio 13 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "phy0tpt"; -+ }; -+ }; -+}; -+ -+ð1 { -+ status = "okay"; -+ -+ compatible = "syscon", "simple-mfd"; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -220,6 +220,22 @@ define Device/tplink_cpe510-v3 - endef - TARGET_DEVICES += tplink_cpe510-v3 - -+define Device/tplink_cpe610-v1 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE610 v1 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE610 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe610 -+endef -+TARGET_DEVICES += tplink_cpe610-v1 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -309,21 +309,20 @@ static struct device_info boards[] = { - .soft_ver = NULL, - - .partitions = { -- {"fs-uboot", 0x00000, 0x20000}, -- {"partition-table", 0x20000, 0x02000}, -- {"default-mac", 0x30000, 0x00020}, -- {"product-info", 0x31100, 0x00100}, -- {"device-info", 0x31400, 0x00400}, -- {"signature", 0x32000, 0x00400}, -- {"device-id", 0x33000, 0x00100}, -- {"firmware", 0x40000, 0x770000}, -- {"soft-version", 0x7b0000, 0x00100}, -- {"support-list", 0x7b1000, 0x01000}, -- {"user-config", 0x7c0000, 0x10000}, -- {"default-config", 0x7d0000, 0x10000}, -- {"log", 0x7e0000, 0x10000}, -- {"radio", 0x7f0000, 0x10000}, -- {NULL, 0, 0} -+ {"fs-uboot", 0x00000, 0x20000}, -+ {"partition-table", 0x20000, 0x02000}, -+ {"default-mac", 0x30000, 0x00020}, -+ {"product-info", 0x31100, 0x00100}, -+ {"signature", 0x32000, 0x00400}, -+ {"os-image", 0x40000, 0x1c0000}, -+ {"file-system", 0x200000, 0x5b0000}, -+ {"soft-version", 0x7b0000, 0x00100}, -+ {"support-list", 0x7b1000, 0x00400}, -+ {"user-config", 0x7c0000, 0x10000}, -+ {"default-config", 0x7d0000, 0x10000}, -+ {"log", 0x7e0000, 0x10000}, -+ {"radio", 0x7f0000, 0x10000}, -+ {NULL, 0, 0} - }, - - .first_sysupgrade_partition = "os-image", diff --git a/patches/001-add_support_for_TP-Link_ATH79_CPE610_v2.patch b/patches/001-add_support_for_TP-Link_ATH79_CPE610_v2.patch deleted file mode 100644 index 4cb041e9..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_CPE610_v2.patch +++ /dev/null @@ -1,135 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -174,7 +174,8 @@ tplink,cpe510-v3) - ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13" - ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13" - ;; --tplink,cpe610-v1) -+tplink,cpe610-v1|\ -+tplink,cpe610-v2) - ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" - ;; - tplink,re450-v2) ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -29,6 +29,7 @@ ath79_setup_interfaces() - tplink,cpe510-v2|\ - tplink,cpe510-v3|\ - tplink,cpe610-v1|\ -+ tplink,cpe610-v2|\ - tplink,re350k-v1|\ - tplink,re450-v2|\ - tplink,tl-mr10u|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe610-v2.dts -@@ -0,0 +1,36 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe.dtsi" -+ -+/ { -+ model = "TP-Link CPE610 v2"; -+ compatible = "tplink,cpe610-v2", "qca,ar9344"; -+ -+ aliases { -+ led-boot = &led_lan; -+ led-failsafe = &led_lan; -+ led-upgrade = &led_lan; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_lan: lan { -+ label = "tp-link:green:lan"; -+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; -+ }; -+ -+ wlan5g { -+ label = "tp-link:green:wlan5g"; -+ gpios = <&gpio 13 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "phy0tpt"; -+ }; -+ }; -+}; -+ -+ð1 { -+ status = "okay"; -+ -+ compatible = "syscon", "simple-mfd"; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -236,6 +236,22 @@ define Device/tplink_cpe610-v1 - endef - TARGET_DEVICES += tplink_cpe610-v1 - -+define Device/tplink_cpe610-v2 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link CPE610 v2 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := CPE610V2 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += cpe610-v2 -+endef -+TARGET_DEVICES += tplink_cpe610-v2 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -249,6 +249,46 @@ static struct device_info boards[] = { - .last_sysupgrade_partition = "support-list", - }, - -+ /** Firmware layout for the CPE610 v2 */ -+ { -+ .id = "CPE610V2", -+ .vendor = "CPE610(TP-LINK|UN|N300-5|00000000):2.0\r\n", -+ .support_list = -+ "SupportList:\r\n" -+ "CPE610(TP-LINK|EU|N300-5|00000000):2.0\r\n" -+ "CPE610(TP-LINK|EU|N300-5|45550000):2.0\r\n" -+ "CPE610(TP-LINK|EU|N300-5|55530000):2.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5|00000000):2.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5|45550000):2.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5|55530000):2.0\r\n" -+ "CPE610(TP-LINK|US|N300-5|55530000):2.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5):2.0\r\n" -+ "CPE610(TP-LINK|EU|N300-5):2.0\r\n" -+ "CPE610(TP-LINK|US|N300-5):2.0\r\n", -+ .support_trail = '\xff', -+ .soft_ver = NULL, -+ -+ .partitions = { -+ {"fs-uboot", 0x00000, 0x20000}, -+ {"partition-table", 0x20000, 0x02000}, -+ {"default-mac", 0x30000, 0x00020}, -+ {"product-info", 0x31100, 0x00100}, -+ {"signature", 0x32000, 0x00400}, -+ {"os-image", 0x40000, 0x1c0000}, -+ {"file-system", 0x200000, 0x5b0000}, -+ {"soft-version", 0x7b0000, 0x00100}, -+ {"support-list", 0x7b1000, 0x00400}, -+ {"user-config", 0x7c0000, 0x10000}, -+ {"default-config", 0x7d0000, 0x10000}, -+ {"log", 0x7e0000, 0x10000}, -+ {"radio", 0x7f0000, 0x10000}, -+ {NULL, 0, 0} -+ }, -+ -+ .first_sysupgrade_partition = "os-image", -+ .last_sysupgrade_partition = "support-list", -+ }, -+ - /** Firmware layout for the CPE220 V3 */ - { - .id = "CPE220V3", diff --git a/patches/001-add_support_for_TP-Link_ATH79_WBS210_v1.patch b/patches/001-add_support_for_TP-Link_ATH79_WBS210_v1.patch deleted file mode 100644 index 43959473..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_WBS210_v1.patch +++ /dev/null @@ -1,71 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -147,6 +147,7 @@ tplink,archer-d50-v1) - ucidef_set_led_switch "wan_data" "WAN Data" "tp-link:white:internet" "switch0" "0x02" "" "tx rx" - ucidef_set_led_switch "wan_link" "WAN Link" "tp-link:white:wan" "switch0" "0x02" "" "link" - ;; -+tplink,wbs210-v1|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -119,6 +119,7 @@ ath79_setup_interfaces() - ;; - comfast,cf-e110n-v2|\ - comfast,cf-e120a-v3|\ -+ tplink,wbs210-v1|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -27,6 +27,7 @@ tplink,archer-c25-v1) - ucidef_add_gpio_switch "led_control" "LED control" "21" "0" - ucidef_add_gpio_switch "led_reset" "LED reset" "19" "1" - ;; -+tplink,wbs210-v1|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_wbs210-v1.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,wbs210-v1", "qca,ar9344"; -+ model = "TP-Link WBS210 v1"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -300,6 +300,22 @@ define Device/tplink_cpe610-v2 - endef - TARGET_DEVICES += tplink_cpe610-v2 - -+define Device/tplink_wbs210-v1 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link WBS210 v1 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := WBS210 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += wbs210 -+endef -+TARGET_DEVICES += tplink_wbs210-v1 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 diff --git a/patches/001-add_support_for_TP-Link_ATH79_WBS210_v2.patch b/patches/001-add_support_for_TP-Link_ATH79_WBS210_v2.patch deleted file mode 100644 index d9f2dbef..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_WBS210_v2.patch +++ /dev/null @@ -1,117 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -148,6 +148,7 @@ tplink,archer-d50-v1) - ucidef_set_led_switch "wan_link" "WAN Link" "tp-link:white:wan" "switch0" "0x02" "" "link" - ;; - tplink,wbs210-v1|\ -+tplink,wbs210-v2|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -120,6 +120,7 @@ ath79_setup_interfaces() - comfast,cf-e110n-v2|\ - comfast,cf-e120a-v3|\ - tplink,wbs210-v1|\ -+ tplink,wbs210-v2|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -28,6 +28,7 @@ tplink,archer-c25-v1) - ucidef_add_gpio_switch "led_reset" "LED reset" "19" "1" - ;; - tplink,wbs210-v1|\ -+tplink,wbs210-v2|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_wbs210-v2.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,wbs210-v2", "qca,ar9344"; -+ model = "TP-Link WBS210 v2"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -316,6 +316,22 @@ define Device/tplink_wbs210-v1 - endef - TARGET_DEVICES += tplink_wbs210-v1 - -+define Device/tplink_wbs210-v2 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link WBS210 v2 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := WBS210V2 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += wbs210-v2 -+endef -+TARGET_DEVICES += tplink_wbs210-v2 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -1,4 +1,3 @@ -- - /* - Copyright (c) 2014, Matthias Schiffer - All rights reserved. -@@ -502,6 +501,38 @@ static struct device_info boards[] = { - .support_trail = '\xff', - .soft_ver = NULL, - -+ .partitions = { -+ {"fs-uboot", 0x00000, 0x20000}, -+ {"partition-table", 0x20000, 0x02000}, -+ {"default-mac", 0x30000, 0x00020}, -+ {"product-info", 0x31100, 0x00100}, -+ {"signature", 0x32000, 0x00400}, -+ {"os-image", 0x40000, 0x1c0000}, -+ {"file-system", 0x200000, 0x5b0000}, -+ {"soft-version", 0x7b0000, 0x00100}, -+ {"support-list", 0x7b1000, 0x00400}, -+ {"user-config", 0x7c0000, 0x10000}, -+ {"default-config", 0x7d0000, 0x10000}, -+ {"log", 0x7e0000, 0x10000}, -+ {"radio", 0x7f0000, 0x10000}, -+ {NULL, 0, 0} -+ }, -+ -+ .first_sysupgrade_partition = "os-image", -+ .last_sysupgrade_partition = "support-list", -+ }, -+ -+ { -+ .id = "WBS210V2", -+ .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n", -+ .support_list = -+ "SupportList:\r\n" -+ "WBS210(TP-LINK|UN|N300-2|00000000):2.00\r\n" -+ "WBS210(TP-LINK|US|N300-2|55530000):2.00\r\n" -+ "WBS210(TP-LINK|EU|N300-2|45550000):2.00\r\n", -+ .support_trail = '\xff', -+ .soft_ver = NULL, -+ - .partitions = { - {"fs-uboot", 0x00000, 0x20000}, - {"partition-table", 0x20000, 0x02000}, diff --git a/patches/001-add_support_for_TP-Link_ATH79_WBS510_v1.patch b/patches/001-add_support_for_TP-Link_ATH79_WBS510_v1.patch deleted file mode 100644 index 229514b9..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_WBS510_v1.patch +++ /dev/null @@ -1,71 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -149,6 +149,7 @@ tplink,archer-d50-v1) - ;; - tplink,wbs210-v1|\ - tplink,wbs210-v2|\ -+tplink,wbs510-v1|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -121,6 +121,7 @@ ath79_setup_interfaces() - comfast,cf-e120a-v3|\ - tplink,wbs210-v1|\ - tplink,wbs210-v2|\ -+ tplink,wbs510-v1|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -29,6 +29,7 @@ tplink,archer-c25-v1) - ;; - tplink,wbs210-v1|\ - tplink,wbs210-v2|\ -+tplink,wbs510-v1|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_wbs510-v1.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,wbs510-v1", "qca,ar9344"; -+ model = "TP-Link WBS510 v1"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -332,6 +332,22 @@ define Device/tplink_wbs210-v2 - endef - TARGET_DEVICES += tplink_wbs210-v2 - -+define Device/tplink_wbs510-v1 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link WBS510 v1 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := WBS510 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += wbs510 -+endef -+TARGET_DEVICES += tplink_wbs510-v1 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 diff --git a/patches/001-add_support_for_TP-Link_ATH79_WBS510_v2.patch b/patches/001-add_support_for_TP-Link_ATH79_WBS510_v2.patch deleted file mode 100644 index 5a3a7895..00000000 --- a/patches/001-add_support_for_TP-Link_ATH79_WBS510_v2.patch +++ /dev/null @@ -1,71 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/01_leds -+++ b/target/linux/ath79/base-files/etc/board.d/01_leds -@@ -150,6 +150,7 @@ tplink,archer-d50-v1) - tplink,wbs210-v1|\ - tplink,wbs210-v2|\ - tplink,wbs510-v1|\ -+tplink,wbs510-v2|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -122,6 +122,7 @@ ath79_setup_interfaces() - tplink,wbs210-v1|\ - tplink,wbs210-v2|\ - tplink,wbs510-v1|\ -+ tplink,wbs510-v2|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- a/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ath79/base-files/etc/board.d/03_gpio_switches -@@ -30,6 +30,7 @@ tplink,archer-c25-v1) - tplink,wbs210-v1|\ - tplink,wbs210-v2|\ - tplink,wbs510-v1|\ -+tplink,wbs510-v2|\ - tplink,cpe510-v1|\ - tplink,cpe210-v1|\ - tplink,cpe220-v2|\ ---- /dev/null -+++ b/target/linux/ath79/dts/ar9344_tplink_wbs510-v2.dts -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/dts-v1/; -+ -+#include "ar9344_tplink_cpe_2port.dtsi" -+ -+/ { -+ compatible = "tplink,wbs510-v2", "qca,ar9344"; -+ model = "TP-Link WBS510 v2"; -+}; -+ -+&led_link4 { -+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>; -+}; ---- a/target/linux/ath79/image/generic-tp-link.mk -+++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -348,6 +348,22 @@ define Device/tplink_wbs510-v1 - endef - TARGET_DEVICES += tplink_wbs510-v1 - -+define Device/tplink_wbs510-v2 -+ $(Device/tplink-safeloader) -+ ATH_SOC := ar9344 -+ IMAGE_SIZE := 7680k -+ DEVICE_TITLE := TP-Link WBS510 v2 -+ DEVICE_PACKAGES := rssileds -+ TPLINK_BOARD_ID := WBS510V2 -+ LOADER_TYPE := elf -+ LOADER_FLASH_OFFS := 0x43000 -+ COMPILE := loader-$(1).elf -+ COMPILE/loader-$(1).elf := loader-okli-compile -+ KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 -+ SUPPORTED_DEVICES += wbs510-v2 -+endef -+TARGET_DEVICES += tplink_wbs510-v2 -+ - define Device/tplink_archer-d50-v1 - ATH_SOC := qca9531 - DEVICE_TITLE := TP-Link Archer D50 v1 diff --git a/patches/001-add_support_for_TP-Link_CPE220_v2.patch b/patches/001-add_support_for_TP-Link_CPE220_v2.patch deleted file mode 100644 index 1e56521b..00000000 --- a/patches/001-add_support_for_TP-Link_CPE220_v2.patch +++ /dev/null @@ -1,103 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -254,6 +254,7 @@ cf-e530n) - cpe210|\ - cpe210-v2|\ - cpe210-v3|\ -+cpe220-v2|\ - cpe220-v3|\ - cpe510|\ - cpe510-v2|\ ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -290,6 +290,7 @@ ar71xx_setup_interfaces() - "0@eth0" "2:lan" "1:wan" "6@eth1" - ;; - cpe210|\ -+ cpe220-v2|\ - cpe220-v3|\ - cpe510|\ - wbs210|\ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -759,6 +759,10 @@ ar71xx_board_detect() { - name="cpe210-v3" - tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" - ;; -+ *"CPE220 v2") -+ name="cpe220-v2" -+ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" -+ ;; - *"CPE220 v3") - name="cpe220-v3" - tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -599,6 +599,7 @@ platform_check_image() { - tplink_pharos_check_image "$1" "01000000" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 - return 1 - ;; -+ cpe220-v2|\ - cpe610|\ - cpe510-v2|\ - cpe510-v3) ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -@@ -334,6 +334,9 @@ MIPS_MACHINE(ATH79_MACH_CPE210_V2, "CPE2 - MIPS_MACHINE(ATH79_MACH_CPE210_V3, "CPE210V3", "TP-LINK CPE210 v3", - cpe210_v2_setup); - -+MIPS_MACHINE(ATH79_MACH_CPE220_V2, "CPE220V2", "TP-LINK CPE220 v2", -+ cpe210_setup); -+ - MIPS_MACHINE(ATH79_MACH_CPE220_V3, "CPE220V3", "TP-LINK CPE220 v3", - cpe220_v3_setup); - ---- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -+++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -@@ -77,6 +77,7 @@ enum ath79_mach_type { - ATH79_MACH_CPE210, /* TP-LINK CPE210 v1 */ - ATH79_MACH_CPE210_V2, /* TP-LINK CPE210 v2 */ - ATH79_MACH_CPE210_V3, /* TP-LINK CPE210 v3 */ -+ ATH79_MACH_CPE220_V2, /* TP-LINK CPE220 v2 */ - ATH79_MACH_CPE220_V3, /* TP-LINK CPE220 v3 */ - ATH79_MACH_CPE505N, /* P&W CPE505N */ - ATH79_MACH_CPE510, /* TP-LINK CPE510 */ ---- a/target/linux/ar71xx/image/generic-tp-link.mk -+++ b/target/linux/ar71xx/image/generic-tp-link.mk -@@ -239,6 +239,14 @@ define Device/cpe610-v1 - endef - TARGET_DEVICES += cpe610-v1 - -+define Device/cpe220-v2 -+ $(Device/cpe510-520-v1) -+ DEVICE_TITLE := TP-LINK CPE220 v2 -+ BOARDNAME := CPE220V2 -+ TPLINK_BOARD_ID := CPE210 -+endef -+TARGET_DEVICES += cpe220-v2 -+ - define Device/cpe220-v3 - $(Device/cpe210-v2) - DEVICE_TITLE := TP-LINK CPE220 v3 ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -131,7 +131,17 @@ static struct device_info boards[] = { - "CPE210(TP-LINK|EU|N300-2):1.1\r\n" - "CPE220(TP-LINK|UN|N300-2):1.1\r\n" - "CPE220(TP-LINK|US|N300-2):1.1\r\n" -- "CPE220(TP-LINK|EU|N300-2):1.1\r\n", -+ "CPE220(TP-LINK|EU|N300-2):1.1\r\n" -+ "CPE220(TP-LINK|EU|N300-2|00000000):2.0\r\n" -+ "CPE220(TP-LINK|EU|N300-2|45550000):2.0\r\n" -+ "CPE220(TP-LINK|EU|N300-2|55530000):2.0\r\n" -+ "CPE220(TP-LINK|UN|N300-2|00000000):2.0\r\n" -+ "CPE220(TP-LINK|UN|N300-2|45550000):2.0\r\n" -+ "CPE220(TP-LINK|UN|N300-2|55530000):2.0\r\n" -+ "CPE220(TP-LINK|US|N300-2|55530000):2.0\r\n" -+ "CPE220(TP-LINK|UN|N300-2):2.0\r\n" -+ "CPE220(TP-LINK|EU|N300-2):2.0\r\n" -+ "CPE220(TP-LINK|US|N300-2):2.0\r\n", - .support_trail = '\xff', - .soft_ver = NULL, - diff --git a/patches/001-add_support_for_TP-Link_CPE220_v3.patch b/patches/001-add_support_for_TP-Link_CPE220_v3.patch deleted file mode 100644 index 918ea49d..00000000 --- a/patches/001-add_support_for_TP-Link_CPE220_v3.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 70260d35ff2f9428c085583f30b053ec45eea2f8 Mon Sep 17 00:00:00 2001 -From: Andrew Cameron -Date: Fri, 25 Oct 2019 20:32:48 -0500 -Subject: [PATCH 2/2] ar71xx: add Support for the TP-LINK CPE220 V3.0 Device - -This adds support for a popular low-cost 2.4GHz N based AP - -Specifications: -SoC: Qualcomm Atheros QCA9533 (650MHz) -RAM: 64MB -Storage: 8 MB SPI NOR -Wireless: 2.4GHz N based built into SoC 2x2 -Ethernet: 2x 100/10 Mbps, integrated into SoC - -Installation: -Flash factory image through stock firmware WEB UI -or through TFTP -To get to TFTP recovery just hold reset button while powering on for -around 4-5 seconds and release. -Rename factory image to recovery.bin -Stock TFTP server IP:192.168.0.100 -Stock device TFTP adress:192.168.0.254 - -Signed-off-by: Andrew Cameron apcameron@softhome.net ---- - .../ar71xx/base-files/etc/board.d/01_leds | 1 + - .../ar71xx/base-files/etc/board.d/02_network | 1 + - .../base-files/etc/board.d/03_gpio_switches | 1 + - target/linux/ar71xx/base-files/lib/ar71xx.sh | 4 ++++ - .../ar71xx/base-files/lib/upgrade/platform.sh | 3 ++- - .../files/arch/mips/ath79/mach-cpe510.c | 24 +++++++++++++++++++ - .../ar71xx/files/arch/mips/ath79/machtypes.h | 1 + - target/linux/ar71xx/image/generic-tp-link.mk | 8 +++++++ - 8 files changed, 42 insertions(+), 1 deletion(-) - ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -254,6 +254,7 @@ cf-e530n) - cpe210|\ - cpe210-v2|\ - cpe210-v3|\ -+cpe220-v3|\ - cpe510|\ - cpe510-v2|\ - wbs210|\ ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -289,6 +289,7 @@ ar71xx_setup_interfaces() - "0@eth0" "2:lan" "1:wan" "6@eth1" - ;; - cpe210|\ -+ cpe220-v3|\ - cpe510|\ - wbs210|\ - wbs510) ---- a/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches -@@ -11,6 +11,7 @@ board=$(board_name) - - case "$board" in - cpe210|\ -+cpe220-v3|\ - cpe510|\ - wbs210|\ - wbs510) ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -759,6 +759,10 @@ ar71xx_board_detect() { - name="cpe210-v3" - tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" - ;; -+ *"CPE220 v3") -+ name="cpe220-v3" -+ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" -+ ;; - *"CPE505N") - name="cpe505n" - ;; ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -594,7 +594,8 @@ platform_check_image() { - return 1 - ;; - cpe210-v2|\ -- cpe210-v3) -+ cpe210-v3|\ -+ cpe220-v3) - tplink_pharos_check_image "$1" "01000000" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 - return 1 - ;; ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -@@ -304,6 +304,27 @@ static void __init cpe610_setup(void) - ath79_register_wmac(ee, mac); - } - -+static void __init cpe220_v3_setup(void) -+{ -+ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); -+ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); -+ -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe510_leds_gpio), -+ cpe510_leds_gpio); -+ -+ ath79_register_gpio_keys_polled(-1, CPE510_KEYS_POLL_INTERVAL, -+ ARRAY_SIZE(cpe210_v2_gpio_keys), -+ cpe210_v2_gpio_keys); -+ -+ ath79_register_m25p80(NULL); -+ ath79_register_mdio(0, 0x0); -+ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); -+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; -+ ath79_register_eth(1); -+ -+ ath79_register_wmac(ee, mac); -+} -+ - MIPS_MACHINE(ATH79_MACH_CPE210, "CPE210", "TP-LINK CPE210/220", - cpe210_setup); - -@@ -313,6 +334,9 @@ MIPS_MACHINE(ATH79_MACH_CPE210_V2, "CPE2 - MIPS_MACHINE(ATH79_MACH_CPE210_V3, "CPE210V3", "TP-LINK CPE210 v3", - cpe210_v2_setup); - -+MIPS_MACHINE(ATH79_MACH_CPE220_V3, "CPE220V3", "TP-LINK CPE220 v3", -+ cpe220_v3_setup); -+ - MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510", "TP-LINK CPE510/520", - cpe510_setup); - ---- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -+++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -@@ -77,6 +77,7 @@ enum ath79_mach_type { - ATH79_MACH_CPE210, /* TP-LINK CPE210 v1 */ - ATH79_MACH_CPE210_V2, /* TP-LINK CPE210 v2 */ - ATH79_MACH_CPE210_V3, /* TP-LINK CPE210 v3 */ -+ ATH79_MACH_CPE220_V3, /* TP-LINK CPE220 v3 */ - ATH79_MACH_CPE505N, /* P&W CPE505N */ - ATH79_MACH_CPE510, /* TP-LINK CPE510 */ - ATH79_MACH_CPE510_V2, /* TP-LINK CPE510 v2 */ ---- a/target/linux/ar71xx/image/generic-tp-link.mk -+++ b/target/linux/ar71xx/image/generic-tp-link.mk -@@ -231,6 +231,14 @@ define Device/cpe610-v1 - endef - TARGET_DEVICES += cpe610-v1 - -+define Device/cpe220-v3 -+ $(Device/cpe210-v2) -+ DEVICE_TITLE := TP-LINK CPE220 v3 -+ BOARDNAME := CPE220V3 -+ TPLINK_BOARD_ID := CPE220V3 -+endef -+TARGET_DEVICES += cpe220-v3 -+ - define Device/wbs210-v1 - $(Device/cpe510-520-v1) - DEVICE_TITLE := TP-LINK WBS210 v1 diff --git a/patches/001-add_support_for_TP-Link_CPE510_v3.20.patch b/patches/001-add_support_for_TP-Link_CPE510_v3.20.patch deleted file mode 100644 index 0f7bb1c3..00000000 --- a/patches/001-add_support_for_TP-Link_CPE510_v3.20.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -424,13 +424,12 @@ static struct device_info boards[] = { - "CPE510(TP-LINK|UN|N300-5):2.0\r\n" - "CPE510(TP-LINK|EU|N300-5):2.0\r\n" - "CPE510(TP-LINK|US|N300-5):2.0\r\n" -- "CPE510(TP-LINK|EU|N300-5|00000000):3.0\r\n" - "CPE510(TP-LINK|EU|N300-5|45550000):3.0\r\n" -- "CPE510(TP-LINK|EU|N300-5|55530000):3.0\r\n" - "CPE510(TP-LINK|UN|N300-5|00000000):3.0\r\n" -- "CPE510(TP-LINK|UN|N300-5|45550000):3.0\r\n" -- "CPE510(TP-LINK|UN|N300-5|55530000):3.0\r\n" - "CPE510(TP-LINK|US|N300-5|55530000):3.0\r\n" -+ "CPE510(TP-LINK|EU|N300-5|45550000):3.20\r\n" -+ "CPE510(TP-LINK|UN|N300-5|00000000):3.20\r\n" -+ "CPE510(TP-LINK|US|N300-5|55530000):3.20\r\n" - "CPE510(TP-LINK|UN|N300-5):3.0\r\n" - "CPE510(TP-LINK|EU|N300-5):3.0\r\n" - "CPE510(TP-LINK|US|N300-5):3.0\r\n", diff --git a/patches/001-add_support_for_TP-Link_CPE510_v3.patch b/patches/001-add_support_for_TP-Link_CPE510_v3.patch deleted file mode 100644 index fc69d75b..00000000 --- a/patches/001-add_support_for_TP-Link_CPE510_v3.patch +++ /dev/null @@ -1,115 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -257,6 +257,7 @@ cpe210-v3|\ - cpe220-v3|\ - cpe510|\ - cpe510-v2|\ -+cpe510-v3|\ - wbs210|\ - wbs510) - ucidef_set_rssimon "wlan0" "200000" "1" -@@ -268,7 +269,8 @@ wbs510) - case "$board" in - cpe210-v2|\ - cpe210-v3|\ -- cpe510-v2) -+ cpe510-v2|\ -+ cpe510-v3) - ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan0" "eth0" - ;; - *) ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -78,6 +78,7 @@ ar71xx_setup_interfaces() - cpe210-v2|\ - cpe210-v3|\ - cpe510-v2|\ -+ cpe510-v3|\ - dr342|\ - eap120|\ - eap300v2|\ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -774,6 +774,10 @@ ar71xx_board_detect() { - name="cpe510-v2" - tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" - ;; -+ *"CPE510 v3") -+ name="cpe510-v3" -+ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" -+ ;; - *"CPE610") - name="cpe610" - tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -600,7 +600,8 @@ platform_check_image() { - return 1 - ;; - cpe610|\ -- cpe510-v2) -+ cpe510-v2|\ -+ cpe510-v3) - tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 - return 1 - ;; ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -@@ -337,6 +337,9 @@ MIPS_MACHINE(ATH79_MACH_CPE210_V3, "CPE2 - MIPS_MACHINE(ATH79_MACH_CPE220_V3, "CPE220V3", "TP-LINK CPE220 v3", - cpe220_v3_setup); - -+MIPS_MACHINE(ATH79_MACH_CPE510_V3, "CPE510V3", "TP-LINK CPE510 v3", -+ cpe510_v2_setup); -+ - MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510", "TP-LINK CPE510/520", - cpe510_setup); - ---- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -+++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -@@ -81,6 +81,7 @@ enum ath79_mach_type { - ATH79_MACH_CPE505N, /* P&W CPE505N */ - ATH79_MACH_CPE510, /* TP-LINK CPE510 */ - ATH79_MACH_CPE510_V2, /* TP-LINK CPE510 v2 */ -+ ATH79_MACH_CPE510_V3, /* TP-LINK CPE510 v3 */ - ATH79_MACH_CPE610, /* TP-LINK CPE610 */ - ATH79_MACH_CPE830, /* YunCore CPE830 */ - ATH79_MACH_CPE870, /* YunCore CPE870 */ ---- a/target/linux/ar71xx/image/generic-tp-link.mk -+++ b/target/linux/ar71xx/image/generic-tp-link.mk -@@ -185,6 +185,14 @@ define Device/cpe510-v2 - endef - TARGET_DEVICES += cpe510-v2 - -+define Device/cpe510-v3 -+ $(Device/cpe510-520-v1) -+ DEVICE_TITLE := TP-LINK CPE510 v3 -+ BOARDNAME := CPE510V3 -+ TPLINK_BOARD_ID := CPE510V2 -+endef -+TARGET_DEVICES += cpe510-v3 -+ - define Device/cpe210-220-v1 - $(Device/cpe510-520-v1) - DEVICE_TITLE := TP-LINK CPE210/220 v1 ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -375,7 +375,17 @@ static struct device_info boards[] = { - "CPE510(TP-LINK|US|N300-5|55530000):2.0\r\n" - "CPE510(TP-LINK|UN|N300-5):2.0\r\n" - "CPE510(TP-LINK|EU|N300-5):2.0\r\n" -- "CPE510(TP-LINK|US|N300-5):2.0\r\n", -+ "CPE510(TP-LINK|US|N300-5):2.0\r\n" -+ "CPE510(TP-LINK|EU|N300-5|00000000):3.0\r\n" -+ "CPE510(TP-LINK|EU|N300-5|45550000):3.0\r\n" -+ "CPE510(TP-LINK|EU|N300-5|55530000):3.0\r\n" -+ "CPE510(TP-LINK|UN|N300-5|00000000):3.0\r\n" -+ "CPE510(TP-LINK|UN|N300-5|45550000):3.0\r\n" -+ "CPE510(TP-LINK|UN|N300-5|55530000):3.0\r\n" -+ "CPE510(TP-LINK|US|N300-5|55530000):3.0\r\n" -+ "CPE510(TP-LINK|UN|N300-5):3.0\r\n" -+ "CPE510(TP-LINK|EU|N300-5):3.0\r\n" -+ "CPE510(TP-LINK|US|N300-5):3.0\r\n", - .support_trail = '\xff', - .soft_ver = NULL, - diff --git a/patches/001-add_support_for_TP-Link_CPE610_v1.patch b/patches/001-add_support_for_TP-Link_CPE610_v1.patch deleted file mode 100644 index ae648746..00000000 --- a/patches/001-add_support_for_TP-Link_CPE610_v1.patch +++ /dev/null @@ -1,198 +0,0 @@ ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -598,6 +598,7 @@ platform_check_image() { - tplink_pharos_check_image "$1" "01000000" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 - return 1 - ;; -+ cpe610|\ - cpe510-v2) - tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 - return 1 ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -1,3 +1,4 @@ -+ - /* - Copyright (c) 2014, Matthias Schiffer - All rights reserved. -@@ -257,6 +258,46 @@ static struct device_info boards[] = { - .support_trail = '\xff', - .soft_ver = NULL, - -+ .partitions = { -+ {"fs-uboot", 0x00000, 0x20000}, -+ {"partition-table", 0x20000, 0x02000}, -+ {"default-mac", 0x30000, 0x00020}, -+ {"product-info", 0x31100, 0x00100}, -+ {"signature", 0x32000, 0x00400}, -+ {"os-image", 0x40000, 0x200000}, -+ {"file-system", 0x240000, 0x570000}, -+ {"soft-version", 0x7b0000, 0x00100}, -+ {"support-list", 0x7b1000, 0x00400}, -+ {"user-config", 0x7c0000, 0x10000}, -+ {"default-config", 0x7d0000, 0x10000}, -+ {"log", 0x7e0000, 0x10000}, -+ {"radio", 0x7f0000, 0x10000}, -+ {NULL, 0, 0} -+ }, -+ -+ .first_sysupgrade_partition = "os-image", -+ .last_sysupgrade_partition = "support-list", -+ }, -+ -+ /** Firmware layout for the CPE610 */ -+ { -+ .id = "CPE610", -+ .vendor = "CPE610(TP-LINK|UN|N300-5|00000000):1.0\r\n", -+ .support_list = -+ "SupportList:\r\n" -+ "CPE610(TP-LINK|EU|N300-5|00000000):1.0\r\n" -+ "CPE610(TP-LINK|EU|N300-5|45550000):1.0\r\n" -+ "CPE610(TP-LINK|EU|N300-5|55530000):1.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5|00000000):1.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5|45550000):1.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5|55530000):1.0\r\n" -+ "CPE610(TP-LINK|US|N300-5|55530000):1.0\r\n" -+ "CPE610(TP-LINK|UN|N300-5):1.0\r\n" -+ "CPE610(TP-LINK|EU|N300-5):1.0\r\n" -+ "CPE610(TP-LINK|US|N300-5):1.0\r\n", -+ .support_trail = '\xff', -+ .soft_ver = NULL, -+ - .partitions = { - {"fs-uboot", 0x00000, 0x20000}, - {"partition-table", 0x20000, 0x02000}, ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -@@ -125,6 +125,18 @@ static struct gpio_led cpe210_v2_leds_gp - }, - }; - -+static struct gpio_led cpe610_leds_gpio[] __initdata = { -+ { -+ .name = "tp-link:green:lan0", -+ .gpio = CPE510_GPIO_LED_LAN0, -+ .active_low = 1, -+ }, { -+ .name = "tp-link:green:link1", -+ .gpio = CPE510_GPIO_LED_L1, -+ .active_low = 1, -+ }, -+}; -+ - static struct gpio_keys_button cpe510_gpio_keys[] __initdata = { - { - .desc = "Reset button", -@@ -259,6 +271,39 @@ static void __init cpe510_v2_setup(void) - ath79_register_wmac(ee, mac); - } - -+static void __init cpe610_setup(void) -+{ -+ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); -+ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); -+ -+ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ -+ ath79_setup_ar933x_phy4_switch(false, false); -+ -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe610_leds_gpio), -+ cpe610_leds_gpio); -+ ath79_register_gpio_keys_polled(-1, CPE510_KEYS_POLL_INTERVAL, -+ ARRAY_SIZE(cpe510_gpio_keys), -+ cpe510_gpio_keys); -+ ath79_register_m25p80(NULL); -+ ath79_register_mdio(1, 0x0); -+ /* WAN */ -+ ath79_switch_data.phy4_mii_en = 1; -+ ath79_switch_data.phy_poll_mask = BIT(4); -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; -+ ath79_eth0_data.phy_mask = BIT(4); -+ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; -+ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); -+ ath79_register_eth(0); -+ /* LAN */ -+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; -+ ath79_eth1_data.duplex = DUPLEX_FULL; -+ ath79_eth1_data.speed = SPEED_1000; -+ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); -+ ath79_register_eth(1); -+ -+ ath79_register_wmac(ee, mac); -+} -+ - MIPS_MACHINE(ATH79_MACH_CPE210, "CPE210", "TP-LINK CPE210/220", - cpe210_setup); - -@@ -274,6 +319,9 @@ MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510" - MIPS_MACHINE(ATH79_MACH_CPE510_V2, "CPE510V2", "TP-LINK CPE510 v2", - cpe510_v2_setup); - -+MIPS_MACHINE(ATH79_MACH_CPE610, "CPE610", "TP-LINK CPE610", -+ cpe610_setup); -+ - MIPS_MACHINE(ATH79_MACH_WBS210, "WBS210", "TP-LINK WBS210", - wbs_setup); - ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -770,6 +770,10 @@ ar71xx_board_detect() { - name="cpe510-v2" - tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" - ;; -+ *"CPE610") -+ name="cpe610" -+ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" -+ ;; - *"CPE830") - name="cpe830" - ;; ---- a/target/linux/ar71xx/image/generic-tp-link.mk -+++ b/target/linux/ar71xx/image/generic-tp-link.mk -@@ -223,6 +223,14 @@ define Device/cpe210-v3 - endef - TARGET_DEVICES += cpe210-v3 - -+define Device/cpe610-v1 -+ $(Device/cpe510-520-v1) -+ DEVICE_TITLE := TP-LINK CPE610 -+ BOARDNAME := CPE610 -+ TPLINK_BOARD_ID := CPE610 -+endef -+TARGET_DEVICES += cpe610-v1 -+ - define Device/wbs210-v1 - $(Device/cpe510-520-v1) - DEVICE_TITLE := TP-LINK WBS210 v1 ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -276,6 +276,10 @@ wbs510) - ;; - esac - ;; -+cpe610) -+ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan0" "eth0" -+ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:link1" "wlan0" -+ ;; - cr3000) - ucidef_set_led_netdev "wan" "WAN" "pcs:blue:wan" "eth1" - ucidef_set_led_switch "lan1" "LAN1" "pcs:blue:lan1" "switch0" "0x04" ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -74,6 +74,7 @@ ar71xx_setup_interfaces() - cap4200ag|\ - cf-e380ac-v1|\ - cf-e380ac-v2|\ -+ cpe610|\ - cpe210-v2|\ - cpe210-v3|\ - cpe510-v2|\ ---- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -+++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -@@ -80,6 +80,7 @@ enum ath79_mach_type { - ATH79_MACH_CPE505N, /* P&W CPE505N */ - ATH79_MACH_CPE510, /* TP-LINK CPE510 */ - ATH79_MACH_CPE510_V2, /* TP-LINK CPE510 v2 */ -+ ATH79_MACH_CPE610, /* TP-LINK CPE610 */ - ATH79_MACH_CPE830, /* YunCore CPE830 */ - ATH79_MACH_CPE870, /* YunCore CPE870 */ - ATH79_MACH_CR3000, /* PowerCloud Systems CR3000 */ diff --git a/patches/001-add_support_for_TP-Link_WBS510_v2.patch b/patches/001-add_support_for_TP-Link_WBS510_v2.patch deleted file mode 100644 index b2dd7daa..00000000 --- a/patches/001-add_support_for_TP-Link_WBS510_v2.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 7bda7f94da2ba8ded6326c48b5feb1a0bd50aa47 Mon Sep 17 00:00:00 2001 -From: Andrew Cameron -Date: Sun, 17 Nov 2019 19:40:42 -0600 -Subject: [PATCH] ar71xx: add Support for the TP-LINK WBS510 V2.0 Device - -This adds support for a popular low-cost 5GHz N based AP - -Specifications: -- SoC: Atheros AR9344 -- RAM: 64MB -- Storage: 8 MB SPI NOR -- Wireless: 5GHz 300 Mbps, 2x RP-SMA connector, 27 dBm TX power -- Ethernet: 1x 10/100 Mbps with 24V POE IN, 1x 10/100 Mbps - -Installation: -Flash factory image through stock firmware WEB UI -or through TFTP -To get to TFTP recovery just hold reset button while powering on for -around 4-5 seconds and release. -Rename factory image to recovery.bin -Stock TFTP server IP:192.168.0.100 -Stock device TFTP adress:192.168.0.254 - -Signed-off-by: Andrew Cameron ---- - target/linux/ar71xx/base-files/etc/board.d/01_leds | 3 +- - .../linux/ar71xx/base-files/etc/board.d/02_network | 3 +- - .../ar71xx/base-files/etc/board.d/03_gpio_switches | 3 +- - target/linux/ar71xx/base-files/lib/ar71xx.sh | 4 +++ - .../ar71xx/base-files/lib/upgrade/platform.sh | 3 +- - .../ar71xx/files/arch/mips/ath79/mach-cpe510.c | 3 ++ - .../linux/ar71xx/files/arch/mips/ath79/machtypes.h | 1 + - target/linux/ar71xx/image/generic-tp-link.mk | 8 ++++++ - tools/firmware-utils/src/tplink-safeloader.c | 33 ++++++++++++++++++++++ - 9 files changed, 57 insertions(+), 4 deletions(-) - ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -260,7 +260,8 @@ cpe510|\ - cpe510-v2|\ - cpe510-v3|\ - wbs210|\ --wbs510) -+wbs510|\ -+wbs510-v2) - ucidef_set_rssimon "wlan0" "200000" "1" - ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:link1" "wlan0" "1" "100" "0" "13" - ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:link2" "wlan0" "26" "100" "-25" "13" ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -294,7 +294,8 @@ ar71xx_setup_interfaces() - cpe220-v3|\ - cpe510|\ - wbs210|\ -- wbs510) -+ wbs510|\ -+ wbs510-v2) - ucidef_add_switch "switch0" \ - "0@eth0" "5:lan" "4:wan" - ;; ---- a/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches -+++ b/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches -@@ -14,7 +14,8 @@ cpe210|\ - cpe220-v3|\ - cpe510|\ - wbs210|\ --wbs510) -+wbs510|\ -+wbs510-v2) - ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "20" - ;; - nanostation-m) ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -1472,6 +1472,10 @@ ar71xx_board_detect() { - name="wbs510" - tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" - ;; -+ *"WBS510 v2") -+ name="wbs510-v2" -+ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" -+ ;; - "WeIO"*) - name="weio" - ;; ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -602,7 +602,8 @@ platform_check_image() { - cpe220-v2|\ - cpe610|\ - cpe510-v2|\ -- cpe510-v3) -+ cpe510-v3|\ -+ wbs510-v2) - tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 - return 1 - ;; ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c -@@ -357,3 +357,6 @@ MIPS_MACHINE(ATH79_MACH_WBS210, "WBS210" - - MIPS_MACHINE(ATH79_MACH_WBS510, "WBS510", "TP-LINK WBS510", - wbs_setup); -+ -+MIPS_MACHINE(ATH79_MACH_WBS510_V2, "WBS510V2", "TP-LINK WBS510 v2", -+ wbs_setup); ---- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -+++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -@@ -348,6 +348,7 @@ enum ath79_mach_type { - ATH79_MACH_WAM250, /* Samsung WAM250 */ - ATH79_MACH_WBS210, /* TP-LINK WBS210 */ - ATH79_MACH_WBS510, /* TP-LINK WBS510 */ -+ ATH79_MACH_WBS510_V2, /* TP-LINK WBS510 v2*/ - ATH79_MACH_WEIO, /* WeIO board */ - ATH79_MACH_WHR_G301N, /* Buffalo WHR-G301N */ - ATH79_MACH_WHR_HP_G300N, /* Buffalo WHR-HP-G300N */ ---- a/target/linux/ar71xx/image/generic-tp-link.mk -+++ b/target/linux/ar71xx/image/generic-tp-link.mk -@@ -271,6 +271,14 @@ define Device/wbs510-v1 - endef - TARGET_DEVICES += wbs510-v1 - -+define Device/wbs510-v2 -+ $(Device/cpe510-520-v1) -+ DEVICE_TITLE := TP-LINK WBS510 v2 -+ BOARDNAME := WBS510V2 -+ TPLINK_BOARD_ID := WBS510V2 -+endef -+TARGET_DEVICES += wbs510-v2 -+ - define Device/eap120-v1 - DEVICE_TITLE := TP-LINK EAP120 v1 - MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,1536k(kernel),14336k(rootfs),192k(config)ro,64k(ART)ro,15872k@0x40000(firmware) ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -484,6 +484,39 @@ static struct device_info boards[] = { - .last_sysupgrade_partition = "support-list", - }, - -+ { -+ .id = "WBS510V2", -+ .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n", -+ .support_list = -+ "SupportList:\r\n" -+ "WBS510(TP-LINK|UN|N300-5|00000000):2.0\r\n" -+ "WBS510(TP-LINK|US|N300-5|55530000):2.0\r\n" -+ "WBS510(TP-LINK|EU|N300-5|45550000):2.0\r\n" -+ "WBS510(TP-LINK|CA|N300-5|43410000):2.0\r\n", -+ .support_trail = '\xff', -+ .soft_ver = NULL, -+ -+ .partitions = { -+ {"fs-uboot", 0x00000, 0x20000}, -+ {"partition-table", 0x20000, 0x02000}, -+ {"default-mac", 0x30000, 0x00020}, -+ {"product-info", 0x31100, 0x00100}, -+ {"signature", 0x32000, 0x00400}, -+ {"os-image", 0x40000, 0x1c0000}, -+ {"file-system", 0x200000, 0x5b0000}, -+ {"soft-version", 0x7b0000, 0x00100}, -+ {"support-list", 0x7b1000, 0x00400}, -+ {"user-config", 0x7c0000, 0x10000}, -+ {"default-config", 0x7d0000, 0x10000}, -+ {"log", 0x7e0000, 0x10000}, -+ {"radio", 0x7f0000, 0x10000}, -+ {NULL, 0, 0} -+ }, -+ -+ .first_sysupgrade_partition = "os-image", -+ .last_sysupgrade_partition = "support-list", -+ }, -+ - /** Firmware layout for the C2600 */ - { - .id = "C2600", diff --git a/patches/001-ath79-cpe220v3-sysupgrade-supported.patch b/patches/001-ath79-cpe220v3-sysupgrade-supported.patch index b935f425..c7901975 100644 --- a/patches/001-ath79-cpe220v3-sysupgrade-supported.patch +++ b/patches/001-ath79-cpe220v3-sysupgrade-supported.patch @@ -1,6 +1,6 @@ --- a/target/linux/ath79/image/generic-tp-link.mk +++ b/target/linux/ath79/image/generic-tp-link.mk -@@ -217,6 +217,7 @@ define Device/tplink_cpe220-v3 +@@ -312,6 +312,7 @@ define Device/tplink_cpe220-v3 DEVICE_PACKAGES := rssileds TPLINK_BOARD_ID := CPE220V3 LOADER_TYPE := elf diff --git a/patches/001-ath79-cpexxx_lna.patch b/patches/001-ath79-cpexxx_lna.patch deleted file mode 100644 index 5c769273..00000000 --- a/patches/001-ath79-cpexxx_lna.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/target/linux/ath79/dts/ar9344_tplink_cpe.dtsi -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe.dtsi -@@ -110,3 +110,20 @@ - - mtd-mac-address = <&info 0x8>; - }; -+ -+&gpio { -+ gpio_ext_lna0 { -+ gpio-hog; -+ gpios = <18 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "tp-link:ext:lna0"; -+ }; -+ -+ -+ gpio_ext_lna1 { -+ gpio-hog; -+ gpios = <19 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "tp-link:ext:lna1"; -+ }; -+}; ---- a/target/linux/ath79/dts/ar9344_tplink_cpe_2port.dtsi -+++ b/target/linux/ath79/dts/ar9344_tplink_cpe_2port.dtsi -@@ -44,21 +44,6 @@ - }; - }; - --&gpio { -- gpio_ext_lna0 { -- gpio-hog; -- gpios = <18 0>; -- output-high; -- line-name = "tp-link:ext:lna0"; -- }; -- -- gpio_ext_lna1 { -- gpio-hog; -- gpios = <19 0>; -- output-high; -- line-name = "tp-link:ext:lna1"; -- }; --}; - - ð1 { - status = "okay"; diff --git a/patches/001-ath79-reverse-wpad-basic-wolfssl.patch b/patches/001-ath79-reverse-wpad-basic-wolfssl.patch new file mode 100644 index 00000000..9f0b58d6 --- /dev/null +++ b/patches/001-ath79-reverse-wpad-basic-wolfssl.patch @@ -0,0 +1,55 @@ +--- a/target/linux/ath79/generic/target.mk ++++ b/target/linux/ath79/generic/target.mk +@@ -1,6 +1,6 @@ + BOARDNAME:=Generic + +-DEFAULT_PACKAGES += wpad-basic-wolfssl ++DEFAULT_PACKAGES += wpad-mini + + define Target/Description + Build firmware images for generic Atheros AR71xx/AR913x/AR934x based boards. +--- a/target/linux/ath79/mikrotik/target.mk ++++ b/target/linux/ath79/mikrotik/target.mk +@@ -3,7 +3,7 @@ FEATURES += minor nand + KERNELNAME := vmlinux vmlinuz + IMAGES_DIR := ../../.. + +-DEFAULT_PACKAGES += wpad-basic-wolfssl ++DEFAULT_PACKAGES += wpad-mini + + define Target/Description + Build firmware images for MikroTik devices based on Qualcomm Atheros +--- a/target/linux/ath79/nand/target.mk ++++ b/target/linux/ath79/nand/target.mk +@@ -2,7 +2,7 @@ BOARDNAME := Generic devices with NAND f + + FEATURES += nand + +-DEFAULT_PACKAGES += wpad-basic-wolfssl ++DEFAULT_PACKAGES += wpad-mini + + define Target/Description + Firmware for boards using Qualcomm Atheros, MIPS-based SoCs +--- a/target/linux/ath79/tiny/target.mk ++++ b/target/linux/ath79/tiny/target.mk +@@ -1,7 +1,7 @@ + BOARDNAME:=Devices with small flash + FEATURES += small_flash + +-DEFAULT_PACKAGES += wpad-basic-wolfssl ++DEFAULT_PACKAGES += wpad-mini + + define Target/Description + Build firmware images for Atheros AR71xx/AR913x/AR934x based boards with small flash + +--- a/target/linux/ipq40xx/Makefile ++++ b/target/linux/ipq40xx/Makefile +@@ -17,7 +17,7 @@ + DEFAULT_PACKAGES += \ + kmod-usb-dwc3-qcom \ + kmod-leds-gpio kmod-gpio-button-hotplug swconfig \ +- kmod-ath10k-ct wpad-basic-wolfssl \ ++ kmod-ath10k-ct wpad-mini \ + kmod-usb3 kmod-usb-dwc3 ath10k-firmware-qca4019-ct \ + uboot-envtools + diff --git a/patches/001_cpe220v3_bugfix.patch b/patches/001_cpe220v3_bugfix.patch deleted file mode 100644 index 6477264a..00000000 --- a/patches/001_cpe220v3_bugfix.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- a/tools/firmware-utils/src/tplink-safeloader.c -+++ b/tools/firmware-utils/src/tplink-safeloader.c -@@ -313,10 +313,10 @@ static struct device_info boards[] = { - {"default-mac", 0x30000, 0x00020}, - {"product-info", 0x31100, 0x00100}, - {"signature", 0x32000, 0x00400}, -- {"os-image", 0x40000, 0x200000}, -- {"file-system", 0x240000, 0x570000}, -+ {"device-id", 0x33000, 0x00100}, -+ {"firmware", 0x40000, 0x770000}, - {"soft-version", 0x7b0000, 0x00100}, -- {"support-list", 0x7b1000, 0x00400}, -+ {"support-list", 0x7b1000, 0x01000}, - {"user-config", 0x7c0000, 0x10000}, - {"default-config", 0x7d0000, 0x10000}, - {"log", 0x7e0000, 0x10000}, diff --git a/patches/004-add-ldf-5nd.patch b/patches/004-add-ldf-5nd.patch deleted file mode 100644 index 38012a40..00000000 --- a/patches/004-add-ldf-5nd.patch +++ /dev/null @@ -1,76 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -693,7 +693,8 @@ rb-2011uias-2hnd-r2) - ucidef_set_led_switch "eth10" "ETH10" "rb:green:eth10" "switch1" "0x02" - ;; - rb-lhg-5nd|\ --rb-lhg-5hpnd-xl) -+rb-lhg-5hpnd-xl|\ -+rb-ldf-5nd) - ucidef_set_led_netdev "lan" "LAN" "rb:green:eth" "eth0" - ucidef_set_rssimon "wlan0" "200000" "1" - ucidef_set_led_rssi "rssilow" "RSSILOW" "rb:green:rssi0" "wlan0" "1" "100" "0" "13" ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -115,6 +115,7 @@ ar71xx_setup_interfaces() - rb-922uags-5hpacd|\ - rb-lhg-5nd|\ - rb-lhg-5hpnd-xl|\ -+ rb-ldf-5nd|\ - rb-mapl-2nd|\ - rb-sxt2n|\ - rb-sxt-2nd-r3|\ ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -380,6 +380,7 @@ get_status_led() { - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ - rb-lhg-5hpnd-xl|\ -+ rb-ldf-5nd|\ - rb-map-2nd|\ - rb-mapl-2nd|\ - rb-sxt-2nd-r3|\ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -528,6 +528,12 @@ mikrotik_board_detect() { - *"LHG 5HPnD-XL") - name="rb-lhg-5hpnd-xl" - ;; -+ *"LDF-5nD") -+ name="rb-ldf-5nd" -+ ;; -+ *"RBLDF-5nD") -+ name="rb-ldf-5nd" -+ ;; - *"mAP 2nD"|\ - *"mAP2nD") - name="rb-map-2nd" ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -729,6 +729,7 @@ platform_check_image() { - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ - rb-lhg-5hpnd-xl|\ -+ rb-ldf-5nd|\ - rb-map-2nd|\ - rb-mapl-2nd|\ - rb-sxt-2nd-r3|\ -@@ -759,6 +760,7 @@ platform_pre_upgrade() { - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ - rb-lhg-5hpnd-xl|\ -+ rb-ldf-5nd|\ - rb-map-2nd|\ - rb-mapl-2nd|\ - rb-sxt-2nd-r3|\ ---- a/target/linux/ar71xx/image/mikrotik.mk -+++ b/target/linux/ar71xx/image/mikrotik.mk -@@ -46,7 +46,7 @@ define Device/rb-nor-flash-16M - DEVICE_PACKAGES := rbcfg rssileds -nand-utils kmod-ledtrig-gpio - IMAGE_SIZE := 16000k - KERNEL_INSTALL := 1 -- SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-lhg-5hpnd-xl rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 -+ SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-lhg-5hpnd-xl rb-ldf-5nd rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 - IMAGE/sysupgrade.bin := append-kernel | kernel2minor -s 1024 -e | pad-to $$$$(BLOCKSIZE) | \ - append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) - endef diff --git a/patches/004-add-lhg-5hpnd-xl.patch b/patches/004-add-lhg-5hpnd-xl.patch deleted file mode 100644 index 2acbd4fd..00000000 --- a/patches/004-add-lhg-5hpnd-xl.patch +++ /dev/null @@ -1,73 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -692,7 +692,8 @@ rb-2011uias-2hnd-r2) - ucidef_set_led_switch "eth9" "ETH9" "rb:green:eth9" "switch1" "0x04" - ucidef_set_led_switch "eth10" "ETH10" "rb:green:eth10" "switch1" "0x02" - ;; --rb-lhg-5nd) -+rb-lhg-5nd|\ -+rb-lhg-5hpnd-xl) - ucidef_set_led_netdev "lan" "LAN" "rb:green:eth" "eth0" - ucidef_set_rssimon "wlan0" "200000" "1" - ucidef_set_led_rssi "rssilow" "RSSILOW" "rb:green:rssi0" "wlan0" "1" "100" "0" "13" ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -114,6 +114,7 @@ ar71xx_setup_interfaces() - rb-921gs-5hpacd-r2|\ - rb-922uags-5hpacd|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd-xl|\ - rb-mapl-2nd|\ - rb-sxt2n|\ - rb-sxt-2nd-r3|\ ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -379,6 +379,7 @@ get_status_led() { - rb-952ui-5ac2nd|\ - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd-xl|\ - rb-map-2nd|\ - rb-mapl-2nd|\ - rb-sxt-2nd-r3|\ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -525,6 +525,9 @@ mikrotik_board_detect() { - *"LHG 5nD") - name="rb-lhg-5nd" - ;; -+ *"LHG 5HPnD-XL") -+ name="rb-lhg-5hpnd-xl" -+ ;; - *"mAP 2nD"|\ - *"mAP2nD") - name="rb-map-2nd" ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -728,6 +728,7 @@ platform_check_image() { - rb-952ui-5ac2nd|\ - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd-xl|\ - rb-map-2nd|\ - rb-mapl-2nd|\ - rb-sxt-2nd-r3|\ -@@ -757,6 +758,7 @@ platform_pre_upgrade() { - rb-952ui-5ac2nd|\ - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd-xl|\ - rb-map-2nd|\ - rb-mapl-2nd|\ - rb-sxt-2nd-r3|\ ---- a/target/linux/ar71xx/image/mikrotik.mk -+++ b/target/linux/ar71xx/image/mikrotik.mk -@@ -46,7 +46,7 @@ define Device/rb-nor-flash-16M - DEVICE_PACKAGES := rbcfg rssileds -nand-utils kmod-ledtrig-gpio - IMAGE_SIZE := 16000k - KERNEL_INSTALL := 1 -- SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 -+ SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-lhg-5hpnd-xl rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 - IMAGE/sysupgrade.bin := append-kernel | kernel2minor -s 1024 -e | pad-to $$$$(BLOCKSIZE) | \ - append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) - endef diff --git a/patches/005-add-haplite-new-model.patch b/patches/005-add-haplite-new-model.patch deleted file mode 100644 index 615edb43..00000000 --- a/patches/005-add-haplite-new-model.patch +++ /dev/null @@ -1,14 +0,0 @@ -Index: openwrt/target/linux/ar71xx/base-files/lib/ar71xx.sh -=================================================================== ---- openwrt.orig/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ openwrt/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -519,6 +519,9 @@ mikrotik_board_detect() { - *"952Ui-5ac2nD") - name="rb-952ui-5ac2nd" - ;; -+ *"RB952Ui-5ac2nD") -+ name="rb-952ui-5ac2nd" -+ ;; - *"962UiGS-5HacT2HnT") - name="rb-962uigs-5hact2hnt" - ;; diff --git a/patches/006-add-lhg-5hpnd.patch b/patches/006-add-lhg-5hpnd.patch deleted file mode 100644 index 61a61020..00000000 --- a/patches/006-add-lhg-5hpnd.patch +++ /dev/null @@ -1,80 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -693,6 +693,7 @@ rb-2011uias-2hnd-r2) - ucidef_set_led_switch "eth10" "ETH10" "rb:green:eth10" "switch1" "0x02" - ;; - rb-lhg-5nd|\ -+rb-lhg-5hpnd|\ - rb-lhg-5hpnd-xl|\ - rb-ldf-5nd) - ucidef_set_led_netdev "lan" "LAN" "rb:green:eth" "eth0" ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -114,6 +114,7 @@ ar71xx_setup_interfaces() - rb-921gs-5hpacd-r2|\ - rb-922uags-5hpacd|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd|\ - rb-lhg-5hpnd-xl|\ - rb-ldf-5nd|\ - rb-mapl-2nd|\ ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -379,6 +379,7 @@ get_status_led() { - rb-952ui-5ac2nd|\ - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd|\ - rb-lhg-5hpnd-xl|\ - rb-ldf-5nd|\ - rb-map-2nd|\ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -525,9 +525,13 @@ mikrotik_board_detect() { - *"962UiGS-5HacT2HnT") - name="rb-962uigs-5hact2hnt" - ;; -+ *"LHG-5nD"|\ - *"LHG 5nD") - name="rb-lhg-5nd" - ;; -+ *"LHG 5HPnD") -+ name="rb-lhg-5hpnd" -+ ;; - *"LHG 5HPnD-XL") - name="rb-lhg-5hpnd-xl" - ;; -@@ -566,6 +570,12 @@ mikrotik_board_detect() { - *"wAPG-5HacT2HnD") - name="rb-wapg-5hact2hnd" - ;; -+ *"RBLHG-5HPnD") -+ name="rb-lhg-5hpnd" -+ ;; -+ *"RBLHG-2nD") -+ name="rb-lhg-5nd" -+ ;; - esac - - echo "$name" ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -728,6 +728,7 @@ platform_check_image() { - rb-952ui-5ac2nd|\ - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd|\ - rb-lhg-5hpnd-xl|\ - rb-ldf-5nd|\ - rb-map-2nd|\ ---- a/target/linux/ar71xx/image/mikrotik.mk -+++ b/target/linux/ar71xx/image/mikrotik.mk -@@ -46,7 +46,7 @@ define Device/rb-nor-flash-16M - DEVICE_PACKAGES := rbcfg rssileds -nand-utils kmod-ledtrig-gpio - IMAGE_SIZE := 16000k - KERNEL_INSTALL := 1 -- SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-lhg-5hpnd-xl rb-ldf-5nd rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 -+ SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-lhg-5hpnd rb-lhg-5hpnd-xl rb-ldf-5nd rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 - IMAGE/sysupgrade.bin := append-kernel | kernel2minor -s 1024 -e | pad-to $$$$(BLOCKSIZE) | \ - append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) - endef diff --git a/patches/006-rocket-m-flash-fix.patch b/patches/006-rocket-m-flash-fix.patch new file mode 100644 index 00000000..4cfbdb3b --- /dev/null +++ b/patches/006-rocket-m-flash-fix.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/target/linux/generic/backport-5.10/420-spansion-flash.patch +@@ -0,0 +1,12 @@ ++--- a/drivers/mtd/spi-nor/spansion.c +++++ b/drivers/mtd/spi-nor/spansion.c ++@@ -83,8 +83,7 @@ ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, ++- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +++ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) }, ++ { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) }, diff --git a/patches/007-fix-sysupgrade-fail.patch b/patches/007-fix-sysupgrade-fail.patch deleted file mode 100644 index 78f2dedc..00000000 --- a/patches/007-fix-sysupgrade-fail.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Jeff Kletsky - -Wifi can, in certain situations, cause sysupgrade to fail silently -with a 256 return value as all processes can't be killed. -One of these situations is mesh with batman-adv active. - -Added `wifi down` just prior to the killall sequence in stage2 - -Run-tested-on: Linksys EA8300 - -Signed-off-by: Jeff Kletsky ---- -package/base-files/files/lib/upgrade/stage2 | 4 ++++ -1 file changed, 4 insertions(+) - -Index: openwrt/package/base-files/files/lib/upgrade/stage2 -=================================================================== ---- openwrt.orig/package/base-files/files/lib/upgrade/stage2 -+++ openwrt/package/base-files/files/lib/upgrade/stage2 -@@ -123,6 +123,10 @@ kill_remaining KILL 1 - - sleep 1 - -+if [ -x "$(which wifi)" ]; then -+ wifi down -+ sleep 1 -+fi - - if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then - platform_pre_upgrade "$IMAGE" diff --git a/patches/008-add-lhg.patch b/patches/008-add-lhg.patch deleted file mode 100644 index 23faf33f..00000000 --- a/patches/008-add-lhg.patch +++ /dev/null @@ -1,83 +0,0 @@ -Index: openwrt/target/linux/ar71xx/base-files/lib/ar71xx.sh -=================================================================== ---- openwrt.orig/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ openwrt/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -529,12 +529,31 @@ mikrotik_board_detect() { - *"LHG 5nD") - name="rb-lhg-5nd" - ;; -+ *"LHG 2nD") -+ name="rb-lhg-5nd" -+ ;; -+ *"RBLHG 2nD") -+ name="rb-lhg-5nd" -+ ;; - *"LHG 5HPnD") - name="rb-lhg-5hpnd" - ;; - *"LHG 5HPnD-XL") - name="rb-lhg-5hpnd-xl" - ;; -+ *"LHG-2nD-XL"|\ -+ *"LHG 2nD-XL") -+ name="rb-lhg-5hpnd-xl" -+ ;; -+ *"RBLHG 2nD-XL") -+ name="rb-lhg-5hpnd-xl" -+ ;; -+ *"LDF-2nD") -+ name="rb-lhg-5nd" -+ ;; -+ *"RBLDF-2nD") -+ name="rb-lhg-5nd" -+ ;; - *"LDF-5nD") - name="rb-ldf-5nd" - ;; -Index: openwrt/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c -=================================================================== ---- openwrt.orig/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c -+++ openwrt/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c -@@ -13,7 +13,10 @@ - * - MikroTik RouterBOARD 750UP r2 - * - MikroTik RouterBOARD 750P-PBr2 - * - MikroTik RouterBOARD 750 r2 -+ * - MikroTik RouterBOARD LHG 2nD - * - MikroTik RouterBOARD LHG 5nD -+ * - MikroTik RouterBOARD LDF 2nD -+ * - MikroTik RouterBOARD LDF 2nD-XL - * - MikroTik RouterBOARD wAP2nD - * - MikroTik RouterBOARD wAP G-5HacT2HnDwAP (wAP AC) - * - MikroTik RouterBOARD wAP R-2nD -@@ -1254,6 +1257,7 @@ MIPS_MACHINE_NONAME(ATH79_MACH_RB_952, " - MIPS_MACHINE_NONAME(ATH79_MACH_RB_962, "962", rb962_setup); - MIPS_MACHINE_NONAME(ATH79_MACH_RB_750UPR2, "750-hb", rb750upr2_setup); - MIPS_MACHINE_NONAME(ATH79_MACH_RB_LHG5, "lhg", rblhg_setup); -+MIPS_MACHINE_NONAME(ATH79_MACH_RB_LHG2, "lhg-hb", rblhg_setup); - MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAP, "wap-hb", rbwap_setup); - MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAPR, "wap-lte", rbwapr_setup); - MIPS_MACHINE_NONAME(ATH79_MACH_RB_CAP, "cap-hb", rbcap_setup); -Index: openwrt/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -=================================================================== ---- openwrt.orig/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -+++ openwrt/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h -@@ -230,6 +230,7 @@ enum ath79_mach_type { - ATH79_MACH_RB_962, /* MikroTik RouterBOARD 962UiGS-5HacT2HnT */ - ATH79_MACH_RB_CAP, /* Mikrotik RouterBOARD cAP2nD */ - ATH79_MACH_RB_LHG5, /* Mikrotik RouterBOARD LHG5 */ -+ ATH79_MACH_RB_LHG2, /* Mikrotik RouterBOARD LHG2 */ - ATH79_MACH_RB_MAP, /* Mikrotik RouterBOARD mAP2nD */ - ATH79_MACH_RB_MAPL, /* Mikrotik RouterBOARD mAP L-2nD */ - ATH79_MACH_RB_WAP, /* Mikrotik RouterBOARD wAP2nD */ -Index: openwrt/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -=================================================================== ---- openwrt.orig/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ openwrt/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -760,6 +760,7 @@ platform_pre_upgrade() { - rb-952ui-5ac2nd|\ - rb-962uigs-5hact2hnt|\ - rb-lhg-5nd|\ -+ rb-lhg-5hpnd|\ - rb-lhg-5hpnd-xl|\ - rb-ldf-5nd|\ - rb-map-2nd|\ diff --git a/patches/009-add-sxtsq.patch b/patches/009-add-sxtsq.patch deleted file mode 100644 index fe45aeb5..00000000 --- a/patches/009-add-sxtsq.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -577,6 +577,20 @@ mikrotik_board_detect() { - *"SXT Lite5") - name="rb-sxt5n" - ;; -+ *"SXTsq5nD"|\ -+ *"SXTsq 5nD") -+ name="rb-lhg-5nd" -+ ;; -+ *"SXTsq 2nD") -+ name="rb-lhg-5nd" -+ ;; -+ *"RBSXTsq2nD") -+ name="rb-lhg-5nd" -+ ;; -+ *"SXTsq 5HPnD"|\ -+ *"SXTsq5HPnD") -+ name="rb-lhg-5hpnd" -+ ;; - *"wAP 2nD r2"|\ - *"wAP 2nD r3") - name="rb-wap-2nd" diff --git a/patches/700-cpe-diags.patch b/patches/700-cpe-diags.patch deleted file mode 100644 index 8c4b3627..00000000 --- a/patches/700-cpe-diags.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -164,9 +164,20 @@ get_status_led() { - cf-e385ac) - status_led="$board:blue:wlan2g" - ;; -+ cpe210-v2|\ -+ cpe210-v3|\ -+ cpe220-v2|\ -+ cpe220-v3|\ -+ cpe510-v2|\ -+ cpe510-v3|\ -+ cpe210|\ -+ wbs510-v2|\ - cpe510) - status_led="tp-link:green:link4" - ;; -+ cpe610) -+ status_led="tp-link:green:link1" -+ ;; - cr3000|\ - cr5000) - status_led="pcs:amber:power" diff --git a/patches/701-extended-spectrum.patch b/patches/701-extended-spectrum.patch index faf22c4b..9fc3cad4 100644 --- a/patches/701-extended-spectrum.patch +++ b/patches/701-extended-spectrum.patch @@ -1,180 +1,157 @@ --- /dev/null +++ b/package/kernel/mac80211/patches/ath/301-extended-spectrum.patch -@@ -0,0 +1,174 @@ -+Index: a/drivers/net/wireless/ath/ath9k/hw.h -+=================================================================== +@@ -0,0 +1,151 @@ ++--- a/drivers/net/wireless/ath/ath9k/common-init.c +++++ b/drivers/net/wireless/ath/ath9k/common-init.c ++39a40,41 ++> CHAN2G(2397, 39), /* Channel -2 */ ++> CHAN2G(2402, 38), /* Channel -1 */ ++70a73,99 ++> /* _We_ claim this "For the HAMS" */ ++> CHAN5G(5370, 40), /* Channel 74 */ ++> CHAN5G(5375, 41), /* Channel 75 */ ++> CHAN5G(5380, 42), /* Channel 76 */ ++> CHAN5G(5385, 43), /* Channel 77 */ ++> CHAN5G(5390, 44), /* Channel 78 */ ++> CHAN5G(5395, 45), /* Channel 79 */ ++> CHAN5G(5400, 46), /* Channel 80 */ ++> CHAN5G(5405, 47), /* Channel 81 */ ++> CHAN5G(5410, 48), /* Channel 82 */ ++> CHAN5G(5415, 49), /* Channel 83 */ ++> CHAN5G(5420, 50), /* Channel 84 */ ++> CHAN5G(5425, 51), /* Channel 85 */ ++> CHAN5G(5430, 52), /* Channel 86 */ ++> CHAN5G(5435, 53), /* Channel 87 */ ++> CHAN5G(5440, 54), /* Channel 88 */ ++> CHAN5G(5445, 55), /* Channel 89 */ ++> CHAN5G(5450, 56), /* Channel 90 */ ++> CHAN5G(5455, 57), /* Channel 91 */ ++> CHAN5G(5460, 58), /* Channel 92 */ ++> CHAN5G(5465, 59), /* Channel 93 */ ++> CHAN5G(5470, 60), /* Channel 94 */ ++> CHAN5G(5475, 61), /* Channel 95 */ ++> CHAN5G(5480, 62), /* Channel 96 */ ++> CHAN5G(5485, 63), /* Channel 97 */ ++> CHAN5G(5490, 64), /* Channel 98 */ ++> CHAN5G(5495, 65), /* Channel 99 */ ++88a118,164 ++> /* _We_ claim this "For the HAMS" x2 */ ++> CHAN5G(5655, 66), /* Channel 131 */ ++> CHAN5G(5665, 67), /* Channel 133 */ ++> CHAN5G(5670, 68), /* Channel 134 */ ++> CHAN5G(5675, 69), /* Channel 135 */ ++> CHAN5G(5685, 70), /* Channel 137 */ ++> CHAN5G(5690, 71), /* Channel 138 */ ++> CHAN5G(5695, 72), /* Channel 139 */ ++> CHAN5G(5705, 73), /* Channel 141 */ ++> CHAN5G(5710, 74), /* Channel 142 */ ++> CHAN5G(5715, 75), /* Channel 143 */ ++> CHAN5G(5720, 76), /* Channel 144 */ ++> CHAN5G(5725, 77), /* Channel 145 */ ++> CHAN5G(5730, 78), /* Channel 146 */ ++> CHAN5G(5735, 79), /* Channel 147 */ ++> CHAN5G(5740, 80), /* Channel 148 */ ++> CHAN5G(5750, 81), /* Channel 150 */ ++> CHAN5G(5755, 82), /* Channel 151 */ ++> CHAN5G(5760, 83), /* Channel 152 */ ++> CHAN5G(5770, 84), /* Channel 154 */ ++> CHAN5G(5775, 85), /* Channel 155 */ ++> CHAN5G(5780, 86), /* Channel 156 */ ++> CHAN5G(5790, 87), /* Channel 158 */ ++> CHAN5G(5795, 88), /* Channel 159 */ ++> CHAN5G(5800, 89), /* Channel 160 */ ++> CHAN5G(5810, 90), /* Channel 162 */ ++> CHAN5G(5815, 91), /* Channel 163 */ ++> CHAN5G(5820, 92), /* Channel 164 */ ++> CHAN5G(5830, 93), /* Channel 166 */ ++> CHAN5G(5835, 94), /* Channel 167 */ ++> CHAN5G(5840, 95), /* Channel 168 */ ++> CHAN5G(5845, 96), /* Channel 169 */ ++> CHAN5G(5850, 97), /* Channel 170 */ ++> CHAN5G(5855, 98), /* Channel 171 */ ++> CHAN5G(5860, 99), /* Channel 172 */ ++> CHAN5G(5865, 100), /* Channel 173 */ ++> CHAN5G(5870, 101), /* Channel 174 */ ++> CHAN5G(5875, 102), /* Channel 175 */ ++> CHAN5G(5880, 103), /* Channel 176 */ ++> CHAN5G(5885, 104), /* Channel 177 */ ++> CHAN5G(5890, 105), /* Channel 178 */ ++> CHAN5G(5895, 106), /* Channel 179 */ ++> CHAN5G(5900, 107), /* Channel 180 */ ++> CHAN5G(5905, 108), /* Channel 181 */ ++> CHAN5G(5910, 109), /* Channel 182 */ ++> CHAN5G(5915, 110), /* Channel 183 */ ++> CHAN5G(5920, 111), /* Channel 184 */ +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h -+@@ -74,7 +74,7 @@ ++@@ -71,7 +71,7 @@ + + #define ATH9K_RSSI_BAD -128 + +-#define ATH9K_NUM_CHANNELS 38 -++#define ATH9K_NUM_CHANNELS 114 +++#define ATH9K_NUM_CHANNELS 112 + + /* Register read/write primitives */ + #define REG_WRITE(_ah, _reg, _val) \ -+Index: a/drivers/net/wireless/ath/regd.c -+=================================================================== +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c -+@@ -34,6 +34,7 @@ static struct reg_dmn_pair_mapping *ath_ ++@@ -33,6 +33,7 @@ + */ + + /* Only these channels all allow active scan on all world regulatory domains */ -++#define ATH9K_2GHZ_CHN02_00 REG_RULE(2387-10, 2407+10, 40, 0, 20, 0) -+ #define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) +++#define ATH_2GHZ_CHN02_00 REG_RULE(2392-5, 2407+10, 40, 0, 20, 0) ++ #define ATH_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + + /* We enable active scan on these a case by case basis by regulatory domain */ -+@@ -47,17 +48,25 @@ static struct reg_dmn_pair_mapping *ath_ -+ #define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ -+ REG_RULE(5260-10, 5350+10, 80, 0, 30,\ ++@@ -45,17 +46,24 @@ ++ /* We allow IBSS on these on a case by case basis by regulatory domain */ ++ #define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) -++#define ATH9K_5GHZ_5320_5490 REG_RULE(5320-10, 5490+10, 80, 0, 30,\ +++#define ATH_5GHZ_5320_5490 REG_RULE(5320-10, 5490+10, 80, 0, 30,\ ++ NL80211_RRF_NO_IR) -+ #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ ++ #define ATH_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) -+ #define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ ++ #define ATH_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) -++#define ATH9K_5GHZ_5850_5925 REG_RULE(5850-10, 5925+5, 80, 0, 30,\ +++#define ATH_5GHZ_5850_5925 REG_RULE(5850-10, 5925+5, 80, 0, 30,\ ++ NL80211_RRF_NO_IR) -++ + -+-#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ -++#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CHN02_00, \ -++ ATH9K_2GHZ_CH01_11, \ -+ ATH9K_2GHZ_CH12_13, \ -+ ATH9K_2GHZ_CH14 ++-#define ATH_2GHZ_ALL ATH_2GHZ_CH01_11, \ +++#define ATH_2GHZ_ALL ATH_2GHZ_CHN02_00, \ +++ ATH_2GHZ_CH01_11, \ ++ ATH_2GHZ_CH12_13, \ ++ ATH_2GHZ_CH14 + -+ #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ -+- ATH9K_5GHZ_5470_5850 -++ ATH9K_5GHZ_5320_5490, \ -++ ATH9K_5GHZ_5470_5850, \ -++ ATH9K_5GHZ_5850_5925 ++ #define ATH_5GHZ_ALL ATH_5GHZ_5150_5350, \ ++- ATH_5GHZ_5470_5850 +++ ATH_5GHZ_5320_5490, \ +++ ATH_5GHZ_5470_5850, \ +++ ATH_5GHZ_5850_5925 + + /* This one skips what we call "mid band" */ -+ #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ -+Index: a/net/wireless/util.c -+=================================================================== ++ #define ATH_5GHZ_NO_MIDBAND ATH_5GHZ_5150_5350, \ +--- a/net/wireless/util.c ++++ b/net/wireless/util.c -+@@ -76,13 +76,16 @@ int ieee80211_channel_to_frequency(int c ++@@ -80,13 +80,18 @@ + return 0; /* not supported */ + switch (band) { + case NL80211_BAND_2GHZ: ++ chan = (int)(char)chan; + if (chan == 14) -+ return 2484; -++ else if (chan > 14) -++ return 2402 - (255 - chan) * 5; ++ return MHZ_TO_KHZ(2484); +++ else if (chan == 255) +++ return MHZ_TO_KHZ(2402); +++ else if (chan == 254) +++ return MHZ_TO_KHZ(2397); + else if (chan < 14) -+ return 2407 + chan * 5; ++ return MHZ_TO_KHZ(2407 + chan * 5); + break; + case NL80211_BAND_5GHZ: +- if (chan >= 182 && chan <= 196) ++ if (chan >= 187 && chan <= 196) -+ return 4000 + chan * 5; ++ return MHZ_TO_KHZ(4000 + chan * 5); + else -+ return 5000 + chan * 5; -+Index: a/drivers/net/wireless/ath/ath9k/common-init.c -+=================================================================== -+--- a/drivers/net/wireless/ath/ath9k/common-init.c -++++ b/drivers/net/wireless/ath/ath9k/common-init.c -+*************** -+*** 37,42 **** -+--- 37,46 ---- -+ * we have calibration data for all cards though to make -+ * this static */ -+ static const struct ieee80211_channel ath9k_2ghz_chantable[] = { -++ CHAN2G(2387, 38), /* Channel -4 */ -++ CHAN2G(2392, 39), /* Channel -3 */ -++ CHAN2G(2397, 40), /* Channel -2 */ -++ CHAN2G(2402, 41), /* Channel -1 */ -+ CHAN2G(2412, 0), /* Channel 1 */ -+ CHAN2G(2417, 1), /* Channel 2 */ -+ CHAN2G(2422, 2), /* Channel 3 */ -+*************** static const struct ieee80211_channel at -+*** 68,73 **** -+--- 72,150 ---- -+ CHAN5G(5280, 19), /* Channel 56 */ -+ CHAN5G(5300, 20), /* Channel 60 */ -+ CHAN5G(5320, 21), /* Channel 64 */ -++ /* Added "For the HAMS" */ -++ CHAN5G(5370, 42), /* Channel 74 */ -++ CHAN5G(5375, 43), /* Channel 75 */ -++ CHAN5G(5380, 44), /* Channel 76 */ -++ CHAN5G(5385, 45), /* Channel 77 */ -++ CHAN5G(5390, 46), /* Channel 78 */ -++ CHAN5G(5395, 47), /* Channel 79 */ -++ CHAN5G(5400, 48), /* Channel 80 */ -++ CHAN5G(5405, 49), /* Channel 81 */ -++ CHAN5G(5410, 50), /* Channel 82 */ -++ CHAN5G(5415, 51), /* Channel 83 */ -++ CHAN5G(5420, 52), /* Channel 84 */ -++ CHAN5G(5425, 53), /* Channel 85 */ -++ CHAN5G(5430, 54), /* Channel 86 */ -++ CHAN5G(5435, 55), /* Channel 87 */ -++ CHAN5G(5440, 56), /* Channel 88 */ -++ CHAN5G(5445, 57), /* Channel 89 */ -++ CHAN5G(5450, 58), /* Channel 90 */ -++ CHAN5G(5455, 59), /* Channel 91 */ -++ CHAN5G(5460, 60), /* Channel 92 */ -++ CHAN5G(5465, 61), /* Channel 93 */ -++ CHAN5G(5470, 62), /* Channel 94 */ -++ CHAN5G(5475, 63), /* Channel 95 */ -++ CHAN5G(5480, 64), /* Channel 96 */ -++ CHAN5G(5485, 65), /* Channel 97 */ -++ CHAN5G(5490, 66), /* Channel 98 */ -++ CHAN5G(5495, 67), /* Channel 99 */ -++ CHAN5G(5655, 68), /* Channel 131 */ -++ CHAN5G(5665, 69), /* Channel 133 */ -++ CHAN5G(5670, 70), /* Channel 134 */ -++ CHAN5G(5675, 71), /* Channel 135 */ -++ CHAN5G(5685, 72), /* Channel 137 */ -++ CHAN5G(5690, 73), /* Channel 138 */ -++ CHAN5G(5695, 74), /* Channel 139 */ -++ CHAN5G(5705, 75), /* Channel 141 */ -++ CHAN5G(5710, 76), /* Channel 142 */ -++ CHAN5G(5715, 77), /* Channel 143 */ -++ CHAN5G(5720, 78), /* Channel 144 */ -++ CHAN5G(5725, 79), /* Channel 145 */ -++ CHAN5G(5730, 80), /* Channel 146 */ -++ CHAN5G(5735, 81), /* Channel 147 */ -++ CHAN5G(5740, 82), /* Channel 148 */ -++ CHAN5G(5750, 83), /* Channel 150 */ -++ CHAN5G(5755, 84), /* Channel 151 */ -++ CHAN5G(5760, 85), /* Channel 152 */ -++ CHAN5G(5770, 86), /* Channel 154 */ -++ CHAN5G(5775, 87), /* Channel 155 */ -++ CHAN5G(5780, 88), /* Channel 156 */ -++ CHAN5G(5790, 89), /* Channel 158 */ -++ CHAN5G(5795, 90), /* Channel 159 */ -++ CHAN5G(5800, 91), /* Channel 160 */ -++ CHAN5G(5810, 92), /* Channel 162 */ -++ CHAN5G(5815, 93), /* Channel 163 */ -++ CHAN5G(5820, 94), /* Channel 164 */ -++ CHAN5G(5830, 95), /* Channel 166 */ -++ CHAN5G(5835, 96), /* Channel 167 */ -++ CHAN5G(5840, 97), /* Channel 168 */ -++ CHAN5G(5845, 98), /* Channel 169 */ -++ CHAN5G(5850, 99), /* Channel 170 */ -++ CHAN5G(5855, 100), /* Channel 171 */ -++ CHAN5G(5860, 101), /* Channel 172 */ -++ CHAN5G(5865, 102), /* Channel 173 */ -++ CHAN5G(5870, 103), /* Channel 174 */ -++ CHAN5G(5875, 104), /* Channel 175 */ -++ CHAN5G(5880, 105), /* Channel 176 */ -++ CHAN5G(5885, 106), /* Channel 177 */ -++ CHAN5G(5890, 107), /* Channel 178 */ -++ CHAN5G(5895, 108), /* Channel 179 */ -++ CHAN5G(5900, 109), /* Channel 180 */ -++ CHAN5G(5905, 110), /* Channel 181 */ -++ CHAN5G(5910, 111), /* Channel 182 */ -++ CHAN5G(5915, 112), /* Channel 183 */ -++ CHAN5G(5920, 113), /* Channel 184 */ -+ /* _We_ call this "Middle band" */ -+ CHAN5G(5500, 22), /* Channel 100 */ -+ CHAN5G(5520, 23), /* Channel 104 */ ++ return MHZ_TO_KHZ(5000 + chan * 5); --- /dev/null +++ b/package/network/utils/iw/patches/300-extended_spectrum.patch @@ -0,0 +1,39 @@ @@ -294,3 +271,104 @@ + return (channel * 5) + 5000; + } + +--- /dev/null ++++ b/package/kernel/ath10k-ct/patches/999-0000-ath10k-part97-chan-extend.patch +@@ -0,0 +1,98 @@ ++--- a/ath10k-5.15/core.h +++++ b/ath10k-5.15/core.h ++@@ -49,8 +49,8 @@ ++ #define WMI_READY_TIMEOUT (5 * HZ) ++ #define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ) ++ #define ATH10K_CONNECTION_LOSS_HZ (3 * HZ) ++-#define ATH10K_NUM_CHANS 41 ++-#define ATH10K_MAX_5G_CHAN 173 +++#define ATH10K_NUM_CHANS 86 +++#define ATH10K_MAX_5G_CHAN 184 ++ ++ /* Antenna noise floor */ ++ #define ATH10K_DEFAULT_NOISE_FLOOR -95 ++--- a/ath10k-5.15/mac.c +++++ b/ath10k-5.15/mac.c ++@@ -9089,6 +9089,8 @@ ++ } ++ ++ static const struct ieee80211_channel ath10k_2ghz_channels[] = { +++ CHAN2G(254, 2397, 0), +++ CHAN2G(255, 2402, 0), ++ CHAN2G(1, 2412, 0), ++ CHAN2G(2, 2417, 0), ++ CHAN2G(3, 2422, 0), ++@@ -9122,17 +9124,60 @@ ++ CHAN5G(120, 5600, 0), ++ CHAN5G(124, 5620, 0), ++ CHAN5G(128, 5640, 0), +++ CHAN5G(131, 5655, 0), ++ CHAN5G(132, 5660, 0), +++ CHAN5G(133, 5665, 0), +++ CHAN5G(134, 5670, 0), +++ CHAN5G(135, 5675, 0), ++ CHAN5G(136, 5680, 0), +++ CHAN5G(137, 5685, 0), +++ CHAN5G(138, 5690, 0), +++ CHAN5G(139, 5695, 0), ++ CHAN5G(140, 5700, 0), +++ CHAN5G(141, 5705, 0), +++ CHAN5G(142, 5710, 0), +++ CHAN5G(143, 5715, 0), ++ CHAN5G(144, 5720, 0), +++ CHAN5G(145, 5725, 0), +++ CHAN5G(146, 5730, 0), +++ CHAN5G(147, 5735, 0), +++ CHAN5G(148, 5740, 0), ++ CHAN5G(149, 5745, 0), +++ CHAN5G(150, 5750, 0), +++ CHAN5G(151, 5755, 0), +++ CHAN5G(152, 5760, 0), ++ CHAN5G(153, 5765, 0), +++ CHAN5G(154, 5770, 0), +++ CHAN5G(155, 5775, 0), +++ CHAN5G(156, 5780, 0), ++ CHAN5G(157, 5785, 0), +++ CHAN5G(158, 5790, 0), +++ CHAN5G(159, 5795, 0), +++ CHAN5G(160, 5800, 0), ++ CHAN5G(161, 5805, 0), +++ CHAN5G(162, 5810, 0), +++ CHAN5G(163, 5815, 0), +++ CHAN5G(164, 5820, 0), ++ CHAN5G(165, 5825, 0), +++ CHAN5G(166, 5830, 0), +++ CHAN5G(167, 5835, 0), +++ CHAN5G(168, 5840, 0), ++ CHAN5G(169, 5845, 0), +++ CHAN5G(170, 5850, 0), +++ CHAN5G(171, 5855, 0), +++ CHAN5G(172, 5860, 0), ++ CHAN5G(173, 5865, 0), +++ CHAN5G(174, 5870, 0), +++ CHAN5G(175, 5875, 0), +++ CHAN5G(176, 5880, 0), +++ CHAN5G(177, 5885, 0), +++ CHAN5G(178, 5890, 0), +++ CHAN5G(179, 5895, 0), +++ CHAN5G(180, 5900, 0), +++ CHAN5G(181, 5905, 0), +++ CHAN5G(182, 5910, 0), +++ CHAN5G(183, 5915, 0), +++ CHAN5G(184, 5920, 0), ++ /* If you add more, you may need to change ATH10K_MAX_5G_CHAN */ ++ /* And you will definitely need to change ATH10K_NUM_CHANS in core.h */ ++ }; ++--- a/ath10k-5.15/wmi.h +++++ b/ath10k-5.15/wmi.h ++@@ -3355,6 +3355,10 @@ ++ ++ /* passively scan all channels including active channels */ ++ #define WMI_SCAN_FLAG_PASSIVE 0x1 +++/** set HALF (10MHz) rate support */ +++#define WMI_SCAN_FLAG_HALF_RATE_SUPPORT 0x20000 +++/** set Quarter (5MHz) rate support */ +++#define WMI_SCAN_FLAG_QUARTER_RATE_SUPPORT 0x40000 ++ /* add wild card ssid probe request even though ssid_list is specified. */ ++ #define WMI_SCAN_ADD_BCAST_PROBE_REQ 0x2 ++ /* add cck rates to rates/xrate ie for the generated probe request */ diff --git a/patches/703-disable-ipv6-dnsmasq.patch b/patches/703-disable-ipv6-dnsmasq.patch new file mode 100644 index 00000000..bea0f141 --- /dev/null +++ b/patches/703-disable-ipv6-dnsmasq.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/package/network/services/dnsmasq/patches/110.disable-ipv6.patch +@@ -0,0 +1,12 @@ ++--- a/src/config.h +++++ b/src/config.h ++@@ -170,7 +170,7 @@ ++ has no library dependencies other than libc */ ++ ++ #define HAVE_DHCP ++-#define HAVE_DHCP6 +++/* #define HAVE_DHCP6 */ ++ #define HAVE_TFTP ++ #define HAVE_SCRIPT ++ #define HAVE_AUTH ++ diff --git a/patches/703-fix-dnsmasq.patch b/patches/703-fix-dnsmasq.patch index 3395c815..1e063334 100644 --- a/patches/703-fix-dnsmasq.patch +++ b/patches/703-fix-dnsmasq.patch @@ -1,18 +1,14 @@ -Index: openwrt/package/base-files/files/etc/rc.local -=================================================================== ---- openwrt.orig/package/base-files/files/etc/rc.local -+++ openwrt/package/base-files/files/etc/rc.local +--- a/package/base-files/files/etc/rc.local ++++ b/package/base-files/files/etc/rc.local @@ -1,4 +1,4 @@ # Put your custom commands here that should be executed once # the system init finished. By default this file does nothing. - +/etc/init.d/dnsmasq start exit 0 -Index: openwrt/package/network/services/dnsmasq/Makefile -=================================================================== ---- openwrt.orig/package/network/services/dnsmasq/Makefile -+++ openwrt/package/network/services/dnsmasq/Makefile -@@ -165,7 +165,7 @@ define Package/dnsmasq/install +--- a/package/network/services/dnsmasq/Makefile ++++ b/package/network/services/dnsmasq/Makefile +@@ -167,7 +167,7 @@ define Package/dnsmasq/install $(INSTALL_CONF) ./files/dhcp.conf $(1)/etc/config/dhcp $(INSTALL_CONF) ./files/dnsmasq.conf $(1)/etc/dnsmasq.conf $(INSTALL_DIR) $(1)/etc/init.d @@ -21,11 +17,9 @@ Index: openwrt/package/network/services/dnsmasq/Makefile $(INSTALL_DIR) $(1)/etc/hotplug.d/dhcp $(INSTALL_DIR) $(1)/etc/hotplug.d/neigh $(INSTALL_DIR) $(1)/etc/hotplug.d/ntp -Index: openwrt/package/network/services/dnsmasq/files/dnsmasq.init.aredn -=================================================================== --- /dev/null -+++ openwrt/package/network/services/dnsmasq/files/dnsmasq.init.aredn -@@ -0,0 +1,640 @@ ++++ b/package/network/services/dnsmasq/files/dnsmasq.init.aredn +@@ -0,0 +1,641 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2007-2012 OpenWrt.org + @@ -652,6 +646,7 @@ Index: openwrt/package/network/services/dnsmasq/files/dnsmasq.init.aredn + for DNS_SERVER in $DNS_SERVERS ; do + echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf + done ++ ln -sf /tmp/resolv.conf.d/resolv.conf.auto /tmp/resolv.conf.auto +} + +reload_service() { diff --git a/patches/704-enable-telnet.patch b/patches/704-enable-telnet.patch index 931de62e..f94b0b0f 100644 --- a/patches/704-enable-telnet.patch +++ b/patches/704-enable-telnet.patch @@ -1,18 +1,25 @@ --- a/package/base-files/files/lib/preinit/99_10_failsafe_login +++ b/package/base-files/files/lib/preinit/99_10_failsafe_login -@@ -3,8 +3,7 @@ +@@ -1,6 +1,10 @@ + # Copyright (C) 2006-2015 OpenWrt.org # Copyright (C) 2010 Vertical Communications - failsafe_netlogin () { -- dropbearkey -t rsa -s 1024 -f /tmp/dropbear_failsafe_host_key -- dropbear -r /tmp/dropbear_failsafe_host_key <> /dev/null 2>&1 ++failsafe_netlogin () { + telnetd -l /bin/login.sh <> /dev/null 2>&1 ++} ++ + failsafe_shell() { + local console="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | head -1 | sed -e 's/^console=//' -e 's/,.*//')" + [ -n "$console" ] || console=console +@@ -11,4 +15,5 @@ failsafe_shell() { + done & } - failsafe_shell() { ++boot_hook_add failsafe failsafe_netlogin + boot_hook_add failsafe failsafe_shell --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in -@@ -2480,10 +2480,10 @@ config BUSYBOX_DEFAULT_UDPSVD +@@ -2552,10 +2552,10 @@ config BUSYBOX_DEFAULT_UDPSVD default n config BUSYBOX_DEFAULT_TELNET bool @@ -25,7 +32,7 @@ config BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN bool default n -@@ -2492,10 +2492,10 @@ config BUSYBOX_DEFAULT_FEATURE_TELNET_WI +@@ -2564,10 +2564,10 @@ config BUSYBOX_DEFAULT_FEATURE_TELNET_WI default n config BUSYBOX_DEFAULT_TELNETD bool @@ -35,14 +42,14 @@ bool - default n + default y - config BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT - bool - default n + config BUSYBOX_DEFAULT_FEATURE_TELNETD_PORT_DEFAULT + int + default 23 --- a/package/utils/busybox/Makefile +++ b/package/utils/busybox/Makefile -@@ -110,6 +110,8 @@ define Package/busybox/install - ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_CROND),) +@@ -148,6 +148,8 @@ ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_C $(INSTALL_BIN) ./files/cron $(1)/etc/init.d/cron + $(INSTALL_DIR) $(1)/etc/crontabs endif + $(INSTALL_BIN) ./files/telnet $(1)/etc/init.d/telnet + $(INSTALL_BIN) ./files/login.sh $(1)/bin/login.sh diff --git a/patches/705-aredn-banner.patch b/patches/705-aredn-banner.patch index 7baf7937..d4e7c352 100644 --- a/patches/705-aredn-banner.patch +++ b/patches/705-aredn-banner.patch @@ -1,7 +1,5 @@ -Index: openwrt/package/base-files/files/etc/banner -=================================================================== ---- openwrt.orig/package/base-files/files/etc/banner -+++ openwrt/package/base-files/files/etc/banner +--- a/package/base-files/files/etc/banner ++++ b/package/base-files/files/etc/banner @@ -1,8 +1,14 @@ - _______ ________ __ - | |.-----.-----.-----.| | | |.----.| |_ diff --git a/patches/706-MeshNode-SSID.patch b/patches/706-MeshNode-SSID.patch index e1ff2c1f..1f7ce543 100644 --- a/patches/706-MeshNode-SSID.patch +++ b/patches/706-MeshNode-SSID.patch @@ -1,8 +1,6 @@ -Index: openwrt/package/kernel/mac80211/files/lib/wifi/mac80211.sh -=================================================================== ---- openwrt.orig/package/kernel/mac80211/files/lib/wifi/mac80211.sh -+++ openwrt/package/kernel/mac80211/files/lib/wifi/mac80211.sh -@@ -106,6 +106,12 @@ detect_mac80211() { +--- a/package/kernel/mac80211/files/lib/wifi/mac80211.sh ++++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh +@@ -167,6 +167,12 @@ dev_id="set wireless.radio${devidx}.macaddr=$(cat /sys/class/ieee80211/${dev}/macaddress)" fi @@ -15,10 +13,10 @@ Index: openwrt/package/kernel/mac80211/files/lib/wifi/mac80211.sh uci -q batch <<-EOF set wireless.radio${devidx}=wifi-device set wireless.radio${devidx}.type=mac80211 -@@ -113,13 +119,12 @@ detect_mac80211() { - set wireless.radio${devidx}.hwmode=11${mode_band} - ${dev_id} - ${ht_capab} +@@ -174,13 +180,12 @@ + set wireless.radio${devidx}.channel=${channel} + set wireless.radio${devidx}.band=${mode_band} + set wireless.radio${devidx}.htmode=$htmode - set wireless.radio${devidx}.disabled=1 set wireless.default_radio${devidx}=wifi-iface diff --git a/patches/707-enable-board-name.patch b/patches/707-enable-board-name.patch deleted file mode 100644 index e87a5137..00000000 --- a/patches/707-enable-board-name.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -1663,3 +1663,11 @@ ar71xx_board_detect() { - echo "$AR71XX_BOARD_NAME" > /tmp/sysinfo/board_name - echo "$AR71XX_MODEL" > /tmp/sysinfo/model - } -+ar71xx_board_name() { -+ local name -+ -+ [ -f /tmp/sysinfo/board_name ] && name=$(cat /tmp/sysinfo/board_name) -+ [ -z "$name" ] && name="unknown" -+ -+ echo "$name" -+} diff --git a/patches/708-define-aredn-ath79-networks.patch b/patches/708-define-aredn-ath79-networks.patch new file mode 100644 index 00000000..fa4d0ca7 --- /dev/null +++ b/patches/708-define-aredn-ath79-networks.patch @@ -0,0 +1,326 @@ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -113,7 +113,9 @@ ath79_setup_interfaces() + ubnt,unifi|\ + wd,mynet-wifi-rangeextender|\ + winchannel,wb2000) +- ucidef_set_interface_lan "eth0" ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" + ;; + airtight,c-75) + ucidef_add_switch "switch0" \ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -130,7 +132,9 @@ ath79_setup_interfaces() + engenius,ews511ap|\ + ocedo,ursus|\ + ubnt,unifi-ap-outdoor-plus) +- ucidef_set_interface_lan "eth0 eth1" ++ ucidef_set_interfaces_lan_wan "eth0 eth1" "eth0.1 eth1.1" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" + ;; + atheros,db120) + ucidef_add_switch "switch0" \ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -165,6 +169,7 @@ ath79_setup_interfaces() + ;; + buffalo,bhr-4grv2|\ + trendnet,tew-823dru) ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ucidef_add_switch "switch0" \ + "0@eth1" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" "6@eth0" + ;; +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -180,7 +185,8 @@ ath79_setup_interfaces() + ubnt,airrouter) + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ +- "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" ++ "0@eth0" "1t:dummy" "1t:dtdlink" "4:lan" "3:lan" "2:lan" ++ ucidef_set_interface "wifi" device "wlan0" "protocol" "static" + ;; + buffalo,wzr-hp-g300nh-rb|\ + buffalo,wzr-hp-g300nh-s|\ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -214,7 +220,10 @@ ath79_setup_interfaces() + tplink,wbs510-v2|\ + ubnt,nanostation-m|\ + ubnt,routerstation) +- ucidef_set_interfaces_lan_wan "eth1" "eth0" ++ ucidef_set_interface_lan "eth0 eth1" ++ ucidef_set_interface_wan "eth0.1 eth1.1" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + comfast,cf-e375ac) + ucidef_add_switch "switch0" \ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -272,13 +281,15 @@ ath79_setup_interfaces() + tplink,tl-wr1043nd-v4|\ + tplink,tl-wr1043n-v5) + ucidef_add_switch "switch0" \ +- "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan" ++ "0@eth0" "5:wan" "1t:wan" "1t:dtdlink" "2:lan" "3:lan" "4:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + elecom,wrc-1750ghbk2-i|\ + elecom,wrc-300ghbk2-i|\ + sitecom,wlr-8100) + ucidef_add_switch "switch0" \ +- "0@eth0" "2:lan:4" "3:lan:3" "4:lan:2" "5:lan:1" "1:wan" ++ "0@eth0" "5t:wan" "1:wan" "5t:dtdlink" "2:lan" "3:lan" "4:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + embeddedwireless,balin) + ucidef_add_switch "switch0" \ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -303,7 +314,8 @@ ath79_setup_interfaces() + glinet,gl-ar750) + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ +- "0@eth0" "1:lan" "2:lan" ++ "0@eth0" "1:lan" "2t:dtdlink" ++ ucidef_set_interface "wifi" device "wlan1" protocol "static" + ;; + glinet,gl-x300b) + ucidef_set_interface_wan "eth1" +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -355,7 +367,8 @@ ath79_setup_interfaces() + tplink,tl-wdr4300-v1-il|\ + tplink,tl-wdr4310-v1) + ucidef_add_switch "switch0" \ +- "0@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "1:wan" ++ "0@eth0" "1:wan" "5t:wan" "5t:dtdlink" "2:lan" "3:lan" "4:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + nec,wf1200cr) + ucidef_set_interface_wan "eth1" +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -367,8 +380,6 @@ ath79_setup_interfaces() + qxwlan,e1700ac-v2-16m|\ + qxwlan,e750g-v8-8m|\ + qxwlan,e750g-v8-16m|\ +- ubnt,nanobeam-ac-gen2|\ +- ubnt,nanostation-ac|\ + yuncore,a782|\ + yuncore,xd3200|\ + yuncore,xd4200) +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -484,30 +495,38 @@ ath79_setup_interfaces() + ubnt,edgeswitch-5xp) + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ +- "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:lan" ++ "0@eth0" "1t:dummy" "1t:dtdlink" "2:lan" "3:lan" "4:lan" "5:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + ubnt,edgeswitch-8xp) + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ +- "0:lan:1" "1:lan:2" "2:lan:3" "3:lan:4" "4:lan:5" "5:lan:6" "6:lan:7" "7:lan:8" "8@eth0" ++ "8@eth0" "7:wan" "1t:dtdlink" "2:lan" "3:lan" "4:lan" "5:lan" "6:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + ubnt,routerstation-pro) + ucidef_set_interface_wan "eth0" + ucidef_add_switch "switch0" \ +- "0@eth1" "2:lan:3" "3:lan:2" "4:lan:1" ++ "0@eth1" "4t:dummy" "4t:dtdlink" "2:lan" "3:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; +- ubnt,nanostation-m-xw) +- ucidef_add_switch "switch0" \ +- "0@eth0" "5:lan" "1:wan" ++ ubnt,nanostation-m-xw|\ ++ ubnt,nanobeam-ac-gen2|\ ++ ubnt,nanostation-ac) ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + ubnt,unifiac-mesh-pro|\ + ubnt,unifiac-pro) + ucidef_add_switch "switch0" \ +- "0@eth0" "2:lan:1" "3:lan:2" ++ "0@eth0" "3t:wan" "3t:dtdlink" "2:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + ubnt,unifi-ap-pro) + ucidef_add_switch "switch0" \ +- "0@eth0" "1:lan" "2:lan" ++ "0@eth0" "3t:wan" "3t:dtdlink" "1:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + tplink,deco-m4r-v1) + ucidef_add_switch "switch0" \ +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -519,8 +538,15 @@ ath79_setup_interfaces() + ucidef_add_switch "switch0" \ + "0@eth0" "3:lan:1" "4:lan:2" + ;; ++ glinet,gl-ar150) ++ ucidef_set_interfaces_lan_wan "eth0 eth1" "eth0.1 eth1.1" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ;; + *) +- ucidef_set_interfaces_lan_wan "eth0" "eth1" ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + esac + } +--- a/target/linux/ath79/nand/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/nand/base-files/etc/board.d/02_network +@@ -9,7 +9,9 @@ ath79_setup_interfaces() + case "$board" in + aerohive,hiveap-121|\ + glinet,gl-e750) +- ucidef_set_interface_lan "eth0" ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + domywifi,dw33d) + ucidef_add_switch "switch0" \ +--- a/target/linux/ath79/nand/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/nand/base-files/etc/board.d/02_network +@@ -23,7 +25,8 @@ ath79_setup_interfaces() + glinet,gl-ar750s-nor|\ + glinet,gl-ar750s-nor-nand) + ucidef_add_switch "switch0" \ +- "0@eth0" "2:lan:2" "3:lan:1" "1:wan" ++ "0@eth0" "1:wan" "3t:dtdlink" "2:lan" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + glinet,gl-xe300) + ucidef_set_interface_wan "eth1" +--- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +@@ -19,6 +19,7 @@ + mikrotik,routerboard-lhg-5nd|\ + mikrotik,routerboard-mapl-2nd|\ + mikrotik,routerboard-sxt-5nd-r2|\ ++ mikrotik,routerboard-sxt-5nd|\ + mikrotik,routerboard-wap-2nd|\ + mikrotik,routerboard-wap-g-5hact2hnd|\ + mikrotik,routerboard-wapr-2nd) + +--- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +@@ -22,14 +22,21 @@ + mikrotik,routerboard-wap-2nd|\ + mikrotik,routerboard-wap-g-5hact2hnd|\ + mikrotik,routerboard-wapr-2nd) +- ucidef_set_interface_lan "eth0" ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; +- mikrotik,routerboard-951ui-2nd|\ +- mikrotik,routerboard-952ui-5ac2nd) ++ mikrotik,routerboard-951ui-2nd) + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ + "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" + ;; ++ mikrotik,routerboard-952ui-5ac2nd) ++ ucidef_set_interface_wan "eth1" ++ ucidef_set_interface "wifi" device "wlan1" protocol "static" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "4:lan:2" "3:lan:3" "2:lan:4" "1t:dtdlink:5" ++ ;; + mikrotik,routerboard-map-2nd) + ucidef_set_interface_lan "eth0 eth1" + ;; + +--- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +@@ -35,7 +37,9 @@ ath79_setup_interfaces() + "0@eth0" "2:lan" "3:lan" "4:lan" "5:lan" "1:wan" + ;; + *) +- ucidef_set_interfaces_lan_wan "eth0" "eth1" ++ ucidef_set_interfaces_lan_wan "eth0" "eth1.1" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + esac + } + +--- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +@@ -27,6 +27,12 @@ + ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" + ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; ++ mikrotik,routerboard-921gs-5hpacd-15s|\ ++ mikrotik,routerboard-921gs-5hpacd-19s) ++ ucidef_set_interfaces_lan_wan "eth0 eth1" "eth0.1 eth1.1" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ;; + mikrotik,routerboard-951ui-2nd) + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ + +--- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +@@ -67,6 +68,7 @@ + mikrotik,routerboard-map-2nd|\ + mikrotik,routerboard-mapl-2nd|\ + mikrotik,routerboard-sxt-5nd-r2|\ ++ mikrotik,routerboard-sxt-5nd|\ + mikrotik,routerboard-wap-2nd|\ + mikrotik,routerboard-wap-g-5hact2hnd|\ + mikrotik,routerboard-wapr-2nd) + +--- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +@@ -82,6 +82,7 @@ + lan_mac="$mac_base" + ;; + mikrotik,routerboard-921gs-5hpacd-15s|\ ++ mikrotik,routerboard-921gs-5hpacd-19s|\ + mikrotik,routerboard-922uags-5hpacd) + label_mac="$mac_base" + lan_mac="$mac_base" + +--- a/target/linux/ath79/tiny/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/tiny/base-files/etc/board.d/02_network +@@ -111,7 +111,10 @@ + "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" + ;; + ubnt,nanostation-m) +- ucidef_set_interfaces_lan_wan "eth1" "eth0" ++ ucidef_set_interface_lan "eth0 eth1" ++ ucidef_set_interface_wan "eth0.1 eth1.1" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + *) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + +--- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom ++++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +@@ -26,6 +26,7 @@ + mikrotik,routerboard-912uag-2hpnd|\ + mikrotik,routerboard-lhg-2nd|\ + mikrotik,routerboard-lhg-5nd|\ ++ mikrotik,routerboard-sxt-5nd|\ + mikrotik,routerboard-sxt-5nd-r2|\ + mikrotik,routerboard-wap-2nd|\ + mikrotik,routerboard-wapr-2nd) diff --git a/patches/708-define-aredn-ipq40xx-networks.patch b/patches/708-define-aredn-ipq40xx-networks.patch new file mode 100644 index 00000000..09096e66 --- /dev/null +++ b/patches/708-define-aredn-ipq40xx-networks.patch @@ -0,0 +1,36 @@ +--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network ++++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network +@@ -30,12 +30,16 @@ + engenius,emd1|\ + meraki,mr33|\ + mikrotik,lhgg-60ad|\ +- mikrotik,sxtsq-5-ac|\ + netgear,ex6100v2|\ + netgear,ex6150v2|\ + zyxel,wre6606) + ucidef_set_interface_lan "eth0" + ;; ++ mikrotik,sxtsq-5-ac) ++ ucidef_set_interfaces_lan_wan "lan" "lan.1" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ucidef_set_interface "dtdlink" device "lan.2" protocol "static" ++ ;; + aruba,ap-303h|\ + teltonika,rutx10) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + +--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network ++++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network +@@ -61,9 +61,9 @@ + p2w,r619ac-64m|\ + p2w,r619ac-128m|\ + zyxel,nbg6617) +- ucidef_set_interfaces_lan_wan "eth0" "eth1" +- ucidef_add_switch "switch0" \ +- "0u@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" ++ ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" ++ ucidef_set_interface "dtdlink" device "lan4.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + avm,fritzbox-4040|\ + linksys,ea6350v3|\ diff --git a/patches/708-define-aredn-leds-ar71xx.patch b/patches/708-define-aredn-leds-ar71xx.patch deleted file mode 100644 index c4e0f519..00000000 --- a/patches/708-define-aredn-leds-ar71xx.patch +++ /dev/null @@ -1,56 +0,0 @@ ---- a/target/linux/ar71xx/base-files/etc/board.d/01_leds -+++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds -@@ -18,6 +18,9 @@ a60) - ucidef_set_led_default "status-red" "Status (red)" "a60:red:status" "0" - ucidef_set_led_default "status-blue" "Status (blue)" "a60:blue:status" "0" - ;; -+airrouter) -+ ucidef_set_led_timer "user" "USER" "ubnt:green:globe" "1000" "1000" -+ ;; - airgateway|\ - airgatewaypro) - ucidef_set_led_wlan "wlan" "WLAN" "ubnt:blue:wlan" "phy0tpt" -@@ -93,7 +96,7 @@ ap531b0|\ - gl-usb150|\ - sc1750|\ - sc450) -- ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" -+ ucidef_set_led_timer "user" "USER" "$board:green:wlan" "1000" "1000" - ;; - ap91-5g|\ - n5q) -@@ -425,12 +428,12 @@ fritz450e) - ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" - ;; - gl-ar300m) -- ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" - ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" -+ ucidef_set_led_timer "user" "USER" "$board:red:wlan" "1000" "1000" - ;; - gl-ar750) - ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:white:wlan2g" "phy1tpt" -- ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:white:wlan5g" "phy0tpt" -+ ucidef_set_led_timer "user" "USER" "$board:white:wlan5g" "1000" "1000" - ;; - gl-ar750s) - ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2g" "phy1tpt" -@@ -443,7 +446,7 @@ gl-mifi) - ucidef_set_led_netdev "3gnet" "3GNET" "$board:green:net" "3g-wan" - ;; - gl-ar150) -- ucidef_set_led_wlan "wlan" "WLAN" "$board:orange:wlan" "phy0tpt" -+ ucidef_set_led_timer "user" "USER" "$board:orange:wlan" "1000" "1000" - ucidef_set_led_netdev "wan" "WAN" "$board:green:lan" "eth0" - ucidef_set_led_netdev "lan" "LAN" "$board:green:wan" "eth1" - ;; -@@ -661,6 +664,10 @@ rb-911-2hn|\ - rb-911-5hn) - ucidef_set_led_netdev "eth" "ETH" "rb:green:eth" "eth0" - ;; -+rb-911g-5hpnd|\ -+rb-912uag-5hpnd) -+ ucidef_set_led_timer "user" "USER" "rb:green:user" "1000" "1000" -+ ;; - rb-931-2nd|\ - rb-941-2nd) - ucidef_set_led_timer "user" "USR/ACT" "rb:green:user" "1000" "1000" diff --git a/patches/708-define-aredn-network-ath79.patch b/patches/708-define-aredn-network-ath79.patch deleted file mode 100644 index de459352..00000000 --- a/patches/708-define-aredn-network-ath79.patch +++ /dev/null @@ -1,71 +0,0 @@ ---- a/target/linux/ath79/base-files/etc/board.d/02_network -+++ b/target/linux/ath79/base-files/etc/board.d/02_network -@@ -58,6 +58,7 @@ ath79_setup_interfaces() - ubnt,nanostation-loco-m|\ - ubnt,nanostation-loco-m-xw|\ - ubnt,picostation-m|\ -+ ubnt,nanostation-m-xw|\ - ubnt,rocket-m|\ - ubnt,unifiac-lite|\ - ubnt,unifiac-lr|\ -@@ -65,7 +66,9 @@ ath79_setup_interfaces() - ubnt,unifi|\ - wd,mynet-wifi-rangeextender|\ - winchannel,wb2000) -- ucidef_set_interface_lan "eth0" -+ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interface "dtdlink" ifname "eth0.2" protocol "static" - ;; - avm,fritz4020|\ - pcs,cr3000|\ -@@ -110,8 +113,9 @@ ath79_setup_interfaces() - tplink,tl-wr941nd-v6|\ - ubnt,airrouter) - ucidef_set_interface_wan "eth1" -+ ucidef_set_interface "wifi" "ifname" "wlan0" "protocol" "static" - ucidef_add_switch "switch0" \ -- "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" -+ "0@eth0" "4:lan:1" "3:lan:2" "2:lan:3" "1t:unused" "1t:dtdlink" - ;; - buffalo,wzr-hp-g302h-a1a0) - ucidef_add_switch "switch0" \ -@@ -129,7 +133,10 @@ ath79_setup_interfaces() - tplink,cpe220-v3|\ - ubnt,nanostation-m|\ - ubnt,routerstation) -- ucidef_set_interfaces_lan_wan "eth1" "eth0" -+ ucidef_set_interface_lan "eth0 eth1" -+ ucidef_set_interface_wan "eth0.1 eth1.1" -+ ucidef_set_interface "dtdlink" ifname "eth0.2 eth1.2" protocol "static" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ;; - devolo,dvl1200e|\ - devolo,dvl1750e|\ -@@ -287,18 +294,21 @@ ath79_setup_interfaces() - ucidef_add_switch "switch0" \ - "0@eth1" "2:lan:3" "3:lan:2" "4:lan:1" - ;; -- ubnt,nanostation-m-xw) -- ucidef_add_switch "switch0" \ -- "0@eth0" "5:lan" "1:wan" -- ;; - zbtlink,zbt-wd323|\ - xiaomi,mi-router-4q) - ucidef_set_interface_wan "eth1" - ucidef_add_switch "switch0" \ - "0@eth0" "3:lan:1" "4:lan:2" - ;; -+ glinet,gl-ar150) -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interfaces_lan_wan "eth0" "eth1" -+ ucidef_set_interface "dtdlink" ifname "eth0.2" protocol "static" -+ ;; - *) -- ucidef_set_interfaces_lan_wan "eth0" "eth1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" -+ ucidef_set_interface "dtdlink" ifname "eth0.2" protocol "static" - ;; - esac - } diff --git a/patches/708-define-aredn-networks.patch b/patches/708-define-aredn-networks.patch deleted file mode 100644 index 19a96154..00000000 --- a/patches/708-define-aredn-networks.patch +++ /dev/null @@ -1,184 +0,0 @@ ---- a/package/base-files/files/lib/functions/uci-defaults.sh -+++ b/package/base-files/files/lib/functions/uci-defaults.sh -@@ -153,7 +153,7 @@ _ucidef_finish_switch_roles() { - - if [ ${need_tag:-0} -eq 1 -o ${want_untag:-0} -ne 1 ]; then - num="${num}t" -- device="${device}.${index}" -+ device="${device}.$((index - 1))" - fi - - json_select roles ---- a/package/base-files/files/bin/config_generate -+++ b/package/base-files/files/bin/config_generate -@@ -165,10 +165,11 @@ generate_switch_vlans_ports() { - json_get_vars ports - json_select .. - -+ vlan_num=$((role - 1)) - uci -q batch <<-EOF - add network switch_vlan - set network.@switch_vlan[-1].device='$switch' -- set network.@switch_vlan[-1].vlan='$role' -+ set network.@switch_vlan[-1].vlan='$vlan_num' - set network.@switch_vlan[-1].ports='$ports' - EOF - done ---- a/target/linux/ar71xx/base-files/etc/board.d/02_network -+++ b/target/linux/ar71xx/base-files/etc/board.d/02_network -@@ -12,8 +12,9 @@ ar71xx_setup_interfaces() - - case "$board" in - airgatewaypro) -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth0" "4:lan" "5:wan" -+ "0@eth0" "4:lan" "5t:wan" "5t:dtdlink" - ;; - airrouter|\ - ap121|\ -@@ -55,9 +56,10 @@ ar71xx_setup_interfaces() - whr-hp-gn|\ - wzr-hp-ag300h|\ - zbt-we1526) -- ucidef_set_interfaces_lan_wan "eth0.1" "eth1" -+ ucidef_set_interface_wan "eth1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" -+ "0@eth0" "4:lan:1" "3:lan:2" "2:lan:3" "1t:unused" "1t:dtdlink" - ;; - alfa-ap120c|\ - all0305|\ -@@ -101,6 +103,7 @@ ar71xx_setup_interfaces() - mr900|\ - mr900v2|\ - mynet-rext|\ -+ nanostation-m-xw|\ - pqi-air-pen|\ - rb-411|\ - rb-411u|\ -@@ -160,7 +163,9 @@ ar71xx_setup_interfaces() - wifi-pineapple-nano|\ - wndap360|\ - wp543) -- ucidef_set_interface_lan "eth0" -+ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interface "dtdlink" ifname "eth0.2" protocol "static" - ;; - a40|\ - a60|\ -@@ -186,6 +191,8 @@ ar71xx_setup_interfaces() - wpe72|\ - wrtnode2q) - ucidef_set_interfaces_lan_wan "eth1" "eth0" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interface "dtdlink" ifname "eth1.2" protocol "static" - ;; - all0258n|\ - all0315n|\ -@@ -194,7 +201,9 @@ ar71xx_setup_interfaces() - ja76pf2|\ - rocket-m-ti|\ - ubnt-unifi-outdoor) -- ucidef_set_interface_lan "eth0 eth1" -+ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interface "dtdlink" ifname "eth0.2" protocol "static" - ;; - wzr-hp-g300nh2) - ucidef_add_switch "switch0" \ -@@ -209,8 +218,9 @@ ar71xx_setup_interfaces() - rb-962uigs-5hact2hnt|\ - wlr8100|\ - wzr-hp-g450h) -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth0" "2:lan" "3:lan" "4:lan" "5:lan" "1:wan" -+ "0@eth0" "2:lan" "3:lan" "4:lan" "1:wan" "5t:dtdlink" - ;; - ap135-020|\ - ap136-020|\ -@@ -250,12 +260,18 @@ ar71xx_setup_interfaces() - rb-750-r2|\ - rb-750p-pbr2|\ - rb-750up-r2|\ -- rb-951ui-2nd|\ -- rb-952ui-5ac2nd) -- ucidef_set_interfaces_lan_wan "eth1.1" "eth0" -+ rb-951ui-2nd) -+ ucidef_set_interface_wan "eth0" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth1" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" -+ "0@eth1" "1:lan:4" "2:lan:3" "3:lan:2" "4t:unused" "4t:dtdlink" - ;; -+ rb-952ui-5ac2nd) -+ ucidef_set_interface_wan "eth0" -+ ucidef_set_interface "wifi" ifname "wlan1" protocol "static" -+ ucidef_add_switch "switch0" \ -+ "0@eth1" "4:lan:1" "3:lan:2" "2:lan:3" "1t:unused" "1t:dtdlink" -+ ;; - archer-c58-v1|\ - archer-c59-v1|\ - archer-c59-v2|\ -@@ -299,11 +315,13 @@ ar71xx_setup_interfaces() - wbs210|\ - wbs510|\ - wbs510-v2) -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth0" "5:lan" "4:wan" -+ "0@eth0" "5:lan" "4t:wan" "4t:dtdlink" - ;; - cr3000) - ucidef_set_interfaces_lan_wan "eth0.1" "eth1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ - "0@eth0" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" - ;; -@@ -455,9 +473,10 @@ ar71xx_setup_interfaces() - ;; - gl-ar750|\ - rb-435g) -- ucidef_set_interfaces_lan_wan "eth1.1" "eth0" -+ ucidef_set_interface_wan "eth0" -+ ucidef_set_interface "wifi" ifname "wlan1" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth1" "1:lan" "2:lan" -+ "0@eth1" "1:lan" "2t:unused" "2t:dtdlink" - ;; - gl-ar750s) - ucidef_add_switch "switch0" \ -@@ -481,9 +500,10 @@ ar71xx_setup_interfaces() - "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth1" - ;; - routerstation-pro) -- ucidef_set_interfaces_lan_wan "eth1.1" "eth0" -+ ucidef_set_interface_wan "eth0" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" - ucidef_add_switch "switch0" \ -- "0@eth1" "2:lan:3" "3:lan:2" "4:lan:1" -+ "0@eth1" "2:lan:3" "3:lan:2" "4t:unused" "4t:dtdlink" - ;; - rb-493g) - ucidef_set_interfaces_lan_wan "eth0.1 eth1.1" "eth1.2" -@@ -595,8 +615,16 @@ ar71xx_setup_interfaces() - ucidef_add_switch "switch0" \ - "0@eth1" "2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "1:wan" - ;; -+ nanostation-m) -+ ucidef_set_interface_lan "eth0 eth1" -+ ucidef_set_interface_wan "eth0.1 eth1.1" -+ ucidef_set_interface "dtdlink" ifname "eth0.2 eth1.2" protocol "static" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ;; - *) -- ucidef_set_interfaces_lan_wan "eth0" "eth1" -+ ucidef_set_interface "wifi" ifname "wlan0" protocol "static" -+ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" -+ ucidef_set_interface "dtdlink" ifname "eth0.2" protocol "static" - ;; - esac - } diff --git a/patches/708-define-aredn-rocket-m-networks.patch b/patches/708-define-aredn-rocket-m-networks.patch new file mode 100644 index 00000000..f62b796c --- /dev/null +++ b/patches/708-define-aredn-rocket-m-networks.patch @@ -0,0 +1,13 @@ +--- a/target/linux/ath79/tiny/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/tiny/base-files/etc/board.d/02_network +@@ -57,7 +57,9 @@ + ubnt,nanostation-loco-m|\ + ubnt,powerbridge-m|\ + ubnt,rocket-m) +- ucidef_set_interface_lan "eth0" ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; + engenius,enh202-v1) + ucidef_set_interface_lan "eth0" diff --git a/patches/709-iperf-fw-restart.patch b/patches/709-iperf-fw-restart.patch index 0c6ff00a..4ba6c764 100644 --- a/patches/709-iperf-fw-restart.patch +++ b/patches/709-iperf-fw-restart.patch @@ -1,11 +1,11 @@ -Index: openwrt/package/network/utils/iperf3/Makefile +Index: openwrt/feeds/packages/net/iperf3/Makefile =================================================================== ---- openwrt.orig/package/network/utils/iperf3/Makefile -+++ openwrt/package/network/utils/iperf3/Makefile +--- openwrt.orig/feeds/packages/net/iperf3/Makefile ++++ openwrt/feeds/packages/net/iperf3/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iperf - PKG_VERSION:=3.7 + PKG_VERSION:=3.11 -PKG_RELEASE:=1 +PKG_RELEASE:=1AREDN @@ -30,17 +30,17 @@ Index: openwrt/package/network/utils/iperf3/Makefile endef define Package/iperf3-ssl/install -Index: openwrt/package/network/utils/iperf3/files/iperf.firewall +Index: openwrt/feeds/packages/net/iperf3/files/iperf.firewall =================================================================== --- /dev/null -+++ openwrt/package/network/utils/iperf3/files/iperf.firewall ++++ openwrt/feeds/packages/net/iperf3/files/iperf.firewall @@ -0,0 +1,9 @@ +#!/bin/sh -+iptables -I zone_wifi_input -p udp -m udp --dport 5201 -j ACCEPT -+iptables -I zone_wifi_input -p tcp -m tcp --dport 5201 -j ACCEPT -+iptables -I zone_dtdlink_input -p udp -m udp --dport 5201 -j ACCEPT -+iptables -I zone_dtdlink_input -p tcp -m tcp --dport 5201 -j ACCEPT ++nft insert rule ip fw4 input_wifi udp dport 5201 counter accept ++nft insert rule ip fw4 input_wifi tcp dport 5201 counter accept ++nft insert rule ip fw4 input_dtdlink udp dport 5201 counter accept ++nft insert rule ip fw4 input_dtdlink tcp dport 5201 counter accept +if [ "$MESHFW_TUNNELS_ENABLED" == "1" ]; then -+ iptables -I zone_vpn_input -p udp -m udp --dport 5201 -j ACCEPT -+ iptables -I zone_vpn_input -p tcp -m tcp --dport 5201 -j ACCEPT ++ nft insert rule ip fw4 input_vpn udp dport 5201 counter accept ++ nft insert rule ip fw4 input_vpn tcp dport 5201 counter accept +fi diff --git a/patches/710-no-ping6-traceroute6.patch b/patches/710-no-ping6-traceroute6.patch index 2678622c..a9c6911d 100644 --- a/patches/710-no-ping6-traceroute6.patch +++ b/patches/710-no-ping6-traceroute6.patch @@ -1,6 +1,6 @@ --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in -@@ -2450,7 +2450,7 @@ config BUSYBOX_DEFAULT_PING +@@ -2522,7 +2522,7 @@ config BUSYBOX_DEFAULT_PING default y config BUSYBOX_DEFAULT_PING6 bool @@ -9,7 +9,7 @@ config BUSYBOX_DEFAULT_FEATURE_FANCY_PING bool default y -@@ -2528,7 +2528,7 @@ config BUSYBOX_DEFAULT_TRACEROUTE +@@ -2606,7 +2606,7 @@ config BUSYBOX_DEFAULT_TRACEROUTE default y config BUSYBOX_DEFAULT_TRACEROUTE6 bool diff --git a/patches/711-aredn-ports-dumbswitch-ar8216.patch b/patches/711-aredn-ports-dumbswitch-ar8216.patch new file mode 100644 index 00000000..7ffb7f43 --- /dev/null +++ b/patches/711-aredn-ports-dumbswitch-ar8216.patch @@ -0,0 +1,16 @@ +--- /dev/null ++++ b/target/linux/ath79/patches-5.10/903-phy-ar8216-no-van-ports.patch +@@ -0,0 +1,13 @@ ++--- a/drivers/net/phy/ar8216.c +++++ b/drivers/net/phy/ar8216.c ++@@ -1393,7 +1393,9 @@ ++ if (i == AR8216_PORT_CPU) ++ continue; ++ ++- portmask[i] = 1 << AR8216_PORT_CPU; +++ for (j = 0; j < dev->ports; j++) { +++ portmask[i] |= (1 << j); +++ } ++ portmask[AR8216_PORT_CPU] |= (1 << i); ++ } ++ } diff --git a/patches/711-nano-xw-switch-config.patch b/patches/711-nano-xw-switch-config.patch deleted file mode 100644 index f1dd3335..00000000 --- a/patches/711-nano-xw-switch-config.patch +++ /dev/null @@ -1,34 +0,0 @@ -Index: openwrt/target/linux/ar71xx/patches-4.14/903-phy-ar8216-no-vlan-ports.patch -=================================================================== ---- /dev/null -+++ openwrt/target/linux/ar71xx/patches-4.14/903-phy-ar8216-no-vlan-ports.patch -@@ -0,0 +1,13 @@ -+--- a/drivers/net/phy/ar8216.c -++++ b/drivers/net/phy/ar8216.c -+@@ -1154,7 +1154,9 @@ -+ if (i == AR8216_PORT_CPU) -+ continue; -+ -+- portmask[i] = 1 << AR8216_PORT_CPU; -++ for (j = 0; j < dev->ports; j++) { -++ portmask[i] |= (1 << j); -++ } -+ portmask[AR8216_PORT_CPU] |= (1 << i); -+ } -+ } ---- /dev/null -+++ openwrt/target/linux/ath79/patches-4.14/903-phy-ar8216-no-vlan-ports.patch -@@ -0,0 +1,13 @@ -+--- a/drivers/net/phy/ar8216.c -++++ b/drivers/net/phy/ar8216.c -+@@ -1154,7 +1154,9 @@ -+ if (i == AR8216_PORT_CPU) -+ continue; -+ -+- portmask[i] = 1 << AR8216_PORT_CPU; -++ for (j = 0; j < dev->ports; j++) { -++ portmask[i] |= (1 << j); -++ } -+ portmask[AR8216_PORT_CPU] |= (1 << i); -+ } -+ } diff --git a/patches/712-auto-distance-settings.patch b/patches/712-auto-distance-settings.patch index fa230bc4..21e39307 100644 --- a/patches/712-auto-distance-settings.patch +++ b/patches/712-auto-distance-settings.patch @@ -1,150 +1,15 @@ ---- /dev/null -+++ b/package/kernel/mac80211/patches/569-ath9k-dynack-set-max-timeout.patch -@@ -0,0 +1,36 @@ -+--- a/drivers/net/wireless/ath/ath9k/dynack.c -++++ b/drivers/net/wireless/ath/ath9k/dynack.c -+@@ -103,9 +103,10 @@ -+ struct ath_dynack *da = &ah->dynack; -+ struct ath_node *an; -+ int to = 0; -++ u32 max_to = ath_dynack_get_max_to(ah); -+ -+ list_for_each_entry(an, &da->nodes, list) -+- if (an->ackto > to) -++ if (an->ackto > to && an->ackto < max_to) -+ to = an->ackto; -+ -+ if (to && da->ackto != to) { -+@@ -308,8 +309,8 @@ -+ */ -+ void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an) -+ { -+- /* ackto = slottime + sifs + air delay */ -+- u32 ackto = 9 + 16 + 64; -++ /* AREDN set ackto to max_to initialize */ -++ u32 ackto = ath_dynack_get_max_to(ah); -+ struct ath_dynack *da = &ah->dynack; -+ -+ an->ackto = ackto; -+@@ -343,8 +344,8 @@ -+ */ -+ void ath_dynack_reset(struct ath_hw *ah) -+ { -+- /* ackto = slottime + sifs + air delay */ -+- u32 ackto = 9 + 16 + 64; -++ /* AREDN set ackto to max_to initialize */ -++ u32 ackto = ath_dynack_get_max_to(ah); -+ struct ath_dynack *da = &ah->dynack; -+ -+ da->lto = jiffies; --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh -@@ -770,7 +770,11 @@ drv_mac80211_setup() { +@@ -1096,7 +1096,11 @@ drv_mac80211_setup() { iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 - iw phy "$phy" set antenna_gain $antenna_gain -- iw phy "$phy" set distance "$distance" -+ if [ $distance -eq 0 -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ]; then -+ iw phy "$phy" set distance auto -+ else -+ iw phy "$phy" set distance "$distance" -+ fi + iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 +- iw phy "$phy" set distance "$distance" >/dev/null 2>&1 ++ if [ $distance -eq 0 -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ]; then ++ iw phy "$phy" set distance auto ++ else ++ iw phy "$phy" set distance "$distance" ++ fi - [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}" - [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}" ---- /dev/null -+++ b/package/kernel/mac80211/patches/568-ath-dynack-set-max-timeout-according-to-clockrate.patch -@@ -0,0 +1,93 @@ -+From 72f4ba6f6b6021fcc48d07d03407c2fdb16a46c5 Mon Sep 17 00:00:00 2001 -+Message-Id: <72f4ba6f6b6021fcc48d07d03407c2fdb16a46c5.1554035972.git.lorenzo@kernel.org> -+In-Reply-To: -+References: -+From: Lorenzo Bianconi -+Date: Sun, 31 Mar 2019 14:38:49 +0200 -+Subject: [PATCH] ath: dynack: set max timeout according to clockrate -+ -+Signed-off-by: Lorenzo Bianconi -+--- -+ drivers/net/wireless/ath/ath9k/dynack.c | 36 ++++++++++++++++++------- -+ 1 file changed, 26 insertions(+), 10 deletions(-) -+ -+diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c -+index f112fa5b2eac..0627111249dd 100644 -+--- a/drivers/net/wireless/ath/ath9k/dynack.c -++++ b/drivers/net/wireless/ath/ath9k/dynack.c -+@@ -20,11 +20,24 @@ -+ -+ #define COMPUTE_TO (5 * HZ) -+ #define LATEACK_DELAY (10 * HZ) -+-#define LATEACK_TO 256 -+-#define MAX_DELAY 300 -+ #define EWMA_LEVEL 96 -+ #define EWMA_DIV 128 -+ -++/** -++ * ath_dynack_get_max_to - set max timeout according to clockrate -++ * @ah: ath hw -++ * -++ */ -++static u32 ath_dynack_get_max_to(struct ath_hw *ah) -++{ -++ struct ath_common *common = ath9k_hw_common(ah); -++ -++ if (common->clockrate) -++ return AR_TIME_OUT_ACK / common->clockrate; -++ -++ return 300; -++} -++ -+ /** -+ * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation -+ * -+@@ -116,15 +129,16 @@ static void ath_dynack_compute_ackto(struct ath_hw *ah) -+ */ -+ static void ath_dynack_compute_to(struct ath_hw *ah) -+ { -+- u32 ackto, ack_ts; -+- u8 *dst, *src; -++ struct ath_dynack *da = &ah->dynack; -++ u32 ackto, ack_ts, max_to; -+ struct ieee80211_sta *sta; -+- struct ath_node *an; -+ struct ts_info *st_ts; -+- struct ath_dynack *da = &ah->dynack; -++ struct ath_node *an; -++ u8 *dst, *src; -+ -+ rcu_read_lock(); -+ -++ max_to = ath_dynack_get_max_to(ah); -+ while (da->st_rbf.h_rb != da->st_rbf.t_rb && -+ da->ack_rbf.h_rb != da->ack_rbf.t_rb) { -+ ack_ts = da->ack_rbf.tstamp[da->ack_rbf.h_rb]; -+@@ -140,7 +154,7 @@ static void ath_dynack_compute_to(struct ath_hw *ah) -+ if (ack_ts > st_ts->tstamp + st_ts->dur) { -+ ackto = ack_ts - st_ts->tstamp - st_ts->dur; -+ -+- if (ackto < MAX_DELAY) { -++ if (ackto < max_to) { -+ sta = ieee80211_find_sta_by_ifaddr(ah->hw, dst, -+ src); -+ if (sta) { -+@@ -197,11 +211,13 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb, -+ if (ieee80211_is_assoc_req(hdr->frame_control) || -+ ieee80211_is_assoc_resp(hdr->frame_control) || -+ ieee80211_is_auth(hdr->frame_control)) { -++ u32 max_to = ath_dynack_get_max_to(ah); -++ -+ ath_dbg(common, DYNACK, "late ack\n"); -+ -+- ath9k_hw_setslottime(ah, (LATEACK_TO - 3) / 2); -+- ath9k_hw_set_ack_timeout(ah, LATEACK_TO); -+- ath9k_hw_set_cts_timeout(ah, LATEACK_TO); -++ ath9k_hw_setslottime(ah, (max_to - 3) / 2); -++ ath9k_hw_set_ack_timeout(ah, max_to); -++ ath9k_hw_set_cts_timeout(ah, max_to); -+ if (sta) { -+ struct ath_node *an; -+ -+-- -+2.20.1 + if [ -n "$txpower" ]; then + iw phy "$phy" set txpower fixed "${txpower%%.*}00" diff --git a/patches/713-delay-snmpd-startup.patch b/patches/713-delay-snmpd-startup.patch deleted file mode 100644 index da1039a5..00000000 --- a/patches/713-delay-snmpd-startup.patch +++ /dev/null @@ -1,12 +0,0 @@ -Index: openwrt/feeds/packages/net/net-snmp/files/snmpd.init -=================================================================== ---- openwrt.orig/feeds/packages/net/net-snmp/files/snmpd.init -+++ openwrt/feeds/packages/net/net-snmp/files/snmpd.init -@@ -1,6 +1,6 @@ - #!/bin/sh /etc/rc.common - # Copyright (C) 2008 OpenWrt.org --START=50 -+START=98 - - USE_PROCD=1 - PROG="/usr/sbin/snmpd" diff --git a/patches/714-vtun-fix-cdefs.patch b/patches/714-vtun-fix-cdefs.patch new file mode 100644 index 00000000..cc9234c5 --- /dev/null +++ b/patches/714-vtun-fix-cdefs.patch @@ -0,0 +1,88 @@ +Index: openwrt/feeds/arednpackages/net/vtun/patches/104-vtun.patch +=================================================================== +--- /dev/null ++++ openwrt/feeds/arednpackages/net/vtun/patches/104-vtun.patch +@@ -0,0 +1,83 @@ ++diff -NarU5 a/cdefs.h b/cdefs.h ++--- a/cdefs.h 1970-01-01 01:00:00.000000000 +0100 +++++ b/cdefs.h 2022-09-04 11:07:04.405285403 +0100 ++@@ -0,0 +1,79 @@ +++/* +++ * Copyright (c) 1991 The Regents of the University of California. +++ * All rights reserved. +++ * +++ * Redistribution and use in source and binary forms, with or without +++ * modification, are permitted provided that the following conditions +++ * are met: +++ * 1. Redistributions of source code must retain the above copyright +++ * notice, this list of conditions and the following disclaimer. +++ * 2. Redistributions in binary form must reproduce the above copyright +++ * notice, this list of conditions and the following disclaimer in the +++ * documentation and/or other materials provided with the distribution. +++ * 3. All advertising materials mentioning features or use of this software +++ * must display the following acknowledgement: +++ * This product includes software developed by the University of +++ * California, Berkeley and its contributors. +++ * 4. Neither the name of the University nor the names of its contributors +++ * may be used to endorse or promote products derived from this software +++ * without specific prior written permission. +++ * +++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +++ * SUCH DAMAGE. +++ * +++ * @(#)cdefs.h 7.6 (Berkeley) 5/4/91 +++ */ +++ +++#ifndef _CDEFS_H_ +++#define _CDEFS_H_ +++ +++#if defined(__cplusplus) +++#define __BEGIN_DECLS extern "C" { +++#define __END_DECLS }; +++#else +++#define __BEGIN_DECLS +++#define __END_DECLS +++#endif +++ +++/* +++ * The __CONCAT macro is used to concatenate parts of symbol names, e.g. +++ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. +++ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces +++ * in between its arguments. __CONCAT can also concatenate double-quoted +++ * strings produced by the __STRING macro, but this only works with ANSI C. +++ */ +++#if defined(__STDC__) || defined(__cplusplus) +++#define __P(protos) protos /* full-blown ANSI C */ +++#define __CONCAT(x,y) x ## y +++#define __STRING(x) #x +++ +++#else /* !(__STDC__ || __cplusplus) */ +++#define __P(protos) () /* traditional C preprocessor */ +++#define __CONCAT(x,y) x/**/y +++#define __STRING(x) "x" +++ +++#ifdef __GNUC__ +++#define const __const /* GCC: ANSI C with -traditional */ +++#define inline __inline +++#define signed __signed +++#define volatile __volatile +++ +++#else /* !__GNUC__ */ +++#define const /* delete ANSI C keywords */ +++#define inline +++#define signed +++#define volatile +++#endif /* !__GNUC__ */ +++#endif /* !(__STDC__ || __cplusplus) */ +++ +++#endif /* !_CDEFS_H_ */ +++ diff --git a/patches/714-vtun-openssl-fix.patch b/patches/714-vtun-openssl-fix.patch index 0aed5ccc..10661202 100644 --- a/patches/714-vtun-openssl-fix.patch +++ b/patches/714-vtun-openssl-fix.patch @@ -1,7 +1,5 @@ -Index: openwrt/feeds/arednpackages/net/vtun/patches/102-vtun.patch -=================================================================== --- /dev/null -+++ openwrt/feeds/arednpackages/net/vtun/patches/102-vtun.patch ++++ b/feeds/arednpackages/net/vtun/patches/102-vtun.patch @@ -0,0 +1,287 @@ +diff -NarU5 a/lfd_encrypt.c b/lfd_encrypt.c +--- a/lfd_encrypt.c 2008-01-07 16:35:32.000000000 -0600 @@ -290,10 +288,8 @@ Index: openwrt/feeds/arednpackages/net/vtun/patches/102-vtun.patch + } + #ifdef LFD_ENCRYPT_DEBUG + vtun_syslog(LOG_INFO, "Local decryptor out of sync"); -Index: openwrt/feeds/arednpackages/net/vtun/patches/103-vtun.patch -=================================================================== --- /dev/null -+++ openwrt/feeds/arednpackages/net/vtun/patches/103-vtun.patch ++++ b/feeds/arednpackages/net/vtun/patches/103-vtun.patch @@ -0,0 +1,2110 @@ +diff -NarU5 a/auth.c b/auth.c +--- a/auth.c 2009-05-15 02:23:39.000000000 -0500 @@ -435,7 +431,7 @@ Index: openwrt/feeds/arednpackages/net/vtun/patches/103-vtun.patch ++ * [including the GNU Public Licence.] ++ */ ++ -++#include +++#include "cdefs.h" ++ ++#include ++ @@ -587,7 +583,7 @@ Index: openwrt/feeds/arednpackages/net/vtun/patches/103-vtun.patch ++ * [including the GNU Public Licence.] ++ */ ++ -++#include +++#include "cdefs.h" ++ ++#include ++ @@ -679,7 +675,7 @@ Index: openwrt/feeds/arednpackages/net/vtun/patches/103-vtun.patch ++ * [including the GNU Public Licence.] ++ */ ++ -++#include +++#include "cdefs.h" ++ ++#include ++#include "blowfish.h" @@ -1400,7 +1396,7 @@ Index: openwrt/feeds/arednpackages/net/vtun/patches/103-vtun.patch ++ * [including the GNU Public Licence.] ++ */ ++ -++#include +++#include "cdefs.h" ++ ++#include ++#include diff --git a/patches/715-set-min-free.patch b/patches/715-set-min-free.patch index 4993d97b..916cf147 100644 --- a/patches/715-set-min-free.patch +++ b/patches/715-set-min-free.patch @@ -1,7 +1,5 @@ -Index: openwrt/package/base-files/files/etc/init.d/sysctl -=================================================================== ---- openwrt.orig/package/base-files/files/etc/init.d/sysctl -+++ openwrt/package/base-files/files/etc/init.d/sysctl +--- a/package/base-files/files/etc/init.d/sysctl ++++ b/package/base-files/files/etc/init.d/sysctl @@ -10,7 +10,7 @@ apply_defaults() { if [ "$mem" -gt 65536 ]; then # 128M min_free=16384 diff --git a/patches/716-ubnt-pbe-100mb-port.patch b/patches/716-ubnt-pbe-100mb-port.patch index ebf21557..707b7c3c 100644 --- a/patches/716-ubnt-pbe-100mb-port.patch +++ b/patches/716-ubnt-pbe-100mb-port.patch @@ -1,11 +1,8 @@ -Index: openwrt/package/base-files/files/etc/rc.local -=================================================================== ---- openwrt.orig/package/base-files/files/etc/rc.local -+++ openwrt/package/base-files/files/etc/rc.local +--- a/package/base-files/files/etc/rc.local ++++ b/package/base-files/files/etc/rc.local @@ -1,4 +1,12 @@ # Put your custom commands here that should be executed once # the system init finished. By default this file does nothing. - /etc/init.d/dnsmasq start + +BOARDID=$(/usr/local/bin/get_boardid) +case "$BOARDID" in diff --git a/patches/717-fix-olsrd-gpsdclient-error.patch b/patches/717-fix-olsrd-gpsdclient-error.patch new file mode 100644 index 00000000..23d4ac45 --- /dev/null +++ b/patches/717-fix-olsrd-gpsdclient-error.patch @@ -0,0 +1,29 @@ +--- /dev/null ++++ openwrt/feeds/arednpackages/net/olsrd/patches/014-fix-gpsd_compile.patch +@@ -0,0 +1,26 @@ ++diff -Naur a/lib/pud/nmealib/Makefile.inc b/lib/pud/nmealib/Makefile.inc ++--- a/lib/pud/nmealib/Makefile.inc 2017-06-06 11:17:26.000000000 +0100 +++++ b/lib/pud/nmealib/Makefile.inc 2022-09-03 17:19:20.618461094 +0100 ++@@ -63,7 +63,7 @@ ++ -Wmissing-format-attribute -Wno-multichar -Wno-deprecated-declarations -Wendif-labels -Wwrite-strings \ ++ -Wbad-function-cast -Wpointer-arith -Wcast-qual -Wshadow -Wformat -Wsequence-point -Wcast-align \ ++ -Wnested-externs -Winline -Wdisabled-optimization -funit-at-a-time -fPIC -ggdb -Wformat=2 -Winit-self \ ++- -Wswitch-default -Wswitch-enum -Wconversion -Wdouble-promotion \ +++ -Wswitch-default -Wswitch-enum -Wno-narrowing -Wdouble-promotion \ ++ -Werror=format-security -Wformat-security -Wformat-y2k -Wredundant-decls -Wundef -Wunreachable-code \ ++ -Wunused-parameter ++ ++diff -Naur a/lib/pud/src/gpsdclient.c b/lib/pud/src/gpsdclient.c ++--- a/lib/pud/src/gpsdclient.c 2022-09-03 17:12:42.966455073 +0100 +++++ b/lib/pud/src/gpsdclient.c 2022-09-03 17:21:15.766462838 +0100 ++@@ -370,10 +370,6 @@ ++ ); ++ ++ gpsdata->set &= ~STATUS_SET; /* always valid */ ++- if (gpsdata-> fix.status == STATUS_NO_FIX) { ++- nmeaInfoClear(info); ++- return; ++- } ++ ++ if (!gpsdata->set) { ++ return; diff --git a/patches/717-fix-olsrd-oparse-error.patch b/patches/717-fix-olsrd-oparse-error.patch new file mode 100644 index 00000000..2943d757 --- /dev/null +++ b/patches/717-fix-olsrd-oparse-error.patch @@ -0,0 +1,154 @@ +--- /dev/null ++++ b/feeds/arednpackages/net/olsrd/patches/009-fix-oparse-error.patch +@@ -0,0 +1,151 @@ ++diff -NarU5 a/lib/pud/src/gpsdclient.c b/lib/pud/src/gpsdclient.c ++--- a/lib/pud/src/gpsdclient.c 2017-06-06 05:17:26.000000000 -0500 +++++ b/lib/pud/src/gpsdclient.c 2021-05-27 21:19:12.534140371 -0500 ++@@ -77,10 +77,27 @@ ++ /* log gpsd errors */ ++ static void gpsdError(const char *s) { ++ syslog(LOG_ERR, "gpsd error: %s", s); ++ } ++ +++#if GPSD_API_MAJOR_VERSION >= 9 +++static double time_as_double(struct timespec *ts) { +++ return (ts->tv_sec + ts->tv_nsec * 1e-9); +++} +++ +++static bool is_online(struct gps_data_t *gpsdata) { +++ return !!gpsdata->online.tv_sec; +++} +++#else +++ +++#define time_as_double(x) *(x) +++ +++static bool is_online(struct gps_data_t *gpsdata) { +++ return !!gpsdata->online; +++} +++#endif +++ ++ /* standard parsing of a GPS data source spec */ ++ void gpsdParseSourceSpec(char *arg, GpsDaemon *gpsDaemon) { ++ if (!arg // ++ || !gpsDaemon) { ++ return; ++@@ -296,12 +313,12 @@ ++ dev->driver_mode ? "native" : "compatibility", // ++ dev->baudrate, // ++ 8, // ++ dev->parity, // ++ dev->stopbits, // ++- dev->cycle, // ++- dev->mincycle); +++ time_as_double(&dev->cycle), // +++ time_as_double(&dev->mincycle)); ++ ++ connectionTracking->devSeen[i] = true; ++ connectionTracking->dev[i] = *dev; ++ } else if (connectionTracking->devSeen[i]) { ++ size_t subtypeLength; ++@@ -351,11 +368,11 @@ ++ | NAVDATA_SET // ++ #endif ++ ); ++ ++ gpsdata->set &= ~STATUS_SET; /* always valid */ ++- if (gpsdata->status == STATUS_NO_FIX) { +++ if (gpsdata-> fix.status == STATUS_NO_FIX) { ++ nmeaInfoClear(info); ++ return; ++ } ++ ++ if (!gpsdata->set) { ++@@ -364,31 +381,38 @@ ++ ++ info->smask = NMEALIB_SENTENCE_MASK; ++ nmeaInfoSetPresent(&info->present, NMEALIB_PRESENT_SMASK); ++ ++ /* date & time */ +++#if GPSD_API_MAJOR_VERSION >= 9 +++ if (gpsdata->fix.time.tv_sec > 0) { +++ struct tm *time = gmtime(&gpsdata->fix.time.tv_sec); +++ unsigned int hsec = (unsigned int) (gpsdata->fix.time.tv_nsec / 10000000); +++#else ++ if (!isNaN(gpsdata->fix.time)) { ++ double seconds; ++ double fraction = modf(fabs(gpsdata->fix.time), &seconds); ++ long sec = lrint(seconds); ++ struct tm *time = gmtime(&sec); +++ unsigned int hsec = (unsigned int) lrint(fraction * 100); +++#endif ++ if (time) { ++ info->utc.year = (unsigned int) time->tm_year + 1900; ++ info->utc.mon = (unsigned int) time->tm_mon + 1; ++ info->utc.day = (unsigned int) time->tm_mday; ++ info->utc.hour = (unsigned int) time->tm_hour; ++ info->utc.min = (unsigned int) time->tm_min; ++ info->utc.sec = (unsigned int) time->tm_sec; ++- info->utc.hsec = (unsigned int) lrint(fraction * 100); +++ info->utc.hsec = hsec; ++ ++ nmeaInfoSetPresent(&info->present, NMEALIB_PRESENT_UTCDATE | NMEALIB_PRESENT_UTCTIME); ++ } ++ } ++ gpsdata->set &= ~TIME_SET; ++ ++ /* sig & fix */ ++- if (!gpsdata->online) { +++ if (!is_online(gpsdata)) { ++ gpsdata->fix.mode = MODE_NO_FIX; ++ } ++ ++ switch (gpsdata->fix.mode) { ++ case MODE_3D: ++@@ -458,11 +482,15 @@ ++ ++ /* elv */ ++ if ((gpsdata->fix.mode >= MODE_3D) // ++ && !isNaN(gpsdata->fix.altitude)) { ++ info->elevation = gpsdata->fix.altitude; +++#if GPSD_API_MAJOR_VERSION >= 9 +++ info->height = gpsdata->fix.geoid_sep; +++#else ++ info->height = gpsdata->separation; +++#endif ++ nmeaInfoSetPresent(&info->present, NMEALIB_PRESENT_ELV | NMEALIB_PRESENT_HEIGHT); ++ } ++ gpsdata->set &= ~ALTITUDE_SET; ++ ++ /* speed */ ++@@ -582,11 +610,11 @@ ++ ++ errno = 0; ++ if (!connectionTracking->connected) { ++ gpsReadCode = -1; ++ } else { ++- gpsReadCode = gps_read(gpsdata); +++ gpsReadCode = gps_read(gpsdata, NULL, 0); ++ } ++ ++ if (gpsReadCode > 0) { ++ /* data received from gpsd */ ++ nmeaInfoFromGpsd(gpsdata, nmeaInfo, connectionTracking); ++diff -NarU5 a/src/cfgparser/local.mk b/src/cfgparser/local.mk ++--- a/src/cfgparser/local.mk 2017-06-06 05:17:26.000000000 -0500 +++++ b/src/cfgparser/local.mk 2021-05-27 19:55:01.969001000 -0500 ++@@ -72,16 +72,12 @@ ++ ++ $(C)oparse.c: $(C)oparse.y $(C)olsrd_conf.h $(C)Makefile ++ ifeq ($(VERBOSE),0) ++ @echo "[BISON] $@" ++ endif ++- $(MAKECMDPREFIX)$(BISON) -d -o "$@-tmp" "$<" ++- $(MAKECMDPREFIX)sed -e 's/register //' \ ++- -e '/^#line/s/$(call quote,$@-tmp)/$(call quote,$@)/' \ ++- < "$@-tmp" >"$@" ++- $(MAKECMDPREFIX)mv "$(subst .c,.h,$@-tmp)" "$(subst .c,.h,$@)" ++- $(MAKECMDPREFIX)$(RM) "$@-tmp" "$(subst .c,.h,$@-tmp)" +++ $(MAKECMDPREFIX)$(BISON) -d -o "$@" "$<" +++ $(MAKECMDPREFIX)sed -e 's/register //' "$@" > "$@.o" && mv "$@.o" "$@" ++ ++ $(C)oparse.o: CFLAGS := $(filter-out -Wunreachable-code,$(CFLAGS)) ++ ++ # and a few files to be cleaned ++ TMPFILES += $(foreach pat,oscan.c oparse.c oparse.h,$(C)$(pat) $(C)$(pat)-tmp) diff --git a/patches/718-temp-remove-olsrd-pud.patch b/patches/718-temp-remove-olsrd-pud.patch new file mode 100644 index 00000000..b85c386a --- /dev/null +++ b/patches/718-temp-remove-olsrd-pud.patch @@ -0,0 +1,59 @@ +--- a/package/feeds/arednpackages/olsrd/Makefile ++++ b/package/feeds/arednpackages/olsrd/Makefile +@@ -107,12 +107,6 @@ define Package/olsrd-mod-pgraph + TITLE:=output network topology for pgraph + endef + +-define Package/olsrd-mod-pud +- $(call Package/olsrd/template) +- DEPENDS:=olsrd +libgps +- TITLE:=Position Update Distribution plugin +-endef +- + define Package/olsrd-mod-quagga + $(call Package/olsrd/template) + DEPENDS:=olsrd +@@ -143,10 +137,6 @@ define Package/olsrd-mod-watchdog + TITLE:=Watchdog plugin + endef + +-define Package/olsrd-mod-pud/conffiles +-/etc/olsrd.d/olsrd.pud.position.conf +-endef +- + define Package/olsrd-mod-secure/conffiles + /etc/olsrd.d/olsrd_secure_key + endef +@@ -161,7 +151,7 @@ MAKE_FLAGS+= \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + STRIP="true" \ + INSTALL_LIB="true" \ +- SUBDIRS="arprefresh bmf dot_draw dyn_gw dyn_gw_plain httpinfo jsoninfo mdns nameservice p2pd pgraph pud quagga secure sgwdynspeed txtinfo watchdog" ++ SUBDIRS="arprefresh bmf dot_draw dyn_gw dyn_gw_plain httpinfo jsoninfo mdns nameservice p2pd pgraph quagga secure sgwdynspeed txtinfo watchdog" + + define Build/Compile + $(call Build/Compile/Default,all) +@@ -238,15 +228,6 @@ define Package/olsrd-mod-pgraph/install + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/pgraph/olsrd_pgraph.so.* $(1)/usr/lib/ + endef + +-define Package/olsrd-mod-pud/install +- $(INSTALL_DIR) $(1)/etc/olsrd.d +- $(CP) ./files/olsrd.pud.position.conf $(1)/etc/olsrd.d/ +- $(INSTALL_DIR) $(1)/usr/lib +- $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/pud/nmealib/lib/libnmea.so $(1)/usr/lib/ +- $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/pud/wireformat/lib/libOlsrdPudWireFormat.so $(1)/usr/lib/ +- $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/pud/olsrd_pud.so.* $(1)/usr/lib/ +-endef +- + define Package/olsrd-mod-quagga/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/quagga/olsrd_quagga.so.* $(1)/usr/lib/ +@@ -288,7 +269,6 @@ $(eval $(call BuildPackage,olsrd-mod-mdn + $(eval $(call BuildPackage,olsrd-mod-nameservice)) + $(eval $(call BuildPackage,olsrd-mod-p2pd)) + $(eval $(call BuildPackage,olsrd-mod-pgraph)) +-$(eval $(call BuildPackage,olsrd-mod-pud)) + $(eval $(call BuildPackage,olsrd-mod-quagga)) + $(eval $(call BuildPackage,olsrd-mod-secure)) + $(eval $(call BuildPackage,olsrd-mod-sgwdynspeed)) diff --git a/patches/719-disable-ipv6.patch b/patches/719-disable-ipv6.patch new file mode 100644 index 00000000..14178fbf --- /dev/null +++ b/patches/719-disable-ipv6.patch @@ -0,0 +1,168 @@ +--- a/config/Config-build.in ++++ b/config/Config-build.in +@@ -156,7 +156,7 @@ + config IPV6 + bool + prompt "Enable IPv6 support in packages" +- default y ++ default n + help + Enables IPv6 support in kernel (builtin) and packages. + +--- a/include/netfilter.mk ++++ b/include/netfilter.mk +@@ -325,7 +325,7 @@ + $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_OBJREF, $(P_XT)nft_objref),)) + $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_QUOTA, $(P_XT)nft_quota),)) + $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_REDIR, $(P_XT)nft_redir),)) +-$(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_REJECT, $(P_XT)nft_reject $(P_V4)nft_reject_ipv4 $(P_V6)nft_reject_ipv6),)) ++$(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_REJECT, $(P_XT)nft_reject $(P_V4)nft_reject_ipv4),)) + $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_REJECT_INET, $(P_XT)nft_reject_inet),)) + + $(eval $(if $(NF_KMOD),$(call nf_add,NFT_BRIDGE,CONFIG_NFT_BRIDGE_META, $(P_EBT)nft_meta_bridge),)) + +--- a/package/kernel/linux/modules/netfilter.mk ++++ b/package/kernel/linux/modules/netfilter.mk +@@ -1153,7 +1153,7 @@ + define KernelPackage/nft-offload + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter nf_tables routing/NAT offload support +- DEPENDS:=@IPV6 +kmod-nf-flow +kmod-nft-nat ++ DEPENDS:=+kmod-nf-flow +kmod-nft-nat + KCONFIG:= \ + CONFIG_NF_FLOW_TABLE_INET \ + CONFIG_NF_FLOW_TABLE_IPV4 \ +@@ -1162,9 +1162,8 @@ + FILES:= \ + $(LINUX_DIR)/net/netfilter/nf_flow_table_inet.ko \ + $(LINUX_DIR)/net/ipv4/netfilter/nf_flow_table_ipv4.ko \ +- $(LINUX_DIR)/net/ipv6/netfilter/nf_flow_table_ipv6.ko \ + $(LINUX_DIR)/net/netfilter/nft_flow_offload.ko +- AUTOLOAD:=$(call AutoProbe,nf_flow_table_inet nf_flow_table_ipv4 nf_flow_table_ipv6 nft_flow_offload) ++ AUTOLOAD:=$(call AutoProbe,nf_flow_table_inet nf_flow_table_ipv4 nft_flow_offload) + endef + + $(eval $(call KernelPackage,nft-offload)) + +--- /dev/null ++++ b/package/network/config/firewall4/patches/001-disable-ipv6.patch +@@ -0,0 +1,119 @@ ++--- a/root/usr/share/firewall4/main.uc +++++ b/root/usr/share/firewall4/main.uc ++@@ -33,14 +33,14 @@ function reload_sets() { ++ let first = true; ++ let printer = (entry) => { ++ if (first) { ++- print(`add element inet fw4 ${set.name} {\n`); +++ print(`add element ip fw4 ${set.name} {\n`); ++ first = false; ++ } ++ ++ print(` ${join(" . ", entry)},\n`); ++ }; ++ ++- print(`flush set inet fw4 ${set.name}\n`); +++ print(`flush set ip fw4 ${set.name}\n`); ++ ++ map(set.entries, printer); ++ ++--- a/root/usr/share/firewall4/templates/redirect.uc +++++ b/root/usr/share/firewall4/templates/redirect.uc ++@@ -1,5 +1,5 @@ ++ {%+ if (redirect.family && !redirect.has_addrs): -%} ++- meta nfproto {{ fw4.nfproto(redirect.family) }} {%+ endif -%} +++ {%+ endif -%} ++ {%+ if (!redirect.proto.any && !redirect.has_ports): -%} ++ meta l4proto {{ ++ (redirect.proto.name == 'icmp' && redirect.family == 6) ? 'ipv6-icmp' : redirect.proto.name ++--- a/root/usr/share/firewall4/templates/rule.uc +++++ b/root/usr/share/firewall4/templates/rule.uc ++@@ -1,5 +1,5 @@ ++ {%+ if (rule.family && !rule.has_addrs): -%} ++- meta nfproto {{ fw4.nfproto(rule.family) }} {%+ endif -%} +++ {%+ endif -%} ++ {%+ if (!rule.proto.any && !rule.has_ports && !rule.icmp_types && !rule.icmp_codes): -%} ++ meta l4proto {{ fw4.l4proto(rule.family, rule.proto) }} {%+ endif -%} ++ {%+ if (rule.iifnames): -%} ++--- a/root/usr/share/firewall4/templates/ruleset.uc +++++ b/root/usr/share/firewall4/templates/ruleset.uc ++@@ -4,14 +4,14 @@ ++ let defined_ipsets = fw4.ipsets(); ++ -%} ++ ++-table inet fw4 ++-flush table inet fw4 +++table ip fw4 +++flush table ip fw4 ++ {% if (fw4.check_flowtable()): %} ++-delete flowtable inet fw4 ft +++delete flowtable ip fw4 ft ++ {% endif %} ++ {% fw4.includes('ruleset-prepend') %} ++ ++-table inet fw4 { +++table ip fw4 { ++ {% if (length(flowtable_devices) > 0): %} ++ # ++ # Flowtable ++@@ -187,12 +187,12 @@ table inet fw4 { ++ chain handle_reject { ++ meta l4proto tcp reject with {{ ++ (fw4.default_option("tcp_reject_code") != "tcp-reset") ++- ? `icmpx type ${fw4.default_option("tcp_reject_code")}` +++ ? `icmp type ${fw4.default_option("tcp_reject_code")}` ++ : "tcp reset" ++ }} comment "!fw4: Reject TCP traffic" ++ reject with {{ ++ (fw4.default_option("any_reject_code") != "tcp-reset") ++- ? `icmpx type ${fw4.default_option("any_reject_code")}` +++ ? `icmp type ${fw4.default_option("any_reject_code")}` ++ : "tcp reset" ++ }} comment "!fw4: Reject any other traffic" ++ } ++--- a/root/usr/share/firewall4/templates/zone-jump.uc +++++ b/root/usr/share/firewall4/templates/zone-jump.uc ++@@ -1,5 +1,5 @@ ++ {%+ if (rule.family): -%} ++- meta nfproto {{ fw4.nfproto(rule.family) }} {%+ endif -%} +++ {%+ endif -%} ++ {%+ include("zone-match.uc", { egress: (direction in ["output", "srcnat"]), rule }) -%} ++ jump {{ direction }}_{{ zone.name }} comment "!fw4: Handle {{ zone.name }} {{ ++ fw4.nfproto(rule.family, true) ++--- a/root/usr/share/firewall4/templates/zone-masq.uc +++++ b/root/usr/share/firewall4/templates/zone-masq.uc ++@@ -1,4 +1,4 @@ ++-meta nfproto {{ fw4.nfproto(family) }} {%+ if (saddrs && saddrs[0]): -%} +++{%+ if (saddrs && saddrs[0]): -%} ++ {{ fw4.ipproto(family) }} saddr {{ fw4.set(map(saddrs[0], fw4.cidr)) }} {%+ endif -%} ++ {%+ if (saddrs && saddrs[1]): -%} ++ {{ fw4.ipproto(family) }} saddr != {{ fw4.set(map(saddrs[1], fw4.cidr)) }} {%+ endif -%} ++--- a/root/usr/share/firewall4/templates/zone-mssfix.uc +++++ b/root/usr/share/firewall4/templates/zone-mssfix.uc ++@@ -1,5 +1,5 @@ ++ {%+ if (rule.family): -%} ++- meta nfproto {{ fw4.nfproto(rule.family) }} {%+ endif -%} +++ {%+ endif -%} ++ {%+ include("zone-match.uc", { egress, rule }) -%} ++ tcp flags syn tcp option maxseg size set rt mtu {%+ if (zone.log & 2): -%} ++ log prefix "MSSFIX {{ zone.name }} out: " {%+ endif -%} ++--- a/root/usr/share/firewall4/templates/zone-notrack.uc +++++ b/root/usr/share/firewall4/templates/zone-notrack.uc ++@@ -7,7 +7,7 @@ ++ return; ++ -%} ++ {%+ if (rule.family): -%} ++- meta nfproto {{ fw4.nfproto(rule.family) }} {%+ endif -%} +++ {%+ endif -%} ++ {%+ if (length(devs)): -%} ++ iifname {{ fw4.set(devs) }} {%+ endif -%} ++ {%+ if (rule.devices_neg): -%} ++--- a/root/usr/share/firewall4/templates/zone-verdict.uc +++++ b/root/usr/share/firewall4/templates/zone-verdict.uc ++@@ -1,5 +1,5 @@ ++ {%+ if (rule.family): -%} ++- meta nfproto {{ fw4.nfproto(rule.family) }} {%+ endif -%} +++ {%+ endif -%} ++ {%+ include("zone-match.uc", { egress, rule }) -%} ++ {%+ if (zone.counter): -%} ++ counter {%+ endif -%} diff --git a/patches/720-curl-without-ssl.patch b/patches/720-curl-without-ssl.patch new file mode 100644 index 00000000..47d0320d --- /dev/null +++ b/patches/720-curl-without-ssl.patch @@ -0,0 +1,10 @@ +--- a/package/feeds/packages/curl/Makefile ++++ b/package/feeds/packages/curl/Makefile +@@ -120,6 +120,7 @@ + --without-ca-path \ + --without-libpsl \ + --without-zstd \ ++ --without-ssl \ + --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt \ + \ + $(call autoconf_bool,CONFIG_IPV6,ipv6) \ diff --git a/patches/730-ipq40xx-dsa.patch b/patches/730-ipq40xx-dsa.patch new file mode 100644 index 00000000..bce10450 --- /dev/null +++ b/patches/730-ipq40xx-dsa.patch @@ -0,0 +1,19041 @@ +--- a/target/linux/ipq40xx/Makefile ++++ b/target/linux/ipq40xx/Makefile +@@ -15,7 +15,7 @@ KERNELNAME:=zImage Image dtbs + include $(INCLUDE_DIR)/target.mk + DEFAULT_PACKAGES += \ + kmod-usb-dwc3-qcom \ +- kmod-leds-gpio kmod-gpio-button-hotplug swconfig \ ++ kmod-leds-gpio kmod-gpio-button-hotplug \ + kmod-ath10k-ct wpad-mini \ + kmod-usb3 kmod-usb-dwc3 ath10k-firmware-qca4019-ct \ + uboot-envtools +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -1,7 +1,6 @@ + CONFIG_ALIGNMENT_TRAP=y + # CONFIG_APQ_GCC_8084 is not set + # CONFIG_APQ_MMCC_8084 is not set +-CONFIG_AR40XX_PHY=y + CONFIG_ARCH_32BIT_OFF_T=y + CONFIG_ARCH_HIBERNATION_POSSIBLE=y + CONFIG_ARCH_IPQ40XX=y +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -148,7 +147,6 @@ CONFIG_DYNAMIC_DEBUG=y + CONFIG_EDAC_ATOMIC_SCRUB=y + CONFIG_EDAC_SUPPORT=y + CONFIG_EEPROM_AT24=y +-CONFIG_ESSEDMA=y + CONFIG_EXTCON=y + CONFIG_FIXED_PHY=y + CONFIG_FIX_EARLYCON_MEM=y +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -457,8 +455,6 @@ CONFIG_SPMI=y + CONFIG_SPMI_MSM_PMIC_ARB=y + # CONFIG_SPMI_PMIC_CLKDIV is not set + CONFIG_SRCU=y +-CONFIG_SWCONFIG=y +-CONFIG_SWCONFIG_LEDS=y + CONFIG_SWPHY=y + CONFIG_SWP_EMULATE=y + CONFIG_SYS_SUPPORTS_APM_EMULATION=y +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/Makefile ++++ /dev/null +@@ -1,9 +0,0 @@ +-# +-## Makefile for the Qualcomm Atheros ethernet edma driver +-# +- +- +-obj-$(CONFIG_ESSEDMA) += essedma.o +- +-essedma-objs := edma_axi.o edma.o edma_ethtool.o +- +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.c ++++ /dev/null +@@ -1,2177 +0,0 @@ +-/* +- * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +- * +- * Permission to use, copy, modify, and/or distribute this software for +- * any purpose with or without fee is hereby granted, provided that the +- * above copyright notice and this permission notice appear in all copies. +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#include +-#include +-#include "ess_edma.h" +-#include "edma.h" +- +-extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; +-bool edma_stp_rstp; +-u16 edma_ath_eth_type; +- +-/* edma_skb_priority_offset() +- * get edma skb priority +- */ +-static unsigned int edma_skb_priority_offset(struct sk_buff *skb) +-{ +- return (skb->priority >> 2) & 1; +-} +- +-/* edma_alloc_tx_ring() +- * Allocate Tx descriptors ring +- */ +-static int edma_alloc_tx_ring(struct edma_common_info *edma_cinfo, +- struct edma_tx_desc_ring *etdr) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- +- /* Initialize ring */ +- etdr->size = sizeof(struct edma_sw_desc) * etdr->count; +- etdr->sw_next_to_fill = 0; +- etdr->sw_next_to_clean = 0; +- +- /* Allocate SW descriptors */ +- etdr->sw_desc = vzalloc(etdr->size); +- if (!etdr->sw_desc) { +- dev_err(&pdev->dev, "buffer alloc of tx ring failed=%p", etdr); +- return -ENOMEM; +- } +- +- /* Allocate HW descriptors */ +- etdr->hw_desc = dma_alloc_coherent(&pdev->dev, etdr->size, &etdr->dma, +- GFP_KERNEL); +- if (!etdr->hw_desc) { +- dev_err(&pdev->dev, "descriptor allocation for tx ring failed"); +- vfree(etdr->sw_desc); +- return -ENOMEM; +- } +- +- return 0; +-} +- +-/* edma_free_tx_ring() +- * Free tx rings allocated by edma_alloc_tx_rings +- */ +-static void edma_free_tx_ring(struct edma_common_info *edma_cinfo, +- struct edma_tx_desc_ring *etdr) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- +- if (likely(etdr->dma)) +- dma_free_coherent(&pdev->dev, etdr->size, etdr->hw_desc, +- etdr->dma); +- +- vfree(etdr->sw_desc); +- etdr->sw_desc = NULL; +-} +- +-/* edma_alloc_rx_ring() +- * allocate rx descriptor ring +- */ +-static int edma_alloc_rx_ring(struct edma_common_info *edma_cinfo, +- struct edma_rfd_desc_ring *erxd) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- +- erxd->size = sizeof(struct edma_sw_desc) * erxd->count; +- erxd->sw_next_to_fill = 0; +- erxd->sw_next_to_clean = 0; +- +- /* Allocate SW descriptors */ +- erxd->sw_desc = vzalloc(erxd->size); +- if (!erxd->sw_desc) +- return -ENOMEM; +- +- /* Alloc HW descriptors */ +- erxd->hw_desc = dma_alloc_coherent(&pdev->dev, erxd->size, &erxd->dma, +- GFP_KERNEL); +- if (!erxd->hw_desc) { +- vfree(erxd->sw_desc); +- return -ENOMEM; +- } +- +- /* Initialize pending_fill */ +- erxd->pending_fill = 0; +- +- return 0; +-} +- +-/* edma_free_rx_ring() +- * Free rx ring allocated by alloc_rx_ring +- */ +-static void edma_free_rx_ring(struct edma_common_info *edma_cinfo, +- struct edma_rfd_desc_ring *rxdr) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- +- if (likely(rxdr->dma)) +- dma_free_coherent(&pdev->dev, rxdr->size, rxdr->hw_desc, +- rxdr->dma); +- +- vfree(rxdr->sw_desc); +- rxdr->sw_desc = NULL; +-} +- +-/* edma_configure_tx() +- * Configure transmission control data +- */ +-static void edma_configure_tx(struct edma_common_info *edma_cinfo) +-{ +- u32 txq_ctrl_data; +- +- txq_ctrl_data = (EDMA_TPD_BURST << EDMA_TXQ_NUM_TPD_BURST_SHIFT); +- txq_ctrl_data |= EDMA_TXQ_CTRL_TPD_BURST_EN; +- txq_ctrl_data |= (EDMA_TXF_BURST << EDMA_TXQ_TXF_BURST_NUM_SHIFT); +- edma_write_reg(EDMA_REG_TXQ_CTRL, txq_ctrl_data); +-} +- +- +-/* edma_configure_rx() +- * configure reception control data +- */ +-static void edma_configure_rx(struct edma_common_info *edma_cinfo) +-{ +- struct edma_hw *hw = &edma_cinfo->hw; +- u32 rss_type, rx_desc1, rxq_ctrl_data; +- +- /* Set RSS type */ +- rss_type = hw->rss_type; +- edma_write_reg(EDMA_REG_RSS_TYPE, rss_type); +- +- /* Set RFD burst number */ +- rx_desc1 = (EDMA_RFD_BURST << EDMA_RXQ_RFD_BURST_NUM_SHIFT); +- +- /* Set RFD prefetch threshold */ +- rx_desc1 |= (EDMA_RFD_THR << EDMA_RXQ_RFD_PF_THRESH_SHIFT); +- +- /* Set RFD in host ring low threshold to generte interrupt */ +- rx_desc1 |= (EDMA_RFD_LTHR << EDMA_RXQ_RFD_LOW_THRESH_SHIFT); +- edma_write_reg(EDMA_REG_RX_DESC1, rx_desc1); +- +- /* Set Rx FIFO threshold to start to DMA data to host */ +- rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE; +- +- /* Set RX remove vlan bit */ +- rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; +- +- edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data); +-} +- +-/* edma_alloc_rx_buf() +- * does skb allocation for the received packets. +- */ +-static int edma_alloc_rx_buf(struct edma_common_info +- *edma_cinfo, +- struct edma_rfd_desc_ring *erdr, +- int cleaned_count, int queue_id) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- struct edma_rx_free_desc *rx_desc; +- struct edma_sw_desc *sw_desc; +- struct sk_buff *skb; +- unsigned int i; +- u16 prod_idx, length; +- u32 reg_data; +- +- if (cleaned_count > erdr->count) +- cleaned_count = erdr->count - 1; +- +- i = erdr->sw_next_to_fill; +- +- while (cleaned_count) { +- sw_desc = &erdr->sw_desc[i]; +- length = edma_cinfo->rx_head_buffer_len; +- +- if (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_REUSE) { +- skb = sw_desc->skb; +- +- /* Clear REUSE Flag */ +- sw_desc->flags &= ~EDMA_SW_DESC_FLAG_SKB_REUSE; +- } else { +- /* alloc skb */ +- skb = netdev_alloc_skb_ip_align(edma_netdev[0], length); +- if (!skb) { +- /* Better luck next round */ +- break; +- } +- } +- +- if (edma_cinfo->page_mode) { +- struct page *pg = alloc_page(GFP_ATOMIC); +- +- if (!pg) { +- dev_kfree_skb_any(skb); +- break; +- } +- +- sw_desc->dma = dma_map_page(&pdev->dev, pg, 0, +- edma_cinfo->rx_page_buffer_len, +- DMA_FROM_DEVICE); +- if (dma_mapping_error(&pdev->dev, +- sw_desc->dma)) { +- __free_page(pg); +- dev_kfree_skb_any(skb); +- break; +- } +- +- skb_fill_page_desc(skb, 0, pg, 0, +- edma_cinfo->rx_page_buffer_len); +- sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_FRAG; +- sw_desc->length = edma_cinfo->rx_page_buffer_len; +- } else { +- sw_desc->dma = dma_map_single(&pdev->dev, skb->data, +- length, DMA_FROM_DEVICE); +- if (dma_mapping_error(&pdev->dev, +- sw_desc->dma)) { +- dev_kfree_skb_any(skb); +- break; +- } +- +- sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_HEAD; +- sw_desc->length = length; +- } +- +- /* Update the buffer info */ +- sw_desc->skb = skb; +- rx_desc = (&((struct edma_rx_free_desc *)(erdr->hw_desc))[i]); +- rx_desc->buffer_addr = cpu_to_le64(sw_desc->dma); +- if (++i == erdr->count) +- i = 0; +- cleaned_count--; +- } +- +- erdr->sw_next_to_fill = i; +- +- if (i == 0) +- prod_idx = erdr->count - 1; +- else +- prod_idx = i - 1; +- +- /* Update the producer index */ +- edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), ®_data); +- reg_data &= ~EDMA_RFD_PROD_IDX_BITS; +- reg_data |= prod_idx; +- edma_write_reg(EDMA_REG_RFD_IDX_Q(queue_id), reg_data); +- +- /* If we couldn't allocate all the buffers +- * we increment the alloc failure counters +- */ +- if (cleaned_count) +- edma_cinfo->edma_ethstats.rx_alloc_fail_ctr++; +- +- return cleaned_count; +-} +- +-/* edma_init_desc() +- * update descriptor ring size, buffer and producer/consumer index +- */ +-static void edma_init_desc(struct edma_common_info *edma_cinfo) +-{ +- struct edma_rfd_desc_ring *rfd_ring; +- struct edma_tx_desc_ring *etdr; +- int i = 0, j = 0; +- u32 data = 0; +- u16 hw_cons_idx = 0; +- +- /* Set the base address of every TPD ring. */ +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) { +- etdr = edma_cinfo->tpd_ring[i]; +- +- /* Update descriptor ring base address */ +- edma_write_reg(EDMA_REG_TPD_BASE_ADDR_Q(i), (u32)etdr->dma); +- edma_read_reg(EDMA_REG_TPD_IDX_Q(i), &data); +- +- /* Calculate hardware consumer index */ +- hw_cons_idx = (data >> EDMA_TPD_CONS_IDX_SHIFT) & 0xffff; +- etdr->sw_next_to_fill = hw_cons_idx; +- etdr->sw_next_to_clean = hw_cons_idx; +- data &= ~(EDMA_TPD_PROD_IDX_MASK << EDMA_TPD_PROD_IDX_SHIFT); +- data |= hw_cons_idx; +- +- /* update producer index */ +- edma_write_reg(EDMA_REG_TPD_IDX_Q(i), data); +- +- /* update SW consumer index register */ +- edma_write_reg(EDMA_REG_TX_SW_CONS_IDX_Q(i), hw_cons_idx); +- +- /* Set TPD ring size */ +- edma_write_reg(EDMA_REG_TPD_RING_SIZE, +- edma_cinfo->tx_ring_count & +- EDMA_TPD_RING_SIZE_MASK); +- } +- +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- rfd_ring = edma_cinfo->rfd_ring[j]; +- /* Update Receive Free descriptor ring base address */ +- edma_write_reg(EDMA_REG_RFD_BASE_ADDR_Q(j), +- (u32)(rfd_ring->dma)); +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +- +- data = edma_cinfo->rx_head_buffer_len; +- if (edma_cinfo->page_mode) +- data = edma_cinfo->rx_page_buffer_len; +- +- data &= EDMA_RX_BUF_SIZE_MASK; +- data <<= EDMA_RX_BUF_SIZE_SHIFT; +- +- /* Update RFD ring size and RX buffer size */ +- data |= (edma_cinfo->rx_ring_count & EDMA_RFD_RING_SIZE_MASK) +- << EDMA_RFD_RING_SIZE_SHIFT; +- +- edma_write_reg(EDMA_REG_RX_DESC0, data); +- +- /* Disable TX FIFO low watermark and high watermark */ +- edma_write_reg(EDMA_REG_TXF_WATER_MARK, 0); +- +- /* Load all of base address above */ +- edma_read_reg(EDMA_REG_TX_SRAM_PART, &data); +- data |= 1 << EDMA_LOAD_PTR_SHIFT; +- edma_write_reg(EDMA_REG_TX_SRAM_PART, data); +-} +- +-/* edma_receive_checksum +- * Api to check checksum on receive packets +- */ +-static void edma_receive_checksum(struct edma_rx_return_desc *rd, +- struct sk_buff *skb) +-{ +- skb_checksum_none_assert(skb); +- +- /* check the RRD IP/L4 checksum bit to see if +- * its set, which in turn indicates checksum +- * failure. +- */ +- if (rd->rrd6 & EDMA_RRD_CSUM_FAIL_MASK) +- return; +- +- skb->ip_summed = CHECKSUM_UNNECESSARY; +-} +- +-/* edma_clean_rfd() +- * clean up rx resourcers on error +- */ +-static void edma_clean_rfd(struct edma_rfd_desc_ring *erdr, u16 index) +-{ +- struct edma_rx_free_desc *rx_desc; +- struct edma_sw_desc *sw_desc; +- +- rx_desc = (&((struct edma_rx_free_desc *)(erdr->hw_desc))[index]); +- sw_desc = &erdr->sw_desc[index]; +- if (sw_desc->skb) { +- dev_kfree_skb_any(sw_desc->skb); +- sw_desc->skb = NULL; +- } +- +- memset(rx_desc, 0, sizeof(struct edma_rx_free_desc)); +-} +- +-/* edma_rx_complete_fraglist() +- * Complete Rx processing for fraglist skbs +- */ +-static void edma_rx_complete_stp_rstp(struct sk_buff *skb, int port_id, struct edma_rx_return_desc *rd) +-{ +- int i; +- u32 priority; +- u16 port_type; +- u8 mac_addr[EDMA_ETH_HDR_LEN]; +- +- port_type = (rd->rrd1 >> EDMA_RRD_PORT_TYPE_SHIFT) +- & EDMA_RRD_PORT_TYPE_MASK; +- /* if port type is 0x4, then only proceed with +- * other stp/rstp calculation +- */ +- if (port_type == EDMA_RX_ATH_HDR_RSTP_PORT_TYPE) { +- u8 bpdu_mac[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; +- +- /* calculate the frame priority */ +- priority = (rd->rrd1 >> EDMA_RRD_PRIORITY_SHIFT) +- & EDMA_RRD_PRIORITY_MASK; +- +- for (i = 0; i < EDMA_ETH_HDR_LEN; i++) +- mac_addr[i] = skb->data[i]; +- +- /* Check if destination mac addr is bpdu addr */ +- if (!memcmp(mac_addr, bpdu_mac, 6)) { +- /* destination mac address is BPDU +- * destination mac address, then add +- * atheros header to the packet. +- */ +- u16 athr_hdr = (EDMA_RX_ATH_HDR_VERSION << EDMA_RX_ATH_HDR_VERSION_SHIFT) | +- (priority << EDMA_RX_ATH_HDR_PRIORITY_SHIFT) | +- (EDMA_RX_ATH_HDR_RSTP_PORT_TYPE << EDMA_RX_ATH_PORT_TYPE_SHIFT) | port_id; +- skb_push(skb, 4); +- memcpy(skb->data, mac_addr, EDMA_ETH_HDR_LEN); +- *(uint16_t *)&skb->data[12] = htons(edma_ath_eth_type); +- *(uint16_t *)&skb->data[14] = htons(athr_hdr); +- } +- } +-} +- +-/* +- * edma_rx_complete_fraglist() +- * Complete Rx processing for fraglist skbs +- */ +-static int edma_rx_complete_fraglist(struct sk_buff *skb, u16 num_rfds, u16 length, u32 sw_next_to_clean, +- u16 *cleaned_count, struct edma_rfd_desc_ring *erdr, struct edma_common_info *edma_cinfo) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- struct edma_hw *hw = &edma_cinfo->hw; +- struct sk_buff *skb_temp; +- struct edma_sw_desc *sw_desc; +- int i; +- u16 size_remaining; +- +- skb->data_len = 0; +- skb->tail += (hw->rx_head_buff_size - 16); +- skb->len = skb->truesize = length; +- size_remaining = length - (hw->rx_head_buff_size - 16); +- +- /* clean-up all related sw_descs */ +- for (i = 1; i < num_rfds; i++) { +- struct sk_buff *skb_prev; +- sw_desc = &erdr->sw_desc[sw_next_to_clean]; +- skb_temp = sw_desc->skb; +- +- dma_unmap_single(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_FROM_DEVICE); +- +- if (size_remaining < hw->rx_head_buff_size) +- skb_put(skb_temp, size_remaining); +- else +- skb_put(skb_temp, hw->rx_head_buff_size); +- +- /* +- * If we are processing the first rfd, we link +- * skb->frag_list to the skb corresponding to the +- * first RFD +- */ +- if (i == 1) +- skb_shinfo(skb)->frag_list = skb_temp; +- else +- skb_prev->next = skb_temp; +- skb_prev = skb_temp; +- skb_temp->next = NULL; +- +- skb->data_len += skb_temp->len; +- size_remaining -= skb_temp->len; +- +- /* Increment SW index */ +- sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); +- (*cleaned_count)++; +- } +- +- return sw_next_to_clean; +-} +- +-/* edma_rx_complete_paged() +- * Complete Rx processing for paged skbs +- */ +-static int edma_rx_complete_paged(struct sk_buff *skb, u16 num_rfds, u16 length, u32 sw_next_to_clean, +- u16 *cleaned_count, struct edma_rfd_desc_ring *erdr, struct edma_common_info *edma_cinfo) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- struct sk_buff *skb_temp; +- struct edma_sw_desc *sw_desc; +- int i; +- u16 size_remaining; +- +- skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; +- +- /* Setup skbuff fields */ +- skb->len = length; +- +- if (likely(num_rfds <= 1)) { +- skb->data_len = length; +- skb->truesize += edma_cinfo->rx_page_buffer_len; +- skb_fill_page_desc(skb, 0, skb_frag_page(frag), +- 16, length); +- } else { +- skb_frag_size_sub(frag, 16); +- skb->data_len = skb_frag_size(frag); +- skb->truesize += edma_cinfo->rx_page_buffer_len; +- size_remaining = length - skb_frag_size(frag); +- +- skb_fill_page_desc(skb, 0, skb_frag_page(frag), +- 16, skb_frag_size(frag)); +- +- /* clean-up all related sw_descs */ +- for (i = 1; i < num_rfds; i++) { +- sw_desc = &erdr->sw_desc[sw_next_to_clean]; +- skb_temp = sw_desc->skb; +- frag = &skb_shinfo(skb_temp)->frags[0]; +- dma_unmap_page(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_FROM_DEVICE); +- +- if (size_remaining < edma_cinfo->rx_page_buffer_len) +- skb_frag_size_set(frag, size_remaining); +- +- skb_fill_page_desc(skb, i, skb_frag_page(frag), +- 0, skb_frag_size(frag)); +- +- skb_shinfo(skb_temp)->nr_frags = 0; +- dev_kfree_skb_any(skb_temp); +- +- skb->data_len += skb_frag_size(frag); +- skb->truesize += edma_cinfo->rx_page_buffer_len; +- size_remaining -= skb_frag_size(frag); +- +- /* Increment SW index */ +- sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); +- (*cleaned_count)++; +- } +- } +- +- return sw_next_to_clean; +-} +- +-/* +- * edma_rx_complete() +- * Main api called from the poll function to process rx packets. +- */ +-static u16 edma_rx_complete(struct edma_common_info *edma_cinfo, +- int *work_done, int work_to_do, int queue_id, +- struct napi_struct *napi) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- struct edma_rfd_desc_ring *erdr = edma_cinfo->rfd_ring[queue_id]; +- struct net_device *netdev; +- struct edma_adapter *adapter; +- struct edma_sw_desc *sw_desc; +- struct sk_buff *skb; +- struct edma_rx_return_desc *rd; +- u16 hash_type, rrd[8], cleaned_count = 0, length = 0, num_rfds = 1, +- sw_next_to_clean, hw_next_to_clean = 0, vlan = 0, ret_count = 0; +- u32 data = 0; +- u8 *vaddr; +- int port_id, i, drop_count = 0; +- u32 priority; +- u16 count = erdr->count, rfd_avail; +- u8 queue_to_rxid[8] = {0, 0, 1, 1, 2, 2, 3, 3}; +- +- cleaned_count = erdr->pending_fill; +- sw_next_to_clean = erdr->sw_next_to_clean; +- +- edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), &data); +- hw_next_to_clean = (data >> EDMA_RFD_CONS_IDX_SHIFT) & +- EDMA_RFD_CONS_IDX_MASK; +- +- do { +- while (sw_next_to_clean != hw_next_to_clean) { +- if (!work_to_do) +- break; +- +- sw_desc = &erdr->sw_desc[sw_next_to_clean]; +- skb = sw_desc->skb; +- +- /* Unmap the allocated buffer */ +- if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD)) +- dma_unmap_single(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_FROM_DEVICE); +- else +- dma_unmap_page(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_FROM_DEVICE); +- +- /* Get RRD */ +- if (edma_cinfo->page_mode) { +- vaddr = kmap_atomic(skb_frag_page(&skb_shinfo(skb)->frags[0])); +- memcpy((uint8_t *)&rrd[0], vaddr, 16); +- rd = (struct edma_rx_return_desc *)rrd; +- kunmap_atomic(vaddr); +- } else { +- rd = (struct edma_rx_return_desc *)skb->data; +- } +- +- /* Check if RRD is valid */ +- if (!(rd->rrd7 & EDMA_RRD_DESC_VALID)) { +- edma_clean_rfd(erdr, sw_next_to_clean); +- sw_next_to_clean = (sw_next_to_clean + 1) & +- (erdr->count - 1); +- cleaned_count++; +- continue; +- } +- +- /* Get the number of RFDs from RRD */ +- num_rfds = rd->rrd1 & EDMA_RRD_NUM_RFD_MASK; +- +- /* Get Rx port ID from switch */ +- port_id = (rd->rrd1 >> EDMA_PORT_ID_SHIFT) & EDMA_PORT_ID_MASK; +- if ((!port_id) || (port_id > EDMA_MAX_PORTID_SUPPORTED)) { +- dev_err(&pdev->dev, "Invalid RRD source port bit set"); +- for (i = 0; i < num_rfds; i++) { +- edma_clean_rfd(erdr, sw_next_to_clean); +- sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); +- cleaned_count++; +- } +- continue; +- } +- +- /* check if we have a sink for the data we receive. +- * If the interface isn't setup, we have to drop the +- * incoming data for now. +- */ +- netdev = edma_cinfo->portid_netdev_lookup_tbl[port_id]; +- if (!netdev) { +- edma_clean_rfd(erdr, sw_next_to_clean); +- sw_next_to_clean = (sw_next_to_clean + 1) & +- (erdr->count - 1); +- cleaned_count++; +- continue; +- } +- adapter = netdev_priv(netdev); +- +- /* This code is added to handle a usecase where high +- * priority stream and a low priority stream are +- * received simultaneously on DUT. The problem occurs +- * if one of the Rx rings is full and the corresponding +- * core is busy with other stuff. This causes ESS CPU +- * port to backpressure all incoming traffic including +- * high priority one. We monitor free descriptor count +- * on each CPU and whenever it reaches threshold (< 80), +- * we drop all low priority traffic and let only high +- * priotiy traffic pass through. We can hence avoid +- * ESS CPU port to send backpressure on high priroity +- * stream. +- */ +- priority = (rd->rrd1 >> EDMA_RRD_PRIORITY_SHIFT) +- & EDMA_RRD_PRIORITY_MASK; +- if (likely(!priority && !edma_cinfo->page_mode && (num_rfds <= 1))) { +- rfd_avail = (count + sw_next_to_clean - hw_next_to_clean - 1) & (count - 1); +- if (rfd_avail < EDMA_RFD_AVAIL_THR) { +- sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_REUSE; +- sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); +- adapter->stats.rx_dropped++; +- cleaned_count++; +- drop_count++; +- if (drop_count == 3) { +- work_to_do--; +- (*work_done)++; +- drop_count = 0; +- } +- if (cleaned_count >= EDMA_RX_BUFFER_WRITE) { +- /* If buffer clean count reaches 16, we replenish HW buffers. */ +- ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); +- edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), +- sw_next_to_clean); +- cleaned_count = ret_count; +- erdr->pending_fill = ret_count; +- } +- continue; +- } +- } +- +- work_to_do--; +- (*work_done)++; +- +- /* Increment SW index */ +- sw_next_to_clean = (sw_next_to_clean + 1) & +- (erdr->count - 1); +- +- cleaned_count++; +- +- /* Get the packet size and allocate buffer */ +- length = rd->rrd6 & EDMA_RRD_PKT_SIZE_MASK; +- +- if (edma_cinfo->page_mode) { +- /* paged skb */ +- sw_next_to_clean = edma_rx_complete_paged(skb, num_rfds, length, sw_next_to_clean, &cleaned_count, erdr, edma_cinfo); +- if (!pskb_may_pull(skb, ETH_HLEN)) { +- dev_kfree_skb_any(skb); +- continue; +- } +- } else { +- /* single or fraglist skb */ +- +- /* Addition of 16 bytes is required, as in the packet +- * first 16 bytes are rrd descriptors, so actual data +- * starts from an offset of 16. +- */ +- skb_reserve(skb, 16); +- if (likely((num_rfds <= 1) || !edma_cinfo->fraglist_mode)) { +- skb_put(skb, length); +- } else { +- sw_next_to_clean = edma_rx_complete_fraglist(skb, num_rfds, length, sw_next_to_clean, &cleaned_count, erdr, edma_cinfo); +- } +- } +- +- if (edma_stp_rstp) { +- edma_rx_complete_stp_rstp(skb, port_id, rd); +- } +- +- skb->protocol = eth_type_trans(skb, netdev); +- +- /* Record Rx queue for RFS/RPS and fill flow hash from HW */ +- skb_record_rx_queue(skb, queue_to_rxid[queue_id]); +- if (netdev->features & NETIF_F_RXHASH) { +- hash_type = (rd->rrd5 >> EDMA_HASH_TYPE_SHIFT); +- if ((hash_type > EDMA_HASH_TYPE_START) && (hash_type < EDMA_HASH_TYPE_END)) +- skb_set_hash(skb, rd->rrd2, PKT_HASH_TYPE_L4); +- } +- +-#ifdef CONFIG_NF_FLOW_COOKIE +- skb->flow_cookie = rd->rrd3 & EDMA_RRD_FLOW_COOKIE_MASK; +-#endif +- edma_receive_checksum(rd, skb); +- +- /* Process VLAN HW acceleration indication provided by HW */ +- if (unlikely(adapter->default_vlan_tag != rd->rrd4)) { +- vlan = rd->rrd4; +- if (likely(rd->rrd7 & EDMA_RRD_CVLAN)) +- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); +- else if (rd->rrd1 & EDMA_RRD_SVLAN) +- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan); +- } +- +- /* Update rx statistics */ +- adapter->stats.rx_packets++; +- adapter->stats.rx_bytes += length; +- +- /* Check if we reached refill threshold */ +- if (cleaned_count >= EDMA_RX_BUFFER_WRITE) { +- ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); +- edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), +- sw_next_to_clean); +- cleaned_count = ret_count; +- erdr->pending_fill = ret_count; +- } +- +- /* At this point skb should go to stack */ +- napi_gro_receive(napi, skb); +- } +- +- /* Check if we still have NAPI budget */ +- if (!work_to_do) +- break; +- +- /* Read index once again since we still have NAPI budget */ +- edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), &data); +- hw_next_to_clean = (data >> EDMA_RFD_CONS_IDX_SHIFT) & +- EDMA_RFD_CONS_IDX_MASK; +- } while (hw_next_to_clean != sw_next_to_clean); +- +- erdr->sw_next_to_clean = sw_next_to_clean; +- +- /* Refill here in case refill threshold wasn't reached */ +- if (likely(cleaned_count)) { +- ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); +- erdr->pending_fill = ret_count; +- if (ret_count) { +- if (net_ratelimit()) +- dev_dbg(&pdev->dev, "Not all buffers was reallocated"); +- } +- +- edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), +- erdr->sw_next_to_clean); +- } +- +- return erdr->pending_fill; +-} +- +-/* edma_delete_rfs_filter() +- * Remove RFS filter from switch +- */ +-static int edma_delete_rfs_filter(struct edma_adapter *adapter, +- struct edma_rfs_filter_node *filter_node) +-{ +- int res = -1; +- +- struct flow_keys *keys = &filter_node->keys; +- +- if (likely(adapter->set_rfs_rule)) +- res = (*adapter->set_rfs_rule)(adapter->netdev, +- flow_get_u32_src(keys), flow_get_u32_dst(keys), +- keys->ports.src, keys->ports.dst, +- keys->basic.ip_proto, filter_node->rq_id, 0); +- +- return res; +-} +- +-/* edma_add_rfs_filter() +- * Add RFS filter to switch +- */ +-static int edma_add_rfs_filter(struct edma_adapter *adapter, +- struct flow_keys *keys, u16 rq, +- struct edma_rfs_filter_node *filter_node) +-{ +- int res = -1; +- +- struct flow_keys *dest_keys = &filter_node->keys; +- +- memcpy(dest_keys, &filter_node->keys, sizeof(*dest_keys)); +-/* +- dest_keys->control = keys->control; +- dest_keys->basic = keys->basic; +- dest_keys->addrs = keys->addrs; +- dest_keys->ports = keys->ports; +- dest_keys.ip_proto = keys->ip_proto; +-*/ +- /* Call callback registered by ESS driver */ +- if (likely(adapter->set_rfs_rule)) +- res = (*adapter->set_rfs_rule)(adapter->netdev, flow_get_u32_src(keys), +- flow_get_u32_dst(keys), keys->ports.src, keys->ports.dst, +- keys->basic.ip_proto, rq, 1); +- +- return res; +-} +- +-/* edma_rfs_key_search() +- * Look for existing RFS entry +- */ +-static struct edma_rfs_filter_node *edma_rfs_key_search(struct hlist_head *h, +- struct flow_keys *key) +-{ +- struct edma_rfs_filter_node *p; +- +- hlist_for_each_entry(p, h, node) +- if (flow_get_u32_src(&p->keys) == flow_get_u32_src(key) && +- flow_get_u32_dst(&p->keys) == flow_get_u32_dst(key) && +- p->keys.ports.src == key->ports.src && +- p->keys.ports.dst == key->ports.dst && +- p->keys.basic.ip_proto == key->basic.ip_proto) +- return p; +- return NULL; +-} +- +-/* edma_initialise_rfs_flow_table() +- * Initialise EDMA RFS flow table +- */ +-static void edma_initialise_rfs_flow_table(struct edma_adapter *adapter) +-{ +- int i; +- +- spin_lock_init(&adapter->rfs.rfs_ftab_lock); +- +- /* Initialize EDMA flow hash table */ +- for (i = 0; i < EDMA_RFS_FLOW_ENTRIES; i++) +- INIT_HLIST_HEAD(&adapter->rfs.hlist_head[i]); +- +- adapter->rfs.max_num_filter = EDMA_RFS_FLOW_ENTRIES; +- adapter->rfs.filter_available = adapter->rfs.max_num_filter; +- adapter->rfs.hashtoclean = 0; +- +- /* Add timer to get periodic RFS updates from OS */ +- timer_setup(&adapter->rfs.expire_rfs, edma_flow_may_expire, 0); +- mod_timer(&adapter->rfs.expire_rfs, jiffies + HZ / 4); +-} +- +-/* edma_free_rfs_flow_table() +- * Free EDMA RFS flow table +- */ +-static void edma_free_rfs_flow_table(struct edma_adapter *adapter) +-{ +- int i; +- +- /* Remove sync timer */ +- del_timer_sync(&adapter->rfs.expire_rfs); +- spin_lock_bh(&adapter->rfs.rfs_ftab_lock); +- +- /* Free EDMA RFS table entries */ +- adapter->rfs.filter_available = 0; +- +- /* Clean-up EDMA flow hash table */ +- for (i = 0; i < EDMA_RFS_FLOW_ENTRIES; i++) { +- struct hlist_head *hhead; +- struct hlist_node *tmp; +- struct edma_rfs_filter_node *filter_node; +- int res; +- +- hhead = &adapter->rfs.hlist_head[i]; +- hlist_for_each_entry_safe(filter_node, tmp, hhead, node) { +- res = edma_delete_rfs_filter(adapter, filter_node); +- if (res < 0) +- dev_warn(&adapter->netdev->dev, +- "EDMA going down but RFS entry %d not allowed to be flushed by Switch", +- filter_node->flow_id); +- hlist_del(&filter_node->node); +- kfree(filter_node); +- } +- } +- spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +-} +- +-/* edma_tx_unmap_and_free() +- * clean TX buffer +- */ +-static inline void edma_tx_unmap_and_free(struct platform_device *pdev, +- struct edma_sw_desc *sw_desc) +-{ +- struct sk_buff *skb = sw_desc->skb; +- +- if (likely((sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD) || +- (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAGLIST))) +- /* unmap_single for skb head area */ +- dma_unmap_single(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_TO_DEVICE); +- else if (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAG) +- /* unmap page for paged fragments */ +- dma_unmap_page(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_TO_DEVICE); +- +- if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_LAST)) +- dev_kfree_skb_any(skb); +- +- sw_desc->flags = 0; +-} +- +-/* edma_tx_complete() +- * Used to clean tx queues and update hardware and consumer index +- */ +-static void edma_tx_complete(struct edma_common_info *edma_cinfo, int queue_id) +-{ +- struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; +- struct edma_sw_desc *sw_desc; +- struct platform_device *pdev = edma_cinfo->pdev; +- int i; +- +- u16 sw_next_to_clean = etdr->sw_next_to_clean; +- u16 hw_next_to_clean; +- u32 data = 0; +- +- edma_read_reg(EDMA_REG_TPD_IDX_Q(queue_id), &data); +- hw_next_to_clean = (data >> EDMA_TPD_CONS_IDX_SHIFT) & EDMA_TPD_CONS_IDX_MASK; +- +- /* clean the buffer here */ +- while (sw_next_to_clean != hw_next_to_clean) { +- sw_desc = &etdr->sw_desc[sw_next_to_clean]; +- edma_tx_unmap_and_free(pdev, sw_desc); +- sw_next_to_clean = (sw_next_to_clean + 1) & (etdr->count - 1); +- } +- +- etdr->sw_next_to_clean = sw_next_to_clean; +- +- /* update the TPD consumer index register */ +- edma_write_reg(EDMA_REG_TX_SW_CONS_IDX_Q(queue_id), sw_next_to_clean); +- +- /* Wake the queue if queue is stopped and netdev link is up */ +- for (i = 0; i < EDMA_MAX_NETDEV_PER_QUEUE && etdr->nq[i] ; i++) { +- if (netif_tx_queue_stopped(etdr->nq[i])) { +- if ((etdr->netdev[i]) && netif_carrier_ok(etdr->netdev[i])) +- netif_tx_wake_queue(etdr->nq[i]); +- } +- } +-} +- +-/* edma_get_tx_buffer() +- * Get sw_desc corresponding to the TPD +- */ +-static struct edma_sw_desc *edma_get_tx_buffer(struct edma_common_info *edma_cinfo, +- struct edma_tx_desc *tpd, int queue_id) +-{ +- struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; +- return &etdr->sw_desc[tpd - (struct edma_tx_desc *)etdr->hw_desc]; +-} +- +-/* edma_get_next_tpd() +- * Return a TPD descriptor for transfer +- */ +-static struct edma_tx_desc *edma_get_next_tpd(struct edma_common_info *edma_cinfo, +- int queue_id) +-{ +- struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; +- u16 sw_next_to_fill = etdr->sw_next_to_fill; +- struct edma_tx_desc *tpd_desc = +- (&((struct edma_tx_desc *)(etdr->hw_desc))[sw_next_to_fill]); +- +- etdr->sw_next_to_fill = (etdr->sw_next_to_fill + 1) & (etdr->count - 1); +- +- return tpd_desc; +-} +- +-/* edma_tpd_available() +- * Check number of free TPDs +- */ +-static inline u16 edma_tpd_available(struct edma_common_info *edma_cinfo, +- int queue_id) +-{ +- struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; +- +- u16 sw_next_to_fill; +- u16 sw_next_to_clean; +- u16 count = 0; +- +- sw_next_to_clean = etdr->sw_next_to_clean; +- sw_next_to_fill = etdr->sw_next_to_fill; +- +- if (likely(sw_next_to_clean <= sw_next_to_fill)) +- count = etdr->count; +- +- return count + sw_next_to_clean - sw_next_to_fill - 1; +-} +- +-/* edma_tx_queue_get() +- * Get the starting number of the queue +- */ +-static inline int edma_tx_queue_get(struct edma_adapter *adapter, +- struct sk_buff *skb, int txq_id) +-{ +- /* skb->priority is used as an index to skb priority table +- * and based on packet priority, correspong queue is assigned. +- */ +- return adapter->tx_start_offset[txq_id] + edma_skb_priority_offset(skb); +-} +- +-/* edma_tx_update_hw_idx() +- * update the producer index for the ring transmitted +- */ +-static void edma_tx_update_hw_idx(struct edma_common_info *edma_cinfo, +- struct sk_buff *skb, int queue_id) +-{ +- struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; +- u32 tpd_idx_data; +- +- /* Read and update the producer index */ +- edma_read_reg(EDMA_REG_TPD_IDX_Q(queue_id), &tpd_idx_data); +- tpd_idx_data &= ~EDMA_TPD_PROD_IDX_BITS; +- tpd_idx_data |= (etdr->sw_next_to_fill & EDMA_TPD_PROD_IDX_MASK) +- << EDMA_TPD_PROD_IDX_SHIFT; +- +- edma_write_reg(EDMA_REG_TPD_IDX_Q(queue_id), tpd_idx_data); +-} +- +-/* edma_rollback_tx() +- * Function to retrieve tx resources in case of error +- */ +-static void edma_rollback_tx(struct edma_adapter *adapter, +- struct edma_tx_desc *start_tpd, int queue_id) +-{ +- struct edma_tx_desc_ring *etdr = adapter->edma_cinfo->tpd_ring[queue_id]; +- struct edma_sw_desc *sw_desc; +- struct edma_tx_desc *tpd = NULL; +- u16 start_index, index; +- +- start_index = start_tpd - (struct edma_tx_desc *)(etdr->hw_desc); +- +- index = start_index; +- while (index != etdr->sw_next_to_fill) { +- tpd = (&((struct edma_tx_desc *)(etdr->hw_desc))[index]); +- sw_desc = &etdr->sw_desc[index]; +- edma_tx_unmap_and_free(adapter->pdev, sw_desc); +- memset(tpd, 0, sizeof(struct edma_tx_desc)); +- if (++index == etdr->count) +- index = 0; +- } +- etdr->sw_next_to_fill = start_index; +-} +- +-/* edma_tx_map_and_fill() +- * gets called from edma_xmit_frame +- * +- * This is where the dma of the buffer to be transmitted +- * gets mapped +- */ +-static int edma_tx_map_and_fill(struct edma_common_info *edma_cinfo, +- struct edma_adapter *adapter, struct sk_buff *skb, int queue_id, +- unsigned int flags_transmit, u16 from_cpu, u16 dp_bitmap, +- bool packet_is_rstp, int nr_frags) +-{ +- struct edma_sw_desc *sw_desc = NULL; +- struct platform_device *pdev = edma_cinfo->pdev; +- struct edma_tx_desc *tpd = NULL, *start_tpd = NULL; +- struct sk_buff *iter_skb; +- int i = 0; +- u32 word1 = 0, word3 = 0, lso_word1 = 0, svlan_tag = 0; +- u16 buf_len, lso_desc_len = 0; +- +- /* It should either be a nr_frags skb or fraglist skb but not both */ +- BUG_ON(nr_frags && skb_has_frag_list(skb)); +- +- if (skb_is_gso(skb)) { +- /* TODO: What additional checks need to be performed here */ +- if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { +- lso_word1 |= EDMA_TPD_IPV4_EN; +- ip_hdr(skb)->check = 0; +- tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, +- ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); +- } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { +- lso_word1 |= EDMA_TPD_LSO_V2_EN; +- ipv6_hdr(skb)->payload_len = 0; +- tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, +- &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); +- } else +- return -EINVAL; +- +- lso_word1 |= EDMA_TPD_LSO_EN | ((skb_shinfo(skb)->gso_size & EDMA_TPD_MSS_MASK) << EDMA_TPD_MSS_SHIFT) | +- (skb_transport_offset(skb) << EDMA_TPD_HDR_SHIFT); +- } else if (flags_transmit & EDMA_HW_CHECKSUM) { +- u8 css, cso; +- cso = skb_checksum_start_offset(skb); +- css = cso + skb->csum_offset; +- +- word1 |= (EDMA_TPD_CUSTOM_CSUM_EN); +- word1 |= (cso >> 1) << EDMA_TPD_HDR_SHIFT; +- word1 |= ((css >> 1) << EDMA_TPD_CUSTOM_CSUM_SHIFT); +- } +- +- if (skb->protocol == htons(ETH_P_PPP_SES)) +- word1 |= EDMA_TPD_PPPOE_EN; +- +- if (flags_transmit & EDMA_VLAN_TX_TAG_INSERT_FLAG) { +- switch(skb->vlan_proto) { +- case htons(ETH_P_8021Q): +- word3 |= (1 << EDMA_TX_INS_CVLAN); +- word3 |= skb_vlan_tag_get(skb) << EDMA_TX_CVLAN_TAG_SHIFT; +- break; +- case htons(ETH_P_8021AD): +- word1 |= (1 << EDMA_TX_INS_SVLAN); +- svlan_tag = skb_vlan_tag_get(skb) << EDMA_TX_SVLAN_TAG_SHIFT; +- break; +- default: +- dev_err(&pdev->dev, "no ctag or stag present\n"); +- goto vlan_tag_error; +- } +- } else if (flags_transmit & EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG) { +- word3 |= (1 << EDMA_TX_INS_CVLAN); +- word3 |= (adapter->default_vlan_tag) << EDMA_TX_CVLAN_TAG_SHIFT; +- } +- +- if (packet_is_rstp) { +- word3 |= dp_bitmap << EDMA_TPD_PORT_BITMAP_SHIFT; +- word3 |= from_cpu << EDMA_TPD_FROM_CPU_SHIFT; +- } else { +- word3 |= adapter->dp_bitmap << EDMA_TPD_PORT_BITMAP_SHIFT; +- } +- +- buf_len = skb_headlen(skb); +- +- if (lso_word1) { +- if (lso_word1 & EDMA_TPD_LSO_V2_EN) { +- +- /* IPv6 LSOv2 descriptor */ +- start_tpd = tpd = edma_get_next_tpd(edma_cinfo, queue_id); +- sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); +- sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_NONE; +- +- /* LSOv2 descriptor overrides addr field to pass length */ +- tpd->addr = cpu_to_le16(skb->len); +- tpd->svlan_tag = svlan_tag; +- tpd->word1 = word1 | lso_word1; +- tpd->word3 = word3; +- } +- +- tpd = edma_get_next_tpd(edma_cinfo, queue_id); +- if (!start_tpd) +- start_tpd = tpd; +- sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); +- +- /* The last buffer info contain the skb address, +- * so skb will be freed after unmap +- */ +- sw_desc->length = lso_desc_len; +- sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; +- +- sw_desc->dma = dma_map_single(&adapter->pdev->dev, +- skb->data, buf_len, DMA_TO_DEVICE); +- if (dma_mapping_error(&pdev->dev, sw_desc->dma)) +- goto dma_error; +- +- tpd->addr = cpu_to_le32(sw_desc->dma); +- tpd->len = cpu_to_le16(buf_len); +- +- tpd->svlan_tag = svlan_tag; +- tpd->word1 = word1 | lso_word1; +- tpd->word3 = word3; +- +- /* The last buffer info contain the skb address, +- * so it will be freed after unmap +- */ +- sw_desc->length = lso_desc_len; +- sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; +- +- buf_len = 0; +- } +- +- if (likely(buf_len)) { +- +- /* TODO Do not dequeue descriptor if there is a potential error */ +- tpd = edma_get_next_tpd(edma_cinfo, queue_id); +- +- if (!start_tpd) +- start_tpd = tpd; +- +- sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); +- +- /* The last buffer info contain the skb address, +- * so it will be free after unmap +- */ +- sw_desc->length = buf_len; +- sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; +- sw_desc->dma = dma_map_single(&adapter->pdev->dev, +- skb->data, buf_len, DMA_TO_DEVICE); +- if (dma_mapping_error(&pdev->dev, sw_desc->dma)) +- goto dma_error; +- +- tpd->addr = cpu_to_le32(sw_desc->dma); +- tpd->len = cpu_to_le16(buf_len); +- +- tpd->svlan_tag = svlan_tag; +- tpd->word1 = word1 | lso_word1; +- tpd->word3 = word3; +- } +- +- /* Walk through all paged fragments */ +- while (nr_frags--) { +- skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; +- buf_len = skb_frag_size(frag); +- tpd = edma_get_next_tpd(edma_cinfo, queue_id); +- sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); +- sw_desc->length = buf_len; +- sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_FRAG; +- +- sw_desc->dma = skb_frag_dma_map(&pdev->dev, frag, 0, buf_len, DMA_TO_DEVICE); +- +- if (dma_mapping_error(NULL, sw_desc->dma)) +- goto dma_error; +- +- tpd->addr = cpu_to_le32(sw_desc->dma); +- tpd->len = cpu_to_le16(buf_len); +- +- tpd->svlan_tag = svlan_tag; +- tpd->word1 = word1 | lso_word1; +- tpd->word3 = word3; +- i++; +- } +- +- /* Walk through all fraglist skbs */ +- skb_walk_frags(skb, iter_skb) { +- buf_len = iter_skb->len; +- tpd = edma_get_next_tpd(edma_cinfo, queue_id); +- sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); +- sw_desc->length = buf_len; +- sw_desc->dma = dma_map_single(&adapter->pdev->dev, +- iter_skb->data, buf_len, DMA_TO_DEVICE); +- +- if (dma_mapping_error(NULL, sw_desc->dma)) +- goto dma_error; +- +- tpd->addr = cpu_to_le32(sw_desc->dma); +- tpd->len = cpu_to_le16(buf_len); +- tpd->svlan_tag = svlan_tag; +- tpd->word1 = word1 | lso_word1; +- tpd->word3 = word3; +- sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_FRAGLIST; +- } +- +- if (tpd) +- tpd->word1 |= 1 << EDMA_TPD_EOP_SHIFT; +- +- sw_desc->skb = skb; +- sw_desc->flags |= EDMA_SW_DESC_FLAG_LAST; +- +- return 0; +- +-dma_error: +- edma_rollback_tx(adapter, start_tpd, queue_id); +- dev_err(&pdev->dev, "TX DMA map failed\n"); +-vlan_tag_error: +- return -ENOMEM; +-} +- +-/* edma_check_link() +- * check Link status +- */ +-static int edma_check_link(struct edma_adapter *adapter) +-{ +- struct phy_device *phydev = adapter->phydev; +- +- if (!(adapter->poll_required)) +- return __EDMA_LINKUP; +- +- if (phydev->link) +- return __EDMA_LINKUP; +- +- return __EDMA_LINKDOWN; +-} +- +-/* edma_adjust_link() +- * check for edma link status +- */ +-void edma_adjust_link(struct net_device *netdev) +-{ +- int status; +- struct edma_adapter *adapter = netdev_priv(netdev); +- struct phy_device *phydev = adapter->phydev; +- +- if (!test_bit(__EDMA_UP, &adapter->state_flags)) +- return; +- +- status = edma_check_link(adapter); +- +- if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) { +- phy_print_status(phydev); +- adapter->link_state = __EDMA_LINKUP; +- if (adapter->edma_cinfo->is_single_phy) { +- ess_set_port_status_speed(adapter->edma_cinfo, phydev, +- ffs(adapter->dp_bitmap) - 1); +- } +- netif_carrier_on(netdev); +- if (netif_running(netdev)) +- netif_tx_wake_all_queues(netdev); +- } else if (status == __EDMA_LINKDOWN && adapter->link_state == __EDMA_LINKUP) { +- phy_print_status(phydev); +- adapter->link_state = __EDMA_LINKDOWN; +- netif_carrier_off(netdev); +- netif_tx_stop_all_queues(netdev); +- } +-} +- +-/* edma_get_stats() +- * Statistics api used to retreive the tx/rx statistics +- */ +-struct net_device_stats *edma_get_stats(struct net_device *netdev) +-{ +- struct edma_adapter *adapter = netdev_priv(netdev); +- +- return &adapter->stats; +-} +- +-/* edma_xmit() +- * Main api to be called by the core for packet transmission +- */ +-netdev_tx_t edma_xmit(struct sk_buff *skb, +- struct net_device *net_dev) +-{ +- struct edma_adapter *adapter = netdev_priv(net_dev); +- struct edma_common_info *edma_cinfo = adapter->edma_cinfo; +- struct edma_tx_desc_ring *etdr; +- u16 from_cpu, dp_bitmap, txq_id; +- int ret, nr_frags = 0, num_tpds_needed = 1, queue_id; +- unsigned int flags_transmit = 0; +- bool packet_is_rstp = false; +- struct netdev_queue *nq = NULL; +- +- if (skb_shinfo(skb)->nr_frags) { +- nr_frags = skb_shinfo(skb)->nr_frags; +- num_tpds_needed += nr_frags; +- } else if (skb_has_frag_list(skb)) { +- struct sk_buff *iter_skb; +- +- skb_walk_frags(skb, iter_skb) +- num_tpds_needed++; +- } +- +- if (num_tpds_needed > EDMA_MAX_SKB_FRAGS) { +- dev_err(&net_dev->dev, +- "skb received with fragments %d which is more than %lu", +- num_tpds_needed, EDMA_MAX_SKB_FRAGS); +- dev_kfree_skb_any(skb); +- adapter->stats.tx_errors++; +- return NETDEV_TX_OK; +- } +- +- if (edma_stp_rstp) { +- u16 ath_hdr, ath_eth_type; +- u8 mac_addr[EDMA_ETH_HDR_LEN]; +- ath_eth_type = ntohs(*(uint16_t *)&skb->data[12]); +- if (ath_eth_type == edma_ath_eth_type) { +- packet_is_rstp = true; +- ath_hdr = htons(*(uint16_t *)&skb->data[14]); +- dp_bitmap = ath_hdr & EDMA_TX_ATH_HDR_PORT_BITMAP_MASK; +- from_cpu = (ath_hdr & EDMA_TX_ATH_HDR_FROM_CPU_MASK) >> EDMA_TX_ATH_HDR_FROM_CPU_SHIFT; +- memcpy(mac_addr, skb->data, EDMA_ETH_HDR_LEN); +- +- skb_pull(skb, 4); +- +- memcpy(skb->data, mac_addr, EDMA_ETH_HDR_LEN); +- } +- } +- +- /* this will be one of the 4 TX queues exposed to linux kernel */ +- txq_id = skb_get_queue_mapping(skb); +- queue_id = edma_tx_queue_get(adapter, skb, txq_id); +- etdr = edma_cinfo->tpd_ring[queue_id]; +- nq = netdev_get_tx_queue(net_dev, txq_id); +- +- local_bh_disable(); +- /* Tx is not handled in bottom half context. Hence, we need to protect +- * Tx from tasks and bottom half +- */ +- +- if (num_tpds_needed > edma_tpd_available(edma_cinfo, queue_id)) { +- /* not enough descriptor, just stop queue */ +- netif_tx_stop_queue(nq); +- local_bh_enable(); +- dev_dbg(&net_dev->dev, "Not enough descriptors available"); +- edma_cinfo->edma_ethstats.tx_desc_error++; +- return NETDEV_TX_BUSY; +- } +- +- /* Check and mark VLAN tag offload */ +- if (unlikely(skb_vlan_tag_present(skb))) +- flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; +- else if (!adapter->edma_cinfo->is_single_phy && adapter->default_vlan_tag) +- flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; +- +- /* Check and mark checksum offload */ +- if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) +- flags_transmit |= EDMA_HW_CHECKSUM; +- +- /* Map and fill descriptor for Tx */ +- ret = edma_tx_map_and_fill(edma_cinfo, adapter, skb, queue_id, +- flags_transmit, from_cpu, dp_bitmap, packet_is_rstp, nr_frags); +- if (ret) { +- dev_kfree_skb_any(skb); +- adapter->stats.tx_errors++; +- goto netdev_okay; +- } +- +- /* Update SW producer index */ +- edma_tx_update_hw_idx(edma_cinfo, skb, queue_id); +- +- /* update tx statistics */ +- adapter->stats.tx_packets++; +- adapter->stats.tx_bytes += skb->len; +- +-netdev_okay: +- local_bh_enable(); +- return NETDEV_TX_OK; +-} +- +-/* +- * edma_flow_may_expire() +- * Timer function called periodically to delete the node +- */ +-void edma_flow_may_expire(struct timer_list *t) +-{ +- struct edma_rfs_flow_table *table = from_timer(table, t, expire_rfs); +- struct edma_adapter *adapter = +- container_of(table, typeof(*adapter), rfs); +- int j; +- +- spin_lock_bh(&adapter->rfs.rfs_ftab_lock); +- for (j = 0; j < EDMA_RFS_EXPIRE_COUNT_PER_CALL; j++) { +- struct hlist_head *hhead; +- struct hlist_node *tmp; +- struct edma_rfs_filter_node *n; +- bool res; +- +- hhead = &adapter->rfs.hlist_head[adapter->rfs.hashtoclean++]; +- hlist_for_each_entry_safe(n, tmp, hhead, node) { +- res = rps_may_expire_flow(adapter->netdev, n->rq_id, +- n->flow_id, n->filter_id); +- if (res) { +- int ret; +- ret = edma_delete_rfs_filter(adapter, n); +- if (ret < 0) +- dev_dbg(&adapter->netdev->dev, +- "RFS entry %d not allowed to be flushed by Switch", +- n->flow_id); +- else { +- hlist_del(&n->node); +- kfree(n); +- adapter->rfs.filter_available++; +- } +- } +- } +- } +- +- adapter->rfs.hashtoclean = adapter->rfs.hashtoclean & (EDMA_RFS_FLOW_ENTRIES - 1); +- spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +- mod_timer(&adapter->rfs.expire_rfs, jiffies + HZ / 4); +-} +- +-/* edma_rx_flow_steer() +- * Called by core to to steer the flow to CPU +- */ +-int edma_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, +- u16 rxq, u32 flow_id) +-{ +- struct flow_keys keys; +- struct edma_rfs_filter_node *filter_node; +- struct edma_adapter *adapter = netdev_priv(dev); +- u16 hash_tblid; +- int res; +- +- if (skb->protocol == htons(ETH_P_IPV6)) { +- dev_err(&adapter->pdev->dev, "IPv6 not supported\n"); +- res = -EINVAL; +- goto no_protocol_err; +- } +- +- /* Dissect flow parameters +- * We only support IPv4 + TCP/UDP +- */ +- res = skb_flow_dissect_flow_keys(skb, &keys, 0); +- if (!((keys.basic.ip_proto == IPPROTO_TCP) || (keys.basic.ip_proto == IPPROTO_UDP))) { +- res = -EPROTONOSUPPORT; +- goto no_protocol_err; +- } +- +- /* Check if table entry exists */ +- hash_tblid = skb_get_hash_raw(skb) & EDMA_RFS_FLOW_ENTRIES_MASK; +- +- spin_lock_bh(&adapter->rfs.rfs_ftab_lock); +- filter_node = edma_rfs_key_search(&adapter->rfs.hlist_head[hash_tblid], &keys); +- +- if (filter_node) { +- if (rxq == filter_node->rq_id) { +- res = -EEXIST; +- goto out; +- } else { +- res = edma_delete_rfs_filter(adapter, filter_node); +- if (res < 0) +- dev_warn(&adapter->netdev->dev, +- "Cannot steer flow %d to different queue", +- filter_node->flow_id); +- else { +- adapter->rfs.filter_available++; +- res = edma_add_rfs_filter(adapter, &keys, rxq, filter_node); +- if (res < 0) { +- dev_warn(&adapter->netdev->dev, +- "Cannot steer flow %d to different queue", +- filter_node->flow_id); +- } else { +- adapter->rfs.filter_available--; +- filter_node->rq_id = rxq; +- filter_node->filter_id = res; +- } +- } +- } +- } else { +- if (adapter->rfs.filter_available == 0) { +- res = -EBUSY; +- goto out; +- } +- +- filter_node = kmalloc(sizeof(*filter_node), GFP_ATOMIC); +- if (!filter_node) { +- res = -ENOMEM; +- goto out; +- } +- +- res = edma_add_rfs_filter(adapter, &keys, rxq, filter_node); +- if (res < 0) { +- kfree(filter_node); +- goto out; +- } +- +- adapter->rfs.filter_available--; +- filter_node->rq_id = rxq; +- filter_node->filter_id = res; +- filter_node->flow_id = flow_id; +- filter_node->keys = keys; +- INIT_HLIST_NODE(&filter_node->node); +- hlist_add_head(&filter_node->node, &adapter->rfs.hlist_head[hash_tblid]); +- } +- +-out: +- spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +-no_protocol_err: +- return res; +-} +- +-/* edma_register_rfs_filter() +- * Add RFS filter callback +- */ +-int edma_register_rfs_filter(struct net_device *netdev, +- set_rfs_filter_callback_t set_filter) +-{ +- struct edma_adapter *adapter = netdev_priv(netdev); +- +- spin_lock_bh(&adapter->rfs.rfs_ftab_lock); +- +- if (adapter->set_rfs_rule) { +- spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +- return -1; +- } +- +- adapter->set_rfs_rule = set_filter; +- spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +- +- return 0; +-} +- +-/* edma_alloc_tx_rings() +- * Allocate rx rings +- */ +-int edma_alloc_tx_rings(struct edma_common_info *edma_cinfo) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- int i, err = 0; +- +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) { +- err = edma_alloc_tx_ring(edma_cinfo, edma_cinfo->tpd_ring[i]); +- if (err) { +- dev_err(&pdev->dev, "Tx Queue alloc %u failed\n", i); +- return err; +- } +- } +- +- return 0; +-} +- +-/* edma_free_tx_rings() +- * Free tx rings +- */ +-void edma_free_tx_rings(struct edma_common_info *edma_cinfo) +-{ +- int i; +- +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) +- edma_free_tx_ring(edma_cinfo, edma_cinfo->tpd_ring[i]); +-} +- +-/* edma_free_tx_resources() +- * Free buffers associated with tx rings +- */ +-void edma_free_tx_resources(struct edma_common_info *edma_cinfo) +-{ +- struct edma_tx_desc_ring *etdr; +- struct edma_sw_desc *sw_desc; +- struct platform_device *pdev = edma_cinfo->pdev; +- int i, j; +- +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) { +- etdr = edma_cinfo->tpd_ring[i]; +- for (j = 0; j < EDMA_TX_RING_SIZE; j++) { +- sw_desc = &etdr->sw_desc[j]; +- if (sw_desc->flags & (EDMA_SW_DESC_FLAG_SKB_HEAD | +- EDMA_SW_DESC_FLAG_SKB_FRAG | EDMA_SW_DESC_FLAG_SKB_FRAGLIST)) +- edma_tx_unmap_and_free(pdev, sw_desc); +- } +- } +-} +- +-/* edma_alloc_rx_rings() +- * Allocate rx rings +- */ +-int edma_alloc_rx_rings(struct edma_common_info *edma_cinfo) +-{ +- struct platform_device *pdev = edma_cinfo->pdev; +- int i, j, err = 0; +- +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- err = edma_alloc_rx_ring(edma_cinfo, edma_cinfo->rfd_ring[j]); +- if (err) { +- dev_err(&pdev->dev, "Rx Queue alloc%u failed\n", i); +- return err; +- } +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +- +- return 0; +-} +- +-/* edma_free_rx_rings() +- * free rx rings +- */ +-void edma_free_rx_rings(struct edma_common_info *edma_cinfo) +-{ +- int i, j; +- +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- edma_free_rx_ring(edma_cinfo, edma_cinfo->rfd_ring[j]); +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +-} +- +-/* edma_free_queues() +- * Free the queues allocaated +- */ +-void edma_free_queues(struct edma_common_info *edma_cinfo) +-{ +- int i , j; +- +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) { +- if (edma_cinfo->tpd_ring[i]) +- kfree(edma_cinfo->tpd_ring[i]); +- edma_cinfo->tpd_ring[i] = NULL; +- } +- +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- if (edma_cinfo->rfd_ring[j]) +- kfree(edma_cinfo->rfd_ring[j]); +- edma_cinfo->rfd_ring[j] = NULL; +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +- +- edma_cinfo->num_rx_queues = 0; +- edma_cinfo->num_tx_queues = 0; +- +- return; +-} +- +-/* edma_free_rx_resources() +- * Free buffers associated with tx rings +- */ +-void edma_free_rx_resources(struct edma_common_info *edma_cinfo) +-{ +- struct edma_rfd_desc_ring *erdr; +- struct edma_sw_desc *sw_desc; +- struct platform_device *pdev = edma_cinfo->pdev; +- int i, j, k; +- +- for (i = 0, k = 0; i < edma_cinfo->num_rx_queues; i++) { +- erdr = edma_cinfo->rfd_ring[k]; +- for (j = 0; j < EDMA_RX_RING_SIZE; j++) { +- sw_desc = &erdr->sw_desc[j]; +- if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD)) { +- dma_unmap_single(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_FROM_DEVICE); +- edma_clean_rfd(erdr, j); +- } else if ((sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAG)) { +- dma_unmap_page(&pdev->dev, sw_desc->dma, +- sw_desc->length, DMA_FROM_DEVICE); +- edma_clean_rfd(erdr, j); +- } +- } +- k += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- +- } +-} +- +-/* edma_alloc_queues_tx() +- * Allocate memory for all rings +- */ +-int edma_alloc_queues_tx(struct edma_common_info *edma_cinfo) +-{ +- int i; +- +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) { +- struct edma_tx_desc_ring *etdr; +- etdr = kzalloc(sizeof(struct edma_tx_desc_ring), GFP_KERNEL); +- if (!etdr) +- goto err; +- etdr->count = edma_cinfo->tx_ring_count; +- edma_cinfo->tpd_ring[i] = etdr; +- } +- +- return 0; +-err: +- edma_free_queues(edma_cinfo); +- return -1; +-} +- +-/* edma_alloc_queues_rx() +- * Allocate memory for all rings +- */ +-int edma_alloc_queues_rx(struct edma_common_info *edma_cinfo) +-{ +- int i, j; +- +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- struct edma_rfd_desc_ring *rfd_ring; +- rfd_ring = kzalloc(sizeof(struct edma_rfd_desc_ring), +- GFP_KERNEL); +- if (!rfd_ring) +- goto err; +- rfd_ring->count = edma_cinfo->rx_ring_count; +- edma_cinfo->rfd_ring[j] = rfd_ring; +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +- return 0; +-err: +- edma_free_queues(edma_cinfo); +- return -1; +-} +- +-/* edma_clear_irq_status() +- * Clear interrupt status +- */ +-void edma_clear_irq_status() +-{ +- edma_write_reg(EDMA_REG_RX_ISR, 0xff); +- edma_write_reg(EDMA_REG_TX_ISR, 0xffff); +- edma_write_reg(EDMA_REG_MISC_ISR, 0x1fff); +- edma_write_reg(EDMA_REG_WOL_ISR, 0x1); +-}; +- +-/* edma_configure() +- * Configure skb, edma interrupts and control register. +- */ +-int edma_configure(struct edma_common_info *edma_cinfo) +-{ +- struct edma_hw *hw = &edma_cinfo->hw; +- u32 intr_modrt_data; +- u32 intr_ctrl_data = 0; +- int i, j, ret_count; +- +- edma_read_reg(EDMA_REG_INTR_CTRL, &intr_ctrl_data); +- intr_ctrl_data &= ~(1 << EDMA_INTR_SW_IDX_W_TYP_SHIFT); +- intr_ctrl_data |= hw->intr_sw_idx_w << EDMA_INTR_SW_IDX_W_TYP_SHIFT; +- edma_write_reg(EDMA_REG_INTR_CTRL, intr_ctrl_data); +- +- edma_clear_irq_status(); +- +- /* Clear any WOL status */ +- edma_write_reg(EDMA_REG_WOL_CTRL, 0); +- intr_modrt_data = (EDMA_TX_IMT << EDMA_IRQ_MODRT_TX_TIMER_SHIFT); +- intr_modrt_data |= (EDMA_RX_IMT << EDMA_IRQ_MODRT_RX_TIMER_SHIFT); +- edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data); +- edma_configure_tx(edma_cinfo); +- edma_configure_rx(edma_cinfo); +- +- /* Allocate the RX buffer */ +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- struct edma_rfd_desc_ring *ring = edma_cinfo->rfd_ring[j]; +- ret_count = edma_alloc_rx_buf(edma_cinfo, ring, ring->count, j); +- if (ret_count) { +- dev_dbg(&edma_cinfo->pdev->dev, "not all rx buffers allocated\n"); +- } +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +- +- /* Configure descriptor Ring */ +- edma_init_desc(edma_cinfo); +- return 0; +-} +- +-/* edma_irq_enable() +- * Enable default interrupt generation settings +- */ +-void edma_irq_enable(struct edma_common_info *edma_cinfo) +-{ +- struct edma_hw *hw = &edma_cinfo->hw; +- int i, j; +- +- edma_write_reg(EDMA_REG_RX_ISR, 0xff); +- for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { +- edma_write_reg(EDMA_REG_RX_INT_MASK_Q(j), hw->rx_intr_mask); +- j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); +- } +- edma_write_reg(EDMA_REG_TX_ISR, 0xffff); +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) +- edma_write_reg(EDMA_REG_TX_INT_MASK_Q(i), hw->tx_intr_mask); +-} +- +-/* edma_irq_disable() +- * Disable Interrupt +- */ +-void edma_irq_disable(struct edma_common_info *edma_cinfo) +-{ +- int i; +- +- for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) +- edma_write_reg(EDMA_REG_RX_INT_MASK_Q(i), 0x0); +- +- for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) +- edma_write_reg(EDMA_REG_TX_INT_MASK_Q(i), 0x0); +- edma_write_reg(EDMA_REG_MISC_IMR, 0); +- edma_write_reg(EDMA_REG_WOL_IMR, 0); +-} +- +-/* edma_free_irqs() +- * Free All IRQs +- */ +-void edma_free_irqs(struct edma_adapter *adapter) +-{ +- struct edma_common_info *edma_cinfo = adapter->edma_cinfo; +- int i, j; +- int k = ((edma_cinfo->num_rx_queues == 4) ? 1 : 2); +- +- for (i = 0; i < CONFIG_NR_CPUS; i++) { +- for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + 4); j++) +- free_irq(edma_cinfo->tx_irq[j], &edma_cinfo->edma_percpu_info[i]); +- +- for (j = edma_cinfo->edma_percpu_info[i].rx_start; j < (edma_cinfo->edma_percpu_info[i].rx_start + k); j++) +- free_irq(edma_cinfo->rx_irq[j], &edma_cinfo->edma_percpu_info[i]); +- } +-} +- +-/* edma_enable_rx_ctrl() +- * Enable RX queue control +- */ +-void edma_enable_rx_ctrl(struct edma_hw *hw) +-{ +- u32 data; +- +- edma_read_reg(EDMA_REG_RXQ_CTRL, &data); +- data |= EDMA_RXQ_CTRL_EN; +- edma_write_reg(EDMA_REG_RXQ_CTRL, data); +-} +- +- +-/* edma_enable_tx_ctrl() +- * Enable TX queue control +- */ +-void edma_enable_tx_ctrl(struct edma_hw *hw) +-{ +- u32 data; +- +- edma_read_reg(EDMA_REG_TXQ_CTRL, &data); +- data |= EDMA_TXQ_CTRL_TXQ_EN; +- edma_write_reg(EDMA_REG_TXQ_CTRL, data); +-} +- +-/* edma_stop_rx_tx() +- * Disable RX/TQ Queue control +- */ +-void edma_stop_rx_tx(struct edma_hw *hw) +-{ +- u32 data; +- +- edma_read_reg(EDMA_REG_RXQ_CTRL, &data); +- data &= ~EDMA_RXQ_CTRL_EN; +- edma_write_reg(EDMA_REG_RXQ_CTRL, data); +- edma_read_reg(EDMA_REG_TXQ_CTRL, &data); +- data &= ~EDMA_TXQ_CTRL_TXQ_EN; +- edma_write_reg(EDMA_REG_TXQ_CTRL, data); +-} +- +-/* edma_reset() +- * Reset the EDMA +- */ +-int edma_reset(struct edma_common_info *edma_cinfo) +-{ +- struct edma_hw *hw = &edma_cinfo->hw; +- +- edma_irq_disable(edma_cinfo); +- +- edma_clear_irq_status(); +- +- edma_stop_rx_tx(hw); +- +- return 0; +-} +- +-/* edma_fill_netdev() +- * Fill netdev for each etdr +- */ +-int edma_fill_netdev(struct edma_common_info *edma_cinfo, int queue_id, +- int dev, int txq_id) +-{ +- struct edma_tx_desc_ring *etdr; +- int i = 0; +- +- etdr = edma_cinfo->tpd_ring[queue_id]; +- +- while (etdr->netdev[i]) +- i++; +- +- if (i >= EDMA_MAX_NETDEV_PER_QUEUE) +- return -1; +- +- /* Populate the netdev associated with the tpd ring */ +- etdr->netdev[i] = edma_netdev[dev]; +- etdr->nq[i] = netdev_get_tx_queue(edma_netdev[dev], txq_id); +- +- return 0; +-} +- +-/* edma_set_mac() +- * Change the Ethernet Address of the NIC +- */ +-int edma_set_mac_addr(struct net_device *netdev, void *p) +-{ +- struct sockaddr *addr = p; +- +- if (!is_valid_ether_addr(addr->sa_data)) +- return -EINVAL; +- +- if (netif_running(netdev)) +- return -EBUSY; +- +- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); +- return 0; +-} +- +-/* edma_set_stp_rstp() +- * set stp/rstp +- */ +-void edma_set_stp_rstp(bool rstp) +-{ +- edma_stp_rstp = rstp; +-} +- +-/* edma_assign_ath_hdr_type() +- * assign atheros header eth type +- */ +-void edma_assign_ath_hdr_type(int eth_type) +-{ +- edma_ath_eth_type = eth_type & EDMA_ETH_TYPE_MASK; +-} +- +-/* edma_get_default_vlan_tag() +- * Used by other modules to get the default vlan tag +- */ +-int edma_get_default_vlan_tag(struct net_device *netdev) +-{ +- struct edma_adapter *adapter = netdev_priv(netdev); +- +- if (adapter->default_vlan_tag) +- return adapter->default_vlan_tag; +- +- return 0; +-} +- +-/* edma_open() +- * gets called when netdevice is up, start the queue. +- */ +-int edma_open(struct net_device *netdev) +-{ +- struct edma_adapter *adapter = netdev_priv(netdev); +- struct platform_device *pdev = adapter->edma_cinfo->pdev; +- +- netif_tx_start_all_queues(netdev); +- edma_initialise_rfs_flow_table(adapter); +- set_bit(__EDMA_UP, &adapter->state_flags); +- +- /* if Link polling is enabled, in our case enabled for WAN, then +- * do a phy start, else always set link as UP +- */ +- if (adapter->poll_required) { +- if (!IS_ERR(adapter->phydev)) { +- /* AR40xx calibration will leave the PHY in unwanted state, +- * so a soft reset is required before phy_start() +- */ +- genphy_soft_reset(adapter->phydev); +- phy_start(adapter->phydev); +- phy_start_aneg(adapter->phydev); +- adapter->link_state = __EDMA_LINKDOWN; +- } else { +- dev_dbg(&pdev->dev, "Invalid PHY device for a link polled interface\n"); +- } +- } else { +- adapter->link_state = __EDMA_LINKUP; +- netif_carrier_on(netdev); +- } +- +- return 0; +-} +- +- +-/* edma_close() +- * gets called when netdevice is down, stops the queue. +- */ +-int edma_close(struct net_device *netdev) +-{ +- struct edma_adapter *adapter = netdev_priv(netdev); +- +- edma_free_rfs_flow_table(adapter); +- netif_carrier_off(netdev); +- netif_tx_stop_all_queues(netdev); +- +- if (adapter->poll_required) { +- if (!IS_ERR(adapter->phydev)) +- phy_stop(adapter->phydev); +- } +- +- adapter->link_state = __EDMA_LINKDOWN; +- +- /* Set GMAC state to UP before link state is checked +- */ +- clear_bit(__EDMA_UP, &adapter->state_flags); +- +- return 0; +-} +- +-/* edma_poll +- * polling function that gets called when the napi gets scheduled. +- * +- * Main sequence of task performed in this api +- * is clear irq status -> clear_tx_irq -> clean_rx_irq-> +- * enable interrupts. +- */ +-int edma_poll(struct napi_struct *napi, int budget) +-{ +- struct edma_per_cpu_queues_info *edma_percpu_info = container_of(napi, +- struct edma_per_cpu_queues_info, napi); +- struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; +- u32 reg_data; +- u32 shadow_rx_status, shadow_tx_status; +- int queue_id; +- int i, work_done = 0; +- u16 rx_pending_fill; +- +- /* Store the Rx/Tx status by ANDing it with +- * appropriate CPU RX?TX mask +- */ +- edma_read_reg(EDMA_REG_RX_ISR, ®_data); +- edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask; +- shadow_rx_status = edma_percpu_info->rx_status; +- edma_read_reg(EDMA_REG_TX_ISR, ®_data); +- edma_percpu_info->tx_status |= reg_data & edma_percpu_info->tx_mask; +- shadow_tx_status = edma_percpu_info->tx_status; +- +- /* Every core will have a start, which will be computed +- * in probe and stored in edma_percpu_info->tx_start variable. +- * We will shift the status bit by tx_start to obtain +- * status bits for the core on which the current processing +- * is happening. Since, there are 4 tx queues per core, +- * we will run the loop till we get the correct queue to clear. +- */ +- while (edma_percpu_info->tx_status) { +- queue_id = ffs(edma_percpu_info->tx_status) - 1; +- edma_tx_complete(edma_cinfo, queue_id); +- edma_percpu_info->tx_status &= ~(1 << queue_id); +- } +- +- /* Every core will have a start, which will be computed +- * in probe and stored in edma_percpu_info->tx_start variable. +- * We will shift the status bit by tx_start to obtain +- * status bits for the core on which the current processing +- * is happening. Since, there are 4 tx queues per core, we +- * will run the loop till we get the correct queue to clear. +- */ +- while (edma_percpu_info->rx_status) { +- queue_id = ffs(edma_percpu_info->rx_status) - 1; +- rx_pending_fill = edma_rx_complete(edma_cinfo, &work_done, +- budget, queue_id, napi); +- +- if (likely(work_done < budget)) { +- if (rx_pending_fill) { +- /* reschedule poll() to refill rx buffer deficit */ +- work_done = budget; +- break; +- } +- edma_percpu_info->rx_status &= ~(1 << queue_id); +- } else { +- break; +- } +- } +- +- /* Clear the status register, to avoid the interrupts to +- * reoccur.This clearing of interrupt status register is +- * done here as writing to status register only takes place +- * once the producer/consumer index has been updated to +- * reflect that the packet transmission/reception went fine. +- */ +- edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status); +- edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status); +- +- /* If budget not fully consumed, exit the polling mode */ +- if (likely(work_done < budget)) { +- napi_complete(napi); +- +- /* re-enable the interrupts */ +- for (i = 0; i < edma_cinfo->num_rxq_per_core; i++) +- edma_write_reg(EDMA_REG_RX_INT_MASK_Q(edma_percpu_info->rx_start + i), 0x1); +- for (i = 0; i < edma_cinfo->num_txq_per_core; i++) +- edma_write_reg(EDMA_REG_TX_INT_MASK_Q(edma_percpu_info->tx_start + i), 0x1); +- } +- +- return work_done; +-} +- +-/* edma interrupt() +- * interrupt handler +- */ +-irqreturn_t edma_interrupt(int irq, void *dev) +-{ +- struct edma_per_cpu_queues_info *edma_percpu_info = (struct edma_per_cpu_queues_info *) dev; +- struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; +- int i; +- +- /* Unmask the TX/RX interrupt register */ +- for (i = 0; i < edma_cinfo->num_rxq_per_core; i++) +- edma_write_reg(EDMA_REG_RX_INT_MASK_Q(edma_percpu_info->rx_start + i), 0x0); +- +- for (i = 0; i < edma_cinfo->num_txq_per_core; i++) +- edma_write_reg(EDMA_REG_TX_INT_MASK_Q(edma_percpu_info->tx_start + i), 0x0); +- +- napi_schedule(&edma_percpu_info->napi); +- +- return IRQ_HANDLED; +-} +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.h ++++ /dev/null +@@ -1,455 +0,0 @@ +-/* +- * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +- * +- * Permission to use, copy, modify, and/or distribute this software for +- * any purpose with or without fee is hereby granted, provided that the +- * above copyright notice and this permission notice appear in all copies. +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#ifndef _EDMA_H_ +-#define _EDMA_H_ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "ess_edma.h" +- +-#define EDMA_CPU_CORES_SUPPORTED 4 +-#define EDMA_MAX_PORTID_SUPPORTED 5 +-#define EDMA_MAX_VLAN_SUPPORTED EDMA_MAX_PORTID_SUPPORTED +-#define EDMA_MAX_PORTID_BITMAP_INDEX (EDMA_MAX_PORTID_SUPPORTED + 1) +-#define EDMA_MAX_PORTID_BITMAP_SUPPORTED 0x1f /* 0001_1111 = 0x1f */ +-#define EDMA_MAX_NETDEV_PER_QUEUE 4 /* 3 Netdev per queue, 1 space for indexing */ +- +-#define EDMA_MAX_RECEIVE_QUEUE 8 +-#define EDMA_MAX_TRANSMIT_QUEUE 16 +- +-/* WAN/LAN adapter number */ +-#define EDMA_WAN 0 +-#define EDMA_LAN 1 +- +-/* VLAN tag */ +-#define EDMA_LAN_DEFAULT_VLAN 1 +-#define EDMA_WAN_DEFAULT_VLAN 2 +- +-#define EDMA_DEFAULT_GROUP1_VLAN 1 +-#define EDMA_DEFAULT_GROUP2_VLAN 2 +-#define EDMA_DEFAULT_GROUP3_VLAN 3 +-#define EDMA_DEFAULT_GROUP4_VLAN 4 +-#define EDMA_DEFAULT_GROUP5_VLAN 5 +- +-/* Queues exposed to linux kernel */ +-#define EDMA_NETDEV_TX_QUEUE 4 +-#define EDMA_NETDEV_RX_QUEUE 4 +- +-/* Number of queues per core */ +-#define EDMA_NUM_TXQ_PER_CORE 4 +-#define EDMA_NUM_RXQ_PER_CORE 2 +- +-#define EDMA_TPD_EOP_SHIFT 31 +- +-#define EDMA_PORT_ID_SHIFT 12 +-#define EDMA_PORT_ID_MASK 0x7 +- +-/* tpd word 3 bit 18-28 */ +-#define EDMA_TPD_PORT_BITMAP_SHIFT 18 +- +-#define EDMA_TPD_FROM_CPU_SHIFT 25 +- +-#define EDMA_FROM_CPU_MASK 0x80 +-#define EDMA_SKB_PRIORITY_MASK 0x38 +- +-/* TX/RX descriptor ring count */ +-/* should be a power of 2 */ +-#define EDMA_RX_RING_SIZE 128 +-#define EDMA_TX_RING_SIZE 128 +- +-/* Flags used in paged/non paged mode */ +-#define EDMA_RX_HEAD_BUFF_SIZE_JUMBO 256 +-#define EDMA_RX_HEAD_BUFF_SIZE 1540 +- +-/* MAX frame size supported by switch */ +-#define EDMA_MAX_JUMBO_FRAME_SIZE 9216 +- +-/* Configurations */ +-#define EDMA_INTR_CLEAR_TYPE 0 +-#define EDMA_INTR_SW_IDX_W_TYPE 0 +-#define EDMA_FIFO_THRESH_TYPE 0 +-#define EDMA_RSS_TYPE 0 +-#define EDMA_RX_IMT 0x0020 +-#define EDMA_TX_IMT 0x0050 +-#define EDMA_TPD_BURST 5 +-#define EDMA_TXF_BURST 0x100 +-#define EDMA_RFD_BURST 8 +-#define EDMA_RFD_THR 16 +-#define EDMA_RFD_LTHR 0 +- +-/* RX/TX per CPU based mask/shift */ +-#define EDMA_TX_PER_CPU_MASK 0xF +-#define EDMA_RX_PER_CPU_MASK 0x3 +-#define EDMA_TX_PER_CPU_MASK_SHIFT 0x2 +-#define EDMA_RX_PER_CPU_MASK_SHIFT 0x1 +-#define EDMA_TX_CPU_START_SHIFT 0x2 +-#define EDMA_RX_CPU_START_SHIFT 0x1 +- +-/* FLags used in transmit direction */ +-#define EDMA_HW_CHECKSUM 0x00000001 +-#define EDMA_VLAN_TX_TAG_INSERT_FLAG 0x00000002 +-#define EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG 0x00000004 +- +-#define EDMA_SW_DESC_FLAG_LAST 0x1 +-#define EDMA_SW_DESC_FLAG_SKB_HEAD 0x2 +-#define EDMA_SW_DESC_FLAG_SKB_FRAG 0x4 +-#define EDMA_SW_DESC_FLAG_SKB_FRAGLIST 0x8 +-#define EDMA_SW_DESC_FLAG_SKB_NONE 0x10 +-#define EDMA_SW_DESC_FLAG_SKB_REUSE 0x20 +- +- +-#define EDMA_MAX_SKB_FRAGS (MAX_SKB_FRAGS + 1) +- +-/* Ethtool specific list of EDMA supported features */ +-#define EDMA_SUPPORTED_FEATURES (SUPPORTED_10baseT_Half \ +- | SUPPORTED_10baseT_Full \ +- | SUPPORTED_100baseT_Half \ +- | SUPPORTED_100baseT_Full \ +- | SUPPORTED_1000baseT_Full) +- +-/* Recevie side atheros Header */ +-#define EDMA_RX_ATH_HDR_VERSION 0x2 +-#define EDMA_RX_ATH_HDR_VERSION_SHIFT 14 +-#define EDMA_RX_ATH_HDR_PRIORITY_SHIFT 11 +-#define EDMA_RX_ATH_PORT_TYPE_SHIFT 6 +-#define EDMA_RX_ATH_HDR_RSTP_PORT_TYPE 0x4 +- +-/* Transmit side atheros Header */ +-#define EDMA_TX_ATH_HDR_PORT_BITMAP_MASK 0x7F +-#define EDMA_TX_ATH_HDR_FROM_CPU_MASK 0x80 +-#define EDMA_TX_ATH_HDR_FROM_CPU_SHIFT 7 +- +-#define EDMA_TXQ_START_CORE0 8 +-#define EDMA_TXQ_START_CORE1 12 +-#define EDMA_TXQ_START_CORE2 0 +-#define EDMA_TXQ_START_CORE3 4 +- +-#define EDMA_TXQ_IRQ_MASK_CORE0 0x0F00 +-#define EDMA_TXQ_IRQ_MASK_CORE1 0xF000 +-#define EDMA_TXQ_IRQ_MASK_CORE2 0x000F +-#define EDMA_TXQ_IRQ_MASK_CORE3 0x00F0 +- +-#define EDMA_ETH_HDR_LEN 12 +-#define EDMA_ETH_TYPE_MASK 0xFFFF +- +-#define EDMA_RX_BUFFER_WRITE 16 +-#define EDMA_RFD_AVAIL_THR 80 +- +-#define EDMA_GMAC_NO_MDIO_PHY PHY_MAX_ADDR +- +-extern int ssdk_rfs_ipct_rule_set(__be32 ip_src, __be32 ip_dst, +- __be16 sport, __be16 dport, +- uint8_t proto, u16 loadbalance, bool action); +-struct edma_ethtool_statistics { +- u32 tx_q0_pkt; +- u32 tx_q1_pkt; +- u32 tx_q2_pkt; +- u32 tx_q3_pkt; +- u32 tx_q4_pkt; +- u32 tx_q5_pkt; +- u32 tx_q6_pkt; +- u32 tx_q7_pkt; +- u32 tx_q8_pkt; +- u32 tx_q9_pkt; +- u32 tx_q10_pkt; +- u32 tx_q11_pkt; +- u32 tx_q12_pkt; +- u32 tx_q13_pkt; +- u32 tx_q14_pkt; +- u32 tx_q15_pkt; +- u32 tx_q0_byte; +- u32 tx_q1_byte; +- u32 tx_q2_byte; +- u32 tx_q3_byte; +- u32 tx_q4_byte; +- u32 tx_q5_byte; +- u32 tx_q6_byte; +- u32 tx_q7_byte; +- u32 tx_q8_byte; +- u32 tx_q9_byte; +- u32 tx_q10_byte; +- u32 tx_q11_byte; +- u32 tx_q12_byte; +- u32 tx_q13_byte; +- u32 tx_q14_byte; +- u32 tx_q15_byte; +- u32 rx_q0_pkt; +- u32 rx_q1_pkt; +- u32 rx_q2_pkt; +- u32 rx_q3_pkt; +- u32 rx_q4_pkt; +- u32 rx_q5_pkt; +- u32 rx_q6_pkt; +- u32 rx_q7_pkt; +- u32 rx_q0_byte; +- u32 rx_q1_byte; +- u32 rx_q2_byte; +- u32 rx_q3_byte; +- u32 rx_q4_byte; +- u32 rx_q5_byte; +- u32 rx_q6_byte; +- u32 rx_q7_byte; +- u32 tx_desc_error; +- u32 rx_alloc_fail_ctr; +-}; +- +-struct edma_mdio_data { +- struct mii_bus *mii_bus; +- void __iomem *membase; +- int phy_irq[PHY_MAX_ADDR]; +-}; +- +-/* EDMA LINK state */ +-enum edma_link_state { +- __EDMA_LINKUP, /* Indicate link is UP */ +- __EDMA_LINKDOWN /* Indicate link is down */ +-}; +- +-/* EDMA GMAC state */ +-enum edma_gmac_state { +- __EDMA_UP /* use to indicate GMAC is up */ +-}; +- +-/* edma transmit descriptor */ +-struct edma_tx_desc { +- __le16 len; /* full packet including CRC */ +- __le16 svlan_tag; /* vlan tag */ +- __le32 word1; /* byte 4-7 */ +- __le32 addr; /* address of buffer */ +- __le32 word3; /* byte 12 */ +-}; +- +-/* edma receive return descriptor */ +-struct edma_rx_return_desc { +- u16 rrd0; +- u16 rrd1; +- u16 rrd2; +- u16 rrd3; +- u16 rrd4; +- u16 rrd5; +- u16 rrd6; +- u16 rrd7; +-}; +- +-/* RFD descriptor */ +-struct edma_rx_free_desc { +- __le32 buffer_addr; /* buffer address */ +-}; +- +-/* edma hw specific data */ +-struct edma_hw { +- u32 __iomem *hw_addr; /* inner register address */ +- struct edma_adapter *adapter; /* netdevice adapter */ +- u32 rx_intr_mask; /*rx interrupt mask */ +- u32 tx_intr_mask; /* tx interrupt nask */ +- u32 misc_intr_mask; /* misc interrupt mask */ +- u32 wol_intr_mask; /* wake on lan interrupt mask */ +- bool intr_clear_type; /* interrupt clear */ +- bool intr_sw_idx_w; /* interrupt software index */ +- u32 rx_head_buff_size; /* Rx buffer size */ +- u8 rss_type; /* rss protocol type */ +-}; +- +-/* edma_sw_desc stores software descriptor +- * SW descriptor has 1:1 map with HW descriptor +- */ +-struct edma_sw_desc { +- struct sk_buff *skb; +- dma_addr_t dma; /* dma address */ +- u16 length; /* Tx/Rx buffer length */ +- u32 flags; +-}; +- +-/* per core related information */ +-struct edma_per_cpu_queues_info { +- struct napi_struct napi; /* napi associated with the core */ +- u32 tx_mask; /* tx interrupt mask */ +- u32 rx_mask; /* rx interrupt mask */ +- u32 tx_status; /* tx interrupt status */ +- u32 rx_status; /* rx interrupt status */ +- u32 tx_start; /* tx queue start */ +- u32 rx_start; /* rx queue start */ +- struct edma_common_info *edma_cinfo; /* edma common info */ +-}; +- +-/* edma specific common info */ +-struct edma_common_info { +- struct edma_tx_desc_ring *tpd_ring[16]; /* 16 Tx queues */ +- struct edma_rfd_desc_ring *rfd_ring[8]; /* 8 Rx queues */ +- struct platform_device *pdev; /* device structure */ +- struct net_device *netdev[EDMA_MAX_PORTID_SUPPORTED]; +- struct net_device *portid_netdev_lookup_tbl[EDMA_MAX_PORTID_BITMAP_INDEX]; +- struct ctl_table_header *edma_ctl_table_hdr; +- int num_gmac; +- struct edma_ethtool_statistics edma_ethstats; /* ethtool stats */ +- int num_rx_queues; /* number of rx queue */ +- u32 num_tx_queues; /* number of tx queue */ +- u32 tx_irq[16]; /* number of tx irq */ +- u32 rx_irq[8]; /* number of rx irq */ +- u32 from_cpu; /* from CPU TPD field */ +- u32 num_rxq_per_core; /* Rx queues per core */ +- u32 num_txq_per_core; /* Tx queues per core */ +- u16 tx_ring_count; /* Tx ring count */ +- u16 rx_ring_count; /* Rx ring*/ +- u16 rx_head_buffer_len; /* rx buffer length */ +- u16 rx_page_buffer_len; /* rx buffer length */ +- u32 page_mode; /* Jumbo frame supported flag */ +- u32 fraglist_mode; /* fraglist supported flag */ +- struct edma_hw hw; /* edma hw specific structure */ +- struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */ +- spinlock_t stats_lock; /* protect edma stats area for updation */ +- struct timer_list edma_stats_timer; +- bool is_single_phy; +- void __iomem *ess_hw_addr; +- struct clk *ess_clk; +-}; +- +-/* transimit packet descriptor (tpd) ring */ +-struct edma_tx_desc_ring { +- struct netdev_queue *nq[EDMA_MAX_NETDEV_PER_QUEUE]; /* Linux queue index */ +- struct net_device *netdev[EDMA_MAX_NETDEV_PER_QUEUE]; +- /* Array of netdevs associated with the tpd ring */ +- void *hw_desc; /* descriptor ring virtual address */ +- struct edma_sw_desc *sw_desc; /* buffer associated with ring */ +- int netdev_bmp; /* Bitmap for per-ring netdevs */ +- u32 size; /* descriptor ring length in bytes */ +- u16 count; /* number of descriptors in the ring */ +- dma_addr_t dma; /* descriptor ring physical address */ +- u16 sw_next_to_fill; /* next Tx descriptor to fill */ +- u16 sw_next_to_clean; /* next Tx descriptor to clean */ +-}; +- +-/* receive free descriptor (rfd) ring */ +-struct edma_rfd_desc_ring { +- void *hw_desc; /* descriptor ring virtual address */ +- struct edma_sw_desc *sw_desc; /* buffer associated with ring */ +- u16 size; /* bytes allocated to sw_desc */ +- u16 count; /* number of descriptors in the ring */ +- dma_addr_t dma; /* descriptor ring physical address */ +- u16 sw_next_to_fill; /* next descriptor to fill */ +- u16 sw_next_to_clean; /* next descriptor to clean */ +- u16 pending_fill; /* fill pending from previous iteration */ +-}; +- +-/* edma_rfs_flter_node - rfs filter node in hash table */ +-struct edma_rfs_filter_node { +- struct flow_keys keys; +- u32 flow_id; /* flow_id of filter provided by kernel */ +- u16 filter_id; /* filter id of filter returned by adaptor */ +- u16 rq_id; /* desired rq index */ +- struct hlist_node node; /* edma rfs list node */ +-}; +- +-/* edma_rfs_flow_tbl - rfs flow table */ +-struct edma_rfs_flow_table { +- u16 max_num_filter; /* Maximum number of filters edma supports */ +- u16 hashtoclean; /* hash table index to clean next */ +- int filter_available; /* Number of free filters available */ +- struct hlist_head hlist_head[EDMA_RFS_FLOW_ENTRIES]; +- spinlock_t rfs_ftab_lock; +- struct timer_list expire_rfs; /* timer function for edma_rps_may_expire_flow */ +-}; +- +-/* EDMA net device structure */ +-struct edma_adapter { +- struct net_device *netdev; /* netdevice */ +- struct platform_device *pdev; /* platform device */ +- struct edma_common_info *edma_cinfo; /* edma common info */ +- struct phy_device *phydev; /* Phy device */ +- struct edma_rfs_flow_table rfs; /* edma rfs flow table */ +- struct net_device_stats stats; /* netdev statistics */ +- set_rfs_filter_callback_t set_rfs_rule; +- u32 flags;/* status flags */ +- unsigned long state_flags; /* GMAC up/down flags */ +- u32 forced_speed; /* link force speed */ +- u32 forced_duplex; /* link force duplex */ +- u32 link_state; /* phy link state */ +- u32 phy_mdio_addr; /* PHY device address on MII interface */ +- u32 poll_required; /* check if link polling is required */ +- u32 tx_start_offset[CONFIG_NR_CPUS]; /* tx queue start */ +- u32 default_vlan_tag; /* vlan tag */ +- u32 dp_bitmap; +- uint8_t phy_id[MII_BUS_ID_SIZE + 3]; +-}; +- +-int edma_alloc_queues_tx(struct edma_common_info *edma_cinfo); +-int edma_alloc_queues_rx(struct edma_common_info *edma_cinfo); +-int edma_open(struct net_device *netdev); +-int edma_close(struct net_device *netdev); +-void edma_free_tx_resources(struct edma_common_info *edma_c_info); +-void edma_free_rx_resources(struct edma_common_info *edma_c_info); +-int edma_alloc_tx_rings(struct edma_common_info *edma_cinfo); +-int edma_alloc_rx_rings(struct edma_common_info *edma_cinfo); +-void edma_free_tx_rings(struct edma_common_info *edma_cinfo); +-void edma_free_rx_rings(struct edma_common_info *edma_cinfo); +-void edma_free_queues(struct edma_common_info *edma_cinfo); +-void edma_irq_disable(struct edma_common_info *edma_cinfo); +-int edma_reset(struct edma_common_info *edma_cinfo); +-int edma_poll(struct napi_struct *napi, int budget); +-netdev_tx_t edma_xmit(struct sk_buff *skb, +- struct net_device *netdev); +-int edma_configure(struct edma_common_info *edma_cinfo); +-void edma_irq_enable(struct edma_common_info *edma_cinfo); +-void edma_enable_tx_ctrl(struct edma_hw *hw); +-void edma_enable_rx_ctrl(struct edma_hw *hw); +-void edma_stop_rx_tx(struct edma_hw *hw); +-void edma_free_irqs(struct edma_adapter *adapter); +-irqreturn_t edma_interrupt(int irq, void *dev); +-void edma_write_reg(u16 reg_addr, u32 reg_value); +-void edma_read_reg(u16 reg_addr, volatile u32 *reg_value); +-struct net_device_stats *edma_get_stats(struct net_device *netdev); +-int edma_set_mac_addr(struct net_device *netdev, void *p); +-int edma_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, +- u16 rxq, u32 flow_id); +-int edma_register_rfs_filter(struct net_device *netdev, +- set_rfs_filter_callback_t set_filter); +-void edma_flow_may_expire(struct timer_list *t); +-void edma_set_ethtool_ops(struct net_device *netdev); +-void edma_set_stp_rstp(bool tag); +-void edma_assign_ath_hdr_type(int tag); +-int edma_get_default_vlan_tag(struct net_device *netdev); +-void edma_adjust_link(struct net_device *netdev); +-int edma_fill_netdev(struct edma_common_info *edma_cinfo, int qid, int num, int txq_id); +-void edma_read_append_stats(struct edma_common_info *edma_cinfo); +-void edma_change_tx_coalesce(int usecs); +-void edma_change_rx_coalesce(int usecs); +-void edma_get_tx_rx_coalesce(u32 *reg_val); +-void edma_clear_irq_status(void); +-void ess_set_port_status_speed(struct edma_common_info *edma_cinfo, +- struct phy_device *phydev, uint8_t port_id); +-#endif /* _EDMA_H_ */ +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c ++++ /dev/null +@@ -1,1346 +0,0 @@ +-/* +- * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +- * +- * Permission to use, copy, modify, and/or distribute this software for +- * any purpose with or without fee is hereby granted, provided that the +- * above copyright notice and this permission notice appear in all copies. +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "edma.h" +-#include "ess_edma.h" +- +-/* Weight round robin and virtual QID mask */ +-#define EDMA_WRR_VID_SCTL_MASK 0xffff +- +-/* Weight round robin and virtual QID shift */ +-#define EDMA_WRR_VID_SCTL_SHIFT 16 +- +-char edma_axi_driver_name[] = "ess_edma"; +-static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | +- NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; +- +-static u32 edma_hw_addr; +- +-char edma_tx_irq[16][64]; +-char edma_rx_irq[8][64]; +-struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; +-static u16 tx_start[4] = {EDMA_TXQ_START_CORE0, EDMA_TXQ_START_CORE1, +- EDMA_TXQ_START_CORE2, EDMA_TXQ_START_CORE3}; +-static u32 tx_mask[4] = {EDMA_TXQ_IRQ_MASK_CORE0, EDMA_TXQ_IRQ_MASK_CORE1, +- EDMA_TXQ_IRQ_MASK_CORE2, EDMA_TXQ_IRQ_MASK_CORE3}; +- +-static u32 edma_default_ltag __read_mostly = EDMA_LAN_DEFAULT_VLAN; +-static u32 edma_default_wtag __read_mostly = EDMA_WAN_DEFAULT_VLAN; +-static u32 edma_default_group1_vtag __read_mostly = EDMA_DEFAULT_GROUP1_VLAN; +-static u32 edma_default_group2_vtag __read_mostly = EDMA_DEFAULT_GROUP2_VLAN; +-static u32 edma_default_group3_vtag __read_mostly = EDMA_DEFAULT_GROUP3_VLAN; +-static u32 edma_default_group4_vtag __read_mostly = EDMA_DEFAULT_GROUP4_VLAN; +-static u32 edma_default_group5_vtag __read_mostly = EDMA_DEFAULT_GROUP5_VLAN; +-static u32 edma_rss_idt_val = EDMA_RSS_IDT_VALUE; +-static u32 edma_rss_idt_idx; +- +-static int edma_weight_assigned_to_q __read_mostly; +-static int edma_queue_to_virtual_q __read_mostly; +-static bool edma_enable_rstp __read_mostly; +-static int edma_athr_hdr_eth_type __read_mostly; +- +-static int page_mode; +-module_param(page_mode, int, 0); +-MODULE_PARM_DESC(page_mode, "enable page mode"); +- +-static int overwrite_mode; +-module_param(overwrite_mode, int, 0); +-MODULE_PARM_DESC(overwrite_mode, "overwrite default page_mode setting"); +- +-static int jumbo_mru = EDMA_RX_HEAD_BUFF_SIZE; +-module_param(jumbo_mru, int, 0); +-MODULE_PARM_DESC(jumbo_mru, "enable fraglist support"); +- +-static int num_rxq = 4; +-module_param(num_rxq, int, 0); +-MODULE_PARM_DESC(num_rxq, "change the number of rx queues"); +- +-void edma_write_reg(u16 reg_addr, u32 reg_value) +-{ +- writel(reg_value, ((void __iomem *)(edma_hw_addr + reg_addr))); +-} +- +-void edma_read_reg(u16 reg_addr, volatile u32 *reg_value) +-{ +- *reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr)); +-} +- +-static void ess_write_reg(struct edma_common_info *edma, u16 reg_addr, u32 reg_value) +-{ +- writel(reg_value, ((void __iomem *) +- ((unsigned long)edma->ess_hw_addr + reg_addr))); +-} +- +-static void ess_read_reg(struct edma_common_info *edma, u16 reg_addr, +- volatile u32 *reg_value) +-{ +- *reg_value = readl((void __iomem *) +- ((unsigned long)edma->ess_hw_addr + reg_addr)); +-} +- +-static int ess_reset(struct edma_common_info *edma) +-{ +- struct device_node *switch_node = NULL; +- struct reset_control *ess_rst; +- u32 regval; +- +- switch_node = of_find_node_by_name(NULL, "ess-switch"); +- if (!switch_node) { +- pr_err("switch-node not found\n"); +- return -EINVAL; +- } +- +- ess_rst = of_reset_control_get(switch_node, "ess_rst"); +- of_node_put(switch_node); +- +- if (IS_ERR(ess_rst)) { +- pr_err("failed to find ess_rst!\n"); +- return -ENOENT; +- } +- +- reset_control_assert(ess_rst); +- msleep(10); +- reset_control_deassert(ess_rst); +- msleep(100); +- reset_control_put(ess_rst); +- +- /* Enable only port 5 <--> port 0 +- * bits 0:6 bitmap of ports it can fwd to */ +-#define SET_PORT_BMP(r,v) \ +- ess_read_reg(edma, r, ®val); \ +- ess_write_reg(edma, r, ((regval & ~0x3F) | v)); +- +- SET_PORT_BMP(ESS_PORT0_LOOKUP_CTRL,0x20); +- SET_PORT_BMP(ESS_PORT1_LOOKUP_CTRL,0x00); +- SET_PORT_BMP(ESS_PORT2_LOOKUP_CTRL,0x00); +- SET_PORT_BMP(ESS_PORT3_LOOKUP_CTRL,0x00); +- SET_PORT_BMP(ESS_PORT4_LOOKUP_CTRL,0x00); +- SET_PORT_BMP(ESS_PORT5_LOOKUP_CTRL,0x01); +- ess_write_reg(edma, ESS_RGMII_CTRL, 0x400); +- ess_write_reg(edma, ESS_PORT0_STATUS, ESS_PORT_1G_FDX); +- ess_write_reg(edma, ESS_PORT5_STATUS, ESS_PORT_1G_FDX); +- ess_write_reg(edma, ESS_PORT0_HEADER_CTRL, 0); +-#undef SET_PORT_BMP +- +- /* forward multicast and broadcast frames to CPU */ +- ess_write_reg(edma, ESS_FWD_CTRL1, +- (ESS_PORTS_ALL << ESS_FWD_CTRL1_UC_FLOOD_S) | +- (ESS_PORTS_ALL << ESS_FWD_CTRL1_MC_FLOOD_S) | +- (ESS_PORTS_ALL << ESS_FWD_CTRL1_BC_FLOOD_S)); +- +- return 0; +-} +- +-void ess_set_port_status_speed(struct edma_common_info *edma, +- struct phy_device *phydev, uint8_t port_id) +-{ +- uint16_t reg_off = ESS_PORT0_STATUS + (4 * port_id); +- uint32_t reg_val = 0; +- +- ess_read_reg(edma, reg_off, ®_val); +- +- /* reset the speed bits [0:1] */ +- reg_val &= ~ESS_PORT_STATUS_SPEED_INV; +- +- /* set the new speed */ +- switch(phydev->speed) { +- case SPEED_1000: reg_val |= ESS_PORT_STATUS_SPEED_1000; break; +- case SPEED_100: reg_val |= ESS_PORT_STATUS_SPEED_100; break; +- case SPEED_10: reg_val |= ESS_PORT_STATUS_SPEED_10; break; +- default: reg_val |= ESS_PORT_STATUS_SPEED_INV; break; +- } +- +- /* check full/half duplex */ +- if (phydev->duplex) { +- reg_val |= ESS_PORT_STATUS_DUPLEX_MODE; +- } else { +- reg_val &= ~ESS_PORT_STATUS_DUPLEX_MODE; +- } +- +- ess_write_reg(edma, reg_off, reg_val); +-} +- +-/* edma_change_tx_coalesce() +- * change tx interrupt moderation timer +- */ +-void edma_change_tx_coalesce(int usecs) +-{ +- u32 reg_value; +- +- /* Here, we right shift the value from the user by 1, this is +- * done because IMT resolution timer is 2usecs. 1 count +- * of this register corresponds to 2 usecs. +- */ +- edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, ®_value); +- reg_value = ((reg_value & 0xffff) | ((usecs >> 1) << 16)); +- edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_value); +-} +- +-/* edma_change_rx_coalesce() +- * change rx interrupt moderation timer +- */ +-void edma_change_rx_coalesce(int usecs) +-{ +- u32 reg_value; +- +- /* Here, we right shift the value from the user by 1, this is +- * done because IMT resolution timer is 2usecs. 1 count +- * of this register corresponds to 2 usecs. +- */ +- edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, ®_value); +- reg_value = ((reg_value & 0xffff0000) | (usecs >> 1)); +- edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_value); +-} +- +-/* edma_get_tx_rx_coalesce() +- * Get tx/rx interrupt moderation value +- */ +-void edma_get_tx_rx_coalesce(u32 *reg_val) +-{ +- edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_val); +-} +- +-void edma_read_append_stats(struct edma_common_info *edma_cinfo) +-{ +- uint32_t *p; +- int i; +- u32 stat; +- +- spin_lock_bh(&edma_cinfo->stats_lock); +- p = (uint32_t *)&(edma_cinfo->edma_ethstats); +- +- for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) { +- edma_read_reg(EDMA_REG_TX_STAT_PKT_Q(i), &stat); +- *p += stat; +- p++; +- } +- +- for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) { +- edma_read_reg(EDMA_REG_TX_STAT_BYTE_Q(i), &stat); +- *p += stat; +- p++; +- } +- +- for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) { +- edma_read_reg(EDMA_REG_RX_STAT_PKT_Q(i), &stat); +- *p += stat; +- p++; +- } +- +- for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) { +- edma_read_reg(EDMA_REG_RX_STAT_BYTE_Q(i), &stat); +- *p += stat; +- p++; +- } +- +- spin_unlock_bh(&edma_cinfo->stats_lock); +-} +- +-static void edma_statistics_timer(struct timer_list *t) +-{ +- struct edma_common_info *edma_cinfo = +- from_timer(edma_cinfo, t, edma_stats_timer); +- +- edma_read_append_stats(edma_cinfo); +- +- mod_timer(&edma_cinfo->edma_stats_timer, jiffies + 1*HZ); +-} +- +-static int edma_enable_stp_rstp(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- int ret; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write) +- edma_set_stp_rstp(edma_enable_rstp); +- +- return ret; +-} +- +-static int edma_ath_hdr_eth_type(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- int ret; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write) +- edma_assign_ath_hdr_type(edma_athr_hdr_eth_type); +- +- return ret; +-} +- +-static int edma_change_default_lan_vlan(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- int ret; +- +- if (!edma_netdev[1]) { +- pr_err("Netdevice for default_lan does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[1]); +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_ltag; +- +- return ret; +-} +- +-static int edma_change_default_wan_vlan(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- int ret; +- +- if (!edma_netdev[0]) { +- pr_err("Netdevice for default_wan does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[0]); +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_wtag; +- +- return ret; +-} +- +-static int edma_change_group1_vtag(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- struct edma_common_info *edma_cinfo; +- int ret; +- +- if (!edma_netdev[0]) { +- pr_err("Netdevice for Group 1 does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[0]); +- edma_cinfo = adapter->edma_cinfo; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_group1_vtag; +- +- return ret; +-} +- +-static int edma_change_group2_vtag(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- struct edma_common_info *edma_cinfo; +- int ret; +- +- if (!edma_netdev[1]) { +- pr_err("Netdevice for Group 2 does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[1]); +- edma_cinfo = adapter->edma_cinfo; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_group2_vtag; +- +- return ret; +-} +- +-static int edma_change_group3_vtag(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- struct edma_common_info *edma_cinfo; +- int ret; +- +- if (!edma_netdev[2]) { +- pr_err("Netdevice for Group 3 does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[2]); +- edma_cinfo = adapter->edma_cinfo; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_group3_vtag; +- +- return ret; +-} +- +-static int edma_change_group4_vtag(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- struct edma_common_info *edma_cinfo; +- int ret; +- +- if (!edma_netdev[3]) { +- pr_err("Netdevice for Group 4 does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[3]); +- edma_cinfo = adapter->edma_cinfo; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_group4_vtag; +- +- return ret; +-} +- +-static int edma_change_group5_vtag(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- struct edma_adapter *adapter; +- struct edma_common_info *edma_cinfo; +- int ret; +- +- if (!edma_netdev[4]) { +- pr_err("Netdevice for Group 5 does not exist\n"); +- return -1; +- } +- +- adapter = netdev_priv(edma_netdev[4]); +- edma_cinfo = adapter->edma_cinfo; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- +- if (write) +- adapter->default_vlan_tag = edma_default_group5_vtag; +- +- return ret; +-} +- +-static int edma_set_rss_idt_value(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- int ret; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write && !ret) +- edma_write_reg(EDMA_REG_RSS_IDT(edma_rss_idt_idx), +- edma_rss_idt_val); +- return ret; +-} +- +-static int edma_set_rss_idt_idx(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- int ret; +- u32 old_value = edma_rss_idt_idx; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- if (!write || ret) +- return ret; +- +- if (edma_rss_idt_idx >= EDMA_NUM_IDT) { +- pr_err("Invalid RSS indirection table index %d\n", +- edma_rss_idt_idx); +- edma_rss_idt_idx = old_value; +- return -EINVAL; +- } +- return ret; +-} +- +-static int edma_weight_assigned_to_queues(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- int ret, queue_id, weight; +- u32 reg_data, data, reg_addr; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write) { +- queue_id = edma_weight_assigned_to_q & EDMA_WRR_VID_SCTL_MASK; +- if (queue_id < 0 || queue_id > 15) { +- pr_err("queue_id not within desired range\n"); +- return -EINVAL; +- } +- +- weight = edma_weight_assigned_to_q >> EDMA_WRR_VID_SCTL_SHIFT; +- if (weight < 0 || weight > 0xF) { +- pr_err("queue_id not within desired range\n"); +- return -EINVAL; +- } +- +- data = weight << EDMA_WRR_SHIFT(queue_id); +- +- reg_addr = EDMA_REG_WRR_CTRL_Q0_Q3 + (queue_id & ~0x3); +- edma_read_reg(reg_addr, ®_data); +- reg_data &= ~(1 << EDMA_WRR_SHIFT(queue_id)); +- edma_write_reg(reg_addr, data | reg_data); +- } +- +- return ret; +-} +- +-static int edma_queue_to_virtual_queue_map(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, +- loff_t *ppos) +-{ +- int ret, queue_id, virtual_qid; +- u32 reg_data, data, reg_addr; +- +- ret = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write) { +- queue_id = edma_queue_to_virtual_q & EDMA_WRR_VID_SCTL_MASK; +- if (queue_id < 0 || queue_id > 15) { +- pr_err("queue_id not within desired range\n"); +- return -EINVAL; +- } +- +- virtual_qid = edma_queue_to_virtual_q >> +- EDMA_WRR_VID_SCTL_SHIFT; +- if (virtual_qid < 0 || virtual_qid > 8) { +- pr_err("queue_id not within desired range\n"); +- return -EINVAL; +- } +- +- data = virtual_qid << EDMA_VQ_ID_SHIFT(queue_id); +- +- reg_addr = EDMA_REG_VQ_CTRL0 + (queue_id & ~0x3); +- edma_read_reg(reg_addr, ®_data); +- reg_data &= ~(1 << EDMA_VQ_ID_SHIFT(queue_id)); +- edma_write_reg(reg_addr, data | reg_data); +- } +- +- return ret; +-} +- +-static struct ctl_table edma_table[] = { +- { +- .procname = "default_lan_tag", +- .data = &edma_default_ltag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_default_lan_vlan +- }, +- { +- .procname = "default_wan_tag", +- .data = &edma_default_wtag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_default_wan_vlan +- }, +- { +- .procname = "weight_assigned_to_queues", +- .data = &edma_weight_assigned_to_q, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_weight_assigned_to_queues +- }, +- { +- .procname = "queue_to_virtual_queue_map", +- .data = &edma_queue_to_virtual_q, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_queue_to_virtual_queue_map +- }, +- { +- .procname = "enable_stp_rstp", +- .data = &edma_enable_rstp, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_enable_stp_rstp +- }, +- { +- .procname = "athr_hdr_eth_type", +- .data = &edma_athr_hdr_eth_type, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_ath_hdr_eth_type +- }, +- { +- .procname = "default_group1_vlan_tag", +- .data = &edma_default_group1_vtag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_group1_vtag +- }, +- { +- .procname = "default_group2_vlan_tag", +- .data = &edma_default_group2_vtag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_group2_vtag +- }, +- { +- .procname = "default_group3_vlan_tag", +- .data = &edma_default_group3_vtag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_group3_vtag +- }, +- { +- .procname = "default_group4_vlan_tag", +- .data = &edma_default_group4_vtag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_group4_vtag +- }, +- { +- .procname = "default_group5_vlan_tag", +- .data = &edma_default_group5_vtag, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_change_group5_vtag +- }, +- { +- .procname = "edma_rss_idt_value", +- .data = &edma_rss_idt_val, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_set_rss_idt_value +- }, +- { +- .procname = "edma_rss_idt_idx", +- .data = &edma_rss_idt_idx, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = edma_set_rss_idt_idx +- }, +- {} +-}; +- +-static int ess_parse(struct edma_common_info *edma) +-{ +- struct device_node *switch_node; +- int ret = -EINVAL; +- +- switch_node = of_find_node_by_name(NULL, "ess-switch"); +- if (!switch_node) { +- pr_err("cannot find ess-switch node\n"); +- goto out; +- } +- +- edma->ess_hw_addr = of_io_request_and_map(switch_node, +- 0, KBUILD_MODNAME); +- if (!edma->ess_hw_addr) { +- pr_err("%s ioremap fail.", __func__); +- goto out; +- } +- +- edma->ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); +- ret = clk_prepare_enable(edma->ess_clk); +-out: +- of_node_put(switch_node); +- return ret; +-} +- +-/* edma_axi_netdev_ops +- * Describe the operations supported by registered netdevices +- * +- * static const struct net_device_ops edma_axi_netdev_ops = { +- * .ndo_open = edma_open, +- * .ndo_stop = edma_close, +- * .ndo_start_xmit = edma_xmit_frame, +- * .ndo_set_mac_address = edma_set_mac_addr, +- * } +- */ +-static const struct net_device_ops edma_axi_netdev_ops = { +- .ndo_open = edma_open, +- .ndo_stop = edma_close, +- .ndo_start_xmit = edma_xmit, +- .ndo_set_mac_address = edma_set_mac_addr, +-#ifdef CONFIG_RFS_ACCEL +- .ndo_rx_flow_steer = edma_rx_flow_steer, +- .ndo_register_rfs_filter = edma_register_rfs_filter, +- .ndo_get_default_vlan_tag = edma_get_default_vlan_tag, +-#endif +- .ndo_get_stats = edma_get_stats, +-}; +- +-/* edma_axi_probe() +- * Initialise an adapter identified by a platform_device structure. +- * +- * The OS initialization, configuring of the adapter private structure, +- * and a hardware reset occur in the probe. +- */ +-static int edma_axi_probe(struct platform_device *pdev) +-{ +- struct edma_common_info *edma_cinfo; +- struct edma_hw *hw; +- struct edma_adapter *adapter[EDMA_MAX_PORTID_SUPPORTED]; +- struct resource *res; +- struct device_node *np = pdev->dev.of_node; +- struct device_node *pnp; +- struct device_node *mdio_node = NULL; +- struct mii_bus *miibus = NULL; +- int i, j, k, err = 0; +- int portid_bmp; +- int idx = 0, idx_mac = 0; +- +- if (CONFIG_NR_CPUS != EDMA_CPU_CORES_SUPPORTED) { +- dev_err(&pdev->dev, "Invalid CPU Cores\n"); +- return -EINVAL; +- } +- +- if ((num_rxq != 4) && (num_rxq != 8)) { +- dev_err(&pdev->dev, "Invalid RX queue, edma probe failed\n"); +- return -EINVAL; +- } +- edma_cinfo = kzalloc(sizeof(struct edma_common_info), GFP_KERNEL); +- if (!edma_cinfo) { +- err = -ENOMEM; +- goto err_alloc; +- } +- +- edma_cinfo->pdev = pdev; +- +- of_property_read_u32(np, "qcom,num_gmac", &edma_cinfo->num_gmac); +- if (edma_cinfo->num_gmac > EDMA_MAX_PORTID_SUPPORTED) { +- pr_err("Invalid DTSI Entry for qcom,num_gmac\n"); +- err = -EINVAL; +- goto err_cinfo; +- } +- +- /* Initialize the netdev array before allocation +- * to avoid double free +- */ +- for (i = 0 ; i < edma_cinfo->num_gmac ; i++) +- edma_netdev[i] = NULL; +- +- for (i = 0 ; i < edma_cinfo->num_gmac ; i++) { +- edma_netdev[i] = alloc_etherdev_mqs(sizeof(struct edma_adapter), +- EDMA_NETDEV_TX_QUEUE, EDMA_NETDEV_RX_QUEUE); +- +- if (!edma_netdev[i]) { +- dev_err(&pdev->dev, +- "net device alloc fails for index=%d\n", i); +- err = -ENODEV; +- goto err_ioremap; +- } +- +- SET_NETDEV_DEV(edma_netdev[i], &pdev->dev); +- platform_set_drvdata(pdev, edma_netdev[i]); +- edma_cinfo->netdev[i] = edma_netdev[i]; +- } +- +- /* Fill ring details */ +- edma_cinfo->num_tx_queues = EDMA_MAX_TRANSMIT_QUEUE; +- edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / 4); +- edma_cinfo->tx_ring_count = EDMA_TX_RING_SIZE; +- +- /* Update num rx queues based on module parameter */ +- edma_cinfo->num_rx_queues = num_rxq; +- edma_cinfo->num_rxq_per_core = ((num_rxq == 4) ? 1 : 2); +- +- edma_cinfo->rx_ring_count = EDMA_RX_RING_SIZE; +- +- hw = &edma_cinfo->hw; +- +- /* Fill HW defaults */ +- hw->tx_intr_mask = EDMA_TX_IMR_NORMAL_MASK; +- hw->rx_intr_mask = EDMA_RX_IMR_NORMAL_MASK; +- +- of_property_read_u32(np, "qcom,page-mode", &edma_cinfo->page_mode); +- of_property_read_u32(np, "qcom,rx_head_buf_size", +- &hw->rx_head_buff_size); +- +- if (overwrite_mode) { +- dev_info(&pdev->dev, "page mode overwritten"); +- edma_cinfo->page_mode = page_mode; +- } +- +- if (jumbo_mru) +- edma_cinfo->fraglist_mode = 1; +- +- if (edma_cinfo->page_mode) +- hw->rx_head_buff_size = EDMA_RX_HEAD_BUFF_SIZE_JUMBO; +- else if (edma_cinfo->fraglist_mode) +- hw->rx_head_buff_size = jumbo_mru; +- else if (!hw->rx_head_buff_size) +- hw->rx_head_buff_size = EDMA_RX_HEAD_BUFF_SIZE; +- +- hw->misc_intr_mask = 0; +- hw->wol_intr_mask = 0; +- +- hw->intr_clear_type = EDMA_INTR_CLEAR_TYPE; +- hw->intr_sw_idx_w = EDMA_INTR_SW_IDX_W_TYPE; +- +- /* configure RSS type to the different protocol that can be +- * supported +- */ +- hw->rss_type = EDMA_RSS_TYPE_IPV4TCP | EDMA_RSS_TYPE_IPV6_TCP | +- EDMA_RSS_TYPE_IPV4_UDP | EDMA_RSS_TYPE_IPV6UDP | +- EDMA_RSS_TYPE_IPV4 | EDMA_RSS_TYPE_IPV6; +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- +- edma_cinfo->hw.hw_addr = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(edma_cinfo->hw.hw_addr)) { +- err = PTR_ERR(edma_cinfo->hw.hw_addr); +- goto err_ioremap; +- } +- +- edma_hw_addr = (u32)edma_cinfo->hw.hw_addr; +- +- /* Parse tx queue interrupt number from device tree */ +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) +- edma_cinfo->tx_irq[i] = platform_get_irq(pdev, i); +- +- /* Parse rx queue interrupt number from device tree +- * Here we are setting j to point to the point where we +- * left tx interrupt parsing(i.e 16) and run run the loop +- * from 0 to 7 to parse rx interrupt number. +- */ +- for (i = 0, j = edma_cinfo->num_tx_queues, k = 0; +- i < edma_cinfo->num_rx_queues; i++) { +- edma_cinfo->rx_irq[k] = platform_get_irq(pdev, j); +- k += ((num_rxq == 4) ? 2 : 1); +- j += ((num_rxq == 4) ? 2 : 1); +- } +- +- edma_cinfo->rx_head_buffer_len = edma_cinfo->hw.rx_head_buff_size; +- edma_cinfo->rx_page_buffer_len = PAGE_SIZE; +- +- err = edma_alloc_queues_tx(edma_cinfo); +- if (err) { +- dev_err(&pdev->dev, "Allocation of TX queue failed\n"); +- goto err_tx_qinit; +- } +- +- err = edma_alloc_queues_rx(edma_cinfo); +- if (err) { +- dev_err(&pdev->dev, "Allocation of RX queue failed\n"); +- goto err_rx_qinit; +- } +- +- err = edma_alloc_tx_rings(edma_cinfo); +- if (err) { +- dev_err(&pdev->dev, "Allocation of TX resources failed\n"); +- goto err_tx_rinit; +- } +- +- err = edma_alloc_rx_rings(edma_cinfo); +- if (err) { +- dev_err(&pdev->dev, "Allocation of RX resources failed\n"); +- goto err_rx_rinit; +- } +- +- /* Initialize netdev and netdev bitmap for transmit descriptor rings */ +- for (i = 0; i < edma_cinfo->num_tx_queues; i++) { +- struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[i]; +- int j; +- +- etdr->netdev_bmp = 0; +- for (j = 0; j < EDMA_MAX_NETDEV_PER_QUEUE; j++) { +- etdr->netdev[j] = NULL; +- etdr->nq[j] = NULL; +- } +- } +- +- if (of_property_read_bool(np, "qcom,mdio_supported")) { +- mdio_node = of_find_compatible_node(NULL, NULL, +- "qcom,ipq4019-mdio"); +- if (!mdio_node) { +- dev_err(&pdev->dev, "cannot find mdio node by phandle"); +- err = -EIO; +- goto err_mdiobus_init_fail; +- } +- +- miibus = of_mdio_find_bus(mdio_node); +- if (!miibus) +- return -EINVAL; +- } +- +- if (of_property_read_bool(np, "qcom,single-phy") && +- edma_cinfo->num_gmac == 1) { +- err = ess_parse(edma_cinfo); +- if (!err) +- err = ess_reset(edma_cinfo); +- if (err) +- goto err_single_phy_init; +- else +- edma_cinfo->is_single_phy = true; +- } +- +- for_each_available_child_of_node(np, pnp) { +- /* this check is needed if parent and daughter dts have +- * different number of gmac nodes +- */ +- if (idx_mac == edma_cinfo->num_gmac) { +- of_node_put(np); +- break; +- } +- +- of_get_mac_address(pnp, edma_netdev[idx_mac]->dev_addr); +- +- idx_mac++; +- } +- +- /* Populate the adapter structure register the netdevice */ +- for (i = 0; i < edma_cinfo->num_gmac; i++) { +- int k, m; +- +- adapter[i] = netdev_priv(edma_netdev[i]); +- adapter[i]->netdev = edma_netdev[i]; +- adapter[i]->pdev = pdev; +- for (j = 0; j < CONFIG_NR_CPUS; j++) { +- m = i % 2; +- adapter[i]->tx_start_offset[j] = +- ((j << EDMA_TX_CPU_START_SHIFT) + (m << 1)); +- /* Share the queues with available net-devices. +- * For instance , with 5 net-devices +- * eth0/eth2/eth4 will share q0,q1,q4,q5,q8,q9,q12,q13 +- * and eth1/eth3 will get the remaining. +- */ +- for (k = adapter[i]->tx_start_offset[j]; k < +- (adapter[i]->tx_start_offset[j] + 2); k++) { +- if (edma_fill_netdev(edma_cinfo, k, i, j)) { +- pr_err("Netdev overflow Error\n"); +- goto err_register; +- } +- } +- } +- +- adapter[i]->edma_cinfo = edma_cinfo; +- edma_netdev[i]->netdev_ops = &edma_axi_netdev_ops; +- edma_netdev[i]->max_mtu = 9000; +- edma_netdev[i]->features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM +- | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_SG | +- NETIF_F_TSO | NETIF_F_GRO | NETIF_F_HW_VLAN_CTAG_TX; +- edma_netdev[i]->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | +- NETIF_F_HW_VLAN_CTAG_RX +- | NETIF_F_SG | NETIF_F_TSO | NETIF_F_GRO; +- edma_netdev[i]->vlan_features = NETIF_F_HW_CSUM | NETIF_F_SG | +- NETIF_F_TSO | NETIF_F_GRO; +- edma_netdev[i]->wanted_features = NETIF_F_HW_CSUM | NETIF_F_SG | +- NETIF_F_TSO | NETIF_F_GRO; +- +-#ifdef CONFIG_RFS_ACCEL +- edma_netdev[i]->features |= NETIF_F_NTUPLE | NETIF_F_RXHASH; +- edma_netdev[i]->hw_features |= NETIF_F_NTUPLE | NETIF_F_RXHASH; +- edma_netdev[i]->vlan_features |= NETIF_F_NTUPLE | NETIF_F_RXHASH; +- edma_netdev[i]->wanted_features |= NETIF_F_NTUPLE | NETIF_F_RXHASH; +-#endif +- edma_set_ethtool_ops(edma_netdev[i]); +- +- /* This just fill in some default MAC address +- */ +- if (!is_valid_ether_addr(edma_netdev[i]->dev_addr)) { +- random_ether_addr(edma_netdev[i]->dev_addr); +- pr_info("EDMA using MAC@ - using"); +- pr_info("%02x:%02x:%02x:%02x:%02x:%02x\n", +- *(edma_netdev[i]->dev_addr), +- *(edma_netdev[i]->dev_addr + 1), +- *(edma_netdev[i]->dev_addr + 2), +- *(edma_netdev[i]->dev_addr + 3), +- *(edma_netdev[i]->dev_addr + 4), +- *(edma_netdev[i]->dev_addr + 5)); +- } +- +- err = register_netdev(edma_netdev[i]); +- if (err) +- goto err_register; +- +- /* carrier off reporting is important to +- * ethtool even BEFORE open +- */ +- netif_carrier_off(edma_netdev[i]); +- +- /* Allocate reverse irq cpu mapping structure for +- * receive queues +- */ +-#ifdef CONFIG_RFS_ACCEL +- edma_netdev[i]->rx_cpu_rmap = +- alloc_irq_cpu_rmap(EDMA_NETDEV_RX_QUEUE); +- if (!edma_netdev[i]->rx_cpu_rmap) { +- err = -ENOMEM; +- goto err_rmap_alloc_fail; +- } +-#endif +- } +- +- for (i = 0; i < EDMA_MAX_PORTID_BITMAP_INDEX; i++) +- edma_cinfo->portid_netdev_lookup_tbl[i] = NULL; +- +- for_each_available_child_of_node(np, pnp) { +- const uint32_t *vlan_tag = NULL; +- int len; +- +- /* this check is needed if parent and daughter dts have +- * different number of gmac nodes +- */ +- if (idx == edma_cinfo->num_gmac) +- break; +- +- /* Populate port-id to netdev lookup table */ +- vlan_tag = of_get_property(pnp, "vlan_tag", &len); +- if (!vlan_tag) { +- pr_err("Vlan tag parsing Failed.\n"); +- goto err_rmap_alloc_fail; +- } +- +- adapter[idx]->default_vlan_tag = of_read_number(vlan_tag, 1); +- vlan_tag++; +- portid_bmp = of_read_number(vlan_tag, 1); +- adapter[idx]->dp_bitmap = portid_bmp; +- +- portid_bmp = portid_bmp >> 1; /* We ignore CPU Port bit 0 */ +- while (portid_bmp) { +- int port_bit = ffs(portid_bmp); +- +- if (port_bit > EDMA_MAX_PORTID_SUPPORTED) +- goto err_rmap_alloc_fail; +- edma_cinfo->portid_netdev_lookup_tbl[port_bit] = +- edma_netdev[idx]; +- portid_bmp &= ~(1 << (port_bit - 1)); +- } +- +- if (!of_property_read_u32(pnp, "qcom,poll_required", +- &adapter[idx]->poll_required)) { +- if (adapter[idx]->poll_required) { +- of_property_read_u32(pnp, "qcom,phy_mdio_addr", +- &adapter[idx]->phy_mdio_addr); +- of_property_read_u32(pnp, "qcom,forced_speed", +- &adapter[idx]->forced_speed); +- of_property_read_u32(pnp, "qcom,forced_duplex", +- &adapter[idx]->forced_duplex); +- +- /* create a phyid using MDIO bus id +- * and MDIO bus address +- */ +- snprintf(adapter[idx]->phy_id, +- MII_BUS_ID_SIZE + 3, PHY_ID_FMT, +- miibus->id, +- adapter[idx]->phy_mdio_addr); +- } +- } else { +- adapter[idx]->poll_required = 0; +- adapter[idx]->forced_speed = SPEED_1000; +- adapter[idx]->forced_duplex = DUPLEX_FULL; +- } +- +- idx++; +- } +- +- edma_cinfo->edma_ctl_table_hdr = register_net_sysctl(&init_net, +- "net/edma", +- edma_table); +- if (!edma_cinfo->edma_ctl_table_hdr) { +- dev_err(&pdev->dev, "edma sysctl table hdr not registered\n"); +- goto err_unregister_sysctl_tbl; +- } +- +- /* Disable all 16 Tx and 8 rx irqs */ +- edma_irq_disable(edma_cinfo); +- +- err = edma_reset(edma_cinfo); +- if (err) { +- err = -EIO; +- goto err_reset; +- } +- +- /* populate per_core_info, do a napi_Add, request 16 TX irqs, +- * 8 RX irqs, do a napi enable +- */ +- for (i = 0; i < CONFIG_NR_CPUS; i++) { +- u8 rx_start; +- +- edma_cinfo->edma_percpu_info[i].napi.state = 0; +- +- netif_napi_add(edma_netdev[0], +- &edma_cinfo->edma_percpu_info[i].napi, +- edma_poll, 64); +- napi_enable(&edma_cinfo->edma_percpu_info[i].napi); +- edma_cinfo->edma_percpu_info[i].tx_mask = tx_mask[i]; +- edma_cinfo->edma_percpu_info[i].rx_mask = EDMA_RX_PER_CPU_MASK +- << (i << EDMA_RX_PER_CPU_MASK_SHIFT); +- edma_cinfo->edma_percpu_info[i].tx_start = tx_start[i]; +- edma_cinfo->edma_percpu_info[i].rx_start = +- i << EDMA_RX_CPU_START_SHIFT; +- rx_start = i << EDMA_RX_CPU_START_SHIFT; +- edma_cinfo->edma_percpu_info[i].tx_status = 0; +- edma_cinfo->edma_percpu_info[i].rx_status = 0; +- edma_cinfo->edma_percpu_info[i].edma_cinfo = edma_cinfo; +- +- /* Request irq per core */ +- for (j = edma_cinfo->edma_percpu_info[i].tx_start; +- j < tx_start[i] + 4; j++) { +- sprintf(&edma_tx_irq[j][0], "edma_eth_tx%d", j); +- err = request_irq(edma_cinfo->tx_irq[j], +- edma_interrupt, +- 0, +- &edma_tx_irq[j][0], +- &edma_cinfo->edma_percpu_info[i]); +- if (err) +- goto err_reset; +- } +- +- for (j = edma_cinfo->edma_percpu_info[i].rx_start; +- j < (rx_start + +- ((edma_cinfo->num_rx_queues == 4) ? 1 : 2)); +- j++) { +- sprintf(&edma_rx_irq[j][0], "edma_eth_rx%d", j); +- err = request_irq(edma_cinfo->rx_irq[j], +- edma_interrupt, +- 0, +- &edma_rx_irq[j][0], +- &edma_cinfo->edma_percpu_info[i]); +- if (err) +- goto err_reset; +- } +- +-#ifdef CONFIG_RFS_ACCEL +- for (j = edma_cinfo->edma_percpu_info[i].rx_start; +- j < rx_start + 2; j += 2) { +- err = irq_cpu_rmap_add(edma_netdev[0]->rx_cpu_rmap, +- edma_cinfo->rx_irq[j]); +- if (err) +- goto err_rmap_add_fail; +- } +-#endif +- } +- +- /* Used to clear interrupt status, allocate rx buffer, +- * configure edma descriptors registers +- */ +- err = edma_configure(edma_cinfo); +- if (err) { +- err = -EIO; +- goto err_configure; +- } +- +- /* Configure RSS indirection table. +- * 128 hash will be configured in the following +- * pattern: hash{0,1,2,3} = {Q0,Q2,Q4,Q6} respectively +- * and so on +- */ +- for (i = 0; i < EDMA_NUM_IDT; i++) +- edma_write_reg(EDMA_REG_RSS_IDT(i), EDMA_RSS_IDT_VALUE); +- +- /* Configure load balance mapping table. +- * 4 table entry will be configured according to the +- * following pattern: load_balance{0,1,2,3} = {Q0,Q1,Q3,Q4} +- * respectively. +- */ +- edma_write_reg(EDMA_REG_LB_RING, EDMA_LB_REG_VALUE); +- +- /* Configure Virtual queue for Tx rings +- * User can also change this value runtime through +- * a sysctl +- */ +- edma_write_reg(EDMA_REG_VQ_CTRL0, EDMA_VQ_REG_VALUE); +- edma_write_reg(EDMA_REG_VQ_CTRL1, EDMA_VQ_REG_VALUE); +- +- /* Configure Max AXI Burst write size to 128 bytes*/ +- edma_write_reg(EDMA_REG_AXIW_CTRL_MAXWRSIZE, +- EDMA_AXIW_MAXWRSIZE_VALUE); +- +- /* Enable All 16 tx and 8 rx irq mask */ +- edma_irq_enable(edma_cinfo); +- edma_enable_tx_ctrl(&edma_cinfo->hw); +- edma_enable_rx_ctrl(&edma_cinfo->hw); +- +- for (i = 0; i < edma_cinfo->num_gmac; i++) { +- if (adapter[i]->poll_required) { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0) +- phy_interface_t phy_mode; +- +- err = of_get_phy_mode(np, &phy_mode); +- if (err) +- phy_mode = PHY_INTERFACE_MODE_SGMII; +-#else +- int phy_mode = of_get_phy_mode(np); +- if (phy_mode < 0) +- phy_mode = PHY_INTERFACE_MODE_SGMII; +-#endif +- adapter[i]->phydev = +- phy_connect(edma_netdev[i], +- (const char *)adapter[i]->phy_id, +- &edma_adjust_link, +- phy_mode); +- if (IS_ERR(adapter[i]->phydev)) { +- dev_dbg(&pdev->dev, "PHY attach FAIL"); +- err = -EIO; +- goto edma_phy_attach_fail; +- } else { +- linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, +- adapter[i]->phydev->advertising); +- linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, +- adapter[i]->phydev->advertising); +- linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, +- adapter[i]->phydev->supported); +- linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, +- adapter[i]->phydev->supported); +- } +- } else { +- adapter[i]->phydev = NULL; +- } +- } +- +- spin_lock_init(&edma_cinfo->stats_lock); +- +- timer_setup(&edma_cinfo->edma_stats_timer, edma_statistics_timer, 0); +- mod_timer(&edma_cinfo->edma_stats_timer, jiffies + 1*HZ); +- +- return 0; +- +-edma_phy_attach_fail: +- miibus = NULL; +-err_configure: +-#ifdef CONFIG_RFS_ACCEL +- for (i = 0; i < edma_cinfo->num_gmac; i++) { +- free_irq_cpu_rmap(adapter[i]->netdev->rx_cpu_rmap); +- adapter[i]->netdev->rx_cpu_rmap = NULL; +- } +-#endif +-err_rmap_add_fail: +- edma_free_irqs(adapter[0]); +- for (i = 0; i < CONFIG_NR_CPUS; i++) +- napi_disable(&edma_cinfo->edma_percpu_info[i].napi); +-err_reset: +-err_unregister_sysctl_tbl: +-err_rmap_alloc_fail: +- for (i = 0; i < edma_cinfo->num_gmac; i++) +- unregister_netdev(edma_netdev[i]); +-err_register: +-err_single_phy_init: +- iounmap(edma_cinfo->ess_hw_addr); +- clk_disable_unprepare(edma_cinfo->ess_clk); +-err_mdiobus_init_fail: +- edma_free_rx_rings(edma_cinfo); +-err_rx_rinit: +- edma_free_tx_rings(edma_cinfo); +-err_tx_rinit: +- edma_free_queues(edma_cinfo); +-err_rx_qinit: +-err_tx_qinit: +- iounmap(edma_cinfo->hw.hw_addr); +-err_ioremap: +- for (i = 0; i < edma_cinfo->num_gmac; i++) { +- if (edma_netdev[i]) +- free_netdev(edma_netdev[i]); +- } +-err_cinfo: +- kfree(edma_cinfo); +-err_alloc: +- return err; +-} +- +-/* edma_axi_remove() +- * Device Removal Routine +- * +- * edma_axi_remove is called by the platform subsystem to alert the driver +- * that it should release a platform device. +- */ +-static int edma_axi_remove(struct platform_device *pdev) +-{ +- struct edma_adapter *adapter = netdev_priv(edma_netdev[0]); +- struct edma_common_info *edma_cinfo = adapter->edma_cinfo; +- struct edma_hw *hw = &edma_cinfo->hw; +- int i; +- +- for (i = 0; i < edma_cinfo->num_gmac; i++) +- unregister_netdev(edma_netdev[i]); +- +- edma_stop_rx_tx(hw); +- for (i = 0; i < CONFIG_NR_CPUS; i++) +- napi_disable(&edma_cinfo->edma_percpu_info[i].napi); +- +- edma_irq_disable(edma_cinfo); +- edma_write_reg(EDMA_REG_RX_ISR, 0xff); +- edma_write_reg(EDMA_REG_TX_ISR, 0xffff); +-#ifdef CONFIG_RFS_ACCEL +- for (i = 0; i < edma_cinfo->num_gmac; i++) { +- free_irq_cpu_rmap(edma_netdev[i]->rx_cpu_rmap); +- edma_netdev[i]->rx_cpu_rmap = NULL; +- } +-#endif +- +- for (i = 0; i < edma_cinfo->num_gmac; i++) { +- struct edma_adapter *adapter = netdev_priv(edma_netdev[i]); +- +- if (adapter->phydev) +- phy_disconnect(adapter->phydev); +- } +- +- del_timer_sync(&edma_cinfo->edma_stats_timer); +- edma_free_irqs(adapter); +- unregister_net_sysctl_table(edma_cinfo->edma_ctl_table_hdr); +- iounmap(edma_cinfo->ess_hw_addr); +- clk_disable_unprepare(edma_cinfo->ess_clk); +- edma_free_tx_resources(edma_cinfo); +- edma_free_rx_resources(edma_cinfo); +- edma_free_tx_rings(edma_cinfo); +- edma_free_rx_rings(edma_cinfo); +- edma_free_queues(edma_cinfo); +- for (i = 0; i < edma_cinfo->num_gmac; i++) +- free_netdev(edma_netdev[i]); +- +- kfree(edma_cinfo); +- +- return 0; +-} +- +-static const struct of_device_id edma_of_mtable[] = { +- {.compatible = "qcom,ess-edma" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, edma_of_mtable); +- +-static struct platform_driver edma_axi_driver = { +- .driver = { +- .name = edma_axi_driver_name, +- .of_match_table = edma_of_mtable, +- }, +- .probe = edma_axi_probe, +- .remove = edma_axi_remove, +-}; +- +-module_platform_driver(edma_axi_driver); +- +-MODULE_AUTHOR("Qualcomm Atheros Inc"); +-MODULE_DESCRIPTION("QCA ESS EDMA driver"); +-MODULE_LICENSE("GPL"); +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/ess_edma.h ++++ /dev/null +@@ -1,389 +0,0 @@ +-/* +- * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +- * +- * Permission to use, copy, modify, and/or distribute this software for +- * any purpose with or without fee is hereby granted, provided that the +- * above copyright notice and this permission notice appear in all copies. +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#ifndef _ESS_EDMA_H_ +-#define _ESS_EDMA_H_ +- +-#include +- +-struct edma_adapter; +-struct edma_hw; +- +-/* register definition */ +-#define EDMA_REG_MAS_CTRL 0x0 +-#define EDMA_REG_TIMEOUT_CTRL 0x004 +-#define EDMA_REG_DBG0 0x008 +-#define EDMA_REG_DBG1 0x00C +-#define EDMA_REG_SW_CTRL0 0x100 +-#define EDMA_REG_SW_CTRL1 0x104 +- +-/* Interrupt Status Register */ +-#define EDMA_REG_RX_ISR 0x200 +-#define EDMA_REG_TX_ISR 0x208 +-#define EDMA_REG_MISC_ISR 0x210 +-#define EDMA_REG_WOL_ISR 0x218 +- +-#define EDMA_MISC_ISR_RX_URG_Q(x) (1 << x) +- +-#define EDMA_MISC_ISR_AXIR_TIMEOUT 0x00000100 +-#define EDMA_MISC_ISR_AXIR_ERR 0x00000200 +-#define EDMA_MISC_ISR_TXF_DEAD 0x00000400 +-#define EDMA_MISC_ISR_AXIW_ERR 0x00000800 +-#define EDMA_MISC_ISR_AXIW_TIMEOUT 0x00001000 +- +-#define EDMA_WOL_ISR 0x00000001 +- +-/* Interrupt Mask Register */ +-#define EDMA_REG_MISC_IMR 0x214 +-#define EDMA_REG_WOL_IMR 0x218 +- +-#define EDMA_RX_IMR_NORMAL_MASK 0x1 +-#define EDMA_TX_IMR_NORMAL_MASK 0x1 +-#define EDMA_MISC_IMR_NORMAL_MASK 0x80001FFF +-#define EDMA_WOL_IMR_NORMAL_MASK 0x1 +- +-/* Edma receive consumer index */ +-#define EDMA_REG_RX_SW_CONS_IDX_Q(x) (0x220 + ((x) << 2)) /* x is the queue id */ +-/* Edma transmit consumer index */ +-#define EDMA_REG_TX_SW_CONS_IDX_Q(x) (0x240 + ((x) << 2)) /* x is the queue id */ +- +-/* IRQ Moderator Initial Timer Register */ +-#define EDMA_REG_IRQ_MODRT_TIMER_INIT 0x280 +-#define EDMA_IRQ_MODRT_TIMER_MASK 0xFFFF +-#define EDMA_IRQ_MODRT_RX_TIMER_SHIFT 0 +-#define EDMA_IRQ_MODRT_TX_TIMER_SHIFT 16 +- +-/* Interrupt Control Register */ +-#define EDMA_REG_INTR_CTRL 0x284 +-#define EDMA_INTR_CLR_TYP_SHIFT 0 +-#define EDMA_INTR_SW_IDX_W_TYP_SHIFT 1 +-#define EDMA_INTR_CLEAR_TYPE_W1 0 +-#define EDMA_INTR_CLEAR_TYPE_R 1 +- +-/* RX Interrupt Mask Register */ +-#define EDMA_REG_RX_INT_MASK_Q(x) (0x300 + ((x) << 2)) /* x = queue id */ +- +-/* TX Interrupt mask register */ +-#define EDMA_REG_TX_INT_MASK_Q(x) (0x340 + ((x) << 2)) /* x = queue id */ +- +-/* Load Ptr Register +- * Software sets this bit after the initialization of the head and tail +- */ +-#define EDMA_REG_TX_SRAM_PART 0x400 +-#define EDMA_LOAD_PTR_SHIFT 16 +- +-/* TXQ Control Register */ +-#define EDMA_REG_TXQ_CTRL 0x404 +-#define EDMA_TXQ_CTRL_IP_OPTION_EN 0x10 +-#define EDMA_TXQ_CTRL_TXQ_EN 0x20 +-#define EDMA_TXQ_CTRL_ENH_MODE 0x40 +-#define EDMA_TXQ_CTRL_LS_8023_EN 0x80 +-#define EDMA_TXQ_CTRL_TPD_BURST_EN 0x100 +-#define EDMA_TXQ_CTRL_LSO_BREAK_EN 0x200 +-#define EDMA_TXQ_NUM_TPD_BURST_MASK 0xF +-#define EDMA_TXQ_TXF_BURST_NUM_MASK 0xFFFF +-#define EDMA_TXQ_NUM_TPD_BURST_SHIFT 0 +-#define EDMA_TXQ_TXF_BURST_NUM_SHIFT 16 +- +-#define EDMA_REG_TXF_WATER_MARK 0x408 /* In 8-bytes */ +-#define EDMA_TXF_WATER_MARK_MASK 0x0FFF +-#define EDMA_TXF_LOW_WATER_MARK_SHIFT 0 +-#define EDMA_TXF_HIGH_WATER_MARK_SHIFT 16 +-#define EDMA_TXQ_CTRL_BURST_MODE_EN 0x80000000 +- +-/* WRR Control Register */ +-#define EDMA_REG_WRR_CTRL_Q0_Q3 0x40c +-#define EDMA_REG_WRR_CTRL_Q4_Q7 0x410 +-#define EDMA_REG_WRR_CTRL_Q8_Q11 0x414 +-#define EDMA_REG_WRR_CTRL_Q12_Q15 0x418 +- +-/* Weight round robin(WRR), it takes queue as input, and computes +- * starting bits where we need to write the weight for a particular +- * queue +- */ +-#define EDMA_WRR_SHIFT(x) (((x) * 5) % 20) +- +-/* Tx Descriptor Control Register */ +-#define EDMA_REG_TPD_RING_SIZE 0x41C +-#define EDMA_TPD_RING_SIZE_SHIFT 0 +-#define EDMA_TPD_RING_SIZE_MASK 0xFFFF +- +-/* Transmit descriptor base address */ +-#define EDMA_REG_TPD_BASE_ADDR_Q(x) (0x420 + ((x) << 2)) /* x = queue id */ +- +-/* TPD Index Register */ +-#define EDMA_REG_TPD_IDX_Q(x) (0x460 + ((x) << 2)) /* x = queue id */ +- +-#define EDMA_TPD_PROD_IDX_BITS 0x0000FFFF +-#define EDMA_TPD_CONS_IDX_BITS 0xFFFF0000 +-#define EDMA_TPD_PROD_IDX_MASK 0xFFFF +-#define EDMA_TPD_CONS_IDX_MASK 0xFFFF +-#define EDMA_TPD_PROD_IDX_SHIFT 0 +-#define EDMA_TPD_CONS_IDX_SHIFT 16 +- +-/* TX Virtual Queue Mapping Control Register */ +-#define EDMA_REG_VQ_CTRL0 0x4A0 +-#define EDMA_REG_VQ_CTRL1 0x4A4 +- +-/* Virtual QID shift, it takes queue as input, and computes +- * Virtual QID position in virtual qid control register +- */ +-#define EDMA_VQ_ID_SHIFT(i) (((i) * 3) % 24) +- +-/* Virtual Queue Default Value */ +-#define EDMA_VQ_REG_VALUE 0x240240 +- +-/* Tx side Port Interface Control Register */ +-#define EDMA_REG_PORT_CTRL 0x4A8 +-#define EDMA_PAD_EN_SHIFT 15 +- +-/* Tx side VLAN Configuration Register */ +-#define EDMA_REG_VLAN_CFG 0x4AC +- +-#define EDMA_TX_CVLAN 16 +-#define EDMA_TX_INS_CVLAN 17 +-#define EDMA_TX_CVLAN_TAG_SHIFT 0 +- +-#define EDMA_TX_SVLAN 14 +-#define EDMA_TX_INS_SVLAN 15 +-#define EDMA_TX_SVLAN_TAG_SHIFT 16 +- +-/* Tx Queue Packet Statistic Register */ +-#define EDMA_REG_TX_STAT_PKT_Q(x) (0x700 + ((x) << 3)) /* x = queue id */ +- +-#define EDMA_TX_STAT_PKT_MASK 0xFFFFFF +- +-/* Tx Queue Byte Statistic Register */ +-#define EDMA_REG_TX_STAT_BYTE_Q(x) (0x704 + ((x) << 3)) /* x = queue id */ +- +-/* Load Balance Based Ring Offset Register */ +-#define EDMA_REG_LB_RING 0x800 +-#define EDMA_LB_RING_ENTRY_MASK 0xff +-#define EDMA_LB_RING_ID_MASK 0x7 +-#define EDMA_LB_RING_PROFILE_ID_MASK 0x3 +-#define EDMA_LB_RING_ENTRY_BIT_OFFSET 8 +-#define EDMA_LB_RING_ID_OFFSET 0 +-#define EDMA_LB_RING_PROFILE_ID_OFFSET 3 +-#define EDMA_LB_REG_VALUE 0x6040200 +- +-/* Load Balance Priority Mapping Register */ +-#define EDMA_REG_LB_PRI_START 0x804 +-#define EDMA_REG_LB_PRI_END 0x810 +-#define EDMA_LB_PRI_REG_INC 4 +-#define EDMA_LB_PRI_ENTRY_BIT_OFFSET 4 +-#define EDMA_LB_PRI_ENTRY_MASK 0xf +- +-/* RSS Priority Mapping Register */ +-#define EDMA_REG_RSS_PRI 0x820 +-#define EDMA_RSS_PRI_ENTRY_MASK 0xf +-#define EDMA_RSS_RING_ID_MASK 0x7 +-#define EDMA_RSS_PRI_ENTRY_BIT_OFFSET 4 +- +-/* RSS Indirection Register */ +-#define EDMA_REG_RSS_IDT(x) (0x840 + ((x) << 2)) /* x = No. of indirection table */ +-#define EDMA_NUM_IDT 16 +-#define EDMA_RSS_IDT_VALUE 0x64206420 +- +-/* Default RSS Ring Register */ +-#define EDMA_REG_DEF_RSS 0x890 +-#define EDMA_DEF_RSS_MASK 0x7 +- +-/* RSS Hash Function Type Register */ +-#define EDMA_REG_RSS_TYPE 0x894 +-#define EDMA_RSS_TYPE_NONE 0x01 +-#define EDMA_RSS_TYPE_IPV4TCP 0x02 +-#define EDMA_RSS_TYPE_IPV6_TCP 0x04 +-#define EDMA_RSS_TYPE_IPV4_UDP 0x08 +-#define EDMA_RSS_TYPE_IPV6UDP 0x10 +-#define EDMA_RSS_TYPE_IPV4 0x20 +-#define EDMA_RSS_TYPE_IPV6 0x40 +-#define EDMA_RSS_HASH_MODE_MASK 0x7f +- +-#define EDMA_REG_RSS_HASH_VALUE 0x8C0 +- +-#define EDMA_REG_RSS_TYPE_RESULT 0x8C4 +- +-#define EDMA_HASH_TYPE_START 0 +-#define EDMA_HASH_TYPE_END 5 +-#define EDMA_HASH_TYPE_SHIFT 12 +- +-#define EDMA_RFS_FLOW_ENTRIES 1024 +-#define EDMA_RFS_FLOW_ENTRIES_MASK (EDMA_RFS_FLOW_ENTRIES - 1) +-#define EDMA_RFS_EXPIRE_COUNT_PER_CALL 128 +- +-/* RFD Base Address Register */ +-#define EDMA_REG_RFD_BASE_ADDR_Q(x) (0x950 + ((x) << 2)) /* x = queue id */ +- +-/* RFD Index Register */ +-#define EDMA_REG_RFD_IDX_Q(x) (0x9B0 + ((x) << 2)) +- +-#define EDMA_RFD_PROD_IDX_BITS 0x00000FFF +-#define EDMA_RFD_CONS_IDX_BITS 0x0FFF0000 +-#define EDMA_RFD_PROD_IDX_MASK 0xFFF +-#define EDMA_RFD_CONS_IDX_MASK 0xFFF +-#define EDMA_RFD_PROD_IDX_SHIFT 0 +-#define EDMA_RFD_CONS_IDX_SHIFT 16 +- +-/* Rx Descriptor Control Register */ +-#define EDMA_REG_RX_DESC0 0xA10 +-#define EDMA_RFD_RING_SIZE_MASK 0xFFF +-#define EDMA_RX_BUF_SIZE_MASK 0xFFFF +-#define EDMA_RFD_RING_SIZE_SHIFT 0 +-#define EDMA_RX_BUF_SIZE_SHIFT 16 +- +-#define EDMA_REG_RX_DESC1 0xA14 +-#define EDMA_RXQ_RFD_BURST_NUM_MASK 0x3F +-#define EDMA_RXQ_RFD_PF_THRESH_MASK 0x1F +-#define EDMA_RXQ_RFD_LOW_THRESH_MASK 0xFFF +-#define EDMA_RXQ_RFD_BURST_NUM_SHIFT 0 +-#define EDMA_RXQ_RFD_PF_THRESH_SHIFT 8 +-#define EDMA_RXQ_RFD_LOW_THRESH_SHIFT 16 +- +-/* RXQ Control Register */ +-#define EDMA_REG_RXQ_CTRL 0xA18 +-#define EDMA_FIFO_THRESH_TYPE_SHIF 0 +-#define EDMA_FIFO_THRESH_128_BYTE 0x0 +-#define EDMA_FIFO_THRESH_64_BYTE 0x1 +-#define EDMA_RXQ_CTRL_RMV_VLAN 0x00000002 +-#define EDMA_RXQ_CTRL_EN 0x0000FF00 +- +-/* AXI Burst Size Config */ +-#define EDMA_REG_AXIW_CTRL_MAXWRSIZE 0xA1C +-#define EDMA_AXIW_MAXWRSIZE_VALUE 0x0 +- +-/* Rx Statistics Register */ +-#define EDMA_REG_RX_STAT_BYTE_Q(x) (0xA30 + ((x) << 2)) /* x = queue id */ +-#define EDMA_REG_RX_STAT_PKT_Q(x) (0xA50 + ((x) << 2)) /* x = queue id */ +- +-/* WoL Pattern Length Register */ +-#define EDMA_REG_WOL_PATTERN_LEN0 0xC00 +-#define EDMA_WOL_PT_LEN_MASK 0xFF +-#define EDMA_WOL_PT0_LEN_SHIFT 0 +-#define EDMA_WOL_PT1_LEN_SHIFT 8 +-#define EDMA_WOL_PT2_LEN_SHIFT 16 +-#define EDMA_WOL_PT3_LEN_SHIFT 24 +- +-#define EDMA_REG_WOL_PATTERN_LEN1 0xC04 +-#define EDMA_WOL_PT4_LEN_SHIFT 0 +-#define EDMA_WOL_PT5_LEN_SHIFT 8 +-#define EDMA_WOL_PT6_LEN_SHIFT 16 +- +-/* WoL Control Register */ +-#define EDMA_REG_WOL_CTRL 0xC08 +-#define EDMA_WOL_WK_EN 0x00000001 +-#define EDMA_WOL_MG_EN 0x00000002 +-#define EDMA_WOL_PT0_EN 0x00000004 +-#define EDMA_WOL_PT1_EN 0x00000008 +-#define EDMA_WOL_PT2_EN 0x00000010 +-#define EDMA_WOL_PT3_EN 0x00000020 +-#define EDMA_WOL_PT4_EN 0x00000040 +-#define EDMA_WOL_PT5_EN 0x00000080 +-#define EDMA_WOL_PT6_EN 0x00000100 +- +-/* MAC Control Register */ +-#define EDMA_REG_MAC_CTRL0 0xC20 +-#define EDMA_REG_MAC_CTRL1 0xC24 +- +-/* WoL Pattern Register */ +-#define EDMA_REG_WOL_PATTERN_START 0x5000 +-#define EDMA_PATTERN_PART_REG_OFFSET 0x40 +- +- +-/* TX descriptor fields */ +-#define EDMA_TPD_HDR_SHIFT 0 +-#define EDMA_TPD_PPPOE_EN 0x00000100 +-#define EDMA_TPD_IP_CSUM_EN 0x00000200 +-#define EDMA_TPD_TCP_CSUM_EN 0x0000400 +-#define EDMA_TPD_UDP_CSUM_EN 0x00000800 +-#define EDMA_TPD_CUSTOM_CSUM_EN 0x00000C00 +-#define EDMA_TPD_LSO_EN 0x00001000 +-#define EDMA_TPD_LSO_V2_EN 0x00002000 +-#define EDMA_TPD_IPV4_EN 0x00010000 +-#define EDMA_TPD_MSS_MASK 0x1FFF +-#define EDMA_TPD_MSS_SHIFT 18 +-#define EDMA_TPD_CUSTOM_CSUM_SHIFT 18 +- +-/* RRD descriptor fields */ +-#define EDMA_RRD_NUM_RFD_MASK 0x000F +-#define EDMA_RRD_SVLAN 0x8000 +-#define EDMA_RRD_FLOW_COOKIE_MASK 0x07FF; +- +-#define EDMA_RRD_PKT_SIZE_MASK 0x3FFF +-#define EDMA_RRD_CSUM_FAIL_MASK 0xC000 +-#define EDMA_RRD_CVLAN 0x0001 +-#define EDMA_RRD_DESC_VALID 0x8000 +- +-#define EDMA_RRD_PRIORITY_SHIFT 4 +-#define EDMA_RRD_PRIORITY_MASK 0x7 +-#define EDMA_RRD_PORT_TYPE_SHIFT 7 +-#define EDMA_RRD_PORT_TYPE_MASK 0x1F +- +-#define ESS_RGMII_CTRL 0x0004 +- +-/* Port status registers */ +-#define ESS_PORT0_STATUS 0x007C +-#define ESS_PORT1_STATUS 0x0080 +-#define ESS_PORT2_STATUS 0x0084 +-#define ESS_PORT3_STATUS 0x0088 +-#define ESS_PORT4_STATUS 0x008C +-#define ESS_PORT5_STATUS 0x0090 +- +-#define ESS_PORT_STATUS_HDX_FLOW_CTL 0x80 +-#define ESS_PORT_STATUS_DUPLEX_MODE 0x40 +-#define ESS_PORT_STATUS_RX_FLOW_EN 0x20 +-#define ESS_PORT_STATUS_TX_FLOW_EN 0x10 +-#define ESS_PORT_STATUS_RX_MAC_EN 0x08 +-#define ESS_PORT_STATUS_TX_MAC_EN 0x04 +-#define ESS_PORT_STATUS_SPEED_INV 0x03 +-#define ESS_PORT_STATUS_SPEED_1000 0x02 +-#define ESS_PORT_STATUS_SPEED_100 0x01 +-#define ESS_PORT_STATUS_SPEED_10 0x00 +- +-#define ESS_PORT_1G_FDX (ESS_PORT_STATUS_DUPLEX_MODE | ESS_PORT_STATUS_RX_FLOW_EN | \ +- ESS_PORT_STATUS_TX_FLOW_EN | ESS_PORT_STATUS_RX_MAC_EN | \ +- ESS_PORT_STATUS_TX_MAC_EN | ESS_PORT_STATUS_SPEED_1000) +- +-#define PHY_STATUS_REG 0x11 +-#define PHY_STATUS_SPEED 0xC000 +-#define PHY_STATUS_SPEED_SHIFT 14 +-#define PHY_STATUS_DUPLEX 0x2000 +-#define PHY_STATUS_DUPLEX_SHIFT 13 +-#define PHY_STATUS_SPEED_DUPLEX_RESOLVED 0x0800 +-#define PHY_STATUS_CARRIER 0x0400 +-#define PHY_STATUS_CARRIER_SHIFT 10 +- +-/* Port lookup control registers */ +-#define ESS_PORT0_LOOKUP_CTRL 0x0660 +-#define ESS_PORT1_LOOKUP_CTRL 0x066C +-#define ESS_PORT2_LOOKUP_CTRL 0x0678 +-#define ESS_PORT3_LOOKUP_CTRL 0x0684 +-#define ESS_PORT4_LOOKUP_CTRL 0x0690 +-#define ESS_PORT5_LOOKUP_CTRL 0x069C +- +-#define ESS_PORT0_HEADER_CTRL 0x009C +- +-#define ESS_PORTS_ALL 0x3f +- +-#define ESS_FWD_CTRL1 0x0624 +-#define ESS_FWD_CTRL1_UC_FLOOD BITS(0, 7) +-#define ESS_FWD_CTRL1_UC_FLOOD_S 0 +-#define ESS_FWD_CTRL1_MC_FLOOD BITS(8, 7) +-#define ESS_FWD_CTRL1_MC_FLOOD_S 8 +-#define ESS_FWD_CTRL1_BC_FLOOD BITS(16, 7) +-#define ESS_FWD_CTRL1_BC_FLOOD_S 16 +-#define ESS_FWD_CTRL1_IGMP BITS(24, 7) +-#define ESS_FWD_CTRL1_IGMP_S 24 +- +-#endif /* _ESS_EDMA_H_ */ +--- a/target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.c ++++ /dev/null +@@ -1,1893 +0,0 @@ +-/* +- * Copyright (c) 2016, The Linux Foundation. All rights reserved. +- * +- * Permission to use, copy, modify, and/or distribute this software for +- * any purpose with or without fee is hereby granted, provided that the +- * above copyright notice and this permission notice appear in all copies. +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "ar40xx.h" +- +-static struct ar40xx_priv *ar40xx_priv; +- +-#define MIB_DESC(_s , _o, _n) \ +- { \ +- .size = (_s), \ +- .offset = (_o), \ +- .name = (_n), \ +- } +- +-static const struct ar40xx_mib_desc ar40xx_mibs[] = { +- MIB_DESC(1, AR40XX_STATS_RXBROAD, "RxBroad"), +- MIB_DESC(1, AR40XX_STATS_RXPAUSE, "RxPause"), +- MIB_DESC(1, AR40XX_STATS_RXMULTI, "RxMulti"), +- MIB_DESC(1, AR40XX_STATS_RXFCSERR, "RxFcsErr"), +- MIB_DESC(1, AR40XX_STATS_RXALIGNERR, "RxAlignErr"), +- MIB_DESC(1, AR40XX_STATS_RXRUNT, "RxRunt"), +- MIB_DESC(1, AR40XX_STATS_RXFRAGMENT, "RxFragment"), +- MIB_DESC(1, AR40XX_STATS_RX64BYTE, "Rx64Byte"), +- MIB_DESC(1, AR40XX_STATS_RX128BYTE, "Rx128Byte"), +- MIB_DESC(1, AR40XX_STATS_RX256BYTE, "Rx256Byte"), +- MIB_DESC(1, AR40XX_STATS_RX512BYTE, "Rx512Byte"), +- MIB_DESC(1, AR40XX_STATS_RX1024BYTE, "Rx1024Byte"), +- MIB_DESC(1, AR40XX_STATS_RX1518BYTE, "Rx1518Byte"), +- MIB_DESC(1, AR40XX_STATS_RXMAXBYTE, "RxMaxByte"), +- MIB_DESC(1, AR40XX_STATS_RXTOOLONG, "RxTooLong"), +- MIB_DESC(2, AR40XX_STATS_RXGOODBYTE, "RxGoodByte"), +- MIB_DESC(2, AR40XX_STATS_RXBADBYTE, "RxBadByte"), +- MIB_DESC(1, AR40XX_STATS_RXOVERFLOW, "RxOverFlow"), +- MIB_DESC(1, AR40XX_STATS_FILTERED, "Filtered"), +- MIB_DESC(1, AR40XX_STATS_TXBROAD, "TxBroad"), +- MIB_DESC(1, AR40XX_STATS_TXPAUSE, "TxPause"), +- MIB_DESC(1, AR40XX_STATS_TXMULTI, "TxMulti"), +- MIB_DESC(1, AR40XX_STATS_TXUNDERRUN, "TxUnderRun"), +- MIB_DESC(1, AR40XX_STATS_TX64BYTE, "Tx64Byte"), +- MIB_DESC(1, AR40XX_STATS_TX128BYTE, "Tx128Byte"), +- MIB_DESC(1, AR40XX_STATS_TX256BYTE, "Tx256Byte"), +- MIB_DESC(1, AR40XX_STATS_TX512BYTE, "Tx512Byte"), +- MIB_DESC(1, AR40XX_STATS_TX1024BYTE, "Tx1024Byte"), +- MIB_DESC(1, AR40XX_STATS_TX1518BYTE, "Tx1518Byte"), +- MIB_DESC(1, AR40XX_STATS_TXMAXBYTE, "TxMaxByte"), +- MIB_DESC(1, AR40XX_STATS_TXOVERSIZE, "TxOverSize"), +- MIB_DESC(2, AR40XX_STATS_TXBYTE, "TxByte"), +- MIB_DESC(1, AR40XX_STATS_TXCOLLISION, "TxCollision"), +- MIB_DESC(1, AR40XX_STATS_TXABORTCOL, "TxAbortCol"), +- MIB_DESC(1, AR40XX_STATS_TXMULTICOL, "TxMultiCol"), +- MIB_DESC(1, AR40XX_STATS_TXSINGLECOL, "TxSingleCol"), +- MIB_DESC(1, AR40XX_STATS_TXEXCDEFER, "TxExcDefer"), +- MIB_DESC(1, AR40XX_STATS_TXDEFER, "TxDefer"), +- MIB_DESC(1, AR40XX_STATS_TXLATECOL, "TxLateCol"), +-}; +- +-static u32 +-ar40xx_read(struct ar40xx_priv *priv, int reg) +-{ +- return readl(priv->hw_addr + reg); +-} +- +-static u32 +-ar40xx_psgmii_read(struct ar40xx_priv *priv, int reg) +-{ +- return readl(priv->psgmii_hw_addr + reg); +-} +- +-static void +-ar40xx_write(struct ar40xx_priv *priv, int reg, u32 val) +-{ +- writel(val, priv->hw_addr + reg); +-} +- +-static u32 +-ar40xx_rmw(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) +-{ +- u32 ret; +- +- ret = ar40xx_read(priv, reg); +- ret &= ~mask; +- ret |= val; +- ar40xx_write(priv, reg, ret); +- return ret; +-} +- +-static void +-ar40xx_psgmii_write(struct ar40xx_priv *priv, int reg, u32 val) +-{ +- writel(val, priv->psgmii_hw_addr + reg); +-} +- +-static void +-ar40xx_phy_dbg_write(struct ar40xx_priv *priv, int phy_addr, +- u16 dbg_addr, u16 dbg_data) +-{ +- struct mii_bus *bus = priv->mii_bus; +- +- mutex_lock(&bus->mdio_lock); +- bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); +- bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA, dbg_data); +- mutex_unlock(&bus->mdio_lock); +-} +- +-static void +-ar40xx_phy_dbg_read(struct ar40xx_priv *priv, int phy_addr, +- u16 dbg_addr, u16 *dbg_data) +-{ +- struct mii_bus *bus = priv->mii_bus; +- +- mutex_lock(&bus->mdio_lock); +- bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); +- *dbg_data = bus->read(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA); +- mutex_unlock(&bus->mdio_lock); +-} +- +-static void +-ar40xx_phy_mmd_write(struct ar40xx_priv *priv, u32 phy_id, +- u16 mmd_num, u16 reg_id, u16 reg_val) +-{ +- struct mii_bus *bus = priv->mii_bus; +- +- mutex_lock(&bus->mdio_lock); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_ADDR, mmd_num); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_DATA, reg_id); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_ADDR, +- 0x4000 | mmd_num); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_DATA, reg_val); +- mutex_unlock(&bus->mdio_lock); +-} +- +-static u16 +-ar40xx_phy_mmd_read(struct ar40xx_priv *priv, u32 phy_id, +- u16 mmd_num, u16 reg_id) +-{ +- u16 value; +- struct mii_bus *bus = priv->mii_bus; +- +- mutex_lock(&bus->mdio_lock); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_ADDR, mmd_num); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_DATA, reg_id); +- bus->write(bus, phy_id, +- AR40XX_MII_ATH_MMD_ADDR, +- 0x4000 | mmd_num); +- value = bus->read(bus, phy_id, AR40XX_MII_ATH_MMD_DATA); +- mutex_unlock(&bus->mdio_lock); +- return value; +-} +- +-/* Start of swconfig support */ +- +-static void +-ar40xx_phy_poll_reset(struct ar40xx_priv *priv) +-{ +- u32 i, in_reset, retries = 500; +- struct mii_bus *bus = priv->mii_bus; +- +- /* Assume RESET was recently issued to some or all of the phys */ +- in_reset = GENMASK(AR40XX_NUM_PHYS - 1, 0); +- +- while (retries--) { +- /* 1ms should be plenty of time. +- * 802.3 spec allows for a max wait time of 500ms +- */ +- usleep_range(1000, 2000); +- +- for (i = 0; i < AR40XX_NUM_PHYS; i++) { +- int val; +- +- /* skip devices which have completed reset */ +- if (!(in_reset & BIT(i))) +- continue; +- +- val = mdiobus_read(bus, i, MII_BMCR); +- if (val < 0) +- continue; +- +- /* mark when phy is no longer in reset state */ +- if (!(val & BMCR_RESET)) +- in_reset &= ~BIT(i); +- } +- +- if (!in_reset) +- return; +- } +- +- dev_warn(&bus->dev, "Failed to reset all phys! (in_reset: 0x%x)\n", +- in_reset); +-} +- +-static void +-ar40xx_phy_init(struct ar40xx_priv *priv) +-{ +- int i; +- struct mii_bus *bus; +- u16 val; +- +- bus = priv->mii_bus; +- for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { +- ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); +- val &= ~AR40XX_PHY_MANU_CTRL_EN; +- ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); +- mdiobus_write(bus, i, +- MII_ADVERTISE, ADVERTISE_ALL | +- ADVERTISE_PAUSE_CAP | +- ADVERTISE_PAUSE_ASYM); +- mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); +- mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); +- } +- +- ar40xx_phy_poll_reset(priv); +-} +- +-static void +-ar40xx_port_phy_linkdown(struct ar40xx_priv *priv) +-{ +- struct mii_bus *bus; +- int i; +- u16 val; +- +- bus = priv->mii_bus; +- for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { +- mdiobus_write(bus, i, MII_CTRL1000, 0); +- mdiobus_write(bus, i, MII_ADVERTISE, 0); +- mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); +- ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); +- val |= AR40XX_PHY_MANU_CTRL_EN; +- ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); +- /* disable transmit */ +- ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_2, &val); +- val &= 0xf00f; +- ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_2, val); +- } +-} +- +-static void +-ar40xx_set_mirror_regs(struct ar40xx_priv *priv) +-{ +- int port; +- +- /* reset all mirror registers */ +- ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, +- AR40XX_FWD_CTRL0_MIRROR_PORT, +- (0xF << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); +- for (port = 0; port < AR40XX_NUM_PORTS; port++) { +- ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(port), +- AR40XX_PORT_LOOKUP_ING_MIRROR_EN, 0); +- +- ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(port), +- AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); +- } +- +- /* now enable mirroring if necessary */ +- if (priv->source_port >= AR40XX_NUM_PORTS || +- priv->monitor_port >= AR40XX_NUM_PORTS || +- priv->source_port == priv->monitor_port) { +- return; +- } +- +- ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, +- AR40XX_FWD_CTRL0_MIRROR_PORT, +- (priv->monitor_port << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); +- +- if (priv->mirror_rx) +- ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(priv->source_port), 0, +- AR40XX_PORT_LOOKUP_ING_MIRROR_EN); +- +- if (priv->mirror_tx) +- ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(priv->source_port), +- 0, AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN); +-} +- +-static int +-ar40xx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- u8 ports = priv->vlan_table[val->port_vlan]; +- int i; +- +- val->len = 0; +- for (i = 0; i < dev->ports; i++) { +- struct switch_port *p; +- +- if (!(ports & BIT(i))) +- continue; +- +- p = &val->value.ports[val->len++]; +- p->id = i; +- if ((priv->vlan_tagged & BIT(i)) || +- (priv->pvid[i] != val->port_vlan)) +- p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); +- else +- p->flags = 0; +- } +- return 0; +-} +- +-static int +-ar40xx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- u8 *vt = &priv->vlan_table[val->port_vlan]; +- int i; +- +- *vt = 0; +- for (i = 0; i < val->len; i++) { +- struct switch_port *p = &val->value.ports[i]; +- +- if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { +- if (val->port_vlan == priv->pvid[p->id]) +- priv->vlan_tagged |= BIT(p->id); +- } else { +- priv->vlan_tagged &= ~BIT(p->id); +- priv->pvid[p->id] = val->port_vlan; +- } +- +- *vt |= BIT(p->id); +- } +- return 0; +-} +- +-static int +-ar40xx_reg_wait(struct ar40xx_priv *priv, u32 reg, u32 mask, u32 val, +- unsigned timeout) +-{ +- int i; +- +- for (i = 0; i < timeout; i++) { +- u32 t; +- +- t = ar40xx_read(priv, reg); +- if ((t & mask) == val) +- return 0; +- +- usleep_range(1000, 2000); +- } +- +- return -ETIMEDOUT; +-} +- +-static int +-ar40xx_mib_op(struct ar40xx_priv *priv, u32 op) +-{ +- int ret; +- +- lockdep_assert_held(&priv->mib_lock); +- +- /* Capture the hardware statistics for all ports */ +- ar40xx_rmw(priv, AR40XX_REG_MIB_FUNC, +- AR40XX_MIB_FUNC, (op << AR40XX_MIB_FUNC_S)); +- +- /* Wait for the capturing to complete. */ +- ret = ar40xx_reg_wait(priv, AR40XX_REG_MIB_FUNC, +- AR40XX_MIB_BUSY, 0, 10); +- +- return ret; +-} +- +-static void +-ar40xx_mib_fetch_port_stat(struct ar40xx_priv *priv, int port, bool flush) +-{ +- unsigned int base; +- u64 *mib_stats; +- int i; +- u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); +- +- WARN_ON(port >= priv->dev.ports); +- +- lockdep_assert_held(&priv->mib_lock); +- +- base = AR40XX_REG_PORT_STATS_START + +- AR40XX_REG_PORT_STATS_LEN * port; +- +- mib_stats = &priv->mib_stats[port * num_mibs]; +- if (flush) { +- u32 len; +- +- len = num_mibs * sizeof(*mib_stats); +- memset(mib_stats, 0, len); +- return; +- } +- for (i = 0; i < num_mibs; i++) { +- const struct ar40xx_mib_desc *mib; +- u64 t; +- +- mib = &ar40xx_mibs[i]; +- t = ar40xx_read(priv, base + mib->offset); +- if (mib->size == 2) { +- u64 hi; +- +- hi = ar40xx_read(priv, base + mib->offset + 4); +- t |= hi << 32; +- } +- +- mib_stats[i] += t; +- } +-} +- +-static int +-ar40xx_mib_capture(struct ar40xx_priv *priv) +-{ +- return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_CAPTURE); +-} +- +-static int +-ar40xx_mib_flush(struct ar40xx_priv *priv) +-{ +- return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_FLUSH); +-} +- +-static int +-ar40xx_sw_set_reset_mibs(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- unsigned int len; +- int ret; +- u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); +- +- mutex_lock(&priv->mib_lock); +- +- len = priv->dev.ports * num_mibs * sizeof(*priv->mib_stats); +- memset(priv->mib_stats, 0, len); +- ret = ar40xx_mib_flush(priv); +- +- mutex_unlock(&priv->mib_lock); +- return ret; +-} +- +-static int +-ar40xx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- priv->vlan = !!val->value.i; +- return 0; +-} +- +-static int +-ar40xx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- val->value.i = priv->vlan; +- return 0; +-} +- +-static int +-ar40xx_sw_set_mirror_rx_enable(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- priv->mirror_rx = !!val->value.i; +- ar40xx_set_mirror_regs(priv); +- mutex_unlock(&priv->reg_mutex); +- +- return 0; +-} +- +-static int +-ar40xx_sw_get_mirror_rx_enable(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- val->value.i = priv->mirror_rx; +- mutex_unlock(&priv->reg_mutex); +- return 0; +-} +- +-static int +-ar40xx_sw_set_mirror_tx_enable(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- priv->mirror_tx = !!val->value.i; +- ar40xx_set_mirror_regs(priv); +- mutex_unlock(&priv->reg_mutex); +- +- return 0; +-} +- +-static int +-ar40xx_sw_get_mirror_tx_enable(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- val->value.i = priv->mirror_tx; +- mutex_unlock(&priv->reg_mutex); +- return 0; +-} +- +-static int +-ar40xx_sw_set_mirror_monitor_port(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- priv->monitor_port = val->value.i; +- ar40xx_set_mirror_regs(priv); +- mutex_unlock(&priv->reg_mutex); +- +- return 0; +-} +- +-static int +-ar40xx_sw_get_mirror_monitor_port(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- val->value.i = priv->monitor_port; +- mutex_unlock(&priv->reg_mutex); +- return 0; +-} +- +-static int +-ar40xx_sw_set_mirror_source_port(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- priv->source_port = val->value.i; +- ar40xx_set_mirror_regs(priv); +- mutex_unlock(&priv->reg_mutex); +- +- return 0; +-} +- +-static int +-ar40xx_sw_get_mirror_source_port(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- mutex_lock(&priv->reg_mutex); +- val->value.i = priv->source_port; +- mutex_unlock(&priv->reg_mutex); +- return 0; +-} +- +-static int +-ar40xx_sw_set_linkdown(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- if (val->value.i == 1) +- ar40xx_port_phy_linkdown(priv); +- else +- ar40xx_phy_init(priv); +- +- return 0; +-} +- +-static int +-ar40xx_sw_set_port_reset_mib(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- int port; +- int ret; +- +- port = val->port_vlan; +- if (port >= dev->ports) +- return -EINVAL; +- +- mutex_lock(&priv->mib_lock); +- ret = ar40xx_mib_capture(priv); +- if (ret) +- goto unlock; +- +- ar40xx_mib_fetch_port_stat(priv, port, true); +- +-unlock: +- mutex_unlock(&priv->mib_lock); +- return ret; +-} +- +-static int +-ar40xx_sw_get_port_mib(struct switch_dev *dev, +- const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- u64 *mib_stats; +- int port; +- int ret; +- char *buf = priv->buf; +- int i, len = 0; +- u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); +- +- port = val->port_vlan; +- if (port >= dev->ports) +- return -EINVAL; +- +- mutex_lock(&priv->mib_lock); +- ret = ar40xx_mib_capture(priv); +- if (ret) +- goto unlock; +- +- ar40xx_mib_fetch_port_stat(priv, port, false); +- +- len += snprintf(buf + len, sizeof(priv->buf) - len, +- "Port %d MIB counters\n", +- port); +- +- mib_stats = &priv->mib_stats[port * num_mibs]; +- for (i = 0; i < num_mibs; i++) +- len += snprintf(buf + len, sizeof(priv->buf) - len, +- "%-12s: %llu\n", +- ar40xx_mibs[i].name, +- mib_stats[i]); +- +- val->value.s = buf; +- val->len = len; +- +-unlock: +- mutex_unlock(&priv->mib_lock); +- return ret; +-} +- +-static int +-ar40xx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- priv->vlan_id[val->port_vlan] = val->value.i; +- return 0; +-} +- +-static int +-ar40xx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, +- struct switch_val *val) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- val->value.i = priv->vlan_id[val->port_vlan]; +- return 0; +-} +- +-static int +-ar40xx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- *vlan = priv->pvid[port]; +- return 0; +-} +- +-static int +-ar40xx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- /* make sure no invalid PVIDs get set */ +- if (vlan >= dev->vlans) +- return -EINVAL; +- +- priv->pvid[port] = vlan; +- return 0; +-} +- +-static void +-ar40xx_read_port_link(struct ar40xx_priv *priv, int port, +- struct switch_port_link *link) +-{ +- u32 status; +- u32 speed; +- +- memset(link, 0, sizeof(*link)); +- +- status = ar40xx_read(priv, AR40XX_REG_PORT_STATUS(port)); +- +- link->aneg = !!(status & AR40XX_PORT_AUTO_LINK_EN); +- if (link->aneg || (port != AR40XX_PORT_CPU)) +- link->link = !!(status & AR40XX_PORT_STATUS_LINK_UP); +- else +- link->link = true; +- +- if (!link->link) +- return; +- +- link->duplex = !!(status & AR40XX_PORT_DUPLEX); +- link->tx_flow = !!(status & AR40XX_PORT_STATUS_TXFLOW); +- link->rx_flow = !!(status & AR40XX_PORT_STATUS_RXFLOW); +- +- speed = (status & AR40XX_PORT_SPEED) >> +- AR40XX_PORT_STATUS_SPEED_S; +- +- switch (speed) { +- case AR40XX_PORT_SPEED_10M: +- link->speed = SWITCH_PORT_SPEED_10; +- break; +- case AR40XX_PORT_SPEED_100M: +- link->speed = SWITCH_PORT_SPEED_100; +- break; +- case AR40XX_PORT_SPEED_1000M: +- link->speed = SWITCH_PORT_SPEED_1000; +- break; +- default: +- link->speed = SWITCH_PORT_SPEED_UNKNOWN; +- break; +- } +-} +- +-static int +-ar40xx_sw_get_port_link(struct switch_dev *dev, int port, +- struct switch_port_link *link) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- +- ar40xx_read_port_link(priv, port, link); +- return 0; +-} +- +-static const struct switch_attr ar40xx_sw_attr_globals[] = { +- { +- .type = SWITCH_TYPE_INT, +- .name = "enable_vlan", +- .description = "Enable VLAN mode", +- .set = ar40xx_sw_set_vlan, +- .get = ar40xx_sw_get_vlan, +- .max = 1 +- }, +- { +- .type = SWITCH_TYPE_NOVAL, +- .name = "reset_mibs", +- .description = "Reset all MIB counters", +- .set = ar40xx_sw_set_reset_mibs, +- }, +- { +- .type = SWITCH_TYPE_INT, +- .name = "enable_mirror_rx", +- .description = "Enable mirroring of RX packets", +- .set = ar40xx_sw_set_mirror_rx_enable, +- .get = ar40xx_sw_get_mirror_rx_enable, +- .max = 1 +- }, +- { +- .type = SWITCH_TYPE_INT, +- .name = "enable_mirror_tx", +- .description = "Enable mirroring of TX packets", +- .set = ar40xx_sw_set_mirror_tx_enable, +- .get = ar40xx_sw_get_mirror_tx_enable, +- .max = 1 +- }, +- { +- .type = SWITCH_TYPE_INT, +- .name = "mirror_monitor_port", +- .description = "Mirror monitor port", +- .set = ar40xx_sw_set_mirror_monitor_port, +- .get = ar40xx_sw_get_mirror_monitor_port, +- .max = AR40XX_NUM_PORTS - 1 +- }, +- { +- .type = SWITCH_TYPE_INT, +- .name = "mirror_source_port", +- .description = "Mirror source port", +- .set = ar40xx_sw_set_mirror_source_port, +- .get = ar40xx_sw_get_mirror_source_port, +- .max = AR40XX_NUM_PORTS - 1 +- }, +- { +- .type = SWITCH_TYPE_INT, +- .name = "linkdown", +- .description = "Link down all the PHYs", +- .set = ar40xx_sw_set_linkdown, +- .max = 1 +- }, +-}; +- +-static const struct switch_attr ar40xx_sw_attr_port[] = { +- { +- .type = SWITCH_TYPE_NOVAL, +- .name = "reset_mib", +- .description = "Reset single port MIB counters", +- .set = ar40xx_sw_set_port_reset_mib, +- }, +- { +- .type = SWITCH_TYPE_STRING, +- .name = "mib", +- .description = "Get port's MIB counters", +- .set = NULL, +- .get = ar40xx_sw_get_port_mib, +- }, +-}; +- +-const struct switch_attr ar40xx_sw_attr_vlan[] = { +- { +- .type = SWITCH_TYPE_INT, +- .name = "vid", +- .description = "VLAN ID (0-4094)", +- .set = ar40xx_sw_set_vid, +- .get = ar40xx_sw_get_vid, +- .max = 4094, +- }, +-}; +- +-/* End of swconfig support */ +- +-static int +-ar40xx_wait_bit(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) +-{ +- int timeout = 20; +- u32 t; +- +- while (1) { +- t = ar40xx_read(priv, reg); +- if ((t & mask) == val) +- return 0; +- +- if (timeout-- <= 0) +- break; +- +- usleep_range(10, 20); +- } +- +- pr_err("ar40xx: timeout for reg %08x: %08x & %08x != %08x\n", +- (unsigned int)reg, t, mask, val); +- return -ETIMEDOUT; +-} +- +-static int +-ar40xx_atu_flush(struct ar40xx_priv *priv) +-{ +- int ret; +- +- ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC, +- AR40XX_ATU_FUNC_BUSY, 0); +- if (!ret) +- ar40xx_write(priv, AR40XX_REG_ATU_FUNC, +- AR40XX_ATU_FUNC_OP_FLUSH | +- AR40XX_ATU_FUNC_BUSY); +- +- return ret; +-} +- +-static void +-ar40xx_ess_reset(struct ar40xx_priv *priv) +-{ +- reset_control_assert(priv->ess_rst); +- mdelay(10); +- reset_control_deassert(priv->ess_rst); +- /* Waiting for all inner tables init done. +- * It cost 5~10ms. +- */ +- mdelay(10); +- +- pr_info("ESS reset ok!\n"); +-} +- +-/* Start of psgmii self test */ +- +-static void +-ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) +-{ +- u32 n; +- struct mii_bus *bus = priv->mii_bus; +- /* reset phy psgmii */ +- /* fix phy psgmii RX 20bit */ +- mdiobus_write(bus, 5, 0x0, 0x005b); +- /* reset phy psgmii */ +- mdiobus_write(bus, 5, 0x0, 0x001b); +- /* release reset phy psgmii */ +- mdiobus_write(bus, 5, 0x0, 0x005b); +- +- for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { +- u16 status; +- +- status = ar40xx_phy_mmd_read(priv, 5, 1, 0x28); +- if (status & BIT(0)) +- break; +- /* Polling interval to check PSGMII PLL in malibu is ready +- * the worst time is 8.67ms +- * for 25MHz reference clock +- * [512+(128+2048)*49]*80ns+100us +- */ +- mdelay(2); +- } +- mdelay(50); +- +- /*check malibu psgmii calibration done end..*/ +- +- /*freeze phy psgmii RX CDR*/ +- mdiobus_write(bus, 5, 0x1a, 0x2230); +- +- ar40xx_ess_reset(priv); +- +- /*check psgmii calibration done start*/ +- for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { +- u32 status; +- +- status = ar40xx_psgmii_read(priv, 0xa0); +- if (status & BIT(0)) +- break; +- /* Polling interval to check PSGMII PLL in ESS is ready */ +- mdelay(2); +- } +- mdelay(50); +- +- /* check dakota psgmii calibration done end..*/ +- +- /* relesae phy psgmii RX CDR */ +- mdiobus_write(bus, 5, 0x1a, 0x3230); +- /* release phy psgmii RX 20bit */ +- mdiobus_write(bus, 5, 0x0, 0x005f); +- mdelay(200); +-} +- +-static void +-ar40xx_psgmii_single_phy_testing(struct ar40xx_priv *priv, int phy) +-{ +- int j; +- u32 tx_ok, tx_error; +- u32 rx_ok, rx_error; +- u32 tx_ok_high16; +- u32 rx_ok_high16; +- u32 tx_all_ok, rx_all_ok; +- struct mii_bus *bus = priv->mii_bus; +- +- mdiobus_write(bus, phy, 0x0, 0x9000); +- mdiobus_write(bus, phy, 0x0, 0x4140); +- +- for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { +- u16 status; +- +- status = mdiobus_read(bus, phy, 0x11); +- if (status & AR40XX_PHY_SPEC_STATUS_LINK) +- break; +- /* the polling interval to check if the PHY link up or not +- * maxwait_timer: 750 ms +/-10 ms +- * minwait_timer : 1 us +/- 0.1us +- * time resides in minwait_timer ~ maxwait_timer +- * see IEEE 802.3 section 40.4.5.2 +- */ +- mdelay(8); +- } +- +- /* enable check */ +- ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0000); +- ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0003); +- +- /* start traffic */ +- ar40xx_phy_mmd_write(priv, phy, 7, 0x8020, 0xa000); +- /* wait for all traffic end +- * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms +- */ +- mdelay(50); +- +- /* check counter */ +- tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); +- tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); +- tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); +- rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); +- rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); +- rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); +- tx_all_ok = tx_ok + (tx_ok_high16 << 16); +- rx_all_ok = rx_ok + (rx_ok_high16 << 16); +- if (tx_all_ok == 0x1000 && tx_error == 0) { +- /* success */ +- priv->phy_t_status &= (~BIT(phy)); +- } else { +- pr_info("PHY %d single test PSGMII issue happen!\n", phy); +- priv->phy_t_status |= BIT(phy); +- } +- +- mdiobus_write(bus, phy, 0x0, 0x1840); +-} +- +-static void +-ar40xx_psgmii_all_phy_testing(struct ar40xx_priv *priv) +-{ +- int phy, j; +- struct mii_bus *bus = priv->mii_bus; +- +- mdiobus_write(bus, 0x1f, 0x0, 0x9000); +- mdiobus_write(bus, 0x1f, 0x0, 0x4140); +- +- for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { +- for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { +- u16 status; +- +- status = mdiobus_read(bus, phy, 0x11); +- if (!(status & BIT(10))) +- break; +- } +- +- if (phy >= (AR40XX_NUM_PORTS - 1)) +- break; +- /* The polling interva to check if the PHY link up or not */ +- mdelay(8); +- } +- /* enable check */ +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0000); +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0003); +- +- /* start traffic */ +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0xa000); +- /* wait for all traffic end +- * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms +- */ +- mdelay(50); +- +- for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { +- u32 tx_ok, tx_error; +- u32 rx_ok, rx_error; +- u32 tx_ok_high16; +- u32 rx_ok_high16; +- u32 tx_all_ok, rx_all_ok; +- +- /* check counter */ +- tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); +- tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); +- tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); +- rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); +- rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); +- rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); +- tx_all_ok = tx_ok + (tx_ok_high16<<16); +- rx_all_ok = rx_ok + (rx_ok_high16<<16); +- if (tx_all_ok == 0x1000 && tx_error == 0) { +- /* success */ +- priv->phy_t_status &= ~BIT(phy + 8); +- } else { +- pr_info("PHY%d test see issue!\n", phy); +- priv->phy_t_status |= BIT(phy + 8); +- } +- } +- +- pr_debug("PHY all test 0x%x \r\n", priv->phy_t_status); +-} +- +-void +-ar40xx_psgmii_self_test(struct ar40xx_priv *priv) +-{ +- u32 i, phy; +- struct mii_bus *bus = priv->mii_bus; +- +- ar40xx_malibu_psgmii_ess_reset(priv); +- +- /* switch to access MII reg for copper */ +- mdiobus_write(bus, 4, 0x1f, 0x8500); +- for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { +- /*enable phy mdio broadcast write*/ +- ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x801f); +- } +- /* force no link by power down */ +- mdiobus_write(bus, 0x1f, 0x0, 0x1840); +- /*packet number*/ +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x1000); +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8062, 0x05e0); +- +- /*fix mdi status */ +- mdiobus_write(bus, 0x1f, 0x10, 0x6800); +- for (i = 0; i < AR40XX_PSGMII_CALB_NUM; i++) { +- priv->phy_t_status = 0; +- +- for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { +- ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), +- AR40XX_PORT_LOOKUP_LOOPBACK, +- AR40XX_PORT_LOOKUP_LOOPBACK); +- } +- +- for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) +- ar40xx_psgmii_single_phy_testing(priv, phy); +- +- ar40xx_psgmii_all_phy_testing(priv); +- +- if (priv->phy_t_status) +- ar40xx_malibu_psgmii_ess_reset(priv); +- else +- break; +- } +- +- if (i >= AR40XX_PSGMII_CALB_NUM) +- pr_info("PSGMII cannot recover\n"); +- else +- pr_debug("PSGMII recovered after %d times reset\n", i); +- +- /* configuration recover */ +- /* packet number */ +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x0); +- /* disable check */ +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0); +- /* disable traffic */ +- ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0x0); +-} +- +-void +-ar40xx_psgmii_self_test_clean(struct ar40xx_priv *priv) +-{ +- int phy; +- struct mii_bus *bus = priv->mii_bus; +- +- /* disable phy internal loopback */ +- mdiobus_write(bus, 0x1f, 0x10, 0x6860); +- mdiobus_write(bus, 0x1f, 0x0, 0x9040); +- +- for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { +- /* disable mac loop back */ +- ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), +- AR40XX_PORT_LOOKUP_LOOPBACK, 0); +- /* disable phy mdio broadcast write */ +- ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x001f); +- } +- +- /* clear fdb entry */ +- ar40xx_atu_flush(priv); +-} +- +-/* End of psgmii self test */ +- +-static void +-ar40xx_mac_mode_init(struct ar40xx_priv *priv, u32 mode) +-{ +- if (mode == PORT_WRAPPER_PSGMII) { +- ar40xx_psgmii_write(priv, AR40XX_PSGMII_MODE_CONTROL, 0x2200); +- ar40xx_psgmii_write(priv, AR40XX_PSGMIIPHY_TX_CONTROL, 0x8380); +- } +-} +- +-static +-int ar40xx_cpuport_setup(struct ar40xx_priv *priv) +-{ +- u32 t; +- +- t = AR40XX_PORT_STATUS_TXFLOW | +- AR40XX_PORT_STATUS_RXFLOW | +- AR40XX_PORT_TXHALF_FLOW | +- AR40XX_PORT_DUPLEX | +- AR40XX_PORT_SPEED_1000M; +- ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); +- usleep_range(10, 20); +- +- t |= AR40XX_PORT_TX_EN | +- AR40XX_PORT_RX_EN; +- ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); +- +- return 0; +-} +- +-static void +-ar40xx_init_port(struct ar40xx_priv *priv, int port) +-{ +- u32 t; +- +- ar40xx_write(priv, AR40XX_REG_PORT_STATUS(port), 0); +- +- ar40xx_write(priv, AR40XX_REG_PORT_HEADER(port), 0); +- +- ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), 0); +- +- t = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH << AR40XX_PORT_VLAN1_OUT_MODE_S; +- ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); +- +- t = AR40XX_PORT_LOOKUP_LEARN; +- t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; +- ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); +-} +- +-void +-ar40xx_init_globals(struct ar40xx_priv *priv) +-{ +- u32 t; +- +- /* enable CPU port and disable mirror port */ +- t = AR40XX_FWD_CTRL0_CPU_PORT_EN | +- AR40XX_FWD_CTRL0_MIRROR_PORT; +- ar40xx_write(priv, AR40XX_REG_FWD_CTRL0, t); +- +- /* forward multicast and broadcast frames to CPU */ +- t = (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_UC_FLOOD_S) | +- (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_MC_FLOOD_S) | +- (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_BC_FLOOD_S); +- ar40xx_write(priv, AR40XX_REG_FWD_CTRL1, t); +- +- /* enable jumbo frames */ +- ar40xx_rmw(priv, AR40XX_REG_MAX_FRAME_SIZE, +- AR40XX_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); +- +- /* Enable MIB counters */ +- ar40xx_rmw(priv, AR40XX_REG_MODULE_EN, 0, +- AR40XX_MODULE_EN_MIB); +- +- /* Disable AZ */ +- ar40xx_write(priv, AR40XX_REG_EEE_CTRL, 0); +- +- /* set flowctrl thershold for cpu port */ +- t = (AR40XX_PORT0_FC_THRESH_ON_DFLT << 16) | +- AR40XX_PORT0_FC_THRESH_OFF_DFLT; +- ar40xx_write(priv, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), t); +-} +- +-static int +-ar40xx_hw_init(struct ar40xx_priv *priv) +-{ +- u32 i; +- +- ar40xx_ess_reset(priv); +- +- if (!priv->mii_bus) +- return -1; +- +- ar40xx_psgmii_self_test(priv); +- ar40xx_psgmii_self_test_clean(priv); +- +- ar40xx_mac_mode_init(priv, priv->mac_mode); +- +- for (i = 0; i < priv->dev.ports; i++) +- ar40xx_init_port(priv, i); +- +- ar40xx_init_globals(priv); +- +- return 0; +-} +- +-/* Start of qm error WAR */ +- +-static +-int ar40xx_force_1g_full(struct ar40xx_priv *priv, u32 port_id) +-{ +- u32 reg; +- +- if (port_id < 0 || port_id > 6) +- return -1; +- +- reg = AR40XX_REG_PORT_STATUS(port_id); +- return ar40xx_rmw(priv, reg, AR40XX_PORT_SPEED, +- (AR40XX_PORT_SPEED_1000M | AR40XX_PORT_DUPLEX)); +-} +- +-static +-int ar40xx_get_qm_status(struct ar40xx_priv *priv, +- u32 port_id, u32 *qm_buffer_err) +-{ +- u32 reg; +- u32 qm_val; +- +- if (port_id < 1 || port_id > 5) { +- *qm_buffer_err = 0; +- return -1; +- } +- +- if (port_id < 4) { +- reg = AR40XX_REG_QM_PORT0_3_QNUM; +- ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); +- qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); +- /* every 8 bits for each port */ +- *qm_buffer_err = (qm_val >> (port_id * 8)) & 0xFF; +- } else { +- reg = AR40XX_REG_QM_PORT4_6_QNUM; +- ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); +- qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); +- /* every 8 bits for each port */ +- *qm_buffer_err = (qm_val >> ((port_id-4) * 8)) & 0xFF; +- } +- +- return 0; +-} +- +-static void +-ar40xx_sw_mac_polling_task(struct ar40xx_priv *priv) +-{ +- static int task_count; +- u32 i; +- u32 reg, value; +- u32 link, speed, duplex; +- u32 qm_buffer_err; +- u16 port_phy_status[AR40XX_NUM_PORTS]; +- static u32 qm_err_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; +- static u32 link_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; +- struct mii_bus *bus = NULL; +- +- if (!priv || !priv->mii_bus) +- return; +- +- bus = priv->mii_bus; +- +- ++task_count; +- +- for (i = 1; i < AR40XX_NUM_PORTS; ++i) { +- port_phy_status[i] = +- mdiobus_read(bus, i-1, AR40XX_PHY_SPEC_STATUS); +- +- speed = FIELD_GET(AR40XX_PHY_SPEC_STATUS_SPEED, +- port_phy_status[i]); +- link = FIELD_GET(AR40XX_PHY_SPEC_STATUS_LINK, +- port_phy_status[i]); +- duplex = FIELD_GET(AR40XX_PHY_SPEC_STATUS_DUPLEX, +- port_phy_status[i]); +- +- if (link != priv->ar40xx_port_old_link[i]) { +- ++link_cnt[i]; +- /* Up --> Down */ +- if ((priv->ar40xx_port_old_link[i] == +- AR40XX_PORT_LINK_UP) && +- (link == AR40XX_PORT_LINK_DOWN)) { +- /* LINK_EN disable(MAC force mode)*/ +- reg = AR40XX_REG_PORT_STATUS(i); +- ar40xx_rmw(priv, reg, +- AR40XX_PORT_AUTO_LINK_EN, 0); +- +- /* Check queue buffer */ +- qm_err_cnt[i] = 0; +- ar40xx_get_qm_status(priv, i, &qm_buffer_err); +- if (qm_buffer_err) { +- priv->ar40xx_port_qm_buf[i] = +- AR40XX_QM_NOT_EMPTY; +- } else { +- u16 phy_val = 0; +- +- priv->ar40xx_port_qm_buf[i] = +- AR40XX_QM_EMPTY; +- ar40xx_force_1g_full(priv, i); +- /* Ref:QCA8337 Datasheet,Clearing +- * MENU_CTRL_EN prevents phy to +- * stuck in 100BT mode when +- * bringing up the link +- */ +- ar40xx_phy_dbg_read(priv, i-1, +- AR40XX_PHY_DEBUG_0, +- &phy_val); +- phy_val &= (~AR40XX_PHY_MANU_CTRL_EN); +- ar40xx_phy_dbg_write(priv, i-1, +- AR40XX_PHY_DEBUG_0, +- phy_val); +- } +- priv->ar40xx_port_old_link[i] = link; +- } else if ((priv->ar40xx_port_old_link[i] == +- AR40XX_PORT_LINK_DOWN) && +- (link == AR40XX_PORT_LINK_UP)) { +- /* Down --> Up */ +- if (priv->port_link_up[i] < 1) { +- ++priv->port_link_up[i]; +- } else { +- /* Change port status */ +- reg = AR40XX_REG_PORT_STATUS(i); +- value = ar40xx_read(priv, reg); +- priv->port_link_up[i] = 0; +- +- value &= ~(AR40XX_PORT_DUPLEX | +- AR40XX_PORT_SPEED); +- value |= speed | (duplex ? BIT(6) : 0); +- ar40xx_write(priv, reg, value); +- /* clock switch need such time +- * to avoid glitch +- */ +- usleep_range(100, 200); +- +- value |= AR40XX_PORT_AUTO_LINK_EN; +- ar40xx_write(priv, reg, value); +- /* HW need such time to make sure link +- * stable before enable MAC +- */ +- usleep_range(100, 200); +- +- if (speed == AR40XX_PORT_SPEED_100M) { +- u16 phy_val = 0; +- /* Enable @100M, if down to 10M +- * clock will change smoothly +- */ +- ar40xx_phy_dbg_read(priv, i-1, +- 0, +- &phy_val); +- phy_val |= +- AR40XX_PHY_MANU_CTRL_EN; +- ar40xx_phy_dbg_write(priv, i-1, +- 0, +- phy_val); +- } +- priv->ar40xx_port_old_link[i] = link; +- } +- } +- } +- +- if (priv->ar40xx_port_qm_buf[i] == AR40XX_QM_NOT_EMPTY) { +- /* Check QM */ +- ar40xx_get_qm_status(priv, i, &qm_buffer_err); +- if (qm_buffer_err) { +- ++qm_err_cnt[i]; +- } else { +- priv->ar40xx_port_qm_buf[i] = +- AR40XX_QM_EMPTY; +- qm_err_cnt[i] = 0; +- ar40xx_force_1g_full(priv, i); +- } +- } +- } +-} +- +-static void +-ar40xx_qm_err_check_work_task(struct work_struct *work) +-{ +- struct ar40xx_priv *priv = container_of(work, struct ar40xx_priv, +- qm_dwork.work); +- +- mutex_lock(&priv->qm_lock); +- +- ar40xx_sw_mac_polling_task(priv); +- +- mutex_unlock(&priv->qm_lock); +- +- schedule_delayed_work(&priv->qm_dwork, +- msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); +-} +- +-static int +-ar40xx_qm_err_check_work_start(struct ar40xx_priv *priv) +-{ +- mutex_init(&priv->qm_lock); +- +- INIT_DELAYED_WORK(&priv->qm_dwork, ar40xx_qm_err_check_work_task); +- +- schedule_delayed_work(&priv->qm_dwork, +- msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); +- +- return 0; +-} +- +-/* End of qm error WAR */ +- +-static int +-ar40xx_vlan_init(struct ar40xx_priv *priv) +-{ +- int port; +- unsigned long bmp; +- +- /* By default Enable VLAN */ +- priv->vlan = 1; +- priv->vlan_table[AR40XX_LAN_VLAN] = priv->cpu_bmp | priv->lan_bmp; +- priv->vlan_table[AR40XX_WAN_VLAN] = priv->cpu_bmp | priv->wan_bmp; +- priv->vlan_tagged = priv->cpu_bmp; +- bmp = priv->lan_bmp; +- for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) +- priv->pvid[port] = AR40XX_LAN_VLAN; +- +- bmp = priv->wan_bmp; +- for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) +- priv->pvid[port] = AR40XX_WAN_VLAN; +- +- return 0; +-} +- +-static void +-ar40xx_mib_work_func(struct work_struct *work) +-{ +- struct ar40xx_priv *priv; +- int err; +- +- priv = container_of(work, struct ar40xx_priv, mib_work.work); +- +- mutex_lock(&priv->mib_lock); +- +- err = ar40xx_mib_capture(priv); +- if (err) +- goto next_port; +- +- ar40xx_mib_fetch_port_stat(priv, priv->mib_next_port, false); +- +-next_port: +- priv->mib_next_port++; +- if (priv->mib_next_port >= priv->dev.ports) +- priv->mib_next_port = 0; +- +- mutex_unlock(&priv->mib_lock); +- +- schedule_delayed_work(&priv->mib_work, +- msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); +-} +- +-static void +-ar40xx_setup_port(struct ar40xx_priv *priv, int port, u32 members) +-{ +- u32 t; +- u32 egress, ingress; +- u32 pvid = priv->vlan_id[priv->pvid[port]]; +- +- if (priv->vlan) { +- egress = AR40XX_PORT_VLAN1_OUT_MODE_UNMOD; +- +- ingress = AR40XX_IN_SECURE; +- } else { +- egress = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH; +- ingress = AR40XX_IN_PORT_ONLY; +- } +- +- t = pvid << AR40XX_PORT_VLAN0_DEF_SVID_S; +- t |= pvid << AR40XX_PORT_VLAN0_DEF_CVID_S; +- ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), t); +- +- t = AR40XX_PORT_VLAN1_PORT_VLAN_PROP; +- t |= egress << AR40XX_PORT_VLAN1_OUT_MODE_S; +- +- ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); +- +- t = members; +- t |= AR40XX_PORT_LOOKUP_LEARN; +- t |= ingress << AR40XX_PORT_LOOKUP_IN_MODE_S; +- t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; +- ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); +-} +- +-static void +-ar40xx_vtu_op(struct ar40xx_priv *priv, u32 op, u32 val) +-{ +- if (ar40xx_wait_bit(priv, AR40XX_REG_VTU_FUNC1, +- AR40XX_VTU_FUNC1_BUSY, 0)) +- return; +- +- if ((op & AR40XX_VTU_FUNC1_OP) == AR40XX_VTU_FUNC1_OP_LOAD) +- ar40xx_write(priv, AR40XX_REG_VTU_FUNC0, val); +- +- op |= AR40XX_VTU_FUNC1_BUSY; +- ar40xx_write(priv, AR40XX_REG_VTU_FUNC1, op); +-} +- +-static void +-ar40xx_vtu_load_vlan(struct ar40xx_priv *priv, u32 vid, u32 port_mask) +-{ +- u32 op; +- u32 val; +- int i; +- +- op = AR40XX_VTU_FUNC1_OP_LOAD | (vid << AR40XX_VTU_FUNC1_VID_S); +- val = AR40XX_VTU_FUNC0_VALID | AR40XX_VTU_FUNC0_IVL; +- for (i = 0; i < AR40XX_NUM_PORTS; i++) { +- u32 mode; +- +- if ((port_mask & BIT(i)) == 0) +- mode = AR40XX_VTU_FUNC0_EG_MODE_NOT; +- else if (priv->vlan == 0) +- mode = AR40XX_VTU_FUNC0_EG_MODE_KEEP; +- else if ((priv->vlan_tagged & BIT(i)) || +- (priv->vlan_id[priv->pvid[i]] != vid)) +- mode = AR40XX_VTU_FUNC0_EG_MODE_TAG; +- else +- mode = AR40XX_VTU_FUNC0_EG_MODE_UNTAG; +- +- val |= mode << AR40XX_VTU_FUNC0_EG_MODE_S(i); +- } +- ar40xx_vtu_op(priv, op, val); +-} +- +-static void +-ar40xx_vtu_flush(struct ar40xx_priv *priv) +-{ +- ar40xx_vtu_op(priv, AR40XX_VTU_FUNC1_OP_FLUSH, 0); +-} +- +-static int +-ar40xx_sw_hw_apply(struct switch_dev *dev) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- u8 portmask[AR40XX_NUM_PORTS]; +- int i, j; +- +- mutex_lock(&priv->reg_mutex); +- /* flush all vlan entries */ +- ar40xx_vtu_flush(priv); +- +- memset(portmask, 0, sizeof(portmask)); +- if (priv->vlan) { +- for (j = 0; j < AR40XX_MAX_VLANS; j++) { +- u8 vp = priv->vlan_table[j]; +- +- if (!vp) +- continue; +- +- for (i = 0; i < dev->ports; i++) { +- u8 mask = BIT(i); +- +- if (vp & mask) +- portmask[i] |= vp & ~mask; +- } +- +- ar40xx_vtu_load_vlan(priv, priv->vlan_id[j], +- priv->vlan_table[j]); +- } +- } else { +- /* 8021q vlan disabled */ +- for (i = 0; i < dev->ports; i++) { +- if (i == AR40XX_PORT_CPU) +- continue; +- +- portmask[i] = BIT(AR40XX_PORT_CPU); +- portmask[AR40XX_PORT_CPU] |= BIT(i); +- } +- } +- +- /* update the port destination mask registers and tag settings */ +- for (i = 0; i < dev->ports; i++) +- ar40xx_setup_port(priv, i, portmask[i]); +- +- ar40xx_set_mirror_regs(priv); +- +- mutex_unlock(&priv->reg_mutex); +- return 0; +-} +- +-static int +-ar40xx_sw_reset_switch(struct switch_dev *dev) +-{ +- struct ar40xx_priv *priv = swdev_to_ar40xx(dev); +- int i, rv; +- +- mutex_lock(&priv->reg_mutex); +- memset(&priv->vlan, 0, sizeof(struct ar40xx_priv) - +- offsetof(struct ar40xx_priv, vlan)); +- +- for (i = 0; i < AR40XX_MAX_VLANS; i++) +- priv->vlan_id[i] = i; +- +- ar40xx_vlan_init(priv); +- +- priv->mirror_rx = false; +- priv->mirror_tx = false; +- priv->source_port = 0; +- priv->monitor_port = 0; +- +- mutex_unlock(&priv->reg_mutex); +- +- rv = ar40xx_sw_hw_apply(dev); +- return rv; +-} +- +-static int +-ar40xx_start(struct ar40xx_priv *priv) +-{ +- int ret; +- +- ret = ar40xx_hw_init(priv); +- if (ret) +- return ret; +- +- ret = ar40xx_sw_reset_switch(&priv->dev); +- if (ret) +- return ret; +- +- /* at last, setup cpu port */ +- ret = ar40xx_cpuport_setup(priv); +- if (ret) +- return ret; +- +- schedule_delayed_work(&priv->mib_work, +- msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); +- +- ar40xx_qm_err_check_work_start(priv); +- +- return 0; +-} +- +-static const struct switch_dev_ops ar40xx_sw_ops = { +- .attr_global = { +- .attr = ar40xx_sw_attr_globals, +- .n_attr = ARRAY_SIZE(ar40xx_sw_attr_globals), +- }, +- .attr_port = { +- .attr = ar40xx_sw_attr_port, +- .n_attr = ARRAY_SIZE(ar40xx_sw_attr_port), +- }, +- .attr_vlan = { +- .attr = ar40xx_sw_attr_vlan, +- .n_attr = ARRAY_SIZE(ar40xx_sw_attr_vlan), +- }, +- .get_port_pvid = ar40xx_sw_get_pvid, +- .set_port_pvid = ar40xx_sw_set_pvid, +- .get_vlan_ports = ar40xx_sw_get_ports, +- .set_vlan_ports = ar40xx_sw_set_ports, +- .apply_config = ar40xx_sw_hw_apply, +- .reset_switch = ar40xx_sw_reset_switch, +- .get_port_link = ar40xx_sw_get_port_link, +-}; +- +-/* Platform driver probe function */ +- +-static int ar40xx_probe(struct platform_device *pdev) +-{ +- struct device_node *switch_node; +- struct device_node *psgmii_node; +- struct device_node *mdio_node; +- const __be32 *mac_mode; +- struct clk *ess_clk; +- struct switch_dev *swdev; +- struct ar40xx_priv *priv; +- u32 len; +- u32 num_mibs; +- struct resource psgmii_base = {0}; +- struct resource switch_base = {0}; +- int ret; +- +- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- platform_set_drvdata(pdev, priv); +- ar40xx_priv = priv; +- +- switch_node = of_node_get(pdev->dev.of_node); +- if (of_address_to_resource(switch_node, 0, &switch_base) != 0) +- return -EIO; +- +- priv->hw_addr = devm_ioremap_resource(&pdev->dev, &switch_base); +- if (IS_ERR(priv->hw_addr)) { +- dev_err(&pdev->dev, "Failed to ioremap switch_base!\n"); +- return PTR_ERR(priv->hw_addr); +- } +- +- /*psgmii dts get*/ +- psgmii_node = of_find_node_by_name(NULL, "ess-psgmii"); +- if (!psgmii_node) { +- dev_err(&pdev->dev, "Failed to find ess-psgmii node!\n"); +- return -EINVAL; +- } +- +- if (of_address_to_resource(psgmii_node, 0, &psgmii_base) != 0) +- return -EIO; +- +- priv->psgmii_hw_addr = devm_ioremap_resource(&pdev->dev, &psgmii_base); +- if (IS_ERR(priv->psgmii_hw_addr)) { +- dev_err(&pdev->dev, "psgmii ioremap fail!\n"); +- return PTR_ERR(priv->psgmii_hw_addr); +- } +- +- mac_mode = of_get_property(switch_node, "switch_mac_mode", &len); +- if (!mac_mode) { +- dev_err(&pdev->dev, "Failed to read switch_mac_mode\n"); +- return -EINVAL; +- } +- priv->mac_mode = be32_to_cpup(mac_mode); +- +- ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); +- if (ess_clk) +- clk_prepare_enable(ess_clk); +- +- priv->ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); +- if (IS_ERR(priv->ess_rst)) { +- dev_err(&pdev->dev, "Failed to get ess_rst control!\n"); +- return PTR_ERR(priv->ess_rst); +- } +- +- if (of_property_read_u32(switch_node, "switch_cpu_bmp", +- &priv->cpu_bmp) || +- of_property_read_u32(switch_node, "switch_lan_bmp", +- &priv->lan_bmp) || +- of_property_read_u32(switch_node, "switch_wan_bmp", +- &priv->wan_bmp)) { +- dev_err(&pdev->dev, "Failed to read port properties\n"); +- return -EIO; +- } +- +- mutex_init(&priv->reg_mutex); +- mutex_init(&priv->mib_lock); +- INIT_DELAYED_WORK(&priv->mib_work, ar40xx_mib_work_func); +- +- /* register switch */ +- swdev = &priv->dev; +- +- mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq4019-mdio"); +- if (!mdio_node) { +- dev_err(&pdev->dev, "Probe failed - Cannot find mdio node by phandle!\n"); +- ret = -ENODEV; +- goto err_missing_phy; +- } +- +- priv->mii_bus = of_mdio_find_bus(mdio_node); +- +- if (priv->mii_bus == NULL) { +- dev_err(&pdev->dev, "Probe failed - Missing PHYs!\n"); +- ret = -ENODEV; +- goto err_missing_phy; +- } +- +- swdev->alias = dev_name(&priv->mii_bus->dev); +- +- swdev->cpu_port = AR40XX_PORT_CPU; +- swdev->name = "QCA AR40xx"; +- swdev->vlans = AR40XX_MAX_VLANS; +- swdev->ports = AR40XX_NUM_PORTS; +- swdev->ops = &ar40xx_sw_ops; +- ret = register_switch(swdev, NULL); +- if (ret < 0) { +- dev_err(&pdev->dev, "Switch registration failed!\n"); +- return ret; +- } +- +- num_mibs = ARRAY_SIZE(ar40xx_mibs); +- len = priv->dev.ports * num_mibs * +- sizeof(*priv->mib_stats); +- priv->mib_stats = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); +- if (!priv->mib_stats) { +- ret = -ENOMEM; +- goto err_unregister_switch; +- } +- +- ar40xx_start(priv); +- +- return 0; +- +-err_unregister_switch: +- unregister_switch(&priv->dev); +-err_missing_phy: +- platform_set_drvdata(pdev, NULL); +- return ret; +-} +- +-static int ar40xx_remove(struct platform_device *pdev) +-{ +- struct ar40xx_priv *priv = platform_get_drvdata(pdev); +- +- cancel_delayed_work_sync(&priv->qm_dwork); +- cancel_delayed_work_sync(&priv->mib_work); +- +- unregister_switch(&priv->dev); +- +- return 0; +-} +- +-static const struct of_device_id ar40xx_of_mtable[] = { +- {.compatible = "qcom,ess-switch" }, +- {} +-}; +- +-struct platform_driver ar40xx_drv = { +- .probe = ar40xx_probe, +- .remove = ar40xx_remove, +- .driver = { +- .name = "ar40xx", +- .of_match_table = ar40xx_of_mtable, +- }, +-}; +- +-module_platform_driver(ar40xx_drv); +- +-MODULE_DESCRIPTION("IPQ40XX ESS driver"); +-MODULE_LICENSE("Dual BSD/GPL"); +--- a/target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.h ++++ /dev/null +@@ -1,342 +0,0 @@ +-/* +- * Copyright (c) 2016, The Linux Foundation. All rights reserved. +- * +- * Permission to use, copy, modify, and/or distribute this software for +- * any purpose with or without fee is hereby granted, provided that the +- * above copyright notice and this permission notice appear in all copies. +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +- #ifndef __AR40XX_H +-#define __AR40XX_H +- +-#define AR40XX_MAX_VLANS 128 +-#define AR40XX_NUM_PORTS 6 +-#define AR40XX_NUM_PHYS 5 +- +-#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) +- +-struct ar40xx_priv { +- struct switch_dev dev; +- +- u8 __iomem *hw_addr; +- u8 __iomem *psgmii_hw_addr; +- u32 mac_mode; +- struct reset_control *ess_rst; +- u32 cpu_bmp; +- u32 lan_bmp; +- u32 wan_bmp; +- +- struct mii_bus *mii_bus; +- struct phy_device *phy; +- +- /* mutex for qm task */ +- struct mutex qm_lock; +- struct delayed_work qm_dwork; +- u32 port_link_up[AR40XX_NUM_PORTS]; +- u32 ar40xx_port_old_link[AR40XX_NUM_PORTS]; +- u32 ar40xx_port_qm_buf[AR40XX_NUM_PORTS]; +- +- u32 phy_t_status; +- +- /* mutex for switch reg access */ +- struct mutex reg_mutex; +- +- /* mutex for mib task */ +- struct mutex mib_lock; +- struct delayed_work mib_work; +- int mib_next_port; +- u64 *mib_stats; +- +- char buf[2048]; +- +- /* all fields below will be cleared on reset */ +- bool vlan; +- u16 vlan_id[AR40XX_MAX_VLANS]; +- u8 vlan_table[AR40XX_MAX_VLANS]; +- u8 vlan_tagged; +- u16 pvid[AR40XX_NUM_PORTS]; +- +- /* mirror */ +- bool mirror_rx; +- bool mirror_tx; +- int source_port; +- int monitor_port; +-}; +- +-#define AR40XX_PORT_LINK_UP 1 +-#define AR40XX_PORT_LINK_DOWN 0 +-#define AR40XX_QM_NOT_EMPTY 1 +-#define AR40XX_QM_EMPTY 0 +- +-#define AR40XX_LAN_VLAN 1 +-#define AR40XX_WAN_VLAN 2 +- +-enum ar40xx_port_wrapper_cfg { +- PORT_WRAPPER_PSGMII = 0, +-}; +- +-struct ar40xx_mib_desc { +- u32 size; +- u32 offset; +- const char *name; +-}; +- +-#define AR40XX_PORT_CPU 0 +- +-#define AR40XX_PSGMII_MODE_CONTROL 0x1b4 +-#define AR40XX_PSGMII_ATHR_CSCO_MODE_25M BIT(0) +- +-#define AR40XX_PSGMIIPHY_TX_CONTROL 0x288 +- +-#define AR40XX_MII_ATH_MMD_ADDR 0x0d +-#define AR40XX_MII_ATH_MMD_DATA 0x0e +-#define AR40XX_MII_ATH_DBG_ADDR 0x1d +-#define AR40XX_MII_ATH_DBG_DATA 0x1e +- +-#define AR40XX_STATS_RXBROAD 0x00 +-#define AR40XX_STATS_RXPAUSE 0x04 +-#define AR40XX_STATS_RXMULTI 0x08 +-#define AR40XX_STATS_RXFCSERR 0x0c +-#define AR40XX_STATS_RXALIGNERR 0x10 +-#define AR40XX_STATS_RXRUNT 0x14 +-#define AR40XX_STATS_RXFRAGMENT 0x18 +-#define AR40XX_STATS_RX64BYTE 0x1c +-#define AR40XX_STATS_RX128BYTE 0x20 +-#define AR40XX_STATS_RX256BYTE 0x24 +-#define AR40XX_STATS_RX512BYTE 0x28 +-#define AR40XX_STATS_RX1024BYTE 0x2c +-#define AR40XX_STATS_RX1518BYTE 0x30 +-#define AR40XX_STATS_RXMAXBYTE 0x34 +-#define AR40XX_STATS_RXTOOLONG 0x38 +-#define AR40XX_STATS_RXGOODBYTE 0x3c +-#define AR40XX_STATS_RXBADBYTE 0x44 +-#define AR40XX_STATS_RXOVERFLOW 0x4c +-#define AR40XX_STATS_FILTERED 0x50 +-#define AR40XX_STATS_TXBROAD 0x54 +-#define AR40XX_STATS_TXPAUSE 0x58 +-#define AR40XX_STATS_TXMULTI 0x5c +-#define AR40XX_STATS_TXUNDERRUN 0x60 +-#define AR40XX_STATS_TX64BYTE 0x64 +-#define AR40XX_STATS_TX128BYTE 0x68 +-#define AR40XX_STATS_TX256BYTE 0x6c +-#define AR40XX_STATS_TX512BYTE 0x70 +-#define AR40XX_STATS_TX1024BYTE 0x74 +-#define AR40XX_STATS_TX1518BYTE 0x78 +-#define AR40XX_STATS_TXMAXBYTE 0x7c +-#define AR40XX_STATS_TXOVERSIZE 0x80 +-#define AR40XX_STATS_TXBYTE 0x84 +-#define AR40XX_STATS_TXCOLLISION 0x8c +-#define AR40XX_STATS_TXABORTCOL 0x90 +-#define AR40XX_STATS_TXMULTICOL 0x94 +-#define AR40XX_STATS_TXSINGLECOL 0x98 +-#define AR40XX_STATS_TXEXCDEFER 0x9c +-#define AR40XX_STATS_TXDEFER 0xa0 +-#define AR40XX_STATS_TXLATECOL 0xa4 +- +-#define AR40XX_REG_MODULE_EN 0x030 +-#define AR40XX_MODULE_EN_MIB BIT(0) +- +-#define AR40XX_REG_MIB_FUNC 0x034 +-#define AR40XX_MIB_BUSY BIT(17) +-#define AR40XX_MIB_CPU_KEEP BIT(20) +-#define AR40XX_MIB_FUNC BITS(24, 3) +-#define AR40XX_MIB_FUNC_S 24 +-#define AR40XX_MIB_FUNC_NO_OP 0x0 +-#define AR40XX_MIB_FUNC_FLUSH 0x1 +- +-#define AR40XX_ESS_SERVICE_TAG 0x48 +-#define AR40XX_ESS_SERVICE_TAG_STAG BIT(17) +- +-#define AR40XX_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) +-#define AR40XX_PORT_SPEED BITS(0, 2) +-#define AR40XX_PORT_STATUS_SPEED_S 0 +-#define AR40XX_PORT_TX_EN BIT(2) +-#define AR40XX_PORT_RX_EN BIT(3) +-#define AR40XX_PORT_STATUS_TXFLOW BIT(4) +-#define AR40XX_PORT_STATUS_RXFLOW BIT(5) +-#define AR40XX_PORT_DUPLEX BIT(6) +-#define AR40XX_PORT_TXHALF_FLOW BIT(7) +-#define AR40XX_PORT_STATUS_LINK_UP BIT(8) +-#define AR40XX_PORT_AUTO_LINK_EN BIT(9) +-#define AR40XX_PORT_STATUS_FLOW_CONTROL BIT(12) +- +-#define AR40XX_REG_MAX_FRAME_SIZE 0x078 +-#define AR40XX_MAX_FRAME_SIZE_MTU BITS(0, 14) +- +-#define AR40XX_REG_PORT_HEADER(_i) (0x09c + (_i) * 4) +- +-#define AR40XX_REG_EEE_CTRL 0x100 +-#define AR40XX_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) +- +-#define AR40XX_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) +-#define AR40XX_PORT_VLAN0_DEF_SVID BITS(0, 12) +-#define AR40XX_PORT_VLAN0_DEF_SVID_S 0 +-#define AR40XX_PORT_VLAN0_DEF_CVID BITS(16, 12) +-#define AR40XX_PORT_VLAN0_DEF_CVID_S 16 +- +-#define AR40XX_REG_PORT_VLAN1(_i) (0x424 + (_i) * 0x8) +-#define AR40XX_PORT_VLAN1_CORE_PORT BIT(9) +-#define AR40XX_PORT_VLAN1_PORT_TLS_MODE BIT(7) +-#define AR40XX_PORT_VLAN1_PORT_VLAN_PROP BIT(6) +-#define AR40XX_PORT_VLAN1_OUT_MODE BITS(12, 2) +-#define AR40XX_PORT_VLAN1_OUT_MODE_S 12 +-#define AR40XX_PORT_VLAN1_OUT_MODE_UNMOD 0 +-#define AR40XX_PORT_VLAN1_OUT_MODE_UNTAG 1 +-#define AR40XX_PORT_VLAN1_OUT_MODE_TAG 2 +-#define AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH 3 +- +-#define AR40XX_REG_VTU_FUNC0 0x0610 +-#define AR40XX_VTU_FUNC0_EG_MODE BITS(4, 14) +-#define AR40XX_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) +-#define AR40XX_VTU_FUNC0_EG_MODE_KEEP 0 +-#define AR40XX_VTU_FUNC0_EG_MODE_UNTAG 1 +-#define AR40XX_VTU_FUNC0_EG_MODE_TAG 2 +-#define AR40XX_VTU_FUNC0_EG_MODE_NOT 3 +-#define AR40XX_VTU_FUNC0_IVL BIT(19) +-#define AR40XX_VTU_FUNC0_VALID BIT(20) +- +-#define AR40XX_REG_VTU_FUNC1 0x0614 +-#define AR40XX_VTU_FUNC1_OP BITS(0, 3) +-#define AR40XX_VTU_FUNC1_OP_NOOP 0 +-#define AR40XX_VTU_FUNC1_OP_FLUSH 1 +-#define AR40XX_VTU_FUNC1_OP_LOAD 2 +-#define AR40XX_VTU_FUNC1_OP_PURGE 3 +-#define AR40XX_VTU_FUNC1_OP_REMOVE_PORT 4 +-#define AR40XX_VTU_FUNC1_OP_GET_NEXT 5 +-#define AR40XX7_VTU_FUNC1_OP_GET_ONE 6 +-#define AR40XX_VTU_FUNC1_FULL BIT(4) +-#define AR40XX_VTU_FUNC1_PORT BIT(8, 4) +-#define AR40XX_VTU_FUNC1_PORT_S 8 +-#define AR40XX_VTU_FUNC1_VID BIT(16, 12) +-#define AR40XX_VTU_FUNC1_VID_S 16 +-#define AR40XX_VTU_FUNC1_BUSY BIT(31) +- +-#define AR40XX_REG_FWD_CTRL0 0x620 +-#define AR40XX_FWD_CTRL0_CPU_PORT_EN BIT(10) +-#define AR40XX_FWD_CTRL0_MIRROR_PORT BITS(4, 4) +-#define AR40XX_FWD_CTRL0_MIRROR_PORT_S 4 +- +-#define AR40XX_REG_FWD_CTRL1 0x624 +-#define AR40XX_FWD_CTRL1_UC_FLOOD BITS(0, 7) +-#define AR40XX_FWD_CTRL1_UC_FLOOD_S 0 +-#define AR40XX_FWD_CTRL1_MC_FLOOD BITS(8, 7) +-#define AR40XX_FWD_CTRL1_MC_FLOOD_S 8 +-#define AR40XX_FWD_CTRL1_BC_FLOOD BITS(16, 7) +-#define AR40XX_FWD_CTRL1_BC_FLOOD_S 16 +-#define AR40XX_FWD_CTRL1_IGMP BITS(24, 7) +-#define AR40XX_FWD_CTRL1_IGMP_S 24 +- +-#define AR40XX_REG_PORT_LOOKUP(_i) (0x660 + (_i) * 0xc) +-#define AR40XX_PORT_LOOKUP_MEMBER BITS(0, 7) +-#define AR40XX_PORT_LOOKUP_IN_MODE BITS(8, 2) +-#define AR40XX_PORT_LOOKUP_IN_MODE_S 8 +-#define AR40XX_PORT_LOOKUP_STATE BITS(16, 3) +-#define AR40XX_PORT_LOOKUP_STATE_S 16 +-#define AR40XX_PORT_LOOKUP_LEARN BIT(20) +-#define AR40XX_PORT_LOOKUP_LOOPBACK BIT(21) +-#define AR40XX_PORT_LOOKUP_ING_MIRROR_EN BIT(25) +- +-#define AR40XX_REG_ATU_FUNC 0x60c +-#define AR40XX_ATU_FUNC_OP BITS(0, 4) +-#define AR40XX_ATU_FUNC_OP_NOOP 0x0 +-#define AR40XX_ATU_FUNC_OP_FLUSH 0x1 +-#define AR40XX_ATU_FUNC_OP_LOAD 0x2 +-#define AR40XX_ATU_FUNC_OP_PURGE 0x3 +-#define AR40XX_ATU_FUNC_OP_FLUSH_LOCKED 0x4 +-#define AR40XX_ATU_FUNC_OP_FLUSH_UNICAST 0x5 +-#define AR40XX_ATU_FUNC_OP_GET_NEXT 0x6 +-#define AR40XX_ATU_FUNC_OP_SEARCH_MAC 0x7 +-#define AR40XX_ATU_FUNC_OP_CHANGE_TRUNK 0x8 +-#define AR40XX_ATU_FUNC_BUSY BIT(31) +- +-#define AR40XX_REG_QM_DEBUG_ADDR 0x820 +-#define AR40XX_REG_QM_DEBUG_VALUE 0x824 +-#define AR40XX_REG_QM_PORT0_3_QNUM 0x1d +-#define AR40XX_REG_QM_PORT4_6_QNUM 0x1e +- +-#define AR40XX_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) +-#define AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) +- +-#define AR40XX_REG_PORT_FLOWCTRL_THRESH(_i) (0x9b0 + (_i) * 0x4) +-#define AR40XX_PORT0_FC_THRESH_ON_DFLT 0x60 +-#define AR40XX_PORT0_FC_THRESH_OFF_DFLT 0x90 +- +-#define AR40XX_PHY_DEBUG_0 0 +-#define AR40XX_PHY_MANU_CTRL_EN BIT(12) +- +-#define AR40XX_PHY_DEBUG_2 2 +- +-#define AR40XX_PHY_SPEC_STATUS 0x11 +-#define AR40XX_PHY_SPEC_STATUS_LINK BIT(10) +-#define AR40XX_PHY_SPEC_STATUS_DUPLEX BIT(13) +-#define AR40XX_PHY_SPEC_STATUS_SPEED BITS(14, 2) +- +-/* port forwarding state */ +-enum { +- AR40XX_PORT_STATE_DISABLED = 0, +- AR40XX_PORT_STATE_BLOCK = 1, +- AR40XX_PORT_STATE_LISTEN = 2, +- AR40XX_PORT_STATE_LEARN = 3, +- AR40XX_PORT_STATE_FORWARD = 4 +-}; +- +-/* ingress 802.1q mode */ +-enum { +- AR40XX_IN_PORT_ONLY = 0, +- AR40XX_IN_PORT_FALLBACK = 1, +- AR40XX_IN_VLAN_ONLY = 2, +- AR40XX_IN_SECURE = 3 +-}; +- +-/* egress 802.1q mode */ +-enum { +- AR40XX_OUT_KEEP = 0, +- AR40XX_OUT_STRIP_VLAN = 1, +- AR40XX_OUT_ADD_VLAN = 2 +-}; +- +-/* port speed */ +-enum { +- AR40XX_PORT_SPEED_10M = 0, +- AR40XX_PORT_SPEED_100M = 1, +- AR40XX_PORT_SPEED_1000M = 2, +- AR40XX_PORT_SPEED_ERR = 3, +-}; +- +-#define AR40XX_MIB_WORK_DELAY 2000 /* msecs */ +- +-#define AR40XX_QM_WORK_DELAY 100 +- +-#define AR40XX_MIB_FUNC_CAPTURE 0x3 +- +-#define AR40XX_REG_PORT_STATS_START 0x1000 +-#define AR40XX_REG_PORT_STATS_LEN 0x100 +- +-#define AR40XX_PORTS_ALL 0x3f +- +-#define AR40XX_PSGMII_ID 5 +-#define AR40XX_PSGMII_CALB_NUM 100 +-#define AR40XX_MALIBU_PSGMII_MODE_CTRL 0x6d +-#define AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL 0x220c +-#define AR40XX_MALIBU_PHY_MMD7_DAC_CTRL 0x801a +-#define AR40XX_MALIBU_DAC_CTRL_MASK 0x380 +-#define AR40XX_MALIBU_DAC_CTRL_VALUE 0x280 +-#define AR40XX_MALIBU_PHY_RLP_CTRL 0x805a +-#define AR40XX_PSGMII_TX_DRIVER_1_CTRL 0xb +-#define AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP 0x8a +-#define AR40XX_MALIBU_PHY_LAST_ADDR 4 +- +-static inline struct ar40xx_priv * +-swdev_to_ar40xx(struct switch_dev *swdev) +-{ +- return container_of(swdev, struct ar40xx_priv, dev); +-} +- +-#endif +- +--- a/target/linux/ipq40xx/patches-5.10/702-dts-ipq4019-add-PHY-switch-nodes.patch ++++ /dev/null +@@ -1,46 +0,0 @@ +-From 9deeec35dd3b628b95624e41d4e04acf728991ba Mon Sep 17 00:00:00 2001 +-From: Christian Lamparter +-Date: Sun, 20 Nov 2016 02:20:54 +0100 +-Subject: [PATCH] dts: ipq4019: add PHY/switch nodes +- +-This patch adds both the "qcom,ess-switch" and "qcom,ess-psgmii" +-nodes which are needed for the ar40xx.c driver to initialize the +-switch. +- +-Signed-off-by: Christian Lamparter +---- +- arch/arm/boot/dts/qcom-ipq4019.dtsi | 23 +++++++++++++++++++++++ +- 1 file changed, 23 insertions(+) +- +---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +-+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +-@@ -617,6 +617,29 @@ +- }; +- }; +- +-+ ess-switch@c000000 { +-+ compatible = "qcom,ess-switch"; +-+ reg = <0xc000000 0x80000>; +-+ switch_access_mode = "local bus"; +-+ resets = <&gcc ESS_RESET>; +-+ reset-names = "ess_rst"; +-+ clocks = <&gcc GCC_ESS_CLK>; +-+ clock-names = "ess_clk"; +-+ switch_cpu_bmp = <0x1>; +-+ switch_lan_bmp = <0x1e>; +-+ switch_wan_bmp = <0x20>; +-+ switch_mac_mode = <0>; /* PORT_WRAPPER_PSGMII */ +-+ switch_initvlas = <0x7c 0x54>; +-+ status = "disabled"; +-+ }; +-+ +-+ ess-psgmii@98000 { +-+ compatible = "qcom,ess-psgmii"; +-+ reg = <0x98000 0x800>; +-+ psgmii_access_mode = "local bus"; +-+ status = "disabled"; +-+ }; +-+ +- usb3_ss_phy: ssphy@9a000 { +- compatible = "qcom,usb-ss-ipq4019-phy"; +- #phy-cells = <0>; + +--- a/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch ++++ /dev/null +@@ -1,53 +0,0 @@ +-From 7c129254adb1093d10a62ed7bf7b956fcc6ffe34 Mon Sep 17 00:00:00 2001 +-From: Rakesh Nair +-Date: Wed, 20 Jul 2016 15:02:01 +0530 +-Subject: [PATCH] net: IPQ4019 needs rfs/vlan_tag callbacks in +- netdev_ops +- +-Add callback support to get default vlan tag and register +-receive flow steering filter. +- +-Used by IPQ4019 ess-edma driver. +- +-BUG=chrome-os-partner:33096 +-TEST=none +- +-Change-Id: I266070e4a0fbe4a0d9966fe79a71e50ec4f26c75 +-Signed-off-by: Rakesh Nair +-Reviewed-on: https://chromium-review.googlesource.com/362203 +-Commit-Ready: Grant Grundler +-Tested-by: Grant Grundler +-Reviewed-by: Grant Grundler +---- +- include/linux/netdevice.h | 13 +++++++++++++ +- 1 file changed, 13 insertions(+) +- +---- a/include/linux/netdevice.h +-+++ b/include/linux/netdevice.h +-@@ -779,6 +779,16 @@ struct xps_map { +- #define XPS_MIN_MAP_ALLOC ((L1_CACHE_ALIGN(offsetof(struct xps_map, queues[1])) \ +- - sizeof(struct xps_map)) / sizeof(u16)) +- +-+#ifdef CONFIG_RFS_ACCEL +-+typedef int (*set_rfs_filter_callback_t)(struct net_device *dev, +-+ __be32 src, +-+ __be32 dst, +-+ __be16 sport, +-+ __be16 dport, +-+ u8 proto, +-+ u16 rxq_index, +-+ u32 action); +-+#endif +- /* +- * This structure holds all XPS maps for device. Maps are indexed by CPU. +- */ +-@@ -1466,6 +1476,9 @@ struct net_device_ops { +- const struct sk_buff *skb, +- u16 rxq_index, +- u32 flow_id); +-+ int (*ndo_register_rfs_filter)(struct net_device *dev, +-+ set_rfs_filter_callback_t set_filter); +-+ int (*ndo_get_default_vlan_tag)(struct net_device *net); +- #endif +- int (*ndo_add_slave)(struct net_device *dev, +- struct net_device *slave_dev, +--- a/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch ++++ /dev/null +@@ -1,27 +0,0 @@ +---- a/drivers/net/mdio/Kconfig +-+++ b/drivers/net/mdio/Kconfig +-@@ -27,6 +27,13 @@ config OF_MDIO +- help +- OpenFirmware MDIO bus (Ethernet PHY) accessors +- +-+config AR40XX_PHY +-+ tristate "Driver for Qualcomm Atheros IPQ40XX switches" +-+ depends on HAS_IOMEM && OF && OF_MDIO +-+ select SWCONFIG +-+ help +-+ This is the driver for Qualcomm Atheros IPQ40XX ESS switches. +-+ +- if MDIO_BUS +- +- config MDIO_DEVRES +---- a/drivers/net/mdio/Makefile +-+++ b/drivers/net/mdio/Makefile +-@@ -21,6 +21,8 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i. +- obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o +- obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o +- +-+obj-$(CONFIG_AR40XX_PHY) += ar40xx.o +-+ +- obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o +- obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o +- obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o +--- a/target/linux/ipq40xx/patches-5.10/710-net-add-qualcomm-essedma-ethernet-driver.patch ++++ /dev/null +@@ -1,37 +0,0 @@ +-From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001 +-From: Christian Lamparter +-Date: Thu, 19 Jan 2017 02:01:31 +0100 +-Subject: [PATCH 33/38] NET: add qualcomm essedma ethernet driver +- +-Signed-off-by: Christian Lamparter +---- +- drivers/net/ethernet/qualcomm/Kconfig | 9 +++++++++ +- drivers/net/ethernet/qualcomm/Makefile | 1 + +- 2 files changed, 10 insertions(+) +- +---- a/drivers/net/ethernet/qualcomm/Kconfig +-+++ b/drivers/net/ethernet/qualcomm/Kconfig +-@@ -62,4 +62,14 @@ config QCOM_EMAC +- +- source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" +- +-+config ESSEDMA +-+ tristate "Qualcomm Atheros ESS Edma support" +-+ depends on OF_MDIO +-+ help +-+ This driver supports ethernet edma adapter. +-+ Say Y to build this driver. +-+ +-+ To compile this driver as a module, choose M here. The module +-+ will be called essedma.ko. +-+ +- endif # NET_VENDOR_QUALCOMM +---- a/drivers/net/ethernet/qualcomm/Makefile +-+++ b/drivers/net/ethernet/qualcomm/Makefile +-@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o +- qcauart-objs := qca_uart.o +- +- obj-y += emac/ +-+obj-$(CONFIG_ESSEDMA) += essedma/ +- +- obj-$(CONFIG_RMNET) += rmnet/ +--- a/target/linux/ipq40xx/patches-5.10/711-dts-ipq4019-add-ethernet-essedma-node.patch ++++ /dev/null +@@ -1,92 +0,0 @@ +-From c611d3780fa101662a822d10acf8feb04ca97409 Mon Sep 17 00:00:00 2001 +-From: Christian Lamparter +-Date: Sun, 20 Nov 2016 01:01:10 +0100 +-Subject: [PATCH] dts: ipq4019: add ethernet essedma node +- +-This patch adds the device-tree node for the ethernet +-interfaces. +- +-Note: The driver isn't anywhere close to be upstream, +-so the info might change. +- +-Signed-off-by: Christian Lamparter +---- +- arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++++++++++ +- 1 file changed, 60 insertions(+) +- +---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +-+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +-@@ -39,6 +39,8 @@ +- spi1 = &blsp1_spi2; +- i2c0 = &blsp1_i2c3; +- i2c1 = &blsp1_i2c4; +-+ ethernet0 = &gmac0; +-+ ethernet1 = &gmac1; +- }; +- +- cpus { +-@@ -658,6 +660,64 @@ +- status = "disabled"; +- }; +- +-+ edma@c080000 { +-+ compatible = "qcom,ess-edma"; +-+ reg = <0xc080000 0x8000>; +-+ qcom,page-mode = <0>; +-+ qcom,rx_head_buf_size = <1540>; +-+ qcom,mdio_supported; +-+ qcom,poll_required = <1>; +-+ qcom,num_gmac = <2>; +-+ interrupts = <0 65 IRQ_TYPE_EDGE_RISING +-+ 0 66 IRQ_TYPE_EDGE_RISING +-+ 0 67 IRQ_TYPE_EDGE_RISING +-+ 0 68 IRQ_TYPE_EDGE_RISING +-+ 0 69 IRQ_TYPE_EDGE_RISING +-+ 0 70 IRQ_TYPE_EDGE_RISING +-+ 0 71 IRQ_TYPE_EDGE_RISING +-+ 0 72 IRQ_TYPE_EDGE_RISING +-+ 0 73 IRQ_TYPE_EDGE_RISING +-+ 0 74 IRQ_TYPE_EDGE_RISING +-+ 0 75 IRQ_TYPE_EDGE_RISING +-+ 0 76 IRQ_TYPE_EDGE_RISING +-+ 0 77 IRQ_TYPE_EDGE_RISING +-+ 0 78 IRQ_TYPE_EDGE_RISING +-+ 0 79 IRQ_TYPE_EDGE_RISING +-+ 0 80 IRQ_TYPE_EDGE_RISING +-+ 0 240 IRQ_TYPE_EDGE_RISING +-+ 0 241 IRQ_TYPE_EDGE_RISING +-+ 0 242 IRQ_TYPE_EDGE_RISING +-+ 0 243 IRQ_TYPE_EDGE_RISING +-+ 0 244 IRQ_TYPE_EDGE_RISING +-+ 0 245 IRQ_TYPE_EDGE_RISING +-+ 0 246 IRQ_TYPE_EDGE_RISING +-+ 0 247 IRQ_TYPE_EDGE_RISING +-+ 0 248 IRQ_TYPE_EDGE_RISING +-+ 0 249 IRQ_TYPE_EDGE_RISING +-+ 0 250 IRQ_TYPE_EDGE_RISING +-+ 0 251 IRQ_TYPE_EDGE_RISING +-+ 0 252 IRQ_TYPE_EDGE_RISING +-+ 0 253 IRQ_TYPE_EDGE_RISING +-+ 0 254 IRQ_TYPE_EDGE_RISING +-+ 0 255 IRQ_TYPE_EDGE_RISING>; +-+ +-+ status = "disabled"; +-+ +-+ gmac0: gmac0 { +-+ local-mac-address = [00 00 00 00 00 00]; +-+ vlan_tag = <1 0x1f>; +-+ }; +-+ +-+ gmac1: gmac1 { +-+ local-mac-address = [00 00 00 00 00 00]; +-+ qcom,phy_mdio_addr = <4>; +-+ qcom,poll_required = <1>; +-+ qcom,forced_speed = <1000>; +-+ qcom,forced_duplex = <1>; +-+ vlan_tag = <2 0x20>; +-+ }; +-+ }; +-+ +- usb3_ss_phy: ssphy@9a000 { +- compatible = "qcom,usb-ss-ipq4019-phy"; +- #phy-cells = <0>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts +@@ -21,10 +21,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts +@@ -62,14 +58,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts +@@ -174,22 +162,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <2 0x20>; +-}; +- +-&gmac1 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &usb2_hs_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts +@@ -65,10 +65,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts +@@ -118,17 +114,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- +- switch_lan_bmp = <0x10>; +- switch_wan_bmp = <0x20>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts +@@ -277,22 +262,6 @@ + #gpio-cells = <2>; + }; + +-&gmac0 { +- qcom,forced_duplex = <1>; +- qcom,forced_speed = <1000>; +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- vlan_tag = <1 0x10>; +-}; +- +-&gmac1 { +- qcom,forced_duplex = <1>; +- qcom,forced_speed = <1000>; +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- vlan_tag = <2 0x20>; +-}; +- + &tlmm { + i2c0_pins: i2c0_pinmux { + mux_i2c { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cap-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cap-ac.dts +@@ -61,16 +61,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,poll_required = <0>; +- qcom,num_gmac = <1>; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cap-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cap-ac.dts +@@ -222,10 +212,6 @@ + status = "okay"; + }; + +-&gmac0 { +- vlan_tag = <0 0x3f>; +-}; +- + ðphy3 { + gpio-controller; + #gpio-cells = <2>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts +@@ -29,10 +29,6 @@ + reset-delay-us = <5000>; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts +@@ -64,14 +60,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + leds { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts +@@ -264,13 +252,3 @@ + nvmem-cell-names = "pre-calibration"; + nvmem-cells = <&precal_art_5000>; + }; +- +-&gmac0 { +- nvmem-cell-names = "mac-address"; +- nvmem-cells = <&macaddr_art_6>; +-}; +- +-&gmac1 { +- nvmem-cell-names = "mac-address"; +- nvmem-cells = <&macaddr_art_0>; +-}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts +@@ -17,11 +17,6 @@ + }; + + soc { +- edma@c080000 { +- qcom,num_gmac = <1>; +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts +@@ -51,16 +46,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x20>; +- switch_wan_bmp = <0x00>; +- }; +- +- ess-psgmii@98000 { +- status = "okay"; +- }; + }; + + leds { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts +@@ -192,14 +177,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x20>; +-}; +- + &mdio { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts +@@ -25,10 +25,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts +@@ -68,14 +64,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts +@@ -18,10 +18,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts +@@ -47,14 +43,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts +@@ -227,14 +215,6 @@ + status = "okay"; + }; + +-&gmac0 { +- vlan_tag = <2 0x20>; +-}; +- +-&gmac1 { +- vlan_tag = <1 0x10>; +-}; +- + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts +@@ -14,7 +14,6 @@ + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; +- label-mac-device = &gmac0; + }; + + chosen { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts +@@ -57,10 +56,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts +@@ -110,17 +105,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- +- switch_lan_bmp = <0x10>; +- switch_wan_bmp = <0x20>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts +@@ -303,18 +287,6 @@ + pinctrl-names = "default"; + }; + +-&gmac0 { +- qcom,poll_required = <1>; +- qcom,phy_mdio_addr = <4>; +- vlan_tag = <2 0x20>; +-}; +- +-&gmac1 { +- qcom,poll_required = <1>; +- qcom,phy_mdio_addr = <3>; +- vlan_tag = <1 0x10>; +-}; +- + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts +@@ -25,10 +25,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts +@@ -54,17 +50,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x20>; +- switch_wan_bmp = <0x00>; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,num_gmac = <1>; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts +@@ -210,14 +195,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x20>; +-}; +- + &cryptobam { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts +@@ -18,10 +18,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts +@@ -51,14 +47,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts +@@ -212,14 +200,6 @@ + status = "okay"; + }; + +-&gmac0 { +- vlan_tag = <1 0x10>; +-}; +- +-&gmac1 { +- vlan_tag = <2 0x20>; +-}; +- + &usb2_hs_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts +@@ -26,14 +26,6 @@ + status = "okay"; + }; + +- mdio@90000 { +- status = "okay"; +- }; +- +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts +@@ -60,14 +52,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + /* + * Disable the broken restart as a workaround for the buggy + * 3.0.0/3.0.1 U-boots that ship with the device. +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi +@@ -33,10 +33,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi +@@ -62,15 +58,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,num_gmac = <1>; +- }; + }; + + aliases { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi +@@ -78,7 +65,6 @@ + led-failsafe = &power_amber; + led-running = &power_green; + led-upgrade = &power_amber; +- label-mac-device = &gmac0; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts +@@ -14,7 +14,6 @@ + led-failsafe = &flash; + led-running = &power; + led-upgrade = &flash; +- label-mac-device = &gmac0; + }; + + soc { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts +@@ -26,10 +25,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts +@@ -69,14 +64,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts +@@ -34,10 +34,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts +@@ -79,16 +75,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x18>; +- switch_wan_bmp = <0x20>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts +@@ -78,14 +78,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi +@@ -19,10 +19,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi +@@ -69,16 +65,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- +- switch_lan_bmp = <0x10>; /* lan port bitmap */ +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi +@@ -241,20 +227,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,poll_required = <1>; +- qcom,poll_required_dynamic = <1>; +- qcom,phy_mdio_addr = <3>; +- vlan_tag = <1 0x10>; +-}; +- +-&gmac1 { +- qcom,poll_required = <1>; +- qcom,poll_required_dynamic = <1>; +- qcom,phy_mdio_addr = <4>; +- vlan_tag = <2 0x20>; +-}; +- + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts +@@ -29,10 +29,6 @@ + /delete-node/ ethernet-phy@1; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + crypto@8e3a000 { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts +@@ -41,42 +37,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x3e>; +- switch_wan_bmp = <0x0>; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,num_gmac = <3>; +- +- gmac0 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- /delete-property/ qcom,forced_speed; +- /delete-property/ qcom,forced_duplex; +- vlan_tag = <1 0x10>; +- }; +- +- gmac1 { +- qcom,phy_mdio_addr = <2>; +- qcom,poll_required = <1>; +- /delete-property/ qcom,forced_speed; +- /delete-property/ qcom,forced_duplex; +- vlan_tag = <1 0x08>; +- }; +- +- gmac2 { +- local-mac-address = [00 00 00 00 00 00]; +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- /delete-property/ qcom,forced_speed; +- /delete-property/ qcom,forced_duplex; +- vlan_tag = <1 0x20>; +- }; +- }; +- + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts +@@ -35,10 +35,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts +@@ -103,14 +99,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts +@@ -21,10 +21,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts +@@ -62,14 +58,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts +@@ -166,22 +154,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <2 0x20>; +-}; +- +-&gmac1 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &usb2_hs_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts +@@ -30,10 +30,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts +@@ -84,14 +80,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rutx.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rutx.dtsi +@@ -6,10 +6,6 @@ + #include + + / { +- aliases { +- label-mac-device = &gmac0; +- }; +- + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts +@@ -65,17 +65,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-psgmii@98000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- phy-mode = "rgmii"; +- qcom,num_gmac = <1>; +- qcom,single-phy; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts +@@ -228,14 +217,6 @@ + qcom,ath10k-calibration-variant = "MikroTik-SXTsq-5-ac"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x20>; +-}; +- + &mdio { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts +@@ -16,7 +16,6 @@ + led-failsafe = &led_power_amber; + led-running = &led_power_green; + led-upgrade = &led_power_amber; +- label-mac-device = &gmac0; + }; + + chosen { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts +@@ -28,10 +27,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts +@@ -62,14 +57,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts +@@ -358,14 +345,6 @@ + reset-delay-us = <2000>; + }; + +-&gmac0 { +- qcom,forced_duplex = <1>; +- qcom,forced_speed = <1000>; +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration", "mac-address"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts +@@ -44,10 +44,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts +@@ -73,15 +69,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,num_gmac = <1>; +- }; + }; + + leds { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts +@@ -53,10 +53,6 @@ + /delete-node/ ethernet-phy@3; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts +@@ -96,17 +92,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- +- switch_lan_bmp = <0x1e>; +- switch_wan_bmp = <0x20>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts +@@ -224,16 +209,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <2>; +- qcom,poll_required = <1>; +-}; +- +-&gmac1 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +-}; +- + &tlmm { + serial0_pins: serial0_pinmux { + mux { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts +@@ -21,10 +21,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts +@@ -62,17 +58,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- switch_lan_bmp = <0x10>; +- switch_wan_bmp = <0x20>; +- +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts +@@ -184,14 +169,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &usb2_hs_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts +@@ -29,10 +29,6 @@ + reset-delay-us = <1000>; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts +@@ -97,14 +93,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + led_spi { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts +@@ -196,16 +184,6 @@ + status = "okay"; + }; + +-&gmac0 { +- nvmem-cells = <&macaddr_art_1006>; +- nvmem-cell-names = "mac-address"; +-}; +- +-&gmac1 { +- nvmem-cells = <&macaddr_art_5006>; +- nvmem-cell-names = "mac-address"; +-}; +- + &nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi +@@ -30,10 +30,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi +@@ -120,14 +116,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + leds { + compatible = "gpio-leds"; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts +@@ -76,10 +76,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + crypto@8e3a000 { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts +@@ -87,15 +83,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x10>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts +@@ -189,10 +176,6 @@ + status = "okay"; + }; + +-&gmac0 { +- vlan_tag = <1 0x10>; +-}; +- + &nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +--- 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 +@@ -25,10 +25,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- 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 +@@ -64,15 +60,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,num_gmac = <1>; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts +@@ -59,19 +59,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ +- switch_lan_bmp = <0x0>; /* lan port bitmap */ +- switch_wan_bmp = <0x10>; /* wan port bitmap */ +- }; +- +- edma@c080000 { +- status = "okay"; +- phy-mode = "rgmii-id"; +- qcom,num_gmac = <1>; +- qcom,single-phy; +- }; + }; + + key { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts +@@ -265,9 +252,3 @@ + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200"; + }; +- +-&gmac0 { +- qcom,phy_mdio_addr = <0>; +- qcom,poll_required = <1>; +- vlan_tag = <0 0x20>; +-}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts +@@ -25,10 +25,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts +@@ -54,18 +50,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- +- switch_lan_bmp = <0x30>; +- switch_wan_bmp = <0x02>; +- }; +- +- edma@c080000 { +- status = "okay"; +- qcom,num_gmac = <1>; +- }; + }; + + key { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts +@@ -210,10 +194,6 @@ + }; + }; + +-&gmac0 { +- vlan_tag = <1 0x30>; +-}; +- + &cryptobam { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts +@@ -27,10 +27,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts +@@ -60,16 +56,6 @@ + crypto@8e3a000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x2e>; +- switch_wan_bmp = <0x10>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts +@@ -113,18 +99,6 @@ + }; + }; + +-&gmac1 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <2 0x10>; +-}; +- +-&gmac0 { +- vlan_tag = <1 0x2e>; +-}; +- + &vqmmc { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts +@@ -29,10 +29,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts +@@ -79,14 +75,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hap-ac3.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hap-ac3.dts +@@ -73,14 +73,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts +@@ -85,19 +85,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ +- switch_lan_bmp = <0x0>; /* lan port bitmap */ +- switch_wan_bmp = <0x10>; /* wan port bitmap */ +- }; +- +- edma@c080000 { +- status = "okay"; +- phy-mode = "rgmii-id"; +- qcom,num_gmac = <1>; +- qcom,single-phy; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts +@@ -260,9 +247,3 @@ + }; + }; + }; +- +-&gmac0 { +- qcom,phy_mdio_addr = <0>; +- qcom,poll_required = <1>; +- vlan_tag = <0 0x20>; +-}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts +@@ -26,10 +26,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts +@@ -59,14 +55,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts +@@ -130,14 +130,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts +@@ -225,17 +217,6 @@ + status = "okay"; + }; + +-&gmac0 { +- nvmem-cell-names = "mac-address"; +- nvmem-cells = <&macaddr_config_0>; +-}; +- +-&gmac1 { +- nvmem-cell-names = "mac-address"; +- nvmem-cells = <&macaddr_config_0>; +- mac-address-increment = <1>; +-}; +- + &nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts +@@ -27,10 +27,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts +@@ -97,17 +93,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_mac_mode = <0x0>; /* mac mode for RGMII RMII */ +- switch_initvlas = <0x0007c 0x54>; /* port0 status */ +- switch_lan_bmp = <0x10>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + key { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-orbi.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-orbi.dtsi +@@ -25,10 +25,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-orbi.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-orbi.dtsi +@@ -67,17 +63,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- +- switch_lan_bmp = <0x1c>; +- switch_wan_bmp = <0x02>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-orbi.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-orbi.dtsi +@@ -281,15 +266,6 @@ + status = "okay"; + }; + +-&gmac0 { +- vlan_tag = <1 0x1c>; +-}; +- +-&gmac1 { +- qcom,phy_mdio_addr = <0>; +- vlan_tag = <2 0x02>; +-}; +- + &pcie0 { + status = "okay"; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts +@@ -21,10 +21,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts +@@ -50,17 +46,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- switch_lan_bmp = <0x10>; +- switch_wan_bmp = <0x20>; +- +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts +@@ -169,14 +154,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi +@@ -16,7 +16,6 @@ + led-failsafe = &led_sys; + led-running = &led_sys; + led-upgrade = &led_sys; +- label-mac-device = &gmac0; + }; + + soc { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi +@@ -30,10 +29,6 @@ + pinctrl-names = "default"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi +@@ -73,14 +68,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + leds { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts +@@ -142,10 +142,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts +@@ -187,14 +183,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi +@@ -21,10 +21,6 @@ + reset-delay-us = <2000>; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi +@@ -87,14 +83,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + aliases { + led-boot = &led_status; + led-failsafe = &led_status; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts +@@ -253,10 +253,6 @@ + reset-delay-us = <5000>; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts +@@ -333,16 +329,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- switch_lan_bmp = <0x1e>; +- switch_wan_bmp = <0x20>; +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + qpic_bam: dma@7984000 { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts +@@ -371,22 +357,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <2 0x20>; +-}; +- +-&gmac1 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts +@@ -32,7 +32,6 @@ + led-failsafe = &led_power_orange; + led-running = &led_power_white; + led-upgrade = &led_power_blue; +- label-mac-device = &gmac0; + }; + + soc { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts +@@ -73,19 +72,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x1c>; +- }; +- +- ess-psgmii@98000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + usb3@8af8800 { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts +@@ -438,16 +424,6 @@ + reset-gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + }; + +-&gmac0 { +- nvmem-cells = <&macaddr_orgdata_20>; +- nvmem-cell-names = "mac-address"; +-}; +- +-&gmac1 { +- nvmem-cells = <&macaddr_orgdata_20>; +- nvmem-cell-names = "mac-address"; +-}; +- + &usb3_ss_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-x1pro.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-x1pro.dts +@@ -87,17 +87,3 @@ + }; + }; + }; +- +-&gmac0 { +- status = "okay"; +- +- mtd-mac-address = <&art 0x5006>; +- mtd-mac-address-increment = <2>; +-}; +- +-&gmac1 { +- status = "okay"; +- +- mtd-mac-address = <&art 0x5006>; +- mtd-mac-address-increment = <3>; +-}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-x1pro.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-x1pro.dtsi +@@ -30,10 +30,6 @@ + reset-delay-us = <2000>; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-x1pro.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-x1pro.dtsi +@@ -96,14 +92,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi +@@ -35,10 +35,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi +@@ -103,14 +99,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + }; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts +@@ -38,10 +38,6 @@ + reset-delay-us = <2000>; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts +@@ -83,17 +79,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- switch_lan_bmp = <0x10>; +- switch_wan_bmp = <0x20>; +- +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts +@@ -262,22 +247,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <4>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <2 0x20>; +-}; +- +-&gmac1 { +- qcom,phy_mdio_addr = <3>; +- qcom,poll_required = <1>; +- qcom,forced_speed = <1000>; +- qcom,forced_duplex = <1>; +- vlan_tag = <1 0x10>; +-}; +- + &usb3_ss_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303h.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303h.dts +@@ -76,14 +76,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- status = "okay"; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; +- + i2c_0: i2c@78b7000 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi +@@ -64,19 +64,6 @@ + status = "okay"; + }; + +- ess-switch@c000000 { +- switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ +- switch_lan_bmp = <0x0>; /* lan port bitmap */ +- switch_wan_bmp = <0x10>; /* wan port bitmap */ +- }; +- +- edma@c080000 { +- qcom,single-phy; +- qcom,num_gmac = <1>; +- phy-mode = "rgmii-id"; +- status = "okay"; +- }; +- + i2c_0: i2c@78b7000 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi +@@ -123,12 +110,6 @@ + status = "okay"; + }; + +-&gmac0 { +- qcom,phy_mdio_addr = <5>; +- qcom,poll_required = <1>; +- vlan_tag = <0 0x20>; +-}; +- + &qpic_bam { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts +@@ -44,10 +44,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts +@@ -89,16 +85,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x18>; +- switch_wan_bmp = <0x20>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts +@@ -30,10 +30,6 @@ + status = "okay"; + }; + +- ess-psgmii@98000 { +- status = "okay"; +- }; +- + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts +@@ -75,16 +71,6 @@ + watchdog@b017000 { + status = "okay"; + }; +- +- ess-switch@c000000 { +- status = "okay"; +- switch_lan_bmp = <0x18>; +- switch_wan_bmp = <0x20>; +- }; +- +- edma@c080000 { +- status = "okay"; +- }; + }; + + keys { +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -64,6 +64,8 @@ + + #define QCA807X_CHIP_CONFIGURATION 0x1f + #define QCA807X_BT_BX_REG_SEL BIT(15) ++#define QCA807X_BT_BX_REG_SEL_FIBER 0 ++#define QCA807X_BT_BX_REG_SEL_COPPER 1 + #define QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK GENMASK(3, 0) + #define QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII 4 + #define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER 3 +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -400,19 +402,9 @@ static int qca807x_gpio(struct phy_device *phydev) + } + #endif + +-static int qca807x_read_copper_status(struct phy_device *phydev, bool combo_port) ++static int qca807x_read_copper_status(struct phy_device *phydev) + { +- int ss, err, page, old_link = phydev->link; +- +- /* Only combo port has dual pages */ +- if (combo_port) { +- /* Check whether copper page is set and set if needed */ +- page = phy_read(phydev, QCA807X_CHIP_CONFIGURATION); +- if (!(page & QCA807X_BT_BX_REG_SEL)) { +- page |= QCA807X_BT_BX_REG_SEL; +- phy_write(phydev, QCA807X_CHIP_CONFIGURATION, page); +- } +- } ++ int ss, err, old_link = phydev->link; + + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -487,16 +479,9 @@ static int qca807x_read_copper_status(struct phy_device *phydev, bool combo_port + return 0; + } + +-static int qca807x_read_fiber_status(struct phy_device *phydev, bool combo_port) ++static int qca807x_read_fiber_status(struct phy_device *phydev) + { +- int ss, err, page, lpa, old_link = phydev->link; +- +- /* Check whether fiber page is set and set if needed */ +- page = phy_read(phydev, QCA807X_CHIP_CONFIGURATION); +- if (page & QCA807X_BT_BX_REG_SEL) { +- page &= ~QCA807X_BT_BX_REG_SEL; +- phy_write(phydev, QCA807X_CHIP_CONFIGURATION, page); +- } ++ int ss, err, lpa, old_link = phydev->link; + + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -559,28 +544,17 @@ static int qca807x_read_fiber_status(struct phy_device *phydev, bool combo_port) + + static int qca807x_read_status(struct phy_device *phydev) + { +- int val; +- +- /* Check for Combo port */ +- if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { +- /* Check for fiber mode first */ +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) { +- /* Check for actual detected media */ +- val = phy_read(phydev, QCA807X_MEDIA_SELECT_STATUS); +- if (val & QCA807X_MEDIA_DETECTED_COPPER) { +- qca807x_read_copper_status(phydev, true); +- } else if ((val & QCA807X_MEDIA_DETECTED_1000_BASE_X) || +- (val & QCA807X_MEDIA_DETECTED_100_BASE_FX)) { +- qca807x_read_fiber_status(phydev, true); +- } +- } else { +- qca807x_read_copper_status(phydev, true); ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) { ++ switch (phydev->port) { ++ case PORT_FIBRE: ++ return qca807x_read_fiber_status(phydev); ++ case PORT_TP: ++ return qca807x_read_copper_status(phydev); ++ default: ++ return -EINVAL; + } +- } else { +- qca807x_read_copper_status(phydev, false); +- } +- +- return 0; ++ } else ++ return qca807x_read_copper_status(phydev); + } + + static int qca807x_config_intr(struct phy_device *phydev) +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -683,9 +657,63 @@ static int qca807x_led_config(struct phy_device *phydev) + return 0; + } + ++static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; ++ phy_interface_t iface; ++ int ret; ++ ++ sfp_parse_support(phydev->sfp_bus, id, support); ++ iface = sfp_select_interface(phydev->sfp_bus, support); ++ ++ dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface)); ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_100BASEX: ++ /* Set PHY mode to PSGMII combo (1/4 copper + combo ports) mode */ ++ ret = phy_modify(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, ++ QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); ++ /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ ++ ret = phy_set_bits_mmd(phydev, ++ MDIO_MMD_AN, ++ QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, ++ QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN); ++ /* Select fiber page */ ++ ret = phy_clear_bits(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_BT_BX_REG_SEL); ++ ++ phydev->port = PORT_FIBRE; ++ break; ++ default: ++ dev_err(&phydev->mdio.dev, "Incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static void qca807x_sfp_remove(void *upstream) ++{ ++ struct phy_device *phydev = upstream; ++ ++ /* Select copper page */ ++ phy_set_bits(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_BT_BX_REG_SEL); ++ ++ phydev->port = PORT_TP; ++} ++ + static const struct sfp_upstream_ops qca807x_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, ++ .module_insert = qca807x_sfp_insert, ++ .module_remove = qca807x_sfp_remove, + }; + + static int qca807x_config(struct phy_device *phydev) +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -696,28 +724,7 @@ static int qca807x_config(struct phy_device *phydev) + + /* Check for Combo port */ + if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { +- int fiber_mode_autodect; + int psgmii_serdes; +- int chip_config; +- +- if (of_property_read_bool(node, "qcom,fiber-enable")) { +- /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ +- fiber_mode_autodect = phy_read_mmd(phydev, MDIO_MMD_AN, +- QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION); +- fiber_mode_autodect |= QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN; +- phy_write_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, +- fiber_mode_autodect); +- +- /* Enable 4 copper + combo port mode */ +- chip_config = phy_read(phydev, QCA807X_CHIP_CONFIGURATION); +- chip_config &= ~QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK; +- chip_config |= FIELD_PREP(QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, +- QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); +- phy_write(phydev, QCA807X_CHIP_CONFIGURATION, chip_config); +- +- linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); +- linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); +- } + + /* Prevent PSGMII going into hibernation via PSGMII self test */ + psgmii_serdes = phy_read_mmd(phydev, MDIO_MMD_PCS, PSGMII_MMD3_SERDES_CONTROL); +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -761,9 +768,10 @@ static int qca807x_probe(struct phy_device *phydev) + } + + /* Attach SFP bus on combo port*/ +- if (of_property_read_bool(node, "qcom,fiber-enable")) { +- if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) +- ret = phy_sfp_probe(phydev, &qca807x_sfp_ops); ++ if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { ++ ret = phy_sfp_probe(phydev, &qca807x_sfp_ops); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); + } + + return ret; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts +@@ -24,9 +24,6 @@ + pinctrl-names = "default"; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + reset-delay-us = <2000>; +- +- /delete-node/ ethernet-phy@0; +- /delete-node/ ethernet-phy@1; + }; + + crypto@8e3a000 { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts +@@ -152,6 +149,14 @@ + status = "okay"; + }; + ++ðphy0 { ++ status = "disabled"; ++}; ++ ++ðphy1 { ++ status = "disabled"; ++}; ++ + &wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "devolo,magic-2-wifi-next"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts +@@ -47,10 +47,6 @@ + + mdio@90000 { + status = "okay"; +- +- /delete-node/ ethernet-phy@0; +- /delete-node/ ethernet-phy@1; +- /delete-node/ ethernet-phy@3; + }; + + tcsr@1949000 { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts +@@ -248,6 +244,18 @@ + status = "okay"; + }; + ++ðphy0 { ++ status = "disabled"; ++}; ++ ++ðphy1 { ++ status = "disabled"; ++}; ++ ++ðphy3 { ++ status = "disabled"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts +@@ -26,12 +26,6 @@ + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; +- +- /delete-node/ ethernet-phy@1; +- /delete-node/ ethernet-phy@2; +- /delete-node/ ethernet-phy@3; +- /delete-node/ ethernet-phy@4; +- /delete-node/ psgmii-phy@5; + }; + + tcsr@1949000 { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts +@@ -243,6 +237,30 @@ + status = "okay"; + }; + ++ðphy0 { ++ status = "disabled"; ++}; ++ ++ðphy1 { ++ status = "disabled"; ++}; ++ ++ðphy2 { ++ status = "disabled"; ++}; ++ ++ðphy3 { ++ status = "disabled"; ++}; ++ ++ðphy4 { ++ status = "disabled"; ++}; ++ ++&psgmiiphy { ++ status = "disabled"; ++}; ++ + &wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts +@@ -47,12 +47,6 @@ + + mdio@90000 { + status = "okay"; +- +- /delete-node/ ethernet-phy@1; +- /delete-node/ ethernet-phy@2; +- /delete-node/ ethernet-phy@3; +- /delete-node/ ethernet-phy@4; +- /delete-node/ psgmii-phy@5; + }; + + counter@4a1000 { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts +@@ -247,3 +241,23 @@ + }; + }; + }; ++ ++ðphy1 { ++ status = "disabled"; ++}; ++ ++ðphy2 { ++ status = "disabled"; ++}; ++ ++ðphy3 { ++ status = "disabled"; ++}; ++ ++ðphy4 { ++ status = "disabled"; ++}; ++ ++&psgmiiphy { ++ status = "disabled"; ++}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi +@@ -21,13 +21,6 @@ + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + +- /delete-node/ ethernet-phy@0; +- /delete-node/ ethernet-phy@1; +- /delete-node/ ethernet-phy@2; +- /delete-node/ ethernet-phy@3; +- /delete-node/ ethernet-phy@4; +- /delete-node/ psgmii-phy@5; +- + ethernet-phy@5 { + reg = <0x5>; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi +@@ -221,6 +214,30 @@ + }; + }; + ++ðphy0 { ++ status = "disabled"; ++}; ++ ++ðphy1 { ++ status = "disabled"; ++}; ++ ++ðphy2 { ++ status = "disabled"; ++}; ++ ++ðphy3 { ++ status = "disabled"; ++}; ++ ++ðphy4 { ++ status = "disabled"; ++}; ++ ++&psgmiiphy { ++ status = "disabled"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration", "mac-address"; + +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch +@@ -0,0 +1,43 @@ ++From da75807ac41175e9db8c95f7a172b4133763b744 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 11 Jan 2021 17:49:36 +0100 ++Subject: [PATCH] skbuff: add DSA specific data to struct skb_shared_info ++ ++All of the already existing DSA tagging protocol drivers ++are storing the tagging data directly into the skb. In most ++cases that is the only way to send the required information ++to the underlying ethernet switch. ++ ++However on certain platforms (like the Qualcomm IPQ40xx ++SoCs) the built-in ethernet switch is connected directly ++to an ethernet MAC, and the tagging information must be ++sent out-of-band which is done directly via the hardware ++TX descriptors of the ethernet MAC. ++ ++In such cases, putting the information into the skb causes ++unneccesary overhead, because the ethernet driver must ++remove that before sending the ethernet frame towards to ++the hardware. ++ ++This change adds two new DSA specific fields to struct ++skb_shared_info which makes it possible to send the ++tagging information via skb->shinfo. With this approach, ++the twofold modifications of the skb data can be avoided. ++ ++Signed-off-by: Gabor Juhos ++--- ++ include/linux/skbuff.h | 3 +++ ++ 1 file changed, 3 insertions(+) ++ ++--- a/include/linux/skbuff.h +++++ b/include/linux/skbuff.h ++@@ -522,6 +522,9 @@ struct skb_shared_info { ++ unsigned int gso_type; ++ u32 tskey; ++ +++ unsigned int dsa_tag_proto; +++ unsigned char dsa_tag_data[8]; +++ ++ /* ++ * Warning : all fields before dataref are cleared in __alloc_skb() ++ */ +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch +@@ -0,0 +1,188 @@ ++From 29a0c2fae991cab142575c92276c0afdeb260ebe Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Thu, 28 Oct 2021 21:44:52 +0200 ++Subject: [PATCH] net: dsa: tag_ipq4019: add shinfo based tagging driver for ++ IPQ40xx ++ ++This change adds a tagging protocol driver for the built-in ++ethernet switch of the Qualcomm Atheros IPQ4019 SoCs. ++ ++In comparison to the existing tagging protocols this hardware ++requires a slightly different approach because the switch does ++not use in-band tags. ++ ++On the receive path, the source port information is embedded ++into the RX descriptors of the ethernet MAC hardware. Similarly, ++the destination port mask must be sent via the TX descriptors ++of the ethernet MAC when a packet is sent towards the switch. ++ ++In order to support this special requirements, this patch ++adds a new tagging protocol driver. ++ ++The driver extracts the source port information directly ++from the 'receive return descriptor' of the ethernet MAC. ++It is possible because that descriptor is part of the skb ++received from the ethernet driver. ++ ++Unfortunatley, it is not possible to put the destination ++port information directly to the TX descriptors, because ++those are handled internally by the driver of the ethernet ++hardware. ++ ++To overcome this limitation, this tagging driver uses the ++DSA specific fields in skb->shinfo to send the destination ++port information to the ethernet driver. ++ ++A similar tagging driver is exist but that uses skb ++extensions which causes unnecessary overhead. ++ ++Signed-off-by: Gabor Juhos ++--- ++ include/linux/dsa/ipq4019.h | 11 ++++++ ++ include/net/dsa.h | 2 + ++ net/dsa/Kconfig | 6 +++ ++ net/dsa/Makefile | 1 + ++ net/dsa/tag_ipq4019.c | 79 +++++++++++++++++++++++++++++++++++++ ++ 5 files changed, 99 insertions(+) ++ create mode 100644 include/linux/dsa/ipq4019.h ++ create mode 100644 net/dsa/tag_ipq4019.c ++ ++--- /dev/null +++++ b/include/linux/dsa/ipq4019.h ++@@ -0,0 +1,11 @@ +++/* SPDX-License-Identifier: GPL-2.0-only */ +++ +++#ifndef DSA_IPQ40XX_H +++#define DSA_IPQ40XX_H +++ +++struct ipq40xx_dsa_tag_data { +++ u8 from_cpu; +++ u8 dp; +++}; +++ +++#endif /* DSA_IPQ40XX_H */ ++--- a/include/net/dsa.h +++++ b/include/net/dsa.h ++@@ -46,6 +46,7 @@ struct phylink_link_state; ++ #define DSA_TAG_PROTO_AR9331_VALUE 16 ++ #define DSA_TAG_PROTO_RTL4_A_VALUE 17 ++ #define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 +++#define DSA_TAG_PROTO_IPQ4019_VALUE 24 ++ ++ enum dsa_tag_protocol { ++ DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, ++@@ -67,6 +68,7 @@ enum dsa_tag_protocol { ++ DSA_TAG_PROTO_OCELOT = DSA_TAG_PROTO_OCELOT_VALUE, ++ DSA_TAG_PROTO_AR9331 = DSA_TAG_PROTO_AR9331_VALUE, ++ DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE, +++ DSA_TAG_PROTO_IPQ4019 = DSA_TAG_PROTO_IPQ4019_VALUE, ++ }; ++ ++ struct packet_type; ++--- a/net/dsa/Kconfig +++++ b/net/dsa/Kconfig ++@@ -63,6 +63,12 @@ config NET_DSA_TAG_BRCM_PREPEND ++ Broadcom switches which places the tag before the Ethernet header ++ (prepended). ++ +++config NET_DSA_TAG_IPQ4019 +++ tristate "Tag driver for Qualcomm Atheros IPQ4019 SoC built-in switch" +++ help +++ Say Y or M if you want to enable support for tagging frames for +++ the built-in switch of the Qualcomm Atheros IPQ4019 SoC-s. +++ ++ config NET_DSA_TAG_GSWIP ++ tristate "Tag driver for Lantiq / Intel GSWIP switches" ++ help ++--- a/net/dsa/Makefile +++++ b/net/dsa/Makefile ++@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += ++ obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o ++ obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o ++ obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o +++obj-$(CONFIG_NET_DSA_TAG_IPQ4019) += tag_ipq4019.o ++ obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o ++ obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o ++ obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o ++--- /dev/null +++++ b/net/dsa/tag_ipq4019.c ++@@ -0,0 +1,79 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++ +++/* Copyright (c) 2021, Gabor Juhos */ +++ +++#include +++#include +++ +++#include "dsa_priv.h" +++ +++/* Receive Return Descriptor */ +++struct edma_rrd { +++ u16 rrd0; +++ u16 rrd1; +++ u16 rrd2; +++ u16 rrd3; +++ u16 rrd4; +++ u16 rrd5; +++ u16 rrd6; +++ u16 rrd7; +++} __packed; +++ +++#define EDMA_RRD_SIZE sizeof(struct edma_rrd) +++ +++#define EDMA_RRD1_PORT_ID_MASK GENMASK(14, 12) +++ +++static struct sk_buff *ipq4019_sh_tag_xmit(struct sk_buff *skb, +++ struct net_device *dev) +++{ +++ struct dsa_port *dp = dsa_slave_to_port(dev); +++ struct ipq40xx_dsa_tag_data *tag_data; +++ +++ BUILD_BUG_ON(sizeof_field(struct skb_shared_info, dsa_tag_data) < +++ sizeof(struct ipq40xx_dsa_tag_data)); +++ +++ skb_shinfo(skb)->dsa_tag_proto = DSA_TAG_PROTO_IPQ4019; +++ tag_data = (struct ipq40xx_dsa_tag_data *)skb_shinfo(skb)->dsa_tag_data; +++ +++ tag_data->from_cpu = 1; +++ /* set the destination port information */ +++ tag_data->dp = BIT(dp->index); +++ +++ return skb; +++} +++ +++static struct sk_buff *ipq4019_sh_tag_rcv(struct sk_buff *skb, +++ struct net_device *dev, +++ struct packet_type *pt) +++{ +++ struct edma_rrd *rrd; +++ int offset; +++ int port; +++ +++ offset = EDMA_RRD_SIZE + ETH_HLEN; +++ if (unlikely(skb_headroom(skb) < offset)) +++ return NULL; +++ +++ rrd = (struct edma_rrd *)(skb->data - offset); +++ port = FIELD_GET(EDMA_RRD1_PORT_ID_MASK, rrd->rrd1); +++ +++ skb->dev = dsa_master_find_slave(dev, 0, port); +++ if (!skb->dev) +++ return NULL; +++ +++ return skb; +++} +++ +++const struct dsa_device_ops ipq4019_sh_tag_dsa_ops = { +++ .name = "ipq4019-sh", +++ .proto = DSA_TAG_PROTO_IPQ4019, +++ .xmit = ipq4019_sh_tag_xmit, +++ .rcv = ipq4019_sh_tag_rcv, +++}; +++ +++MODULE_LICENSE("GPL v2"); +++MODULE_DESCRIPTION("DSA tag driver for the IPQ4019 SoC built-in ethernet switch"); +++MODULE_AUTHOR("Gabor Juhos "); +++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_IPQ4019); +++ +++module_dsa_tag_driver(ipq4019_sh_tag_dsa_ops); +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch +@@ -0,0 +1,43 @@ ++From da75807ac41175e9db8c95f7a172b4133763b744 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 11 Jan 2021 17:49:36 +0100 ++Subject: [PATCH] skbuff: add DSA specific data to struct skb_shared_info ++ ++All of the already existing DSA tagging protocol drivers ++are storing the tagging data directly into the skb. In most ++cases that is the only way to send the required information ++to the underlying ethernet switch. ++ ++However on certain platforms (like the Qualcomm IPQ40xx ++SoCs) the built-in ethernet switch is connected directly ++to an ethernet MAC, and the tagging information must be ++sent out-of-band which is done directly via the hardware ++TX descriptors of the ethernet MAC. ++ ++In such cases, putting the information into the skb causes ++unneccesary overhead, because the ethernet driver must ++remove that before sending the ethernet frame towards to ++the hardware. ++ ++This change adds two new DSA specific fields to struct ++skb_shared_info which makes it possible to send the ++tagging information via skb->shinfo. With this approach, ++the twofold modifications of the skb data can be avoided. ++ ++Signed-off-by: Gabor Juhos ++--- ++ include/linux/skbuff.h | 3 +++ ++ 1 file changed, 3 insertions(+) ++ ++--- a/include/linux/skbuff.h +++++ b/include/linux/skbuff.h ++@@ -528,6 +528,9 @@ struct skb_shared_info { ++ unsigned int gso_type; ++ u32 tskey; ++ +++ unsigned int dsa_tag_proto; +++ unsigned char dsa_tag_data[8]; +++ ++ /* ++ * Warning : all fields before dataref are cleared in __alloc_skb() ++ */ +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch +@@ -0,0 +1,187 @@ ++From 29a0c2fae991cab142575c92276c0afdeb260ebe Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Thu, 28 Oct 2021 21:44:52 +0200 ++Subject: [PATCH] net: dsa: tag_ipq4019: add shinfo based tagging driver for ++ IPQ40xx ++ ++This change adds a tagging protocol driver for the built-in ++ethernet switch of the Qualcomm Atheros IPQ4019 SoCs. ++ ++In comparison to the existing tagging protocols this hardware ++requires a slightly different approach because the switch does ++not use in-band tags. ++ ++On the receive path, the source port information is embedded ++into the RX descriptors of the ethernet MAC hardware. Similarly, ++the destination port mask must be sent via the TX descriptors ++of the ethernet MAC when a packet is sent towards the switch. ++ ++In order to support this special requirements, this patch ++adds a new tagging protocol driver. ++ ++The driver extracts the source port information directly ++from the 'receive return descriptor' of the ethernet MAC. ++It is possible because that descriptor is part of the skb ++received from the ethernet driver. ++ ++Unfortunatley, it is not possible to put the destination ++port information directly to the TX descriptors, because ++those are handled internally by the driver of the ethernet ++hardware. ++ ++To overcome this limitation, this tagging driver uses the ++DSA specific fields in skb->shinfo to send the destination ++port information to the ethernet driver. ++ ++A similar tagging driver is exist but that uses skb ++extensions which causes unnecessary overhead. ++ ++Signed-off-by: Gabor Juhos ++--- ++ include/linux/dsa/ipq4019.h | 11 ++++++ ++ include/net/dsa.h | 2 + ++ net/dsa/Kconfig | 6 +++ ++ net/dsa/Makefile | 1 + ++ net/dsa/tag_ipq4019.c | 79 +++++++++++++++++++++++++++++++++++++ ++ 5 files changed, 99 insertions(+) ++ create mode 100644 include/linux/dsa/ipq4019.h ++ create mode 100644 net/dsa/tag_ipq4019.c ++ ++--- /dev/null +++++ b/include/linux/dsa/ipq4019.h ++@@ -0,0 +1,11 @@ +++/* SPDX-License-Identifier: GPL-2.0-only */ +++ +++#ifndef DSA_IPQ40XX_H +++#define DSA_IPQ40XX_H +++ +++struct ipq40xx_dsa_tag_data { +++ u8 from_cpu; +++ u8 dp; +++}; +++ +++#endif /* DSA_IPQ40XX_H */ ++--- a/include/net/dsa.h +++++ b/include/net/dsa.h ++@@ -51,6 +51,7 @@ struct phylink_link_state; ++ #define DSA_TAG_PROTO_SEVILLE_VALUE 21 ++ #define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 ++ #define DSA_TAG_PROTO_SJA1110_VALUE 23 +++#define DSA_TAG_PROTO_IPQ4019_VALUE 24 ++ ++ enum dsa_tag_protocol { ++ DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, ++@@ -77,6 +78,7 @@ enum dsa_tag_protocol { ++ DSA_TAG_PROTO_OCELOT_8021Q = DSA_TAG_PROTO_OCELOT_8021Q_VALUE, ++ DSA_TAG_PROTO_SEVILLE = DSA_TAG_PROTO_SEVILLE_VALUE, ++ DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE, +++ DSA_TAG_PROTO_IPQ4019 = DSA_TAG_PROTO_IPQ4019_VALUE, ++ }; ++ ++ struct dsa_switch; ++--- a/net/dsa/Kconfig +++++ b/net/dsa/Kconfig ++@@ -57,6 +57,12 @@ config NET_DSA_TAG_HELLCREEK ++ Say Y or M if you want to enable support for tagging frames ++ for the Hirschmann Hellcreek TSN switches. ++ +++config NET_DSA_TAG_IPQ4019 +++ tristate "Tag driver for Qualcomm Atheros IPQ4019 SoC built-in switch" +++ help +++ Say Y or M if you want to enable support for tagging frames for +++ the built-in switch of the Qualcomm Atheros IPQ4019 SoC-s. +++ ++ config NET_DSA_TAG_GSWIP ++ tristate "Tag driver for Lantiq / Intel GSWIP switches" ++ help ++--- a/net/dsa/Makefile +++++ b/net/dsa/Makefile ++@@ -8,6 +8,7 @@ obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_ ++ obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o ++ obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o ++ obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o +++obj-$(CONFIG_NET_DSA_TAG_IPQ4019) += tag_ipq4019.o ++ obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o ++ obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o ++ obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o ++--- /dev/null +++++ b/net/dsa/tag_ipq4019.c ++@@ -0,0 +1,78 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++ +++/* Copyright (c) 2021, Gabor Juhos */ +++ +++#include +++#include +++ +++#include "dsa_priv.h" +++ +++/* Receive Return Descriptor */ +++struct edma_rrd { +++ u16 rrd0; +++ u16 rrd1; +++ u16 rrd2; +++ u16 rrd3; +++ u16 rrd4; +++ u16 rrd5; +++ u16 rrd6; +++ u16 rrd7; +++} __packed; +++ +++#define EDMA_RRD_SIZE sizeof(struct edma_rrd) +++ +++#define EDMA_RRD1_PORT_ID_MASK GENMASK(14, 12) +++ +++static struct sk_buff *ipq4019_sh_tag_xmit(struct sk_buff *skb, +++ struct net_device *dev) +++{ +++ struct dsa_port *dp = dsa_slave_to_port(dev); +++ struct ipq40xx_dsa_tag_data *tag_data; +++ +++ BUILD_BUG_ON(sizeof_field(struct skb_shared_info, dsa_tag_data) < +++ sizeof(struct ipq40xx_dsa_tag_data)); +++ +++ skb_shinfo(skb)->dsa_tag_proto = DSA_TAG_PROTO_IPQ4019; +++ tag_data = (struct ipq40xx_dsa_tag_data *)skb_shinfo(skb)->dsa_tag_data; +++ +++ tag_data->from_cpu = 1; +++ /* set the destination port information */ +++ tag_data->dp = BIT(dp->index); +++ +++ return skb; +++} +++ +++static struct sk_buff *ipq4019_sh_tag_rcv(struct sk_buff *skb, +++ struct net_device *dev) +++{ +++ struct edma_rrd *rrd; +++ int offset; +++ int port; +++ +++ offset = EDMA_RRD_SIZE + ETH_HLEN; +++ if (unlikely(skb_headroom(skb) < offset)) +++ return NULL; +++ +++ rrd = (struct edma_rrd *)(skb->data - offset); +++ port = FIELD_GET(EDMA_RRD1_PORT_ID_MASK, rrd->rrd1); +++ +++ skb->dev = dsa_master_find_slave(dev, 0, port); +++ if (!skb->dev) +++ return NULL; +++ +++ return skb; +++} +++ +++const struct dsa_device_ops ipq4019_sh_tag_dsa_ops = { +++ .name = "ipq4019-sh", +++ .proto = DSA_TAG_PROTO_IPQ4019, +++ .xmit = ipq4019_sh_tag_xmit, +++ .rcv = ipq4019_sh_tag_rcv, +++}; +++ +++MODULE_LICENSE("GPL v2"); +++MODULE_DESCRIPTION("DSA tag driver for the IPQ4019 SoC built-in ethernet switch"); +++MODULE_AUTHOR("Gabor Juhos "); +++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_IPQ4019); +++ +++module_dsa_tag_driver(ipq4019_sh_tag_dsa_ops); + +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -121,7 +121,7 @@ + #define PSGMII_QSGMII_DRIVE_CONTROL_1 0xb + #define PSGMII_QSGMII_TX_DRIVER_MASK GENMASK(7, 4) + #define PSGMII_MODE_CTRL 0x6d +-#define PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK GENMASK(3, 0) ++#define PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK BIT(0) + #define PSGMII_MMD3_SERDES_CONTROL 0x805a + + struct qca807x_gpio_priv { +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -780,17 +780,14 @@ static int qca807x_probe(struct phy_device *phydev) + static int qca807x_psgmii_config(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; +- int psgmii_az, tx_amp, ret = 0; ++ int tx_amp, ret = 0; + u32 tx_driver_strength; + + /* Workaround to enable AZ transmitting ability */ +- if (of_property_read_bool(node, "qcom,psgmii-az")) { +- psgmii_az = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PSGMII_MODE_CTRL); +- psgmii_az &= ~PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK; +- psgmii_az |= FIELD_PREP(PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK, 0xc); +- ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PSGMII_MODE_CTRL, psgmii_az); +- psgmii_az = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PSGMII_MODE_CTRL); +- } ++ ret = phy_clear_bits_mmd(phydev, ++ MDIO_MMD_PMAPMD, ++ PSGMII_MODE_CTRL, ++ PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK); + + /* PSGMII/QSGMII TX amp set to DT defined value instead of default 600mV */ + if (!of_property_read_u32(node, "qcom,tx-driver-strength", &tx_driver_strength)) { +--- a/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch ++++ b/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch +@@ -56,7 +56,6 @@ Signed-off-by: Robert Marko + + reg = <5>; + + + + qcom,tx-driver-strength = ; +-+ qcom,psgmii-az; + }; + }; + +--- /dev/null ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/Makefile +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# Makefile for the IPQ ESS driver ++# ++ ++obj-$(CONFIG_QCOM_IPQ4019_ESS_EDMA) += ipq_ess.o ++ ++ipq_ess-objs := ipqess.o ipqess_ethtool.o +--- /dev/null ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -0,0 +1,1334 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR ISC) ++/* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 - 2018, John Crispin ++ * Copyright (c) 2018 - 2019, Christian Lamparter ++ * Copyright (c) 2020 - 2021, Gabor Juhos ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ipqess.h" ++ ++#define IPQESS_RRD_SIZE 16 ++#define IPQESS_NEXT_IDX(X, Y) (((X) + 1) & ((Y) - 1)) ++#define IPQESS_TX_DMA_BUF_LEN 0x3fff ++ ++static void ipqess_w32(struct ipqess *ess, u32 reg, u32 val) ++{ ++ writel(val, ess->hw_addr + reg); ++} ++ ++static u32 ipqess_r32(struct ipqess *ess, u16 reg) ++{ ++ return readl(ess->hw_addr + reg); ++} ++ ++static void ipqess_m32(struct ipqess *ess, u32 mask, u32 val, u16 reg) ++{ ++ u32 _val = ipqess_r32(ess, reg); ++ _val &= ~mask; ++ _val |= val; ++ ipqess_w32(ess, reg, _val); ++} ++ ++void ipqess_update_hw_stats(struct ipqess *ess) ++{ ++ uint32_t *p; ++ u32 stat; ++ int i; ++ ++ lockdep_assert_held(&ess->stats_lock); ++ ++ p = (uint32_t *)&(ess->ipqessstats); ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_TX_STAT_PKT_Q(i)); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_TX_STAT_BYTE_Q(i)); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_RX_STAT_PKT_Q(i)); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_RX_STAT_BYTE_Q(i)); ++ *p += stat; ++ p++; ++ } ++} ++ ++static int ipqess_tx_ring_alloc(struct ipqess *ess) ++{ ++ struct device *dev = &ess->pdev->dev; ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ struct ipqess_tx_ring *tx_ring = &ess->tx_ring[i]; ++ size_t size; ++ u32 idx; ++ ++ tx_ring->ess = ess; ++ tx_ring->ring_id = i; ++ tx_ring->idx = i * 4; ++ tx_ring->count = IPQESS_TX_RING_SIZE; ++ tx_ring->nq = netdev_get_tx_queue(ess->netdev, i); ++ ++ size = sizeof(struct ipqess_buf) * IPQESS_TX_RING_SIZE; ++ tx_ring->buf = devm_kzalloc(dev, size, GFP_KERNEL); ++ if (!tx_ring->buf) { ++ netdev_err(ess->netdev, "buffer alloc of tx ring failed"); ++ return -ENOMEM; ++ } ++ ++ size = sizeof(struct ipqess_tx_desc) * IPQESS_TX_RING_SIZE; ++ tx_ring->hw_desc = dmam_alloc_coherent(dev, size, &tx_ring->dma, ++ GFP_KERNEL | __GFP_ZERO); ++ if (!tx_ring->hw_desc) { ++ netdev_err(ess->netdev, "descriptor allocation for tx ring failed"); ++ return -ENOMEM; ++ } ++ ++ ipqess_w32(ess, IPQESS_REG_TPD_BASE_ADDR_Q(tx_ring->idx), ++ (u32)tx_ring->dma); ++ ++ idx = ipqess_r32(ess, IPQESS_REG_TPD_IDX_Q(tx_ring->idx)); ++ idx >>= IPQESS_TPD_CONS_IDX_SHIFT; /* need u32 here */ ++ idx &= 0xffff; ++ tx_ring->head = tx_ring->tail = idx; ++ ++ ipqess_m32(ess, IPQESS_TPD_PROD_IDX_MASK << IPQESS_TPD_PROD_IDX_SHIFT, ++ idx, IPQESS_REG_TPD_IDX_Q(tx_ring->idx)); ++ ipqess_w32(ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx), idx); ++ ipqess_w32(ess, IPQESS_REG_TPD_RING_SIZE, IPQESS_TX_RING_SIZE); ++ } ++ ++ return 0; ++} ++ ++static int ipqess_tx_unmap_and_free(struct device *dev, struct ipqess_buf *buf) ++{ ++ int len = 0; ++ ++ if (buf->flags & IPQESS_DESC_SINGLE) ++ dma_unmap_single(dev, buf->dma, buf->length, DMA_TO_DEVICE); ++ else if (buf->flags & IPQESS_DESC_PAGE) ++ dma_unmap_page(dev, buf->dma, buf->length, DMA_TO_DEVICE); ++ ++ if (buf->flags & IPQESS_DESC_LAST) { ++ len = buf->skb->len; ++ dev_kfree_skb_any(buf->skb); ++ } ++ ++ buf->flags = 0; ++ ++ return len; ++} ++ ++static void ipqess_tx_ring_free(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int j; ++ ++ if (ess->tx_ring[i].hw_desc) ++ continue; ++ ++ for (j = 0; j < IPQESS_TX_RING_SIZE; j++) { ++ struct ipqess_buf *buf = &ess->tx_ring[i].buf[j]; ++ ++ ipqess_tx_unmap_and_free(&ess->pdev->dev, buf); ++ } ++ ++ ess->tx_ring[i].buf = NULL; ++ } ++} ++ ++static int ipqess_rx_buf_prepare(struct ipqess_buf *buf, ++ struct ipqess_rx_ring *rx_ring) ++{ ++ /* Clean the HW DESC header, otherwise we might end up ++ * with a spurious desc because of random garbage */ ++ memset(buf->skb->data, 0, sizeof(struct ipqess_rx_desc)); ++ ++ buf->dma = dma_map_single(rx_ring->ppdev, buf->skb->data, ++ IPQESS_RX_HEAD_BUFF_SIZE, DMA_FROM_DEVICE); ++ if (dma_mapping_error(rx_ring->ppdev, buf->dma)) { ++ dev_err_once(rx_ring->ppdev, ++ "IPQESS DMA mapping failed for linear address %x", ++ buf->dma); ++ dev_kfree_skb_any(buf->skb); ++ buf->skb = NULL; ++ return -EFAULT; ++ } ++ ++ buf->length = IPQESS_RX_HEAD_BUFF_SIZE; ++ rx_ring->hw_desc[rx_ring->head] = (struct ipqess_rx_desc *)buf->dma; ++ rx_ring->head = (rx_ring->head + 1) % IPQESS_RX_RING_SIZE; ++ ++ ipqess_m32(rx_ring->ess, IPQESS_RFD_PROD_IDX_BITS, ++ (rx_ring->head + IPQESS_RX_RING_SIZE - 1) % IPQESS_RX_RING_SIZE, ++ IPQESS_REG_RFD_IDX_Q(rx_ring->idx)); ++ ++ return 0; ++} ++ ++/* locking is handled by the caller */ ++static int ipqess_rx_buf_alloc_napi(struct ipqess_rx_ring *rx_ring) ++{ ++ struct ipqess_buf *buf = &rx_ring->buf[rx_ring->head]; ++ ++ buf->skb = napi_alloc_skb(&rx_ring->napi_rx, ++ IPQESS_RX_HEAD_BUFF_SIZE); ++ if (!buf->skb) ++ return -ENOMEM; ++ ++ return ipqess_rx_buf_prepare(buf, rx_ring); ++} ++ ++static int ipqess_rx_buf_alloc(struct ipqess_rx_ring *rx_ring) ++{ ++ struct ipqess_buf *buf = &rx_ring->buf[rx_ring->head]; ++ ++ buf->skb = netdev_alloc_skb_ip_align(rx_ring->ess->netdev, ++ IPQESS_RX_HEAD_BUFF_SIZE); ++ if (!buf->skb) ++ return -ENOMEM; ++ ++ return ipqess_rx_buf_prepare(buf, rx_ring); ++} ++ ++static void ipqess_refill_work(struct work_struct *work) ++{ ++ struct ipqess_rx_ring_refill *rx_refill = container_of(work, ++ struct ipqess_rx_ring_refill, refill_work); ++ struct ipqess_rx_ring *rx_ring = rx_refill->rx_ring; ++ int refill = 0; ++ ++ /* don't let this loop by accident. */ ++ while (atomic_dec_and_test(&rx_ring->refill_count)) { ++ napi_disable(&rx_ring->napi_rx); ++ if (ipqess_rx_buf_alloc(rx_ring)) { ++ refill++; ++ dev_dbg(rx_ring->ppdev, ++ "Not all buffers were reallocated"); ++ } ++ napi_enable(&rx_ring->napi_rx); ++ } ++ ++ if (atomic_add_return(refill, &rx_ring->refill_count)) ++ schedule_work(&rx_refill->refill_work); ++} ++ ++ ++static int ipqess_rx_ring_alloc(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int j; ++ ++ ess->rx_ring[i].ess = ess; ++ ess->rx_ring[i].ppdev = &ess->pdev->dev; ++ ess->rx_ring[i].ring_id = i; ++ ess->rx_ring[i].idx = i * 2; ++ ++ ess->rx_ring[i].buf = devm_kzalloc(&ess->pdev->dev, ++ sizeof(struct ipqess_buf) * IPQESS_RX_RING_SIZE, ++ GFP_KERNEL); ++ if (!ess->rx_ring[i].buf) ++ return -ENOMEM; ++ ++ ess->rx_ring[i].hw_desc = dmam_alloc_coherent(&ess->pdev->dev, ++ sizeof(struct ipqess_rx_desc) * IPQESS_RX_RING_SIZE, ++ &ess->rx_ring[i].dma, GFP_KERNEL); ++ if (!ess->rx_ring[i].hw_desc) ++ return -ENOMEM; ++ ++ for (j = 0; j < IPQESS_RX_RING_SIZE; j++) ++ if (ipqess_rx_buf_alloc(&ess->rx_ring[i]) < 0) ++ return -ENOMEM; ++ ++ ess->rx_refill[i].rx_ring = &ess->rx_ring[i]; ++ INIT_WORK(&ess->rx_refill[i].refill_work, ipqess_refill_work); ++ ++ ipqess_w32(ess, IPQESS_REG_RFD_BASE_ADDR_Q(ess->rx_ring[i].idx), ++ (u32)(ess->rx_ring[i].dma)); ++ } ++ ++ ipqess_w32(ess, IPQESS_REG_RX_DESC0, ++ (IPQESS_RX_HEAD_BUFF_SIZE << IPQESS_RX_BUF_SIZE_SHIFT) | ++ (IPQESS_RX_RING_SIZE << IPQESS_RFD_RING_SIZE_SHIFT)); ++ ++ return 0; ++} ++ ++static void ipqess_rx_ring_free(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int j; ++ ++ atomic_set(&ess->rx_ring[i].refill_count, 0); ++ cancel_work_sync(&ess->rx_refill[i].refill_work); ++ ++ for (j = 0; j < IPQESS_RX_RING_SIZE; j++) { ++ dma_unmap_single(&ess->pdev->dev, ++ ess->rx_ring[i].buf[j].dma, ++ ess->rx_ring[i].buf[j].length, ++ DMA_FROM_DEVICE); ++ dev_kfree_skb_any(ess->rx_ring[i].buf[j].skb); ++ } ++ } ++} ++ ++static struct net_device_stats *ipqess_get_stats(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ spin_lock(&ess->stats_lock); ++ ipqess_update_hw_stats(ess); ++ spin_unlock(&ess->stats_lock); ++ ++ return &ess->stats; ++} ++ ++static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget) ++{ ++ u32 length = 0, num_desc, tail, rx_ring_tail; ++ int done = 0; ++ ++ rx_ring_tail = rx_ring->tail; ++ ++ tail = ipqess_r32(rx_ring->ess, IPQESS_REG_RFD_IDX_Q(rx_ring->idx)); ++ tail >>= IPQESS_RFD_CONS_IDX_SHIFT; ++ tail &= IPQESS_RFD_CONS_IDX_MASK; ++ ++ while (done < budget) { ++ struct sk_buff *skb; ++ struct ipqess_rx_desc *rd; ++ ++ if (rx_ring_tail == tail) ++ break; ++ ++ dma_unmap_single(rx_ring->ppdev, ++ rx_ring->buf[rx_ring_tail].dma, ++ rx_ring->buf[rx_ring_tail].length, ++ DMA_FROM_DEVICE); ++ ++ skb = xchg(&rx_ring->buf[rx_ring_tail].skb, NULL); ++ rd = (struct ipqess_rx_desc *)skb->data; ++ rx_ring_tail = IPQESS_NEXT_IDX(rx_ring_tail, IPQESS_RX_RING_SIZE); ++ ++ /* Check if RRD is valid */ ++ if (!(rd->rrd7 & IPQESS_RRD_DESC_VALID)) { ++ num_desc = 1; ++ dev_kfree_skb_any(skb); ++ goto skip; ++ } ++ ++ num_desc = rd->rrd1 & IPQESS_RRD_NUM_RFD_MASK; ++ length = rd->rrd6 & IPQESS_RRD_PKT_SIZE_MASK; ++ ++ skb_reserve(skb, IPQESS_RRD_SIZE); ++ if (num_desc > 1) { ++ /* can we use build_skb here ? */ ++ struct sk_buff *skb_prev = NULL; ++ int size_remaining; ++ int i; ++ ++ skb->data_len = 0; ++ skb->tail += (IPQESS_RX_HEAD_BUFF_SIZE - IPQESS_RRD_SIZE); ++ skb->len = skb->truesize = length; ++ size_remaining = length - (IPQESS_RX_HEAD_BUFF_SIZE - IPQESS_RRD_SIZE); ++ ++ for (i = 1; i < num_desc; i++) { ++ /* TODO: use build_skb ? */ ++ struct sk_buff *skb_temp = rx_ring->buf[rx_ring_tail].skb; ++ ++ dma_unmap_single(rx_ring->ppdev, ++ rx_ring->buf[rx_ring_tail].dma, ++ rx_ring->buf[rx_ring_tail].length, ++ DMA_FROM_DEVICE); ++ ++ skb_put(skb_temp, min(size_remaining, IPQESS_RX_HEAD_BUFF_SIZE)); ++ if (skb_prev) ++ skb_prev->next = rx_ring->buf[rx_ring_tail].skb; ++ else ++ skb_shinfo(skb)->frag_list = rx_ring->buf[rx_ring_tail].skb; ++ skb_prev = rx_ring->buf[rx_ring_tail].skb; ++ rx_ring->buf[rx_ring_tail].skb->next = NULL; ++ ++ skb->data_len += rx_ring->buf[rx_ring_tail].skb->len; ++ size_remaining -= rx_ring->buf[rx_ring_tail].skb->len; ++ ++ rx_ring_tail = IPQESS_NEXT_IDX(rx_ring_tail, IPQESS_RX_RING_SIZE); ++ } ++ ++ } else { ++ skb_put(skb, length); ++ } ++ ++ skb->dev = rx_ring->ess->netdev; ++ skb->protocol = eth_type_trans(skb, rx_ring->ess->netdev); ++ skb_record_rx_queue(skb, rx_ring->ring_id); ++ ++ if (rd->rrd6 & IPQESS_RRD_CSUM_FAIL_MASK) ++ skb_checksum_none_assert(skb); ++ else ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ if (rd->rrd7 & IPQESS_RRD_CVLAN) { ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rd->rrd4); ++ } else if (rd->rrd1 & IPQESS_RRD_SVLAN) { ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), rd->rrd4); ++ } ++ napi_gro_receive(&rx_ring->napi_rx, skb); ++ ++ /* TODO: do we need to have these here ? */ ++ rx_ring->ess->stats.rx_packets++; ++ rx_ring->ess->stats.rx_bytes += length; ++ ++ done++; ++skip: ++ ++ num_desc += atomic_xchg(&rx_ring->refill_count, 0); ++ while (num_desc) { ++ if (ipqess_rx_buf_alloc_napi(rx_ring)) { ++ num_desc = atomic_add_return(num_desc, ++ &rx_ring->refill_count); ++ if (num_desc >= ((4 * IPQESS_RX_RING_SIZE + 6) / 7)) ++ schedule_work(&rx_ring->ess->rx_refill[rx_ring->ring_id].refill_work); ++ break; ++ } ++ num_desc--; ++ } ++ } ++ ++ ipqess_w32(rx_ring->ess, IPQESS_REG_RX_SW_CONS_IDX_Q(rx_ring->idx), ++ rx_ring_tail); ++ rx_ring->tail = rx_ring_tail; ++ ++ return done; ++} ++ ++static int ipqess_tx_complete(struct ipqess_tx_ring *tx_ring, int budget) ++{ ++ u32 tail; ++ int done = 0; ++ int total = 0, ret; ++ ++ tail = ipqess_r32(tx_ring->ess, IPQESS_REG_TPD_IDX_Q(tx_ring->idx)); ++ tail >>= IPQESS_TPD_CONS_IDX_SHIFT; ++ tail &= IPQESS_TPD_CONS_IDX_MASK; ++ ++ while ((tx_ring->tail != tail) && (done < budget)) { ++ //pr_info("freeing txq:%d tail:%d tailbuf:%p\n", tx_ring->idx, tx_ring->tail, &tx_ring->buf[tx_ring->tail]); ++ ret = ipqess_tx_unmap_and_free(&tx_ring->ess->pdev->dev, ++ &tx_ring->buf[tx_ring->tail]); ++ tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count); ++ if (ret) { ++ total += ret; ++ done++; ++ } ++ } ++ ++ ipqess_w32(tx_ring->ess, ++ IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx), ++ tx_ring->tail); ++ ++ if (netif_tx_queue_stopped(tx_ring->nq)) { ++ netdev_dbg(tx_ring->ess->netdev, "waking up tx queue %d\n", ++ tx_ring->idx); ++ netif_tx_wake_queue(tx_ring->nq); ++ } ++ ++ netdev_tx_completed_queue(tx_ring->nq, done, total); ++ ++ return done; ++} ++ ++static int ipqess_tx_napi(struct napi_struct *napi, int budget) ++{ ++ struct ipqess_tx_ring *tx_ring = container_of(napi, struct ipqess_tx_ring, ++ napi_tx); ++ u32 tx_status; ++ int work_done = 0; ++ ++ tx_status = ipqess_r32(tx_ring->ess, IPQESS_REG_TX_ISR); ++ tx_status &= BIT(tx_ring->idx); ++ ++ work_done = ipqess_tx_complete(tx_ring, budget); ++ ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TX_ISR, tx_status); ++ ++ if (likely(work_done < budget)) { ++ if (napi_complete_done(napi, work_done)) ++ ipqess_w32(tx_ring->ess, ++ IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), 0x1); ++ } ++ ++ return work_done; ++} ++ ++static int ipqess_rx_napi(struct napi_struct *napi, int budget) ++{ ++ struct ipqess_rx_ring *rx_ring = container_of(napi, struct ipqess_rx_ring, ++ napi_rx); ++ struct ipqess *ess = rx_ring->ess; ++ int remain_budget = budget; ++ int rx_done; ++ u32 rx_mask = BIT(rx_ring->idx); ++ u32 status; ++ ++poll_again: ++ ipqess_w32(ess, IPQESS_REG_RX_ISR, rx_mask); ++ rx_done = ipqess_rx_poll(rx_ring, remain_budget); ++ ++ if (rx_done == remain_budget) ++ return budget; ++ ++ status = ipqess_r32(ess, IPQESS_REG_RX_ISR); ++ if (status & rx_mask) { ++ remain_budget -= rx_done; ++ goto poll_again; ++ } ++ ++ if (napi_complete_done(napi, rx_done + budget - remain_budget)) ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx), 0x1); ++ ++ return rx_done + budget - remain_budget; ++} ++ ++static irqreturn_t ipqess_interrupt_tx(int irq, void *priv) ++{ ++ struct ipqess_tx_ring *tx_ring = (struct ipqess_tx_ring *) priv; ++ ++ if (likely(napi_schedule_prep(&tx_ring->napi_tx))) { ++ __napi_schedule(&tx_ring->napi_tx); ++ ipqess_w32(tx_ring->ess, ++ IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), ++ 0x0); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t ipqess_interrupt_rx(int irq, void *priv) ++{ ++ struct ipqess_rx_ring *rx_ring = (struct ipqess_rx_ring *) priv; ++ ++ if (likely(napi_schedule_prep(&rx_ring->napi_rx))) { ++ __napi_schedule(&rx_ring->napi_rx); ++ ipqess_w32(rx_ring->ess, ++ IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx), ++ 0x0); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void ipqess_irq_enable(struct ipqess *ess) ++{ ++ int i; ++ ++ ipqess_w32(ess, IPQESS_REG_RX_ISR, 0xff); ++ ipqess_w32(ess, IPQESS_REG_TX_ISR, 0xffff); ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(ess->rx_ring[i].idx), 1); ++ ipqess_w32(ess, IPQESS_REG_TX_INT_MASK_Q(ess->tx_ring[i].idx), 1); ++ } ++} ++ ++static void ipqess_irq_disable(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(ess->rx_ring[i].idx), 0); ++ ipqess_w32(ess, IPQESS_REG_TX_INT_MASK_Q(ess->tx_ring[i].idx), 0); ++ } ++} ++ ++static int __init ipqess_init(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ struct device_node *of_node = ess->pdev->dev.of_node; ++ return phylink_of_phy_connect(ess->phylink, of_node, 0); ++} ++ ++static void ipqess_uninit(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ phylink_disconnect_phy(ess->phylink); ++} ++ ++static int ipqess_open(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ napi_enable(&ess->tx_ring[i].napi_tx); ++ napi_enable(&ess->rx_ring[i].napi_rx); ++ } ++ ipqess_irq_enable(ess); ++ phylink_start(ess->phylink); ++ netif_tx_start_all_queues(netdev); ++ ++ return 0; ++} ++ ++static int ipqess_stop(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ int i; ++ ++ netif_tx_stop_all_queues(netdev); ++ phylink_stop(ess->phylink); ++ ipqess_irq_disable(ess); ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ napi_disable(&ess->tx_ring[i].napi_tx); ++ napi_disable(&ess->rx_ring[i].napi_rx); ++ } ++ ++ return 0; ++} ++ ++static int ipqess_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ switch (cmd) { ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ return phylink_mii_ioctl(ess->phylink, ifr, cmd); ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++ ++static inline u16 ipqess_tx_desc_available(struct ipqess_tx_ring *tx_ring) ++{ ++ u16 count = 0; ++ ++ if (tx_ring->tail <= tx_ring->head) ++ count = IPQESS_TX_RING_SIZE; ++ ++ count += tx_ring->tail - tx_ring->head - 1; ++ ++ return count; ++} ++ ++static inline int ipqess_cal_txd_req(struct sk_buff *skb) ++{ ++ int tpds; ++ ++ /* one TPD for the header, and one for each fragments */ ++ tpds = 1 + skb_shinfo(skb)->nr_frags; ++ if (skb_is_gso(skb) && skb_is_gso_v6(skb)) { ++ /* for LSOv2 one extra TPD is needed */ ++ tpds++; ++ } ++ ++ return tpds; ++} ++ ++static struct ipqess_buf *ipqess_get_tx_buffer(struct ipqess_tx_ring *tx_ring, ++ struct ipqess_tx_desc *desc) ++{ ++ return &tx_ring->buf[desc - tx_ring->hw_desc]; ++} ++ ++static struct ipqess_tx_desc *ipqess_tx_desc_next(struct ipqess_tx_ring *tx_ring) ++{ ++ struct ipqess_tx_desc *desc; ++ ++ desc = &tx_ring->hw_desc[tx_ring->head]; ++ tx_ring->head = IPQESS_NEXT_IDX(tx_ring->head, tx_ring->count); ++ ++ return desc; ++} ++ ++static void ipqess_rollback_tx(struct ipqess *eth, ++ struct ipqess_tx_desc *first_desc, int ring_id) ++{ ++ struct ipqess_tx_ring *tx_ring = ð->tx_ring[ring_id]; ++ struct ipqess_buf *buf; ++ struct ipqess_tx_desc *desc = NULL; ++ u16 start_index, index; ++ ++ start_index = first_desc - tx_ring->hw_desc; ++ ++ index = start_index; ++ while (index != tx_ring->head) { ++ desc = &tx_ring->hw_desc[index]; ++ buf = &tx_ring->buf[index]; ++ ipqess_tx_unmap_and_free(ð->pdev->dev, buf); ++ memset(desc, 0, sizeof(struct ipqess_tx_desc)); ++ if (++index == tx_ring->count) ++ index = 0; ++ } ++ tx_ring->head = start_index; ++} ++ ++static bool ipqess_process_dsa_tag_sh(struct sk_buff *skb, u32 *word3) ++{ ++ struct skb_shared_info *shinfo = skb_shinfo(skb); ++ struct ipq40xx_dsa_tag_data *tag_data; ++ ++ if (shinfo->dsa_tag_proto != DSA_TAG_PROTO_IPQ4019) ++ return false; ++ ++ tag_data = (struct ipq40xx_dsa_tag_data *)shinfo->dsa_tag_data; ++ ++ pr_debug("SH tag @ %08x, dp:%02x from_cpu:%u\n", ++ (u32)tag_data, tag_data->dp, tag_data->from_cpu); ++ ++ *word3 |= tag_data->dp << IPQESS_TPD_PORT_BITMAP_SHIFT; ++ if (tag_data->from_cpu) ++ *word3 |= BIT(IPQESS_TPD_FROM_CPU_SHIFT); ++ ++ return true; ++} ++ ++static void ipqess_get_dp_info(struct ipqess *ess, struct sk_buff *skb, ++ u32 *word3) ++{ ++ if (netdev_uses_dsa(ess->netdev)) { ++ ++ if (ipqess_process_dsa_tag_sh(skb, word3)) ++ return; ++ } ++ ++ *word3 |= 0x3e << IPQESS_TPD_PORT_BITMAP_SHIFT; ++} ++ ++static int ipqess_tx_map_and_fill(struct ipqess_tx_ring *tx_ring, struct sk_buff *skb) ++{ ++ struct ipqess_buf *buf = NULL; ++ struct platform_device *pdev = tx_ring->ess->pdev; ++ struct ipqess_tx_desc *desc = NULL, *first_desc = NULL; ++ u32 word1 = 0, word3 = 0, lso_word1 = 0, svlan_tag = 0; ++ u16 len; ++ int i; ++ ++ ipqess_get_dp_info(tx_ring->ess, skb, &word3); ++ ++ if (skb_is_gso(skb)) { ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { ++ lso_word1 |= IPQESS_TPD_IPV4_EN; ++ ip_hdr(skb)->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, ++ ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); ++ } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { ++ lso_word1 |= IPQESS_TPD_LSO_V2_EN; ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); ++ } ++ ++ lso_word1 |= IPQESS_TPD_LSO_EN | ++ ((skb_shinfo(skb)->gso_size & IPQESS_TPD_MSS_MASK) << IPQESS_TPD_MSS_SHIFT) | ++ (skb_transport_offset(skb) << IPQESS_TPD_HDR_SHIFT); ++ } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ u8 css, cso; ++ cso = skb_checksum_start_offset(skb); ++ css = cso + skb->csum_offset; ++ ++ word1 |= (IPQESS_TPD_CUSTOM_CSUM_EN); ++ word1 |= (cso >> 1) << IPQESS_TPD_HDR_SHIFT; ++ word1 |= ((css >> 1) << IPQESS_TPD_CUSTOM_CSUM_SHIFT); ++ } ++ ++ if (skb_vlan_tag_present(skb)) { ++ switch (skb->vlan_proto) { ++ case htons(ETH_P_8021Q): ++ word3 |= BIT(IPQESS_TX_INS_CVLAN); ++ word3 |= skb_vlan_tag_get(skb) << IPQESS_TX_CVLAN_TAG_SHIFT; ++ break; ++ case htons(ETH_P_8021AD): ++ word1 |= BIT(IPQESS_TX_INS_SVLAN); ++ svlan_tag = skb_vlan_tag_get(skb); ++ break; ++ default: ++ dev_err(&pdev->dev, "no ctag or stag present\n"); ++ goto vlan_tag_error; ++ } ++ } ++ ++ if (eth_type_vlan(skb->protocol)) ++ word1 |= IPQESS_TPD_VLAN_TAGGED; ++ ++ if (skb->protocol == htons(ETH_P_PPP_SES)) ++ word1 |= IPQESS_TPD_PPPOE_EN; ++ ++ len = skb_headlen(skb); ++ ++ first_desc = desc = ipqess_tx_desc_next(tx_ring); ++ if (lso_word1 & IPQESS_TPD_LSO_V2_EN) { ++ desc->addr = cpu_to_le16(skb->len); ++ desc->word1 = word1 | lso_word1; ++ desc->svlan_tag = svlan_tag; ++ desc->word3 = word3; ++ desc = ipqess_tx_desc_next(tx_ring); ++ } ++ ++ buf = ipqess_get_tx_buffer(tx_ring, desc); ++ buf->length = len; ++ buf->dma = dma_map_single(&pdev->dev, ++ skb->data, len, DMA_TO_DEVICE); ++ if (dma_mapping_error(&pdev->dev, buf->dma)) ++ goto dma_error; ++ ++ desc->addr = cpu_to_le32(buf->dma); ++ desc->len = cpu_to_le16(len); ++ ++ buf->flags |= IPQESS_DESC_SINGLE; ++ desc->word1 = word1 | lso_word1; ++ desc->svlan_tag = svlan_tag; ++ desc->word3 = word3; ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ len = skb_frag_size(frag); ++ desc = ipqess_tx_desc_next(tx_ring); ++ buf = ipqess_get_tx_buffer(tx_ring, desc); ++ buf->length = len; ++ buf->flags |= IPQESS_DESC_PAGE; ++ buf->dma = skb_frag_dma_map(&pdev->dev, frag, 0, len, DMA_TO_DEVICE); ++ if (dma_mapping_error(&pdev->dev, buf->dma)) ++ goto dma_error; ++ ++ desc->addr = cpu_to_le32(buf->dma); ++ desc->len = cpu_to_le16(len); ++ desc->svlan_tag = svlan_tag; ++ desc->word1 = word1 | lso_word1; ++ desc->word3 = word3; ++ } ++ desc->word1 |= 1 << IPQESS_TPD_EOP_SHIFT; ++ buf->skb = skb; ++ buf->flags |= IPQESS_DESC_LAST; ++ ++ return 0; ++ ++dma_error: ++ ipqess_rollback_tx(tx_ring->ess, first_desc, tx_ring->ring_id); ++ dev_err(&pdev->dev, "TX DMA map failed\n"); ++ ++vlan_tag_error: ++ return -ENOMEM; ++} ++ ++static inline void ipqess_kick_tx(struct ipqess_tx_ring *tx_ring) ++{ ++ /* Ensure that all TPDs has been written completely */ ++ dma_wmb(); ++ ++ /* update software producer index */ ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TPD_IDX_Q(tx_ring->idx), ++ tx_ring->head); ++} ++ ++static netdev_tx_t ipqess_xmit(struct sk_buff *skb, ++ struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ struct ipqess_tx_ring *tx_ring; ++ int avail; ++ int tx_num; ++ int ret; ++ ++ tx_ring = &ess->tx_ring[skb_get_queue_mapping(skb)]; ++ tx_num = ipqess_cal_txd_req(skb); ++ avail = ipqess_tx_desc_available(tx_ring); ++ if (avail < tx_num) { ++ netdev_dbg(netdev, ++ "stopping tx queue %d, avail=%d req=%d im=%x\n", ++ tx_ring->idx, avail, tx_num, ++ ipqess_r32(tx_ring->ess, ++ IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx))); ++ netif_tx_stop_queue(tx_ring->nq); ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), 0x1); ++ ipqess_kick_tx(tx_ring); ++ return NETDEV_TX_BUSY; ++ } ++ ++ ret = ipqess_tx_map_and_fill(tx_ring, skb); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ ess->stats.tx_errors++; ++ goto err_out; ++ } ++ ++ ess->stats.tx_packets++; ++ ess->stats.tx_bytes += skb->len; ++ netdev_tx_sent_queue(tx_ring->nq, skb->len); ++ ++ if (!netdev_xmit_more() || netif_xmit_stopped(tx_ring->nq)) ++ ipqess_kick_tx(tx_ring); ++ ++err_out: ++ return NETDEV_TX_OK; ++} ++ ++static int ipqess_set_mac_address(struct net_device *netdev, void *p) ++{ ++ int ret = eth_mac_addr(netdev, p); ++ struct ipqess *ess = netdev_priv(netdev); ++ const char *macaddr = netdev->dev_addr; ++ ++ if (ret) ++ return ret; ++ ++// spin_lock_bh(&mac->hw->page_lock); ++ ipqess_w32(ess, IPQESS_REG_MAC_CTRL1, ++ (macaddr[0] << 8) | macaddr[1]); ++ ipqess_w32(ess, IPQESS_REG_MAC_CTRL0, ++ (macaddr[2] << 24) | (macaddr[3] << 16) | ++ (macaddr[4] << 8) | macaddr[5]); ++// spin_unlock_bh(&mac->hw->page_lock); ++ ++ return 0; ++} ++ ++static void ipqess_tx_timeout(struct net_device *netdev, unsigned int txq_id) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ struct ipqess_tx_ring *tr = &ess->tx_ring[txq_id]; ++ ++ netdev_warn(netdev, "hardware queue %d is in stuck?\n", ++ tr->idx); ++ ++ /* TODO: dump hardware queue */ ++} ++ ++static const struct net_device_ops ipqess_axi_netdev_ops = { ++ .ndo_init = ipqess_init, ++ .ndo_uninit = ipqess_uninit, ++ .ndo_open = ipqess_open, ++ .ndo_stop = ipqess_stop, ++ .ndo_do_ioctl = ipqess_do_ioctl, ++ .ndo_start_xmit = ipqess_xmit, ++ .ndo_get_stats = ipqess_get_stats, ++ .ndo_set_mac_address = ipqess_set_mac_address, ++ .ndo_tx_timeout = ipqess_tx_timeout, ++}; ++ ++static void ipqess_hw_stop(struct ipqess *ess) ++{ ++ int i; ++ ++ /* disable all RX queue IRQs */ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(i), 0); ++ ++ /* disable all TX queue IRQs */ ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) ++ ipqess_w32(ess, IPQESS_REG_TX_INT_MASK_Q(i), 0); ++ ++ /* disable all other IRQs */ ++ ipqess_w32(ess, IPQESS_REG_MISC_IMR, 0); ++ ipqess_w32(ess, IPQESS_REG_WOL_IMR, 0); ++ ++ /* clear the IRQ status registers */ ++ ipqess_w32(ess, IPQESS_REG_RX_ISR, 0xff); ++ ipqess_w32(ess, IPQESS_REG_TX_ISR, 0xffff); ++ ipqess_w32(ess, IPQESS_REG_MISC_ISR, 0x1fff); ++ ipqess_w32(ess, IPQESS_REG_WOL_ISR, 0x1); ++ ipqess_w32(ess, IPQESS_REG_WOL_CTRL, 0); ++ ++ /* disable RX and TX queues */ ++ ipqess_m32(ess, IPQESS_RXQ_CTRL_EN_MASK, 0, IPQESS_REG_RXQ_CTRL); ++ ipqess_m32(ess, IPQESS_TXQ_CTRL_TXQ_EN, 0, IPQESS_REG_TXQ_CTRL); ++} ++ ++static int ipqess_hw_init(struct ipqess *ess) ++{ ++ u32 tmp; ++ int i, err; ++ ++ ipqess_hw_stop(ess); ++ ++ ipqess_m32(ess, BIT(IPQESS_INTR_SW_IDX_W_TYP_SHIFT), ++ IPQESS_INTR_SW_IDX_W_TYPE << IPQESS_INTR_SW_IDX_W_TYP_SHIFT, ++ IPQESS_REG_INTR_CTRL); ++ ++ /* enable IRQ delay slot */ ++ ipqess_w32(ess, IPQESS_REG_IRQ_MODRT_TIMER_INIT, ++ (IPQESS_TX_IMT << IPQESS_IRQ_MODRT_TX_TIMER_SHIFT) | ++ (IPQESS_RX_IMT << IPQESS_IRQ_MODRT_RX_TIMER_SHIFT)); ++ ++ /* Set Customer and Service VLAN TPIDs */ ++ ipqess_w32(ess, IPQESS_REG_VLAN_CFG, ++ (ETH_P_8021Q << IPQESS_VLAN_CFG_CVLAN_TPID_SHIFT) | ++ (ETH_P_8021AD << IPQESS_VLAN_CFG_SVLAN_TPID_SHIFT)); ++ ++ /* Configure the TX Queue bursting */ ++ ipqess_w32(ess, IPQESS_REG_TXQ_CTRL, ++ (IPQESS_TPD_BURST << IPQESS_TXQ_NUM_TPD_BURST_SHIFT) | ++ (IPQESS_TXF_BURST << IPQESS_TXQ_TXF_BURST_NUM_SHIFT) | ++ IPQESS_TXQ_CTRL_TPD_BURST_EN); ++ ++ /* Set RSS type */ ++ ipqess_w32(ess, IPQESS_REG_RSS_TYPE, ++ IPQESS_RSS_TYPE_IPV4TCP | IPQESS_RSS_TYPE_IPV6_TCP | ++ IPQESS_RSS_TYPE_IPV4_UDP | IPQESS_RSS_TYPE_IPV6UDP | ++ IPQESS_RSS_TYPE_IPV4 | IPQESS_RSS_TYPE_IPV6); ++ ++ /* Set RFD ring burst and threshold */ ++ ipqess_w32(ess, IPQESS_REG_RX_DESC1, ++ (IPQESS_RFD_BURST << IPQESS_RXQ_RFD_BURST_NUM_SHIFT) | ++ (IPQESS_RFD_THR << IPQESS_RXQ_RFD_PF_THRESH_SHIFT) | ++ (IPQESS_RFD_LTHR << IPQESS_RXQ_RFD_LOW_THRESH_SHIFT)); ++ ++ /* Set Rx FIFO ++ * - threshold to start to DMA data to host ++ */ ++ ipqess_w32(ess, IPQESS_REG_RXQ_CTRL, ++ IPQESS_FIFO_THRESH_128_BYTE | IPQESS_RXQ_CTRL_RMV_VLAN); ++ ++ err = ipqess_rx_ring_alloc(ess); ++ if (err) ++ return err; ++ ++ err = ipqess_tx_ring_alloc(ess); ++ if (err) ++ return err; ++ ++ /* Load all of ring base addresses above into the dma engine */ ++ ipqess_m32(ess, 0, BIT(IPQESS_LOAD_PTR_SHIFT), ++ IPQESS_REG_TX_SRAM_PART); ++ ++ /* Disable TX FIFO low watermark and high watermark */ ++ ipqess_w32(ess, IPQESS_REG_TXF_WATER_MARK, 0); ++ ++ /* Configure RSS indirection table. ++ * 128 hash will be configured in the following ++ * pattern: hash{0,1,2,3} = {Q0,Q2,Q4,Q6} respectively ++ * and so on ++ */ ++ for (i = 0; i < IPQESS_NUM_IDT; i++) ++ ipqess_w32(ess, IPQESS_REG_RSS_IDT(i), IPQESS_RSS_IDT_VALUE); ++ ++ /* Configure load balance mapping table. ++ * 4 table entry will be configured according to the ++ * following pattern: load_balance{0,1,2,3} = {Q0,Q1,Q3,Q4} ++ * respectively. ++ */ ++ ipqess_w32(ess, IPQESS_REG_LB_RING, IPQESS_LB_REG_VALUE); ++ ++ /* Configure Virtual queue for Tx rings */ ++ ipqess_w32(ess, IPQESS_REG_VQ_CTRL0, IPQESS_VQ_REG_VALUE); ++ ipqess_w32(ess, IPQESS_REG_VQ_CTRL1, IPQESS_VQ_REG_VALUE); ++ ++ /* Configure Max AXI Burst write size to 128 bytes*/ ++ ipqess_w32(ess, IPQESS_REG_AXIW_CTRL_MAXWRSIZE, ++ IPQESS_AXIW_MAXWRSIZE_VALUE); ++ ++ /* Enable TX queues */ ++ ipqess_m32(ess, 0, IPQESS_TXQ_CTRL_TXQ_EN, IPQESS_REG_TXQ_CTRL); ++ ++ /* Enable RX queues */ ++ tmp = 0; ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) ++ tmp |= IPQESS_RXQ_CTRL_EN(ess->rx_ring[i].idx); ++ ++ ipqess_m32(ess, IPQESS_RXQ_CTRL_EN_MASK, tmp, IPQESS_REG_RXQ_CTRL); ++ ++ return 0; ++} ++ ++static void ipqess_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ struct ipqess *ess = container_of(config, struct ipqess, phylink_config); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; ++ ++ if (state->interface != PHY_INTERFACE_MODE_INTERNAL) { ++ dev_err(&ess->pdev->dev, "unsupported interface mode: %d\n", ++ state->interface); ++ linkmode_zero(supported); ++ return; ++ } ++ ++ phylink_set_port_modes(mask); ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, Pause); ++ phylink_set(mask, Asym_Pause); ++ ++ linkmode_and(supported, supported, mask); ++ linkmode_and(state->advertising, state->advertising, mask); ++} ++ ++static void ipqess_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ /* TODO */ ++} ++ ++static void ipqess_mac_link_down(struct phylink_config *config, ++ unsigned int mode, ++ phy_interface_t interface) ++{ ++ /* TODO */ ++} ++ ++static void ipqess_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, unsigned int mode, ++ phy_interface_t interface, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) ++{ ++ /* TODO */ ++} ++ ++static struct phylink_mac_ops ipqess_phylink_mac_ops = { ++ .validate = ipqess_validate, ++ .mac_config = ipqess_mac_config, ++ .mac_link_up = ipqess_mac_link_up, ++ .mac_link_down = ipqess_mac_link_down, ++}; ++ ++static void ipqess_cleanup(struct ipqess *ess) ++{ ++ ipqess_hw_stop(ess); ++ unregister_netdev(ess->netdev); ++ ++ ipqess_tx_ring_free(ess); ++ ipqess_rx_ring_free(ess); ++ ++ if (!IS_ERR_OR_NULL(ess->phylink)) ++ phylink_destroy(ess->phylink); ++} ++ ++static void ess_reset(struct ipqess *ess) ++{ ++ reset_control_assert(ess->ess_rst); ++ ++ mdelay(10); ++ ++ reset_control_deassert(ess->ess_rst); ++ ++ /* Waiting for all inner tables to be flushed and reinitialized. ++ * This takes between 5 and 10ms. ++ */ ++ mdelay(10); ++} ++ ++static int ipqess_axi_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct ipqess *ess; ++ struct net_device *netdev; ++ struct resource *res; ++ int i, err = 0; ++ ++ netdev = devm_alloc_etherdev_mqs(&pdev->dev, sizeof(struct ipqess), ++ IPQESS_NETDEV_QUEUES, ++ IPQESS_NETDEV_QUEUES); ++ if (!netdev) ++ return -ENOMEM; ++ ++ ess = netdev_priv(netdev); ++ ess->netdev = netdev; ++ ess->pdev = pdev; ++ spin_lock_init(&ess->stats_lock); ++ SET_NETDEV_DEV(netdev, &pdev->dev); ++ platform_set_drvdata(pdev, netdev); ++ ++ err = of_get_mac_address(np, netdev->dev_addr); ++ if (err == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ if (err) { ++ ++ random_ether_addr(netdev->dev_addr); ++ dev_info(&ess->pdev->dev, "generated random MAC address %pM\n", ++ netdev->dev_addr); ++ netdev->addr_assign_type = NET_ADDR_RANDOM; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ess->hw_addr = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(ess->hw_addr)) { ++ err = PTR_ERR(ess->hw_addr); ++ goto err_out; ++ } ++ ++ ess->ess_clk = of_clk_get_by_name(np, "ess_clk"); ++ if (IS_ERR(ess->ess_clk)) { ++ dev_err(&pdev->dev, "Failed to get ess_clk\n"); ++ return PTR_ERR(ess->ess_clk); ++ } ++ ++ ess->ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); ++ if (IS_ERR(ess->ess_rst)) { ++ dev_err(&pdev->dev, "Failed to get ess_rst control!\n"); ++ return PTR_ERR(ess->ess_rst); ++ } ++ ++ clk_prepare_enable(ess->ess_clk); ++ ++ ess_reset(ess); ++ ++ ess->phylink_config.dev = &netdev->dev; ++ ess->phylink_config.type = PHYLINK_NETDEV; ++ ess->phylink_config.pcs_poll = true; ++ ++ ess->phylink = phylink_create(&ess->phylink_config, ++ of_fwnode_handle(np), ++ PHY_INTERFACE_MODE_INTERNAL, ++ &ipqess_phylink_mac_ops); ++ if (IS_ERR(ess->phylink)) { ++ err = PTR_ERR(ess->phylink); ++ goto err_out; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) { ++ ess->tx_irq[i] = platform_get_irq(pdev, i); ++ scnprintf(ess->tx_irq_names[i], sizeof(ess->tx_irq_names[i]), ++ "%s:txq%d", pdev->name, i); ++ } ++ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) { ++ ess->rx_irq[i] = platform_get_irq(pdev, i + IPQESS_MAX_TX_QUEUE); ++ scnprintf(ess->rx_irq_names[i], sizeof(ess->rx_irq_names[i]), ++ "%s:rxq%d", pdev->name, i); ++ } ++ ++#undef NETIF_F_TSO6 ++#define NETIF_F_TSO6 0 ++ ++ netdev->netdev_ops = &ipqess_axi_netdev_ops; ++ netdev->features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | ++ NETIF_F_HW_VLAN_CTAG_RX | ++ NETIF_F_HW_VLAN_CTAG_TX | ++ NETIF_F_TSO | NETIF_F_TSO6 | ++ NETIF_F_GRO | NETIF_F_SG; ++ /* feature change is not supported yet */ ++ netdev->hw_features = 0; ++ netdev->vlan_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_RXCSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | ++ NETIF_F_GRO; ++ netdev->watchdog_timeo = 5 * HZ; ++ netdev->base_addr = (u32) ess->hw_addr; ++ netdev->max_mtu = 9000; ++ netdev->gso_max_segs = IPQESS_TX_RING_SIZE / 2; ++ ++ ipqess_set_ethtool_ops(netdev); ++ ++ err = register_netdev(netdev); ++ if (err) ++ goto err_out; ++ ++ err = ipqess_hw_init(ess); ++ if (err) ++ goto err_out; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int qid; ++ ++ netif_tx_napi_add(netdev, &ess->tx_ring[i].napi_tx, ++ ipqess_tx_napi, 64); ++ netif_napi_add(netdev, ++ &ess->rx_ring[i].napi_rx, ++ ipqess_rx_napi, 64); ++ ++ qid = ess->tx_ring[i].idx; ++ err = devm_request_irq(&ess->netdev->dev, ess->tx_irq[qid], ++ ipqess_interrupt_tx, 0, ess->tx_irq_names[qid], ++ &ess->tx_ring[i]); ++ if (err) ++ goto err_out; ++ ++ qid = ess->rx_ring[i].idx; ++ err = devm_request_irq(&ess->netdev->dev, ess->rx_irq[qid], ++ ipqess_interrupt_rx, 0, ess->rx_irq_names[qid], ++ &ess->rx_ring[i]); ++ if (err) ++ goto err_out; ++ } ++ ++ return 0; ++ ++err_out: ++ ipqess_cleanup(ess); ++ return err; ++} ++ ++static int ipqess_axi_remove(struct platform_device *pdev) ++{ ++ const struct net_device *netdev = platform_get_drvdata(pdev); ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ ipqess_cleanup(ess); ++ ++ return 0; ++} ++ ++static const struct of_device_id ipqess_of_mtable[] = { ++ {.compatible = "qcom,ipq4019-ess-edma" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, ipqess_of_mtable); ++ ++static struct platform_driver ipqess_axi_driver = { ++ .driver = { ++ .name = "ipqess-edma", ++ .of_match_table = ipqess_of_mtable, ++ }, ++ .probe = ipqess_axi_probe, ++ .remove = ipqess_axi_remove, ++}; ++ ++module_platform_driver(ipqess_axi_driver); ++ ++MODULE_AUTHOR("Qualcomm Atheros Inc"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_AUTHOR("Christian Lamparter "); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.h +@@ -0,0 +1,530 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR ISC) ++/* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 - 2018, John Crispin ++ * Copyright (c) 2018 - 2019, Christian Lamparter ++ * Copyright (c) 2020 - 2021, Gabor Juhos ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _IPQESS_H_ ++#define _IPQESS_H_ ++ ++#define IPQESS_NETDEV_QUEUES 4 ++ ++#define IPQESS_TPD_EOP_SHIFT 31 ++ ++#define IPQESS_PORT_ID_SHIFT 12 ++#define IPQESS_PORT_ID_MASK 0x7 ++ ++/* tpd word 3 bit 18-28 */ ++#define IPQESS_TPD_PORT_BITMAP_SHIFT 18 ++ ++#define IPQESS_TPD_FROM_CPU_SHIFT 25 ++ ++#define IPQESS_RX_RING_SIZE 128 ++#define IPQESS_RX_HEAD_BUFF_SIZE 1540 ++#define IPQESS_TX_RING_SIZE 128 ++#define IPQESS_MAX_RX_QUEUE 8 ++#define IPQESS_MAX_TX_QUEUE 16 ++ ++ ++/* Configurations */ ++#define IPQESS_INTR_CLEAR_TYPE 0 ++#define IPQESS_INTR_SW_IDX_W_TYPE 0 ++#define IPQESS_FIFO_THRESH_TYPE 0 ++#define IPQESS_RSS_TYPE 0 ++#define IPQESS_RX_IMT 0x0020 ++#define IPQESS_TX_IMT 0x0050 ++#define IPQESS_TPD_BURST 5 ++#define IPQESS_TXF_BURST 0x100 ++#define IPQESS_RFD_BURST 8 ++#define IPQESS_RFD_THR 16 ++#define IPQESS_RFD_LTHR 0 ++ ++/* Flags used in transmit direction */ ++#define IPQESS_DESC_LAST 0x1 ++#define IPQESS_DESC_SINGLE 0x2 ++#define IPQESS_DESC_PAGE 0x4 ++ ++struct ipqesstool_statistics { ++ u32 tx_q0_pkt; ++ u32 tx_q1_pkt; ++ u32 tx_q2_pkt; ++ u32 tx_q3_pkt; ++ u32 tx_q4_pkt; ++ u32 tx_q5_pkt; ++ u32 tx_q6_pkt; ++ u32 tx_q7_pkt; ++ u32 tx_q8_pkt; ++ u32 tx_q9_pkt; ++ u32 tx_q10_pkt; ++ u32 tx_q11_pkt; ++ u32 tx_q12_pkt; ++ u32 tx_q13_pkt; ++ u32 tx_q14_pkt; ++ u32 tx_q15_pkt; ++ u32 tx_q0_byte; ++ u32 tx_q1_byte; ++ u32 tx_q2_byte; ++ u32 tx_q3_byte; ++ u32 tx_q4_byte; ++ u32 tx_q5_byte; ++ u32 tx_q6_byte; ++ u32 tx_q7_byte; ++ u32 tx_q8_byte; ++ u32 tx_q9_byte; ++ u32 tx_q10_byte; ++ u32 tx_q11_byte; ++ u32 tx_q12_byte; ++ u32 tx_q13_byte; ++ u32 tx_q14_byte; ++ u32 tx_q15_byte; ++ u32 rx_q0_pkt; ++ u32 rx_q1_pkt; ++ u32 rx_q2_pkt; ++ u32 rx_q3_pkt; ++ u32 rx_q4_pkt; ++ u32 rx_q5_pkt; ++ u32 rx_q6_pkt; ++ u32 rx_q7_pkt; ++ u32 rx_q0_byte; ++ u32 rx_q1_byte; ++ u32 rx_q2_byte; ++ u32 rx_q3_byte; ++ u32 rx_q4_byte; ++ u32 rx_q5_byte; ++ u32 rx_q6_byte; ++ u32 rx_q7_byte; ++ u32 tx_desc_error; ++}; ++ ++struct ipqess_tx_desc { ++ __le16 len; ++ __le16 svlan_tag; ++ __le32 word1; ++ __le32 addr; ++ __le32 word3; ++} __aligned(16) __packed; ++ ++struct ipqess_rx_desc { ++ u16 rrd0; ++ u16 rrd1; ++ u16 rrd2; ++ u16 rrd3; ++ u16 rrd4; ++ u16 rrd5; ++ u16 rrd6; ++ u16 rrd7; ++} __aligned(16) __packed; ++ ++struct ipqess_buf { ++ struct sk_buff *skb; ++ dma_addr_t dma; ++ u32 flags; ++ u16 length; ++}; ++ ++struct ipqess_tx_ring { ++ struct napi_struct napi_tx; ++ u32 idx; ++ int ring_id; ++ struct ipqess *ess; ++ struct netdev_queue *nq; ++ struct ipqess_tx_desc *hw_desc; ++ struct ipqess_buf *buf; ++ dma_addr_t dma; ++ u16 count; ++ u16 head; ++ u16 tail; ++}; ++ ++struct ipqess_rx_ring { ++ struct napi_struct napi_rx; ++ u32 idx; ++ int ring_id; ++ struct ipqess *ess; ++ struct device *ppdev; ++ struct ipqess_rx_desc **hw_desc; ++ struct ipqess_buf *buf; ++ dma_addr_t dma; ++ u16 head; ++ u16 tail; ++ atomic_t refill_count; ++}; ++ ++struct ipqess_rx_ring_refill { ++ struct ipqess_rx_ring *rx_ring; ++ struct work_struct refill_work; ++}; ++ ++#define IPQESS_IRQ_NAME_LEN 32 ++ ++struct ipqess { ++ struct net_device *netdev; ++ void __iomem *hw_addr; ++ struct clk *ess_clk; ++ struct reset_control *ess_rst; ++ ++ struct ipqess_rx_ring rx_ring[IPQESS_NETDEV_QUEUES]; ++ ++ struct platform_device *pdev; ++ struct phylink *phylink; ++ struct phylink_config phylink_config; ++ struct ipqess_tx_ring tx_ring[IPQESS_NETDEV_QUEUES]; ++ ++ struct ipqesstool_statistics ipqessstats; ++ spinlock_t stats_lock; ++ struct net_device_stats stats; ++ ++ struct ipqess_rx_ring_refill rx_refill[IPQESS_NETDEV_QUEUES]; ++ u32 tx_irq[IPQESS_MAX_TX_QUEUE]; ++ char tx_irq_names[IPQESS_MAX_TX_QUEUE][IPQESS_IRQ_NAME_LEN]; ++ u32 rx_irq[IPQESS_MAX_RX_QUEUE]; ++ char rx_irq_names[IPQESS_MAX_TX_QUEUE][IPQESS_IRQ_NAME_LEN]; ++}; ++ ++static inline void build_test(void) ++{ ++ struct ipqess *ess; ++ BUILD_BUG_ON(ARRAY_SIZE(ess->rx_ring) != ARRAY_SIZE(ess->rx_refill)); ++} ++ ++void ipqess_set_ethtool_ops(struct net_device *netdev); ++void ipqess_update_hw_stats(struct ipqess *ess); ++ ++/* register definition */ ++#define IPQESS_REG_MAS_CTRL 0x0 ++#define IPQESS_REG_TIMEOUT_CTRL 0x004 ++#define IPQESS_REG_DBG0 0x008 ++#define IPQESS_REG_DBG1 0x00C ++#define IPQESS_REG_SW_CTRL0 0x100 ++#define IPQESS_REG_SW_CTRL1 0x104 ++ ++/* Interrupt Status Register */ ++#define IPQESS_REG_RX_ISR 0x200 ++#define IPQESS_REG_TX_ISR 0x208 ++#define IPQESS_REG_MISC_ISR 0x210 ++#define IPQESS_REG_WOL_ISR 0x218 ++ ++#define IPQESS_MISC_ISR_RX_URG_Q(x) (1 << x) ++ ++#define IPQESS_MISC_ISR_AXIR_TIMEOUT 0x00000100 ++#define IPQESS_MISC_ISR_AXIR_ERR 0x00000200 ++#define IPQESS_MISC_ISR_TXF_DEAD 0x00000400 ++#define IPQESS_MISC_ISR_AXIW_ERR 0x00000800 ++#define IPQESS_MISC_ISR_AXIW_TIMEOUT 0x00001000 ++ ++#define IPQESS_WOL_ISR 0x00000001 ++ ++/* Interrupt Mask Register */ ++#define IPQESS_REG_MISC_IMR 0x214 ++#define IPQESS_REG_WOL_IMR 0x218 ++ ++#define IPQESS_RX_IMR_NORMAL_MASK 0x1 ++#define IPQESS_TX_IMR_NORMAL_MASK 0x1 ++#define IPQESS_MISC_IMR_NORMAL_MASK 0x80001FFF ++#define IPQESS_WOL_IMR_NORMAL_MASK 0x1 ++ ++/* Edma receive consumer index */ ++#define IPQESS_REG_RX_SW_CONS_IDX_Q(x) (0x220 + ((x) << 2)) /* x is the queue id */ ++ ++/* Edma transmit consumer index */ ++#define IPQESS_REG_TX_SW_CONS_IDX_Q(x) (0x240 + ((x) << 2)) /* x is the queue id */ ++ ++/* IRQ Moderator Initial Timer Register */ ++#define IPQESS_REG_IRQ_MODRT_TIMER_INIT 0x280 ++#define IPQESS_IRQ_MODRT_TIMER_MASK 0xFFFF ++#define IPQESS_IRQ_MODRT_RX_TIMER_SHIFT 0 ++#define IPQESS_IRQ_MODRT_TX_TIMER_SHIFT 16 ++ ++/* Interrupt Control Register */ ++#define IPQESS_REG_INTR_CTRL 0x284 ++#define IPQESS_INTR_CLR_TYP_SHIFT 0 ++#define IPQESS_INTR_SW_IDX_W_TYP_SHIFT 1 ++#define IPQESS_INTR_CLEAR_TYPE_W1 0 ++#define IPQESS_INTR_CLEAR_TYPE_R 1 ++ ++/* RX Interrupt Mask Register */ ++#define IPQESS_REG_RX_INT_MASK_Q(x) (0x300 + ((x) << 2)) /* x = queue id */ ++ ++/* TX Interrupt mask register */ ++#define IPQESS_REG_TX_INT_MASK_Q(x) (0x340 + ((x) << 2)) /* x = queue id */ ++ ++/* Load Ptr Register ++ * Software sets this bit after the initialization of the head and tail ++ */ ++#define IPQESS_REG_TX_SRAM_PART 0x400 ++#define IPQESS_LOAD_PTR_SHIFT 16 ++ ++/* TXQ Control Register */ ++#define IPQESS_REG_TXQ_CTRL 0x404 ++#define IPQESS_TXQ_CTRL_IP_OPTION_EN 0x10 ++#define IPQESS_TXQ_CTRL_TXQ_EN 0x20 ++#define IPQESS_TXQ_CTRL_ENH_MODE 0x40 ++#define IPQESS_TXQ_CTRL_LS_8023_EN 0x80 ++#define IPQESS_TXQ_CTRL_TPD_BURST_EN 0x100 ++#define IPQESS_TXQ_CTRL_LSO_BREAK_EN 0x200 ++#define IPQESS_TXQ_NUM_TPD_BURST_MASK 0xF ++#define IPQESS_TXQ_TXF_BURST_NUM_MASK 0xFFFF ++#define IPQESS_TXQ_NUM_TPD_BURST_SHIFT 0 ++#define IPQESS_TXQ_TXF_BURST_NUM_SHIFT 16 ++ ++#define IPQESS_REG_TXF_WATER_MARK 0x408 /* In 8-bytes */ ++#define IPQESS_TXF_WATER_MARK_MASK 0x0FFF ++#define IPQESS_TXF_LOW_WATER_MARK_SHIFT 0 ++#define IPQESS_TXF_HIGH_WATER_MARK_SHIFT 16 ++#define IPQESS_TXQ_CTRL_BURST_MODE_EN 0x80000000 ++ ++/* WRR Control Register */ ++#define IPQESS_REG_WRR_CTRL_Q0_Q3 0x40c ++#define IPQESS_REG_WRR_CTRL_Q4_Q7 0x410 ++#define IPQESS_REG_WRR_CTRL_Q8_Q11 0x414 ++#define IPQESS_REG_WRR_CTRL_Q12_Q15 0x418 ++ ++/* Weight round robin(WRR), it takes queue as input, and computes ++ * starting bits where we need to write the weight for a particular ++ * queue ++ */ ++#define IPQESS_WRR_SHIFT(x) (((x) * 5) % 20) ++ ++/* Tx Descriptor Control Register */ ++#define IPQESS_REG_TPD_RING_SIZE 0x41C ++#define IPQESS_TPD_RING_SIZE_SHIFT 0 ++#define IPQESS_TPD_RING_SIZE_MASK 0xFFFF ++ ++/* Transmit descriptor base address */ ++#define IPQESS_REG_TPD_BASE_ADDR_Q(x) (0x420 + ((x) << 2)) /* x = queue id */ ++ ++/* TPD Index Register */ ++#define IPQESS_REG_TPD_IDX_Q(x) (0x460 + ((x) << 2)) /* x = queue id */ ++ ++#define IPQESS_TPD_PROD_IDX_BITS 0x0000FFFF ++#define IPQESS_TPD_CONS_IDX_BITS 0xFFFF0000 ++#define IPQESS_TPD_PROD_IDX_MASK 0xFFFF ++#define IPQESS_TPD_CONS_IDX_MASK 0xFFFF ++#define IPQESS_TPD_PROD_IDX_SHIFT 0 ++#define IPQESS_TPD_CONS_IDX_SHIFT 16 ++ ++/* TX Virtual Queue Mapping Control Register */ ++#define IPQESS_REG_VQ_CTRL0 0x4A0 ++#define IPQESS_REG_VQ_CTRL1 0x4A4 ++ ++/* Virtual QID shift, it takes queue as input, and computes ++ * Virtual QID position in virtual qid control register ++ */ ++#define IPQESS_VQ_ID_SHIFT(i) (((i) * 3) % 24) ++ ++/* Virtual Queue Default Value */ ++#define IPQESS_VQ_REG_VALUE 0x240240 ++ ++/* Tx side Port Interface Control Register */ ++#define IPQESS_REG_PORT_CTRL 0x4A8 ++#define IPQESS_PAD_EN_SHIFT 15 ++ ++/* Tx side VLAN Configuration Register */ ++#define IPQESS_REG_VLAN_CFG 0x4AC ++ ++#define IPQESS_VLAN_CFG_SVLAN_TPID_SHIFT 0 ++#define IPQESS_VLAN_CFG_SVLAN_TPID_MASK 0xffff ++#define IPQESS_VLAN_CFG_CVLAN_TPID_SHIFT 16 ++#define IPQESS_VLAN_CFG_CVLAN_TPID_MASK 0xffff ++ ++#define IPQESS_TX_CVLAN 16 ++#define IPQESS_TX_INS_CVLAN 17 ++#define IPQESS_TX_CVLAN_TAG_SHIFT 0 ++ ++#define IPQESS_TX_SVLAN 14 ++#define IPQESS_TX_INS_SVLAN 15 ++#define IPQESS_TX_SVLAN_TAG_SHIFT 16 ++ ++/* Tx Queue Packet Statistic Register */ ++#define IPQESS_REG_TX_STAT_PKT_Q(x) (0x700 + ((x) << 3)) /* x = queue id */ ++ ++#define IPQESS_TX_STAT_PKT_MASK 0xFFFFFF ++ ++/* Tx Queue Byte Statistic Register */ ++#define IPQESS_REG_TX_STAT_BYTE_Q(x) (0x704 + ((x) << 3)) /* x = queue id */ ++ ++/* Load Balance Based Ring Offset Register */ ++#define IPQESS_REG_LB_RING 0x800 ++#define IPQESS_LB_RING_ENTRY_MASK 0xff ++#define IPQESS_LB_RING_ID_MASK 0x7 ++#define IPQESS_LB_RING_PROFILE_ID_MASK 0x3 ++#define IPQESS_LB_RING_ENTRY_BIT_OFFSET 8 ++#define IPQESS_LB_RING_ID_OFFSET 0 ++#define IPQESS_LB_RING_PROFILE_ID_OFFSET 3 ++#define IPQESS_LB_REG_VALUE 0x6040200 ++ ++/* Load Balance Priority Mapping Register */ ++#define IPQESS_REG_LB_PRI_START 0x804 ++#define IPQESS_REG_LB_PRI_END 0x810 ++#define IPQESS_LB_PRI_REG_INC 4 ++#define IPQESS_LB_PRI_ENTRY_BIT_OFFSET 4 ++#define IPQESS_LB_PRI_ENTRY_MASK 0xf ++ ++/* RSS Priority Mapping Register */ ++#define IPQESS_REG_RSS_PRI 0x820 ++#define IPQESS_RSS_PRI_ENTRY_MASK 0xf ++#define IPQESS_RSS_RING_ID_MASK 0x7 ++#define IPQESS_RSS_PRI_ENTRY_BIT_OFFSET 4 ++ ++/* RSS Indirection Register */ ++#define IPQESS_REG_RSS_IDT(x) (0x840 + ((x) << 2)) /* x = No. of indirection table */ ++#define IPQESS_NUM_IDT 16 ++#define IPQESS_RSS_IDT_VALUE 0x64206420 ++ ++/* Default RSS Ring Register */ ++#define IPQESS_REG_DEF_RSS 0x890 ++#define IPQESS_DEF_RSS_MASK 0x7 ++ ++/* RSS Hash Function Type Register */ ++#define IPQESS_REG_RSS_TYPE 0x894 ++#define IPQESS_RSS_TYPE_NONE 0x01 ++#define IPQESS_RSS_TYPE_IPV4TCP 0x02 ++#define IPQESS_RSS_TYPE_IPV6_TCP 0x04 ++#define IPQESS_RSS_TYPE_IPV4_UDP 0x08 ++#define IPQESS_RSS_TYPE_IPV6UDP 0x10 ++#define IPQESS_RSS_TYPE_IPV4 0x20 ++#define IPQESS_RSS_TYPE_IPV6 0x40 ++#define IPQESS_RSS_HASH_MODE_MASK 0x7f ++ ++#define IPQESS_REG_RSS_HASH_VALUE 0x8C0 ++ ++#define IPQESS_REG_RSS_TYPE_RESULT 0x8C4 ++ ++#define IPQESS_HASH_TYPE_START 0 ++#define IPQESS_HASH_TYPE_END 5 ++#define IPQESS_HASH_TYPE_SHIFT 12 ++ ++#define IPQESS_RFS_FLOW_ENTRIES 1024 ++#define IPQESS_RFS_FLOW_ENTRIES_MASK (IPQESS_RFS_FLOW_ENTRIES - 1) ++#define IPQESS_RFS_EXPIRE_COUNT_PER_CALL 128 ++ ++/* RFD Base Address Register */ ++#define IPQESS_REG_RFD_BASE_ADDR_Q(x) (0x950 + ((x) << 2)) /* x = queue id */ ++ ++/* RFD Index Register */ ++#define IPQESS_REG_RFD_IDX_Q(x) (0x9B0 + ((x) << 2)) /* x = queue id */ ++ ++#define IPQESS_RFD_PROD_IDX_BITS 0x00000FFF ++#define IPQESS_RFD_CONS_IDX_BITS 0x0FFF0000 ++#define IPQESS_RFD_PROD_IDX_MASK 0xFFF ++#define IPQESS_RFD_CONS_IDX_MASK 0xFFF ++#define IPQESS_RFD_PROD_IDX_SHIFT 0 ++#define IPQESS_RFD_CONS_IDX_SHIFT 16 ++ ++/* Rx Descriptor Control Register */ ++#define IPQESS_REG_RX_DESC0 0xA10 ++#define IPQESS_RFD_RING_SIZE_MASK 0xFFF ++#define IPQESS_RX_BUF_SIZE_MASK 0xFFFF ++#define IPQESS_RFD_RING_SIZE_SHIFT 0 ++#define IPQESS_RX_BUF_SIZE_SHIFT 16 ++ ++#define IPQESS_REG_RX_DESC1 0xA14 ++#define IPQESS_RXQ_RFD_BURST_NUM_MASK 0x3F ++#define IPQESS_RXQ_RFD_PF_THRESH_MASK 0x1F ++#define IPQESS_RXQ_RFD_LOW_THRESH_MASK 0xFFF ++#define IPQESS_RXQ_RFD_BURST_NUM_SHIFT 0 ++#define IPQESS_RXQ_RFD_PF_THRESH_SHIFT 8 ++#define IPQESS_RXQ_RFD_LOW_THRESH_SHIFT 16 ++ ++/* RXQ Control Register */ ++#define IPQESS_REG_RXQ_CTRL 0xA18 ++#define IPQESS_FIFO_THRESH_TYPE_SHIF 0 ++#define IPQESS_FIFO_THRESH_128_BYTE 0x0 ++#define IPQESS_FIFO_THRESH_64_BYTE 0x1 ++#define IPQESS_RXQ_CTRL_RMV_VLAN 0x00000002 ++#define IPQESS_RXQ_CTRL_EN_MASK GENMASK(15, 8) ++#define IPQESS_RXQ_CTRL_EN(__qid) BIT(8 + (__qid)) ++ ++/* AXI Burst Size Config */ ++#define IPQESS_REG_AXIW_CTRL_MAXWRSIZE 0xA1C ++#define IPQESS_AXIW_MAXWRSIZE_VALUE 0x0 ++ ++/* Rx Statistics Register */ ++#define IPQESS_REG_RX_STAT_BYTE_Q(x) (0xA30 + ((x) << 2)) /* x = queue id */ ++#define IPQESS_REG_RX_STAT_PKT_Q(x) (0xA50 + ((x) << 2)) /* x = queue id */ ++ ++/* WoL Pattern Length Register */ ++#define IPQESS_REG_WOL_PATTERN_LEN0 0xC00 ++#define IPQESS_WOL_PT_LEN_MASK 0xFF ++#define IPQESS_WOL_PT0_LEN_SHIFT 0 ++#define IPQESS_WOL_PT1_LEN_SHIFT 8 ++#define IPQESS_WOL_PT2_LEN_SHIFT 16 ++#define IPQESS_WOL_PT3_LEN_SHIFT 24 ++ ++#define IPQESS_REG_WOL_PATTERN_LEN1 0xC04 ++#define IPQESS_WOL_PT4_LEN_SHIFT 0 ++#define IPQESS_WOL_PT5_LEN_SHIFT 8 ++#define IPQESS_WOL_PT6_LEN_SHIFT 16 ++ ++/* WoL Control Register */ ++#define IPQESS_REG_WOL_CTRL 0xC08 ++#define IPQESS_WOL_WK_EN 0x00000001 ++#define IPQESS_WOL_MG_EN 0x00000002 ++#define IPQESS_WOL_PT0_EN 0x00000004 ++#define IPQESS_WOL_PT1_EN 0x00000008 ++#define IPQESS_WOL_PT2_EN 0x00000010 ++#define IPQESS_WOL_PT3_EN 0x00000020 ++#define IPQESS_WOL_PT4_EN 0x00000040 ++#define IPQESS_WOL_PT5_EN 0x00000080 ++#define IPQESS_WOL_PT6_EN 0x00000100 ++ ++/* MAC Control Register */ ++#define IPQESS_REG_MAC_CTRL0 0xC20 ++#define IPQESS_REG_MAC_CTRL1 0xC24 ++ ++/* WoL Pattern Register */ ++#define IPQESS_REG_WOL_PATTERN_START 0x5000 ++#define IPQESS_PATTERN_PART_REG_OFFSET 0x40 ++ ++ ++/* TX descriptor fields */ ++#define IPQESS_TPD_HDR_SHIFT 0 ++#define IPQESS_TPD_PPPOE_EN 0x00000100 ++#define IPQESS_TPD_IP_CSUM_EN 0x00000200 ++#define IPQESS_TPD_TCP_CSUM_EN 0x0000400 ++#define IPQESS_TPD_UDP_CSUM_EN 0x00000800 ++#define IPQESS_TPD_CUSTOM_CSUM_EN 0x00000C00 ++#define IPQESS_TPD_LSO_EN 0x00001000 ++#define IPQESS_TPD_LSO_V2_EN 0x00002000 ++/* The VLAN_TAGGED bit is not used in the publicly available ++ * drivers. The definition has been stolen from the Atheros ++ * 'alx' driver (drivers/net/ethernet/atheros/alx/hw.h). It ++ * seems that it has the same meaning in regard to the EDMA ++ * hardware. ++ */ ++#define IPQESS_TPD_VLAN_TAGGED 0x00004000 ++#define IPQESS_TPD_IPV4_EN 0x00010000 ++#define IPQESS_TPD_MSS_MASK 0x1FFF ++#define IPQESS_TPD_MSS_SHIFT 18 ++#define IPQESS_TPD_CUSTOM_CSUM_SHIFT 18 ++ ++/* RRD descriptor fields */ ++#define IPQESS_RRD_NUM_RFD_MASK 0x000F ++#define IPQESS_RRD_PKT_SIZE_MASK 0x3FFF ++#define IPQESS_RRD_SRC_PORT_NUM_MASK 0x4000 ++#define IPQESS_RRD_SVLAN 0x8000 ++#define IPQESS_RRD_FLOW_COOKIE_MASK 0x07FF; ++ ++#define IPQESS_RRD_PKT_SIZE_MASK 0x3FFF ++#define IPQESS_RRD_CSUM_FAIL_MASK 0xC000 ++#define IPQESS_RRD_CVLAN 0x0001 ++#define IPQESS_RRD_DESC_VALID 0x8000 ++ ++#define IPQESS_RRD_PRIORITY_SHIFT 4 ++#define IPQESS_RRD_PRIORITY_MASK 0x7 ++#define IPQESS_RRD_PORT_TYPE_SHIFT 7 ++#define IPQESS_RRD_PORT_TYPE_MASK 0x1F ++ ++#endif +--- /dev/null ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c +@@ -0,0 +1,175 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR ISC) ++/* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 - 2018, John Crispin ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "ipqess.h" ++ ++struct ipqesstool_stats { ++ uint8_t string[ETH_GSTRING_LEN]; ++ uint32_t offset; ++}; ++ ++#define IPQESS_STAT(m) offsetof(struct ipqesstool_statistics, m) ++#define DRVINFO_LEN 32 ++ ++static const struct ipqesstool_stats ipqess_stats[] = { ++ {"tx_q0_pkt", IPQESS_STAT(tx_q0_pkt)}, ++ {"tx_q1_pkt", IPQESS_STAT(tx_q1_pkt)}, ++ {"tx_q2_pkt", IPQESS_STAT(tx_q2_pkt)}, ++ {"tx_q3_pkt", IPQESS_STAT(tx_q3_pkt)}, ++ {"tx_q4_pkt", IPQESS_STAT(tx_q4_pkt)}, ++ {"tx_q5_pkt", IPQESS_STAT(tx_q5_pkt)}, ++ {"tx_q6_pkt", IPQESS_STAT(tx_q6_pkt)}, ++ {"tx_q7_pkt", IPQESS_STAT(tx_q7_pkt)}, ++ {"tx_q8_pkt", IPQESS_STAT(tx_q8_pkt)}, ++ {"tx_q9_pkt", IPQESS_STAT(tx_q9_pkt)}, ++ {"tx_q10_pkt", IPQESS_STAT(tx_q10_pkt)}, ++ {"tx_q11_pkt", IPQESS_STAT(tx_q11_pkt)}, ++ {"tx_q12_pkt", IPQESS_STAT(tx_q12_pkt)}, ++ {"tx_q13_pkt", IPQESS_STAT(tx_q13_pkt)}, ++ {"tx_q14_pkt", IPQESS_STAT(tx_q14_pkt)}, ++ {"tx_q15_pkt", IPQESS_STAT(tx_q15_pkt)}, ++ {"tx_q0_byte", IPQESS_STAT(tx_q0_byte)}, ++ {"tx_q1_byte", IPQESS_STAT(tx_q1_byte)}, ++ {"tx_q2_byte", IPQESS_STAT(tx_q2_byte)}, ++ {"tx_q3_byte", IPQESS_STAT(tx_q3_byte)}, ++ {"tx_q4_byte", IPQESS_STAT(tx_q4_byte)}, ++ {"tx_q5_byte", IPQESS_STAT(tx_q5_byte)}, ++ {"tx_q6_byte", IPQESS_STAT(tx_q6_byte)}, ++ {"tx_q7_byte", IPQESS_STAT(tx_q7_byte)}, ++ {"tx_q8_byte", IPQESS_STAT(tx_q8_byte)}, ++ {"tx_q9_byte", IPQESS_STAT(tx_q9_byte)}, ++ {"tx_q10_byte", IPQESS_STAT(tx_q10_byte)}, ++ {"tx_q11_byte", IPQESS_STAT(tx_q11_byte)}, ++ {"tx_q12_byte", IPQESS_STAT(tx_q12_byte)}, ++ {"tx_q13_byte", IPQESS_STAT(tx_q13_byte)}, ++ {"tx_q14_byte", IPQESS_STAT(tx_q14_byte)}, ++ {"tx_q15_byte", IPQESS_STAT(tx_q15_byte)}, ++ {"rx_q0_pkt", IPQESS_STAT(rx_q0_pkt)}, ++ {"rx_q1_pkt", IPQESS_STAT(rx_q1_pkt)}, ++ {"rx_q2_pkt", IPQESS_STAT(rx_q2_pkt)}, ++ {"rx_q3_pkt", IPQESS_STAT(rx_q3_pkt)}, ++ {"rx_q4_pkt", IPQESS_STAT(rx_q4_pkt)}, ++ {"rx_q5_pkt", IPQESS_STAT(rx_q5_pkt)}, ++ {"rx_q6_pkt", IPQESS_STAT(rx_q6_pkt)}, ++ {"rx_q7_pkt", IPQESS_STAT(rx_q7_pkt)}, ++ {"rx_q0_byte", IPQESS_STAT(rx_q0_byte)}, ++ {"rx_q1_byte", IPQESS_STAT(rx_q1_byte)}, ++ {"rx_q2_byte", IPQESS_STAT(rx_q2_byte)}, ++ {"rx_q3_byte", IPQESS_STAT(rx_q3_byte)}, ++ {"rx_q4_byte", IPQESS_STAT(rx_q4_byte)}, ++ {"rx_q5_byte", IPQESS_STAT(rx_q5_byte)}, ++ {"rx_q6_byte", IPQESS_STAT(rx_q6_byte)}, ++ {"rx_q7_byte", IPQESS_STAT(rx_q7_byte)}, ++ {"tx_desc_error", IPQESS_STAT(tx_desc_error)}, ++}; ++ ++static int ipqess_get_strset_count(struct net_device *netdev, int sset) ++{ ++ switch (sset) { ++ case ETH_SS_STATS: ++ return ARRAY_SIZE(ipqess_stats); ++ default: ++ netdev_dbg(netdev, "%s: Invalid string set", __func__); ++ return -EOPNOTSUPP; ++ } ++} ++ ++static void ipqess_get_strings(struct net_device *netdev, uint32_t stringset, ++ uint8_t *data) ++{ ++ uint8_t *p = data; ++ uint32_t i; ++ ++ switch (stringset) { ++ case ETH_SS_STATS: ++ for (i = 0; i < ARRAY_SIZE(ipqess_stats); i++) { ++ memcpy(p, ipqess_stats[i].string, ++ min((size_t)ETH_GSTRING_LEN, ++ strlen(ipqess_stats[i].string) + 1)); ++ p += ETH_GSTRING_LEN; ++ } ++ break; ++ } ++} ++ ++static void ipqess_get_ethtool_stats(struct net_device *netdev, ++ struct ethtool_stats *stats, ++ uint64_t *data) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ u32 *essstats = (u32 *)&ess->ipqessstats; ++ int i; ++ ++ spin_lock(&ess->stats_lock); ++ ++ ipqess_update_hw_stats(ess); ++ ++ for (i = 0; i < ARRAY_SIZE(ipqess_stats); i++) ++ data[i] = *(u32 *)(essstats + (ipqess_stats[i].offset / sizeof(u32))); ++ ++ spin_unlock(&ess->stats_lock); ++} ++ ++static void ipqess_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ strlcpy(info->driver, "qca_ipqess", DRVINFO_LEN); ++ strlcpy(info->bus_info, "axi", ETHTOOL_BUSINFO_LEN); ++} ++ ++static int ipqess_get_settings(struct net_device *netdev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_get(ess->phylink, cmd); ++} ++ ++static int ipqess_set_settings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *cmd) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_set(ess->phylink, cmd); ++} ++ ++static void ipqess_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) ++{ ++ ring->tx_max_pending = IPQESS_TX_RING_SIZE; ++ ring->rx_max_pending = IPQESS_RX_RING_SIZE; ++} ++ ++static const struct ethtool_ops ipqesstool_ops = { ++ .get_drvinfo = &ipqess_get_drvinfo, ++ .get_link = ðtool_op_get_link, ++ .get_link_ksettings = &ipqess_get_settings, ++ .set_link_ksettings = &ipqess_set_settings, ++ .get_strings = &ipqess_get_strings, ++ .get_sset_count = &ipqess_get_strset_count, ++ .get_ethtool_stats = &ipqess_get_ethtool_stats, ++ .get_ringparam = ipqess_get_ringparam, ++}; ++ ++void ipqess_set_ethtool_ops(struct net_device *netdev) ++{ ++ netdev->ethtool_ops = &ipqesstool_ops; ++} +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/702-net-ethernet-qualcomm-add-IPQESS-support.patch +@@ -0,0 +1,43 @@ ++From 4f488235f498db43f2412116dea6e02c7fb20216 Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 1 Nov 2021 12:36:51 +0100 ++Subject: [PATCH] net: ethernet: qualcomm: add IPQESS support ++ ++Allow compiling the IPQESS driver that supports the ++Qualcomm IPQ40xx SoC built-in ethernet controller. ++ ++Signed-off-by: Robert Marko ++--- ++ drivers/net/ethernet/qualcomm/Kconfig | 11 +++++++++++ ++ drivers/net/ethernet/qualcomm/Makefile | 1 + ++ 2 files changed, 12 insertions(+) ++ ++--- a/drivers/net/ethernet/qualcomm/Kconfig +++++ b/drivers/net/ethernet/qualcomm/Kconfig ++@@ -60,6 +60,17 @@ config QCOM_EMAC ++ low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 ++ Precision Clock Synchronization Protocol. ++ +++config QCOM_IPQ4019_ESS_EDMA +++ tristate "Qualcomm Atheros IPQ4019 ESS EDMA support" +++ depends on OF +++ select PHYLINK +++ help +++ This driver supports the Qualcomm Atheros IPQ40xx built-in +++ ESS EDMA ethernet controller. +++ +++ To compile this driver as a module, choose M here: the +++ module will be called ipqess. +++ ++ source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" ++ ++ endif # NET_VENDOR_QUALCOMM ++--- a/drivers/net/ethernet/qualcomm/Makefile +++++ b/drivers/net/ethernet/qualcomm/Makefile ++@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o ++ qcauart-objs := qca_uart.o ++ ++ obj-y += emac/ +++obj-y += ipqess/ ++ ++ obj-$(CONFIG_RMNET) += rmnet/ +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch +@@ -0,0 +1,81 @@ ++From 44327d7098d4f32c24ec8c528e5aff6e030956bc Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Wed, 20 Oct 2021 13:21:45 +0200 ++Subject: [PATCH] arm: dts: ipq4019: add ethernet controller DT node ++ ++Since IPQ40xx SoC built-in ethernet controller now has a driver, ++add its DT node so it can be used. ++ ++Signed-off-by: Robert Marko ++--- ++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 48 +++++++++++++++++++++++++++++ ++ 1 file changed, 48 insertions(+) ++ ++--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi ++@@ -38,6 +38,7 @@ ++ spi1 = &blsp1_spi2; ++ i2c0 = &blsp1_i2c3; ++ i2c1 = &blsp1_i2c4; +++ ethernet0 = &gmac; ++ }; ++ ++ cpus { ++@@ -589,6 +590,57 @@ ++ status = "disabled"; ++ }; ++ +++ gmac: ethernet@c080000 { +++ compatible = "qcom,ipq4019-ess-edma"; +++ reg = <0xc080000 0x8000>; +++ resets = <&gcc ESS_RESET>; +++ reset-names = "ess_rst"; +++ clocks = <&gcc GCC_ESS_CLK>; +++ clock-names = "ess_clk"; +++ interrupts = , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ ; +++ +++ status = "disabled"; +++ +++ phy-mode = "internal"; +++ fixed-link { +++ speed = <1000>; +++ full-duplex; +++ pause; +++ asym-pause; +++ }; +++ }; +++ ++ mdio: mdio@90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; +--- a/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch ++++ b/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch +@@ -20,7 +20,7 @@ Signed-off-by: Robert Marko + + / { + #address-cells = <1>; +-@@ -598,22 +599,39 @@ ++@@ -645,22 +646,39 @@ + + ethphy0: ethernet-phy@0 { + reg = <0>; +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/702-net-ethernet-qualcomm-add-IPQESS-support.patch +@@ -0,0 +1,43 @@ ++From 4f488235f498db43f2412116dea6e02c7fb20216 Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 1 Nov 2021 12:36:51 +0100 ++Subject: [PATCH] net: ethernet: qualcomm: add IPQESS support ++ ++Allow compiling the IPQESS driver that supports the ++Qualcomm IPQ40xx SoC built-in ethernet controller. ++ ++Signed-off-by: Robert Marko ++--- ++ drivers/net/ethernet/qualcomm/Kconfig | 11 +++++++++++ ++ drivers/net/ethernet/qualcomm/Makefile | 1 + ++ 2 files changed, 12 insertions(+) ++ ++--- a/drivers/net/ethernet/qualcomm/Kconfig +++++ b/drivers/net/ethernet/qualcomm/Kconfig ++@@ -60,6 +60,17 @@ config QCOM_EMAC ++ low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 ++ Precision Clock Synchronization Protocol. ++ +++config QCOM_IPQ4019_ESS_EDMA +++ tristate "Qualcomm Atheros IPQ4019 ESS EDMA support" +++ depends on OF +++ select PHYLINK +++ help +++ This driver supports the Qualcomm Atheros IPQ40xx built-in +++ ESS EDMA ethernet controller. +++ +++ To compile this driver as a module, choose M here: the +++ module will be called ipqess. +++ ++ source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" ++ ++ endif # NET_VENDOR_QUALCOMM ++--- a/drivers/net/ethernet/qualcomm/Makefile +++++ b/drivers/net/ethernet/qualcomm/Makefile ++@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o ++ qcauart-objs := qca_uart.o ++ ++ obj-y += emac/ +++obj-y += ipqess/ ++ ++ obj-$(CONFIG_RMNET) += rmnet/ +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch +@@ -0,0 +1,81 @@ ++From 44327d7098d4f32c24ec8c528e5aff6e030956bc Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Wed, 20 Oct 2021 13:21:45 +0200 ++Subject: [PATCH] arm: dts: ipq4019: add ethernet controller DT node ++ ++Since IPQ40xx SoC built-in ethernet controller now has a driver, ++add its DT node so it can be used. ++ ++Signed-off-by: Robert Marko ++--- ++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 48 +++++++++++++++++++++++++++++ ++ 1 file changed, 48 insertions(+) ++ ++--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi ++@@ -38,6 +38,7 @@ ++ spi1 = &blsp1_spi2; ++ i2c0 = &blsp1_i2c3; ++ i2c1 = &blsp1_i2c4; +++ ethernet0 = &gmac; ++ }; ++ ++ cpus { ++@@ -589,6 +590,57 @@ ++ status = "disabled"; ++ }; ++ +++ gmac: ethernet@c080000 { +++ compatible = "qcom,ipq4019-ess-edma"; +++ reg = <0xc080000 0x8000>; +++ resets = <&gcc ESS_RESET>; +++ reset-names = "ess_rst"; +++ clocks = <&gcc GCC_ESS_CLK>; +++ clock-names = "ess_clk"; +++ interrupts = , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ , +++ ; +++ +++ status = "disabled"; +++ +++ phy-mode = "internal"; +++ fixed-link { +++ speed = <1000>; +++ full-duplex; +++ pause; +++ asym-pause; +++ }; +++ }; +++ ++ mdio: mdio@90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; + +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/704-net-phy-define-PSGMII-PHY-interface-mode.patch +@@ -0,0 +1,61 @@ ++From 3e1825e00dafb68eec25df389b63f3ab3d905b59 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Fri, 25 Dec 2020 08:02:47 +0100 ++Subject: [PATCH] net: phy: define PSGMII PHY interface mode ++ ++The PSGMII interface is similar to QSGMII. The main difference ++is that the PSGMII interface combines five SGMII lines into a ++single link while in QSGMII only four lines are combined. ++ ++Similarly to the QSGMII, this interface mode might also needs ++special handling within the MAC driver. ++ ++Add definitions for the PHY layer to allow to express this type ++of connection between the MAC and PHY. ++ ++Signed-off-by: Gabor Juhos ++--- ++ Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + ++ drivers/net/phy/phylink.c | 1 + ++ include/linux/phy.h | 3 +++ ++ 3 files changed, 5 insertions(+) ++ ++--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml +++++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml ++@@ -64,6 +64,7 @@ properties: ++ - mii ++ - gmii ++ - sgmii +++ - psgmii ++ - qsgmii ++ - tbi ++ - rev-mii ++--- a/drivers/net/phy/phylink.c +++++ b/drivers/net/phy/phylink.c ++@@ -289,6 +289,7 @@ static int phylink_parse_mode(struct phy ++ ++ switch (pl->link_config.interface) { ++ case PHY_INTERFACE_MODE_SGMII: +++ case PHY_INTERFACE_MODE_PSGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ phylink_set(pl->supported, 10baseT_Half); ++ phylink_set(pl->supported, 10baseT_Full); ++--- a/include/linux/phy.h +++++ b/include/linux/phy.h ++@@ -134,6 +134,7 @@ typedef enum { ++ PHY_INTERFACE_MODE_XGMII, ++ PHY_INTERFACE_MODE_XLGMII, ++ PHY_INTERFACE_MODE_MOCA, +++ PHY_INTERFACE_MODE_PSGMII, ++ PHY_INTERFACE_MODE_QSGMII, ++ PHY_INTERFACE_MODE_TRGMII, ++ PHY_INTERFACE_MODE_100BASEX, ++@@ -201,6 +202,8 @@ static inline const char *phy_modes(phy_ ++ return "xlgmii"; ++ case PHY_INTERFACE_MODE_MOCA: ++ return "moca"; +++ case PHY_INTERFACE_MODE_PSGMII: +++ return "psgmii"; ++ case PHY_INTERFACE_MODE_QSGMII: ++ return "qsgmii"; ++ case PHY_INTERFACE_MODE_TRGMII: +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/704-net-phy-define-PSGMII-PHY-interface-mode.patch +@@ -0,0 +1,61 @@ ++From 3e1825e00dafb68eec25df389b63f3ab3d905b59 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Fri, 25 Dec 2020 08:02:47 +0100 ++Subject: [PATCH] net: phy: define PSGMII PHY interface mode ++ ++The PSGMII interface is similar to QSGMII. The main difference ++is that the PSGMII interface combines five SGMII lines into a ++single link while in QSGMII only four lines are combined. ++ ++Similarly to the QSGMII, this interface mode might also needs ++special handling within the MAC driver. ++ ++Add definitions for the PHY layer to allow to express this type ++of connection between the MAC and PHY. ++ ++Signed-off-by: Gabor Juhos ++--- ++ Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + ++ drivers/net/phy/phylink.c | 1 + ++ include/linux/phy.h | 3 +++ ++ 3 files changed, 5 insertions(+) ++ ++--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml +++++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml ++@@ -64,6 +64,7 @@ properties: ++ - mii ++ - gmii ++ - sgmii +++ - psgmii ++ - qsgmii ++ - tbi ++ - rev-mii ++--- a/drivers/net/phy/phylink.c +++++ b/drivers/net/phy/phylink.c ++@@ -293,6 +293,7 @@ static int phylink_parse_mode(struct phy ++ ++ switch (pl->link_config.interface) { ++ case PHY_INTERFACE_MODE_SGMII: +++ case PHY_INTERFACE_MODE_PSGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ phylink_set(pl->supported, 10baseT_Half); ++ phylink_set(pl->supported, 10baseT_Full); ++--- a/include/linux/phy.h +++++ b/include/linux/phy.h ++@@ -138,6 +138,7 @@ typedef enum { ++ PHY_INTERFACE_MODE_XGMII, ++ PHY_INTERFACE_MODE_XLGMII, ++ PHY_INTERFACE_MODE_MOCA, +++ PHY_INTERFACE_MODE_PSGMII, ++ PHY_INTERFACE_MODE_QSGMII, ++ PHY_INTERFACE_MODE_TRGMII, ++ PHY_INTERFACE_MODE_100BASEX, ++@@ -209,6 +210,8 @@ static inline const char *phy_modes(phy_ ++ return "xlgmii"; ++ case PHY_INTERFACE_MODE_MOCA: ++ return "moca"; +++ case PHY_INTERFACE_MODE_PSGMII: +++ return "psgmii"; ++ case PHY_INTERFACE_MODE_QSGMII: ++ return "qsgmii"; ++ case PHY_INTERFACE_MODE_TRGMII: + +--- /dev/null ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -0,0 +1,2190 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2009 Felix Fietkau ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2016 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "qca8k.h" ++ ++#define MIB_DESC(_s, _o, _n) \ ++ { \ ++ .size = (_s), \ ++ .offset = (_o), \ ++ .name = (_n), \ ++ } ++ ++static const struct qca8k_mib_desc ar8327_mib[] = { ++ MIB_DESC(1, 0x00, "RxBroad"), ++ MIB_DESC(1, 0x04, "RxPause"), ++ MIB_DESC(1, 0x08, "RxMulti"), ++ MIB_DESC(1, 0x0c, "RxFcsErr"), ++ MIB_DESC(1, 0x10, "RxAlignErr"), ++ MIB_DESC(1, 0x14, "RxRunt"), ++ MIB_DESC(1, 0x18, "RxFragment"), ++ MIB_DESC(1, 0x1c, "Rx64Byte"), ++ MIB_DESC(1, 0x20, "Rx128Byte"), ++ MIB_DESC(1, 0x24, "Rx256Byte"), ++ MIB_DESC(1, 0x28, "Rx512Byte"), ++ MIB_DESC(1, 0x2c, "Rx1024Byte"), ++ MIB_DESC(1, 0x30, "Rx1518Byte"), ++ MIB_DESC(1, 0x34, "RxMaxByte"), ++ MIB_DESC(1, 0x38, "RxTooLong"), ++ MIB_DESC(2, 0x3c, "RxGoodByte"), ++ MIB_DESC(2, 0x44, "RxBadByte"), ++ MIB_DESC(1, 0x4c, "RxOverFlow"), ++ MIB_DESC(1, 0x50, "Filtered"), ++ MIB_DESC(1, 0x54, "TxBroad"), ++ MIB_DESC(1, 0x58, "TxPause"), ++ MIB_DESC(1, 0x5c, "TxMulti"), ++ MIB_DESC(1, 0x60, "TxUnderRun"), ++ MIB_DESC(1, 0x64, "Tx64Byte"), ++ MIB_DESC(1, 0x68, "Tx128Byte"), ++ MIB_DESC(1, 0x6c, "Tx256Byte"), ++ MIB_DESC(1, 0x70, "Tx512Byte"), ++ MIB_DESC(1, 0x74, "Tx1024Byte"), ++ MIB_DESC(1, 0x78, "Tx1518Byte"), ++ MIB_DESC(1, 0x7c, "TxMaxByte"), ++ MIB_DESC(1, 0x80, "TxOverSize"), ++ MIB_DESC(2, 0x84, "TxByte"), ++ MIB_DESC(1, 0x8c, "TxCollision"), ++ MIB_DESC(1, 0x90, "TxAbortCol"), ++ MIB_DESC(1, 0x94, "TxMultiCol"), ++ MIB_DESC(1, 0x98, "TxSingleCol"), ++ MIB_DESC(1, 0x9c, "TxExcDefer"), ++ MIB_DESC(1, 0xa0, "TxDefer"), ++ MIB_DESC(1, 0xa4, "TxLateCol"), ++}; ++ ++/* The 32bit switch registers are accessed indirectly. To achieve this we need ++ * to set the page of the register. Track the last page that was set to reduce ++ * mdio writes ++ */ ++static u16 qca8k_current_page = 0xffff; ++ ++static void ++qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) ++{ ++ regaddr >>= 1; ++ *r1 = regaddr & 0x1e; ++ ++ regaddr >>= 5; ++ *r2 = regaddr & 0x7; ++ ++ regaddr >>= 3; ++ *page = regaddr & 0x3ff; ++} ++ ++static int ++qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) ++{ ++ int ret; ++ ++ ret = bus->read(bus, phy_id, regnum); ++ if (ret >= 0) { ++ *val = ret; ++ ret = bus->read(bus, phy_id, regnum + 1); ++ *val |= ret << 16; ++ } ++ ++ if (ret < 0) { ++ dev_err_ratelimited(&bus->dev, ++ "failed to read qca8k 32bit register\n"); ++ *val = 0; ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ++qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) ++{ ++ u16 lo, hi; ++ int ret; ++ ++ lo = val & 0xffff; ++ hi = (u16)(val >> 16); ++ ++ ret = bus->write(bus, phy_id, regnum, lo); ++ if (ret >= 0) ++ ret = bus->write(bus, phy_id, regnum + 1, hi); ++ if (ret < 0) ++ dev_err_ratelimited(&bus->dev, ++ "failed to write qca8k 32bit register\n"); ++} ++ ++static int ++qca8k_set_page(struct mii_bus *bus, u16 page) ++{ ++ int ret; ++ ++ if (page == qca8k_current_page) ++ return 0; ++ ++ ret = bus->write(bus, 0x18, 0, page); ++ if (ret < 0) { ++ dev_err_ratelimited(&bus->dev, ++ "failed to set qca8k page\n"); ++ return ret; ++ } ++ ++ qca8k_current_page = page; ++ usleep_range(1000, 2000); ++ return 0; ++} ++ ++static int ++qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) ++{ ++ struct mii_bus *bus = priv->bus; ++ u16 r1, r2, page; ++ int ret; ++ ++ qca8k_split_addr(reg, &r1, &r2, &page); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = qca8k_set_page(bus, page); ++ if (ret < 0) ++ goto exit; ++ ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, val); ++ ++exit: ++ mutex_unlock(&bus->mdio_lock); ++ return ret; ++} ++ ++static int ++qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) ++{ ++ struct mii_bus *bus = priv->bus; ++ u16 r1, r2, page; ++ int ret; ++ ++ qca8k_split_addr(reg, &r1, &r2, &page); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = qca8k_set_page(bus, page); ++ if (ret < 0) ++ goto exit; ++ ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ ++exit: ++ mutex_unlock(&bus->mdio_lock); ++ return ret; ++} ++ ++static int ++qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) ++{ ++ struct mii_bus *bus = priv->bus; ++ u16 r1, r2, page; ++ u32 val; ++ int ret; ++ ++ qca8k_split_addr(reg, &r1, &r2, &page); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = qca8k_set_page(bus, page); ++ if (ret < 0) ++ goto exit; ++ ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); ++ if (ret < 0) ++ goto exit; ++ ++ val &= ~mask; ++ val |= write_val; ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ ++exit: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val) ++{ ++ return qca8k_rmw(priv, reg, 0, val); ++} ++ ++static int ++qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val) ++{ ++ return qca8k_rmw(priv, reg, val, 0); ++} ++ ++static int ++qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ctx; ++ ++ return qca8k_read(priv, reg, val); ++} ++ ++static int ++qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ctx; ++ ++ return qca8k_write(priv, reg, val); ++} ++ ++static const struct regmap_range qca8k_readable_ranges[] = { ++ regmap_reg_range(0x0000, 0x00e4), /* Global control */ ++ regmap_reg_range(0x0100, 0x0168), /* EEE control */ ++ regmap_reg_range(0x0200, 0x0270), /* Parser control */ ++ regmap_reg_range(0x0400, 0x0454), /* ACL */ ++ regmap_reg_range(0x0600, 0x0718), /* Lookup */ ++ regmap_reg_range(0x0800, 0x0b70), /* QM */ ++ regmap_reg_range(0x0c00, 0x0c80), /* PKT */ ++ regmap_reg_range(0x0e00, 0x0e98), /* L3 */ ++ regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */ ++ regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */ ++ regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */ ++ regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */ ++ regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */ ++ regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */ ++ regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */ ++ ++}; ++ ++static const struct regmap_access_table qca8k_readable_table = { ++ .yes_ranges = qca8k_readable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), ++}; ++ ++static struct regmap_config qca8k_regmap_config = { ++ .reg_bits = 16, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = 0x16ac, /* end MIB - Port6 range */ ++ .reg_read = qca8k_regmap_read, ++ .reg_write = qca8k_regmap_write, ++ .rd_table = &qca8k_readable_table, ++}; ++ ++static int ++qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) ++{ ++ int ret, ret1; ++ u32 val; ++ ++ ret = read_poll_timeout(qca8k_read, ret1, !(val & mask), ++ 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, ++ priv, reg, &val); ++ ++ /* Check if qca8k_read has failed for a different reason ++ * before returning -ETIMEDOUT ++ */ ++ if (ret < 0 && ret1 < 0) ++ return ret1; ++ ++ return ret; ++} ++ ++static int ++qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) ++{ ++ u32 reg[4], val; ++ int i, ret; ++ ++ /* load the ARL table into an array */ ++ for (i = 0; i < 4; i++) { ++ ret = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4), &val); ++ if (ret < 0) ++ return ret; ++ ++ reg[i] = val; ++ } ++ ++ /* vid - 83:72 */ ++ fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M; ++ /* aging - 67:64 */ ++ fdb->aging = reg[2] & QCA8K_ATU_STATUS_M; ++ /* portmask - 54:48 */ ++ fdb->port_mask = (reg[1] >> QCA8K_ATU_PORT_S) & QCA8K_ATU_PORT_M; ++ /* mac - 47:0 */ ++ fdb->mac[0] = (reg[1] >> QCA8K_ATU_ADDR0_S) & 0xff; ++ fdb->mac[1] = reg[1] & 0xff; ++ fdb->mac[2] = (reg[0] >> QCA8K_ATU_ADDR2_S) & 0xff; ++ fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff; ++ fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff; ++ fdb->mac[5] = reg[0] & 0xff; ++ ++ return 0; ++} ++ ++static void ++qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, ++ u8 aging) ++{ ++ u32 reg[3] = { 0 }; ++ int i; ++ ++ /* vid - 83:72 */ ++ reg[2] = (vid & QCA8K_ATU_VID_M) << QCA8K_ATU_VID_S; ++ /* aging - 67:64 */ ++ reg[2] |= aging & QCA8K_ATU_STATUS_M; ++ /* portmask - 54:48 */ ++ reg[1] = (port_mask & QCA8K_ATU_PORT_M) << QCA8K_ATU_PORT_S; ++ /* mac - 47:0 */ ++ reg[1] |= mac[0] << QCA8K_ATU_ADDR0_S; ++ reg[1] |= mac[1]; ++ reg[0] |= mac[2] << QCA8K_ATU_ADDR2_S; ++ reg[0] |= mac[3] << QCA8K_ATU_ADDR3_S; ++ reg[0] |= mac[4] << QCA8K_ATU_ADDR4_S; ++ reg[0] |= mac[5]; ++ ++ /* load the array into the ARL table */ ++ for (i = 0; i < 3; i++) ++ qca8k_write(priv, QCA8K_REG_ATU_DATA0 + (i * 4), reg[i]); ++} ++ ++static int ++qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port) ++{ ++ u32 reg; ++ int ret; ++ ++ /* Set the command and FDB index */ ++ reg = QCA8K_ATU_FUNC_BUSY; ++ reg |= cmd; ++ if (port >= 0) { ++ reg |= QCA8K_ATU_FUNC_PORT_EN; ++ reg |= (port & QCA8K_ATU_FUNC_PORT_M) << QCA8K_ATU_FUNC_PORT_S; ++ } ++ ++ /* Write the function register triggering the table access */ ++ ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg); ++ if (ret) ++ return ret; ++ ++ /* wait for completion */ ++ ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY); ++ if (ret) ++ return ret; ++ ++ /* Check for table full violation when adding an entry */ ++ if (cmd == QCA8K_FDB_LOAD) { ++ ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, ®); ++ if (ret < 0) ++ return ret; ++ if (reg & QCA8K_ATU_FUNC_FULL) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, int port) ++{ ++ int ret; ++ ++ qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port); ++ if (ret < 0) ++ return ret; ++ ++ return qca8k_fdb_read(priv, fdb); ++} ++ ++static int ++qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac, u16 port_mask, ++ u16 vid, u8 aging) ++{ ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ qca8k_fdb_write(priv, vid, port_mask, mac, aging); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1); ++ mutex_unlock(&priv->reg_mutex); ++ ++ return ret; ++} ++ ++static int ++qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, u16 port_mask, u16 vid) ++{ ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ qca8k_fdb_write(priv, vid, port_mask, mac, 0); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1); ++ mutex_unlock(&priv->reg_mutex); ++ ++ return ret; ++} ++ ++static void ++qca8k_fdb_flush(struct qca8k_priv *priv) ++{ ++ mutex_lock(&priv->reg_mutex); ++ qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1); ++ mutex_unlock(&priv->reg_mutex); ++} ++ ++static int ++qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) ++{ ++ u32 reg; ++ int ret; ++ ++ /* Set the command and VLAN index */ ++ reg = QCA8K_VTU_FUNC1_BUSY; ++ reg |= cmd; ++ reg |= vid << QCA8K_VTU_FUNC1_VID_S; ++ ++ /* Write the function register triggering the table access */ ++ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); ++ if (ret) ++ return ret; ++ ++ /* wait for completion */ ++ ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY); ++ if (ret) ++ return ret; ++ ++ /* Check for table full violation when adding an entry */ ++ if (cmd == QCA8K_VLAN_LOAD) { ++ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, ®); ++ if (ret < 0) ++ return ret; ++ if (reg & QCA8K_VTU_FUNC1_FULL) ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, bool untagged) ++{ ++ u32 reg; ++ int ret; ++ ++ /* ++ We do the right thing with VLAN 0 and treat it as untagged while ++ preserving the tag on egress. ++ */ ++ if (vid == 0) ++ return 0; ++ ++ mutex_lock(&priv->reg_mutex); ++ ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid); ++ if (ret < 0) ++ goto out; ++ ++ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); ++ if (ret < 0) ++ goto out; ++ reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; ++ reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); ++ if (untagged) ++ reg |= QCA8K_VTU_FUNC0_EG_MODE_UNTAG << ++ QCA8K_VTU_FUNC0_EG_MODE_S(port); ++ else ++ reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG << ++ QCA8K_VTU_FUNC0_EG_MODE_S(port); ++ ++ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); ++ if (ret) ++ goto out; ++ ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); ++ ++out: ++ mutex_unlock(&priv->reg_mutex); ++ ++ return ret; ++} ++ ++static int ++qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid) ++{ ++ u32 reg, mask; ++ int ret, i; ++ bool del; ++ ++ mutex_lock(&priv->reg_mutex); ++ ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid); ++ if (ret < 0) ++ goto out; ++ ++ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); ++ if (ret < 0) ++ goto out; ++ reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); ++ reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << ++ QCA8K_VTU_FUNC0_EG_MODE_S(port); ++ ++ /* Check if we're the last member to be removed */ ++ del = true; ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ mask = QCA8K_VTU_FUNC0_EG_MODE_NOT; ++ mask <<= QCA8K_VTU_FUNC0_EG_MODE_S(i); ++ ++ if ((reg & mask) != mask) { ++ del = false; ++ break; ++ } ++ } ++ ++ if (del) { ++ ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid); ++ } else { ++ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); ++ if (ret) ++ goto out; ++ ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); ++ } ++ ++out: ++ mutex_unlock(&priv->reg_mutex); ++ ++ return ret; ++} ++ ++static int ++qca8k_mib_init(struct qca8k_priv *priv) ++{ ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); ++ if (ret) ++ goto exit; ++ ++ ret = qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); ++ if (ret) ++ goto exit; ++ ++ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); ++ if (ret) ++ goto exit; ++ ++ ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); ++ ++exit: ++ mutex_unlock(&priv->reg_mutex); ++ return ret; ++} ++ ++static void ++qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) ++{ ++ u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC; ++ ++ /* Port 0 and 6 have no internal PHY */ ++ if (port > 0 && port < 6) ++ mask |= QCA8K_PORT_STATUS_LINK_AUTO; ++ ++ if (enable) ++ qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask); ++ else ++ qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask); ++} ++ ++static u32 ++qca8k_port_to_phy(int port) ++{ ++ /* From Andrew Lunn: ++ * Port 0 has no internal phy. ++ * Port 1 has an internal PHY at MDIO address 0. ++ * Port 2 has an internal PHY at MDIO address 1. ++ * ... ++ * Port 5 has an internal PHY at MDIO address 4. ++ * Port 6 has no internal PHY. ++ */ ++ ++ return port - 1; ++} ++ ++static int ++qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) ++{ ++ u16 r1, r2, page; ++ u32 val; ++ int ret, ret1; ++ ++ qca8k_split_addr(reg, &r1, &r2, &page); ++ ++ ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, ++ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, ++ bus, 0x10 | r2, r1, &val); ++ ++ /* Check if qca8k_read has failed for a different reason ++ * before returnting -ETIMEDOUT ++ */ ++ if (ret < 0 && ret1 < 0) ++ return ret1; ++ ++ return ret; ++} ++ ++static int ++qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) ++{ ++ u16 r1, r2, page; ++ u32 val; ++ int ret; ++ ++ if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) ++ return -EINVAL; ++ ++ val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | ++ QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | ++ QCA8K_MDIO_MASTER_REG_ADDR(regnum) | ++ QCA8K_MDIO_MASTER_DATA(data); ++ ++ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = qca8k_set_page(bus, page); ++ if (ret) ++ goto exit; ++ ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ ++ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_BUSY); ++ ++exit: ++ /* even if the busy_wait timeouts try to clear the MASTER_EN */ ++ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) ++{ ++ u16 r1, r2, page; ++ u32 val; ++ int ret; ++ ++ if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) ++ return -EINVAL; ++ ++ val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | ++ QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | ++ QCA8K_MDIO_MASTER_REG_ADDR(regnum); ++ ++ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = qca8k_set_page(bus, page); ++ if (ret) ++ goto exit; ++ ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ ++ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_BUSY); ++ if (ret) ++ goto exit; ++ ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); ++ ++exit: ++ /* even if the busy_wait timeouts try to clear the MASTER_EN */ ++ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ if (ret >= 0) ++ ret = val & QCA8K_MDIO_MASTER_DATA_MASK; ++ ++ return ret; ++} ++ ++static int ++qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data) ++{ ++ struct qca8k_priv *priv = slave_bus->priv; ++ struct mii_bus *bus = priv->bus; ++ ++ return qca8k_mdio_write(bus, phy, regnum, data); ++} ++ ++static int ++qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) ++{ ++ struct qca8k_priv *priv = slave_bus->priv; ++ struct mii_bus *bus = priv->bus; ++ ++ return qca8k_mdio_read(bus, phy, regnum); ++} ++ ++static int ++qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ /* Check if the legacy mapping should be used and the ++ * port is not correctly mapped to the right PHY in the ++ * devicetree ++ */ ++ if (priv->legacy_phy_port_mapping) ++ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; ++ ++ return qca8k_mdio_write(priv->bus, port, regnum, data); ++} ++ ++static int ++qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int ret; ++ ++ /* Check if the legacy mapping should be used and the ++ * port is not correctly mapped to the right PHY in the ++ * devicetree ++ */ ++ if (priv->legacy_phy_port_mapping) ++ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; ++ ++ ret = qca8k_mdio_read(priv->bus, port, regnum); ++ ++ if (ret < 0) ++ return 0xffff; ++ ++ return ret; ++} ++ ++static int ++qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio) ++{ ++ struct dsa_switch *ds = priv->ds; ++ struct mii_bus *bus; ++ ++ bus = devm_mdiobus_alloc(ds->dev); ++ ++ if (!bus) ++ return -ENOMEM; ++ ++ bus->priv = (void *)priv; ++ bus->name = "qca8k slave mii"; ++ bus->read = qca8k_internal_mdio_read; ++ bus->write = qca8k_internal_mdio_write; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d", ++ ds->index); ++ ++ bus->parent = ds->dev; ++ bus->phy_mask = ~ds->phys_mii_mask; ++ ++ ds->slave_mii_bus = bus; ++ ++ return devm_of_mdiobus_register(priv->dev, bus, mdio); ++} ++ ++static int ++qca8k_setup_mdio_bus(struct qca8k_priv *priv) ++{ ++ u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg; ++ struct device_node *ports, *port, *mdio; ++ phy_interface_t mode; ++ int err; ++ ++ ports = of_get_child_by_name(priv->dev->of_node, "ports"); ++ if (!ports) ++ ports = of_get_child_by_name(priv->dev->of_node, "ethernet-ports"); ++ ++ if (!ports) ++ return -EINVAL; ++ ++ for_each_available_child_of_node(ports, port) { ++ err = of_property_read_u32(port, "reg", ®); ++ if (err) { ++ of_node_put(port); ++ of_node_put(ports); ++ return err; ++ } ++ ++ if (!dsa_is_user_port(priv->ds, reg)) ++ continue; ++ ++ of_get_phy_mode(port, &mode); ++ ++ if (of_property_read_bool(port, "phy-handle") && ++ mode != PHY_INTERFACE_MODE_INTERNAL) ++ external_mdio_mask |= BIT(reg); ++ else ++ internal_mdio_mask |= BIT(reg); ++ } ++ ++ of_node_put(ports); ++ if (!external_mdio_mask && !internal_mdio_mask) { ++ dev_err(priv->dev, "no PHYs are defined.\n"); ++ return -EINVAL; ++ } ++ ++ /* The QCA8K_MDIO_MASTER_EN Bit, which grants access to PHYs through ++ * the MDIO_MASTER register also _disconnects_ the external MDC ++ * passthrough to the internal PHYs. It's not possible to use both ++ * configurations at the same time! ++ * ++ * Because this came up during the review process: ++ * If the external mdio-bus driver is capable magically disabling ++ * the QCA8K_MDIO_MASTER_EN and mutex/spin-locking out the qca8k's ++ * accessors for the time being, it would be possible to pull this ++ * off. ++ */ ++ if (!!external_mdio_mask && !!internal_mdio_mask) { ++ dev_err(priv->dev, "either internal or external mdio bus configuration is supported.\n"); ++ return -EINVAL; ++ } ++ ++ if (external_mdio_mask) { ++ /* Make sure to disable the internal mdio bus in cases ++ * a dt-overlay and driver reload changed the configuration ++ */ ++ ++ return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_EN); ++ } ++ ++ /* Check if the devicetree declare the port:phy mapping */ ++ mdio = of_get_child_by_name(priv->dev->of_node, "mdio"); ++ if (of_device_is_available(mdio)) { ++ err = qca8k_mdio_register(priv, mdio); ++ if (err) ++ of_node_put(mdio); ++ ++ return err; ++ } ++ ++ /* If a mapping can't be found the legacy mapping is used, ++ * using the qca8k_port_to_phy function ++ */ ++ priv->legacy_phy_port_mapping = true; ++ priv->ops.phy_read = qca8k_phy_read; ++ priv->ops.phy_write = qca8k_phy_write; ++ ++ return 0; ++} ++ ++static int ++qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv) ++{ ++ u32 mask = 0; ++ int ret = 0; ++ ++ /* SoC specific settings for ipq8064. ++ * If more device require this consider adding ++ * a dedicated binding. ++ */ ++ if (of_machine_is_compatible("qcom,ipq8064")) ++ mask |= QCA8K_MAC_PWR_RGMII0_1_8V; ++ ++ /* SoC specific settings for ipq8065 */ ++ if (of_machine_is_compatible("qcom,ipq8065")) ++ mask |= QCA8K_MAC_PWR_RGMII1_1_8V; ++ ++ if (mask) { ++ ret = qca8k_rmw(priv, QCA8K_REG_MAC_PWR_SEL, ++ QCA8K_MAC_PWR_RGMII0_1_8V | ++ QCA8K_MAC_PWR_RGMII1_1_8V, ++ mask); ++ } ++ ++ return ret; ++} ++ ++static int qca8k_find_cpu_port(struct dsa_switch *ds) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ /* Find the connected cpu port. Valid port are 0 or 6 */ ++ if (dsa_is_cpu_port(ds, 0)) ++ return 0; ++ ++ dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6"); ++ ++ if (dsa_is_cpu_port(ds, 6)) ++ return 6; ++ ++ return -EINVAL; ++} ++ ++static int ++qca8k_setup_of_pws_reg(struct qca8k_priv *priv) ++{ ++ struct device_node *node = priv->dev->of_node; ++ const struct qca8k_match_data *data; ++ u32 val = 0; ++ int ret; ++ ++ /* QCA8327 require to set to the correct mode. ++ * His bigger brother QCA8328 have the 172 pin layout. ++ * Should be applied by default but we set this just to make sure. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8327) { ++ data = of_device_get_match_data(priv->dev); ++ ++ /* Set the correct package of 148 pin for QCA8327 */ ++ if (data->reduced_package) ++ val |= QCA8327_PWS_PACKAGE148_EN; ++ ++ ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN, ++ val); ++ if (ret) ++ return ret; ++ } ++ ++ if (of_property_read_bool(node, "qca,ignore-power-on-sel")) ++ val |= QCA8K_PWS_POWER_ON_SEL; ++ ++ if (of_property_read_bool(node, "qca,led-open-drain")) { ++ if (!(val & QCA8K_PWS_POWER_ON_SEL)) { ++ dev_err(priv->dev, "qca,led-open-drain require qca,ignore-power-on-sel to be set."); ++ return -EINVAL; ++ } ++ ++ val |= QCA8K_PWS_LED_OPEN_EN_CSR; ++ } ++ ++ return qca8k_rmw(priv, QCA8K_REG_PWS, ++ QCA8K_PWS_LED_OPEN_EN_CSR | QCA8K_PWS_POWER_ON_SEL, ++ val); ++} ++ ++static int ++qca8k_parse_port_config(struct qca8k_priv *priv) ++{ ++ int port, cpu_port_index = -1, ret; ++ struct device_node *port_dn; ++ phy_interface_t mode; ++ struct dsa_port *dp; ++ u32 delay; ++ ++ /* We have 2 CPU port. Check them */ ++ for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) { ++ /* Skip every other port */ ++ if (port != 0 && port != 6) ++ continue; ++ ++ dp = dsa_to_port(priv->ds, port); ++ port_dn = dp->dn; ++ cpu_port_index++; ++ ++ if (!of_device_is_available(port_dn)) ++ continue; ++ ++ ret = of_get_phy_mode(port_dn, &mode); ++ if (ret) ++ continue; ++ ++ switch (mode) { ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_SGMII: ++ delay = 0; ++ ++ if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay)) ++ /* Switch regs accept value in ns, convert ps to ns */ ++ delay = delay / 1000; ++ else if (mode == PHY_INTERFACE_MODE_RGMII_ID || ++ mode == PHY_INTERFACE_MODE_RGMII_TXID) ++ delay = 1; ++ ++ if (delay > QCA8K_MAX_DELAY) { ++ dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); ++ delay = 3; ++ } ++ ++ priv->ports_config.rgmii_tx_delay[cpu_port_index] = delay; ++ ++ delay = 0; ++ ++ if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay)) ++ /* Switch regs accept value in ns, convert ps to ns */ ++ delay = delay / 1000; ++ else if (mode == PHY_INTERFACE_MODE_RGMII_ID || ++ mode == PHY_INTERFACE_MODE_RGMII_RXID) ++ delay = 2; ++ ++ if (delay > QCA8K_MAX_DELAY) { ++ dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); ++ delay = 3; ++ } ++ ++ priv->ports_config.rgmii_rx_delay[cpu_port_index] = delay; ++ ++ /* Skip sgmii parsing for rgmii* mode */ ++ if (mode == PHY_INTERFACE_MODE_RGMII || ++ mode == PHY_INTERFACE_MODE_RGMII_ID || ++ mode == PHY_INTERFACE_MODE_RGMII_TXID || ++ mode == PHY_INTERFACE_MODE_RGMII_RXID) ++ break; ++ ++ if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge")) ++ priv->ports_config.sgmii_tx_clk_falling_edge = true; ++ ++ if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge")) ++ priv->ports_config.sgmii_rx_clk_falling_edge = true; ++ ++ if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) { ++ priv->ports_config.sgmii_enable_pll = true; ++ ++ if (priv->switch_id == QCA8K_ID_QCA8327) { ++ dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling"); ++ priv->ports_config.sgmii_enable_pll = false; ++ } ++ ++ if (priv->switch_revision < 2) ++ dev_warn(priv->dev, "SGMII PLL should NOT be enabled for qca8337 with revision 2 or more."); ++ } ++ ++ break; ++ default: ++ continue; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_setup(struct dsa_switch *ds) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ int cpu_port, ret, i; ++ u32 mask; ++ ++ cpu_port = qca8k_find_cpu_port(ds); ++ if (cpu_port < 0) { ++ dev_err(priv->dev, "No cpu port configured in both cpu port0 and port6"); ++ return cpu_port; ++ } ++ ++ /* Parse CPU port config to be later used in phy_link mac_config */ ++ ret = qca8k_parse_port_config(priv); ++ if (ret) ++ return ret; ++ ++ mutex_init(&priv->reg_mutex); ++ ++ /* Start by setting up the register mapping */ ++ priv->regmap = devm_regmap_init(ds->dev, NULL, priv, ++ &qca8k_regmap_config); ++ if (IS_ERR(priv->regmap)) ++ dev_warn(priv->dev, "regmap initialization failed"); ++ ++ ret = qca8k_setup_mdio_bus(priv); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_setup_of_pws_reg(priv); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_setup_mac_pwr_sel(priv); ++ if (ret) ++ return ret; ++ ++ /* Enable CPU Port */ ++ ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, ++ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling CPU port"); ++ return ret; ++ } ++ ++ /* Enable MIB counters */ ++ ret = qca8k_mib_init(priv); ++ if (ret) ++ dev_warn(priv->dev, "mib init failed"); ++ ++ /* Initial setup of all ports */ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ /* Disable forwarding by default on all ports */ ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_MEMBER, 0); ++ if (ret) ++ return ret; ++ ++ /* Enable QCA header mode on all cpu ports */ ++ if (dsa_is_cpu_port(ds, i)) { ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode"); ++ return ret; ++ } ++ } ++ ++ /* Disable MAC by default on all user ports */ ++ if (dsa_is_user_port(ds, i)) ++ qca8k_port_set_status(priv, i, 0); ++ } ++ ++ /* Forward all unknown frames to CPU port for Linux processing ++ * Notice that in multi-cpu config only one port should be set ++ * for igmp, unknown, multicast and broadcast packet ++ */ ++ ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); ++ if (ret) ++ return ret; ++ ++ /* Setup connection between CPU port & user ports ++ * Configure specific switch configuration for ports ++ */ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ /* CPU port gets connected to all user ports of the switch */ ++ if (dsa_is_cpu_port(ds, i)) { ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); ++ if (ret) ++ return ret; ++ } ++ ++ /* Individual user ports get connected to CPU port only */ ++ if (dsa_is_user_port(ds, i)) { ++ int shift = 16 * (i % 2); ++ ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ BIT(cpu_port)); ++ if (ret) ++ return ret; ++ ++ /* Enable ARP Auto-learning by default */ ++ ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; ++ ++ /* For port based vlans to work we need to set the ++ * default egress vid ++ */ ++ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), ++ 0xfff << shift, ++ QCA8K_PORT_VID_DEF << shift); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), ++ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | ++ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; ++ } ++ ++ /* The port 5 of the qca8337 have some problem in flood condition. The ++ * original legacy driver had some specific buffer and priority settings ++ * for the different port suggested by the QCA switch team. Add this ++ * missing settings to improve switch stability under load condition. ++ * This problem is limited to qca8337 and other qca8k switch are not affected. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) { ++ switch (i) { ++ /* The 2 CPU port and port 5 requires some different ++ * priority than any other ports. ++ */ ++ case 0: ++ case 5: ++ case 6: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); ++ break; ++ default: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); ++ } ++ qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); ++ ++ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN; ++ qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), ++ QCA8K_PORT_HOL_CTRL1_ING_BUF | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN, ++ mask); ++ } ++ ++ /* Set initial MTU for every port. ++ * We have only have a general MTU setting. So track ++ * every port and set the max across all port. ++ */ ++ priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; ++ } ++ ++ /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ ++ if (priv->switch_id == QCA8K_ID_QCA8327) { ++ mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | ++ QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); ++ qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, ++ QCA8K_GLOBAL_FC_GOL_XON_THRES_S | ++ QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S, ++ mask); ++ } ++ ++ /* Setup our port MTUs to match power on defaults */ ++ ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); ++ if (ret) ++ dev_warn(priv->dev, "failed setting MTU settings"); ++ ++ /* Flush the FDB table */ ++ qca8k_fdb_flush(priv); ++ ++ /* We don't have interrupts for link changes, so we need to poll */ ++ ds->pcs_poll = true; ++ ++ return 0; ++} ++ ++static void ++qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_index, ++ u32 reg) ++{ ++ u32 delay, val = 0; ++ int ret; ++ ++ /* Delay can be declared in 3 different way. ++ * Mode to rgmii and internal-delay standard binding defined ++ * rgmii-id or rgmii-tx/rx phy mode set. ++ * The parse logic set a delay different than 0 only when one ++ * of the 3 different way is used. In all other case delay is ++ * not enabled. With ID or TX/RXID delay is enabled and set ++ * to the default and recommended value. ++ */ ++ if (priv->ports_config.rgmii_tx_delay[cpu_port_index]) { ++ delay = priv->ports_config.rgmii_tx_delay[cpu_port_index]; ++ ++ val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) | ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN; ++ } ++ ++ if (priv->ports_config.rgmii_rx_delay[cpu_port_index]) { ++ delay = priv->ports_config.rgmii_rx_delay[cpu_port_index]; ++ ++ val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN; ++ } ++ ++ /* Set RGMII delay based on the selected values */ ++ ret = qca8k_rmw(priv, reg, ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK | ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN, ++ val); ++ if (ret) ++ dev_err(priv->dev, "Failed to set internal delay for CPU port%d", ++ cpu_port_index == QCA8K_CPU_PORT0 ? 0 : 6); ++} ++ ++static void ++qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int cpu_port_index, ret; ++ u32 reg, val; ++ ++ switch (port) { ++ case 0: /* 1st CPU port */ ++ if (state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && ++ state->interface != PHY_INTERFACE_MODE_SGMII) ++ return; ++ ++ reg = QCA8K_REG_PORT0_PAD_CTRL; ++ cpu_port_index = QCA8K_CPU_PORT0; ++ break; ++ case 1: ++ case 2: ++ case 3: ++ case 4: ++ case 5: ++ /* Internal PHY, nothing to do */ ++ return; ++ case 6: /* 2nd CPU port / external PHY */ ++ if (state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && ++ state->interface != PHY_INTERFACE_MODE_SGMII && ++ state->interface != PHY_INTERFACE_MODE_1000BASEX) ++ return; ++ ++ reg = QCA8K_REG_PORT6_PAD_CTRL; ++ cpu_port_index = QCA8K_CPU_PORT6; ++ break; ++ default: ++ dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); ++ return; ++ } ++ ++ if (port != 6 && phylink_autoneg_inband(mode)) { ++ dev_err(ds->dev, "%s: in-band negotiation unsupported\n", ++ __func__); ++ return; ++ } ++ ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN); ++ ++ /* Configure rgmii delay */ ++ qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); ++ ++ /* QCA8337 requires to set rgmii rx delay for all ports. ++ * This is enabled through PORT5_PAD_CTRL for all ports, ++ * rather than individual port registers. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) ++ qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ /* Enable SGMII on the port */ ++ qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); ++ ++ /* Enable/disable SerDes auto-negotiation as necessary */ ++ ret = qca8k_read(priv, QCA8K_REG_PWS, &val); ++ if (ret) ++ return; ++ if (phylink_autoneg_inband(mode)) ++ val &= ~QCA8K_PWS_SERDES_AEN_DIS; ++ else ++ val |= QCA8K_PWS_SERDES_AEN_DIS; ++ qca8k_write(priv, QCA8K_REG_PWS, val); ++ ++ /* Configure the SGMII parameters */ ++ ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); ++ if (ret) ++ return; ++ ++ val |= QCA8K_SGMII_EN_SD; ++ ++ if (priv->ports_config.sgmii_enable_pll) ++ val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | ++ QCA8K_SGMII_EN_TX; ++ ++ if (dsa_is_cpu_port(ds, port)) { ++ /* CPU port, we're talking to the CPU MAC, be a PHY */ ++ val &= ~QCA8K_SGMII_MODE_CTRL_MASK; ++ val |= QCA8K_SGMII_MODE_CTRL_PHY; ++ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { ++ val &= ~QCA8K_SGMII_MODE_CTRL_MASK; ++ val |= QCA8K_SGMII_MODE_CTRL_MAC; ++ } else if (state->interface == PHY_INTERFACE_MODE_1000BASEX) { ++ val &= ~QCA8K_SGMII_MODE_CTRL_MASK; ++ val |= QCA8K_SGMII_MODE_CTRL_BASEX; ++ } ++ ++ qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val); ++ ++ /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and ++ * falling edge is set writing in the PORT0 PAD reg ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8327 || ++ priv->switch_id == QCA8K_ID_QCA8337) ++ reg = QCA8K_REG_PORT0_PAD_CTRL; ++ ++ val = 0; ++ ++ /* SGMII Clock phase configuration */ ++ if (priv->ports_config.sgmii_rx_clk_falling_edge) ++ val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE; ++ ++ if (priv->ports_config.sgmii_tx_clk_falling_edge) ++ val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE; ++ ++ if (val) ++ ret = qca8k_rmw(priv, reg, ++ QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE | ++ QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, ++ val); ++ ++ /* From original code is reported port instability as SGMII also ++ * require delay set. Apply advised values here or take them from DT. ++ */ ++ if (state->interface == PHY_INTERFACE_MODE_SGMII) ++ qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); ++ ++ break; ++ default: ++ dev_err(ds->dev, "xMII mode %s not supported for port %d\n", ++ phy_modes(state->interface), port); ++ return; ++ } ++} ++ ++static void ++qca8k_phylink_validate(struct dsa_switch *ds, int port, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; ++ ++ switch (port) { ++ case 0: /* 1st CPU port */ ++ if (state->interface != PHY_INTERFACE_MODE_NA && ++ state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && ++ state->interface != PHY_INTERFACE_MODE_SGMII) ++ goto unsupported; ++ break; ++ case 1: ++ case 2: ++ case 3: ++ case 4: ++ case 5: ++ /* Internal PHY */ ++ if (state->interface != PHY_INTERFACE_MODE_NA && ++ state->interface != PHY_INTERFACE_MODE_GMII && ++ state->interface != PHY_INTERFACE_MODE_INTERNAL) ++ goto unsupported; ++ break; ++ case 6: /* 2nd CPU port / external PHY */ ++ if (state->interface != PHY_INTERFACE_MODE_NA && ++ state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && ++ state->interface != PHY_INTERFACE_MODE_SGMII && ++ state->interface != PHY_INTERFACE_MODE_1000BASEX) ++ goto unsupported; ++ break; ++ default: ++unsupported: ++ linkmode_zero(supported); ++ return; ++ } ++ ++ phylink_set_port_modes(mask); ++ phylink_set(mask, Autoneg); ++ ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, 10baseT_Half); ++ phylink_set(mask, 10baseT_Full); ++ phylink_set(mask, 100baseT_Half); ++ phylink_set(mask, 100baseT_Full); ++ ++ if (state->interface == PHY_INTERFACE_MODE_1000BASEX) ++ phylink_set(mask, 1000baseX_Full); ++ ++ phylink_set(mask, Pause); ++ phylink_set(mask, Asym_Pause); ++ ++ linkmode_and(supported, supported, mask); ++ linkmode_and(state->advertising, state->advertising, mask); ++} ++ ++static int ++qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port, ++ struct phylink_link_state *state) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ u32 reg; ++ int ret; ++ ++ ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), ®); ++ if (ret < 0) ++ return ret; ++ ++ state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); ++ state->an_complete = state->link; ++ state->an_enabled = !!(reg & QCA8K_PORT_STATUS_LINK_AUTO); ++ state->duplex = (reg & QCA8K_PORT_STATUS_DUPLEX) ? DUPLEX_FULL : ++ DUPLEX_HALF; ++ ++ switch (reg & QCA8K_PORT_STATUS_SPEED) { ++ case QCA8K_PORT_STATUS_SPEED_10: ++ state->speed = SPEED_10; ++ break; ++ case QCA8K_PORT_STATUS_SPEED_100: ++ state->speed = SPEED_100; ++ break; ++ case QCA8K_PORT_STATUS_SPEED_1000: ++ state->speed = SPEED_1000; ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ break; ++ } ++ ++ state->pause = MLO_PAUSE_NONE; ++ if (reg & QCA8K_PORT_STATUS_RXFLOW) ++ state->pause |= MLO_PAUSE_RX; ++ if (reg & QCA8K_PORT_STATUS_TXFLOW) ++ state->pause |= MLO_PAUSE_TX; ++ ++ return 1; ++} ++ ++static void ++qca8k_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ qca8k_port_set_status(priv, port, 0); ++} ++ ++static void ++qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, ++ phy_interface_t interface, struct phy_device *phydev, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ u32 reg; ++ ++ if (phylink_autoneg_inband(mode)) { ++ reg = QCA8K_PORT_STATUS_LINK_AUTO; ++ } else { ++ switch (speed) { ++ case SPEED_10: ++ reg = QCA8K_PORT_STATUS_SPEED_10; ++ break; ++ case SPEED_100: ++ reg = QCA8K_PORT_STATUS_SPEED_100; ++ break; ++ case SPEED_1000: ++ reg = QCA8K_PORT_STATUS_SPEED_1000; ++ break; ++ default: ++ reg = QCA8K_PORT_STATUS_LINK_AUTO; ++ break; ++ } ++ ++ if (duplex == DUPLEX_FULL) ++ reg |= QCA8K_PORT_STATUS_DUPLEX; ++ ++ if (rx_pause || dsa_is_cpu_port(ds, port)) ++ reg |= QCA8K_PORT_STATUS_RXFLOW; ++ ++ if (tx_pause || dsa_is_cpu_port(ds, port)) ++ reg |= QCA8K_PORT_STATUS_TXFLOW; ++ } ++ ++ reg |= QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC; ++ ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg); ++} ++ ++static void ++qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) ++{ ++ int i; ++ ++ if (stringset != ETH_SS_STATS) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) ++ strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name, ++ ETH_GSTRING_LEN); ++} ++ ++static void ++qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, ++ uint64_t *data) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ const struct qca8k_mib_desc *mib; ++ u32 reg, i, val; ++ u32 hi = 0; ++ int ret; ++ ++ for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { ++ mib = &ar8327_mib[i]; ++ reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; ++ ++ ret = qca8k_read(priv, reg, &val); ++ if (ret < 0) ++ continue; ++ ++ if (mib->size == 2) { ++ ret = qca8k_read(priv, reg + 4, &hi); ++ if (ret < 0) ++ continue; ++ } ++ ++ data[i] = val; ++ if (mib->size == 2) ++ data[i] |= (u64)hi << 32; ++ } ++} ++ ++static int ++qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset) ++{ ++ if (sset != ETH_SS_STATS) ++ return 0; ++ ++ return ARRAY_SIZE(ar8327_mib); ++} ++ ++static int ++qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *eee) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port); ++ u32 reg; ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®); ++ if (ret < 0) ++ goto exit; ++ ++ if (eee->eee_enabled) ++ reg |= lpi_en; ++ else ++ reg &= ~lpi_en; ++ ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); ++ ++exit: ++ mutex_unlock(&priv->reg_mutex); ++ return ret; ++} ++ ++static int ++qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) ++{ ++ /* Nothing to do on the port's MAC */ ++ return 0; ++} ++ ++static void ++qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ u32 stp_state; ++ ++ switch (state) { ++ case BR_STATE_DISABLED: ++ stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED; ++ break; ++ case BR_STATE_BLOCKING: ++ stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING; ++ break; ++ case BR_STATE_LISTENING: ++ stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING; ++ break; ++ case BR_STATE_LEARNING: ++ stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; ++ break; ++ case BR_STATE_FORWARDING: ++ default: ++ stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; ++ break; ++ } ++ ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); ++} ++ ++static int ++qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ int port_mask, cpu_port; ++ int i, ret; ++ ++ cpu_port = dsa_to_port(ds, port)->cpu_dp->index; ++ port_mask = BIT(cpu_port); ++ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (dsa_is_cpu_port(ds, i)) ++ continue; ++ if (dsa_to_port(ds, i)->bridge_dev != br) ++ continue; ++ /* Add this port to the portvlan mask of the other ports ++ * in the bridge ++ */ ++ ret = qca8k_reg_set(priv, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); ++ if (ret) ++ return ret; ++ if (i != port) ++ port_mask |= BIT(i); ++ } ++ ++ /* Add all other ports to this ports portvlan mask */ ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, port_mask); ++ ++ return ret; ++} ++ ++static void ++qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ int cpu_port, i; ++ ++ cpu_port = dsa_to_port(ds, port)->cpu_dp->index; ++ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (dsa_is_cpu_port(ds, i)) ++ continue; ++ if (dsa_to_port(ds, i)->bridge_dev != br) ++ continue; ++ /* Remove this port to the portvlan mask of the other ports ++ * in the bridge ++ */ ++ qca8k_reg_clear(priv, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); ++ } ++ ++ /* Set the cpu port to be the only one in the portvlan mask of ++ * this port ++ */ ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); ++} ++ ++static int ++qca8k_port_enable(struct dsa_switch *ds, int port, ++ struct phy_device *phy) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ ++ qca8k_port_set_status(priv, port, 1); ++ priv->port_sts[port].enabled = 1; ++ ++ if (dsa_is_user_port(ds, port)) ++ phy_support_asym_pause(phy); ++ ++ return 0; ++} ++ ++static void ++qca8k_port_disable(struct dsa_switch *ds, int port) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ ++ qca8k_port_set_status(priv, port, 0); ++ priv->port_sts[port].enabled = 0; ++} ++ ++static int ++qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int i, mtu = 0; ++ ++ priv->port_mtu[port] = new_mtu; ++ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) ++ if (priv->port_mtu[i] > mtu) ++ mtu = priv->port_mtu[i]; ++ ++ /* Include L2 header / FCS length */ ++ return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN); ++} ++ ++static int ++qca8k_port_max_mtu(struct dsa_switch *ds, int port) ++{ ++ return QCA8K_MAX_MTU; ++} ++ ++static int ++qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr, ++ u16 port_mask, u16 vid) ++{ ++ /* Set the vid to the port vlan id if no vid is set */ ++ if (!vid) ++ vid = QCA8K_PORT_VID_DEF; ++ ++ return qca8k_fdb_add(priv, addr, port_mask, vid, ++ QCA8K_ATU_STATUS_STATIC); ++} ++ ++static int ++qca8k_port_fdb_add(struct dsa_switch *ds, int port, ++ const unsigned char *addr, u16 vid) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ u16 port_mask = BIT(port); ++ ++ return qca8k_port_fdb_insert(priv, addr, port_mask, vid); ++} ++ ++static int ++qca8k_port_fdb_del(struct dsa_switch *ds, int port, ++ const unsigned char *addr, u16 vid) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ u16 port_mask = BIT(port); ++ ++ if (!vid) ++ vid = QCA8K_PORT_VID_DEF; ++ ++ return qca8k_fdb_del(priv, addr, port_mask, vid); ++} ++ ++static int ++qca8k_port_fdb_dump(struct dsa_switch *ds, int port, ++ dsa_fdb_dump_cb_t *cb, void *data) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ struct qca8k_fdb _fdb = { 0 }; ++ int cnt = QCA8K_NUM_FDB_RECORDS; ++ bool is_static; ++ int ret = 0; ++ ++ mutex_lock(&priv->reg_mutex); ++ while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) { ++ if (!_fdb.aging) ++ break; ++ is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC); ++ ret = cb(_fdb.mac, _fdb.vid, is_static, data); ++ if (ret) ++ break; ++ } ++ mutex_unlock(&priv->reg_mutex); ++ ++ return 0; ++} ++ ++static int ++qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, ++ struct switchdev_trans *trans) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ if (switchdev_trans_ph_prepare(trans)) ++ return 0; ++ ++ if (vlan_filtering) { ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_VLAN_MODE, ++ QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE); ++ } else { ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_VLAN_MODE, ++ QCA8K_PORT_LOOKUP_VLAN_MODE_NONE); ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_port_vlan_prepare(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_vlan *vlan) ++{ ++ return 0; ++} ++ ++static void ++qca8k_port_vlan_add(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_vlan *vlan) ++{ ++ bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; ++ bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; ++ struct qca8k_priv *priv = ds->priv; ++ int ret = 0; ++ u16 vid; ++ ++ for (vid = vlan->vid_begin; vid <= vlan->vid_end && !ret; ++vid) ++ ret = qca8k_vlan_add(priv, port, vid, untagged); ++ ++ if (ret) ++ dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret); ++ ++ if (pvid) { ++ int shift = 16 * (port % 2); ++ ++ qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), ++ 0xfff << shift, ++ vlan->vid_end << shift); ++ qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), ++ QCA8K_PORT_VLAN_CVID(vlan->vid_end) | ++ QCA8K_PORT_VLAN_SVID(vlan->vid_end)); ++ } ++} ++ ++static int ++qca8k_port_vlan_del(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_vlan *vlan) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int ret = 0; ++ u16 vid; ++ ++ for (vid = vlan->vid_begin; vid <= vlan->vid_end && !ret; ++vid) ++ ret = qca8k_vlan_del(priv, port, vid); ++ ++ if (ret) ++ dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret); ++ ++ return ret; ++} ++ ++static u32 qca8k_get_phy_flags(struct dsa_switch *ds, int port) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ /* Communicate to the phy internal driver the switch revision. ++ * Based on the switch revision different values needs to be ++ * set to the dbg and mmd reg on the phy. ++ * The first 2 bit are used to communicate the switch revision ++ * to the phy driver. ++ */ ++ if (port > 0 && port < 6) ++ return priv->switch_revision; ++ ++ return 0; ++} ++ ++static enum dsa_tag_protocol ++qca8k_get_tag_protocol(struct dsa_switch *ds, int port, ++ enum dsa_tag_protocol mp) ++{ ++ return DSA_TAG_PROTO_QCA; ++} ++ ++static const struct dsa_switch_ops qca8k_switch_ops = { ++ .get_tag_protocol = qca8k_get_tag_protocol, ++ .setup = qca8k_setup, ++ .get_strings = qca8k_get_strings, ++ .get_ethtool_stats = qca8k_get_ethtool_stats, ++ .get_sset_count = qca8k_get_sset_count, ++ .get_mac_eee = qca8k_get_mac_eee, ++ .set_mac_eee = qca8k_set_mac_eee, ++ .port_enable = qca8k_port_enable, ++ .port_disable = qca8k_port_disable, ++ .port_change_mtu = qca8k_port_change_mtu, ++ .port_max_mtu = qca8k_port_max_mtu, ++ .port_stp_state_set = qca8k_port_stp_state_set, ++ .port_bridge_join = qca8k_port_bridge_join, ++ .port_bridge_leave = qca8k_port_bridge_leave, ++ .port_fdb_add = qca8k_port_fdb_add, ++ .port_fdb_del = qca8k_port_fdb_del, ++ .port_fdb_dump = qca8k_port_fdb_dump, ++ .port_vlan_filtering = qca8k_port_vlan_filtering, ++ .port_vlan_prepare = qca8k_port_vlan_prepare, ++ .port_vlan_add = qca8k_port_vlan_add, ++ .port_vlan_del = qca8k_port_vlan_del, ++ .phylink_validate = qca8k_phylink_validate, ++ .phylink_mac_link_state = qca8k_phylink_mac_link_state, ++ .phylink_mac_config = qca8k_phylink_mac_config, ++ .phylink_mac_link_down = qca8k_phylink_mac_link_down, ++ .phylink_mac_link_up = qca8k_phylink_mac_link_up, ++ .get_phy_flags = qca8k_get_phy_flags, ++}; ++ ++static int qca8k_read_switch_id(struct qca8k_priv *priv) ++{ ++ const struct qca8k_match_data *data; ++ u32 val; ++ u8 id; ++ int ret; ++ ++ /* get the switches ID from the compatible */ ++ data = of_device_get_match_data(priv->dev); ++ if (!data) ++ return -ENODEV; ++ ++ ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val); ++ if (ret < 0) ++ return -ENODEV; ++ ++ id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); ++ if (id != data->id) { ++ dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); ++ return -ENODEV; ++ } ++ ++ priv->switch_id = id; ++ ++ /* Save revision to communicate to the internal PHY driver */ ++ priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK); ++ ++ return 0; ++} ++ ++static int ++qca8k_sw_probe(struct mdio_device *mdiodev) ++{ ++ struct qca8k_priv *priv; ++ int ret; ++ ++ /* allocate the private data struct so that we can probe the switches ++ * ID register ++ */ ++ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->bus = mdiodev->bus; ++ priv->dev = &mdiodev->dev; ++ ++ priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset", ++ GPIOD_ASIS); ++ if (IS_ERR(priv->reset_gpio)) ++ return PTR_ERR(priv->reset_gpio); ++ ++ if (priv->reset_gpio) { ++ gpiod_set_value_cansleep(priv->reset_gpio, 1); ++ /* The active low duration must be greater than 10 ms ++ * and checkpatch.pl wants 20 ms. ++ */ ++ msleep(20); ++ gpiod_set_value_cansleep(priv->reset_gpio, 0); ++ } ++ ++ /* Check the detected switch id */ ++ ret = qca8k_read_switch_id(priv); ++ if (ret) ++ return ret; ++ ++ priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); ++ if (!priv->ds) ++ return -ENOMEM; ++ ++ priv->ds->dev = &mdiodev->dev; ++ priv->ds->num_ports = QCA8K_NUM_PORTS; ++ priv->ds->configure_vlan_while_not_filtering = true; ++ priv->ds->priv = priv; ++ priv->ops = qca8k_switch_ops; ++ priv->ds->ops = &priv->ops; ++ mutex_init(&priv->reg_mutex); ++ dev_set_drvdata(&mdiodev->dev, priv); ++ ++ return dsa_register_switch(priv->ds); ++} ++ ++static void ++qca8k_sw_remove(struct mdio_device *mdiodev) ++{ ++ struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); ++ int i; ++ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) ++ qca8k_port_set_status(priv, i, 0); ++ ++ dsa_unregister_switch(priv->ds); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static void ++qca8k_set_pm(struct qca8k_priv *priv, int enable) ++{ ++ int i; ++ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (!priv->port_sts[i].enabled) ++ continue; ++ ++ qca8k_port_set_status(priv, i, enable); ++ } ++} ++ ++static int qca8k_suspend(struct device *dev) ++{ ++ struct qca8k_priv *priv = dev_get_drvdata(dev); ++ ++ qca8k_set_pm(priv, 0); ++ ++ return dsa_switch_suspend(priv->ds); ++} ++ ++static int qca8k_resume(struct device *dev) ++{ ++ struct qca8k_priv *priv = dev_get_drvdata(dev); ++ ++ qca8k_set_pm(priv, 1); ++ ++ return dsa_switch_resume(priv->ds); ++} ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, ++ qca8k_suspend, qca8k_resume); ++ ++static const struct qca8k_match_data qca8327 = { ++ .id = QCA8K_ID_QCA8327, ++ .reduced_package = true, ++}; ++ ++static const struct qca8k_match_data qca8328 = { ++ .id = QCA8K_ID_QCA8327, ++}; ++ ++static const struct qca8k_match_data qca833x = { ++ .id = QCA8K_ID_QCA8337, ++}; ++ ++static const struct of_device_id qca8k_of_match[] = { ++ { .compatible = "qca,qca8327", .data = &qca8327 }, ++ { .compatible = "qca,qca8328", .data = &qca8328 }, ++ { .compatible = "qca,qca8334", .data = &qca833x }, ++ { .compatible = "qca,qca8337", .data = &qca833x }, ++ { /* sentinel */ }, ++}; ++ ++static struct mdio_driver qca8kmdio_driver = { ++ .probe = qca8k_sw_probe, ++ .remove = qca8k_sw_remove, ++ .mdiodrv.driver = { ++ .name = "qca8k", ++ .of_match_table = qca8k_of_match, ++ .pm = &qca8k_pm_ops, ++ }, ++}; ++ ++mdio_module_driver(qca8kmdio_driver); ++ ++MODULE_AUTHOR("Mathieu Olivari, John Crispin "); ++MODULE_DESCRIPTION("Driver for QCA8K ethernet switch family"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:qca8k"); +--- /dev/null ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -0,0 +1,310 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2009 Felix Fietkau ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ */ ++ ++#ifndef __QCA8K_H ++#define __QCA8K_H ++ ++#include ++#include ++#include ++ ++#define QCA8K_NUM_PORTS 7 ++#define QCA8K_NUM_CPU_PORTS 2 ++#define QCA8K_MAX_MTU 9000 ++ ++#define PHY_ID_QCA8327 0x004dd034 ++#define QCA8K_ID_QCA8327 0x12 ++#define PHY_ID_QCA8337 0x004dd036 ++#define QCA8K_ID_QCA8337 0x13 ++ ++#define QCA8K_BUSY_WAIT_TIMEOUT 2000 ++ ++#define QCA8K_NUM_FDB_RECORDS 2048 ++ ++#define QCA8K_PORT_VID_DEF 1 ++ ++/* Global control registers */ ++#define QCA8K_REG_MASK_CTRL 0x000 ++#define QCA8K_MASK_CTRL_REV_ID_MASK GENMASK(7, 0) ++#define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0) ++#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) ++#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) ++#define QCA8K_REG_PORT0_PAD_CTRL 0x004 ++#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19) ++#define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18) ++#define QCA8K_REG_PORT5_PAD_CTRL 0x008 ++#define QCA8K_REG_PORT6_PAD_CTRL 0x00c ++#define QCA8K_PORT_PAD_RGMII_EN BIT(26) ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK GENMASK(23, 22) ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22) ++#define QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK GENMASK(21, 20) ++#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20) ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25) ++#define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) ++#define QCA8K_MAX_DELAY 3 ++#define QCA8K_PORT_PAD_SGMII_EN BIT(7) ++#define QCA8K_REG_PWS 0x010 ++#define QCA8K_PWS_POWER_ON_SEL BIT(31) ++/* This reg is only valid for QCA832x and toggle the package ++ * type from 176 pin (by default) to 148 pin used on QCA8327 ++ */ ++#define QCA8327_PWS_PACKAGE148_EN BIT(30) ++#define QCA8K_PWS_LED_OPEN_EN_CSR BIT(24) ++#define QCA8K_PWS_SERDES_AEN_DIS BIT(7) ++#define QCA8K_REG_MODULE_EN 0x030 ++#define QCA8K_MODULE_EN_MIB BIT(0) ++#define QCA8K_REG_MIB 0x034 ++#define QCA8K_MIB_FLUSH BIT(24) ++#define QCA8K_MIB_CPU_KEEP BIT(20) ++#define QCA8K_MIB_BUSY BIT(17) ++#define QCA8K_MDIO_MASTER_CTRL 0x3c ++#define QCA8K_MDIO_MASTER_BUSY BIT(31) ++#define QCA8K_MDIO_MASTER_EN BIT(30) ++#define QCA8K_MDIO_MASTER_READ BIT(27) ++#define QCA8K_MDIO_MASTER_WRITE 0 ++#define QCA8K_MDIO_MASTER_SUP_PRE BIT(26) ++#define QCA8K_MDIO_MASTER_PHY_ADDR(x) ((x) << 21) ++#define QCA8K_MDIO_MASTER_REG_ADDR(x) ((x) << 16) ++#define QCA8K_MDIO_MASTER_DATA(x) (x) ++#define QCA8K_MDIO_MASTER_DATA_MASK GENMASK(15, 0) ++#define QCA8K_MDIO_MASTER_MAX_PORTS 5 ++#define QCA8K_MDIO_MASTER_MAX_REG 32 ++#define QCA8K_GOL_MAC_ADDR0 0x60 ++#define QCA8K_GOL_MAC_ADDR1 0x64 ++#define QCA8K_MAX_FRAME_SIZE 0x78 ++#define QCA8K_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) ++#define QCA8K_PORT_STATUS_SPEED GENMASK(1, 0) ++#define QCA8K_PORT_STATUS_SPEED_10 0 ++#define QCA8K_PORT_STATUS_SPEED_100 0x1 ++#define QCA8K_PORT_STATUS_SPEED_1000 0x2 ++#define QCA8K_PORT_STATUS_TXMAC BIT(2) ++#define QCA8K_PORT_STATUS_RXMAC BIT(3) ++#define QCA8K_PORT_STATUS_TXFLOW BIT(4) ++#define QCA8K_PORT_STATUS_RXFLOW BIT(5) ++#define QCA8K_PORT_STATUS_DUPLEX BIT(6) ++#define QCA8K_PORT_STATUS_LINK_UP BIT(8) ++#define QCA8K_PORT_STATUS_LINK_AUTO BIT(9) ++#define QCA8K_PORT_STATUS_LINK_PAUSE BIT(10) ++#define QCA8K_PORT_STATUS_FLOW_AUTO BIT(12) ++#define QCA8K_REG_PORT_HDR_CTRL(_i) (0x9c + (_i * 4)) ++#define QCA8K_PORT_HDR_CTRL_RX_MASK GENMASK(3, 2) ++#define QCA8K_PORT_HDR_CTRL_RX_S 2 ++#define QCA8K_PORT_HDR_CTRL_TX_MASK GENMASK(1, 0) ++#define QCA8K_PORT_HDR_CTRL_TX_S 0 ++#define QCA8K_PORT_HDR_CTRL_ALL 2 ++#define QCA8K_PORT_HDR_CTRL_MGMT 1 ++#define QCA8K_PORT_HDR_CTRL_NONE 0 ++#define QCA8K_REG_SGMII_CTRL 0x0e0 ++#define QCA8K_SGMII_EN_PLL BIT(1) ++#define QCA8K_SGMII_EN_RX BIT(2) ++#define QCA8K_SGMII_EN_TX BIT(3) ++#define QCA8K_SGMII_EN_SD BIT(4) ++#define QCA8K_SGMII_CLK125M_DELAY BIT(7) ++#define QCA8K_SGMII_MODE_CTRL_MASK (BIT(22) | BIT(23)) ++#define QCA8K_SGMII_MODE_CTRL_BASEX (0 << 22) ++#define QCA8K_SGMII_MODE_CTRL_PHY (1 << 22) ++#define QCA8K_SGMII_MODE_CTRL_MAC (2 << 22) ++ ++/* MAC_PWR_SEL registers */ ++#define QCA8K_REG_MAC_PWR_SEL 0x0e4 ++#define QCA8K_MAC_PWR_RGMII1_1_8V BIT(18) ++#define QCA8K_MAC_PWR_RGMII0_1_8V BIT(19) ++ ++/* EEE control registers */ ++#define QCA8K_REG_EEE_CTRL 0x100 ++#define QCA8K_REG_EEE_CTRL_LPI_EN(_i) ((_i + 1) * 2) ++ ++/* ACL registers */ ++#define QCA8K_REG_PORT_VLAN_CTRL0(_i) (0x420 + (_i * 8)) ++#define QCA8K_PORT_VLAN_CVID(x) (x << 16) ++#define QCA8K_PORT_VLAN_SVID(x) x ++#define QCA8K_REG_PORT_VLAN_CTRL1(_i) (0x424 + (_i * 8)) ++#define QCA8K_REG_IPV4_PRI_BASE_ADDR 0x470 ++#define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474 ++ ++/* Lookup registers */ ++#define QCA8K_REG_ATU_DATA0 0x600 ++#define QCA8K_ATU_ADDR2_S 24 ++#define QCA8K_ATU_ADDR3_S 16 ++#define QCA8K_ATU_ADDR4_S 8 ++#define QCA8K_REG_ATU_DATA1 0x604 ++#define QCA8K_ATU_PORT_M 0x7f ++#define QCA8K_ATU_PORT_S 16 ++#define QCA8K_ATU_ADDR0_S 8 ++#define QCA8K_REG_ATU_DATA2 0x608 ++#define QCA8K_ATU_VID_M 0xfff ++#define QCA8K_ATU_VID_S 8 ++#define QCA8K_ATU_STATUS_M 0xf ++#define QCA8K_ATU_STATUS_STATIC 0xf ++#define QCA8K_REG_ATU_FUNC 0x60c ++#define QCA8K_ATU_FUNC_BUSY BIT(31) ++#define QCA8K_ATU_FUNC_PORT_EN BIT(14) ++#define QCA8K_ATU_FUNC_MULTI_EN BIT(13) ++#define QCA8K_ATU_FUNC_FULL BIT(12) ++#define QCA8K_ATU_FUNC_PORT_M 0xf ++#define QCA8K_ATU_FUNC_PORT_S 8 ++#define QCA8K_REG_VTU_FUNC0 0x610 ++#define QCA8K_VTU_FUNC0_VALID BIT(20) ++#define QCA8K_VTU_FUNC0_IVL_EN BIT(19) ++#define QCA8K_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) ++#define QCA8K_VTU_FUNC0_EG_MODE_MASK 3 ++#define QCA8K_VTU_FUNC0_EG_MODE_UNMOD 0 ++#define QCA8K_VTU_FUNC0_EG_MODE_UNTAG 1 ++#define QCA8K_VTU_FUNC0_EG_MODE_TAG 2 ++#define QCA8K_VTU_FUNC0_EG_MODE_NOT 3 ++#define QCA8K_REG_VTU_FUNC1 0x614 ++#define QCA8K_VTU_FUNC1_BUSY BIT(31) ++#define QCA8K_VTU_FUNC1_VID_S 16 ++#define QCA8K_VTU_FUNC1_FULL BIT(4) ++#define QCA8K_REG_GLOBAL_FW_CTRL0 0x620 ++#define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) ++#define QCA8K_REG_GLOBAL_FW_CTRL1 0x624 ++#define QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S 24 ++#define QCA8K_GLOBAL_FW_CTRL1_BC_DP_S 16 ++#define QCA8K_GLOBAL_FW_CTRL1_MC_DP_S 8 ++#define QCA8K_GLOBAL_FW_CTRL1_UC_DP_S 0 ++#define QCA8K_PORT_LOOKUP_CTRL(_i) (0x660 + (_i) * 0xc) ++#define QCA8K_PORT_LOOKUP_MEMBER GENMASK(6, 0) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE GENMASK(9, 8) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_NONE (0 << 8) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_FALLBACK (1 << 8) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_CHECK (2 << 8) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE (3 << 8) ++#define QCA8K_PORT_LOOKUP_STATE_MASK GENMASK(18, 16) ++#define QCA8K_PORT_LOOKUP_STATE_DISABLED (0 << 16) ++#define QCA8K_PORT_LOOKUP_STATE_BLOCKING (1 << 16) ++#define QCA8K_PORT_LOOKUP_STATE_LISTENING (2 << 16) ++#define QCA8K_PORT_LOOKUP_STATE_LEARNING (3 << 16) ++#define QCA8K_PORT_LOOKUP_STATE_FORWARD (4 << 16) ++#define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) ++#define QCA8K_PORT_LOOKUP_LEARN BIT(20) ++ ++#define QCA8K_REG_GLOBAL_FC_THRESH 0x800 ++#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16) ++#define QCA8K_GLOBAL_FC_GOL_XON_THRES_S GENMASK(24, 16) ++#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) ((x) << 0) ++#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S GENMASK(8, 0) ++ ++#define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF GENMASK(7, 4) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) ((x) << 4) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF GENMASK(11, 8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) ((x) << 8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF GENMASK(15, 12) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) ((x) << 12) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF GENMASK(19, 16) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) ((x) << 16) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF GENMASK(23, 20) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) ((x) << 20) ++#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF GENMASK(29, 24) ++#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) ((x) << 24) ++ ++#define QCA8K_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) ++#define QCA8K_PORT_HOL_CTRL1_ING_BUF GENMASK(3, 0) ++#define QCA8K_PORT_HOL_CTRL1_ING(x) ((x) << 0) ++#define QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN BIT(6) ++#define QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN BIT(7) ++#define QCA8K_PORT_HOL_CTRL1_WRED_EN BIT(8) ++#define QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) ++ ++/* Pkt edit registers */ ++#define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2))) ++ ++/* L3 registers */ ++#define QCA8K_HROUTER_CONTROL 0xe00 ++#define QCA8K_HROUTER_CONTROL_GLB_LOCKTIME_M GENMASK(17, 16) ++#define QCA8K_HROUTER_CONTROL_GLB_LOCKTIME_S 16 ++#define QCA8K_HROUTER_CONTROL_ARP_AGE_MODE 1 ++#define QCA8K_HROUTER_PBASED_CONTROL1 0xe08 ++#define QCA8K_HROUTER_PBASED_CONTROL2 0xe0c ++#define QCA8K_HNAT_CONTROL 0xe38 ++ ++/* MIB registers */ ++#define QCA8K_PORT_MIB_COUNTER(_i) (0x1000 + (_i) * 0x100) ++ ++/* QCA specific MII registers */ ++#define MII_ATH_MMD_ADDR 0x0d ++#define MII_ATH_MMD_DATA 0x0e ++ ++enum { ++ QCA8K_PORT_SPEED_10M = 0, ++ QCA8K_PORT_SPEED_100M = 1, ++ QCA8K_PORT_SPEED_1000M = 2, ++ QCA8K_PORT_SPEED_ERR = 3, ++}; ++ ++enum qca8k_fdb_cmd { ++ QCA8K_FDB_FLUSH = 1, ++ QCA8K_FDB_LOAD = 2, ++ QCA8K_FDB_PURGE = 3, ++ QCA8K_FDB_NEXT = 6, ++ QCA8K_FDB_SEARCH = 7, ++}; ++ ++enum qca8k_vlan_cmd { ++ QCA8K_VLAN_FLUSH = 1, ++ QCA8K_VLAN_LOAD = 2, ++ QCA8K_VLAN_PURGE = 3, ++ QCA8K_VLAN_REMOVE_PORT = 4, ++ QCA8K_VLAN_NEXT = 5, ++ QCA8K_VLAN_READ = 6, ++}; ++ ++struct ar8xxx_port_status { ++ int enabled; ++}; ++ ++struct qca8k_match_data { ++ u8 id; ++ bool reduced_package; ++}; ++ ++enum { ++ QCA8K_CPU_PORT0, ++ QCA8K_CPU_PORT6, ++}; ++ ++struct qca8k_ports_config { ++ bool sgmii_rx_clk_falling_edge; ++ bool sgmii_tx_clk_falling_edge; ++ bool sgmii_enable_pll; ++ u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ ++ u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ ++}; ++ ++struct qca8k_priv { ++ u8 switch_id; ++ u8 switch_revision; ++ bool legacy_phy_port_mapping; ++ struct qca8k_ports_config ports_config; ++ struct regmap *regmap; ++ struct mii_bus *bus; ++ struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; ++ struct dsa_switch *ds; ++ struct mutex reg_mutex; ++ struct device *dev; ++ struct dsa_switch_ops ops; ++ struct gpio_desc *reset_gpio; ++ unsigned int port_mtu[QCA8K_NUM_PORTS]; ++}; ++ ++struct qca8k_mib_desc { ++ unsigned int size; ++ unsigned int offset; ++ const char *name; ++}; ++ ++struct qca8k_fdb { ++ u16 vid; ++ u8 port_mask; ++ u8 aging; ++ u8 mac[6]; ++}; ++ ++#endif /* __QCA8K_H */ + +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1,25 +1,28 @@ + // SPDX-License-Identifier: GPL-2.0 + /* + * Copyright (C) 2009 Felix Fietkau +- * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2011-2012, 2020-2021 Gabor Juhos + * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016 John Crispin ++ * Copyright (c) 2021 Robert Marko + */ + ++#include ++#include ++#include ++#include ++#include + #include +-#include + #include +-#include +-#include + #include ++#include + #include +-#include +-#include ++#include + #include +-#include +-#include ++#include ++#include + +-#include "qca8k.h" ++#include "qca8k-ipq4019.h" + + #define MIB_DESC(_s, _o, _n) \ + { \ +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -68,186 +71,38 @@ static const struct qca8k_mib_desc ar8327_mib[] = { + MIB_DESC(1, 0x9c, "TxExcDefer"), + MIB_DESC(1, 0xa0, "TxDefer"), + MIB_DESC(1, 0xa4, "TxLateCol"), ++ MIB_DESC(1, 0xa8, "RXUnicast"), ++ MIB_DESC(1, 0xac, "TXunicast"), + }; + +-/* The 32bit switch registers are accessed indirectly. To achieve this we need +- * to set the page of the register. Track the last page that was set to reduce +- * mdio writes +- */ +-static u16 qca8k_current_page = 0xffff; +- +-static void +-qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) +-{ +- regaddr >>= 1; +- *r1 = regaddr & 0x1e; +- +- regaddr >>= 5; +- *r2 = regaddr & 0x7; +- +- regaddr >>= 3; +- *page = regaddr & 0x3ff; +-} +- +-static int +-qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) +-{ +- int ret; +- +- ret = bus->read(bus, phy_id, regnum); +- if (ret >= 0) { +- *val = ret; +- ret = bus->read(bus, phy_id, regnum + 1); +- *val |= ret << 16; +- } +- +- if (ret < 0) { +- dev_err_ratelimited(&bus->dev, +- "failed to read qca8k 32bit register\n"); +- *val = 0; +- return ret; +- } +- +- return 0; +-} +- +-static void +-qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) +-{ +- u16 lo, hi; +- int ret; +- +- lo = val & 0xffff; +- hi = (u16)(val >> 16); +- +- ret = bus->write(bus, phy_id, regnum, lo); +- if (ret >= 0) +- ret = bus->write(bus, phy_id, regnum + 1, hi); +- if (ret < 0) +- dev_err_ratelimited(&bus->dev, +- "failed to write qca8k 32bit register\n"); +-} +- +-static int +-qca8k_set_page(struct mii_bus *bus, u16 page) +-{ +- int ret; +- +- if (page == qca8k_current_page) +- return 0; +- +- ret = bus->write(bus, 0x18, 0, page); +- if (ret < 0) { +- dev_err_ratelimited(&bus->dev, +- "failed to set qca8k page\n"); +- return ret; +- } +- +- qca8k_current_page = page; +- usleep_range(1000, 2000); +- return 0; +-} +- + static int + qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) + { +- struct mii_bus *bus = priv->bus; +- u16 r1, r2, page; +- int ret; +- +- qca8k_split_addr(reg, &r1, &r2, &page); +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +- +- ret = qca8k_set_page(bus, page); +- if (ret < 0) +- goto exit; +- +- ret = qca8k_mii_read32(bus, 0x10 | r2, r1, val); +- +-exit: +- mutex_unlock(&bus->mdio_lock); +- return ret; ++ return regmap_read(priv->regmap, reg, val); + } + + static int + qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) + { +- struct mii_bus *bus = priv->bus; +- u16 r1, r2, page; +- int ret; +- +- qca8k_split_addr(reg, &r1, &r2, &page); +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +- +- ret = qca8k_set_page(bus, page); +- if (ret < 0) +- goto exit; +- +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); +- +-exit: +- mutex_unlock(&bus->mdio_lock); +- return ret; ++ return regmap_write(priv->regmap, reg, val); + } + + static int + qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) + { +- struct mii_bus *bus = priv->bus; +- u16 r1, r2, page; +- u32 val; +- int ret; +- +- qca8k_split_addr(reg, &r1, &r2, &page); +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +- +- ret = qca8k_set_page(bus, page); +- if (ret < 0) +- goto exit; +- +- ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); +- if (ret < 0) +- goto exit; +- +- val &= ~mask; +- val |= write_val; +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); +- +-exit: +- mutex_unlock(&bus->mdio_lock); +- +- return ret; ++ return regmap_update_bits(priv->regmap, reg, mask, write_val); + } + + static int + qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val) + { +- return qca8k_rmw(priv, reg, 0, val); ++ return regmap_set_bits(priv->regmap, reg, val); + } + + static int + qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val) + { +- return qca8k_rmw(priv, reg, val, 0); +-} +- +-static int +-qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +-{ +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; +- +- return qca8k_read(priv, reg, val); +-} +- +-static int +-qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) +-{ +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; +- +- return qca8k_write(priv, reg, val); ++ return regmap_clear_bits(priv->regmap, reg, val); + } + + static const struct regmap_range qca8k_readable_ranges[] = { +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -274,33 +129,31 @@ static const struct regmap_access_table qca8k_readable_table = { + .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), + }; + +-static struct regmap_config qca8k_regmap_config = { +- .reg_bits = 16, ++static struct regmap_config qca8k_ipq4019_regmap_config = { ++ .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x16ac, /* end MIB - Port6 range */ +- .reg_read = qca8k_regmap_read, +- .reg_write = qca8k_regmap_write, + .rd_table = &qca8k_readable_table, + }; + ++static struct regmap_config qca8k_ipq4019_psgmii_phy_regmap_config = { ++ .name = "psgmii-phy", ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = 0x7fc, ++}; ++ + static int + qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + { +- int ret, ret1; + u32 val; + +- ret = read_poll_timeout(qca8k_read, ret1, !(val & mask), +- 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- priv, reg, &val); +- +- /* Check if qca8k_read has failed for a different reason +- * before returning -ETIMEDOUT +- */ +- if (ret < 0 && ret1 < 0) +- return ret1; +- +- return ret; ++ return regmap_read_poll_timeout(priv->regmap, reg, val, ++ !(val & mask), ++ 0, ++ QCA8K_BUSY_WAIT_TIMEOUT); + } + + static int +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -595,8 +448,11 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) + { + u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC; + +- /* Port 0 and 6 have no internal PHY */ +- if (port > 0 && port < 6) ++ /* Port 0 is internally connected to the CPU ++ * TODO: Probably check for RGMII as well if it doesnt work ++ * in RGMII mode. ++ */ ++ if (port > QCA8K_CPU_PORT) + mask |= QCA8K_PORT_STATUS_LINK_AUTO; + + if (enable) +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -605,467 +461,56 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) + qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask); + } + +-static u32 +-qca8k_port_to_phy(int port) +-{ +- /* From Andrew Lunn: +- * Port 0 has no internal phy. +- * Port 1 has an internal PHY at MDIO address 0. +- * Port 2 has an internal PHY at MDIO address 1. +- * ... +- * Port 5 has an internal PHY at MDIO address 4. +- * Port 6 has no internal PHY. +- */ +- +- return port - 1; +-} +- +-static int +-qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) +-{ +- u16 r1, r2, page; +- u32 val; +- int ret, ret1; +- +- qca8k_split_addr(reg, &r1, &r2, &page); +- +- ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, +- QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- bus, 0x10 | r2, r1, &val); +- +- /* Check if qca8k_read has failed for a different reason +- * before returnting -ETIMEDOUT +- */ +- if (ret < 0 && ret1 < 0) +- return ret1; +- +- return ret; +-} +- +-static int +-qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) +-{ +- u16 r1, r2, page; +- u32 val; +- int ret; +- +- if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) +- return -EINVAL; +- +- val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | +- QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | +- QCA8K_MDIO_MASTER_REG_ADDR(regnum) | +- QCA8K_MDIO_MASTER_DATA(data); +- +- qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +- +- ret = qca8k_set_page(bus, page); +- if (ret) +- goto exit; +- +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); +- +- ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_BUSY); +- +-exit: +- /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); +- +- mutex_unlock(&bus->mdio_lock); +- +- return ret; +-} +- +-static int +-qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) +-{ +- u16 r1, r2, page; +- u32 val; +- int ret; +- +- if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) +- return -EINVAL; +- +- val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | +- QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | +- QCA8K_MDIO_MASTER_REG_ADDR(regnum); +- +- qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +- +- ret = qca8k_set_page(bus, page); +- if (ret) +- goto exit; +- +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); +- +- ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_BUSY); +- if (ret) +- goto exit; +- +- ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); +- +-exit: +- /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); +- +- mutex_unlock(&bus->mdio_lock); +- +- if (ret >= 0) +- ret = val & QCA8K_MDIO_MASTER_DATA_MASK; +- +- return ret; +-} +- +-static int +-qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data) +-{ +- struct qca8k_priv *priv = slave_bus->priv; +- struct mii_bus *bus = priv->bus; +- +- return qca8k_mdio_write(bus, phy, regnum, data); +-} +- +-static int +-qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) +-{ +- struct qca8k_priv *priv = slave_bus->priv; +- struct mii_bus *bus = priv->bus; +- +- return qca8k_mdio_read(bus, phy, regnum); +-} +- +-static int +-qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) +-{ +- struct qca8k_priv *priv = ds->priv; +- +- /* Check if the legacy mapping should be used and the +- * port is not correctly mapped to the right PHY in the +- * devicetree +- */ +- if (priv->legacy_phy_port_mapping) +- port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; +- +- return qca8k_mdio_write(priv->bus, port, regnum, data); +-} +- + static int +-qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) ++qca8k_setup_port(struct dsa_switch *ds, int port) + { +- struct qca8k_priv *priv = ds->priv; +- int ret; +- +- /* Check if the legacy mapping should be used and the +- * port is not correctly mapped to the right PHY in the +- * devicetree +- */ +- if (priv->legacy_phy_port_mapping) +- port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; +- +- ret = qca8k_mdio_read(priv->bus, port, regnum); +- +- if (ret < 0) +- return 0xffff; +- +- return ret; +-} +- +-static int +-qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio) +-{ +- struct dsa_switch *ds = priv->ds; +- struct mii_bus *bus; +- +- bus = devm_mdiobus_alloc(ds->dev); +- +- if (!bus) +- return -ENOMEM; +- +- bus->priv = (void *)priv; +- bus->name = "qca8k slave mii"; +- bus->read = qca8k_internal_mdio_read; +- bus->write = qca8k_internal_mdio_write; +- snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d", +- ds->index); +- +- bus->parent = ds->dev; +- bus->phy_mask = ~ds->phys_mii_mask; +- +- ds->slave_mii_bus = bus; +- +- return devm_of_mdiobus_register(priv->dev, bus, mdio); +-} +- +-static int +-qca8k_setup_mdio_bus(struct qca8k_priv *priv) +-{ +- u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg; +- struct device_node *ports, *port, *mdio; +- phy_interface_t mode; +- int err; +- +- ports = of_get_child_by_name(priv->dev->of_node, "ports"); +- if (!ports) +- ports = of_get_child_by_name(priv->dev->of_node, "ethernet-ports"); +- +- if (!ports) +- return -EINVAL; +- +- for_each_available_child_of_node(ports, port) { +- err = of_property_read_u32(port, "reg", ®); +- if (err) { +- of_node_put(port); +- of_node_put(ports); +- return err; +- } +- +- if (!dsa_is_user_port(priv->ds, reg)) +- continue; +- +- of_get_phy_mode(port, &mode); +- +- if (of_property_read_bool(port, "phy-handle") && +- mode != PHY_INTERFACE_MODE_INTERNAL) +- external_mdio_mask |= BIT(reg); +- else +- internal_mdio_mask |= BIT(reg); +- } +- +- of_node_put(ports); +- if (!external_mdio_mask && !internal_mdio_mask) { +- dev_err(priv->dev, "no PHYs are defined.\n"); +- return -EINVAL; +- } +- +- /* The QCA8K_MDIO_MASTER_EN Bit, which grants access to PHYs through +- * the MDIO_MASTER register also _disconnects_ the external MDC +- * passthrough to the internal PHYs. It's not possible to use both +- * configurations at the same time! +- * +- * Because this came up during the review process: +- * If the external mdio-bus driver is capable magically disabling +- * the QCA8K_MDIO_MASTER_EN and mutex/spin-locking out the qca8k's +- * accessors for the time being, it would be possible to pull this +- * off. +- */ +- if (!!external_mdio_mask && !!internal_mdio_mask) { +- dev_err(priv->dev, "either internal or external mdio bus configuration is supported.\n"); +- return -EINVAL; +- } +- +- if (external_mdio_mask) { +- /* Make sure to disable the internal mdio bus in cases +- * a dt-overlay and driver reload changed the configuration +- */ +- +- return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_EN); +- } +- +- /* Check if the devicetree declare the port:phy mapping */ +- mdio = of_get_child_by_name(priv->dev->of_node, "mdio"); +- if (of_device_is_available(mdio)) { +- err = qca8k_mdio_register(priv, mdio); +- if (err) +- of_node_put(mdio); +- +- return err; +- } +- +- /* If a mapping can't be found the legacy mapping is used, +- * using the qca8k_port_to_phy function +- */ +- priv->legacy_phy_port_mapping = true; +- priv->ops.phy_read = qca8k_phy_read; +- priv->ops.phy_write = qca8k_phy_write; +- +- return 0; +-} +- +-static int +-qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv) +-{ +- u32 mask = 0; +- int ret = 0; +- +- /* SoC specific settings for ipq8064. +- * If more device require this consider adding +- * a dedicated binding. +- */ +- if (of_machine_is_compatible("qcom,ipq8064")) +- mask |= QCA8K_MAC_PWR_RGMII0_1_8V; +- +- /* SoC specific settings for ipq8065 */ +- if (of_machine_is_compatible("qcom,ipq8065")) +- mask |= QCA8K_MAC_PWR_RGMII1_1_8V; +- +- if (mask) { +- ret = qca8k_rmw(priv, QCA8K_REG_MAC_PWR_SEL, +- QCA8K_MAC_PWR_RGMII0_1_8V | +- QCA8K_MAC_PWR_RGMII1_1_8V, +- mask); +- } +- +- return ret; +-} +- +-static int qca8k_find_cpu_port(struct dsa_switch *ds) +-{ +- struct qca8k_priv *priv = ds->priv; +- +- /* Find the connected cpu port. Valid port are 0 or 6 */ +- if (dsa_is_cpu_port(ds, 0)) +- return 0; +- +- dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6"); +- +- if (dsa_is_cpu_port(ds, 6)) +- return 6; +- +- return -EINVAL; +-} +- +-static int +-qca8k_setup_of_pws_reg(struct qca8k_priv *priv) +-{ +- struct device_node *node = priv->dev->of_node; +- const struct qca8k_match_data *data; +- u32 val = 0; ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + int ret; + +- /* QCA8327 require to set to the correct mode. +- * His bigger brother QCA8328 have the 172 pin layout. +- * Should be applied by default but we set this just to make sure. +- */ +- if (priv->switch_id == QCA8K_ID_QCA8327) { +- data = of_device_get_match_data(priv->dev); +- +- /* Set the correct package of 148 pin for QCA8327 */ +- if (data->reduced_package) +- val |= QCA8327_PWS_PACKAGE148_EN; +- +- ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN, +- val); ++ /* CPU port gets connected to all user ports of the switch */ ++ if (dsa_is_cpu_port(ds, port)) { ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), ++ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); + if (ret) + return ret; +- } +- +- if (of_property_read_bool(node, "qca,ignore-power-on-sel")) +- val |= QCA8K_PWS_POWER_ON_SEL; +- +- if (of_property_read_bool(node, "qca,led-open-drain")) { +- if (!(val & QCA8K_PWS_POWER_ON_SEL)) { +- dev_err(priv->dev, "qca,led-open-drain require qca,ignore-power-on-sel to be set."); +- return -EINVAL; +- } + +- val |= QCA8K_PWS_LED_OPEN_EN_CSR; ++ /* Disable CPU ARP Auto-learning by default */ ++ ret = qca8k_reg_clear(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; + } + +- return qca8k_rmw(priv, QCA8K_REG_PWS, +- QCA8K_PWS_LED_OPEN_EN_CSR | QCA8K_PWS_POWER_ON_SEL, +- val); +-} +- +-static int +-qca8k_parse_port_config(struct qca8k_priv *priv) +-{ +- int port, cpu_port_index = -1, ret; +- struct device_node *port_dn; +- phy_interface_t mode; +- struct dsa_port *dp; +- u32 delay; +- +- /* We have 2 CPU port. Check them */ +- for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) { +- /* Skip every other port */ +- if (port != 0 && port != 6) +- continue; +- +- dp = dsa_to_port(priv->ds, port); +- port_dn = dp->dn; +- cpu_port_index++; ++ /* Individual user ports get connected to CPU port only */ ++ if (dsa_is_user_port(ds, port)) { ++ int shift = 16 * (port % 2); + +- if (!of_device_is_available(port_dn)) +- continue; ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ BIT(QCA8K_CPU_PORT)); ++ if (ret) ++ return ret; + +- ret = of_get_phy_mode(port_dn, &mode); ++ /* Enable ARP Auto-learning by default */ ++ ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); + if (ret) +- continue; ++ return ret; + +- switch (mode) { +- case PHY_INTERFACE_MODE_RGMII: +- case PHY_INTERFACE_MODE_RGMII_ID: +- case PHY_INTERFACE_MODE_RGMII_TXID: +- case PHY_INTERFACE_MODE_RGMII_RXID: +- case PHY_INTERFACE_MODE_SGMII: +- delay = 0; +- +- if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay)) +- /* Switch regs accept value in ns, convert ps to ns */ +- delay = delay / 1000; +- else if (mode == PHY_INTERFACE_MODE_RGMII_ID || +- mode == PHY_INTERFACE_MODE_RGMII_TXID) +- delay = 1; +- +- if (delay > QCA8K_MAX_DELAY) { +- dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); +- delay = 3; +- } +- +- priv->ports_config.rgmii_tx_delay[cpu_port_index] = delay; +- +- delay = 0; +- +- if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay)) +- /* Switch regs accept value in ns, convert ps to ns */ +- delay = delay / 1000; +- else if (mode == PHY_INTERFACE_MODE_RGMII_ID || +- mode == PHY_INTERFACE_MODE_RGMII_RXID) +- delay = 2; +- +- if (delay > QCA8K_MAX_DELAY) { +- dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); +- delay = 3; +- } +- +- priv->ports_config.rgmii_rx_delay[cpu_port_index] = delay; +- +- /* Skip sgmii parsing for rgmii* mode */ +- if (mode == PHY_INTERFACE_MODE_RGMII || +- mode == PHY_INTERFACE_MODE_RGMII_ID || +- mode == PHY_INTERFACE_MODE_RGMII_TXID || +- mode == PHY_INTERFACE_MODE_RGMII_RXID) +- break; +- +- if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge")) +- priv->ports_config.sgmii_tx_clk_falling_edge = true; +- +- if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge")) +- priv->ports_config.sgmii_rx_clk_falling_edge = true; +- +- if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) { +- priv->ports_config.sgmii_enable_pll = true; +- +- if (priv->switch_id == QCA8K_ID_QCA8327) { +- dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling"); +- priv->ports_config.sgmii_enable_pll = false; +- } +- +- if (priv->switch_revision < 2) +- dev_warn(priv->dev, "SGMII PLL should NOT be enabled for qca8337 with revision 2 or more."); +- } ++ /* For port based vlans to work we need to set the ++ * default egress vid ++ */ ++ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), ++ 0xfff << shift, ++ QCA8K_PORT_VID_DEF << shift); ++ if (ret) ++ return ret; + +- break; +- default: +- continue; +- } ++ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), ++ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | ++ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; + } + + return 0; +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1075,40 +520,14 @@ static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +- int cpu_port, ret, i; +- u32 mask; ++ int ret, i; + +- cpu_port = qca8k_find_cpu_port(ds); +- if (cpu_port < 0) { +- dev_err(priv->dev, "No cpu port configured in both cpu port0 and port6"); +- return cpu_port; ++ /* Make sure that port 0 is the cpu port */ ++ if (!dsa_is_cpu_port(ds, 0)) { ++ dev_err(priv->dev, "port 0 is not the CPU port"); ++ return -EINVAL; + } + +- /* Parse CPU port config to be later used in phy_link mac_config */ +- ret = qca8k_parse_port_config(priv); +- if (ret) +- return ret; +- +- mutex_init(&priv->reg_mutex); +- +- /* Start by setting up the register mapping */ +- priv->regmap = devm_regmap_init(ds->dev, NULL, priv, +- &qca8k_regmap_config); +- if (IS_ERR(priv->regmap)) +- dev_warn(priv->dev, "regmap initialization failed"); +- +- ret = qca8k_setup_mdio_bus(priv); +- if (ret) +- return ret; +- +- ret = qca8k_setup_of_pws_reg(priv); +- if (ret) +- return ret; +- +- ret = qca8k_setup_mac_pwr_sel(priv); +- if (ret) +- return ret; +- + /* Enable CPU Port */ + ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1120,149 +539,53 @@ qca8k_setup(struct dsa_switch *ds) + /* Enable MIB counters */ + ret = qca8k_mib_init(priv); + if (ret) +- dev_warn(priv->dev, "mib init failed"); ++ dev_warn(priv->dev, "MIB init failed"); ++ ++ /* Enable QCA header mode on the cpu port */ ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT), ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode"); ++ return ret; ++ } + +- /* Initial setup of all ports */ ++ /* Disable forwarding by default on all ports */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- /* Disable forwarding by default on all ports */ + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), + QCA8K_PORT_LOOKUP_MEMBER, 0); + if (ret) + return ret; +- +- /* Enable QCA header mode on all cpu ports */ +- if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); +- if (ret) { +- dev_err(priv->dev, "failed enabling QCA header mode"); +- return ret; +- } +- } +- +- /* Disable MAC by default on all user ports */ +- if (dsa_is_user_port(ds, i)) +- qca8k_port_set_status(priv, i, 0); + } + +- /* Forward all unknown frames to CPU port for Linux processing +- * Notice that in multi-cpu config only one port should be set +- * for igmp, unknown, multicast and broadcast packet +- */ ++ /* Disable MAC by default on all ports */ ++ for (i = 1; i < QCA8K_NUM_PORTS; i++) ++ qca8k_port_set_status(priv, i, 0); ++ ++ /* Forward all unknown frames to CPU port for Linux processing */ + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); ++ BIT(QCA8K_CPU_PORT) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | ++ BIT(QCA8K_CPU_PORT) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | ++ BIT(QCA8K_CPU_PORT) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | ++ BIT(QCA8K_CPU_PORT) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); + if (ret) + return ret; + +- /* Setup connection between CPU port & user ports +- * Configure specific switch configuration for ports +- */ ++ /* Setup connection between CPU port & user ports */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- /* CPU port gets connected to all user ports of the switch */ +- if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); +- if (ret) +- return ret; +- } +- +- /* Individual user ports get connected to CPU port only */ +- if (dsa_is_user_port(ds, i)) { +- int shift = 16 * (i % 2); +- +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, +- BIT(cpu_port)); +- if (ret) +- return ret; +- +- /* Enable ARP Auto-learning by default */ +- ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); +- if (ret) +- return ret; +- +- /* For port based vlans to work we need to set the +- * default egress vid +- */ +- ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), +- 0xfff << shift, +- QCA8K_PORT_VID_DEF << shift); +- if (ret) +- return ret; +- +- ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), +- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | +- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); +- if (ret) +- return ret; +- } +- +- /* The port 5 of the qca8337 have some problem in flood condition. The +- * original legacy driver had some specific buffer and priority settings +- * for the different port suggested by the QCA switch team. Add this +- * missing settings to improve switch stability under load condition. +- * This problem is limited to qca8337 and other qca8k switch are not affected. +- */ +- if (priv->switch_id == QCA8K_ID_QCA8337) { +- switch (i) { +- /* The 2 CPU port and port 5 requires some different +- * priority than any other ports. +- */ +- case 0: +- case 5: +- case 6: +- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | +- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); +- break; +- default: +- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | +- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); +- } +- qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); +- +- mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | +- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_WRED_EN; +- qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), +- QCA8K_PORT_HOL_CTRL1_ING_BUF | +- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_WRED_EN, +- mask); +- } +- +- /* Set initial MTU for every port. +- * We have only have a general MTU setting. So track +- * every port and set the max across all port. +- */ +- priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; +- } +- +- /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ +- if (priv->switch_id == QCA8K_ID_QCA8327) { +- mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | +- QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); +- qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, +- QCA8K_GLOBAL_FC_GOL_XON_THRES_S | +- QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S, +- mask); ++ ret = qca8k_setup_port(ds, i); ++ if (ret) ++ return ret; + } + + /* Setup our port MTUs to match power on defaults */ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) ++ /* Set per port MTU to 1500 as the MTU change function ++ * will add the overhead and if its set to 1518 then it ++ * will apply the overhead again and we will end up with ++ * MTU of 1536 instead of 1518 ++ */ ++ priv->port_mtu[i] = ETH_DATA_LEN; + ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); + if (ret) + dev_warn(priv->dev, "failed setting MTU settings"); +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1273,48 +596,87 @@ qca8k_setup(struct dsa_switch *ds) + /* We don't have interrupts for link changes, so we need to poll */ + ds->pcs_poll = true; + ++ /* CPU port HW learning doesnt work correctly, so let DSA handle it */ ++ ds->assisted_learning_on_cpu_port = true; ++ + return 0; + } + +-static void +-qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_index, +- u32 reg) ++static int psgmii_vco_calibrate(struct dsa_switch *ds) + { +- u32 delay, val = 0; +- int ret; ++ struct qca8k_priv *priv = ds->priv; ++ int val, ret; + +- /* Delay can be declared in 3 different way. +- * Mode to rgmii and internal-delay standard binding defined +- * rgmii-id or rgmii-tx/rx phy mode set. +- * The parse logic set a delay different than 0 only when one +- * of the 3 different way is used. In all other case delay is +- * not enabled. With ID or TX/RXID delay is enabled and set +- * to the default and recommended value. +- */ +- if (priv->ports_config.rgmii_tx_delay[cpu_port_index]) { +- delay = priv->ports_config.rgmii_tx_delay[cpu_port_index]; ++ if (!priv->psgmii_ethphy) { ++ dev_err(ds->dev, "PSGMII eth PHY missing, calibration failed!\n"); ++ return -ENODEV; ++ } + +- val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) | +- QCA8K_PORT_PAD_RGMII_TX_DELAY_EN; ++ /* Fix PSGMII RX 20bit */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5b); ++ /* Reset PSGMII PHY */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x1b); ++ /* Release reset */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5b); ++ ++ /* Poll for VCO PLL calibration finish */ ++ ret = phy_read_mmd_poll_timeout(priv->psgmii_ethphy, ++ MDIO_MMD_PMAPMD, ++ 0x28, val, ++ (val & BIT(0)), ++ 10000, 1000000, ++ false); ++ if (ret) { ++ dev_err(ds->dev, "QCA807x PSGMII VCO calibration PLL not ready\n"); ++ return ret; + } + +- if (priv->ports_config.rgmii_rx_delay[cpu_port_index]) { +- delay = priv->ports_config.rgmii_rx_delay[cpu_port_index]; ++ /* Freeze PSGMII RX CDR */ ++ ret = phy_write(priv->psgmii_ethphy, MII_RESV2, 0x2230); + +- val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) | +- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN; ++ /* Start PSGMIIPHY VCO PLL calibration */ ++ ret = regmap_set_bits(priv->psgmii, ++ PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1, ++ PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART); ++ ++ /* Poll for PSGMIIPHY PLL calibration finish */ ++ ret = regmap_read_poll_timeout(priv->psgmii, ++ PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2, ++ val, val & PSGMIIPHY_REG_PLL_VCO_CALIB_READY, ++ 10000, 1000000); ++ if (ret) { ++ dev_err(ds->dev, "PSGMIIPHY VCO calibration PLL not ready\n"); ++ return ret; + } + +- /* Set RGMII delay based on the selected values */ +- ret = qca8k_rmw(priv, reg, +- QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK | +- QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK | +- QCA8K_PORT_PAD_RGMII_TX_DELAY_EN | +- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN, +- val); +- if (ret) +- dev_err(priv->dev, "Failed to set internal delay for CPU port%d", +- cpu_port_index == QCA8K_CPU_PORT0 ? 0 : 6); ++ /* Release PSGMII RX CDR */ ++ ret = phy_write(priv->psgmii_ethphy, MII_RESV2, 0x3230); ++ ++ /* Release PSGMII RX 20bit */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5f); ++ ++ return ret; ++} ++ ++static int ipq4019_psgmii_configure(struct dsa_switch *ds) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int ret; ++ ++ if (!priv->psgmii_calibrated) { ++ ret = psgmii_vco_calibrate(ds); ++ ++ ret = regmap_clear_bits(priv->psgmii, PSGMIIPHY_MODE_CONTROL, ++ PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M); ++ ret = regmap_write(priv->psgmii, PSGMIIPHY_TX_CONTROL, ++ PSGMIIPHY_TX_CONTROL_MAGIC_VALUE); ++ ++ priv->psgmii_calibrated = true; ++ ++ return ret; ++ } ++ ++ return 0; + } + + static void +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1322,141 +684,33 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) + { + struct qca8k_priv *priv = ds->priv; +- int cpu_port_index, ret; +- u32 reg, val; + + switch (port) { +- case 0: /* 1st CPU port */ +- if (state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_RGMII_ID && +- state->interface != PHY_INTERFACE_MODE_RGMII_TXID && +- state->interface != PHY_INTERFACE_MODE_RGMII_RXID && +- state->interface != PHY_INTERFACE_MODE_SGMII) +- return; +- +- reg = QCA8K_REG_PORT0_PAD_CTRL; +- cpu_port_index = QCA8K_CPU_PORT0; +- break; ++ case 0: ++ /* CPU port, no configuration needed */ ++ return; + case 1: + case 2: + case 3: ++ if (state->interface == PHY_INTERFACE_MODE_PSGMII) ++ if (ipq4019_psgmii_configure(ds)) ++ dev_err(ds->dev, "PSGMII configuration failed!\n"); ++ return; + case 4: + case 5: +- /* Internal PHY, nothing to do */ +- return; +- case 6: /* 2nd CPU port / external PHY */ +- if (state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_RGMII_ID && +- state->interface != PHY_INTERFACE_MODE_RGMII_TXID && +- state->interface != PHY_INTERFACE_MODE_RGMII_RXID && +- state->interface != PHY_INTERFACE_MODE_SGMII && +- state->interface != PHY_INTERFACE_MODE_1000BASEX) +- return; +- +- reg = QCA8K_REG_PORT6_PAD_CTRL; +- cpu_port_index = QCA8K_CPU_PORT6; +- break; +- default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); +- return; +- } +- +- if (port != 6 && phylink_autoneg_inband(mode)) { +- dev_err(ds->dev, "%s: in-band negotiation unsupported\n", +- __func__); +- return; +- } +- +- switch (state->interface) { +- case PHY_INTERFACE_MODE_RGMII: +- case PHY_INTERFACE_MODE_RGMII_ID: +- case PHY_INTERFACE_MODE_RGMII_TXID: +- case PHY_INTERFACE_MODE_RGMII_RXID: +- qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN); +- +- /* Configure rgmii delay */ +- qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); +- +- /* QCA8337 requires to set rgmii rx delay for all ports. +- * This is enabled through PORT5_PAD_CTRL for all ports, +- * rather than individual port registers. +- */ +- if (priv->switch_id == QCA8K_ID_QCA8337) +- qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, +- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); +- break; +- case PHY_INTERFACE_MODE_SGMII: +- case PHY_INTERFACE_MODE_1000BASEX: +- /* Enable SGMII on the port */ +- qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); +- +- /* Enable/disable SerDes auto-negotiation as necessary */ +- ret = qca8k_read(priv, QCA8K_REG_PWS, &val); +- if (ret) +- return; +- if (phylink_autoneg_inband(mode)) +- val &= ~QCA8K_PWS_SERDES_AEN_DIS; +- else +- val |= QCA8K_PWS_SERDES_AEN_DIS; +- qca8k_write(priv, QCA8K_REG_PWS, val); +- +- /* Configure the SGMII parameters */ +- ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); +- if (ret) +- return; +- +- val |= QCA8K_SGMII_EN_SD; +- +- if (priv->ports_config.sgmii_enable_pll) +- val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | +- QCA8K_SGMII_EN_TX; +- +- if (dsa_is_cpu_port(ds, port)) { +- /* CPU port, we're talking to the CPU MAC, be a PHY */ +- val &= ~QCA8K_SGMII_MODE_CTRL_MASK; +- val |= QCA8K_SGMII_MODE_CTRL_PHY; +- } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { +- val &= ~QCA8K_SGMII_MODE_CTRL_MASK; +- val |= QCA8K_SGMII_MODE_CTRL_MAC; +- } else if (state->interface == PHY_INTERFACE_MODE_1000BASEX) { +- val &= ~QCA8K_SGMII_MODE_CTRL_MASK; +- val |= QCA8K_SGMII_MODE_CTRL_BASEX; ++ if (state->interface == PHY_INTERFACE_MODE_RGMII || ++ state->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ state->interface == PHY_INTERFACE_MODE_RGMII_RXID || ++ state->interface == PHY_INTERFACE_MODE_RGMII_TXID) { ++ qca8k_reg_set(priv, QCA8K_REG_RGMII_CTRL, QCA8K_RGMII_CTRL_CLK); + } + +- qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val); +- +- /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and +- * falling edge is set writing in the PORT0 PAD reg +- */ +- if (priv->switch_id == QCA8K_ID_QCA8327 || +- priv->switch_id == QCA8K_ID_QCA8337) +- reg = QCA8K_REG_PORT0_PAD_CTRL; +- +- val = 0; +- +- /* SGMII Clock phase configuration */ +- if (priv->ports_config.sgmii_rx_clk_falling_edge) +- val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE; +- +- if (priv->ports_config.sgmii_tx_clk_falling_edge) +- val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE; +- +- if (val) +- ret = qca8k_rmw(priv, reg, +- QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE | +- QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, +- val); +- +- /* From original code is reported port instability as SGMII also +- * require delay set. Apply advised values here or take them from DT. +- */ +- if (state->interface == PHY_INTERFACE_MODE_SGMII) +- qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); +- +- break; ++ if (state->interface == PHY_INTERFACE_MODE_PSGMII) ++ if (ipq4019_psgmii_configure(ds)) ++ dev_err(ds->dev, "PSGMII configuration failed!\n"); ++ return; + default: +- dev_err(ds->dev, "xMII mode %s not supported for port %d\n", +- phy_modes(state->interface), port); ++ dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); + return; + } + } +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1469,59 +723,49 @@ qca8k_phylink_validate(struct dsa_switch *ds, int port, + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + switch (port) { +- case 0: /* 1st CPU port */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_RGMII_ID && +- state->interface != PHY_INTERFACE_MODE_RGMII_TXID && +- state->interface != PHY_INTERFACE_MODE_RGMII_RXID && +- state->interface != PHY_INTERFACE_MODE_SGMII) ++ case 0: /* CPU port */ ++ if (state->interface != PHY_INTERFACE_MODE_INTERNAL) + goto unsupported; + break; + case 1: + case 2: + case 3: +- case 4: +- case 5: +- /* Internal PHY */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_GMII && +- state->interface != PHY_INTERFACE_MODE_INTERNAL) ++ /* Only PSGMII mode is supported */ ++ if (state->interface != PHY_INTERFACE_MODE_PSGMII) + goto unsupported; + break; +- case 6: /* 2nd CPU port / external PHY */ +- if (state->interface != PHY_INTERFACE_MODE_NA && ++ case 4: ++ case 5: ++ /* PSGMII and RGMII modes are supported */ ++ if (state->interface != PHY_INTERFACE_MODE_PSGMII && + state->interface != PHY_INTERFACE_MODE_RGMII && + state->interface != PHY_INTERFACE_MODE_RGMII_ID && +- state->interface != PHY_INTERFACE_MODE_RGMII_TXID && + state->interface != PHY_INTERFACE_MODE_RGMII_RXID && +- state->interface != PHY_INTERFACE_MODE_SGMII && +- state->interface != PHY_INTERFACE_MODE_1000BASEX) ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID) + goto unsupported; + break; + default: + unsupported: ++ dev_warn(ds->dev, "interface '%s' (%d) on port %d is not supported\n", ++ phy_modes(state->interface), state->interface, port); + linkmode_zero(supported); + return; + } + +- phylink_set_port_modes(mask); +- phylink_set(mask, Autoneg); +- +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 10baseT_Half); +- phylink_set(mask, 10baseT_Full); +- phylink_set(mask, 100baseT_Half); +- phylink_set(mask, 100baseT_Full); ++ if (port == 0) { ++ phylink_set_port_modes(mask); + +- if (state->interface == PHY_INTERFACE_MODE_1000BASEX) +- phylink_set(mask, 1000baseX_Full); ++ phylink_set(mask, 1000baseT_Full); + +- phylink_set(mask, Pause); +- phylink_set(mask, Asym_Pause); ++ phylink_set(mask, Pause); ++ phylink_set(mask, Asym_Pause); + +- linkmode_and(supported, supported, mask); +- linkmode_and(state->advertising, state->advertising, mask); ++ linkmode_and(supported, supported, mask); ++ linkmode_and(state->advertising, state->advertising, mask); ++ } else { ++ /* Simply copy what PHYs tell us */ ++ linkmode_copy(state->advertising, supported); ++ } + } + + static int +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1895,14 +1139,22 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port, + return 0; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + static int + qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, + struct switchdev_trans *trans) ++#else ++static int ++qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, ++ struct netlink_ext_ack *extack) ++#endif + { + struct qca8k_priv *priv = ds->priv; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + if (switchdev_trans_ph_prepare(trans)) + return 0; ++#endif + + if (vlan_filtering) { + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1917,39 +1169,70 @@ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, + return 0; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + static int + qca8k_port_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) + { + return 0; + } ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + static void + qca8k_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) ++#else ++static int ++qca8k_port_vlan_add(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_vlan *vlan, ++ struct netlink_ext_ack *extack) ++#endif + { + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct qca8k_priv *priv = ds->priv; + int ret = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + u16 vid; + + for (vid = vlan->vid_begin; vid <= vlan->vid_end && !ret; ++vid) + ret = qca8k_vlan_add(priv, port, vid, untagged); +- ++#else ++ ret = qca8k_vlan_add(priv, port, vlan->vid, untagged); ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + if (ret) + dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret); ++#else ++ if (ret) { ++ dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret); ++ return ret; ++ } ++#endif + + if (pvid) { + int shift = 16 * (port % 2); + + qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + 0xfff << shift, + vlan->vid_end << shift); ++#else ++ 0xfff << shift, vlan->vid << shift); ++#endif + qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + QCA8K_PORT_VLAN_CVID(vlan->vid_end) | + QCA8K_PORT_VLAN_SVID(vlan->vid_end)); ++#else ++ QCA8K_PORT_VLAN_CVID(vlan->vid) | ++ QCA8K_PORT_VLAN_SVID(vlan->vid)); ++#endif + } ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5,12,0) ++ return 0; ++#endif + } + + static int +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -1958,38 +1241,25 @@ qca8k_port_vlan_del(struct dsa_switch *ds, int port, + { + struct qca8k_priv *priv = ds->priv; + int ret = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + u16 vid; + + for (vid = vlan->vid_begin; vid <= vlan->vid_end && !ret; ++vid) + ret = qca8k_vlan_del(priv, port, vid); +- ++#else ++ ret = qca8k_vlan_del(priv, port, vlan->vid); ++#endif + if (ret) + dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret); + + return ret; + } + +-static u32 qca8k_get_phy_flags(struct dsa_switch *ds, int port) +-{ +- struct qca8k_priv *priv = ds->priv; +- +- /* Communicate to the phy internal driver the switch revision. +- * Based on the switch revision different values needs to be +- * set to the dbg and mmd reg on the phy. +- * The first 2 bit are used to communicate the switch revision +- * to the phy driver. +- */ +- if (port > 0 && port < 6) +- return priv->switch_revision; +- +- return 0; +-} +- + static enum dsa_tag_protocol + qca8k_get_tag_protocol(struct dsa_switch *ds, int port, + enum dsa_tag_protocol mp) + { +- return DSA_TAG_PROTO_QCA; ++ return DSA_TAG_PROTO_IPQ4019; + } + + static const struct dsa_switch_ops qca8k_switch_ops = { +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -2011,7 +1281,9 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + .port_fdb_del = qca8k_port_fdb_del, + .port_fdb_dump = qca8k_port_fdb_dump, + .port_vlan_filtering = qca8k_port_vlan_filtering, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + .port_vlan_prepare = qca8k_port_vlan_prepare, ++#endif + .port_vlan_add = qca8k_port_vlan_add, + .port_vlan_del = qca8k_port_vlan_del, + .phylink_validate = qca8k_phylink_validate, +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -2019,172 +1291,127 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + .phylink_mac_config = qca8k_phylink_mac_config, + .phylink_mac_link_down = qca8k_phylink_mac_link_down, + .phylink_mac_link_up = qca8k_phylink_mac_link_up, +- .get_phy_flags = qca8k_get_phy_flags, + }; + +-static int qca8k_read_switch_id(struct qca8k_priv *priv) +-{ +- const struct qca8k_match_data *data; +- u32 val; +- u8 id; +- int ret; +- +- /* get the switches ID from the compatible */ +- data = of_device_get_match_data(priv->dev); +- if (!data) +- return -ENODEV; +- +- ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val); +- if (ret < 0) +- return -ENODEV; +- +- id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); +- if (id != data->id) { +- dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); +- return -ENODEV; +- } +- +- priv->switch_id = id; +- +- /* Save revision to communicate to the internal PHY driver */ +- priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK); +- +- return 0; +-} +- + static int +-qca8k_sw_probe(struct mdio_device *mdiodev) ++qca8k_ipq4019_probe(struct platform_device *pdev) + { + struct qca8k_priv *priv; ++ void __iomem *base, *psgmii; ++ struct device_node *np = pdev->dev.of_node, *mdio_np, *psgmii_ethphy_np; + int ret; + +- /* allocate the private data struct so that we can probe the switches +- * ID register +- */ +- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + +- priv->bus = mdiodev->bus; +- priv->dev = &mdiodev->dev; ++ priv->dev = &pdev->dev; + +- priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset", +- GPIOD_ASIS); +- if (IS_ERR(priv->reset_gpio)) +- return PTR_ERR(priv->reset_gpio); ++ base = devm_platform_ioremap_resource_byname(pdev, "base"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + +- if (priv->reset_gpio) { +- gpiod_set_value_cansleep(priv->reset_gpio, 1); +- /* The active low duration must be greater than 10 ms +- * and checkpatch.pl wants 20 ms. +- */ +- msleep(20); +- gpiod_set_value_cansleep(priv->reset_gpio, 0); ++ priv->regmap = devm_regmap_init_mmio(priv->dev, base, ++ &qca8k_ipq4019_regmap_config); ++ if (IS_ERR(priv->regmap)) { ++ ret = PTR_ERR(priv->regmap); ++ dev_err(priv->dev, "base regmap initialization failed, %d\n", ret); ++ return ret; + } + +- /* Check the detected switch id */ +- ret = qca8k_read_switch_id(priv); +- if (ret) ++ psgmii = devm_platform_ioremap_resource_byname(pdev, "psgmii_phy"); ++ if (IS_ERR(psgmii)) ++ return PTR_ERR(psgmii); ++ ++ priv->psgmii = devm_regmap_init_mmio(priv->dev, psgmii, ++ &qca8k_ipq4019_psgmii_phy_regmap_config); ++ if (IS_ERR(priv->psgmii)) { ++ ret = PTR_ERR(priv->psgmii); ++ dev_err(priv->dev, "PSGMII regmap initialization failed, %d\n", ret); + return ret; ++ } ++ ++ mdio_np = of_parse_phandle(np, "mdio", 0); ++ if (!mdio_np) { ++ dev_err(&pdev->dev, "unable to get MDIO bus phandle\n"); ++ of_node_put(mdio_np); ++ return -EINVAL; ++ } ++ ++ priv->bus = of_mdio_find_bus(mdio_np); ++ of_node_put(mdio_np); ++ if (!priv->bus) { ++ dev_err(&pdev->dev, "unable to find MDIO bus\n"); ++ return -EPROBE_DEFER; ++ } + +- priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); ++ psgmii_ethphy_np = of_parse_phandle(np, "psgmii-ethphy", 0); ++ if (!psgmii_ethphy_np) { ++ dev_dbg(&pdev->dev, "unable to get PSGMII eth PHY phandle\n"); ++ of_node_put(psgmii_ethphy_np); ++ } ++ ++ if (psgmii_ethphy_np) { ++ priv->psgmii_ethphy = of_phy_find_device(psgmii_ethphy_np); ++ of_node_put(psgmii_ethphy_np); ++ if (!priv->psgmii_ethphy) { ++ dev_err(&pdev->dev, "unable to get PSGMII eth PHY\n"); ++ return -ENODEV; ++ } ++ } ++ ++ priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) + return -ENOMEM; + +- priv->ds->dev = &mdiodev->dev; ++ priv->ds->dev = priv->dev; + priv->ds->num_ports = QCA8K_NUM_PORTS; +- priv->ds->configure_vlan_while_not_filtering = true; + priv->ds->priv = priv; + priv->ops = qca8k_switch_ops; + priv->ds->ops = &priv->ops; ++ + mutex_init(&priv->reg_mutex); +- dev_set_drvdata(&mdiodev->dev, priv); ++ platform_set_drvdata(pdev, priv); + + return dsa_register_switch(priv->ds); + } + +-static void +-qca8k_sw_remove(struct mdio_device *mdiodev) ++static int ++qca8k_ipq4019_remove(struct platform_device *pdev) + { +- struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); ++ struct qca8k_priv *priv = dev_get_drvdata(&pdev->dev); + int i; + ++ if (!priv) ++ return 0; ++ + for (i = 0; i < QCA8K_NUM_PORTS; i++) + qca8k_port_set_status(priv, i, 0); + + dsa_unregister_switch(priv->ds); +-} +- +-#ifdef CONFIG_PM_SLEEP +-static void +-qca8k_set_pm(struct qca8k_priv *priv, int enable) +-{ +- int i; +- +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- if (!priv->port_sts[i].enabled) +- continue; +- +- qca8k_port_set_status(priv, i, enable); +- } +-} + +-static int qca8k_suspend(struct device *dev) +-{ +- struct qca8k_priv *priv = dev_get_drvdata(dev); +- +- qca8k_set_pm(priv, 0); +- +- return dsa_switch_suspend(priv->ds); +-} ++ dev_set_drvdata(&pdev->dev, NULL); + +-static int qca8k_resume(struct device *dev) +-{ +- struct qca8k_priv *priv = dev_get_drvdata(dev); +- +- qca8k_set_pm(priv, 1); +- +- return dsa_switch_resume(priv->ds); ++ return 0; + } +-#endif /* CONFIG_PM_SLEEP */ +- +-static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, +- qca8k_suspend, qca8k_resume); +- +-static const struct qca8k_match_data qca8327 = { +- .id = QCA8K_ID_QCA8327, +- .reduced_package = true, +-}; +- +-static const struct qca8k_match_data qca8328 = { +- .id = QCA8K_ID_QCA8327, +-}; +- +-static const struct qca8k_match_data qca833x = { +- .id = QCA8K_ID_QCA8337, +-}; + +-static const struct of_device_id qca8k_of_match[] = { +- { .compatible = "qca,qca8327", .data = &qca8327 }, +- { .compatible = "qca,qca8328", .data = &qca8328 }, +- { .compatible = "qca,qca8334", .data = &qca833x }, +- { .compatible = "qca,qca8337", .data = &qca833x }, ++static const struct of_device_id qca8k_ipq4019_of_match[] = { ++ { .compatible = "qca,ipq4019-qca8337n" }, + { /* sentinel */ }, + }; + +-static struct mdio_driver qca8kmdio_driver = { +- .probe = qca8k_sw_probe, +- .remove = qca8k_sw_remove, +- .mdiodrv.driver = { +- .name = "qca8k", +- .of_match_table = qca8k_of_match, +- .pm = &qca8k_pm_ops, ++static struct platform_driver qca8k_ipq4019_driver = { ++ .probe = qca8k_ipq4019_probe, ++ .remove = qca8k_ipq4019_remove, ++ .driver = { ++ .name = "qca8k-ipq4019", ++ .of_match_table = qca8k_ipq4019_of_match, + }, + }; + +-mdio_module_driver(qca8kmdio_driver); ++module_platform_driver(qca8k_ipq4019_driver); + + MODULE_AUTHOR("Mathieu Olivari, John Crispin "); +-MODULE_DESCRIPTION("Driver for QCA8K ethernet switch family"); ++MODULE_AUTHOR("Gabor Juhos , Robert Marko "); ++MODULE_DESCRIPTION("Qualcomm IPQ4019 built-in switch driver"); + MODULE_LICENSE("GPL v2"); +-MODULE_ALIAS("platform:qca8k"); +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -8,19 +8,12 @@ + #ifndef __QCA8K_H + #define __QCA8K_H + +-#include + #include +-#include + +-#define QCA8K_NUM_PORTS 7 +-#define QCA8K_NUM_CPU_PORTS 2 ++#define QCA8K_NUM_PORTS 6 ++#define QCA8K_CPU_PORT 0 + #define QCA8K_MAX_MTU 9000 + +-#define PHY_ID_QCA8327 0x004dd034 +-#define QCA8K_ID_QCA8327 0x12 +-#define PHY_ID_QCA8337 0x004dd036 +-#define QCA8K_ID_QCA8337 0x13 +- + #define QCA8K_BUSY_WAIT_TIMEOUT 2000 + + #define QCA8K_NUM_FDB_RECORDS 2048 +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -33,46 +26,26 @@ + #define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0) + #define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) + #define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) +-#define QCA8K_REG_PORT0_PAD_CTRL 0x004 +-#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19) +-#define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18) +-#define QCA8K_REG_PORT5_PAD_CTRL 0x008 +-#define QCA8K_REG_PORT6_PAD_CTRL 0x00c +-#define QCA8K_PORT_PAD_RGMII_EN BIT(26) +-#define QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK GENMASK(23, 22) +-#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22) +-#define QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK GENMASK(21, 20) +-#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20) +-#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25) +-#define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) +-#define QCA8K_MAX_DELAY 3 +-#define QCA8K_PORT_PAD_SGMII_EN BIT(7) +-#define QCA8K_REG_PWS 0x010 +-#define QCA8K_PWS_POWER_ON_SEL BIT(31) +-/* This reg is only valid for QCA832x and toggle the package +- * type from 176 pin (by default) to 148 pin used on QCA8327 ++#define QCA8K_REG_RGMII_CTRL 0x004 ++#define QCA8K_RGMII_CTRL_RGMII_RXC GENMASK(1, 0) ++#define QCA8K_RGMII_CTRL_RGMII_TXC GENMASK(9, 8) ++/* Some kind of CLK selection ++ * 0: gcc_ess_dly2ns ++ * 1: gcc_ess_clk + */ +-#define QCA8327_PWS_PACKAGE148_EN BIT(30) +-#define QCA8K_PWS_LED_OPEN_EN_CSR BIT(24) +-#define QCA8K_PWS_SERDES_AEN_DIS BIT(7) ++#define QCA8K_RGMII_CTRL_CLK BIT(10) ++#define QCA8K_RGMII_CTRL_DELAY_RMII0 GENMASK(17, 16) ++#define QCA8K_RGMII_CTRL_INVERT_RMII0_REF_CLK BIT(18) ++#define QCA8K_RGMII_CTRL_DELAY_RMII1 GENMASK(20, 19) ++#define QCA8K_RGMII_CTRL_INVERT_RMII1_REF_CLK BIT(21) ++#define QCA8K_RGMII_CTRL_INVERT_RMII0_MASTER_EN BIT(24) ++#define QCA8K_RGMII_CTRL_INVERT_RMII1_MASTER_EN BIT(25) + #define QCA8K_REG_MODULE_EN 0x030 + #define QCA8K_MODULE_EN_MIB BIT(0) + #define QCA8K_REG_MIB 0x034 + #define QCA8K_MIB_FLUSH BIT(24) + #define QCA8K_MIB_CPU_KEEP BIT(20) + #define QCA8K_MIB_BUSY BIT(17) +-#define QCA8K_MDIO_MASTER_CTRL 0x3c +-#define QCA8K_MDIO_MASTER_BUSY BIT(31) +-#define QCA8K_MDIO_MASTER_EN BIT(30) +-#define QCA8K_MDIO_MASTER_READ BIT(27) +-#define QCA8K_MDIO_MASTER_WRITE 0 +-#define QCA8K_MDIO_MASTER_SUP_PRE BIT(26) +-#define QCA8K_MDIO_MASTER_PHY_ADDR(x) ((x) << 21) +-#define QCA8K_MDIO_MASTER_REG_ADDR(x) ((x) << 16) +-#define QCA8K_MDIO_MASTER_DATA(x) (x) +-#define QCA8K_MDIO_MASTER_DATA_MASK GENMASK(15, 0) +-#define QCA8K_MDIO_MASTER_MAX_PORTS 5 +-#define QCA8K_MDIO_MASTER_MAX_REG 32 + #define QCA8K_GOL_MAC_ADDR0 0x60 + #define QCA8K_GOL_MAC_ADDR1 0x64 + #define QCA8K_MAX_FRAME_SIZE 0x78 +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -109,11 +82,6 @@ + #define QCA8K_SGMII_MODE_CTRL_PHY (1 << 22) + #define QCA8K_SGMII_MODE_CTRL_MAC (2 << 22) + +-/* MAC_PWR_SEL registers */ +-#define QCA8K_REG_MAC_PWR_SEL 0x0e4 +-#define QCA8K_MAC_PWR_RGMII1_1_8V BIT(18) +-#define QCA8K_MAC_PWR_RGMII0_1_8V BIT(19) +- + /* EEE control registers */ + #define QCA8K_REG_EEE_CTRL 0x100 + #define QCA8K_REG_EEE_CTRL_LPI_EN(_i) ((_i + 1) * 2) +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -228,9 +196,15 @@ + /* MIB registers */ + #define QCA8K_PORT_MIB_COUNTER(_i) (0x1000 + (_i) * 0x100) + +-/* QCA specific MII registers */ +-#define MII_ATH_MMD_ADDR 0x0d +-#define MII_ATH_MMD_DATA 0x0e ++/* IPQ4019 PSGMII PHY registers */ ++#define PSGMIIPHY_MODE_CONTROL 0x1b4 ++#define PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M BIT(0) ++#define PSGMIIPHY_TX_CONTROL 0x288 ++#define PSGMIIPHY_TX_CONTROL_MAGIC_VALUE 0x8380 ++#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1 0x9c ++#define PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART BIT(14) ++#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2 0xa0 ++#define PSGMIIPHY_REG_PLL_VCO_CALIB_READY BIT(0) + + enum { + QCA8K_PORT_SPEED_10M = 0, +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -260,29 +234,7 @@ struct ar8xxx_port_status { + int enabled; + }; + +-struct qca8k_match_data { +- u8 id; +- bool reduced_package; +-}; +- +-enum { +- QCA8K_CPU_PORT0, +- QCA8K_CPU_PORT6, +-}; +- +-struct qca8k_ports_config { +- bool sgmii_rx_clk_falling_edge; +- bool sgmii_tx_clk_falling_edge; +- bool sgmii_enable_pll; +- u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ +- u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ +-}; +- + struct qca8k_priv { +- u8 switch_id; +- u8 switch_revision; +- bool legacy_phy_port_mapping; +- struct qca8k_ports_config ports_config; + struct regmap *regmap; + struct mii_bus *bus; + struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -290,8 +242,12 @@ struct qca8k_priv { + struct mutex reg_mutex; + struct device *dev; + struct dsa_switch_ops ops; +- struct gpio_desc *reset_gpio; + unsigned int port_mtu[QCA8K_NUM_PORTS]; ++ ++ /* IPQ4019 specific */ ++ struct regmap *psgmii; ++ bool psgmii_calibrated; ++ struct phy_device *psgmii_ethphy; + }; + + struct qca8k_mib_desc { +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch +@@ -0,0 +1,53 @@ ++From b5f71652b85a85ea53162e9e2b760b84fd0d254f Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 1 Nov 2021 18:10:28 +0100 ++Subject: [PATCH] net: dsa: add Qualcomm IPQ4019 built-in switch support ++ ++Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in. ++ ++It shares most of the stuff with its external counterpart, however it is ++modified for the SoC. ++Namely, it doesn't have second CPU port (Port 6), so it has 6 ports ++instead of 7. ++It also has no built-in PHY-s but rather requires external PSGMII based ++companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry ++out calibration before using them. ++PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which ++unfortunately requires some magic values as the datasheet doesnt document ++the bits that are being set or the register at all. ++ ++Since its built-in it is MMIO like other peripherals and doesn't have its ++own MDIO bus but depends on the SoC provided one. ++ ++CPU connection is at Port 0 and it uses some kind of a internal connection ++and no traditional RGMII/SGMII. ++It also doesn't use in-band tagging like other qca8k switches so a shinfo ++based tagger is used. ++ ++Signed-off-by: Robert Marko ++--- ++ drivers/net/dsa/qca/Kconfig | 9 +++++++++ ++ drivers/net/dsa/qca/Makefile | 1 + ++ 2 files changed, 10 insertions(+) ++ ++--- a/drivers/net/dsa/qca/Kconfig +++++ b/drivers/net/dsa/qca/Kconfig ++@@ -7,3 +7,12 @@ config NET_DSA_AR9331 ++ help ++ This enables support for the Qualcomm Atheros AR9331 built-in Ethernet ++ switch. +++ +++config NET_DSA_QCA8K_IPQ4019 +++ tristate "Qualcomm Atheros IPQ4019 built-in Ethernet switch support" +++ depends on HAS_IOMEM && NET_DSA +++ select NET_DSA_TAG_IPQ4019 +++ select REGMAP +++ help +++ This enables support for the Qualcomm Atheros IPQ4019 SoC built-in +++ Ethernet switch. ++--- a/drivers/net/dsa/qca/Makefile +++++ b/drivers/net/dsa/qca/Makefile ++@@ -1,2 +1,3 @@ ++ # SPDX-License-Identifier: GPL-2.0-only ++ obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o +++obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019) += qca8k-ipq4019.o +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/706-arm-dts-ipq4019-add-switch-node.patch +@@ -0,0 +1,98 @@ ++From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 1 Nov 2021 18:15:04 +0100 ++Subject: [PATCH] arm: dts: ipq4019: add switch node ++ ++Since the built-in IPQ40xx switch now has a driver, add the required node ++for it to work. ++ ++Signed-off-by: Robert Marko ++--- ++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++ ++ 1 file changed, 78 insertions(+) ++ ++--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi ++@@ -590,6 +590,82 @@ ++ status = "disabled"; ++ }; ++ +++ switch: switch@c000000 { +++ compatible = "qca,ipq4019-qca8337n"; +++ reg = <0xc000000 0x80000>, <0x98000 0x800>; +++ reg-names = "base", "psgmii_phy"; +++ resets = <&gcc ESS_PSGMII_ARES>; +++ reset-names = "psgmii_rst"; +++ mdio = <&mdio>; +++ psgmii-ethphy = <&psgmiiphy>; +++ +++ status = "disabled"; +++ +++ ports { +++ #address-cells = <1>; +++ #size-cells = <0>; +++ +++ port@0 { /* MAC0 */ +++ reg = <0>; +++ label = "cpu"; +++ ethernet = <&gmac>; +++ phy-mode = "internal"; +++ +++ fixed-link { +++ speed = <1000>; +++ full-duplex; +++ pause; +++ asym-pause; +++ }; +++ }; +++ +++ swport1: port@1 { /* MAC1 */ +++ reg = <1>; +++ label = "lan1"; +++ phy-handle = <ðphy0>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport2: port@2 { /* MAC2 */ +++ reg = <2>; +++ label = "lan2"; +++ phy-handle = <ðphy1>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport3: port@3 { /* MAC3 */ +++ reg = <3>; +++ label = "lan3"; +++ phy-handle = <ðphy2>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport4: port@4 { /* MAC4 */ +++ reg = <4>; +++ label = "lan4"; +++ phy-handle = <ðphy3>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport5: port@5 { /* MAC5 */ +++ reg = <5>; +++ label = "wan"; +++ phy-handle = <ðphy4>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ }; +++ }; +++ ++ gmac: ethernet@c080000 { ++ compatible = "qcom,ipq4019-ess-edma"; ++ reg = <0xc080000 0x8000>; +--- a/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch ++++ b/target/linux/ipq40xx/patches-5.10/709-arm-dts-ipq4019-QCA807x-properties.patch +@@ -20,7 +20,7 @@ Signed-off-by: Robert Marko + + / { + #address-cells = <1>; +-@@ -645,22 +646,39 @@ ++@@ -726,22 +727,38 @@ + + ethphy0: ethernet-phy@0 { + reg = <0>; +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch +@@ -0,0 +1,53 @@ ++From b5f71652b85a85ea53162e9e2b760b84fd0d254f Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 1 Nov 2021 18:10:28 +0100 ++Subject: [PATCH] net: dsa: add Qualcomm IPQ4019 built-in switch support ++ ++Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in. ++ ++It shares most of the stuff with its external counterpart, however it is ++modified for the SoC. ++Namely, it doesn't have second CPU port (Port 6), so it has 6 ports ++instead of 7. ++It also has no built-in PHY-s but rather requires external PSGMII based ++companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry ++out calibration before using them. ++PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which ++unfortunately requires some magic values as the datasheet doesnt document ++the bits that are being set or the register at all. ++ ++Since its built-in it is MMIO like other peripherals and doesn't have its ++own MDIO bus but depends on the SoC provided one. ++ ++CPU connection is at Port 0 and it uses some kind of a internal connection ++and no traditional RGMII/SGMII. ++It also doesn't use in-band tagging like other qca8k switches so a shinfo ++based tagger is used. ++ ++Signed-off-by: Robert Marko ++--- ++ drivers/net/dsa/qca/Kconfig | 9 +++++++++ ++ drivers/net/dsa/qca/Makefile | 1 + ++ 2 files changed, 10 insertions(+) ++ ++--- a/drivers/net/dsa/qca/Kconfig +++++ b/drivers/net/dsa/qca/Kconfig ++@@ -7,3 +7,12 @@ config NET_DSA_AR9331 ++ help ++ This enables support for the Qualcomm Atheros AR9331 built-in Ethernet ++ switch. +++ +++config NET_DSA_QCA8K_IPQ4019 +++ tristate "Qualcomm Atheros IPQ4019 built-in Ethernet switch support" +++ depends on HAS_IOMEM && NET_DSA +++ select NET_DSA_TAG_IPQ4019 +++ select REGMAP +++ help +++ This enables support for the Qualcomm Atheros IPQ4019 SoC built-in +++ Ethernet switch. ++--- a/drivers/net/dsa/qca/Makefile +++++ b/drivers/net/dsa/qca/Makefile ++@@ -1,2 +1,3 @@ ++ # SPDX-License-Identifier: GPL-2.0-only ++ obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o +++obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019) += qca8k-ipq4019.o +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.15/706-arm-dts-ipq4019-add-switch-node.patch +@@ -0,0 +1,98 @@ ++From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 1 Nov 2021 18:15:04 +0100 ++Subject: [PATCH] arm: dts: ipq4019: add switch node ++ ++Since the built-in IPQ40xx switch now has a driver, add the required node ++for it to work. ++ ++Signed-off-by: Robert Marko ++--- ++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++ ++ 1 file changed, 78 insertions(+) ++ ++--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi ++@@ -590,6 +590,82 @@ ++ status = "disabled"; ++ }; ++ +++ switch: switch@c000000 { +++ compatible = "qca,ipq4019-qca8337n"; +++ reg = <0xc000000 0x80000>, <0x98000 0x800>; +++ reg-names = "base", "psgmii_phy"; +++ resets = <&gcc ESS_PSGMII_ARES>; +++ reset-names = "psgmii_rst"; +++ mdio = <&mdio>; +++ psgmii-ethphy = <&psgmiiphy>; +++ +++ status = "disabled"; +++ +++ ports { +++ #address-cells = <1>; +++ #size-cells = <0>; +++ +++ port@0 { /* MAC0 */ +++ reg = <0>; +++ label = "cpu"; +++ ethernet = <&gmac>; +++ phy-mode = "internal"; +++ +++ fixed-link { +++ speed = <1000>; +++ full-duplex; +++ pause; +++ asym-pause; +++ }; +++ }; +++ +++ swport1: port@1 { /* MAC1 */ +++ reg = <1>; +++ label = "lan1"; +++ phy-handle = <ðphy0>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport2: port@2 { /* MAC2 */ +++ reg = <2>; +++ label = "lan2"; +++ phy-handle = <ðphy1>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport3: port@3 { /* MAC3 */ +++ reg = <3>; +++ label = "lan3"; +++ phy-handle = <ðphy2>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport4: port@4 { /* MAC4 */ +++ reg = <4>; +++ label = "lan4"; +++ phy-handle = <ðphy3>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ +++ swport5: port@5 { /* MAC5 */ +++ reg = <5>; +++ label = "wan"; +++ phy-handle = <ðphy4>; +++ phy-mode = "psgmii"; +++ +++ status = "disabled"; +++ }; +++ }; +++ }; +++ ++ gmac: ethernet@c080000 { ++ compatible = "qcom,ipq4019-ess-edma"; ++ reg = <0xc080000 0x8000>; +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -180,6 +180,7 @@ CONFIG_GPIOLIB_IRQCHIP=y + CONFIG_GPIO_74X164=y + CONFIG_GPIO_WATCHDOG=y + CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y ++CONFIG_GRO_CELLS=y + CONFIG_HANDLE_DOMAIN_IRQ=y + CONFIG_HARDEN_BRANCH_PREDICTOR=y + CONFIG_HARDIRQS_SW_RESEND=y +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -287,8 +288,13 @@ CONFIG_MTD_UBI_WL_THRESHOLD=4096 + CONFIG_MUTEX_SPIN_ON_OWNER=y + CONFIG_NEED_DMA_MAP_STATE=y + CONFIG_NEON=y ++CONFIG_NET_DEVLINK=y ++CONFIG_NET_DSA=y ++CONFIG_NET_DSA_QCA8K_IPQ4019=y ++CONFIG_NET_DSA_TAG_IPQ4019=y + CONFIG_NET_FLOW_LIMIT=y + CONFIG_NET_PTP_CLASSIFY=y ++CONFIG_NET_SWITCHDEV=y + CONFIG_NLS=y + CONFIG_NO_HZ=y + CONFIG_NO_HZ_COMMON=y +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -326,6 +332,7 @@ CONFIG_PCI_MSI_IRQ_DOMAIN=y + CONFIG_PERF_USE_VMALLOC=y + CONFIG_PGTABLE_LEVELS=2 + CONFIG_PHYLIB=y ++CONFIG_PHYLINK=y + # CONFIG_PHY_QCOM_APQ8064_SATA is not set + CONFIG_PHY_QCOM_IPQ4019_USB=y + # CONFIG_PHY_QCOM_IPQ806X_SATA is not set +--- a/target/linux/ipq40xx/config-5.10 ++++ b/target/linux/ipq40xx/config-5.10 +@@ -379,6 +386,7 @@ CONFIG_QCOM_BAM_DMA=y + # CONFIG_QCOM_GSBI is not set + # CONFIG_QCOM_HFPLL is not set + # CONFIG_QCOM_IOMMU is not set ++CONFIG_QCOM_IPQ4019_ESS_EDMA=y + # CONFIG_QCOM_LLCC is not set + # CONFIG_QCOM_OCMEM is not set + # CONFIG_QCOM_PDC is not set +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts +@@ -49,7 +49,7 @@ + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; +- qcom,ess-interface-select = ; ++ qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -820,6 +820,8 @@ static struct phy_driver qca807x_drivers[] = { + .soft_reset = genphy_soft_reset, + .get_tunable = qca807x_get_tunable, + .set_tunable = qca807x_set_tunable, ++ .resume = genphy_resume, ++ .suspend = genphy_suspend, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca807x_cable_test_get_status, +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -844,6 +846,8 @@ static struct phy_driver qca807x_drivers[] = { + .soft_reset = genphy_soft_reset, + .get_tunable = qca807x_get_tunable, + .set_tunable = qca807x_set_tunable, ++ .resume = genphy_resume, ++ .suspend = genphy_suspend, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca807x_cable_test_get_status, + +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -12,9 +12,7 @@ + #include + #include + #include +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + #include +-#endif + #include + #include + +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -191,7 +189,6 @@ static int qca807x_set_tunable(struct phy_device *phydev, + } + } + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + static bool qca807x_distance_valid(int result) + { + switch (result) { +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -324,16 +321,11 @@ static int qca807x_cable_test_start(struct phy_device *phydev) + + return ret; + } +-#endif + + #ifdef CONFIG_GPIOLIB + static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) + { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0) + return GPIO_LINE_DIRECTION_OUT; +-#else +- return GPIOF_DIR_OUT; +-#endif + } + + static int qca807x_gpio_get_reg(unsigned int offset) +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -804,9 +796,7 @@ static struct phy_driver qca807x_drivers[] = { + { + PHY_ID_MATCH_EXACT(PHY_ID_QCA8072), + .name = "Qualcomm QCA8072", +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .flags = PHY_POLL_CABLE_TEST, +-#endif + /* PHY_GBIT_FEATURES */ + .probe = qca807x_probe, + .config_init = qca807x_config, +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -822,17 +812,13 @@ static struct phy_driver qca807x_drivers[] = { + .set_tunable = qca807x_set_tunable, + .resume = genphy_resume, + .suspend = genphy_suspend, +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca807x_cable_test_get_status, +-#endif + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_QCA8075), + .name = "Qualcomm QCA8075", +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .flags = PHY_POLL_CABLE_TEST, +-#endif + /* PHY_GBIT_FEATURES */ + .probe = qca807x_probe, + .config_init = qca807x_config, +--- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c ++++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +@@ -848,10 +834,8 @@ static struct phy_driver qca807x_drivers[] = { + .set_tunable = qca807x_set_tunable, + .resume = genphy_resume, + .suspend = genphy_suspend, +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca807x_cable_test_get_status, +-#endif + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_QCA807X_PSGMII), + +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -602,24 +602,23 @@ qca8k_setup(struct dsa_switch *ds) + return 0; + } + +-static int psgmii_vco_calibrate(struct dsa_switch *ds) ++static int psgmii_vco_calibrate(struct qca8k_priv *priv) + { +- struct qca8k_priv *priv = ds->priv; + int val, ret; + + if (!priv->psgmii_ethphy) { +- dev_err(ds->dev, "PSGMII eth PHY missing, calibration failed!\n"); ++ dev_err(priv->dev, "PSGMII eth PHY missing, calibration failed!\n"); + return -ENODEV; + } + + /* Fix PSGMII RX 20bit */ + ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5b); +- /* Reset PSGMII PHY */ ++ /* Reset PHY PSGMII */ + ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x1b); +- /* Release reset */ ++ /* Release PHY PSGMII reset */ + ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5b); + +- /* Poll for VCO PLL calibration finish */ ++ /* Poll for VCO PLL calibration finish - Malibu(QCA8075) */ + ret = phy_read_mmd_poll_timeout(priv->psgmii_ethphy, + MDIO_MMD_PMAPMD, + 0x28, val, +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -627,9 +626,10 @@ static int psgmii_vco_calibrate(struct dsa_switch *ds) + 10000, 1000000, + false); + if (ret) { +- dev_err(ds->dev, "QCA807x PSGMII VCO calibration PLL not ready\n"); ++ dev_err(priv->dev, "QCA807x PSGMII VCO calibration PLL not ready\n"); + return ret; + } ++ mdelay(50); + + /* Freeze PSGMII RX CDR */ + ret = phy_write(priv->psgmii_ethphy, MII_RESV2, 0x2230); +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -639,32 +639,328 @@ static int psgmii_vco_calibrate(struct dsa_switch *ds) + PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1, + PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART); + +- /* Poll for PSGMIIPHY PLL calibration finish */ ++ /* Poll for PSGMIIPHY PLL calibration finish - Dakota(IPQ40xx) */ + ret = regmap_read_poll_timeout(priv->psgmii, + PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2, + val, val & PSGMIIPHY_REG_PLL_VCO_CALIB_READY, + 10000, 1000000); + if (ret) { +- dev_err(ds->dev, "PSGMIIPHY VCO calibration PLL not ready\n"); ++ dev_err(priv->dev, "IPQ PSGMIIPHY VCO calibration PLL not ready\n"); + return ret; + } ++ mdelay(50); + + /* Release PSGMII RX CDR */ + ret = phy_write(priv->psgmii_ethphy, MII_RESV2, 0x3230); +- + /* Release PSGMII RX 20bit */ + ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5f); ++ mdelay(200); + + return ret; + } + +-static int ipq4019_psgmii_configure(struct dsa_switch *ds) ++static void ++qca8k_switch_port_loopback_on_off(struct qca8k_priv *priv, int port, int on) ++{ ++ u32 val = QCA8K_PORT_LOOKUP_LOOPBACK; ++ ++ if (on == 0) ++ val = 0; ++ ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LOOPBACK, val); ++} ++ ++static int ++qca8k_wait_for_phy_link_state(struct phy_device *phy, int need_status) ++{ ++ int a; ++ u16 status; ++ ++ for (a = 0; a < 100; a++) { ++ status = phy_read(phy, MII_QCA8075_SSTATUS); ++ status &= QCA8075_PHY_SPEC_STATUS_LINK; ++ status = !!status; ++ if (status == need_status) ++ return 0; ++ mdelay(8); ++ } ++ ++ return -1; ++} ++ ++static void ++qca8k_phy_loopback_on_off(struct qca8k_priv *priv, struct phy_device *phy, ++ int sw_port, int on) ++{ ++ if (on) { ++ phy_write(phy, MII_BMCR, BMCR_ANENABLE | BMCR_RESET); ++ phy_modify(phy, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); ++ qca8k_wait_for_phy_link_state(phy, 0); ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), 0); ++ phy_write(phy, MII_BMCR, ++ BMCR_SPEED1000 | ++ BMCR_FULLDPLX | ++ BMCR_LOOPBACK); ++ qca8k_wait_for_phy_link_state(phy, 1); ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), ++ QCA8K_PORT_STATUS_SPEED_1000 | ++ QCA8K_PORT_STATUS_TXMAC | ++ QCA8K_PORT_STATUS_RXMAC | ++ QCA8K_PORT_STATUS_DUPLEX); ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(sw_port), ++ QCA8K_PORT_LOOKUP_STATE_FORWARD, ++ QCA8K_PORT_LOOKUP_STATE_FORWARD); ++ } else { /* off */ ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), 0); ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(sw_port), ++ QCA8K_PORT_LOOKUP_STATE_DISABLED, ++ QCA8K_PORT_LOOKUP_STATE_DISABLED); ++ phy_write(phy, MII_BMCR, BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_RESET); ++ /* turn off the power of the phys - so that unused ++ ports do not raise links */ ++ phy_modify(phy, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); ++ } ++} ++ ++static void ++qca8k_phy_pkt_gen_prep(struct qca8k_priv *priv, struct phy_device *phy, ++ int pkts_num, int on) ++{ ++ if (on) { ++ /* enable CRC checker and packets counters */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, 0); ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, ++ QCA8075_MMD7_CNT_FRAME_CHK_EN | QCA8075_MMD7_CNT_SELFCLR); ++ qca8k_wait_for_phy_link_state(phy, 1); ++ /* packet number */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_NUMB, pkts_num); ++ /* pkt size - 1504 bytes + 20 bytes */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_SIZE, 1504); ++ } else { /* off */ ++ /* packet number */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_NUMB, 0); ++ /* disable CRC checker and packet counter */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, 0); ++ /* disable traffic gen */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, 0); ++ } ++} ++ ++static void ++qca8k_wait_for_phy_pkt_gen_fin(struct qca8k_priv *priv, struct phy_device *phy) ++{ ++ int val; ++ /* wait for all traffic end: 4096(pkt num)*1524(size)*8ns(125MHz)=49938us */ ++ phy_read_mmd_poll_timeout(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, ++ val, !(val & QCA8075_MMD7_PKT_GEN_INPROGR), ++ 50000, 1000000, true); ++} ++ ++static void ++qca8k_start_phy_pkt_gen(struct phy_device *phy) ++{ ++ /* start traffic gen */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, ++ QCA8075_MMD7_PKT_GEN_START | QCA8075_MMD7_PKT_GEN_INPROGR); ++} ++ ++static int ++qca8k_start_all_phys_pkt_gens(struct qca8k_priv *priv) ++{ ++ struct phy_device *phy; ++ phy = phy_device_create(priv->bus, QCA8075_MDIO_BRDCST_PHY_ADDR, ++ 0, 0, NULL); ++ if (!phy) { ++ dev_err(priv->dev, "unable to create mdio broadcast PHY(0x%x)\n", ++ QCA8075_MDIO_BRDCST_PHY_ADDR); ++ return -ENODEV; ++ } ++ ++ qca8k_start_phy_pkt_gen(phy); ++ ++ phy_device_free(phy); ++ return 0; ++} ++ ++static int ++qca8k_get_phy_pkt_gen_test_result(struct phy_device *phy, int pkts_num) ++{ ++ u32 tx_ok, tx_error; ++ u32 rx_ok, rx_error; ++ u32 tx_ok_high16; ++ u32 rx_ok_high16; ++ u32 tx_all_ok, rx_all_ok; ++ ++ /* check counters */ ++ tx_ok = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_RECV_CNT_LO); ++ tx_ok_high16 = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_RECV_CNT_HI); ++ tx_error = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_ERR_CNT); ++ rx_ok = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_RECV_CNT_LO); ++ rx_ok_high16 = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_RECV_CNT_HI); ++ rx_error = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_ERR_CNT); ++ tx_all_ok = tx_ok + (tx_ok_high16 << 16); ++ rx_all_ok = rx_ok + (rx_ok_high16 << 16); ++ ++ if (tx_all_ok < pkts_num) ++ return -1; ++ if(rx_all_ok < pkts_num) ++ return -2; ++ if(tx_error) ++ return -3; ++ if(rx_error) ++ return -4; ++ return 0; /* test is ok */ ++} ++ ++static ++void qca8k_phy_broadcast_write_on_off(struct qca8k_priv *priv, ++ struct phy_device *phy, int on) ++{ ++ u32 val; ++ ++ val = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_MDIO_BRDCST_WRITE); ++ ++ if (on == 0) ++ val &= ~QCA8075_MMD7_MDIO_BRDCST_WRITE_EN; ++ else ++ val |= QCA8075_MMD7_MDIO_BRDCST_WRITE_EN; ++ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_MDIO_BRDCST_WRITE, val); ++} ++ ++static int ++qca8k_test_dsa_port_for_errors(struct qca8k_priv *priv, struct phy_device *phy, ++ int port, int test_phase) ++{ ++ int res = 0; ++ const int test_pkts_num = QCA8075_PKT_GEN_PKTS_COUNT; ++ ++ if (test_phase == 1) { /* start test preps */ ++ qca8k_phy_loopback_on_off(priv, phy, port, 1); ++ qca8k_switch_port_loopback_on_off(priv, port, 1); ++ qca8k_phy_broadcast_write_on_off(priv, phy, 1); ++ qca8k_phy_pkt_gen_prep(priv, phy, test_pkts_num, 1); ++ } else if (test_phase == 2) { ++ /* wait for test results, collect it and cleanup */ ++ qca8k_wait_for_phy_pkt_gen_fin(priv, phy); ++ res = qca8k_get_phy_pkt_gen_test_result(phy, test_pkts_num); ++ qca8k_phy_pkt_gen_prep(priv, phy, test_pkts_num, 0); ++ qca8k_phy_broadcast_write_on_off(priv, phy, 0); ++ qca8k_switch_port_loopback_on_off(priv, port, 0); ++ qca8k_phy_loopback_on_off(priv, phy, port, 0); ++ } ++ ++ return res; ++} ++ ++static int ++qca8k_do_dsa_sw_ports_self_test(struct qca8k_priv *priv, int parallel_test) ++{ ++ struct device_node *dn = priv->dev->of_node; ++ struct device_node *ports, *port; ++ struct device_node *phy_dn; ++ struct phy_device *phy; ++ int reg, err = 0, test_phase; ++ u32 tests_result = 0; ++ ++ ports = of_get_child_by_name(dn, "ports"); ++ if (!ports) { ++ dev_err(priv->dev, "no ports child node found\n"); ++ return -EINVAL; ++ } ++ ++ for (test_phase = 1; test_phase <= 2; test_phase++) { ++ if (parallel_test && test_phase == 2) { ++ err = qca8k_start_all_phys_pkt_gens(priv); ++ if (err) ++ goto error; ++ } ++ for_each_available_child_of_node(ports, port) { ++ err = of_property_read_u32(port, "reg", ®); ++ if (err) ++ goto error; ++ if (reg >= QCA8K_NUM_PORTS) { ++ err = -EINVAL; ++ goto error; ++ } ++ phy_dn = of_parse_phandle(port, "phy-handle", 0); ++ if (phy_dn) { ++ phy = of_phy_find_device(phy_dn); ++ of_node_put(phy_dn); ++ if (phy) { ++ int result; ++ result = qca8k_test_dsa_port_for_errors(priv, ++ phy, reg, test_phase); ++ if (!parallel_test && test_phase == 1) ++ qca8k_start_phy_pkt_gen(phy); ++ put_device(&phy->mdio.dev); ++ if (test_phase == 2) { ++ tests_result <<= 1; ++ if (result) ++ tests_result |= 1; ++ } ++ } ++ } ++ } ++ } ++ ++end: ++ of_node_put(ports); ++ qca8k_fdb_flush(priv); ++ return tests_result; ++error: ++ tests_result |= 0xf000; ++ goto end; ++} ++ ++static int ++psgmii_vco_calibrate_and_test(struct dsa_switch *ds) ++{ ++ int ret, a, test_result; ++ struct qca8k_priv *priv = ds->priv; ++ ++ for (a = 0; a <= QCA8K_PSGMII_CALB_NUM; a++) { ++ ret = psgmii_vco_calibrate(priv); ++ if (ret) ++ return ret; ++ /* first we run serial test */ ++ test_result = qca8k_do_dsa_sw_ports_self_test(priv, 0); ++ /* and if it is ok then we run the test in parallel */ ++ if (!test_result) ++ test_result = qca8k_do_dsa_sw_ports_self_test(priv, 1); ++ if (!test_result) { ++ if (a > 0) { ++ dev_warn(priv->dev, "PSGMII work was stabilized after %d " ++ "calibration retries !\n", a); ++ } ++ return 0; ++ } else { ++ schedule(); ++ if (a > 0 && a % 10 == 0) { ++ dev_err(priv->dev, "PSGMII work is unstable !!! " ++ "Let's try to wait a bit ... %d\n", a); ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(msecs_to_jiffies(a * 100)); ++ } ++ } ++ } ++ ++ panic("PSGMII work is unstable !!! " ++ "Repeated recalibration attempts did not help(0x%x) !\n", ++ test_result); ++ ++ return -EFAULT; ++} ++ ++static int ++ipq4019_psgmii_configure(struct dsa_switch *ds) + { + struct qca8k_priv *priv = ds->priv; + int ret; + + if (!priv->psgmii_calibrated) { +- ret = psgmii_vco_calibrate(ds); ++ ret = psgmii_vco_calibrate_and_test(ds); + + ret = regmap_clear_bits(priv->psgmii, PSGMIIPHY_MODE_CONTROL, + PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M); +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -150,6 +150,7 @@ + #define QCA8K_PORT_LOOKUP_STATE_FORWARD (4 << 16) + #define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) ++#define QCA8K_PORT_LOOKUP_LOOPBACK BIT(21) + + #define QCA8K_REG_GLOBAL_FC_THRESH 0x800 + #define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16) +--- a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h ++++ b/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h +@@ -206,6 +207,28 @@ + #define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2 0xa0 + #define PSGMIIPHY_REG_PLL_VCO_CALIB_READY BIT(0) + ++#define QCA8K_PSGMII_CALB_NUM 100 ++#define MII_QCA8075_SSTATUS 0x11 ++#define QCA8075_PHY_SPEC_STATUS_LINK BIT(10) ++#define QCA8075_MMD7_CRC_AND_PKTS_COUNT 0x8029 ++#define QCA8075_MMD7_PKT_GEN_PKT_NUMB 0x8021 ++#define QCA8075_MMD7_PKT_GEN_PKT_SIZE 0x8062 ++#define QCA8075_MMD7_PKT_GEN_CTRL 0x8020 ++#define QCA8075_MMD7_CNT_SELFCLR BIT(1) ++#define QCA8075_MMD7_CNT_FRAME_CHK_EN BIT(0) ++#define QCA8075_MMD7_PKT_GEN_START BIT(13) ++#define QCA8075_MMD7_PKT_GEN_INPROGR BIT(15) ++#define QCA8075_MMD7_IG_FRAME_RECV_CNT_HI 0x802a ++#define QCA8075_MMD7_IG_FRAME_RECV_CNT_LO 0x802b ++#define QCA8075_MMD7_IG_FRAME_ERR_CNT 0x802c ++#define QCA8075_MMD7_EG_FRAME_RECV_CNT_HI 0x802d ++#define QCA8075_MMD7_EG_FRAME_RECV_CNT_LO 0x802e ++#define QCA8075_MMD7_EG_FRAME_ERR_CNT 0x802f ++#define QCA8075_MMD7_MDIO_BRDCST_WRITE 0x8028 ++#define QCA8075_MMD7_MDIO_BRDCST_WRITE_EN BIT(15) ++#define QCA8075_MDIO_BRDCST_PHY_ADDR 0x1f ++#define QCA8075_PKT_GEN_PKTS_COUNT 4096 ++ + enum { + QCA8K_PORT_SPEED_10M = 0, + QCA8K_PORT_SPEED_100M = 1, + +--- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +@@ -10,7 +10,7 @@ board=$(board_name) + + case "$board" in + alfa-network,ap120c-ac) +- ucidef_set_led_netdev "wan" "WAN" "amber:wan" "eth1" ++ ucidef_set_led_netdev "wan" "WAN" "amber:wan" "wan" + ;; + asus,rt-ac42u) + ucidef_set_led_switch "lan1" "LAN1" "blue:lan-1" "switch0" "0x02" +--- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +@@ -24,7 +24,7 @@ asus,rt-ac58u) + ;; + avm,fritzbox-4040) + ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" "phy1tpt" +- ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" ++ ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan" + ucidef_set_led_switch "lan" "LAN" "green:lan" "switch0" "0x1e" + ;; + avm,fritzbox-7530 |\ +--- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +@@ -55,17 +55,17 @@ engenius,ens620ext) + mikrotik,cap-ac) + ucidef_set_led_default "power" "POWER" "blue:power" "1" + ucidef_set_led_default "user" "USER" "green:user" "0" +- ucidef_set_led_switch "eth1" "ETH1" "green:eth1" "switch0" "0x20" +- ucidef_set_led_switch "eth2" "ETH2" "green:eth2" "switch0" "0x10" ++ ucidef_set_led_netdev "eth1" "ETH1" "green:eth1" "wan" ++ ucidef_set_led_netdev "eth2" "ETH2" "green:eth2" "lan" + ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wlan5g" "phy1tpt" + ;; + mikrotik,hap-ac3) +- ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" +- ucidef_set_led_switch "lan1" "LAN1" "green:lan1" "switch0" "0x10" +- ucidef_set_led_switch "lan2" "LAN2" "green:lan2" "switch0" "0x08" +- ucidef_set_led_switch "lan3" "LAN3" "green:lan3" "switch0" "0x04" +- ucidef_set_led_switch "lan4" "LAN4" "green:lan4" "switch0" "0x02" ++ ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth0" ++ ucidef_set_led_netdev "lan1" "LAN1" "green:lan1" "lan1" ++ ucidef_set_led_netdev "lan2" "LAN2" "green:lan2" "lan2" ++ ucidef_set_led_netdev "lan3" "LAN3" "green:lan3" "lan3" ++ ucidef_set_led_netdev "lan4" "LAN4" "green:lan4" "lan4" + ucidef_set_led_gpio "poe" "POE" "red:poe" "452" "0" + ;; + mikrotik,sxtsq-5-ac) +--- /dev/null ++++ b/target/linux/ipq40xx/base-files/etc/board.d/05_compat-version +@@ -0,0 +1,18 @@ ++# ++# Copyright (C) 2022 OpenWrt.org ++# ++ ++. /lib/functions.sh ++. /lib/functions/uci-defaults.sh ++ ++board_config_update ++ ++case "$(board_name)" in ++ *) ++ ucidef_set_compat_version "1.1" ++ ;; ++esac ++ ++board_config_flush ++ ++exit 0 +--- a/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh ++++ b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh +@@ -21,8 +21,8 @@ preinit_set_mac_address() { + linksys,ea8300|\ + linksys,mr8300) + base_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) +- ip link set dev eth0 address "$base_mac" +- ip link set dev eth1 address $(macaddr_add "$base_mac" 1) ++ ip link set dev lan1 address $(macaddr_add "$base_mac" 1) ++ ip link set dev eth0 address $(macaddr_setbit "$base_mac" 7) + ;; + meraki,mr33|\ + meraki,mr74) +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts +@@ -14,6 +14,7 @@ + led-failsafe = &status; + led-running = &status; + led-upgrade = &status; ++ ethernet1 = &swport5; + }; + + keys { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts +@@ -320,6 +321,24 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cap-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cap-ac.dts +@@ -222,6 +222,24 @@ + #gpio-cells = <2>; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts +@@ -102,6 +102,34 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts +@@ -14,6 +14,8 @@ + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; ++ ethernet0 = &swport5; ++ ethernet1 = &gmac; + }; + + chosen { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts +@@ -287,6 +289,24 @@ + pinctrl-names = "default"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts +@@ -273,6 +273,34 @@ + #gpio-cells = <2>; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &usb3_ss_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts +@@ -251,6 +251,38 @@ + qcom,single-led-10; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++ label = "lan4"; ++}; ++ ++&swport2 { ++ status = "okay"; ++ label = "lan3"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ label = "lan2"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ label = "lan1"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi +@@ -7,6 +7,10 @@ + #include + + / { ++ aliases { ++ ethernet1 = &swport5; ++ }; ++ + soc { + rng@22000 { + status = "okay"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi +@@ -227,6 +231,24 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts +@@ -302,6 +302,42 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++ ++ label = "lan4"; ++}; ++ ++&swport2 { ++ status = "okay"; ++ ++ label = "lan3"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ ++ label = "lan2"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan1"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "ZyXEL-NBG6617"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts +@@ -277,6 +277,34 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "RT-AC58U"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts +@@ -220,3 +220,20 @@ + &mdio { + status = "okay"; + }; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++ ++ /delete-property/ psgmii-ethphy; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++ phy-mode = "rgmii"; ++}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts +@@ -16,6 +16,7 @@ + led-failsafe = &led_power_amber; + led-running = &led_power_green; + led-upgrade = &led_power_amber; ++ ethernet1 = &swport5; + }; + + chosen { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wac510.dts +@@ -336,6 +337,24 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &mdio { + status = "okay"; + +--- 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 +@@ -262,6 +262,30 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZBox-7530"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts +@@ -26,6 +26,10 @@ + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; ++ ++ ethphy: ethernet-phy@0 { ++ reg = <0x0>; ++ }; + }; + + tcsr@1949000 { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts +@@ -237,8 +241,32 @@ + status = "okay"; + }; + +-ðphy0 { +- status = "disabled"; ++&wifi0 { ++ status = "okay"; ++ qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200"; ++}; ++ ++&wifi1 { ++ status = "okay"; ++ qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200"; ++}; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++ ++ /delete-property/ psgmii-ethphy; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii-id"; + }; + + ðphy1 { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts +@@ -18,6 +18,10 @@ + bootargs-append = " root=/dev/mmcblk0p2 rw rootwait clk_ignore_unused"; + }; + ++ aliases { ++ ethernet1 = &swport4; ++ }; ++ + soc { + rng@22000 { + status = "okay"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gl-b2200.dts +@@ -346,6 +350,26 @@ + }; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "wan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts +@@ -15,6 +15,7 @@ + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_upgrade; ++ ethernet1 = &swport5; + }; + + soc { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts +@@ -331,6 +332,34 @@ + }; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hap-ac3.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hap-ac3.dts +@@ -306,6 +306,38 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++ label = "lan4"; ++}; ++ ++&swport2 { ++ status = "okay"; ++ label = "lan3"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ label = "lan2"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ label = "lan1"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-lhgg-60ad.dts +@@ -261,3 +261,21 @@ + &psgmiiphy { + status = "disabled"; + }; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++ ++ /delete-property/ psgmii-ethphy; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++ phy-handle = <ðphy0>; ++ phy-mode = "rgmii-id"; ++}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts +@@ -15,6 +15,7 @@ + led-failsafe = &led_red0; + led-running = &led_blue0; + led-upgrade = &led_red0; ++ ethernet1 = &swport4; + }; + + soc { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts +@@ -340,3 +341,23 @@ + pinctrl-names = "default"; + status = "okay"; + }; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "wan"; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts +@@ -217,6 +217,12 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++ nvmem-cell-names = "mac-address"; ++ nvmem-cells = <&macaddr_config_0>; ++}; ++ + &nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mf286d.dts +@@ -319,6 +325,36 @@ + status = "okay"; + }; + ++&switch { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++ ++ label = "lan4"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ ++ label = "lan3"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan2"; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ nvmem-cell-names = "mac-address"; ++ nvmem-cells = <&macaddr_config_0>; ++ mac-address-increment = <1>; ++}; ++ + &tlmm { + i2c_0_pins: i2c_0_pinmux { + mux { +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-r619ac.dtsi +@@ -320,6 +320,42 @@ + qcom,single-led-10; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++ ++ label = "lan4"; ++}; ++ ++&swport2 { ++ status = "okay"; ++ ++ label = "lan3"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ ++ label = "lan2"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan1"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &usb3_ss_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts +@@ -371,3 +371,23 @@ + status = "okay"; + qcom,ath10k-calibration-variant = "cellc,rtl30vw"; + }; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ ++ label = "lan2"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan1"; ++}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi +@@ -3,7 +3,7 @@ + /* + * Device Tree Source for Linksys xx8300 (Dallas) + * +- * Copyright (C) 2019 Jeff Kletsky ++ * Copyright (C) 2019, 2022 Jeff Kletsky + * Updated 2020 Hans Geiblinger + * + */ +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi +@@ -286,3 +286,31 @@ + &usb3_ss_phy { + status = "okay"; + }; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport1 { ++ status = "okay"; ++}; ++ ++&swport2 { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts +@@ -227,6 +227,14 @@ + precal_art_5000: precal@5000 { + reg = <0x5000 0x2f20>; + }; ++ ++ macaddr_art_e010: mac-address@e010 { ++ reg = <0xe010 0x6>; ++ }; ++ ++ macaddr_art_e018: mac-address@e018 { ++ reg = <0xe018 0x6>; ++ }; + }; + partition6@180000 { + compatible = "denx,fit"; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts +@@ -247,6 +255,30 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ label = "lan1"; ++ ++ nvmem-cells = <&macaddr_art_e018>; ++ nvmem-cell-names = "mac-address"; ++}; ++ ++&swport5 { ++ status = "okay"; ++ label = "lan2"; ++ ++ nvmem-cells = <&macaddr_art_e010>; ++ nvmem-cell-names = "mac-address"; ++}; ++ + &usb3_ss_phy { + status = "okay"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi +@@ -21,7 +21,7 @@ + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + +- ethernet-phy@5 { ++ ethphy: ethernet-phy@5 { + reg = <0x5>; + }; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi +@@ -214,6 +214,24 @@ + }; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++ ++ /delete-property/ psgmii-ethphy; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii-id"; ++}; ++ + ðphy0 { + status = "disabled"; + }; +--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts +@@ -266,6 +266,30 @@ + status = "okay"; + }; + ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++}; ++ ++&swport3 { ++ status = "okay"; ++ ++ label = "lan2"; ++}; ++ ++&swport4 { ++ status = "okay"; ++ ++ label = "lan1"; ++}; ++ ++&swport5 { ++ status = "okay"; ++}; ++ + &wifi0 { + status = "okay"; + nvmem-cell-names = "pre-calibration"; +--- a/target/linux/ipq40xx/image/Makefile ++++ b/target/linux/ipq40xx/image/Makefile +@@ -10,6 +10,8 @@ define Device/Default + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin = sysupgrade-tar | append-metadata + IMAGE/sysupgrade.bin/squashfs := ++ DEVICE_COMPAT_VERSION := 1.1 ++ DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA + endef + + include $(SUBTARGET).mk + +--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -13,7 +13,6 @@ case "$FIRMWARE" in + meraki,mr74) + caldata_extract_ubi "ART" 0x9000 0x844 + caldata_valid "4408" || caldata_extract "ART" 0x9000 0x844 +- ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) 1) + ;; + esac + ;; +--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -117,7 +116,6 @@ case "$FIRMWARE" in + meraki,mr74) + caldata_extract_ubi "ART" 0x1000 0x2f20 + caldata_valid "202f" || caldata_extract "ART" 0x1000 0x2f20 +- ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) 2) + ;; + mikrotik,cap-ac |\ + mikrotik,hap-ac2 |\ +--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -207,7 +205,6 @@ case "$FIRMWARE" in + meraki,mr74) + caldata_extract_ubi "ART" 0x5000 0x2f20 + caldata_valid "202f" || caldata_extract "ART" 0x5000 0x2f20 +- ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) 3) + ;; + mikrotik,cap-ac |\ + mikrotik,hap-ac2 |\ +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -542,10 +542,10 @@ static irqreturn_t ipqess_interrupt_tx(int irq, void *priv) + struct ipqess_tx_ring *tx_ring = (struct ipqess_tx_ring *) priv; + + if (likely(napi_schedule_prep(&tx_ring->napi_tx))) { +- __napi_schedule(&tx_ring->napi_tx); + ipqess_w32(tx_ring->ess, + IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), + 0x0); ++ __napi_schedule(&tx_ring->napi_tx); + } + + return IRQ_HANDLED; +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -556,10 +556,10 @@ static irqreturn_t ipqess_interrupt_rx(int irq, void *priv) + struct ipqess_rx_ring *rx_ring = (struct ipqess_rx_ring *) priv; + + if (likely(napi_schedule_prep(&rx_ring->napi_rx))) { +- __napi_schedule(&rx_ring->napi_rx); + ipqess_w32(rx_ring->ess, + IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx), + 0x0); ++ __napi_schedule(&rx_ring->napi_rx); + } + + return IRQ_HANDLED; +--- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -1269,6 +1269,8 @@ static int ipqess_axi_probe(struct platform_device *pdev) + if (err) + goto err_out; + ++ dev_set_threaded(netdev, true); ++ + for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { + int qid; + + +--- /dev/null ++++ b/target/linux/ipq40xx/patches-5.10/903-dts-remove.patch +@@ -0,0 +1,20 @@ ++--- a/arch/arm/boot/dts/Makefile +++++ b/arch/arm/boot/dts/Makefile ++@@ -918,7 +918,6 @@ ++ qcom-ipq4018-ex6100v2.dtb \ ++ qcom-ipq4018-ex6150v2.dtb \ ++ qcom-ipq4018-fritzbox-4040.dtb \ ++- qcom-ipq4018-gl-ap1300.dtb \ ++ qcom-ipq4018-jalapeno.dtb \ ++ qcom-ipq4018-meshpoint-one.dtb \ ++ qcom-ipq4018-cap-ac.dtb \ ++--- a/arch/arm/boot/dts/Makefile +++++ b/arch/arm/boot/dts/Makefile ++@@ -971,7 +971,6 @@ ++ qcom-ipq4029-gl-b1300.dtb \ ++ qcom-ipq4019-gl-b2200.dtb \ ++ qcom-ipq4029-gl-s1300.dtb \ ++- qcom-ipq4029-mr33.dtb \ ++ qcom-ipq8064-ap148.dtb \ ++ qcom-ipq8064-rb3011.dtb \ ++ qcom-msm8660-surf.dtb \ diff --git a/patches/731-ag71xx-updates-and-fixes.patch b/patches/731-ag71xx-updates-and-fixes.patch new file mode 100644 index 00000000..e3190735 --- /dev/null +++ b/patches/731-ag71xx-updates-and-fixes.patch @@ -0,0 +1,131 @@ +diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +index 1955cd288f..0773f1a5af 100644 +--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h ++++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -65,7 +65,7 @@ + #define AG71XX_TX_RING_SIZE_DEFAULT 128 + #define AG71XX_RX_RING_SIZE_DEFAULT 256 + +-#define AG71XX_TX_RING_SIZE_MAX 128 ++#define AG71XX_TX_RING_SIZE_MAX 256 + #define AG71XX_RX_RING_SIZE_MAX 256 + + #ifdef CONFIG_AG71XX_DEBUG +diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index 2fc18d5979..d553c62401 100644 +--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -34,7 +34,7 @@ MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); + + #define ETH_SWITCH_HEADER_LEN 2 + +-static int ag71xx_tx_packets(struct ag71xx *ag, bool flush); ++static int ag71xx_tx_packets(struct ag71xx *ag, bool flush, int budget); + + static inline unsigned int ag71xx_max_frame_len(unsigned int mtu) + { +@@ -478,7 +478,7 @@ static void ag71xx_fast_reset(struct ag71xx *ag) + mii_reg = ag71xx_rr(ag, AG71XX_REG_MII_CFG); + rx_ds = ag71xx_rr(ag, AG71XX_REG_RX_DESC); + +- ag71xx_tx_packets(ag, true); ++ ag71xx_tx_packets(ag, true, 0); + + reset_control_assert(ag->mac_reset); + udelay(10); +@@ -1245,7 +1245,7 @@ static bool ag71xx_check_dma_stuck(struct ag71xx *ag) + return false; + } + +-static int ag71xx_tx_packets(struct ag71xx *ag, bool flush) ++static int ag71xx_tx_packets(struct ag71xx *ag, bool flush, int budget) + { + struct ag71xx_ring *ring = &ag->tx_ring; + bool dma_stuck = false; +@@ -1278,7 +1278,7 @@ static int ag71xx_tx_packets(struct ag71xx *ag, bool flush) + if (!skb) + continue; + +- dev_kfree_skb_any(skb); ++ napi_consume_skb(skb, budget); + ring->buf[i].skb = NULL; + + bytes_compl += ring->buf[i].len; +@@ -1352,7 +1352,11 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit) + dev->stats.rx_packets++; + dev->stats.rx_bytes += pktlen; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) + skb = build_skb(ring->buf[i].rx_buf, ag71xx_buffer_size(ag)); ++#else ++ skb = napi_build_skb(ring->buf[i].rx_buf, ag71xx_buffer_size(ag)); ++#endif + if (!skb) { + skb_free_frag(ring->buf[i].rx_buf); + goto next; +@@ -1400,7 +1404,7 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) + int tx_done; + int rx_done; + +- tx_done = ag71xx_tx_packets(ag, false); ++ tx_done = ag71xx_tx_packets(ag, false, limit); + + DBG("%s: processing RX ring\n", dev->name); + rx_done = ag71xx_rx_packets(ag, limit); +diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +index a58ee3346b..fd05dbd0ca 100644 +--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c ++++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +@@ -201,10 +201,6 @@ static int ag71xx_mdio_probe(struct platform_device *pdev) + mii_bus->parent = amdev; + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s.%d", np->name, bus_count++); + +- if (!builtin_switch && +- of_property_read_u32(np, "phy-mask", &mii_bus->phy_mask)) +- mii_bus->phy_mask = 0; +- + for (i = 0; i < PHY_MAX_ADDR; i++) + mii_bus->irq[i] = PHY_POLL; + +--- a/target/linux/ath79/dts/qca9558_ubnt_rocket-5ac-lite.dts ++++ b/target/linux/ath79/dts/qca9558_ubnt_rocket-5ac-lite.dts +@@ -21,7 +21,6 @@ + &mdio0 { + status = "okay"; + +- phy-mask = <4>; + phy4: ethernet-phy@4 { + phy-mode = "sgmii"; + reg = <4>; +@@ -36,6 +35,14 @@ + nvmem-cell-names = "mac-address"; + phy-mode = "sgmii"; + phy-handle = <&phy4>; ++ pll-reg = <0 0x48 0>; ++ pll-data = <0x03000000 0x00000101 0x00001313>; ++ ++ qca955x-sgmii-fixup; ++ ++ gmac-config { ++ device = <&gmac>; ++ }; + }; + + &art { +--- a/target/linux/ath79/dts/qca9558_ubnt_powerbeam-5ac-500.dts ++++ b/target/linux/ath79/dts/qca9558_ubnt_powerbeam-5ac-500.dts +@@ -36,6 +35,14 @@ + nvmem-cell-names = "mac-address"; + phy-mode = "sgmii"; + phy-handle = <&phy4>; ++ pll-reg = <0 0x48 0>; ++ pll-data = <0x03000000 0x00000101 0x00001313>; ++ ++ qca955x-sgmii-fixup; ++ ++ gmac-config { ++ device = <&gmac>; ++ }; + }; + + &art { diff --git a/patches/742-5-and-10mhz-ath10k-ct-support.patch b/patches/742-5-and-10mhz-ath10k-ct-support.patch new file mode 100644 index 00000000..fd0a1c3c --- /dev/null +++ b/patches/742-5-and-10mhz-ath10k-ct-support.patch @@ -0,0 +1,277 @@ +Index: openwrt/package/kernel/ath10k-ct/patches/999-0002-ath10k-5_10Mhz.patch +=================================================================== +--- /dev/null ++++ openwrt/package/kernel/ath10k-ct/patches/999-0002-ath10k-5_10Mhz.patch +@@ -0,0 +1,272 @@ ++diff -urpN a/ath10k-5.15/debug.c b/ath10k-5.15/debug.c ++--- a/ath10k-5.15/debug.c 2022-05-13 22:42:36.000000000 +0100 +++++ b/ath10k-5.15/debug.c 2022-11-29 12:22:12.836789627 +0000 ++@@ -4403,6 +4403,54 @@ static const struct file_operations fops ++ .llseek = default_llseek, ++ }; ++ +++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, +++ size_t count, loff_t *ppos) +++{ +++ struct ath10k *ar = file->private_data; +++ struct ath_common *common = &ar->ath_common; +++ char buf[32]; +++ unsigned int len; +++ +++ len = sprintf(buf, "0x%08x\n", common->chan_bw); +++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); +++} +++ +++int ath10k_update_channel_list(struct ath10k *ar); +++ +++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, +++ size_t count, loff_t *ppos) +++{ +++ struct ath10k *ar = file->private_data; +++ struct ath_common *common = &ar->ath_common; +++ unsigned long chan_bw; +++ int ret; +++ char buf[32]; +++ ssize_t len; +++ +++ len = min(count, sizeof(buf) - 1); +++ if (copy_from_user(buf, user_buf, len)) +++ return -EFAULT; +++ +++ buf[len] = '\0'; +++ if (kstrtoul(buf, 0, &chan_bw)) +++ return -EINVAL; +++ +++ common->chan_bw = chan_bw; +++ ret = ath10k_update_channel_list(ar); +++ if (ret) +++ ath10k_warn(ar, "failed to update channel list: %d\n", ret); +++ +++ return count; +++} +++ +++static const struct file_operations fops_chanbw = { +++ .read = read_file_chan_bw, +++ .write = write_file_chan_bw, +++ .open = simple_open, +++ .owner = THIS_MODULE, +++ .llseek = default_llseek, +++}; +++ ++ int ath10k_debug_create(struct ath10k *ar) ++ { ++ ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN); ++@@ -4451,6 +4499,9 @@ int ath10k_debug_register(struct ath10k ++ init_completion(&ar->debug.ratepwr_tbl_complete); ++ init_completion(&ar->debug.powerctl_tbl_complete); ++ +++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, ar->debug.debugfs_phy, +++ ar, &fops_chanbw); +++ ++ debugfs_create_file("fw_stats", 0400, ar->debug.debugfs_phy, ar, ++ &fops_fw_stats); ++ ++diff -urpN a/ath10k-5.15/mac.c b/ath10k-5.15/mac.c ++--- a/ath10k-5.15/mac.c 2022-11-29 12:18:41.281151667 +0000 +++++ b/ath10k-5.15/mac.c 2022-11-29 12:21:15.199940728 +0000 ++@@ -697,6 +697,8 @@ chan_to_phymode(const struct cfg80211_ch ++ switch (chandef->chan->band) { ++ case NL80211_BAND_2GHZ: ++ switch (chandef->width) { +++ case NL80211_CHAN_WIDTH_5: +++ case NL80211_CHAN_WIDTH_10: ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM) ++ phymode = MODE_11B; ++@@ -716,6 +718,8 @@ chan_to_phymode(const struct cfg80211_ch ++ break; ++ case NL80211_BAND_5GHZ: ++ switch (chandef->width) { +++ case NL80211_CHAN_WIDTH_5: +++ case NL80211_CHAN_WIDTH_10: ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ phymode = MODE_11A; ++ break; ++@@ -1311,6 +1315,16 @@ static int ath10k_monitor_vdev_start(str ++ arg.channel.max_reg_power = channel->max_reg_power * 2; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); +++ arg.channel.quarter = false; +++ arg.channel.half = false; +++ if (ar->ath_common.chan_bw == 5) +++ arg.channel.quarter = true; +++ else if (ar->ath_common.chan_bw == 10) +++ arg.channel.half = true; +++ else if (chandef->width == NL80211_CHAN_WIDTH_5) +++ arg.channel.quarter = true; +++ else if (chandef->width == NL80211_CHAN_WIDTH_10) +++ arg.channel.half = true; ++ ++ reinit_completion(&ar->vdev_setup_done); ++ reinit_completion(&ar->vdev_delete_done); ++@@ -1756,6 +1770,21 @@ static int ath10k_vdev_start_restart(str ++ } ++ } ++ +++ arg.channel.quarter = false; +++ arg.channel.half = false; +++ if (ar->ath_common.chan_bw == 5) +++ arg.channel.quarter = true; +++ else if (ar->ath_common.chan_bw == 10) +++ arg.channel.half = true; +++ else if (chandef->width == NL80211_CHAN_WIDTH_5) { +++ arg.channel.quarter = true; +++ ar->ath_common.chan_bw = 5; +++ } +++ else if (chandef->width == NL80211_CHAN_WIDTH_10) { +++ arg.channel.half = true; +++ ar->ath_common.chan_bw = 10; +++ } +++ ++ if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ arg.ssid = arvif->u.ap.ssid; ++ arg.ssid_len = arvif->u.ap.ssid_len; ++@@ -4097,7 +4126,7 @@ static int ath10k_station_disassoc(struc ++ /* Regulatory */ ++ /**************/ ++ ++-static int ath10k_update_channel_list(struct ath10k *ar) +++int ath10k_update_channel_list(struct ath10k *ar) ++ { ++ struct ieee80211_hw *hw = ar->hw; ++ struct ieee80211_supported_band **bands; ++@@ -4174,6 +4203,12 @@ static int ath10k_update_channel_list(st ++ ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); ++ ch->reg_class_id = 0; /* FIXME */ +++ ch->half = false; +++ ch->quarter = false; +++ if (ar->ath_common.chan_bw == 5) +++ ch->quarter = true; +++ else if (ar->ath_common.chan_bw == 10) +++ ch->half = true; ++ ++ /* FIXME: why use only legacy modes, why not any ++ * HT/VHT modes? Would that even make any ++@@ -5841,6 +5876,7 @@ static void ath10k_mac_setup_ht_vht_cap( ++ if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { ++ band = &ar->mac.sbands[NL80211_BAND_2GHZ]; ++ band->ht_cap = ht_cap; +++ band->vht_cap = vht_cap; ++ ++ /* Enable the VHT support at 2.4 GHz */ ++ band->vht_cap = vht_cap; ++@@ -7179,7 +7215,7 @@ static void ath10k_mac_op_set_coverage_c ++ if (value != ar->fw_coverage.coverage_class) ++ ar->eeprom_overrides.coverage_already_set = false; /* value is being changed */ ++ mutex_unlock(&ar->conf_mutex); ++- +++ ++ ar->hw_params.hw_ops->set_coverage_class(ar, value); ++ } ++ ++@@ -7319,6 +7355,11 @@ static int ath10k_hw_scan(struct ieee802 ++ arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; ++ } ++ +++ if (ar->ath_common.chan_bw == 5) +++ arg.scan_ctrl_flags |= WMI_SCAN_FLAG_QUARTER_RATE_SUPPORT; +++ else if (ar->ath_common.chan_bw == 10) +++ arg.scan_ctrl_flags |= WMI_SCAN_FLAG_HALF_RATE_SUPPORT; +++ ++ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { ++ arg.scan_ctrl_flags |= WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ; ++ ether_addr_copy(arg.mac_addr.addr, req->mac_addr); ++@@ -8849,6 +8890,10 @@ static int ath10k_remain_on_channel(stru ++ arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; ++ arg.scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ; ++ arg.burst_duration_ms = duration; +++ if (ar->ath_common.chan_bw == 5) +++ arg.scan_ctrl_flags |= WMI_SCAN_FLAG_QUARTER_RATE_SUPPORT; +++ else if (ar->ath_common.chan_bw == 10) +++ arg.scan_ctrl_flags |= WMI_SCAN_FLAG_HALF_RATE_SUPPORT; ++ ++ if (ath10k_mac_vif_has_any_cck(ar, vif, (1 << chan->band))) ++ arg.scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES; ++@@ -11296,6 +11341,7 @@ int ath10k_mac_register(struct ath10k *a ++ ieee80211_hw_set(ar->hw, TDLS_WIDER_BW); ++ } ++ +++ ar->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; ++ if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map)) ++ ieee80211_hw_set(ar->hw, SUPPORTS_TDLS_BUFFER_STA); ++ ++diff -urpN a/ath10k-5.15/spectral.c b/ath10k-5.15/spectral.c ++--- a/ath10k-5.15/spectral.c 2022-11-29 12:18:41.285151725 +0000 +++++ b/ath10k-5.15/spectral.c 2022-11-29 12:21:15.199940728 +0000 ++@@ -90,6 +90,12 @@ int ath10k_spectral_process_fft(struct a ++ * but the results/plots suggest that its actually 22/44/88 MHz. ++ */ ++ switch (phyerr->chan_width_mhz) { +++ case 5: +++ fft_sample->chan_width_mhz = 5; +++ break; +++ case 10: +++ fft_sample->chan_width_mhz = 11; +++ break; ++ case 20: ++ fft_sample->chan_width_mhz = 22; ++ break; ++diff -urpN a/ath10k-5.15/wmi.c b/ath10k-5.15/wmi.c ++--- a/ath10k-5.15/wmi.c 2022-11-29 12:18:41.277151608 +0000 +++++ b/ath10k-5.15/wmi.c 2022-11-29 12:21:15.203940797 +0000 ++@@ -1786,6 +1786,10 @@ void ath10k_wmi_put_wmi_channel(struct a ++ flags |= WMI_CHAN_FLAG_HT40_PLUS; ++ if (arg->chan_radar) ++ flags |= WMI_CHAN_FLAG_DFS; +++ if (arg->quarter) +++ flags |= WMI_CHAN_FLAG_QUARTER; +++ else if (arg->half) +++ flags |= WMI_CHAN_FLAG_HALF; ++ ++ ch->band_center_freq2 = 0; ++ ++@@ -8546,6 +8550,12 @@ ath10k_wmi_op_gen_scan_chan_list(struct ++ for (i = 0; i < arg->n_channels; i++) { ++ ch = &arg->channels[i]; ++ ci = &cmd->chan_info[i]; +++ ch->quarter = false; +++ ch->half = false; +++ if (ar->ath_common.chan_bw == 5) +++ ch->quarter = true; +++ else if (ar->ath_common.chan_bw == 10) +++ ch->half = true; ++ ++ ath10k_wmi_put_wmi_channel(ar, ci, ch, -1); ++ } ++diff -urpN a/ath10k-5.15/wmi.h b/ath10k-5.15/wmi.h ++--- a/ath10k-5.15/wmi.h 2022-11-29 12:18:41.277151608 +0000 +++++ b/ath10k-5.15/wmi.h 2022-11-29 12:21:15.207940866 +0000 ++@@ -2146,6 +2146,8 @@ struct wmi_channel_arg { ++ bool allow_ht; ++ bool allow_vht; ++ bool ht40plus; +++ bool quarter; +++ bool half; ++ bool chan_radar; ++ /* note: power unit is 0.5 dBm */ ++ u32 min_power; ++@@ -3431,6 +3433,18 @@ struct wmi_start_scan_arg { ++ * Allow the driver to have influence over that. ++ */ ++ #define WMI_SCAN_CONTINUE_ON_ERROR 0x80 +++/** set scan with promiscous mode */ +++#define WMI_SCAN_PROMISCOUS_MODE 0x80 +++/** allow capture ppdu with phy errrors */ +++#define WMI_SCAN_CAPTURE_PHY_ERROR 0x100 +++/** always do passive scan on passive channels */ +++#define WMI_SCAN_FLAG_STRICT_PASSIVE_ON_PCHN 0x200 +++/** set HALF (10MHz) rate support */ +++#define WMI_SCAN_FLAG_HALF_RATE_SUPPORT 0x20000 +++/** set Quarter (5MHz) rate support */ +++#define WMI_SCAN_FLAG_QUARTER_RATE_SUPPORT 0x40000 +++/** WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */ +++#define WMI_SCAN_CLASS_MASK 0xFF000000 ++ ++ /* Use random MAC address for TA for Probe Request frame and add ++ * OUI specified by WMI_SCAN_PROB_REQ_OUI_CMDID to the Probe Request frame. diff --git a/patches/743-mac80211-ath10k.patch b/patches/743-mac80211-ath10k.patch new file mode 100644 index 00000000..4b9c5941 --- /dev/null +++ b/patches/743-mac80211-ath10k.patch @@ -0,0 +1,22 @@ +--- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh ++++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +@@ -1081,7 +1081,7 @@ + staidx=0 + + [ -n "$chanbw" ] && { +- for file in /sys/kernel/debug/ieee80211/$phy/ath9k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do ++ for file in /sys/kernel/debug/ieee80211/$phy/ath10k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath9k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do + [ -f "$file" ] && echo "$chanbw" > "$file" + done + } +--- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh ++++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +@@ -1098,6 +1098,8 @@ + iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 + if [ $distance -eq 0 -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ]; then + iw phy "$phy" set distance auto ++ elif [ $distance -eq 0 -a -d /sys/kernel/debug/ieee80211/$phy/ath10k ]; then ++ iw phy "$phy" set distance auto + else + iw phy "$phy" set distance "$distance" + fi diff --git a/patches/744-dd-wrt-firmware.patch b/patches/744-dd-wrt-firmware.patch new file mode 100644 index 00000000..3fa17aa3 --- /dev/null +++ b/patches/744-dd-wrt-firmware.patch @@ -0,0 +1,23 @@ +--- a/package/firmware/ath10k-ct-firmware/Makefile ++++ b/package/firmware/ath10k-ct-firmware/Makefile +@@ -620,7 +620,7 @@ + + $(eval $(call BuildPackage,ath10k-firmware-qca9887-ct)) + $(eval $(call BuildPackage,ath10k-firmware-qca9887-ct-full-htt)) +-$(eval $(call BuildPackage,ath10k-firmware-qca988x-ct)) ++$(eval $(call BuildPackage,ath10k-firmware-qca988x-ct)) + $(eval $(call BuildPackage,ath10k-firmware-qca988x-ct-full-htt)) + $(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct)) + $(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct-full-htt)) +@@ -628,9 +628,9 @@ + $(eval $(call BuildPackage,ath10k-firmware-qca9984-ct)) + $(eval $(call BuildPackage,ath10k-firmware-qca9984-ct-full-htt)) + $(eval $(call BuildPackage,ath10k-firmware-qca9984-ct-htt)) +-$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct)) ++#$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct)) + $(eval $(call BuildPackage,ath10k-firmware-qca4019-ct-full-htt)) + $(eval $(call BuildPackage,ath10k-firmware-qca4019-ct-htt)) +-$(eval $(call BuildPackage,ath10k-firmware-qca9888-ct)) ++#$(eval $(call BuildPackage,ath10k-firmware-qca9888-ct)) + $(eval $(call BuildPackage,ath10k-firmware-qca9888-ct-full-htt)) + $(eval $(call BuildPackage,ath10k-firmware-qca9888-ct-htt)) diff --git a/patches/745-ath10k-more-scan-channels.patch b/patches/745-ath10k-more-scan-channels.patch new file mode 100644 index 00000000..c9a77f96 --- /dev/null +++ b/patches/745-ath10k-more-scan-channels.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ n/package/kernel/ath10k-ct/patches/999-0003-ath10k-scan-channels.patch +@@ -0,0 +1,12 @@ ++--- a/ath10k-5.15/wmi.h +++++ b/ath10k-5.15/wmi.h ++@@ -3406,7 +3406,7 @@ ++ u32 n_bssids; ++ ++ u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN]; ++- u16 channels[64]; +++ u16 channels[256]; ++ struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID]; ++ struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID]; ++ struct wmi_mac_addr mac_addr; ++ diff --git a/patches/746-rocket-m-xw-support.patch b/patches/746-rocket-m-xw-support.patch new file mode 100644 index 00000000..2cc836da --- /dev/null +++ b/patches/746-rocket-m-xw-support.patch @@ -0,0 +1,55 @@ +--- a/target/linux/ath79/image/generic-ubnt.mk ++++ b/target/linux/ath79/image/generic-ubnt.mk +@@ -157,6 +157,14 @@ + endef + TARGET_DEVICES += ubnt_powerbeam-m5-xw + ++define Device/ubnt_rocket-m-xw ++ $(Device/ubnt-xw) ++ DEVICE_MODEL := Rocket M XW ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += rocket-m-xw loco-m-xw ++endef ++TARGET_DEVICES += ubnt_rocket-m-xw ++ + define Device/ubnt_rocket-5ac-lite + $(Device/ubnt-xc) + SOC := qca9558 + +--- /dev/null ++++ b/target/linux/ath79/dts/ar9342_ubnt_rocket-m-xw.dts +@@ -0,0 +1,34 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++#include "ar9342_ubnt_xw.dtsi" ++ ++/ { ++ compatible = "ubnt,rocket-m-xw", "ubnt,xw", "qca,ar9342"; ++ model = "Ubiquiti Rocket M (XW)"; ++}; ++ ++&mdio0 { ++ status = "okay"; ++ ++ phy-mask = <4>; ++ ++ phy4: ethernet-phy@4 { ++ reg = <4>; ++ }; ++}; ++ ++ð0 { ++ status = "okay"; ++ ++ /* default for ar934x, except for 1000M and 10M */ ++ pll-data = <0x02000000 0x00000101 0x00001313>; ++ ++ phy-mode = "rgmii-id"; ++ phy-handle = <&phy4>; ++ ++ gmac-config { ++ device = <&gmac>; ++ rxd-delay = <3>; ++ rxdv-delay = <3>; ++ }; ++}; diff --git a/patches/747-mikrotik-extra-support.patch b/patches/747-mikrotik-extra-support.patch new file mode 100644 index 00000000..44823930 --- /dev/null +++ b/patches/747-mikrotik-extra-support.patch @@ -0,0 +1,500 @@ +--- a/target/linux/ath79/image/mikrotik.mk ++++ a/target/linux/ath79/image/mikrotik.mk +@@ -102,6 +102,15 @@ + endef + TARGET_DEVICES += mikrotik_routerboard-mapl-2nd + ++define Device/mikrotik_routerboard-sxt-5nd ++ $(Device/mikrotik_nor) ++ SOC := ar9344 ++ DEVICE_MODEL := RouterBOARD SXT 5nD (SXT Lite5) ++ DEVICE_PACKAGES += rssileds ++ IMAGE_SIZE := 16256k ++endef ++TARGET_DEVICES += mikrotik_routerboard-sxt-5nd ++ + define Device/mikrotik_routerboard-sxt-5nd-r2 + $(Device/mikrotik_nand) + SOC := ar9344 + +--- /dev/null 2022-10-26 ++++ b/target/linux/ath79/dts/ar9344_mikrotik_routerboard-sxt-5nd.dts +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++#include "ar9344_mikrotik_routerboard-16m-nor.dtsi" ++ ++#include ++#include ++ ++/ { ++ compatible = "mikrotik,routerboard-sxt-5nd", "qca,ar9344"; ++ model = "MikroTik RouterBOARD SXT 5nD (SXT Lite5)"; ++ ++ aliases { ++ led-boot = &led_user; ++ led-failsafe = &led_user; ++ led-running = &led_user; ++ led-upgrade = &led_user; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power { ++ label = "blue:power"; ++ gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ rssilow { ++ label = "green:rssilow"; ++ gpios = <&gpio 13 GPIO_ACTIVE_LOW>; ++ }; ++ ++ rssimediumlow { ++ label = "green:rssimediumlow"; ++ gpios = <&gpio 12 GPIO_ACTIVE_LOW>; ++ }; ++ ++ rssimedium { ++ label = "green:rssimedium"; ++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>; ++ }; ++ ++ rssimediumhigh { ++ label = "green:rssimediumhigh"; ++ gpios = <&gpio 21 GPIO_ACTIVE_LOW>; ++ }; ++ ++ rssihigh { ++ label = "green:rssihigh"; ++ gpios = <&gpio 18 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led_user: user { ++ label = "white:user"; ++ gpios = <&gpio 20 GPIO_ACTIVE_LOW>; ++ }; ++ ++ lan { ++ label = "green:lan"; ++ gpios = <&gpio 14 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ ++ reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&gpio 15 GPIO_ACTIVE_LOW>; ++ debounce-interval = <60>; ++ }; ++ }; ++}; ++ ++ð0 { ++ status = "okay"; ++ ++ phy-handle = <&swphy0>; ++ ++ gmac-config { ++ device = <&gmac>; ++ switch-phy-swap = <1>; ++ }; ++}; ++ ++ð1 { ++ status = "okay"; ++ ++ compatible = "syscon", "simple-mfd"; ++}; +--- a/target/linux/ipq40xx/image/mikrotik.mk ++++ b/target/linux/ipq40xx/image/mikrotik.mk +@@ -62,3 +62,11 @@ + DEVICE_PACKAGES := rssileds + endef + TARGET_DEVICES += mikrotik_sxtsq-5-ac ++ ++define Device/mikrotik_lhgg-5acd ++ $(call Device/mikrotik_nor) ++ DEVICE_MODEL := RouterBOARD LHG 5 AC ++ SOC := qcom-ipq4018 ++ DEVICE_PACKAGES := rssileds ++endef ++TARGET_DEVICES += mikrotik_lhgg-5acd +--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network ++++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network +@@ -35,6 +35,7 @@ + zyxel,wre6606) + ucidef_set_interface_lan "eth0" + ;; ++ mikrotik,lhgg-5acd|\ + mikrotik,sxtsq-5-ac) + ucidef_set_interfaces_lan_wan "lan" "lan.1" + ucidef_set_interface "wifi" device "wlan0" protocol "static" +@@ -216,6 +217,7 @@ + label_mac="$wan_mac" + ;; + mikrotik,lhgg-60ad|\ ++ mikrotik,lhgg-5acd|\ + mikrotik,sxtsq-5-ac) + lan_mac=$(cat /sys/firmware/mikrotik/hard_config/mac_base) + label_mac="$lan_mac" +--- /dev/null ++++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-lhgg-5acd.dts +@@ -0,0 +1,239 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* Copyright (c) 2020, Robert Marko */ ++ ++#include "qcom-ipq4019.dtsi" ++#include ++#include ++#include ++ ++/ { ++ model = "MikroTik LHG 5 ac (RBLHGG-5acD)"; ++ compatible = "mikrotik,lhgg-5acd"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ led-boot = &led_user; ++ led-failsafe = &led_user; ++ led-running = &led_user; ++ led-upgrade = &led_user; ++ }; ++ ++ soc { ++ rng@22000 { ++ status = "okay"; ++ }; ++ ++ mdio@90000 { ++ status = "okay"; ++ }; ++ ++ counter@4a1000 { ++ compatible = "qcom,qca-gcnt"; ++ reg = <0x4a1000 0x4>; ++ }; ++ ++ tcsr@1949000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1949000 0x100>; ++ qcom,wifi_glb_cfg = ; ++ }; ++ ++ ess_tcsr@1953000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1953000 0x1000>; ++ qcom,ess-interface-select = ; ++ }; ++ ++ tcsr@1957000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1957000 0x100>; ++ qcom,wifi_noc_memtype_m0_m2 = ; ++ }; ++ ++ crypto@8e3a000 { ++ status = "okay"; ++ }; ++ ++ watchdog@b017000 { ++ status = "okay"; ++ }; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power { ++ label = "blue:power"; ++ gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; ++ default-state = "keep"; ++ panic-indicator; ++ }; ++ ++ led_user: user { ++ label = "green:user"; ++ gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ rssilow { ++ label = "green:rssilow"; ++ gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ rssimediumlow { ++ label = "green:rssimediumlow"; ++ gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ rssimedium { ++ label = "green:rssimedium"; ++ gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ rssimediumhigh { ++ label = "green:rssimediumhigh"; ++ gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ rssihigh { ++ label = "green:rssihigh"; ++ gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; ++ ++&tlmm { ++ serial_pins: serial_pinmux { ++ mux { ++ pins = "gpio60", "gpio61"; ++ function = "blsp_uart0"; ++ bias-disable; ++ }; ++ }; ++ ++ spi_0_pins: spi_0_pinmux { ++ pin { ++ function = "blsp_spi0"; ++ pins = "gpio55", "gpio56", "gpio57"; ++ drive-strength = <2>; ++ bias-disable; ++ }; ++ pin_cs { ++ function = "gpio"; ++ pins = "gpio54"; ++ drive-strength = <2>; ++ bias-disable; ++ output-high; ++ }; ++ }; ++}; ++ ++&blsp_dma { ++ status = "okay"; ++}; ++ ++&blsp1_spi1 { ++ status = "okay"; ++ ++ pinctrl-0 = <&spi_0_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; ++ ++ flash@0 { ++ reg = <0>; ++ compatible = "jedec,spi-nor"; ++ spi-max-frequency = <40000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "Qualcomm"; ++ reg = <0x0 0x80000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ compatible = "mikrotik,routerboot-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ label = "RouterBoot"; ++ reg = <0x80000 0x80000>; ++ ++ hard_config { ++ read-only; ++ }; ++ ++ dtb_config { ++ read-only; ++ }; ++ ++ soft_config { ++ }; ++ }; ++ ++ partition@100000 { ++ compatible = "mikrotik,minor"; ++ label = "firmware"; ++ reg = <0x100000 0xf00000>; ++ }; ++ }; ++ }; ++}; ++ ++&blsp1_uart1 { ++ status = "okay"; ++ ++ pinctrl-0 = <&serial_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&cryptobam { ++ status = "okay"; ++}; ++ ++&wifi1 { ++ status = "okay"; ++ ++ qcom,ath10k-calibration-variant = "MikroTik-LHGG-5acD"; ++}; ++ ++&mdio { ++ status = "okay"; ++}; ++ ++&gmac { ++ status = "okay"; ++}; ++ ++&switch { ++ status = "okay"; ++ ++ /delete-property/ psgmii-ethphy; ++}; ++ ++&swport5 { ++ status = "okay"; ++ ++ label = "lan"; ++ phy-mode = "rgmii"; ++}; +--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -197,6 +197,7 @@ + mikrotik,cap-ac |\ + mikrotik,hap-ac2 |\ + mikrotik,hap-ac3 |\ ++ mikrotik,lhgg-5acd |\ + mikrotik,sxtsq-5-ac) + wlan_data="/sys/firmware/mikrotik/hard_config/wlan_data" + ( [ -f "$wlan_data" ] && caldata_sysfsload_from_file "$wlan_data" 0x8000 0x2f20 ) || \ +@@ -236,6 +237,7 @@ + mikrotik,cap-ac |\ + mikrotik,hap-ac2 |\ + mikrotik,hap-ac3 |\ ++ mikrotik,lhgg-5acd |\ + mikrotik,sxtsq-5-ac) + wlan_data="/sys/firmware/mikrotik/hard_config/wlan_data" + ( [ -f "$wlan_data" ] && caldata_sysfsload_from_file "$wlan_data" 0xaf20 0x2f20 ) || \ +--- a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh +@@ -163,12 +163,13 @@ + ;; + mikrotik,cap-ac|\ + mikrotik,hap-ac2|\ ++ mikrotik,lhgg-5acd|\ + mikrotik,lhgg-60ad|\ + mikrotik,sxtsq-5-ac) + [ "$(rootfs_type)" = "tmpfs" ] && mtd erase firmware + default_do_upgrade "$1" + ;; + mikrotik,hap-ac3) + platform_do_upgrade_mikrotik_nand "$1" + ;; + netgear,rbr50 |\ +--- a/target/linux/ath79/image/common-mikrotik.mk ++++ b/target/linux/ath79/image/common-mikrotik.mk +@@ -17,5 +17,4 @@ + IMAGE/sysupgrade.bin = append-kernel | kernel2minor -s 2048 -e -c | \ + sysupgrade-tar kernel=$$$$@ | append-metadata + DEVICE_PACKAGES := nand-utils +- DEFAULT := n + endef +--- a/target/linux/ath79/image/mikrotik.mk ++++ b/target/linux/ath79/image/mikrotik.mk +@@ -28,6 +28,16 @@ + endef + TARGET_DEVICES += mikrotik_routerboard-921gs-5hpacd-15s + ++define Device/mikrotik_routerboard-921gs-5hpacd-19s ++ $(Device/mikrotik_nand) ++ SOC := qca9558 ++ DEVICE_MODEL := RouterBOARD 921GS-5HPacD-19s (mANTBox 19s) ++ DEVICE_PACKAGES += kmod-ath10k-ct ath10k-firmware-qca988x-ct kmod-i2c-gpio \ ++ kmod-sfp ++ SUPPORTED_DEVICES += rb-921gs-5hpacd-r2 ++endef ++TARGET_DEVICES += mikrotik_routerboard-921gs-5hpacd-19s ++ + define Device/mikrotik_routerboard-922uags-5hpacd + $(Device/mikrotik_nand) + SOC := qca9558 +--- /dev/null ++++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-19s.dts +@@ -0,0 +1,29 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++#include "qca9558_mikrotik_routerboard-92x.dtsi" ++ ++/ { ++ compatible = "mikrotik,routerboard-921gs-5hpacd-19s", "qca,qca9558"; ++ model = "MikroTik RouterBOARD 921GS-5HPacD-19s"; ++ ++ ath10k-leds { ++ compatible = "gpio-leds"; ++ ++ wlan5g { ++ label = "green:wlan5g"; ++ gpios = <&ath10k 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "phy0tpt"; ++ }; ++ }; ++}; ++ ++&pcie1 { ++ status = "okay"; ++ ++ ath10k: wifi@0,0 { ++ compatible = "qcom,ath10k"; ++ reg = <0 0 0 0 0>; ++ #gpio-cells = <2>; ++ gpio-controller; ++ }; ++}; +--- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -12,6 +12,7 @@ + "ath10k/cal-pci-0000:00:00.0.bin") + case $board in + mikrotik,routerboard-921gs-5hpacd-15s|\ ++ mikrotik,routerboard-921gs-5hpacd-19s|\ + mikrotik,routerboard-951ui-2nd|\ + mikrotik,routerboard-952ui-5ac2nd|\ + mikrotik,routerboard-962uigs-5hact2hnt|\ +--- a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh +@@ -34,6 +34,7 @@ + mikrotik,routerboard-493g|\ + mikrotik,routerboard-912uag-2hpnd|\ + mikrotik,routerboard-921gs-5hpacd-15s|\ ++ mikrotik,routerboard-921gs-5hpacd-19s|\ + mikrotik,routerboard-922uags-5hpacd|\ + mikrotik,routerboard-sxt-5nd-r2) + platform_do_upgrade_mikrotik_nand "$1" diff --git a/patches/748-powerbeam-m5-300-support.patch b/patches/748-powerbeam-m5-300-support.patch new file mode 100644 index 00000000..fa4c4872 --- /dev/null +++ b/patches/748-powerbeam-m5-300-support.patch @@ -0,0 +1,46 @@ +--- /dev/null ++++ b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-300.dts +@@ -0,0 +1,26 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++ ++#include "ar9342_ubnt_xw.dtsi" ++ ++/ { ++ compatible = "ubnt,powerbeam-m5-300", "ubnt,xw", "qca,ar9342"; ++ model = "Ubiquiti PowerBeam M5 300"; ++}; ++ ++&mdio0 { ++ status = "okay"; ++ ++ phy-mask = <0x1>; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ phy-mode = "mii"; ++ reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++ð0 { ++ status = "okay"; ++ ++ phy-handle = <&phy1>; ++}; +--- a/target/linux/ath79/image/generic-ubnt.mk ++++ b/target/linux/ath79/image/generic-ubnt.mk +@@ -157,6 +157,14 @@ + endef + TARGET_DEVICES += ubnt_powerbeam-m5-xw + ++define Device/ubnt_powerbeam-m5-300 ++ $(Device/ubnt-xw) ++ DEVICE_MODEL := PowerBeam M5 300 ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += loco-m-xw ++endef ++TARGET_DEVICES += ubnt_powerbeam-m5-300 ++ + define Device/ubnt_rocket-m-xw + $(Device/ubnt-xw) + DEVICE_MODEL := Rocket M XW diff --git a/patches/749-copy-tiny-nodes-to-generic.patch b/patches/749-copy-tiny-nodes-to-generic.patch new file mode 100644 index 00000000..cf62c892 --- /dev/null +++ b/patches/749-copy-tiny-nodes-to-generic.patch @@ -0,0 +1,128 @@ +# +# Migration our hardware from the ath79-tiny build as upgrades dont work in that mode :-( +# +--- a/target/linux/ath79/image/generic-ubnt.mk ++++ b/target/linux/ath79/image/generic-ubnt.mk +@@ -295,3 +295,85 @@ + SUPPORTED_DEVICES += uap-pro + endef + TARGET_DEVICES += ubnt_unifi-ap-pro ++ ++define Device/ubnt_airrouter ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := AirRouter ++ SUPPORTED_DEVICES += airrouter ++endef ++TARGET_DEVICES += ubnt_airrouter ++ ++define Device/ubnt_nanobridge-m ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := NanoBridge M ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += bullet-m ++endef ++TARGET_DEVICES += ubnt_nanobridge-m ++ ++define Device/ubnt_bullet-m-ar7240 ++ $(Device/ubnt-xm) ++ SOC := ar7240 ++ DEVICE_MODEL := Bullet M ++ DEVICE_VARIANT := XM (AR7240) ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += bullet-m ++endef ++TARGET_DEVICES += ubnt_bullet-m-ar7240 ++ ++define Device/ubnt_bullet-m-ar7241 ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := Bullet M ++ DEVICE_VARIANT := XM (AR7241) ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += bullet-m ubnt,bullet-m ++endef ++TARGET_DEVICES += ubnt_bullet-m-ar7241 ++ ++define Device/ubnt_picostation-m ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := Picostation M ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += bullet-m ++endef ++TARGET_DEVICES += ubnt_picostation-m ++ ++define Device/ubnt_nanostation-m ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := Nanostation M ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += nanostation-m ++endef ++TARGET_DEVICES += ubnt_nanostation-m ++ ++define Device/ubnt_nanostation-loco-m ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := Nanostation Loco M ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += bullet-m ++endef ++TARGET_DEVICES += ubnt_nanostation-loco-m ++ ++define Device/ubnt_powerbridge-m ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := PowerBridge M ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += bullet-m ++endef ++TARGET_DEVICES += ubnt_powerbridge-m ++ ++define Device/ubnt_rocket-m ++ $(Device/ubnt-xm) ++ SOC := ar7241 ++ DEVICE_MODEL := Rocket M ++ DEVICE_PACKAGES += rssileds ++ SUPPORTED_DEVICES += rocket-m ++endef ++TARGET_DEVICES += ubnt_rocket-m +--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network ++++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network +@@ -536,6 +536,19 @@ + ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" + ucidef_set_interface "wifi" device "wlan0" protocol "static" + ;; ++ ubnt,nanostation-m) ++ ucidef_set_interfaces_lan_wan "eth0 eth1" "eth0.1 eth1.1" ++ ucidef_set_interface "dtdlink" device "eth0.2 eth1.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ;; ++ ubnt,bullet-m-ar7241|\ ++ ubnt,nanobridge-m|\ ++ ubnt,rocket-m) ++ ucidef_set_interfaces_lan_wan "eth0" "eth0.1" ++ ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" ++ ucidef_set_interface "wifi" device "wlan0" protocol "static" ++ ;; ++ + *) + ucidef_set_interfaces_lan_wan "eth0" "eth0.1" + ucidef_set_interface "dtdlink" device "eth0.2" protocol "static" +--- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom ++++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +@@ -139,6 +139,12 @@ + caldata_extract "art" 0x1000 0x1000 + ath9k_patch_mac $(nvram get wl0_hwaddr) + ;; ++ ubnt,nanostation-m|\ ++ ubnt,bullet-m-ar7241|\ ++ ubnt,nanobridge-m|\ ++ ubnt,rocket-m) ++ caldata_extract "art" 0x1000 0x1000 ++ ;; + *) + caldata_die "board $board is not supported yet" + ;; diff --git a/patches/749-fix-tiny.patch b/patches/749-fix-tiny.patch new file mode 100644 index 00000000..dc369f85 --- /dev/null +++ b/patches/749-fix-tiny.patch @@ -0,0 +1,9 @@ +--- a/target/linux/ath79/tiny/config-default ++++ b/target/linux/ath79/tiny/config-default +@@ -1,5 +1,5 @@ + CONFIG_LEDS_RESET=y +-CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y ++CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=n + CONFIG_NET_DEVLINK=y + CONFIG_NET_DSA=y + CONFIG_NET_DSA_MV88E6060=y diff --git a/patches/series b/patches/series index a7084bf5..046c22d2 100644 --- a/patches/series +++ b/patches/series @@ -1,46 +1,37 @@ -001-add_support_for_GL-iNet_GL-AR150.patch -001-add_support_for_TP-Link_CPE610_v1.patch -001-add_support_for_TP-Link_CPE220_v3.patch -001-add_support_for_TP-Link_CPE510_v3.patch -001-add_support_for_TP-Link_CPE220_v2.patch -001-add_support_for_TP-Link_WBS510_v2.patch -001-add_support_for_TP-Link_ATH79_CPE510_v2_v3.patch -001-add_support_for_TP-Link_ATH79_CPE610_v1.patch -001-add_support_for_TP-Link_ATH79_CPE610_v2.patch -001-add_support_for_TP-Link_ATH79_CPE220_v2.patch -001-add_support_for_TP-Link_ATH79_CPE510_v1.patch -001-add_support_for_TP-Link_ATH79_CPE210_v1.patch -001-add_support_for_TP-Link_ATH79_WBS210_v1.patch -001-add_support_for_TP-Link_ATH79_WBS210_v2.patch -001-add_support_for_TP-Link_ATH79_WBS510_v1.patch -001-add_support_for_TP-Link_ATH79_WBS510_v2.patch -001-add_support_for_TP-Link_CPE510_v3.20.patch +0001-ath79-add-support-for-TP-Link-CPE605-v1.patch 001-ath79-cpe220v3-sysupgrade-supported.patch -001_cpe220v3_bugfix.patch -001-ath79-cpexxx_lna.patch -004-add-lhg-5hpnd-xl.patch -004-add-ldf-5nd.patch -005-add-haplite-new-model.patch -006-add-lhg-5hpnd.patch -007-fix-sysupgrade-fail.patch -008-add-lhg.patch -009-add-sxtsq.patch -700-cpe-diags.patch +001-ath79-reverse-wpad-basic-wolfssl.patch +006-rocket-m-flash-fix.patch 701-extended-spectrum.patch 702-enable-country-hx.patch 703-fix-dnsmasq.patch +703-disable-ipv6-dnsmasq.patch 704-enable-telnet.patch 705-aredn-banner.patch 706-MeshNode-SSID.patch -707-enable-board-name.patch -708-define-aredn-networks.patch -708-define-aredn-network-ath79.patch -708-define-aredn-leds-ar71xx.patch +708-define-aredn-ath79-networks.patch +708-define-aredn-rocket-m-networks.patch +708-define-aredn-ipq40xx-networks.patch 709-iperf-fw-restart.patch 710-no-ping6-traceroute6.patch -711-nano-xw-switch-config.patch +711-aredn-ports-dumbswitch-ar8216.patch 712-auto-distance-settings.patch -713-delay-snmpd-startup.patch 714-vtun-openssl-fix.patch +714-vtun-fix-cdefs.patch 715-set-min-free.patch 716-ubnt-pbe-100mb-port.patch +717-fix-olsrd-oparse-error.patch +718-temp-remove-olsrd-pud.patch +719-disable-ipv6.patch +720-curl-without-ssl.patch +730-ipq40xx-dsa.patch +731-ag71xx-updates-and-fixes.patch +742-5-and-10mhz-ath10k-ct-support.patch +743-mac80211-ath10k.patch +744-dd-wrt-firmware.patch +745-ath10k-more-scan-channels.patch +746-rocket-m-xw-support.patch +747-mikrotik-extra-support.patch +748-powerbeam-m5-300-support.patch +749-copy-tiny-nodes-to-generic.patch +749-fix-tiny.patch
Mesh RF (2GHz)
Mesh RF
Mesh RF
SSID-" .. wifi_chanbw .. "-v3
Channel  
Channel Width

DNS 2
 
  Tunnels are no longer supported on this hardware  
  Recommend not to use tunneling due to low memory on this node  
 
  Tunnels are no longer supported on this hardware  
  Recommend not to use tunneling due to low memory on this node