mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
ipq806x: add quantenna wireless firmware for E8350/R7500v1
This commit is contained in:
parent
cda8c08d33
commit
54d5790ab6
53
package/firmware/quantenna/BUGS.md
Normal file
53
package/firmware/quantenna/BUGS.md
Normal file
@ -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.
|
||||
|
155
package/firmware/quantenna/Makefile
Normal file
155
package/firmware/quantenna/Makefile
Normal file
@ -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 <bjorn@mork.no>
|
||||
|
||||
# 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))
|
||||
|
31
package/firmware/quantenna/files/lib/netifd/quantenna.sh
Normal file
31
package/firmware/quantenna/files/lib/netifd/quantenna.sh
Normal file
@ -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)
|
@ -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
|
39
package/firmware/quantenna/files/lib/wifi/quantenna.sh
Normal file
39
package/firmware/quantenna/files/lib/wifi/quantenna.sh
Normal file
@ -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
|
||||
}
|
16
package/firmware/quantenna/files/qtn-firmware.defaults
Normal file
16
package/firmware/quantenna/files/qtn-firmware.defaults
Normal file
@ -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 <<EOF
|
||||
set dhcp.qtn_rgmii=dnsmasq
|
||||
set dhcp.qtn_rgmii.enable_tftp=1
|
||||
set dhcp.qtn_rgmii.tftp_root=/lib/firmware/qtn
|
||||
set dhcp.qtn_rgmii.interface='qtn'
|
||||
set dhcp.qtn_rgmii.port=0
|
||||
commit dhcp
|
||||
EOF
|
37
package/firmware/quantenna/files/qtn-utils.init
Normal file
37
package/firmware/quantenna/files/qtn-utils.init
Normal file
@ -0,0 +1,37 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
NAME=qtn-utils
|
||||
# must start before networking
|
||||
START=19
|
||||
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
local ifname=$(uci get network.qtn.ifname)
|
||||
local ipaddr=$(uci get network.qtn.ipaddr)
|
||||
local hex_ip=$(printf "0x%02x%02x%02x%02x" $(echo $ipaddr | tr . \ ))
|
||||
|
||||
eval "$(ipcalc.sh $ipaddr $(uci get network.qtn.netmask) 2)"
|
||||
echo "$START" >/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
|
||||
|
||||
}
|
@ -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 $@
|
@ -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 <sys/types.h>
|
||||
#include <compat.h>
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/in6.h>
|
@ -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 <netdb.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <rpc/clnt.h>
|
||||
-#include <sys/poll.h>
|
||||
+#include <poll.h>
|
||||
#include <assert.h>
|
||||
#include <qcsapi_rpc_common/common/rpc_pci.h>
|
||||
|
20
package/firmware/quantenna/patches/004-include_string.patch
Normal file
20
package/firmware/quantenna/patches/004-include_string.patch
Normal file
@ -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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <qcsapi_rpc_common/common/rpc_raw.h>
|
||||
+#include <string.h>
|
||||
|
||||
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 <qcsapi_rpc_common/client/find_host_addr.h>
|
||||
#include <qcsapi_rpc/client/qcsapi_rpc_client.h>
|
||||
#include <qcsapi_rpc/generated/qcsapi_rpc.h>
|
||||
+#include <string.h>
|
||||
|
||||
static int client_qcsapi_get_udp_retry_timeout(int *argc, char ***argv)
|
||||
{
|
@ -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 <asm/byteorder.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/moduleparam.h>
|
||||
-#include <asm-generic/pci-dma-compat.h>
|
||||
+#include <linux/pci-dma-compat.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#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 <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
@@ -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);
|
Loading…
Reference in New Issue
Block a user