diff --git a/package/firmware/quantenna/BUGS.md b/package/firmware/quantenna/BUGS.md new file mode 100644 index 000000000..a8d50fc35 --- /dev/null +++ b/package/firmware/quantenna/BUGS.md @@ -0,0 +1,53 @@ +# Known Quantenna firmware bugs # + +This is an attempt to document Quantenna firmware bugs, explaining strange +implemtation details in this OpenWrt package and also hopefully helping +anyone else trying to get this mess to work... + +## Quantenna switch and VLANs ## + +Mapping WiFi VIFs to VLANs has a horrible side effect: Traffic from the +Quantenna SoC, like the RPC responses, is tagged with the last used VLAN. + +The tag depends on Wireless client activity! I.e it is unpredictable. + +And even if it were predictable: The module does not accept tagged RPC +calls or other management traffic. The RPC requests must be sent +untagged even if the module responds with an arbitrary tag... + +The switch state is not reset on either Quantenna module reboot by RPC +call, or reset by GPIO. The VLAN issue affects the bootloader, +making the module fail to load the second stage bootloader and OS over +tftp because of the VLAN tag mismatch. + +Full power cycling is necessary to reset the Quantenna switch to +non-tagging. There is no known software controllable reset method. + +### Workaround ### + +Playing with static and gratuitous ARPs, in combination with VLAN +interfaces accepting local traffic works pretty well. + +But this does not solve the reboot issue, caused by the switch bug +being persistent over reset. The two U-Boot stages will switch mac +addresses up to 3 times during module reboot. The final address is +often dynamically allocated, changing for each boot. This makes it +hard to manage a static ARP entry. + +Using "tc" to pop the VLAN tag of any tagged IP and ARP packets for +our management address works perfectly. + + +## Using bootloader environment ## + +The Quantenna bootloader environment is ignored by the firmware unless +/scripts/build_config contains STATELESS=Y. This is a build time +setting, which is not set by the Netgear firmware we use. + +The implications is that the module will use different mac adresses +etc compared to an OEM firmware with STATELESS=Y. + +This should not be considered a bug, but is an issue caused by our +choice of a common Quantenna firmware image for all hosts with such a +module. + diff --git a/package/firmware/quantenna/Makefile b/package/firmware/quantenna/Makefile new file mode 100644 index 000000000..0f798f6fc --- /dev/null +++ b/package/firmware/quantenna/Makefile @@ -0,0 +1,155 @@ +# +# Copyright (C) 2020 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=quantenna +PKG_VERSION:=37.3.2.44 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Bjørn Mork + +# available versions, ref https://kb.netgear.com/2649/NETGEAR-Open-Source-Code-for-Programmers-GPL +# qtn sdk v36.6.0.23: 1.0.0.46, +# qtn sdk v36.6.0.28: 1.0.0.52, +# qtn sdk v36.6.0.30: 1.0.0.68, 1.0.0.70, +# qtn sdk v36.7.3.23: 1.0.0.76, 1.0.0.82, +# qtn sdk v37.3.1.25: 1.0.0.94, 1.0.0.108, 1.0.0.110 , 1.0.0.112, 1.0.0.116, 1.0.0.122, +# qtn sdk v37.3.2.44: 1.0.0.124 + +NETGEAR_R7500V1_SRC-37.3.2.44=R7500-and_qtn_gpl_src_v1.0.0.124.tar.bz2.zip + +NETGEAR_R7500V1_HASH-37.3.2.44=6592e3286c66a8b0ba689e6cff2d10cac5aea3ddef8ca8746d7771319e47112e + +PKG_SOURCE:=$(NETGEAR_R7500V1_SRC-$(strip $(PKG_VERSION))) +PKG_SOURCE_URL:=https://www.downloads.netgear.com/files/GPL +PKG_HASH:=$(NETGEAR_R7500V1_HASH-$(strip $(PKG_VERSION))) + +QCSAPI_ARCHIVE-37.3.2.44=quantenna_gpl_v$(PKG_VERSION).tar.bz2 + +UNPACK_CMD-37.3.2.44=unzip -q -p $(DL_DIR)/$(PKG_SOURCE) | bzcat | $(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS) +UNPACK_CMD=$(UNPACK_CMD-$(strip $(PKG_VERSION))) + +PKG_BUILD_DEPENDS:=libtirpc + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define Build/Prepare + $(PKG_UNPACK) + bzcat $(PKG_BUILD_DIR)/$(QCSAPI_ARCHIVE-$(strip $(PKG_VERSION))) | \ + $(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS) --strip-components=1 \ + --wildcards */libqcsapi_client_src.zip --wildcards *drivers/pcie2* + bzcat $(PKG_BUILD_DIR)/R7500-*.tar.bz2 | \ + $(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS) --strip-components=4 \ + --wildcards */package/qt-wireless/binary/{topaz-linux.lzma.img,u-boot.bin} + unzip -q -d $(PKG_BUILD_DIR) $(PKG_BUILD_DIR)/libqcsapi_client_src.zip + # tunning to make the same patch apply to versions with or without -fstrict-aliasing + sed -i -e 's/ -fstrict-aliasing//' $(PKG_BUILD_DIR)/Makefile + $(Build/Patch) +endef + +define Package/qtn-utils + SECTION:=firmware + CATEGORY:=Firmware + TITLE:=Quantenna QV840 (QTS1000) Utilities + DEPENDS:=+libtirpc +tc +kmod-sched-act-vlan +endef + +define Package/qtn-utils/description + Management tools for Quantenna QV840 (QTS1000) WiFi modules +endef + +TARGET_CFLAGS += $(FPIC) -I$(STAGING_DIR)/usr/include/tirpc +TARGET_LDFLAGS += -ltirpc + +define Build/Compile + $(MAKE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) qcsapi_sockrpc +ifdef CONFIG_PACKAGE_kmod-qtn-pcie2 + $(call Build/Compile/qtn-pcie2) +endif +endef + +define Package/qtn-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) $(1)/etc/init.d + $(CP) $(PKG_BUILD_DIR)/libqcsapi_client.so* $(1)/usr/lib/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/qcsapi_sockrpc $(1)/usr/sbin/ + ln -s /tmp/qcsapi_target_ip.conf $(1)/etc + $(INSTALL_BIN) ./files/qtn-utils.init $(1)/etc/init.d/qtn-utils +endef + +define Package/qtn-firmware + SECTION:=firmware + CATEGORY:=Firmware + TITLE:=Quantenna QV840 (QTS1000) firmware + DEPENDS:=+dnsmasq +endef + +define Package/qtn-firmware/description + Firmware for Quantenna QV840 (QTS1000) WiFi modules +endef + +define Package/qtn-firmware/install + $(INSTALL_DIR) $(1)/lib/firmware/qtn + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/u-boot.bin \ + $(PKG_BUILD_DIR)/topaz-linux.lzma.img \ + $(1)/lib/firmware/qtn + ln -s u-boot.bin $(1)/lib/firmware/qtn/uboot_qsr1000.img + ln -s topaz-linux.lzma.img $(1)/lib/firmware/qtn/fmac_qsr1000.img + cd $(1)/lib/firmware && ln -s qtn/u-boot.bin . && ln -s qtn/topaz-linux.lzma.img . + $(INSTALL_BIN) ./files/qtn-firmware.defaults $(1)/etc/uci-defaults +endef + +define Package/qtn-proto + SECTION:=firmware + CATEGORY:=Firmware + TITLE:=Quantenna QV840 (QTS1000) netifd support + DEPENDS:=+qtn-utils +endef + +define Package/qtn-proto/install + echo "######################################### QTN-PROTO INSTALL #####################################" + $(INSTALL_DIR) $(1)/lib/wifi + $(INSTALL_DIR) $(1)/lib/netifd + $(INSTALL_DIR) $(1)/lib/netifd/wireless + $(INSTALL_BIN) ./files/lib/wifi/quantenna.sh $(1)/lib/wifi + $(INSTALL_BIN) ./files/lib/netifd/quantenna.sh $(1)/lib/netifd + $(INSTALL_BIN) ./files/lib/netifd/wireless/quantenna.sh $(1)/lib/netifd/wireless +endef + +define KernelPackage/qtn-pcie2 + SECTION:=kernel + SUBMENU:=Wireless Drivers + TITLE:=Quantenna QV840 (QTS1000) pcie2 driver + DEPENDS:=+qtn-utils + FILES:=$(PKG_BUILD_DIR)/drivers/pcie2/host/arm/qdpc-host.ko + AUTOLOAD:=$(call AutoProbe,qdpc-host) +endef + +define KernelPackage/qtn-pcie2/description + Quantenna QV840 (QTS1000) WiFi modules PCIE2 driver +endef + +define Build/Compile/qtn-pcie2 + echo "######################################### PCIE2 DRIVER BUILD #####################################" + cd $(PKG_BUILD_DIR)/drivers/pcie2/host/arm + +$(MAKE) $(CT_MAKEDEFS) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/drivers/pcie2/host/arm" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +$(eval $(call BuildPackage,qtn-utils)) +$(eval $(call BuildPackage,qtn-firmware)) +$(eval $(call BuildPackage,qtn-proto)) +$(eval $(call KernelPackage,qtn-pcie2)) + diff --git a/package/firmware/quantenna/files/lib/netifd/quantenna.sh b/package/firmware/quantenna/files/lib/netifd/quantenna.sh new file mode 100644 index 000000000..d66614f48 --- /dev/null +++ b/package/firmware/quantenna/files/lib/netifd/quantenna.sh @@ -0,0 +1,31 @@ +QUANTENNA_TARGET_IP="" +QUANTENNA_FW_VER="" +QUANTENNA_PRIMARY="" +quantenna_target_ip() { + echo "$QUANTENNA_TARGET_IP" +} + +quantenna_device() { + [ -n "$QUANTENNA_TARGET_IP" ] && ip route get "$QUANTENNA_TARGET_IP" 2>/dev/null | sed -e 's,.* dev ,,' -e 's, .*,,' | tr -d \\n +} + +quantenna_fw_ver() { + echo "$QUANTENNA_FW_VER" +} + +quantenna_api_ver() { + echo "$QUANTENNA_FW_VER" | cut -d. -f1 +} + +quantenna_primaryif() { + echo "$QUANTENNA_PRIMARY" +} + +quantenna_ifprefix() { + echo "${QUANTENNA_PRIMARY%0}" +} + +# This depends on a configured qtn-utils package +[ -z "$QUANTENNA_TARGET_IP" ] && [ -r "/etc/qcsapi_target_ip.conf" ] && [ -x "$(which qcsapi_sockrpc)" ] && QUANTENNA_TARGET_IP=$(cat /etc/qcsapi_target_ip.conf) +[ -n "$QUANTENNA_TARGET_IP" ] && [ -z "$QUANTENNA_FW_VER" ] && QUANTENNA_FW_VER=$(qcsapi_sockrpc get_firmware_version) +[ -n "$QUANTENNA_TARGET_IP" ] && [ -z "$QUANTENNA_PRIMARY" ] && QUANTENNA_PRIMARY=$(qcsapi_sockrpc get_primary_interface) diff --git a/package/firmware/quantenna/files/lib/netifd/wireless/quantenna.sh b/package/firmware/quantenna/files/lib/netifd/wireless/quantenna.sh new file mode 100644 index 000000000..15232c830 --- /dev/null +++ b/package/firmware/quantenna/files/lib/netifd/wireless/quantenna.sh @@ -0,0 +1,328 @@ +#!/bin/sh +. /lib/netifd/netifd-wireless.sh +. /lib/netifd/quantenna.sh + +init_wireless_driver "$@" + +# primarily to allow RPC API call debugging +quantenna_call() { + logger "Calling qcsapi_sockrpc" $* + qcsapi_sockrpc $* +} + +quantenna_rfenable() { + local enable=$1 + + # compat: fw v36 req "wifi0" arg, v37 (and later?) does not + case "$(quantenna_api_ver)" in + v36) + quantenna_call rfenable $(quantenna_primaryif) $enable + ;; + *) + quantenna_call rfenable $enable + ;; + esac +} + +quantenna_rfstatus() { + # compat: fw v36 req "wifi0" arg, v37 (and later?) does not + case "$(quantenna_api_ver)" in + v36) + quantenna_call rfstatus $(quantenna_primaryif) + ;; + *) + quantenna_call rfstatus + ;; + esac +} + +# mostly harmless if already done +quantenna_ready() { + [ -n "$(quantenna_ifprefix)" ] || return 1 + [ "$(quantenna_call startprod)" = "complete" ] || return 1 + [ "$(quantenna_call is_startprod_done)" = "1" ] || return 1 + [ "$(quantenna_rfstatus)" = "On" ] || [ "$(quantenna_rfenable 1)" = "complete" ] || return 1 + return 0 +} + +quantenna_set_security_mode() { + local ifname=$1 + [ "$(quantenna_call apply_security_config $ifname)" = "complete" ] || return 1 + return 0 +} + +quantenna_set_ssid_hidden() { + local ifname=$1 + local hidden=${2:-0} + local enable=1 + [ $hidden -gt 0 ] && enable=0 + [ "$(quantenna_call set_option $ifname SSID_broadcast $enable)" = "complete" ] || return 1 + return 0 +} + +quantenna_interface_enable() { + local ifname=$1 + local enable=${2:-0} + local updown=down + [ $enable -gt 0 ] && updown=up + + ip link set $ifname $updown + [ "$(quantenna_call enable_interface $ifname $enable)" = "complete" ] || return 1 + return 0 +} + +_ifname2vid() { + echo "$((${1#$(quantenna_ifprefix)}+10))" +} + +quantenna_interface_add() { + local ifname="$1" + local type="$2" + local phy="$3" + local vid=$(_ifname2vid $ifname) + + # maximum number of devs is 8 + [ $vid -lt 18 ] || return + + case "$type" in + ap) + [ "$ifname" = "$(quantenna_primaryif)" ] || [ "$(quantenna_call wifi_create_bss $ifname)" = "complete" ] || echo "failed to create $ifname" + quantenna_set_security_mode $ifname || return 1 + [ "$(quantenna_call set_pmf $ifname 0)" = "complete" ] || return 1 + ;; + *) + echo "$ifname: unsupported interface type '$type'" + return + ;; + esac + + # host local vlan dev + ip link add link $phy name $ifname type vlan id $vid + + # bind quantenna vif to vlan + [ "$(quantenna_call vlan_config $ifname enable $vid)" = "complete" ] || return 1 + [ "$(quantenna_call vlan_config $ifname bind $vid)" = "complete" ] || return 1 + + # disable interface until configured + quantenna_interface_enable $ifname 0 +} + +quantenna_interface_del() { + local ifname="$1" + local type="$2" + local vid=$(_ifname2vid $ifname) + + quantenna_call vlan_config $ifname unbind $vid + quantenna_call vlan_config $ifname disable $vid + quantenna_interface_enable $ifname 0 + + case "$type" in + ap) + [ "$ifname" = "$(quantenna_primaryif)" ] || quantenna_call wifi_remove_bss $ifname + ;; + *) + echo "$ifname: unsupported interface type '$type'" + return + ;; + esac + + ip link del $ifname +} + +quantenna_set_ssid() { + local ifname=$1 + local ssid=$2 + + quantenna_call set_SSID $ifname $ssid +} + +quantenna_set_macaddr() { + local ifname=$1 + local mac=$2 + + quantenna_call set_macaddr $ifname "$mac" +} + +quantenna_set_encr() { + local ifname=$1 + local encr=$2 + + quantenna_call set_WPA_encryption_modes $ifname "$encr" +} + +quantenna_set_auth() { + local ifname=$1 + local auth=$2 + + quantenna_call set_WPA_authentication_mode $ifname "$auth" +} + +quantenna_set_key() { + local ifname=$1 + local key=$2 + + quantenna_call set_passphrase $ifname 0 "$key" +} + +quantenna_set_beacon() { + local ifname=$1 + local type=$2 + + quantenna_call set_beacon $ifname "$type" +} + +# This will not work with hairpin_mode enabled +quantenna_fixup_vif() { + echo "quantenna_fixup_vif: $(json_dump)" + json_select data + json_get_vars ifname + json_select .. + [ -r "/sys/class/net/$ifname/brport/hairpin_mode" ] && echo 0 > "/sys/class/net/$ifname/brport/hairpin_mode" +} + +quantenna_setup_vif() { + local name="$1" + echo "quantenna_setup_vif: $(json_dump)" + + json_select config + json_get_vars mode ssid macaddr enable key hidden + json_select .. + +# FIXME - mac addresses for VAPs will be auto-generated by Quantenna firmware - we need only managed the first one... +# [ -n "$macaddr" ] || { +# macaddr="$(mac80211_generate_mac $phy)" +# macidx="$(($macidx + 1))" +# } + + if_idx=$((${if_idx:--1} + 1)) + local ifname="$(quantenna_ifprefix)${if_idx}" + set_default enable 1 + + json_add_object data + json_add_string ifname "$ifname" + json_close_object + + json_select config + wireless_vif_parse_encryption + json_select .. + + quantenna_interface_add "$ifname" "$mode" "$phy" || return + quantenna_set_ssid_hidden $ifname "$hidden" + + case "$auth_type" in + none) + quantenna_set_beacon $ifname Basic + ;; + psk) + quantenna_set_auth $ifname PSKAuthentication + ;; + *) + echo "unsupported auth_type: $auth_type" + ;; + esac + + case "$wpa_cipher" in + "TKIP") + quantenna_set_beacon $ifname WPA + quantenna_set_encr $ifname TKIPEncryption + ;; + "CCMP") + quantenna_set_beacon $ifname 11i + quantenna_set_encr $ifname AESEncryption + ;; + "CCMP TKIP") + quantenna_set_beacon $ifname WPAand11i + quantenna_set_encr $ifname TKIPandAESEncryption + ;; + *) + ;; + esac + + [ -n "$key" ] && quantenna_set_key $ifname "$key" + quantenna_set_ssid $ifname "$ssid" + [ -n "$macaddr" ] && quantenna_set_macaddr $ifname "$macaddr" + quantenna_interface_enable $ifname $enable + + wireless_add_vif "$name" "$ifname" +} + +quantenna_cleanup_vif() { + local name="$1" + + echo "quantenna_cleanup_vif ($name): $(json_dump)" + json_select config + json_get_vars mode + json_select .. + + json_select data + json_get_vars ifname + json_select .. + + quantenna_interface_del $ifname $mode +} + +# will be evaled after _wdev_common_device_config(), which adds +# config_add_string channel hwmode htmode noscan +drv_quantenna_init_device_config() { + config_add_string phy + config_add_int beacon_int + echo "drv_quantenna_init_device_config" +} + +# will be evaled after _wdev_common_iface_config(), which adds +# config_add_string mode ssid encryption 'key:wpakey' +drv_quantenna_init_iface_config() { + config_add_boolean enable hidden + echo "drv_quantenna_init_iface_config" +} + +drv_quantenna_setup() { + json_select config + echo "drv_quantenna_setup: $(json_dump)" + json_get_vars phy channel htmode beacon_int + json_select .. + + [ "$(quantenna_device)" = "$phy" ] || { + echo "Could not find PHY for device '$1'" + wireless_set_retry 0 + return 1 + } + + quantenna_ready || { + echo "Failed to connect to Quantenna module" + wireless_set_retry 1 + return 1 + } + + quantenna_call set_channel $(quantenna_primaryif) $channel + + case "$htmode" in + VHT20|HT20) + quantenna_call set_bw $(quantenna_primaryif) 20 + ;; + HT40*|VHT40) + quantenna_call set_bw $(quantenna_primaryif) 40 + ;; + VHT80) + quantenna_call set_bw $(quantenna_primaryif) 80 + ;; + *) + quantenna_call set_bw $(quantenna_primaryif) 40 + ;; + esac + + [ -n "beacon_int" ] && quantenna_call set_beacon_interval $(quantenna_primaryif) $beacon_int + + # FIMXE: support all modes: ap, sta, adhoc, wds, monitor, mesh + for_each_interface "ap" quantenna_setup_vif + wireless_set_up + for_each_interface "ap" quantenna_fixup_vif +} + +drv_quantenna_teardown() { + echo "$drv_quantenna_teardown: $(json_dump)" + for_each_interface "ap" quantenna_cleanup_vif + quantenna_rfenable 0 +} + +add_driver quantenna diff --git a/package/firmware/quantenna/files/lib/wifi/quantenna.sh b/package/firmware/quantenna/files/lib/wifi/quantenna.sh new file mode 100644 index 000000000..77d5024af --- /dev/null +++ b/package/firmware/quantenna/files/lib/wifi/quantenna.sh @@ -0,0 +1,39 @@ +#!/bin/sh +. /lib/netifd/quantenna.sh + +append DRIVERS "quantenna" + +detect_quantenna() { + devidx=0 + config_load wireless + while :; do + config_get type "radio$devidx" type + [ -n "$type" ] || break + # the qcsapi does not support more than one module in a system + [ "$type" = "quantenna" ] && return + devidx=$(($devidx + 1)) + done + + # find "all" - i.e. then single supported - Quantenna devices. + # there is no reliable way to do this, as it can be virtually + # any ethernet device + phy=$(quantenna_device) + [ -z "$phy" ] && return + + uci -q batch <<-EOF + set wireless.radio${devidx}=wifi-device + set wireless.radio${devidx}.type=quantenna + set wireless.radio${devidx}.channel=${channel:-36} + set wireless.radio${devidx}.hwmode=11ac + set wireless.radio${devidx}.phy=${phy} + set wireless.radio${devidx}.disabled=1 + + set wireless.default_radio${devidx}=wifi-iface + set wireless.default_radio${devidx}.device=radio${devidx} + set wireless.default_radio${devidx}.network=lan + set wireless.default_radio${devidx}.mode=ap + set wireless.default_radio${devidx}.ssid=OpenWrt + set wireless.default_radio${devidx}.encryption=none +EOF + uci -q commit wireless +} diff --git a/package/firmware/quantenna/files/qtn-firmware.defaults b/package/firmware/quantenna/files/qtn-firmware.defaults new file mode 100644 index 000000000..b9e78f45a --- /dev/null +++ b/package/firmware/quantenna/files/qtn-firmware.defaults @@ -0,0 +1,16 @@ +#!/bin/sh + +# no need for tftp service if the Quantenna module is PCIe connected +[ "$(basename "$(readlink /sys/class/net/$(uci -q get network.qtn.ifname)/device/driver)")" = "qtnfmac_pcie" ] && exit 0 + +uci -q get dhcp.qtn_rgmii >/dev/null && exit 0 +touch /etc/config/dhcp + +uci batch </tmp/qcsapi_target_ip.conf + + # work around Quatenna vlan bug - pop bogus tags from arp and ip packets for 1.1.1.1 + tc qdisc add dev $ifname handle ffff: ingress + tc filter add dev $ifname parent ffff: pref 1 \ + protocol 802.1q u32 \ + match u16 0x0806 0xffff at -2 \ + match u32 $hex_ip 0xffffffff at 24 \ + action vlan pop + tc filter add dev $ifname parent ffff: pref 2 \ + protocol 802.1q u32 \ + match u16 0x0800 0xffff at -2 \ + match u32 $hex_ip 0xffffffff at 16 \ + action vlan pop +} + +stop_service() { + local ifname=$(uci get network.qtn.ifname) + + tc filter del dev $ifname ingress + tc qdisc del dev $ifname ingress + +} diff --git a/package/firmware/quantenna/patches/001-link-with-rpc-makefile.patch b/package/firmware/quantenna/patches/001-link-with-rpc-makefile.patch new file mode 100644 index 000000000..3196f137c --- /dev/null +++ b/package/firmware/quantenna/patches/001-link-with-rpc-makefile.patch @@ -0,0 +1,40 @@ +--- a/Makefile 2019-06-24 17:38:56.000000000 +0200 ++++ b/Makefile 2019-06-24 17:39:04.000000000 +0200 +@@ -1,6 +1,5 @@ + +-CC = gcc +-CFLAGS = -I. -fPIC -O -g -Wall -Werror -Wno-unused-variable -Wno-unused-parameter ++CFLAGS += -I. + + COMMON_PROG_OBJS = \ + call_qcsapi.o \ +@@ -49,24 +48,25 @@ + LIB_LDNAME = lib$(LIB_NAME).so + LIB_SONAME = $(LIB_LDNAME).1 + LIB_REALNAME = $(LIB_LDNAME).1.0.1 ++LDFLAGS += -L. -l$(LIB_NAME) + + c_rpc_qcsapi_sample: ${SOCKET_C_SAMPLE_OBJS:%=build/%} $(LIB_REALNAME) +- ${CC} $(filter %.o, $^) -L. -l$(LIB_NAME) -o $@ ++ ${CC} $(filter %.o, $^) $(LDFLAGS) -o $@ + + qcsapi_pcie: ${PCIE_PROG_OBJS:%=build/%} $(LIB_REALNAME) +- ${CC} $(filter %.o, $^) -L. -l$(LIB_NAME) -o $@ ++ ${CC} $(filter %.o, $^) $(LDFLAGS) -o $@ + + qcsapi_pcie_static: ${PCIE_PROG_OBJS:%=build/%} ${LIB_OBJS} + ${CC} $(filter %.o, $^) -o $@ + + qcsapi_sockrpc: ${SOCKET_PROG_OBJS:%=build/%} $(LIB_REALNAME) +- ${CC} $(filter %.o, $^) -L. -l$(LIB_NAME) -o $@ ++ ${CC} $(filter %.o, $^) $(LDFLAGS) -o $@ + + qcsapi_sockrpc_static: ${SOCKET_PROG_OBJS:%=build/%} ${LIB_OBJS} + ${CC} $(filter %.o, $^) -o $@ + + qcsapi_sockraw: ${SOCKET_RAW_PROG_OBJS:%=build/%} $(LIB_REALNAME) +- ${CC} $(filter %.o, $^) -L. -l$(LIB_NAME) -o $@ ++ ${CC} $(filter %.o, $^) $(LDFLAGS) -o $@ + + qcsapi_sockraw_static: ${SOCKET_RAW_PROG_OBJS:%=build/%} ${LIB_OBJS} + ${CC} $(filter %.o, $^) -o $@ diff --git a/package/firmware/quantenna/patches/002-include_sys_types.patch b/package/firmware/quantenna/patches/002-include_sys_types.patch new file mode 100644 index 000000000..63aee9ca5 --- /dev/null +++ b/package/firmware/quantenna/patches/002-include_sys_types.patch @@ -0,0 +1,11 @@ +--- a/net80211/_ieee80211.h 2015-03-31 08:19:35.000000000 +0200 ++++ b/net80211/_ieee80211.h 2016-04-14 00:19:20.000000000 +0200 +@@ -33,7 +33,7 @@ + */ + #ifndef _NET80211__IEEE80211_H_ + #define _NET80211__IEEE80211_H_ +- ++#include + #include + #ifdef __KERNEL__ + #include diff --git a/package/firmware/quantenna/patches/003-fix_include_poll.patch b/package/firmware/quantenna/patches/003-fix_include_poll.patch new file mode 100644 index 000000000..caac04846 --- /dev/null +++ b/package/firmware/quantenna/patches/003-fix_include_poll.patch @@ -0,0 +1,11 @@ +--- a/qcsapi_rpc_common/client/rpc_pci_clnt.c 2015-03-31 07:49:58.000000000 +0200 ++++ b/qcsapi_rpc_common/client/rpc_pci_clnt.c 2016-04-14 00:23:46.000000000 +0200 +@@ -39,7 +39,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + diff --git a/package/firmware/quantenna/patches/004-include_string.patch b/package/firmware/quantenna/patches/004-include_string.patch new file mode 100644 index 000000000..45ca6e668 --- /dev/null +++ b/package/firmware/quantenna/patches/004-include_string.patch @@ -0,0 +1,20 @@ +--- a/qcsapi_rpc_common/common/rpc_raw.c 2015-03-31 07:49:58.000000000 +0200 ++++ b/qcsapi_rpc_common/common/rpc_raw.c 2016-04-14 00:25:02.000000000 +0200 +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + int qrpc_set_prot_filter(const int sock, const short prot) + { +--- a/qcsapi_rpc/client/socket/qcsapi_socket_rpc_client.c 2015-03-31 07:49:58.000000000 +0200 ++++ b/qcsapi_rpc/client/socket/qcsapi_socket_rpc_client.c 2016-04-14 00:21:38.000000000 +0200 +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + static int client_qcsapi_get_udp_retry_timeout(int *argc, char ***argv) + { diff --git a/package/firmware/quantenna/patches/050-quantenna-pcie2-k5.4.patch b/package/firmware/quantenna/patches/050-quantenna-pcie2-k5.4.patch new file mode 100644 index 000000000..57ffd2139 --- /dev/null +++ b/package/firmware/quantenna/patches/050-quantenna-pcie2-k5.4.patch @@ -0,0 +1,144 @@ +diff -Naur quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/qdpc_init.c quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/qdpc_init.c +--- quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/qdpc_init.c 2018-03-16 15:08:37.000000000 +0200 ++++ quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/qdpc_init.c 2020-08-02 08:47:22.352332685 +0300 +@@ -691,7 +691,7 @@ + + /* add code to reboot the while QCA system here*/ + printk("%s: Attempting to reboot QCA system.\n", __func__); +- machine_restart(NULL); ++ emergency_restart(); + break; + } + msleep(500); +diff -Naur quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/qdpc_init.h quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/qdpc_init.h +--- quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/qdpc_init.h 2018-03-16 15:08:37.000000000 +0200 ++++ quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/qdpc_init.h 2020-08-02 07:38:28.814212107 +0300 +@@ -42,6 +42,8 @@ + #define QDPC_ROW_INCR_OFFSET 0x04 + #undef QDPC_CS_DEBUG + ++#define mmiowb() do { } while (0) ++ + extern unsigned int (*qdpc_pci_readl)(void *addr); + extern void (*qdpc_pci_writel)(unsigned int val, void *addr); + +diff -Naur quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/qdpc_pcie.c quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/qdpc_pcie.c +--- quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/qdpc_pcie.c 2018-03-16 15:08:37.000000000 +0200 ++++ quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/qdpc_pcie.c 2020-08-02 07:42:31.174353547 +0300 +@@ -29,7 +29,7 @@ + #include + #include + #include +-#include ++#include + #include + + #include "qdpc_config.h" +diff -Naur quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/topaz_vnet.c quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/topaz_vnet.c +--- quantenna_gpl_v37.3.2.44/drivers/pcie2/host/common/topaz_vnet.c 2018-03-16 15:08:37.000000000 +0200 ++++ quantenna_gpl_v37.3.2.44-mod/drivers/pcie2/host/common/topaz_vnet.c 2020-08-05 10:40:48.405527180 +0300 +@@ -21,6 +21,8 @@ + #define EXPORT_SYMTAB + #endif + ++#define NET_NAME_USER 3 /* provided by user-space */ ++ + #include + #include + #include +@@ -50,13 +52,13 @@ + #include "qdpc_init.h" + #include "qdpc_debug.h" + #include "qdpc_regs.h" +-#include "nss_api_if.h" ++//#include "nss_api_if.h" + #include "qdpc_version.h" + + #define DRV_NAME "qdpc-host" + + #ifndef DRV_VERSION +-#define DRV_VERSION "1.0" ++#define DRV_VERSION "1.0-k5.4-openwrt-nonss-tc" + #endif + + #define DRV_AUTHOR "Quantenna Communications Inc." +@@ -73,8 +75,6 @@ + static int __sram_text skb2rbd_attach(struct net_device *ndev, uint16_t i, uint32_t wrap); + static irqreturn_t vmac_interrupt(int irq, void *dev_id); + static void vmac_tx_timeout(struct net_device *ndev); +-static int vmac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd); +-static int vmac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd); + static void vmac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info); + static void free_tx_skbs(struct vmac_priv *vmp); + static void init_tx_bd(struct vmac_priv *vmp); +@@ -824,7 +824,7 @@ + + dump_rx_bd(vmp); + +- ndev->last_rx = jiffies; ++ netif_trans_update(ndev); + + /* + * We are done with the current buffer attached to this descriptor, so attach a new +@@ -1180,7 +1180,7 @@ + inline static void vmac_tx_timeout(struct net_device *ndev) + { + printk(KERN_ERR "%s: vmac_tx_timeout: ndev=%p\n", ndev->name, ndev); +- ndev->trans_start = jiffies; ++ netif_trans_update(ndev); + } + + #ifdef RC_TXDONE_TIMER +@@ -1202,21 +1202,6 @@ + } + #endif + +-/* ethtools support */ +-static int vmac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +-{ +- return -EINVAL; +-} +- +-static int vmac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +-{ +- +- if (!capable(CAP_NET_ADMIN)) +- return -EPERM; +- +- return -EINVAL; +-} +- + static int vmac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) + { + return -EINVAL; +@@ -1233,13 +1218,6 @@ + info->regdump_len = 0; + } + +-static const struct ethtool_ops vmac_ethtool_ops = { +- .get_settings = vmac_get_settings, +- .set_settings = vmac_set_settings, +- .get_drvinfo = vmac_get_drvinfo, +- .get_link = ethtool_op_get_link, +-}; +- + static const struct net_device_ops vmac_device_ops = { + .ndo_open = vmac_open, + .ndo_stop = vmac_close, +@@ -1254,7 +1232,7 @@ + struct net_device * ndev; + + /* Allocate device structure */ +- ndev = alloc_netdev(sizeof(struct vmac_priv), vmaccfg.ifname, ether_setup); ++ ndev = alloc_netdev(sizeof(struct vmac_priv), vmaccfg.ifname, NET_NAME_USER ,ether_setup); + if(!ndev) + printk(KERN_ERR "%s: alloc_etherdev failed\n", vmaccfg.ifname); + +@@ -1297,7 +1275,6 @@ + + ndev->netdev_ops = &vmac_device_ops; + ndev->tx_queue_len = QTN_GLOBAL_INIT_EMAC_TX_QUEUE_LEN; +- SET_ETHTOOL_OPS(ndev, &vmac_ethtool_ops); + + /* Initialize private data */ + vmp = netdev_priv(ndev);