diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000000..fa04fd464a0d7 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,57 @@ +def axisTargets = ["x86_64","x86_geode","ar71xx_generic"] +def checkout_tasks = [:] +def build_tasks = [:] +def archive_tasks = [:] + +for(int i=0; i< axisTargets.size(); i++) { + def target = axisTargets[i] + def targets_split = target.tokenize( '_' ) + def maintarget = targets_split[0] + def subtarget = targets_split[1] + checkout_tasks["${target}"] = { + node { + ws("${env.JOB_NAME}-${target}") { + dir('firmware') { + checkout scm + } + } + } + } + build_tasks["${target}"] = { + node { + ws("${env.JOB_NAME}-${target}") { + dir('firmware') { + sh "./scripts/feeds update -a" + sh "./scripts/feeds install -a" + sh "./create_config.sh ${target}" + sh "make defconfig" + sh "make -j2 V=s" + } + } + } + } + archive_tasks["${target}"] = { + node { + ws("${env.JOB_NAME}-${target}") { + dir('firmware') { + archiveArtifacts artifacts: 'bin/targets/*/*/*', excludes: '' + } + } + } + } +} + +stage('Checkout') { + parallel checkout_tasks +} + +stage ("Build") { + parallel build_tasks +} + +stage ("Archive") { + parallel archive_tasks +} + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..da675a693d3b3 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# OpenC2X embedded + +To build the firmware: + +* Update the feeds: +``` +./scripts/feeds update -a +./scripts/feeds install -a +``` +* Create the configuration, allowed architectures are x86_64, x86_geode, ar71xx_generic: +``` +./create_config.sh x86_64 +make defconfig +``` +* Build +``` +make +``` diff --git a/configs/config.ar71xx_generic.default b/configs/config.ar71xx_generic.default new file mode 100644 index 0000000000000..6f133aa44e93a --- /dev/null +++ b/configs/config.ar71xx_generic.default @@ -0,0 +1,6 @@ +CONFIG_TARGET_ar71xx=y +CONFIG_TARGET_ar71xx_generic=y +CONFIG_TARGET_MULTI_PROFILE=y + +CONFIG_TARGET_DEVICE_ar71xx_generic_DEVICE_tl-wdr3600-v1=y +CONFIG_TARGET_DEVICE_PACKAGES_ar71xx_generic_DEVICE_tl-wdr3600-v1="" diff --git a/configs/config.default b/configs/config.default new file mode 100644 index 0000000000000..f2bc635ea4ecb --- /dev/null +++ b/configs/config.default @@ -0,0 +1,12 @@ +CONFIG_USE_LIBSTDCXX=y +CONFIG_DEFAULT_firewall=n +CONFIG_PACKAGE_firewall=n +CONFIG_PACKAGE_kmod-pcnet32=y +CONFIG_PACKAGE_uhttpd=y +CONFIG_PACKAGE_uhttpd-mod-ubus=y +CONFIG_PACKAGE_luci-mod-admin-full=y +CONFIG_PACKAGE_libiwinfo-lua=y +CONFIG_PACKAGE_luci-app-openc2x=y +CONFIG_PACKAGE_luci-theme-material=y +CONFIG_PACKAGE_openc2x=y +CONFIG_PACKAGE_kmod-usb-serial-ch341=y diff --git a/configs/config.x86_64.default b/configs/config.x86_64.default new file mode 100644 index 0000000000000..9ec7f36582d32 --- /dev/null +++ b/configs/config.x86_64.default @@ -0,0 +1,76 @@ +CONFIG_TARGET_x86=y +CONFIG_TARGET_x86_64=y +CONFIG_VDI_IMAGES=y +CONFIG_PACKAGE_kmod-pcnet32=y +CONFIG_PACKAGE_openssh-sftp-server=y + + +CONFIG_DEVEL=y +CONFIG_ATH9K_SUPPORT_PCOEM=y +CONFIG_ATH_USER_REGD=y +CONFIG_DRIVER_11N_SUPPORT=y +CONFIG_DRIVER_11W_SUPPORT=y +# CONFIG_IPV6 is not set +# CONFIG_KERNEL_IPV6 is not set +CONFIG_KERNEL_RELAY=y +CONFIG_PACKAGE_ATH_DEBUG=y +CONFIG_PACKAGE_ATH_DFS=y +CONFIG_PACKAGE_MAC80211_DEBUGFS=y +CONFIG_PACKAGE_MAC80211_MESH=y +CONFIG_PACKAGE_ath9k-htc-firmware=y +CONFIG_PACKAGE_boost=y +CONFIG_PACKAGE_boost-program_options=y +CONFIG_PACKAGE_gpsd=y +CONFIG_PACKAGE_gpslogger=y +CONFIG_PACKAGE_hostapd-common=y +CONFIG_PACKAGE_iperf=y +CONFIG_PACKAGE_iperf3=y +CONFIG_PACKAGE_iw=y +CONFIG_PACKAGE_kmod-ath=y +CONFIG_PACKAGE_kmod-ath5k=y +CONFIG_PACKAGE_kmod-ath9k=y +CONFIG_PACKAGE_kmod-ath9k-common=y +CONFIG_PACKAGE_kmod-ath9k-htc=y +CONFIG_PACKAGE_kmod-cfg80211=y +CONFIG_PACKAGE_kmod-hwmon-k10temp=y +CONFIG_PACKAGE_kmod-i2c-algo-bit=y +CONFIG_PACKAGE_kmod-i2c-core=y +CONFIG_PACKAGE_kmod-igb=y +CONFIG_PACKAGE_kmod-leds-apu2=y +CONFIG_PACKAGE_kmod-leds-gpio=y +CONFIG_PACKAGE_kmod-leds-pca963x=y +CONFIG_PACKAGE_kmod-ledtrig-default-on=y +CONFIG_PACKAGE_kmod-ledtrig-gpio=y +CONFIG_PACKAGE_kmod-ledtrig-heartbeat=y +CONFIG_PACKAGE_kmod-ledtrig-netdev=y +CONFIG_PACKAGE_kmod-ledtrig-oneshot=y +CONFIG_PACKAGE_kmod-ledtrig-timer=y +CONFIG_PACKAGE_kmod-ledtrig-transient=y +CONFIG_PACKAGE_kmod-mac80211=y +CONFIG_PACKAGE_kmod-nls-base=y +CONFIG_PACKAGE_kmod-scsi-core=y +CONFIG_PACKAGE_kmod-usb-acm=y +CONFIG_PACKAGE_kmod-usb-core=y +CONFIG_PACKAGE_kmod-usb-ohci=y +CONFIG_PACKAGE_kmod-usb-ohci-pci=y +CONFIG_PACKAGE_kmod-usb-serial=y +CONFIG_PACKAGE_kmod-usb-serial-cp210x=y +CONFIG_PACKAGE_kmod-usb-serial-ftdi=y +CONFIG_PACKAGE_kmod-usb-serial-pl2303=y +CONFIG_PACKAGE_kmod-usb-storage=y +CONFIG_PACKAGE_kmod-usb-storage-extras=y +CONFIG_PACKAGE_kmod-usb-uhci=y +CONFIG_PACKAGE_kmod-usb2=y +CONFIG_PACKAGE_kmod-usb3=y +CONFIG_PACKAGE_libcap=y +CONFIG_PACKAGE_libgps=y +CONFIG_PACKAGE_libncurses=y +CONFIG_PACKAGE_libpcap=y +CONFIG_PACKAGE_libprotobuf-c=y +CONFIG_PACKAGE_libstdcpp=y +CONFIG_PACKAGE_libsysfs=y +CONFIG_PACKAGE_libusb-1.0=y + +CONFIG_TARGET_INITRAMFS_COMPRESSION_NONE=y +CONFIG_TARGET_ROOTFS_INITRAMFS=y + diff --git a/configs/config.x86_geode.default b/configs/config.x86_geode.default new file mode 100644 index 0000000000000..7149cbfa69f95 --- /dev/null +++ b/configs/config.x86_geode.default @@ -0,0 +1,76 @@ +CONFIG_TARGET_x86=y +CONFIG_TARGET_x86_geode=y + +CONFIG_PACKAGE_kmod-pcnet32=y +CONFIG_PACKAGE_openssh-sftp-server=y + + +CONFIG_DEVEL=y +CONFIG_ATH9K_SUPPORT_PCOEM=y +CONFIG_ATH_USER_REGD=y +CONFIG_DRIVER_11N_SUPPORT=y +CONFIG_DRIVER_11W_SUPPORT=y +# CONFIG_IPV6 is not set +# CONFIG_KERNEL_IPV6 is not set +CONFIG_KERNEL_RELAY=y +CONFIG_PACKAGE_ATH_DEBUG=y +CONFIG_PACKAGE_ATH_DFS=y +CONFIG_PACKAGE_MAC80211_DEBUGFS=y +CONFIG_PACKAGE_MAC80211_MESH=y +CONFIG_PACKAGE_ath9k-htc-firmware=y +CONFIG_PACKAGE_boost=y +CONFIG_PACKAGE_boost-program_options=y +CONFIG_PACKAGE_gpsd=y +CONFIG_PACKAGE_gpslogger=y +CONFIG_PACKAGE_hostapd-common=y +CONFIG_PACKAGE_iperf=y +CONFIG_PACKAGE_iperf3=y +CONFIG_PACKAGE_iw=y +CONFIG_PACKAGE_kmod-ath=y +CONFIG_PACKAGE_kmod-ath5k=y +CONFIG_PACKAGE_kmod-ath9k=y +CONFIG_PACKAGE_kmod-ath9k-common=y +CONFIG_PACKAGE_kmod-ath9k-htc=y +CONFIG_PACKAGE_kmod-cfg80211=y +CONFIG_PACKAGE_kmod-hwmon-k10temp=y +CONFIG_PACKAGE_kmod-i2c-algo-bit=y +CONFIG_PACKAGE_kmod-i2c-core=y +CONFIG_PACKAGE_kmod-igb=y +CONFIG_PACKAGE_kmod-leds-apu2=y +CONFIG_PACKAGE_kmod-leds-gpio=y +CONFIG_PACKAGE_kmod-leds-pca963x=y +CONFIG_PACKAGE_kmod-ledtrig-default-on=y +CONFIG_PACKAGE_kmod-ledtrig-gpio=y +CONFIG_PACKAGE_kmod-ledtrig-heartbeat=y +CONFIG_PACKAGE_kmod-ledtrig-netdev=y +CONFIG_PACKAGE_kmod-ledtrig-oneshot=y +CONFIG_PACKAGE_kmod-ledtrig-timer=y +CONFIG_PACKAGE_kmod-ledtrig-transient=y +CONFIG_PACKAGE_kmod-mac80211=y +CONFIG_PACKAGE_kmod-nls-base=y +CONFIG_PACKAGE_kmod-scsi-core=y +CONFIG_PACKAGE_kmod-usb-acm=y +CONFIG_PACKAGE_kmod-usb-core=y +CONFIG_PACKAGE_kmod-usb-ohci=y +CONFIG_PACKAGE_kmod-usb-ohci-pci=y +CONFIG_PACKAGE_kmod-usb-serial=y +CONFIG_PACKAGE_kmod-usb-serial-cp210x=y +CONFIG_PACKAGE_kmod-usb-serial-ftdi=y +CONFIG_PACKAGE_kmod-usb-serial-pl2303=y +CONFIG_PACKAGE_kmod-usb-storage=y +CONFIG_PACKAGE_kmod-usb-storage-extras=y +CONFIG_PACKAGE_kmod-usb-uhci=y +CONFIG_PACKAGE_kmod-usb2=y +CONFIG_PACKAGE_kmod-usb3=y +CONFIG_PACKAGE_libcap=y +CONFIG_PACKAGE_libgps=y +CONFIG_PACKAGE_libncurses=y +CONFIG_PACKAGE_libpcap=y +CONFIG_PACKAGE_libprotobuf-c=y +CONFIG_PACKAGE_libstdcpp=y +CONFIG_PACKAGE_libsysfs=y +CONFIG_PACKAGE_libusb-1.0=y + +CONFIG_TARGET_INITRAMFS_COMPRESSION_NONE=y +CONFIG_TARGET_ROOTFS_INITRAMFS=y + diff --git a/create_config.sh b/create_config.sh new file mode 100755 index 0000000000000..8a9639480b082 --- /dev/null +++ b/create_config.sh @@ -0,0 +1,2 @@ +cp configs/config.$1.default .config +cat configs/config.default >> .config diff --git a/feeds.conf.default b/feeds.conf.default index d86737e9ce148..bd15405b08c47 100644 --- a/feeds.conf.default +++ b/feeds.conf.default @@ -2,3 +2,4 @@ src-git packages https://git.lede-project.org/feed/packages.git^cd5c448758f30868 src-git luci https://git.lede-project.org/project/luci.git^d3f0685d63c1291359dc5dd089c82fa1e150e0c6 src-git routing https://git.lede-project.org/feed/routing.git^d11075cd40a88602bf4ba2b275f72100ddcb4767 src-git telephony https://git.lede-project.org/feed/telephony.git^ac6415e61f147a6892fd2785337aec93ddc68fa9 +src-git openc2x https://github.com/florianklingler/OpenC2X-feed.git^61891151a8b7b162d0dc66dc3968fc5b98a97d34 diff --git a/package/kernel/mac80211/files/regdb.txt b/package/kernel/mac80211/files/regdb.txt index d583887602d2e..7583e0b44ee43 100644 --- a/package/kernel/mac80211/files/regdb.txt +++ b/package/kernel/mac80211/files/regdb.txt @@ -366,6 +366,8 @@ country DE: DFS-ETSI (5470 - 5725 @ 160), (500 mW), DFS # short range devices (ETSI EN 300 440-1) (5725 - 5875 @ 80), (25 mW) + # ITS (802.11p) + (5850 - 5925 @ 20), (33) # 60 GHz band channels 1-4 (ETSI EN 302 567) (57000 - 66000 @ 2160), (40) diff --git a/package/kernel/mac80211/patches/998-ath5k_ocb.patch b/package/kernel/mac80211/patches/998-ath5k_ocb.patch new file mode 100644 index 0000000000000..3c55ff821232a --- /dev/null +++ b/package/kernel/mac80211/patches/998-ath5k_ocb.patch @@ -0,0 +1,174 @@ +Author: Florian Klingler +Date: Thu Mar 30 16:32:13 2017 +0200 + + OCB Mode for ath5k - initial version + +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -287,6 +287,8 @@ static bool ath5k_is_standard_channel(short chan, enum nl80211_band band) + ((chan & 3) == 1 && chan >= 149 && chan <= 165) || + /* 802.11j 5.030-5.080 GHz (20MHz) */ + (chan == 8 || chan == 12 || chan == 16) || ++ /* 802.11p (10MHz) */ ++ (chan == 172) || (chan == 174) || (chan == 176) || (chan == 178) || (chan == 180) || (chan == 182) || (chan == 184) || + /* 802.11j 4.9GHz (20MHz) */ + (chan == 184 || chan == 188 || chan == 192 || chan == 196)); + } +@@ -1065,6 +1067,13 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) + qi.tqi_aifs = 0; + qi.tqi_cw_min = 0; + qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN; ++ } else if (ah->opmode == NL80211_IFTYPE_OCB) { ++ /* ++ * Adhoc mode; backoff between 0 and (2 * cw_min). ++ */ ++ qi.tqi_aifs = 0; ++ qi.tqi_cw_min = 0; ++ qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN; + } + + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, +@@ -1433,7 +1442,7 @@ static int ath5k_remove_padding(struct sk_buff *skb) + ewma_beacon_rssi_add(&ah->ah_beacon_rssi_avg, rs->rs_rssi); + + /* check beacons in IBSS mode */ +- if (ah->opmode == NL80211_IFTYPE_ADHOC) ++ if (ah->opmode == NL80211_IFTYPE_ADHOC || ah->opmode == NL80211_IFTYPE_OCB) + ath5k_check_ibss_tsf(ah, skb, rxs); + } + +@@ -1834,7 +1843,7 @@ static int ath5k_remove_padding(struct sk_buff *skb) + antenna = ah->ah_tx_ant; + + flags = AR5K_TXDESC_NOACK; +- if (ah->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { ++ if ((ah->opmode == NL80211_IFTYPE_ADHOC || ah->opmode == NL80211_IFTYPE_OCB) && ath5k_hw_hasveol(ah)) { + ds->ds_link = bf->daddr; /* self-linked */ + flags |= AR5K_TXDESC_VEOL; + } else +@@ -2164,7 +2173,7 @@ static int ath5k_remove_padding(struct sk_buff *skb) + + ah->imask |= AR5K_INT_SWBA; + +- if (ah->opmode == NL80211_IFTYPE_ADHOC) { ++ if (ah->opmode == NL80211_IFTYPE_ADHOC || ah->opmode == NL80211_IFTYPE_OCB) { + if (ath5k_hw_hasveol(ah)) + ath5k_beacon_send(ah); + } else +@@ -2190,7 +2199,7 @@ static void ath5k_tasklet_beacon(unsigned long data) + * transmission time) in order to detect whether + * automatic TSF updates happened. + */ +- if (ah->opmode == NL80211_IFTYPE_ADHOC) { ++ if (ah->opmode == NL80211_IFTYPE_ADHOC || ah->opmode == NL80211_IFTYPE_OCB) { + /* XXX: only if VEOL supported */ + u64 tsf = ath5k_hw_get_tsf64(ah); + ah->nexttbtt += ah->bintval; +@@ -2548,7 +2557,8 @@ static void ath5k_tasklet_beacon(unsigned long data) + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | +- BIT(NL80211_IFTYPE_MESH_POINT); ++ BIT(NL80211_IFTYPE_MESH_POINT) | ++ BIT(NL80211_IFTYPE_OCB); + + hw->wiphy->iface_combinations = &if_comb; + hw->wiphy->n_iface_combinations = 1; + +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -80,7 +80,8 @@ + mutex_lock(&ah->lock); + + if ((vif->type == NL80211_IFTYPE_AP || +- vif->type == NL80211_IFTYPE_ADHOC) ++ vif->type == NL80211_IFTYPE_ADHOC || ++ vif->type == NL80211_IFTYPE_OCB) + && (ah->num_ap_vifs + ah->num_adhoc_vifs) >= ATH_BCBUF) { + ret = -ELNRNG; + goto end; +@@ -103,6 +105,7 @@ + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: ++ case NL80211_IFTYPE_OCB: + avf->opmode = vif->type; + break; + default: +@@ -116,7 +119,8 @@ + /* Assign the vap/adhoc to a beacon xmit slot. */ + if ((avf->opmode == NL80211_IFTYPE_AP) || + (avf->opmode == NL80211_IFTYPE_ADHOC) || +- (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { ++ (avf->opmode == NL80211_IFTYPE_MESH_POINT) || ++ (avf->opmode == NL80211_IFTYPE_OCB)) { + int slot; + + WARN_ON(list_empty(&ah->bcbuf)); +@@ -139,6 +143,8 @@ + ah->num_adhoc_vifs++; + else if (avf->opmode == NL80211_IFTYPE_MESH_POINT) + ah->num_mesh_vifs++; ++ else if (avf->opmode == NL80211_IFTYPE_OCB) ++ ah->num_mesh_vifs++; + } + + /* Any MAC address is fine, all others are included through the +@@ -182,6 +188,8 @@ + ah->num_adhoc_vifs--; + else if (avf->opmode == NL80211_IFTYPE_MESH_POINT) + ah->num_mesh_vifs--; ++ else if (avf->opmode == NL80211_IFTYPE_OCB) ++ ah->num_mesh_vifs--; + + ath5k_update_bssid_mask_and_opmode(ah, NULL); + mutex_unlock(&ah->lock); +@@ -431,6 +439,10 @@ + rfilt |= AR5K_RX_FILTER_PROBEREQ | + AR5K_RX_FILTER_BEACON; + break; ++ case NL80211_IFTYPE_OCB: ++ rfilt |= AR5K_RX_FILTER_PROBEREQ | ++ AR5K_RX_FILTER_BEACON; ++ break; + case NL80211_IFTYPE_STATION: + if (ah->assoc) + rfilt |= AR5K_RX_FILTER_BEACON; +@@ -638,7 +650,7 @@ + * in IBSS mode we need to update the beacon timers too. + * this will also reset the TSF if we call it with 0 + */ +- if (ah->opmode == NL80211_IFTYPE_ADHOC) ++ if (ah->opmode == NL80211_IFTYPE_ADHOC || ah->opmode == NL80211_IFTYPE_OCB) + ath5k_beacon_update_timers(ah, 0); + else + ath5k_hw_reset_tsf(ah); + +--- a/drivers/net/wireless/ath/ath5k/pcu.c ++++ b/drivers/net/wireless/ath/ath5k/pcu.c +@@ -670,6 +670,8 @@ + break; + case NL80211_IFTYPE_ADHOC: + AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); ++ case NL80211_IFTYPE_OCB: ++ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); + default: + /* On non-STA modes timer1 is used as next DMA + * beacon alert (DBA) timer and timer2 as next +@@ -898,6 +900,15 @@ + AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + ++ case NL80211_IFTYPE_OCB: ++ pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; ++ beacon_reg |= AR5K_BCR_ADHOC; ++ if (ah->ah_version == AR5K_AR5210) ++ pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; ++ else ++ AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); ++ break; ++ + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; + diff --git a/package/kernel/mac80211/patches/998-ath9k_allow_11p.patch b/package/kernel/mac80211/patches/998-ath9k_allow_11p.patch new file mode 100644 index 0000000000000..16e1d863fb5f7 --- /dev/null +++ b/package/kernel/mac80211/patches/998-ath9k_allow_11p.patch @@ -0,0 +1,74 @@ +From: Florian Klingler +Date: Wed Mar 15 17:50:09 2017 +0100 + +Subject: ath9k: allow IEEE 802.11p channels (5.9 GHz) + +--- a/drivers/net/wireless/ath/ath9k/common-init.c ++++ b/drivers/net/wireless/ath/ath9k/common-init.c +@@ -86,6 +86,26 @@ static const struct ieee80211_channel ath9k_5ghz_chantable[] = { + CHAN5G(5785, 35), /* Channel 157 */ + CHAN5G(5805, 36), /* Channel 161 */ + CHAN5G(5825, 37), /* Channel 165 */ ++ ++ CHAN5G(5850, 38), /* Channel 170 */ ++ /* ITA-G5B */ ++ CHAN5G(5855, 39), /* Channel 171 */ ++ CHAN5G(5860, 40), /* Channel 172 */ ++ CHAN5G(5865, 41), /* Channel 173 */ ++ CHAN5G(5870, 42), /* Channel 174 */ ++ /* ITS-G5A */ ++ CHAN5G(5875, 43), /* Channel 175 */ ++ CHAN5G(5880, 44), /* Channel 176 */ ++ CHAN5G(5885, 45), /* Channel 177 */ ++ CHAN5G(5890, 46), /* Channel 178 */ ++ CHAN5G(5895, 47), /* Channel 179 */ ++ CHAN5G(5900, 48), /* Channel 180 */ ++ CHAN5G(5905, 49), /* Channel 181 */ ++ /* ITS-G5D */ ++ CHAN5G(5910, 50), /* Channel 182 */ ++ CHAN5G(5915, 51), /* Channel 183 */ ++ CHAN5G(5920, 52), /* Channel 184 */ ++ CHAN5G(5925, 53), /* Channel 185 */ + }; + + /* Atheros hardware rate code addition for short premble */ +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -74,7 +74,7 @@ + + #define ATH9K_RSSI_BAD -128 + +-#define ATH9K_NUM_CHANNELS 38 ++#define ATH9K_NUM_CHANNELS 54 + + /* Register read/write primitives */ + #define REG_WRITE(_ah, _reg, _val) \ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -46,9 +46,9 @@ static int __ath_regd_init(struct ath_regulatory *reg); + #define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ + REG_RULE(5260-10, 5350+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) +-#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ ++#define ATH9K_5GHZ_5470_5925 REG_RULE(5470-10, 5925+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) +-#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ ++#define ATH9K_5GHZ_5725_5925 REG_RULE(5725-10, 5925+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) + + #define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ +@@ -56,11 +56,11 @@ static int __ath_regd_init(struct ath_regulatory *reg); + ATH9K_2GHZ_CH14 + + #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ +- ATH9K_5GHZ_5470_5850 ++ ATH9K_5GHZ_5470_5925 + + /* This one skips what we call "mid band" */ + #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ +- ATH9K_5GHZ_5725_5850 ++ ATH9K_5GHZ_5725_5925 + + #define REGD_RULES(...) \ + .reg_rules = { __VA_ARGS__ }, \ + diff --git a/package/kernel/mac80211/patches/999-Enable-queueing-in-all-4-ACs-BE-BK-VI-VO.patch b/package/kernel/mac80211/patches/999-Enable-queueing-in-all-4-ACs-BE-BK-VI-VO.patch new file mode 100644 index 0000000000000..c3a8b4db92b32 --- /dev/null +++ b/package/kernel/mac80211/patches/999-Enable-queueing-in-all-4-ACs-BE-BK-VI-VO.patch @@ -0,0 +1,30 @@ +From 1206412b9915c9d895d855c42b5f8c84ebd0b896 Mon Sep 17 00:00:00 2001 +From: "Gurjashan S. Pannu" +Date: Wed, 27 Jul 2016 14:20:08 +0200 +Subject: [PATCH 1/2] Enable queueing in all 4 ACs BE, BK, VI, VO + +--- + net/mac80211/wme.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c +index 9eb0aee..b91b7ee 100644 +--- a/net/mac80211/wme.c ++++ b/net/mac80211/wme.c +@@ -214,9 +214,10 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + + /* use the data classifier to determine what 802.1d tag the + * data frame has */ +- qos_map = rcu_dereference(sdata->qos_map); +- skb->priority = cfg80211_classify8021d(skb, qos_map ? +- &qos_map->qos_map : NULL); ++// Quick workaround to enable queueing in different AC (BE, BK, VO, VI) ++// qos_map = rcu_dereference(sdata->qos_map); ++// skb->priority = cfg80211_classify8021d(skb, qos_map ? ++// &qos_map->qos_map : NULL); + + downgrade: + ret = ieee80211_downgrade_queue(sdata, sta, skb); +-- +2.7.4 + diff --git a/package/kernel/mac80211/patches/999-Get-hw-queue-pending-stats-from-ath9k-via-netlink.patch b/package/kernel/mac80211/patches/999-Get-hw-queue-pending-stats-from-ath9k-via-netlink.patch new file mode 100644 index 0000000000000..049a7085623b3 --- /dev/null +++ b/package/kernel/mac80211/patches/999-Get-hw-queue-pending-stats-from-ath9k-via-netlink.patch @@ -0,0 +1,447 @@ +From 8cb405acaadc244925c10e753dfa84d986dc7d52 Mon Sep 17 00:00:00 2001 +From: "Gurjashan S. Pannu" +Date: Wed, 27 Jul 2016 14:23:38 +0200 +Subject: [PATCH 2/2] Get hw queue pending stats from ath9k via netlink + +--- + drivers/net/wireless/ath/ath9k/ath9k.h | 3 ++ + drivers/net/wireless/ath/ath9k/debug.c | 53 ++++++++++---------- + drivers/net/wireless/ath/ath9k/debug.h | 4 ++ + drivers/net/wireless/ath/ath9k/main.c | 24 +++++++++ + drivers/net/wireless/ath/ath9k/xmit.c | 12 +++++ + include/net/cfg80211.h | 27 ++++++++++ + include/net/mac80211.h | 2 + + include/uapi/linux/nl80211.h | 21 ++++++++ + net/mac80211/cfg.c | 9 ++++ + net/mac80211/driver-ops.h | 9 ++++ + net/wireless/nl80211.c | 90 ++++++++++++++++++++++++++++++++++ + net/wireless/rdev-ops.h | 9 ++++ + 12 files changed, 238 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h +index 981ca7c..e6f096b 100644 +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -962,6 +962,8 @@ struct ath_softc { + struct survey_info *cur_survey; + struct survey_info survey[ATH9K_NUM_CHANNELS]; + ++ struct flush_info hw_q_flush_info; ++ u32 flush_hw_q_pending; + spinlock_t intr_lock; + struct tasklet_struct intr_tq; + struct tasklet_struct bcon_tasklet; + struct ath_hw *sc_ah; + +diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c +index b037762..60d7281 100644 +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -593,7 +593,7 @@ + struct ieee80211_hw *hw = dev_get_drvdata(file->private); + struct ath_softc *sc = hw->priv; + +- seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); ++ seq_printf(file, "%38s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); + + PR("MPDUs Queued: ", queued); + PR("MPDUs Completed: ", completed); +@@ -616,6 +616,8 @@ + PR("HW-tx-start: ", txstart); + PR("HW-tx-proc-desc: ", txprocdesc); + PR("TX-Failed: ", txfailed); ++ PR("HW-flush-required: ", hw_flush_required); ++ PR("HW-flush-not-required: ", hw_flush_not_required); + + return 0; + } +@@ -1603,6 +1605,9 @@ + + debugfs_create_u16("airtime_flags", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, &sc->airtime_flags); ++ ++ debugfs_create_u32("flush_hw_q_pending", S_IRUGO | S_IWUGO, ++ sc->debug.debugfs_phy, &sc->flush_hw_q_pending); + + return 0; + } + +diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h +index a8e9319..40f5646 100644 +--- a/drivers/net/wireless/ath/ath9k/debug.h ++++ b/drivers/net/wireless/ath/ath9k/debug.h +@@ -163,6 +163,8 @@ struct ath_interrupt_stats { + * @txstart: Number of times hardware was told to start tx. + * @txprocdesc: Number of times tx descriptor was processed + * @txfailed: Out-of-memory or other errors in xmit path. ++ * @hw_flush_required: Number of times the hardware queue needs to be flushed. ++ * @hw_flush_not_required: Number of times the hardware queue was found empty before pushing new packets to it. + */ + struct ath_tx_stats { + u32 tx_pkts_all; +@@ -187,6 +189,8 @@ struct ath_tx_stats { + u32 txstart; + u32 txprocdesc; + u32 txfailed; ++ u32 hw_flush_required; ++ u32 hw_flush_not_required; + }; + + /* +diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c +index 9dd09e7..3726aaf 100644 +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -1927,6 +1927,29 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, + return 0; + } + ++static int ath9k_get_flush_stats(struct ieee80211_hw *hw, int idx, ++ struct flush_info *survey) ++{ ++ printk(KERN_ALERT "%s:%d\n", __FILE__, __LINE__); ++ struct ath_softc *sc = hw->priv; ++ ++ if (config_enabled(CONFIG_ATH9K_TX99)) ++ return -EOPNOTSUPP; ++ survey->be_flush_req = sc->debug.stats.txstats[ATH_TXQ_AC_BE].hw_flush_required; ++ survey->be_flush_not_req = sc->debug.stats.txstats[ATH_TXQ_AC_BE].hw_flush_not_required; ++ ++ survey->bk_flush_req = sc->debug.stats.txstats[ATH_TXQ_AC_BK].hw_flush_required; ++ survey->bk_flush_not_req = sc->debug.stats.txstats[ATH_TXQ_AC_BK].hw_flush_not_required; ++ ++ survey->vi_flush_req = sc->debug.stats.txstats[ATH_TXQ_AC_VI].hw_flush_required; ++ survey->vi_flush_not_req = sc->debug.stats.txstats[ATH_TXQ_AC_VI].hw_flush_not_required; ++ ++ survey->vo_flush_req = sc->debug.stats.txstats[ATH_TXQ_AC_VO].hw_flush_required; ++ survey->vo_flush_not_req = sc->debug.stats.txstats[ATH_TXQ_AC_VO].hw_flush_not_required; ++ ++ return 0; ++} ++ + static void ath9k_enable_dynack(struct ath_softc *sc) + { + #ifdef CONFIG_ATH9K_DYNACK +@@ -2611,6 +2634,7 @@ struct ieee80211_ops ath9k_ops = { + .reset_tsf = ath9k_reset_tsf, + .ampdu_action = ath9k_ampdu_action, + .get_survey = ath9k_get_survey, ++ .get_flush_stats = ath9k_get_flush_stats, + .rfkill_poll = ath9k_rfkill_poll_state, + .set_coverage_class = ath9k_set_coverage_class, + .flush = ath9k_flush, +diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c +index e9bd02c..1e4c7d6 100644 +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -1985,6 +1985,17 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, + if (list_empty(head)) + return; + ++ if (sc->flush_hw_q_pending) { ++ if (ath9k_hw_numtxpending(ah, txq->axq_qnum)) { ++ // printk(KERN_ALERT "flush and pending!"); ++ TX_STAT_INC(txq->axq_qnum, hw_flush_required); ++ ++ } else { ++ // printk(KERN_ALERT "flush but nothing pending in queues!"); ++ TX_STAT_INC(txq->axq_qnum, hw_flush_not_required); ++ } ++ } ++ + edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); + bf = list_first_entry(head, struct ath_buf, list); + bf_last = list_entry(head->prev, struct ath_buf, list); +@@ -2802,6 +2813,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + error = ath_tx_edma_init(sc); ++ sc->flush_hw_q_pending = 0; + + return error; + } +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 4ebb816..706a4f2 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -569,6 +569,30 @@ struct survey_info { + }; + + /** ++ * struct flush_info - stats for flushing pending packets in hardware queues ++ * ++ * @be_flush_req: number of times when there was need to flush a pending packet for AC_BE ++ * @be_flush_not_req: number of times when there was no pending packet in AC_BE ++ * @bk_flush_req: number of times when there was need to flush a pending packet for AC_BK ++ * @bk_flush_not_req: number of times when there was no pending packet in AC_BK ++ * @vi_flush_req: number of times when there was need to flush a pending packet for AC_VI ++ * @vi_flush_not_req: number of times when there was no pending packet in AC_VI ++ * @vo_flush_req: number of times when there was need to flush a pending packet for AC_VO ++ * @vo_flush_not_req: number of times when there was no pending packet in AC_VO ++ */ ++struct flush_info { ++ u32 be_flush_req; ++ u32 be_flush_not_req; ++ u32 bk_flush_req; ++ u32 bk_flush_not_req; ++ u32 vi_flush_req; ++ u32 vi_flush_not_req; ++ u32 vo_flush_req; ++ u32 vo_flush_not_req; ++}; ++ ++ ++/** + * struct cfg80211_crypto_settings - Crypto settings + * @wpa_versions: indicates which, if any, WPA versions are enabled + * (from enum nl80211_wpa_versions) +@@ -2581,6 +2605,9 @@ struct cfg80211_ops { + int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev, + int idx, struct survey_info *info); + ++ int (*dump_flush_stats)(struct wiphy *wiphy, struct net_device *netdev, ++ int idx, struct flush_info *info); ++ + int (*set_pmksa)(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa); + int (*del_pmksa)(struct wiphy *wiphy, struct net_device *netdev, +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 58d719d..d1a30c4 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3077,6 +3077,8 @@ struct ieee80211_ops { + u8 buf_size); + int (*get_survey)(struct ieee80211_hw *hw, int idx, + struct survey_info *survey); ++ int (*get_flush_stats)(struct ieee80211_hw *hw, int idx, ++ struct flush_info *survey); + void (*rfkill_poll)(struct ieee80211_hw *hw); + void (*set_coverage_class)(struct ieee80211_hw *hw, s16 coverage_class); + #ifdef CONFIG_NL80211_TESTMODE +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index b37bd5a..1dcaa32 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -958,6 +958,9 @@ enum nl80211_commands { + NL80211_CMD_TDLS_CHANNEL_SWITCH, + NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, + ++ NL80211_CMD_FLUSH_STATS, // Related to flushing hardware queues ++ NL80211_CMD_NEW_FLUSH_STATS, ++ + /* add new commands above here */ + + /* used to define NL80211_CMD_MAX below */ +@@ -2045,6 +2048,8 @@ enum nl80211_attrs { + + NL80211_ATTR_MAC_MASK, + ++ NL80211_ATTR_FLUSH_INFO, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -2802,6 +2807,22 @@ enum nl80211_survey_info { + NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 + }; + ++enum nl80211_flush_info { ++ __NL80211_FLUSH_INFO_INVALID, ++ NL80211_FLUSH_REQ_BE, ++ NL80211_FLUSH_NOT_REQ_BE, ++ NL80211_FLUSH_REQ_BK, ++ NL80211_FLUSH_NOT_REQ_BK, ++ NL80211_FLUSH_REQ_VI, ++ NL80211_FLUSH_NOT_REQ_VI, ++ NL80211_FLUSH_REQ_VO, ++ NL80211_FLUSH_NOT_REQ_VO, ++ ++ /* keep last */ ++ __NL80211_FLUSH_INFO_AFTER_LAST, ++ NL80211_FLUSH_INFO_MAX = __NL80211_FLUSH_INFO_AFTER_LAST - 1 ++}; ++ + /** + * enum nl80211_mntr_flags - monitor configuration flags + * +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index e75d5c5..cb3f9e0 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -664,6 +664,16 @@ + return drv_get_survey(local, idx, survey); + } + ++static int ieee80211_dump_flush_stats(struct wiphy *wiphy, struct net_device *dev, ++ int idx, struct flush_info *survey) ++{ ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); ++ ++ return drv_get_flush_stats(local, idx, survey); ++} ++ ++ ++ + static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac, struct station_info *sinfo) + { +@@ -3606,6 +3616,7 @@ + .get_station = ieee80211_get_station, + .dump_station = ieee80211_dump_station, + .dump_survey = ieee80211_dump_survey, ++ .dump_flush_stats = ieee80211_dump_flush_stats, + #ifdef CPTCFG_MAC80211_MESH + .add_mpath = ieee80211_add_mpath, + .del_mpath = ieee80211_del_mpath, + +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index 2ebc9ea..2fd6531 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -763,6 +763,15 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx, + return ret; + } + ++static inline int drv_get_flush_stats(struct ieee80211_local *local, int idx, ++ struct flush_info *survey) ++{ ++ int ret = -EOPNOTSUPP; ++ if (local->ops->get_flush_stats) ++ ret = local->ops->get_flush_stats(&local->hw, idx, survey); ++ return ret; ++} ++ + static inline void drv_rfkill_poll(struct ieee80211_local *local) + { + might_sleep(); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index a17d6bc..1103b5c 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6596,6 +6596,91 @@ static int nl80211_dump_survey(struct sk_buff *skb, + return res; + } + ++static int nl80211_send_flush_stats(struct sk_buff *msg, u32 portid, u32 seq, ++ int flags, struct net_device *dev, ++ struct flush_info *survey) ++{ ++ void *hdr; ++ struct nlattr *infoattr; ++ ++ hdr = nl80211hdr_put(msg, portid, seq, flags, ++ NL80211_CMD_NEW_FLUSH_STATS); ++ if (!hdr) ++ return -ENOMEM; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) ++ goto nla_put_failure; ++ ++ infoattr = nla_nest_start(msg, NL80211_ATTR_FLUSH_INFO); ++ if (!infoattr) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(msg, NL80211_FLUSH_REQ_BE, survey->be_flush_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_NOT_REQ_BE, survey->be_flush_not_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_REQ_BK, survey->bk_flush_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_NOT_REQ_BK, survey->bk_flush_not_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_REQ_VI, survey->vi_flush_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_NOT_REQ_VI, survey->vi_flush_not_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_REQ_VO, survey->vo_flush_req)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_FLUSH_NOT_REQ_VO, survey->vo_flush_not_req)) ++ goto nla_put_failure; ++ ++ int ret = nla_nest_end(msg, infoattr); ++ ++ genlmsg_end(msg, hdr); ++ return ret; ++ ++ nla_put_failure: ++ genlmsg_cancel(msg, hdr); ++ return -EMSGSIZE; ++ ++} ++ ++static int nl80211_dump_flush_stats(struct sk_buff *skb, ++ struct netlink_callback *cb) ++{ ++ struct flush_info survey; ++ struct cfg80211_registered_device *rdev; ++ struct wireless_dev *wdev; ++ int survey_idx = cb->args[2]; ++ int res; ++ ++ // printk(KERN_ALERT "%s:%d\n", __FILE__, __LINE__); ++ res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); ++ if (res) ++ return res; ++ ++ ++ if (!rdev->ops->dump_flush_stats) { ++ res = -EOPNOTSUPP; ++ printk(KERN_ALERT "Operation not supported: %s:%d\n", __FILE__, __LINE__); ++ goto out_err; ++ } ++ ++ res = rdev_dump_flush_stats(rdev, wdev->netdev, survey_idx, &survey); ++ ++ if (nl80211_send_flush_stats(skb, ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, NLM_F_MULTI, ++ wdev->netdev, &survey)) { ++ goto out; ++ } ++ out: ++ cb->args[2] = survey_idx; // <- needed ???? ++ res = skb->len; ++ out_err: ++ nl80211_finish_wdev_dump(rdev); ++ printk(KERN_ALERT "returning %s:%d", __FILE__, __LINE__); ++ return 0; ++} ++ + static bool nl80211_valid_wpa_versions(u32 wpa_versions) + { + return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | +@@ -10736,6 +10821,11 @@ static const struct genl_ops nl80211_ops[] = { + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, ++ { ++ .cmd = NL80211_CMD_FLUSH_STATS, ++ .policy = nl80211_policy, ++ .dumpit = nl80211_dump_flush_stats ++ }, + }; + + /* notification functions */ +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index 35cfb71..96d4709 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -612,6 +612,15 @@ static inline int rdev_dump_survey(struct cfg80211_registered_device *rdev, + return ret; + } + ++static inline int rdev_dump_flush_stats(struct cfg80211_registered_device *rdev, ++ struct net_device *netdev, int idx, ++ struct flush_info *info) ++{ ++ int ret; ++ ret = rdev->ops->dump_flush_stats(&rdev->wiphy, netdev, idx, info); ++ return ret; ++} ++ + static inline int rdev_set_pmksa(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +-- +2.7.4 +