[OpenWrt-Devel] [PATCH RFC] Add support for Ubiquiti Unifi Outdoor Plus
Kirill Berezin
kyb22 at rol.ru
Mon Jun 8 03:42:53 EDT 2015
Hi Stefan,
I have a couple of suggestions.
First of all I think it will be better to initialize static variables in
hsr_tune with zeroes :
> ++static void hsr_tune(struct ath_hw* ah, int bw, int fq) {
> ++ static int initialized = 0;
> ++ static int last_bw = 0, last_fq = 0;
And I have an updated versions of write functions. I added to
hsr_write_byte debug messages that can be activated by atheros CONFIG
flag (of course atheros debugging must be compiled in). Also I
simplified loops in hsr_write_a_chain because it seems that they are
needed to get data from a some sort of output buffer which includes less
than 6 bytes.
static u32 hsr_write_byte(struct ath_hw* ah, int delay, u32 value){
int i;
u32 rval = 0;
struct ath_common *common = ath9k_hw_common(ah);
udelay(delay);
ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
udelay(HSR_DELAY_HALF_TICK);
ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0);
udelay(HSR_DELAY_HALF_TICK);
for( i = 0; i < 8; ++i) {
rval = rval << 1;
// pattern is left to right, that is 7-th bit runs first
ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1);
udelay(HSR_DELAY_HALF_TICK);
ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1);
udelay(HSR_DELAY_HALF_TICK);
rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN);
ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
udelay(HSR_DELAY_HALF_TICK);
}
ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
udelay(HSR_DELAY_HALF_TICK);
ath_dbg(common, CONFIG, "hsr_write_byte: write byte %d return value
is %d %c \n", value, rval, rval > 32 ? rval : '-');
return rval & 0xff;
}
static int hsr_write_a_chain(struct ath_hw* ah, char* chain, int items) {
int i = 0;
int status = 0;
hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
status = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
// clear HSR's reply buffer
if ( status) {
int loop = 0;
for ( loop = 0; (loop < 42) && status; ++loop) {
status = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
}
if ( loop >= 42) {
printk(KERN_WARNING "hsr_write_a_chain: can't clear an output
buffer after a 42 cycles.\n");
return 0;
}
}
// data
for ( i =0; (i < items) && ( 0 != chain[i]); ++i) {
hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]);
}
hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
udelay(HSR_DELAY_FINAL);
// reply
memset(chain, 0, items);
hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
udelay(HSR_DELAY_TRAILING);
for ( i = 0; i < (items - 1); ++i) {
u32 ret;
if ( 0 != (ret = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0))) {
chain[i] = (char)ret;
} else {
break;
}
udelay(HSR_DELAY_TRAILING);
}
return (1 < i) ? simple_strtol(chain + 1, NULL, 10) : 0;
}
> I also tried to change target/linux/ar71xx/generic/profiles/ubnt.mk and
> target/linux/ar71xx/image/Makefile to include this module into the
> UBNTUNIFIOUTDOORPLUS image, but this fails. Any idea why?
May be this happens when building a bunch of different profiles at once?
Kirill.
On 06/06/2015 04:28 PM, Stefan Rompf wrote:
> Hi,
>
> please review my patch to add support for the Ubiquiti Unifi Outdoor Plus
> access point based on the work of Kirill Berezin and me.
>
> The access point has a configurable RF filter in the receive path that must be
> tuned according to the selected Wifi channel.
>
> A patch to compat_wireless adds support to register a callback to the ath9k
> driver that is called whenever the channel changes. It also adds hsr.c, the
> channel change helper that tunes the filter connected to the AR9287 GPIO pins.
> I'm running this part successfully on top of the Chaos Calmer RC1 image.
>
> A new configuration option to create the kmod-ath-hsr. It contains the driver
> .ko and must be installed on the access point. This is compile tested on
> trunk.
>
> I also tried to change target/linux/ar71xx/generic/profiles/ubnt.mk and
> target/linux/ar71xx/image/Makefile to include this module into the
> UBNTUNIFIOUTDOORPLUS image, but this fails. Any idea why?
>
> Comments?
>
> Stefan
>
> Index: package/kernel/mac80211/Makefile
> ===================================================================
> --- package/kernel/mac80211/Makefile (Revision 45907)
> +++ package/kernel/mac80211/Makefile (Arbeitskopie)
> @@ -27,7 +27,7 @@
> rt2x00-lib rt2x00-pci rt2x00-usb rt2800-lib rt2400-pci rt2500-pci \
> rt2500-usb rt61-pci rt73-usb rt2800-mmio rt2800-pci rt2800-usb rt2800-soc \
> rtl8180 rtl8187 zd1211rw mac80211-hwsim carl9170 b43 b43legacy \
> - ath9k-common ath9k ath9k-htc ath10k ath net-libipw net-ipw2100 net-ipw2200 \
> + ath9k-common ath9k ath9k-htc ath9k-hsr ath10k ath net-libipw net-ipw2100 net-ipw2200 \
> mwl8k mwifiex-pcie net-hermes net-hermes-pci net-hermes-plx net-hermes-pcmcia \
> iwl-legacy iwl3945 iwl4965 iwlagn wlcore wl12xx wl18xx lib80211 \
> rtlwifi rtlwifi-pci rtlwifi-usb rtl8192c-common rtl8192ce rtl8192se \
> @@ -589,6 +589,22 @@
>
> endef
>
> +define KernelPackage/ath9k-hsr
> + $(call KernelPackage/mac80211/Default)
> + TITLE:=Driver for the Ubiquiti UniFi Outdoor Plus HSR filter
> + URL:=http://wiki.openwrt.org/toh/ubiquiti/unifi_outdoorplus
> + DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx +kmod-ath9k
> + FILES:= \
> + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hsr.ko
> + AUTOLOAD:=$(call AutoProbe,ath9k_hsr)
> +endef
> +
> +define KernelPackage/ath9k-hsr/description
> +This modules adds support for the 'High-Selectivity Receiver'
> +RF filter in the receive path of the access point. It is
> +required for this and only for this access point.
> +endef
> +
> define KernelPackage/ath9k-htc
> $(call KernelPackage/mac80211/Default)
> TITLE:=Atheros 802.11n USB device support
> @@ -1559,6 +1575,8 @@
> config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD
> config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM
>
> +config-$(call config_package,ath9k-hsr) += ATH9K_HSR
> +
> config-$(call config_package,ath9k-htc) += ATH9K_HTC
> config-$(call config_package,ath10k) += ATH10K ATH10K_PCI
>
> @@ -2055,6 +2073,7 @@
> $(eval $(call KernelPackage,mac80211-hwsim))
> $(eval $(call KernelPackage,ath9k-common))
> $(eval $(call KernelPackage,ath9k))
> +$(eval $(call KernelPackage,ath9k-hsr))
> $(eval $(call KernelPackage,ath9k-htc))
> $(eval $(call KernelPackage,ath10k))
> $(eval $(call KernelPackage,ath))
> Index: package/kernel/mac80211/patches/930-ubnt-uap-plus-hsr.patch
> ===================================================================
> --- package/kernel/mac80211/patches/930-ubnt-uap-plus-hsr.patch (Revision 0)
> +++ package/kernel/mac80211/patches/930-ubnt-uap-plus-hsr.patch (Arbeitskopie)
> @@ -0,0 +1,346 @@
> +diff -X diffign -Npur kernel/drivers/net/wireless/ath/ath9k.orig/ath9k.h kernel/drivers/net/wireless/ath/ath9k/ath9k.h
> +--- kernel/drivers/net/wireless/ath/ath9k.orig/ath9k.h 2015-06-04 21:19:11.000000000 +0200
> ++++ kernel/drivers/net/wireless/ath/ath9k/ath9k.h 2015-06-06 10:23:05.000000000 +0200
> +@@ -1110,4 +1110,10 @@ static inline int ath_ahb_init(void) { r
> + static inline void ath_ahb_exit(void) {};
> + #endif
> +
> ++/*
> ++ * OpenWrt UBNT HSR filter support
> ++ */
> ++typedef void (set_channel_helper_fn)(struct ath_hw* ah, int bw, int fq);
> ++void ath9k_register_set_channel_helper(set_channel_helper_fn *);
> ++
> + #endif /* ATH9K_H */
> +diff -X diffign -Npur kernel/drivers/net/wireless/ath/ath9k.orig/channel.c kernel/drivers/net/wireless/ath/ath9k/channel.c
> +--- kernel/drivers/net/wireless/ath/ath9k.orig/channel.c 2015-03-10 04:37:15.000000000 +0100
> ++++ kernel/drivers/net/wireless/ath/ath9k/channel.c 2015-06-06 10:23:05.000000000 +0200
> +@@ -16,6 +16,18 @@
> +
> + #include "ath9k.h"
> +
> ++/*
> ++ * OpenWrt UBNT HSR filter support
> ++ */
> ++static set_channel_helper_fn *ath9k_set_channel_helper;
> ++
> ++void ath9k_register_set_channel_helper(set_channel_helper_fn *chanfn)
> ++{
> ++ ath9k_set_channel_helper = chanfn;
> ++}
> ++EXPORT_SYMBOL(ath9k_register_set_channel_helper);
> ++
> ++
> + /* Set/change channels. If the channel is really being changed, it's done
> + * by reseting the chip. To accomplish this we must first cleanup any pending
> + * DMA, then restart stuff.
> +@@ -41,6 +53,9 @@ static int ath_set_channel(struct ath_so
> + ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
> + chan->center_freq, chandef->width);
> +
> ++ if (ath9k_set_channel_helper)
> ++ ath9k_set_channel_helper(ah, chandef->width, chan->center_freq);
> ++
> + /* update survey stats for the old channel before switching */
> + spin_lock_bh(&common->cc_lock);
> + ath_update_survey_stats(sc);
> +diff -X diffign -Npur kernel/drivers/net/wireless/ath/ath9k.orig/hsr.c kernel/drivers/net/wireless/ath/ath9k/hsr.c
> +--- kernel/drivers/net/wireless/ath/ath9k.orig/hsr.c 1970-01-01 01:00:00.000000000 +0100
> ++++ kernel/drivers/net/wireless/ath/ath9k/hsr.c 2015-06-06 10:48:46.000000000 +0200
> +@@ -0,0 +1,282 @@
> ++/*
> ++ *
> ++ * The MIT License (MIT)
> ++ *
> ++ * Copyright (c) 2015 Kirill Berezin
> ++ *
> ++ * Permission is hereby granted, free of charge, to any person obtaining a copy
> ++ * of this software and associated documentation files (the "Software"), to deal
> ++ * in the Software without restriction, including without limitation the rights
> ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> ++ * copies of the Software, and to permit persons to whom the Software is
> ++ * furnished to do so, subject to the following conditions:
> ++ *
> ++ * The above copyright notice and this permission notice shall be included in all
> ++ * copies or substantial portions of the Software.
> ++ *
> ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> ++ * SOFTWARE.
> ++ *
> ++ */
> ++
> ++#include <linux/io.h>
> ++#include <linux/slab.h>
> ++#include <linux/module.h>
> ++#include <linux/time.h>
> ++#include <linux/bitops.h>
> ++#include <linux/etherdevice.h>
> ++#include <linux/rtnetlink.h>
> ++#include <asm/unaligned.h>
> ++
> ++#include "hw.h"
> ++#include "hw-ops.h"
> ++#include "ar9003_mac.h"
> ++#include "ar9003_mci.h"
> ++#include "ar9003_phy.h"
> ++#include "ath9k.h"
> ++
> ++#define HSR_GPIO_CSN 8
> ++#define HSR_GPIO_CLK 6
> ++#define HSR_GPIO_DOUT 7
> ++#define HSR_GPIO_DIN 5
> ++
> ++/* delays are in useconds */
> ++#define HSR_DELAY_HALF_TICK 100
> ++#define HSR_DELAY_PRE_WRITE 75
> ++#define HSR_DELAY_FINAL 20000
> ++#define HSR_DELAY_TRAILING 200
> ++
> ++static void hsr_init(struct ath_hw* ah);
> ++static int hsr_disable(struct ath_hw* ah);
> ++static int hsr_enable(struct ath_hw* ah, int bw, int fq);
> ++static int hsr_status(struct ath_hw* ah);
> ++
> ++static void hsr_init(struct ath_hw* ah) {
> ++ ath9k_hw_cfg_gpio_input(ah, HSR_GPIO_DIN);
> ++ ath9k_hw_cfg_output(ah, HSR_GPIO_CSN, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
> ++ ath9k_hw_cfg_output(ah, HSR_GPIO_CLK, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
> ++ ath9k_hw_cfg_output(ah, HSR_GPIO_DOUT, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
> ++
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0);
> ++
> ++ udelay(HSR_DELAY_TRAILING);
> ++
> ++ printk(KERN_NOTICE "hsr_init: done");
> ++}
> ++
> ++static u32 hsr_write_byte(struct ath_hw* ah, int delay, u32 value){
> ++ int i;
> ++ u32 rval = 0;
> ++
> ++ udelay(delay);
> ++
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
> ++ udelay(HSR_DELAY_HALF_TICK);
> ++
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0);
> ++ udelay(HSR_DELAY_HALF_TICK);
> ++
> ++ for( i = 0; i < 8; ++i) {
> ++ rval = rval << 1;
> ++
> ++ // pattern is left to right, that is 7-th bit runs first
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1);
> ++ udelay(HSR_DELAY_HALF_TICK);
> ++
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1);
> ++ udelay(HSR_DELAY_HALF_TICK);
> ++
> ++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN);
> ++
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
> ++ udelay(HSR_DELAY_HALF_TICK);
> ++ }
> ++
> ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
> ++ udelay(HSR_DELAY_HALF_TICK);
> ++
> ++ /* printk(KERN_NOTICE "hsr_write_byte: write byte %d return value is %x %d %c \n", value, rval, rval, rval > 32 ? rval : '-'); */
> ++
> ++ return rval & 0xff;
> ++}
> ++
> ++static int hsr_write_a_chain(struct ath_hw* ah, char* chain, int items) {
> ++ int i = 0, j;
> ++ int status = 0;
> ++
> ++ // a preamble
> ++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
> ++ status = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
> ++
> ++ // Continue preamble if hsr returns non zero (perhaps a stray command result)
> ++ if (status) {
> ++ int loop = 2;
> ++ do {
> ++ ++loop;
> ++ if (loop > 42) {
> ++ printk(KERN_NOTICE "hsr_write_a_chain: too many loops in preamble. giving up.\n");
> ++ return -1;
> ++ }
> ++ status = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
> ++ } while(status);
> ++ }
> ++
> ++ for ( i =0; (i < items) && ( 0 != chain[i]); ++i) {
> ++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]);
> ++ }
> ++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
> ++ mdelay(HSR_DELAY_FINAL / 1000);
> ++
> ++ memset(chain, 0, items);
> ++
> ++ for ( j = 0, i = 0; (i < 7) && (j < (items - 1)) ; ++i) {
> ++ u32 ret;
> ++ if ( 31 < (ret = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0))) {
> ++ chain[j] = (char)ret;
> ++ ++ j;
> ++ }
> ++ udelay(HSR_DELAY_TRAILING);
> ++ }
> ++ /* printk(KERN_NOTICE "hsr_write_a_chain: j %d \n", j); */
> ++ return j > 1 ? simple_strtol(chain + 1, NULL, 10) : 0;
> ++}
> ++
> ++static int hsr_disable(struct ath_hw* ah) {
> ++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0};
> ++ int ret;
> ++
> ++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd));
> ++ /* printk(KERN_NOTICE "hsr_disable: return %d \n", ret); */
> ++ if ( (ret > 0) && (*cmd == 'B')) {
> ++ printk(KERN_NOTICE "hsr_disable: bandwidth set %d \n", ret);
> ++ return 0;
> ++ }
> ++
> ++ return -1;
> ++}
> ++
> ++static int hsr_enable(struct ath_hw* ah, int bw, int fq) {
> ++ char cmd[10];
> ++ int ret;
> ++
> ++ memset(cmd, 0, sizeof(cmd));
> ++ *cmd = 'b'; // 98
> ++ snprintf(cmd + 1, 3, "%02d", bw);
> ++
> ++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd));
> ++ if ( (*cmd != 'B') || (ret != bw)) {
> ++ printk(KERN_NOTICE "hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d) \n", 'b', bw, *cmd, ret);
> ++ return -1;
> ++ }
> ++
> ++ memset(cmd, 0, sizeof(cmd));
> ++ *cmd = 'x'; // 120
> ++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd));
> ++ if ( *cmd != 'X') {
> ++ printk(KERN_NOTICE "hsr_enable: failed 'x' command -> reply (%d, %d) \n", *cmd, ret);
> ++ return -1;
> ++ }
> ++
> ++ memset(cmd, 0, sizeof(cmd));
> ++ *cmd = 'm'; // 109
> ++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd));
> ++ if ( *cmd != 'M') {
> ++ printk(KERN_NOTICE "hsr_enable: failed 'm' command -> reply (%d, %d) \n", *cmd, ret);
> ++ return -1;
> ++ }
> ++
> ++ memset(cmd, 0, sizeof(cmd));
> ++ *cmd = 'f'; // 102
> ++ snprintf(cmd + 1, 6, "%05d", fq);
> ++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd));
> ++ if ( (*cmd != 'F') && (ret != fq)) {
> ++ printk(KERN_NOTICE "hsr_enable: failed set frequency -> reply (%d, %d) \n", *cmd, ret);
> ++ return -1;
> ++ }
> ++
> ++ printk(KERN_NOTICE "hsr_enable: center frequency %dMHz bandwidth %dMHz \n", fq, bw);
> ++
> ++ return 0;
> ++}
> ++
> ++static int hsr_status(struct ath_hw* ah) {
> ++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 115
> ++ int ret;
> ++
> ++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd));
> ++ if ( (*cmd != 'S')) {
> ++ printk(KERN_NOTICE "hsr_status: returned %d,%d \n", *cmd, ret);
> ++ return -1;
> ++ }
> ++
> ++ printk(KERN_NOTICE "hsr_status: current status is %d \n", ret);
> ++
> ++ return 0;
> ++}
> ++
> ++static void hsr_tune(struct ath_hw* ah, int bw, int fq) {
> ++ static int initialized;
> ++ static int last_bw, last_fq;
> ++
> ++ if (NULL == ah) {
> ++ return;
> ++ }
> ++
> ++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn
> ++ 20MHz on invalid values */
> ++ if ( (bw != 5) && (bw != 10) && (bw != 20) && (bw != 40)) {
> ++ bw = 20;
> ++ }
> ++
> ++ if (bw == last_bw && fq == last_fq) {
> ++ /* Avoid tuning if nothing changes */
> ++ printk(KERN_NOTICE "hsr_tune: already tuned to center frequency %dMHz bandwidth %dMHz\n", fq, bw);
> ++ return;
> ++ }
> ++
> ++ if (!initialized) {
> ++ initialized = 1;
> ++ hsr_init(ah);
> ++ }
> ++
> ++ if (!hsr_enable(ah, bw, fq)) {
> ++ hsr_status(ah);
> ++ last_bw = bw;
> ++ last_fq = fq;
> ++ } else {
> ++ /* Tuning failed - make sure that we try again */
> ++ last_bw = -1;
> ++ }
> ++}
> ++
> ++
> ++static int __init hsr_mod_init(void)
> ++{
> ++ rtnl_lock(); /* Should lock against nl80211_set_channel() */
> ++ ath9k_register_set_channel_helper(hsr_tune);
> ++ rtnl_unlock();
> ++ return 0;
> ++}
> ++
> ++static void __exit hsr_mod_exit(void)
> ++{
> ++ rtnl_lock();
> ++ ath9k_register_set_channel_helper(NULL);
> ++ rtnl_unlock();
> ++}
> ++
> ++module_init(hsr_mod_init);
> ++module_exit(hsr_mod_exit);
> ++
> ++MODULE_AUTHOR("Kirill Berezin, Stefan Rompf");
> ++MODULE_DESCRIPTION("Support for Ubiquiti Outdoor Plus HSR filter.");
> ++MODULE_SUPPORTED_DEVICE("Ubiquiti Outdoor Plus");
> ++MODULE_LICENSE("Dual MIT/GPL");
> ++
> +diff -X diffign -Npur kernel/drivers/net/wireless/ath/ath9k.orig/Makefile kernel/drivers/net/wireless/ath/ath9k/Makefile
> +--- kernel/drivers/net/wireless/ath/ath9k.orig/Makefile 2015-03-10 04:37:16.000000000 +0100
> ++++ kernel/drivers/net/wireless/ath/ath9k/Makefile 2015-06-06 10:23:05.000000000 +0200
> +@@ -22,6 +22,10 @@ ath9k-$(CPTCFG_ATH9K_STATION_STATISTICS)
> +
> + obj-$(CPTCFG_ATH9K) += ath9k.o
> +
> ++ath9k_hsr-y := hsr.o
> ++
> ++obj-$(CPTCFG_ATH9K) += ath9k_hsr.o
> ++
> + ath9k_hw-y:= \
> + ar9002_hw.o \
> + ar9003_hw.o \
> Index: target/linux/ar71xx/generic/profiles/ubnt.mk
> ===================================================================
> --- target/linux/ar71xx/generic/profiles/ubnt.mk (Revision 45907)
> +++ target/linux/ar71xx/generic/profiles/ubnt.mk (Arbeitskopie)
> @@ -49,6 +49,17 @@
>
> $(eval $(call Profile,UBNTUNIFIOUTDOOR))
>
> +define Profile/UBNTUNIFIOUTDOORPLUS
> + NAME:=Ubiquiti UniFiAP Outdoor Plus
> + PACKAGES:=kmod-ath9k-hsr
> +endef
> +
> +define Profile/UBNTUNIFIOUTDOORPLUS/Description
> + Package set optimized for the Ubiquiti UniFiAP Outdoor Plus.
> +endef
> +
> +$(eval $(call Profile,UBNTUNIFIOUTDOORPLUS))
> +
> define Profile/UAPPRO
> NAME:=Ubiquiti UniFi AP Pro
> PACKAGES:=
> Index: target/linux/ar71xx/image/Makefile
> ===================================================================
> --- target/linux/ar71xx/image/Makefile (Revision 45907)
> +++ target/linux/ar71xx/image/Makefile (Arbeitskopie)
> @@ -1975,7 +1975,7 @@
> $(eval $(call MultiProfile,TLWR1043,TLWR1043V1 TLWR1043V2))
> $(eval $(call MultiProfile,TLWDR4300,TLWDR3500V1 TLWDR3600V1 TLWDR4300V1 TLWDR4300V1IL TLWDR4310V1 MW4530RV1))
> $(eval $(call MultiProfile,TUBE2H,TUBE2H8M TUBE2H16M))
> -$(eval $(call MultiProfile,UBNT,UBNTAIRROUTER UBNTRS UBNTRSPRO UBNTLSSR71 UBNTBULLETM UBNTROCKETM UBNTROCKETMXW UBNTNANOM UBNTNANOMXW UBNTLOCOXW UBNTUNIFI
> UBNTUNIFIOUTDOOR UBNTUNIFIOUTDOORPLUS UAPPRO UBNTAIRGW))
> +$(eval $(call MultiProfile,UBNT,UBNTAIRROUTER UBNTRS UBNTRSPRO UBNTLSSR71 UBNTBULLETM UBNTROCKETM UBNTROCKETMXW UBNTNANOM UBNTNANOMXW UBNTLOCOXW UBNTUNIFI
> UBNTUNIFIOUTDOOR UAPPRO UBNTAIRGW))
> $(eval $(call MultiProfile,WNR612V2,REALWNR612V2 N150R))
> $(eval $(call MultiProfile,WNR1000V2,REALWNR1000V2 WNR1000V2_VC))
> $(eval $(call MultiProfile,WP543,WP543_2M WP543_4M WP543_8M WP543_16M))
>
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list