From 8194bc1d070206ce2f2da02b27b70fb1b962857e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 28 Apr 2014 23:33:09 +0200 Subject: [PATCH] Backport hostapd and mac80211 from Barrier Breaker --- ...pd-and-mac80211-from-Barrier-Breaker.patch | 13412 ++++++++++++++++ 1 file changed, 13412 insertions(+) create mode 100644 patches/openwrt/0019-Backport-hostapd-and-mac80211-from-Barrier-Breaker.patch diff --git a/patches/openwrt/0019-Backport-hostapd-and-mac80211-from-Barrier-Breaker.patch b/patches/openwrt/0019-Backport-hostapd-and-mac80211-from-Barrier-Breaker.patch new file mode 100644 index 00000000..fd103ad0 --- /dev/null +++ b/patches/openwrt/0019-Backport-hostapd-and-mac80211-from-Barrier-Breaker.patch @@ -0,0 +1,13412 @@ +From: Matthias Schiffer +Date: Mon, 28 Apr 2014 21:44:58 +0200 +Subject: Backport hostapd and mac80211 from Barrier Breaker + +diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile +index b4dc242..ecf9e4b 100644 +--- a/package/hostapd/Makefile ++++ b/package/hostapd/Makefile +@@ -8,9 +8,9 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=hostapd +-PKG_VERSION:=20131120 ++PKG_VERSION:=2014-04-24 + PKG_RELEASE:=1 +-PKG_REV:=594516b4c28a94ca686b17f1e463dfd6712b75a7 ++PKG_REV:=3cf48c4f2e2d558130253457fea02ef4047cf8e1 + + PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 + PKG_SOURCE_URL:=git://w1.fi/srv/git/hostap.git +diff --git a/package/hostapd/patches/100-madwifi_key_fixes.patch b/package/hostapd/patches/100-madwifi_key_fixes.patch +index dcd6d10..a46943b 100644 +--- a/package/hostapd/patches/100-madwifi_key_fixes.patch ++++ b/package/hostapd/patches/100-madwifi_key_fixes.patch +@@ -1,6 +1,6 @@ + --- a/src/drivers/driver_madwifi.c + +++ b/src/drivers/driver_madwifi.c +-@@ -450,7 +450,9 @@ wpa_driver_madwifi_set_key(const char *i ++@@ -449,7 +449,9 @@ wpa_driver_madwifi_set_key(const char *i + + memset(&wk, 0, sizeof(wk)); + wk.ik_type = cipher; +@@ -11,7 +11,7 @@ + if (addr == NULL || is_broadcast_ether_addr(addr)) { + memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); + wk.ik_keyix = key_idx; +-@@ -462,6 +464,20 @@ wpa_driver_madwifi_set_key(const char *i ++@@ -461,6 +463,20 @@ wpa_driver_madwifi_set_key(const char *i + wk.ik_keylen = key_len; + memcpy(wk.ik_keydata, key, key_len); + +diff --git a/package/hostapd/patches/110-bool_fix.patch b/package/hostapd/patches/110-bool_fix.patch +index 9f82b0b..1ad84bf 100644 +--- a/package/hostapd/patches/110-bool_fix.patch ++++ b/package/hostapd/patches/110-bool_fix.patch +@@ -1,6 +1,6 @@ + --- a/src/ap/ieee802_1x.c + +++ b/src/ap/ieee802_1x.c +-@@ -1933,9 +1933,9 @@ void ieee802_1x_notify_pre_auth(struct e ++@@ -2119,9 +2119,9 @@ void ieee802_1x_notify_pre_auth(struct e + } + + +diff --git a/package/hostapd/patches/130-wds_sta_del_fix.patch b/package/hostapd/patches/130-wds_sta_del_fix.patch +deleted file mode 100644 +index 06b6906..0000000 +--- a/package/hostapd/patches/130-wds_sta_del_fix.patch ++++ /dev/null +@@ -1,13 +0,0 @@ +---- a/src/drivers/driver_nl80211.c +-+++ b/src/drivers/driver_nl80211.c +-@@ -9083,8 +9083,8 @@ static int i802_set_wds_sta(void *priv, +- name); +- +- i802_set_sta_vlan(priv, addr, bss->ifname, 0); +-- return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN, +-- name); +-+ nl80211_remove_iface(drv, if_nametoindex(name)); +-+ return 0; +- } +- } +- +diff --git a/package/hostapd/patches/200-multicall.patch b/package/hostapd/patches/200-multicall.patch +index 2289f51..1511b19 100644 +--- a/package/hostapd/patches/200-multicall.patch ++++ b/package/hostapd/patches/200-multicall.patch +@@ -1,14 +1,14 @@ + --- a/hostapd/Makefile + +++ b/hostapd/Makefile +-@@ -14,6 +14,7 @@ CFLAGS += -I../src/utils ++@@ -14,6 +14,7 @@ CFLAGS += -I$(abspath ../src/utils) + # CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include + + -include .config + +-include $(if $(MULTICALL), ../wpa_supplicant/.config) + +- ifndef CONFIG_OS +- ifdef CONFIG_NATIVE_WINDOWS +-@@ -200,10 +201,14 @@ ifdef CONFIG_IEEE80211AC ++ ifdef CONFIG_TESTING_OPTIONS ++ CFLAGS += -DCONFIG_TESTING_OPTIONS ++@@ -223,10 +224,14 @@ ifdef CONFIG_IEEE80211AC + CFLAGS += -DCONFIG_IEEE80211AC + endif + +@@ -26,7 +26,7 @@ + LIBS += $(DRV_AP_LIBS) + + ifdef CONFIG_L2_PACKET +-@@ -890,6 +895,12 @@ install: all ++@@ -913,6 +918,12 @@ install: all + + BCHECK=../src/drivers/build.hostapd + +@@ -39,7 +39,7 @@ + hostapd: $(BCHECK) $(OBJS) + $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) + @$(E) " LD " $@ +-@@ -928,6 +939,12 @@ HOBJS += ../src/crypto/aes-internal.o ++@@ -951,6 +962,12 @@ HOBJS += ../src/crypto/aes-internal.o + HOBJS += ../src/crypto/aes-internal-enc.o + endif + +@@ -54,15 +54,15 @@ + @$(E) " LD " $@ + --- a/wpa_supplicant/Makefile + +++ b/wpa_supplicant/Makefile +-@@ -14,6 +14,7 @@ CFLAGS += -I../src +- CFLAGS += -I../src/utils ++@@ -14,6 +14,7 @@ CFLAGS += -I$(abspath ../src) ++ CFLAGS += -I$(abspath ../src/utils) + + -include .config + +-include $(if $(MULTICALL),../hostapd/.config) + +- BINALL=wpa_supplicant wpa_cli +- +-@@ -727,6 +728,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS ++ ifdef CONFIG_TESTING_OPTIONS ++ CFLAGS += -DCONFIG_TESTING_OPTIONS ++@@ -746,6 +747,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS + CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS + LIBS += -ldl -rdynamic + endif +@@ -73,7 +73,7 @@ + endif + + ifdef CONFIG_AP +-@@ -735,9 +740,11 @@ NEED_EAP_COMMON=y ++@@ -754,9 +759,11 @@ NEED_EAP_COMMON=y + NEED_RSN_AUTHENTICATOR=y + CFLAGS += -DCONFIG_AP + OBJS += ap.o +@@ -85,7 +85,7 @@ + OBJS += ../src/ap/hostapd.o + OBJS += ../src/ap/wpa_auth_glue.o + OBJS += ../src/ap/utils.o +-@@ -799,10 +806,18 @@ endif ++@@ -818,10 +825,18 @@ endif + ifdef CONFIG_HS20 + OBJS += ../src/ap/hs20.o + endif +@@ -104,7 +104,7 @@ + NEED_AES_WRAP=y + OBJS += ../src/ap/wpa_auth.o + OBJS += ../src/ap/wpa_auth_ie.o +-@@ -1551,6 +1566,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv) ++@@ -1584,6 +1599,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv) + + $(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config + +@@ -117,7 +117,7 @@ + wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) + $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) + @$(E) " LD " $@ +-@@ -1625,6 +1646,12 @@ eap_eke.so: ../src/eap_peer/eap_eke.c .. ++@@ -1664,6 +1685,12 @@ endif + %@.service: %.service.arg.in + sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ + +@@ -132,7 +132,7 @@ + wpa_cli.exe: wpa_cli + --- a/src/drivers/driver.h + +++ b/src/drivers/driver.h +-@@ -4079,8 +4079,8 @@ union wpa_event_data { ++@@ -3886,8 +3886,8 @@ union wpa_event_data { + * Driver wrapper code should call this function whenever an event is received + * from the driver. + */ +@@ -145,7 +145,7 @@ + /* + --- a/src/ap/drv_callbacks.c + +++ b/src/ap/drv_callbacks.c +-@@ -844,8 +844,8 @@ static void hostapd_event_dfs_nop_finish ++@@ -906,8 +906,8 @@ static void hostapd_event_dfs_nop_finish + #endif /* NEED_AP_MLME */ + + +@@ -158,7 +158,7 @@ + #ifndef CONFIG_NO_STDOUT_DEBUG + --- a/wpa_supplicant/wpa_priv.c + +++ b/wpa_supplicant/wpa_priv.c +-@@ -817,8 +817,8 @@ static void wpa_priv_send_ft_response(st ++@@ -815,8 +815,8 @@ static void wpa_priv_send_ft_response(st + } + + +@@ -169,7 +169,7 @@ + { + struct wpa_priv_interface *iface = ctx; + +-@@ -960,6 +960,7 @@ int main(int argc, char *argv[]) ++@@ -956,6 +956,7 @@ int main(int argc, char *argv[]) + if (os_program_init()) + return -1; + +@@ -179,7 +179,7 @@ + for (;;) { + --- a/wpa_supplicant/events.c + +++ b/wpa_supplicant/events.c +-@@ -2710,8 +2710,8 @@ static void wpa_supplicant_update_channe ++@@ -2929,8 +2929,8 @@ static void wpa_supplicant_notify_avoid_ + } + + +@@ -192,7 +192,7 @@ + + --- a/wpa_supplicant/wpa_supplicant.c + +++ b/wpa_supplicant/wpa_supplicant.c +-@@ -3138,6 +3138,9 @@ static void wpa_supplicant_deinit_iface( ++@@ -3724,6 +3724,9 @@ static void wpa_supplicant_deinit_iface( + os_free(wpa_s); + } + +@@ -202,7 +202,7 @@ + + /** + * wpa_supplicant_add_iface - Add a new network interface +-@@ -3329,6 +3332,7 @@ struct wpa_global * wpa_supplicant_init( ++@@ -3915,6 +3918,7 @@ struct wpa_global * wpa_supplicant_init( + wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); + #endif /* CONFIG_NO_WPA_MSG */ + +@@ -212,7 +212,7 @@ + wpa_debug_open_syslog(); + --- a/hostapd/main.c + +++ b/hostapd/main.c +-@@ -511,6 +511,9 @@ static int hostapd_get_ctrl_iface_group( ++@@ -502,6 +502,9 @@ static int hostapd_get_ctrl_iface_group( + return 0; + } + +@@ -220,27 +220,25 @@ + + union wpa_event_data *data); + + + +- int main(int argc, char *argv[]) +- { +-@@ -541,6 +544,7 @@ int main(int argc, char *argv[]) ++ #ifdef CONFIG_WPS ++ static int gen_uuid(const char *txt_addr) ++@@ -553,6 +556,7 @@ int main(int argc, char *argv[]) + interfaces.global_iface_name = NULL; + interfaces.global_ctrl_sock = -1; + + + wpa_supplicant_event = hostapd_wpa_event; + for (;;) { +- c = getopt(argc, argv, "b:Bde:f:hKP:Ttvg:G:"); ++ c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:"); + if (c < 0) + --- a/src/drivers/drivers.c + +++ b/src/drivers/drivers.c +-@@ -7,7 +7,11 @@ +- */ +- +- #include "includes.h" +-+#include "common.h" +-+#include "driver.h" ++@@ -10,6 +10,9 @@ ++ #include "utils/common.h" ++ #include "driver.h" + + +void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event, + + union wpa_event_data *data); +- +++ + #ifdef CONFIG_DRIVER_WEXT + extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */ ++ #endif /* CONFIG_DRIVER_WEXT */ +diff --git a/package/hostapd/patches/300-noscan.patch b/package/hostapd/patches/300-noscan.patch +index 17e7661..50b70b7 100644 +--- a/package/hostapd/patches/300-noscan.patch ++++ b/package/hostapd/patches/300-noscan.patch +@@ -1,17 +1,17 @@ + --- a/hostapd/config_file.c + +++ b/hostapd/config_file.c +-@@ -2412,6 +2412,8 @@ static int hostapd_config_fill(struct ho +- } ++@@ -2638,6 +2638,8 @@ static int hostapd_config_fill(struct ho ++ } + #endif /* CONFIG_IEEE80211W */ + #ifdef CONFIG_IEEE80211N +-+ } else if (os_strcmp(buf, "noscan") == 0) { +-+ conf->noscan = atoi(pos); +- } else if (os_strcmp(buf, "ieee80211n") == 0) { +- conf->ieee80211n = atoi(pos); +- } else if (os_strcmp(buf, "ht_capab") == 0) { +++ } else if (os_strcmp(buf, "noscan") == 0) { +++ conf->noscan = atoi(pos); ++ } else if (os_strcmp(buf, "ieee80211n") == 0) { ++ conf->ieee80211n = atoi(pos); ++ } else if (os_strcmp(buf, "ht_capab") == 0) { + --- a/src/ap/ap_config.h + +++ b/src/ap/ap_config.h +-@@ -527,6 +527,7 @@ struct hostapd_config { ++@@ -576,6 +576,7 @@ struct hostapd_config { + + int ht_op_mode_fixed; + u16 ht_capab; +@@ -21,7 +21,7 @@ + int require_ht; + --- a/src/ap/hw_features.c + +++ b/src/ap/hw_features.c +-@@ -577,7 +577,7 @@ static int ieee80211n_check_40mhz(struct ++@@ -574,7 +574,7 @@ static int ieee80211n_check_40mhz(struct + { + struct wpa_driver_scan_params params; + +diff --git a/package/hostapd/patches/310-rescan_immediately.patch b/package/hostapd/patches/310-rescan_immediately.patch +index 043f07c..f96c7e6 100644 +--- a/package/hostapd/patches/310-rescan_immediately.patch ++++ b/package/hostapd/patches/310-rescan_immediately.patch +@@ -1,6 +1,6 @@ + --- a/wpa_supplicant/wpa_supplicant.c + +++ b/wpa_supplicant/wpa_supplicant.c +-@@ -2488,7 +2488,7 @@ static struct wpa_supplicant * wpa_suppl ++@@ -2746,7 +2746,7 @@ static struct wpa_supplicant * wpa_suppl + if (wpa_s == NULL) + return NULL; + wpa_s->scan_req = INITIAL_SCAN_REQ; +diff --git a/package/hostapd/patches/320-optional_rfkill.patch b/package/hostapd/patches/320-optional_rfkill.patch +index 7ec51b1..b0ea38f 100644 +--- a/package/hostapd/patches/320-optional_rfkill.patch ++++ b/package/hostapd/patches/320-optional_rfkill.patch +@@ -1,218 +1,3 @@ +---- a/src/drivers/driver_nl80211.c +-+++ b/src/drivers/driver_nl80211.c +-@@ -254,7 +254,9 @@ struct wpa_driver_nl80211_data { +- int if_removed; +- int if_disabled; +- int ignore_if_down_event; +-+#ifdef CONFIG_RFKILL +- struct rfkill_data *rfkill; +-+#endif +- struct wpa_driver_capa capa; +- u8 *extended_capa, *extended_capa_mask; +- unsigned int extended_capa_len; +-@@ -3630,7 +3632,7 @@ static int wpa_driver_nl80211_init_nl(st +- return 0; +- } +- +-- +-+#ifdef CONFIG_RFKILL +- static void wpa_driver_nl80211_rfkill_blocked(void *ctx) +- { +- wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked"); +-@@ -3652,6 +3654,7 @@ static void wpa_driver_nl80211_rfkill_un +- } +- /* rtnetlink ifup handler will report interface as enabled */ +- } +-+#endif /* CONFIG_RFKILL */ +- +- +- static void wpa_driver_nl80211_handle_eapol_tx_status(int sock, +-@@ -3740,7 +3743,9 @@ static void * wpa_driver_nl80211_drv_ini +- const u8 *set_addr) +- { +- struct wpa_driver_nl80211_data *drv; +-+#ifdef CONFIG_RFKILL +- struct rfkill_config *rcfg; +-+#endif +- struct i802_bss *bss; +- +- if (global_priv == NULL) +-@@ -3778,6 +3783,7 @@ static void * wpa_driver_nl80211_drv_ini +- if (nl80211_init_bss(bss)) +- goto failed; +- +-+#ifdef CONFIG_RFKILL +- rcfg = os_zalloc(sizeof(*rcfg)); +- if (rcfg == NULL) +- goto failed; +-@@ -3790,6 +3796,7 @@ static void * wpa_driver_nl80211_drv_ini +- wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available"); +- os_free(rcfg); +- } +-+#endif /* CONFIG_RFKILL */ +- +- if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0) +- drv->start_iface_up = 1; +-@@ -4116,10 +4123,12 @@ static void nl80211_mgmt_unsubscribe(str +- } +- +- +-+#ifdef CONFIG_RFKILL +- static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx) +- { +- wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); +- } +-+#endif /* CONFIG_RFKILL */ +- +- +- static void nl80211_del_p2pdev(struct i802_bss *bss) +-@@ -4246,13 +4255,16 @@ wpa_driver_nl80211_finish_drv_init(struc +- } +- +- if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) { +-+#ifdef CONFIG_RFKILL +- if (rfkill_is_blocked(drv->rfkill)) { +- wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable " +- "interface '%s' due to rfkill", +- bss->ifname); +- drv->if_disabled = 1; +- send_rfkill_event = 1; +-- } else { +-+ } else +-+#endif +-+ { +- wpa_printf(MSG_ERROR, "nl80211: Could not set " +- "interface '%s' UP", bss->ifname); +- return -1; +-@@ -4268,8 +4280,10 @@ wpa_driver_nl80211_finish_drv_init(struc +- return -1; +- +- if (send_rfkill_event) { +-+#ifdef CONFIG_RFKILL +- eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill, +- drv, drv->ctx); +-+#endif +- } +- +- return 0; +-@@ -4347,7 +4361,9 @@ static void wpa_driver_nl80211_deinit(st +- +- netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0, +- IF_OPER_UP); +-+#ifdef CONFIG_RFKILL +- rfkill_deinit(drv->rfkill); +-+#endif +- +- eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); +- +---- a/src/drivers/driver_wext.c +-+++ b/src/drivers/driver_wext.c +-@@ -740,7 +740,7 @@ static void wpa_driver_wext_event_rtm_de +- } +- } +- +-- +-+#ifdef CONFIG_RFKILL +- static void wpa_driver_wext_rfkill_blocked(void *ctx) +- { +- wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked"); +-@@ -762,7 +762,7 @@ static void wpa_driver_wext_rfkill_unblo +- } +- /* rtnetlink ifup handler will report interface as enabled */ +- } +-- +-+#endif /* CONFIG_RFKILL */ +- +- static void wext_get_phy_name(struct wpa_driver_wext_data *drv) +- { +-@@ -808,7 +808,9 @@ void * wpa_driver_wext_init(void *ctx, c +- { +- struct wpa_driver_wext_data *drv; +- struct netlink_config *cfg; +-+#ifdef CONFIG_RFKILL +- struct rfkill_config *rcfg; +-+#endif +- char path[128]; +- struct stat buf; +- +-@@ -843,6 +845,7 @@ void * wpa_driver_wext_init(void *ctx, c +- goto err2; +- } +- +-+#ifdef CONFIG_RFKILL +- rcfg = os_zalloc(sizeof(*rcfg)); +- if (rcfg == NULL) +- goto err3; +-@@ -855,6 +858,7 @@ void * wpa_driver_wext_init(void *ctx, c +- wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available"); +- os_free(rcfg); +- } +-+#endif /* CONFIG_RFKILL */ +- +- drv->mlme_sock = -1; +- +-@@ -872,7 +876,9 @@ void * wpa_driver_wext_init(void *ctx, c +- return drv; +- +- err3: +-+#ifdef CONFIG_RFKILL +- rfkill_deinit(drv->rfkill); +-+#endif +- netlink_deinit(drv->netlink); +- err2: +- close(drv->ioctl_sock); +-@@ -882,10 +888,12 @@ err1: +- } +- +- +-+#ifdef CONFIG_RFKILL +- static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx) +- { +- wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); +- } +-+#endif /* CONFIG_RFKILL */ +- +- +- static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) +-@@ -893,13 +901,16 @@ static int wpa_driver_wext_finish_drv_in +- int send_rfkill_event = 0; +- +- if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) { +-+#ifdef CONFIG_RFKILL +- if (rfkill_is_blocked(drv->rfkill)) { +- wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable " +- "interface '%s' due to rfkill", +- drv->ifname); +- drv->if_disabled = 1; +- send_rfkill_event = 1; +-- } else { +-+ } else +-+#endif +-+ { +- wpa_printf(MSG_ERROR, "WEXT: Could not set " +- "interface '%s' UP", drv->ifname); +- return -1; +-@@ -947,8 +958,10 @@ static int wpa_driver_wext_finish_drv_in +- 1, IF_OPER_DORMANT); +- +- if (send_rfkill_event) { +-+#ifdef CONFIG_RFKILL +- eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill, +- drv, drv->ctx); +-+#endif +- } +- +- return 0; +-@@ -978,7 +991,9 @@ void wpa_driver_wext_deinit(void *priv) +- +- netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); +- netlink_deinit(drv->netlink); +-+#ifdef CONFIG_RFKILL +- rfkill_deinit(drv->rfkill); +-+#endif +- +- if (drv->mlme_sock >= 0) +- eloop_unregister_read_sock(drv->mlme_sock); + --- a/src/drivers/drivers.mak + +++ b/src/drivers/drivers.mak + @@ -25,7 +25,6 @@ NEED_SME=y +@@ -247,15 +32,30 @@ + endif + + ifdef CONFIG_VLAN_NETLINK +---- a/src/drivers/driver_wext.h +-+++ b/src/drivers/driver_wext.h +-@@ -22,7 +22,9 @@ struct wpa_driver_wext_data { +- int ifindex2; +- int if_removed; +- int if_disabled; +-+#ifdef CONFIG_RFKILL +- struct rfkill_data *rfkill; +-+#endif +- u8 *assoc_req_ies; +- size_t assoc_req_ies_len; +- u8 *assoc_resp_ies; ++--- a/src/drivers/rfkill.h +++++ b/src/drivers/rfkill.h ++@@ -18,8 +18,24 @@ struct rfkill_config { ++ void (*unblocked_cb)(void *ctx); ++ }; ++ +++#ifdef CONFIG_RFKILL ++ struct rfkill_data * rfkill_init(struct rfkill_config *cfg); ++ void rfkill_deinit(struct rfkill_data *rfkill); ++ int rfkill_is_blocked(struct rfkill_data *rfkill); +++#else +++static inline struct rfkill_data * rfkill_init(struct rfkill_config *cfg) +++{ +++ return (void *) 1; +++} +++ +++static inline void rfkill_deinit(struct rfkill_data *rfkill) +++{ +++} +++ +++static inline int rfkill_is_blocked(struct rfkill_data *rfkill) +++{ +++ return 0; +++} +++#endif ++ ++ #endif /* RFKILL_H */ +diff --git a/package/hostapd/patches/330-nl80211_fix_set_freq.patch b/package/hostapd/patches/330-nl80211_fix_set_freq.patch +index a505a60..864ac5e 100644 +--- a/package/hostapd/patches/330-nl80211_fix_set_freq.patch ++++ b/package/hostapd/patches/330-nl80211_fix_set_freq.patch +@@ -1,6 +1,6 @@ + --- a/src/drivers/driver_nl80211.c + +++ b/src/drivers/driver_nl80211.c +-@@ -6860,7 +6860,7 @@ static int wpa_driver_nl80211_set_freq(s ++@@ -7380,7 +7380,7 @@ static int wpa_driver_nl80211_set_freq(s + + nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY); + +@@ -9,7 +9,7 @@ + if (nl80211_put_freq_params(msg, freq) < 0) + goto nla_put_failure; + +-@@ -11322,7 +11322,7 @@ static int nl80211_switch_channel(void * ++@@ -11905,7 +11905,7 @@ static int nl80211_switch_channel(void * + return -ENOMEM; + + nl80211_cmd(drv, msg, 0, NL80211_CMD_CHANNEL_SWITCH); +diff --git a/package/hostapd/patches/340-reload_freq_change.patch b/package/hostapd/patches/340-reload_freq_change.patch +index 9316794..d76f9de 100644 +--- a/package/hostapd/patches/340-reload_freq_change.patch ++++ b/package/hostapd/patches/340-reload_freq_change.patch +@@ -1,6 +1,6 @@ + --- a/src/ap/hostapd.c + +++ b/src/ap/hostapd.c +-@@ -72,6 +72,16 @@ static void hostapd_reload_bss(struct ho ++@@ -68,6 +68,16 @@ static void hostapd_reload_bss(struct ho + #endif /* CONFIG_NO_RADIUS */ + + ssid = &hapd->conf->ssid; +@@ -17,7 +17,7 @@ + if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next && + ssid->wpa_passphrase_set && ssid->wpa_passphrase) { + /* +-@@ -172,6 +182,9 @@ int hostapd_reload_config(struct hostapd ++@@ -168,20 +178,12 @@ int hostapd_reload_config(struct hostapd + oldconf = hapd->iconf; + iface->conf = newconf; + +@@ -27,3 +27,17 @@ + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + hapd->iconf = newconf; ++- hapd->iconf->channel = oldconf->channel; ++- hapd->iconf->secondary_channel = oldconf->secondary_channel; ++- hapd->iconf->ieee80211n = oldconf->ieee80211n; ++- hapd->iconf->ieee80211ac = oldconf->ieee80211ac; ++- hapd->iconf->ht_capab = oldconf->ht_capab; ++- hapd->iconf->vht_capab = oldconf->vht_capab; ++- hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth; ++- hapd->iconf->vht_oper_centr_freq_seg0_idx = ++- oldconf->vht_oper_centr_freq_seg0_idx; ++- hapd->iconf->vht_oper_centr_freq_seg1_idx = ++- oldconf->vht_oper_centr_freq_seg1_idx; ++ hapd->conf = newconf->bss[j]; ++ hostapd_reload_bss(hapd); ++ } +diff --git a/package/hostapd/patches/350-nl80211_del_beacon_bss.patch b/package/hostapd/patches/350-nl80211_del_beacon_bss.patch +index 885922c..8da6372 100644 +--- a/package/hostapd/patches/350-nl80211_del_beacon_bss.patch ++++ b/package/hostapd/patches/350-nl80211_del_beacon_bss.patch +@@ -1,6 +1,6 @@ + --- a/src/drivers/driver_nl80211.c + +++ b/src/drivers/driver_nl80211.c +-@@ -4290,18 +4290,20 @@ wpa_driver_nl80211_finish_drv_init(struc ++@@ -4748,18 +4748,20 @@ wpa_driver_nl80211_finish_drv_init(struc + } + + +@@ -24,7 +24,7 @@ + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: +-@@ -4309,6 +4311,15 @@ static int wpa_driver_nl80211_del_beacon ++@@ -4767,6 +4769,15 @@ static int wpa_driver_nl80211_del_beacon + return -ENOBUFS; + } + +@@ -40,7 +40,7 @@ + + /** + * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface +-@@ -9911,7 +9922,6 @@ static int wpa_driver_nl80211_stop_ap(vo ++@@ -10475,7 +10486,6 @@ static int wpa_driver_nl80211_stop_ap(vo + if (!is_ap_interface(drv->nlmode)) + return -1; + wpa_driver_nl80211_del_beacon(drv); +diff --git a/package/hostapd/patches/360-ctrl_iface_reload.patch b/package/hostapd/patches/360-ctrl_iface_reload.patch +index 170d4f2..e69c3d3 100644 +--- a/package/hostapd/patches/360-ctrl_iface_reload.patch ++++ b/package/hostapd/patches/360-ctrl_iface_reload.patch +@@ -1,6 +1,6 @@ + --- a/hostapd/ctrl_iface.c + +++ b/hostapd/ctrl_iface.c +-@@ -34,6 +34,7 @@ ++@@ -37,6 +37,7 @@ + #include "wps/wps.h" + #include "config_file.h" + #include "ctrl_iface.h" +@@ -8,7 +8,7 @@ + + + struct wpa_ctrl_dst { +-@@ -44,6 +45,7 @@ struct wpa_ctrl_dst { ++@@ -47,6 +48,7 @@ struct wpa_ctrl_dst { + int errors; + }; + +@@ -16,7 +16,7 @@ + + static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, + const char *buf, size_t len); +-@@ -153,6 +155,68 @@ static int hostapd_ctrl_iface_new_sta(st ++@@ -156,6 +158,68 @@ static int hostapd_ctrl_iface_new_sta(st + return 0; + } + +@@ -85,14 +85,14 @@ + + #ifdef CONFIG_IEEE80211W + #ifdef NEED_AP_MLME +-@@ -1199,6 +1263,10 @@ static void hostapd_ctrl_iface_receive(i +- reply_len += res; +- } +- #endif /* CONFIG_NO_RADIUS */ ++@@ -1546,6 +1610,10 @@ static void hostapd_ctrl_iface_receive(i ++ } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { ++ reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, ++ reply_size); + + } else if (os_strcmp(buf, "DOWN") == 0) { + + hostapd_ctrl_iface_set_down(hapd); + + } else if (os_strncmp(buf, "UPDATE ", 7) == 0) { + + hostapd_ctrl_iface_update(hapd, buf + 7); +- } else if (os_strcmp(buf, "STA-FIRST") == 0) { +- reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, +- reply_size); ++ ++ } else { ++ os_memcpy(reply, "UNKNOWN COMMAND\n", 16); +diff --git a/package/hostapd/patches/370-ap_sta_support.patch b/package/hostapd/patches/370-ap_sta_support.patch +index a3d0572..5e82252 100644 +--- a/package/hostapd/patches/370-ap_sta_support.patch ++++ b/package/hostapd/patches/370-ap_sta_support.patch +@@ -1,6 +1,6 @@ + --- a/wpa_supplicant/wpa_supplicant_i.h + +++ b/wpa_supplicant/wpa_supplicant_i.h +-@@ -96,6 +96,11 @@ struct wpa_interface { ++@@ -108,6 +108,11 @@ struct wpa_interface { + const char *ifname; + + /** +@@ -12,7 +12,7 @@ + * bridge_ifname - Optional bridge interface name + * + * If the driver interface (ifname) is included in a Linux bridge +-@@ -325,6 +330,8 @@ struct wpa_supplicant { ++@@ -395,6 +400,8 @@ struct wpa_supplicant { + #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ + char bridge_ifname[16]; + +@@ -20,12 +20,12 @@ + + + char *confname; + char *confanother; +- struct wpa_config *conf; ++ + --- a/wpa_supplicant/Makefile + +++ b/wpa_supplicant/Makefile + @@ -13,6 +13,10 @@ PKG_CONFIG ?= pkg-config +- CFLAGS += -I../src +- CFLAGS += -I../src/utils ++ CFLAGS += -I$(abspath ../src) ++ CFLAGS += -I$(abspath ../src/utils) + + +ifdef MULTICALL + +CFLAGS += -DMULTICALL +@@ -34,7 +34,7 @@ + -include .config + -include $(if $(MULTICALL),../hostapd/.config) + +-@@ -76,6 +80,8 @@ OBJS_c = wpa_cli.o ../src/common/wpa_ctr ++@@ -82,6 +86,8 @@ OBJS_c = wpa_cli.o ../src/common/wpa_ctr + OBJS_c += ../src/utils/wpa_debug.o + OBJS_c += ../src/utils/common.o + +@@ -45,9 +45,9 @@ + CONFIG_OS=win32 + --- a/wpa_supplicant/wpa_supplicant.c + +++ b/wpa_supplicant/wpa_supplicant.c +-@@ -109,6 +109,46 @@ extern int wpa_debug_show_keys; +- extern int wpa_debug_timestamp; +- extern struct wpa_driver_ops *wpa_drivers[]; ++@@ -104,6 +104,46 @@ const char *wpa_supplicant_full_license5 ++ "\n"; ++ #endif /* CONFIG_NO_STDOUT_DEBUG */ + + +static int hostapd_stop(struct wpa_supplicant *wpa_s) + +{ +@@ -92,7 +92,7 @@ + /* Configure default/group WEP keys for static WEP */ + int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) + { +-@@ -685,8 +725,12 @@ void wpa_supplicant_set_state(struct wpa ++@@ -705,8 +745,12 @@ void wpa_supplicant_set_state(struct wpa + #endif /* CONFIG_P2P */ + + sme_sched_obss_scan(wpa_s, 1); +@@ -105,7 +105,7 @@ + wpa_s->new_connection = 1; + wpa_drv_set_operstate(wpa_s, 0); + #ifndef IEEE8021X_EAPOL +-@@ -2906,6 +2950,20 @@ static int wpa_supplicant_init_iface(str ++@@ -3516,6 +3560,20 @@ static int wpa_supplicant_init_iface(str + sizeof(wpa_s->bridge_ifname)); + } + +@@ -126,7 +126,7 @@ + /* RSNA Supplicant Key Management - INITIALIZE */ + eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, FALSE); +-@@ -3125,6 +3183,11 @@ static void wpa_supplicant_deinit_iface( ++@@ -3711,6 +3769,11 @@ static void wpa_supplicant_deinit_iface( + if (terminate) + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); + +@@ -148,9 +148,9 @@ + #include "drivers/driver.h" + #include "wpa_supplicant_i.h" + #include "config.h" +-@@ -245,6 +246,9 @@ static void calculate_update_time(const ++@@ -247,6 +248,9 @@ static void calculate_update_time(const + static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src, +- struct os_time *fetch_time) ++ struct os_reltime *fetch_time) + { + + struct ieee80211_ht_capabilities *capab; + + struct ieee802_11_elems elems; +@@ -158,7 +158,7 @@ + dst->flags = src->flags; + os_memcpy(dst->bssid, src->bssid, ETH_ALEN); + dst->freq = src->freq; +-@@ -255,6 +259,12 @@ static void wpa_bss_copy_res(struct wpa_ ++@@ -257,6 +261,12 @@ static void wpa_bss_copy_res(struct wpa_ + dst->level = src->level; + dst->tsf = src->tsf; + +@@ -173,16 +173,16 @@ + + --- a/wpa_supplicant/main.c + +++ b/wpa_supplicant/main.c +-@@ -27,7 +27,7 @@ static void usage(void) +- " wpa_supplicant [-BddhKLqqstuvW] [-P] " ++@@ -33,7 +33,7 @@ static void usage(void) ++ "vW] [-P] " + "[-g] \\\n" + " [-G] \\\n" + - " -i -c [-C] [-D] " + + " -i -c [-C] [-D] [-H] " + "[-p] \\\n" +- " [-b] [-f] [-e] " +- "\\\n" +-@@ -72,6 +72,7 @@ static void usage(void) ++ " [-b] [-e]" ++ #ifdef CONFIG_DEBUG_FILE ++@@ -84,6 +84,7 @@ static void usage(void) + #endif /* CONFIG_DEBUG_LINUX_TRACING */ + printf(" -t = include timestamp in debug messages\n" + " -h = show this help text\n" +@@ -190,16 +190,16 @@ + " -L = show license (BSD)\n" + " -o = override driver parameter for new interfaces\n" + " -O = override ctrl_interface parameter for new interfaces\n" +-@@ -160,7 +161,7 @@ int main(int argc, char *argv[]) ++@@ -175,7 +176,7 @@ int main(int argc, char *argv[]) + + for (;;) { + c = getopt(argc, argv, +-- "b:Bc:C:D:de:f:g:G:hi:I:KLNo:O:p:P:qsTtuvW"); +-+ "b:Bc:C:D:de:f:g:G:hH:i:I:KLNo:O:p:P:qsTtuvW"); ++- "b:Bc:C:D:de:f:g:G:hi:I:KLm:No:O:p:P:qsTtuvW"); +++ "b:Bc:C:D:de:f:g:G:hH:i:I:KLm:No:O:p:P:qsTtuvW"); + if (c < 0) + break; + switch (c) { +-@@ -207,6 +208,9 @@ int main(int argc, char *argv[]) ++@@ -222,6 +223,9 @@ int main(int argc, char *argv[]) + usage(); + exitcode = 0; + goto out; +@@ -211,7 +211,7 @@ + break; + --- a/wpa_supplicant/bss.h + +++ b/wpa_supplicant/bss.h +-@@ -69,6 +69,8 @@ struct wpa_bss { ++@@ -70,6 +70,8 @@ struct wpa_bss { + u8 ssid[32]; + /** Length of SSID */ + size_t ssid_len; +diff --git a/package/hostapd/patches/380-disable_ctrl_iface_mib.patch b/package/hostapd/patches/380-disable_ctrl_iface_mib.patch +index 27f21bd..d39ba2e 100644 +--- a/package/hostapd/patches/380-disable_ctrl_iface_mib.patch ++++ b/package/hostapd/patches/380-disable_ctrl_iface_mib.patch +@@ -1,6 +1,6 @@ + --- a/hostapd/Makefile + +++ b/hostapd/Makefile +-@@ -144,6 +144,9 @@ endif ++@@ -163,6 +163,9 @@ endif + ifdef CONFIG_NO_CTRL_IFACE + CFLAGS += -DCONFIG_NO_CTRL_IFACE + else +@@ -12,28 +12,15 @@ + endif + --- a/hostapd/ctrl_iface.c + +++ b/hostapd/ctrl_iface.c +-@@ -1234,6 +1234,7 @@ static void hostapd_ctrl_iface_receive(i +- } else if (os_strcmp(buf, "STATUS") == 0) { +- reply_len = hostapd_ctrl_iface_status(hapd, reply, ++@@ -1447,6 +1447,7 @@ static void hostapd_ctrl_iface_receive(i + reply_size); ++ } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { ++ reply_len = hostapd_drv_status(hapd, reply, reply_size); + +#ifdef CONFIG_CTRL_IFACE_MIB + } else if (os_strcmp(buf, "MIB") == 0) { + reply_len = ieee802_11_get_mib(hapd, reply, reply_size); + if (reply_len >= 0) { +-@@ -1263,10 +1264,12 @@ static void hostapd_ctrl_iface_receive(i +- reply_len += res; +- } +- #endif /* CONFIG_NO_RADIUS */ +-+#endif +- } else if (os_strcmp(buf, "DOWN") == 0) { +- hostapd_ctrl_iface_set_down(hapd); +- } else if (os_strncmp(buf, "UPDATE ", 7) == 0) { +- hostapd_ctrl_iface_update(hapd, buf + 7); +-+#ifdef CONFIG_CTRL_IFACE_MIB +- } else if (os_strcmp(buf, "STA-FIRST") == 0) { +- reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, +- reply_size); +-@@ -1276,6 +1279,7 @@ static void hostapd_ctrl_iface_receive(i ++@@ -1488,6 +1489,7 @@ static void hostapd_ctrl_iface_receive(i + } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { + reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, + reply_size); +@@ -43,7 +30,7 @@ + reply_len = -1; + --- a/wpa_supplicant/Makefile + +++ b/wpa_supplicant/Makefile +-@@ -778,6 +778,9 @@ ifdef CONFIG_WNM ++@@ -797,6 +797,9 @@ ifdef CONFIG_WNM + OBJS += ../src/ap/wnm_ap.o + endif + ifdef CONFIG_CTRL_IFACE +@@ -55,7 +42,7 @@ + + --- a/wpa_supplicant/ctrl_iface.c + +++ b/wpa_supplicant/ctrl_iface.c +-@@ -5262,6 +5262,7 @@ char * wpa_supplicant_ctrl_iface_process ++@@ -6075,6 +6075,7 @@ char * wpa_supplicant_ctrl_iface_process + reply_len = -1; + } else if (os_strncmp(buf, "NOTE ", 5) == 0) { + wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); +@@ -63,7 +50,7 @@ + } else if (os_strcmp(buf, "MIB") == 0) { + reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); + if (reply_len >= 0) { +-@@ -5273,6 +5274,7 @@ char * wpa_supplicant_ctrl_iface_process ++@@ -6086,6 +6087,7 @@ char * wpa_supplicant_ctrl_iface_process + else + reply_len += res; + } +@@ -71,7 +58,7 @@ + } else if (os_strncmp(buf, "STATUS", 6) == 0) { + reply_len = wpa_supplicant_ctrl_iface_status( + wpa_s, buf + 6, reply, reply_size); +-@@ -5687,6 +5689,7 @@ char * wpa_supplicant_ctrl_iface_process ++@@ -6490,6 +6492,7 @@ char * wpa_supplicant_ctrl_iface_process + reply_len = wpa_supplicant_ctrl_iface_bss( + wpa_s, buf + 4, reply, reply_size); + #ifdef CONFIG_AP +@@ -79,7 +66,7 @@ + } else if (os_strcmp(buf, "STA-FIRST") == 0) { + reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); + } else if (os_strncmp(buf, "STA ", 4) == 0) { +-@@ -5695,6 +5698,7 @@ char * wpa_supplicant_ctrl_iface_process ++@@ -6498,6 +6501,7 @@ char * wpa_supplicant_ctrl_iface_process + } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { + reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, + reply_size); +@@ -89,15 +76,15 @@ + reply_len = -1; + --- a/src/ap/ctrl_iface_ap.c + +++ b/src/ap/ctrl_iface_ap.c +-@@ -20,6 +20,7 @@ ++@@ -21,6 +21,7 @@ + #include "ctrl_iface_ap.h" + #include "ap_drv_ops.h" + + +#ifdef CONFIG_CTRL_IFACE_MIB + +- static int hostapd_get_sta_conn_time(struct sta_info *sta, +- char *buf, size_t buflen) +-@@ -129,6 +130,7 @@ int hostapd_ctrl_iface_sta_next(struct h ++ static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd, ++ struct sta_info *sta, ++@@ -214,6 +215,7 @@ int hostapd_ctrl_iface_sta_next(struct h + return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); + } + +@@ -105,14 +92,14 @@ + + #ifdef CONFIG_P2P_MANAGER + static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, +-@@ -423,3 +425,4 @@ int hostapd_parse_csa_settings(const cha ++@@ -524,3 +526,4 @@ int hostapd_parse_csa_settings(const cha + + return 0; + } + + + --- a/src/ap/ieee802_1x.c + +++ b/src/ap/ieee802_1x.c +-@@ -1938,6 +1938,7 @@ static const char * bool_txt(Boolean boo ++@@ -2124,6 +2124,7 @@ static const char * bool_txt(Boolean boo + return bool_val ? "TRUE" : "FALSE"; + } + +@@ -120,17 +107,17 @@ + + int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) + { +-@@ -2090,6 +2091,7 @@ int ieee802_1x_get_mib_sta(struct hostap ++@@ -2291,6 +2292,7 @@ int ieee802_1x_get_mib_sta(struct hostap + return len; + } + + +#endif + + static void ieee802_1x_finished(struct hostapd_data *hapd, +- struct sta_info *sta, int success) ++ struct sta_info *sta, int success, + --- a/src/ap/wpa_auth.c + +++ b/src/ap/wpa_auth.c +-@@ -2708,6 +2708,7 @@ static const char * wpa_bool_txt(int boo ++@@ -2830,6 +2830,7 @@ static const char * wpa_bool_txt(int boo + return bool ? "TRUE" : "FALSE"; + } + +@@ -138,7 +125,7 @@ + + #define RSN_SUITE "%02x-%02x-%02x-%d" + #define RSN_SUITE_ARG(s) \ +-@@ -2852,7 +2853,7 @@ int wpa_get_mib_sta(struct wpa_state_mac ++@@ -2974,7 +2975,7 @@ int wpa_get_mib_sta(struct wpa_state_mac + + return len; + } +@@ -149,7 +136,7 @@ + { + --- a/src/rsn_supp/wpa.c + +++ b/src/rsn_supp/wpa.c +-@@ -1844,6 +1844,8 @@ static u32 wpa_key_mgmt_suite(struct wpa ++@@ -1912,6 +1912,8 @@ static u32 wpa_key_mgmt_suite(struct wpa + } + + +@@ -158,7 +145,7 @@ + #define RSN_SUITE "%02x-%02x-%02x-%d" + #define RSN_SUITE_ARG(s) \ + ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff +-@@ -1927,6 +1929,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch ++@@ -1995,6 +1997,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch + + return (int) len; + } +diff --git a/package/hostapd/patches/390-wpa_ie_cap_workaround.patch b/package/hostapd/patches/390-wpa_ie_cap_workaround.patch +index 00a3222..40148fc 100644 +--- a/package/hostapd/patches/390-wpa_ie_cap_workaround.patch ++++ b/package/hostapd/patches/390-wpa_ie_cap_workaround.patch +@@ -1,6 +1,6 @@ + --- a/src/common/wpa_common.c + +++ b/src/common/wpa_common.c +-@@ -959,6 +959,31 @@ const char * wpa_key_mgmt_txt(int key_mg ++@@ -1002,6 +1002,31 @@ const char * wpa_key_mgmt_txt(int key_mg + } + + +@@ -32,7 +32,7 @@ + int wpa_compare_rsn_ie(int ft_initial_assoc, + const u8 *ie1, size_t ie1len, + const u8 *ie2, size_t ie2len) +-@@ -966,8 +991,19 @@ int wpa_compare_rsn_ie(int ft_initial_as ++@@ -1009,8 +1034,19 @@ int wpa_compare_rsn_ie(int ft_initial_as + if (ie1 == NULL || ie2 == NULL) + return -1; + +diff --git a/package/hostapd/patches/400-terminate_on_setup_failure.patch b/package/hostapd/patches/400-terminate_on_setup_failure.patch +deleted file mode 100644 +index 0d9065a..0000000 +--- a/package/hostapd/patches/400-terminate_on_setup_failure.patch ++++ /dev/null +@@ -1,85 +0,0 @@ +---- a/src/ap/hostapd.c +-+++ b/src/ap/hostapd.c +-@@ -1103,13 +1103,8 @@ int hostapd_setup_interface_complete(str +- size_t j; +- u8 *prev_addr; +- +-- if (err) { +-- wpa_printf(MSG_ERROR, "Interface initialization failed"); +-- hostapd_set_state(iface, HAPD_IFACE_DISABLED); +-- if (iface->interfaces && iface->interfaces->terminate_on_error) +-- eloop_terminate(); +-- return -1; +-- } +-+ if (err) +-+ goto error; +- +- wpa_printf(MSG_DEBUG, "Completing interface initialization"); +- if (iface->conf->channel) { +-@@ -1140,7 +1135,7 @@ int hostapd_setup_interface_complete(str +- hapd->iconf->vht_oper_centr_freq_seg1_idx)) { +- wpa_printf(MSG_ERROR, "Could not set channel for " +- "kernel driver"); +-- return -1; +-+ goto error; +- } +- } +- +-@@ -1151,7 +1146,7 @@ int hostapd_setup_interface_complete(str +- hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, +- HOSTAPD_LEVEL_WARNING, +- "Failed to prepare rates table."); +-- return -1; +-+ goto error; +- } +- } +- +-@@ -1159,14 +1154,14 @@ int hostapd_setup_interface_complete(str +- hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { +- wpa_printf(MSG_ERROR, "Could not set RTS threshold for " +- "kernel driver"); +-- return -1; +-+ goto error; +- } +- +- if (hapd->iconf->fragm_threshold > -1 && +- hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { +- wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " +- "for kernel driver"); +-- return -1; +-+ goto error; +- } +- +- prev_addr = hapd->own_addr; +-@@ -1176,7 +1171,7 @@ int hostapd_setup_interface_complete(str +- if (j) +- os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); +- if (hostapd_setup_bss(hapd, j == 0)) +-- return -1; +-+ goto error; +- if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) +- prev_addr = hapd->own_addr; +- } +-@@ -1191,7 +1186,7 @@ int hostapd_setup_interface_complete(str +- if (hostapd_driver_commit(hapd) < 0) { +- wpa_printf(MSG_ERROR, "%s: Failed to commit driver " +- "configuration", __func__); +-- return -1; +-+ goto error; +- } +- +- /* +-@@ -1216,6 +1211,13 @@ int hostapd_setup_interface_complete(str +- iface->interfaces->terminate_on_error--; +- +- return 0; +-+ +-+error: +-+ wpa_printf(MSG_ERROR, "Interface initialization failed"); +-+ hostapd_set_state(iface, HAPD_IFACE_DISABLED); +-+ if (iface->interfaces && iface->interfaces->terminate_on_error) +-+ eloop_terminate(); +-+ return -1; +- } +- +- +diff --git a/package/hostapd/patches/410-bring_down_interface.patch b/package/hostapd/patches/410-bring_down_interface.patch +index 31033a0..5a57249 100644 +--- a/package/hostapd/patches/410-bring_down_interface.patch ++++ b/package/hostapd/patches/410-bring_down_interface.patch +@@ -1,6 +1,6 @@ + --- a/src/drivers/driver_nl80211.c + +++ b/src/drivers/driver_nl80211.c +-@@ -8480,12 +8480,7 @@ static int wpa_driver_nl80211_set_mode(s ++@@ -8936,12 +8936,7 @@ static int wpa_driver_nl80211_set_mode(s + /* Try to set the mode again while the interface is + * down */ + ret = nl80211_set_mode(drv, drv->ifindex, nlmode); +@@ -14,7 +14,7 @@ + break; + } else + wpa_printf(MSG_DEBUG, "nl80211: Failed to set " +-@@ -8498,6 +8493,8 @@ static int wpa_driver_nl80211_set_mode(s ++@@ -8954,6 +8949,8 @@ static int wpa_driver_nl80211_set_mode(s + "interface is down"); + drv->nlmode = nlmode; + drv->ignore_if_down_event = 1; +diff --git a/package/hostapd/patches/420-fix_wps_pin_crash.patch b/package/hostapd/patches/420-fix_wps_pin_crash.patch +index 130bd53..31995c4 100644 +--- a/package/hostapd/patches/420-fix_wps_pin_crash.patch ++++ b/package/hostapd/patches/420-fix_wps_pin_crash.patch +@@ -1,6 +1,6 @@ + --- a/hostapd/ctrl_iface.c + +++ b/hostapd/ctrl_iface.c +-@@ -480,6 +480,9 @@ static int hostapd_ctrl_iface_wps_ap_pin ++@@ -540,6 +540,9 @@ static int hostapd_ctrl_iface_wps_ap_pin + char *pos; + const char *pin_txt; + +diff --git a/package/hostapd/patches/430-wps_single_auth_enc_type.patch b/package/hostapd/patches/430-wps_single_auth_enc_type.patch +index 6e86658..8dae52b 100644 +--- a/package/hostapd/patches/430-wps_single_auth_enc_type.patch ++++ b/package/hostapd/patches/430-wps_single_auth_enc_type.patch +@@ -1,6 +1,6 @@ + --- a/src/ap/wps_hostapd.c + +++ b/src/ap/wps_hostapd.c +-@@ -1069,11 +1069,9 @@ int hostapd_init_wps(struct hostapd_data ++@@ -1051,11 +1051,9 @@ int hostapd_init_wps(struct hostapd_data + + if (conf->rsn_pairwise & WPA_CIPHER_CCMP) + wps->encr_types |= WPS_ENCR_AES; +@@ -14,7 +14,7 @@ + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) + wps->auth_types |= WPS_AUTH_WPAPSK; + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) +-@@ -1081,7 +1079,7 @@ int hostapd_init_wps(struct hostapd_data ++@@ -1063,7 +1061,7 @@ int hostapd_init_wps(struct hostapd_data + + if (conf->wpa_pairwise & WPA_CIPHER_CCMP) + wps->encr_types |= WPS_ENCR_AES; +diff --git a/package/hostapd/patches/440-dynamic_20_40_mhz.patch b/package/hostapd/patches/440-dynamic_20_40_mhz.patch +index 905ec2c..af2fb26 100644 +--- a/package/hostapd/patches/440-dynamic_20_40_mhz.patch ++++ b/package/hostapd/patches/440-dynamic_20_40_mhz.patch +@@ -1,19 +1,19 @@ + --- a/hostapd/config_file.c + +++ b/hostapd/config_file.c +-@@ -2422,6 +2422,10 @@ static int hostapd_config_fill(struct ho +- "ht_capab", line); +- errors++; +- } +-+ } else if (os_strcmp(buf, "dynamic_ht40") == 0) { +-+ conf->dynamic_ht40 = atoi(pos); +-+ if (conf->dynamic_ht40 == 1) +-+ conf->dynamic_ht40 = 1500; +- } else if (os_strcmp(buf, "require_ht") == 0) { +- conf->require_ht = atoi(pos); +- } else if (os_strcmp(buf, "obss_interval") == 0) { ++@@ -2648,6 +2648,10 @@ static int hostapd_config_fill(struct ho ++ line); ++ return 1; ++ } +++ } else if (os_strcmp(buf, "dynamic_ht40") == 0) { +++ conf->dynamic_ht40 = atoi(pos); +++ if (conf->dynamic_ht40 == 1) +++ conf->dynamic_ht40 = 1500; ++ } else if (os_strcmp(buf, "require_ht") == 0) { ++ conf->require_ht = atoi(pos); ++ } else if (os_strcmp(buf, "obss_interval") == 0) { + --- a/src/ap/ap_config.h + +++ b/src/ap/ap_config.h +-@@ -531,6 +531,7 @@ struct hostapd_config { ++@@ -580,6 +580,7 @@ struct hostapd_config { + int ieee80211n; + int secondary_channel; + int require_ht; +@@ -23,7 +23,7 @@ + int ieee80211ac; + --- a/src/ap/hostapd.c + +++ b/src/ap/hostapd.c +-@@ -23,6 +23,7 @@ ++@@ -22,6 +22,7 @@ + #include "beacon.h" + #include "iapp.h" + #include "ieee802_1x.h" +@@ -31,7 +31,7 @@ + #include "ieee802_11_auth.h" + #include "vlan_init.h" + #include "wpa_auth.h" +-@@ -332,6 +333,7 @@ static void hostapd_cleanup(struct hosta ++@@ -328,6 +329,7 @@ static void hostapd_cleanup(struct hosta + static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) + { + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); +@@ -41,7 +41,7 @@ + os_free(iface->current_rates); + --- a/src/ap/hostapd.h + +++ b/src/ap/hostapd.h +-@@ -326,6 +326,9 @@ struct hostapd_iface { ++@@ -330,6 +330,9 @@ struct hostapd_iface { + /* Overlapping BSS information */ + int olbc_ht; + +@@ -53,7 +53,7 @@ + /* surveying helpers */ + --- a/src/ap/ieee802_11.c + +++ b/src/ap/ieee802_11.c +-@@ -1538,6 +1538,9 @@ static void handle_beacon(struct hostapd ++@@ -1556,6 +1556,9 @@ static void handle_beacon(struct hostapd + sizeof(mgmt->u.beacon)), &elems, + 0); + +@@ -65,7 +65,7 @@ + + --- a/src/ap/ieee802_11.h + +++ b/src/ap/ieee802_11.h +-@@ -82,4 +82,17 @@ int hostapd_update_time_adv(struct hosta ++@@ -83,4 +83,17 @@ int hostapd_update_time_adv(struct hosta + void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); + u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); + +@@ -85,8 +85,8 @@ + #endif /* IEEE802_11_H */ + --- a/src/ap/ieee802_11_ht.c + +++ b/src/ap/ieee802_11_ht.c +-@@ -20,9 +20,11 @@ +- #include "drivers/driver.h" ++@@ -13,9 +13,11 @@ ++ #include "common/ieee802_11_defs.h" + #include "hostapd.h" + #include "ap_config.h" + +#include "ap_drv_ops.h" +@@ -97,29 +97,25 @@ + + + u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) +-@@ -86,12 +88,15 @@ u8 * hostapd_eid_ht_operation(struct hos ++@@ -92,6 +94,9 @@ u8 * hostapd_eid_ht_operation(struct hos + +- oper->control_chan = hapd->iconf->channel; ++ oper->primary_chan = hapd->iconf->channel; + oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); +-- if (hapd->iconf->secondary_channel == 1) +-- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | +-- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; +-- if (hapd->iconf->secondary_channel == -1) +-- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | +-- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; +-+ +-+ if (!hapd->iface->force_20mhz) { +-+ if (hapd->iconf->secondary_channel == 1) +-+ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | +-+ HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; +-+ if (hapd->iconf->secondary_channel == -1) +-+ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | +-+ HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; +-+ } +++ if (hapd->iface->force_20mhz) +++ goto skip; +++ ++ if (hapd->iconf->secondary_channel == 1) ++ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | ++ HT_INFO_HT_PARAM_STA_CHNL_WIDTH; ++@@ -99,6 +104,7 @@ u8 * hostapd_eid_ht_operation(struct hos ++ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | ++ HT_INFO_HT_PARAM_STA_CHNL_WIDTH; + +++skip: + pos += sizeof(*oper); + +-@@ -286,3 +291,84 @@ void hostapd_get_ht_capab(struct hostapd ++ return pos; ++@@ -288,3 +294,84 @@ void hostapd_get_ht_capab(struct hostapd + + neg_ht_cap->ht_capabilities_info = host_to_le16(cap); + } +diff --git a/package/hostapd/patches/450-limit_debug_messages.patch b/package/hostapd/patches/450-limit_debug_messages.patch +index aaea941..08f17dc 100644 +--- a/package/hostapd/patches/450-limit_debug_messages.patch ++++ b/package/hostapd/patches/450-limit_debug_messages.patch +@@ -20,40 +20,41 @@ + { + size_t i; + +-@@ -375,20 +375,9 @@ static void _wpa_hexdump(int level, cons ++@@ -375,20 +375,8 @@ static void _wpa_hexdump(int level, cons + #endif /* CONFIG_ANDROID_LOG */ + } + +--void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) ++-void wpa_hexdump(int level, const char *title, const void *buf, size_t len) + -{ + - _wpa_hexdump(level, title, buf, len, 1); + -} + - + - +--void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) ++-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) + -{ + - _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); + -} +- + - +--static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, ++- ++-static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, + - size_t len, int show) +-+void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, +++void _wpa_hexdump_ascii(int level, const char *title, const void *buf, + + size_t len, int show) + { + size_t i, llen; + const u8 *pos = buf; +-@@ -495,19 +484,6 @@ static void _wpa_hexdump_ascii(int level ++@@ -495,20 +483,6 @@ static void _wpa_hexdump_ascii(int level + } + + +--void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) ++-void wpa_hexdump_ascii(int level, const char *title, const void *buf, ++- size_t len) + -{ + - _wpa_hexdump_ascii(level, title, buf, len, 1); + -} + - + - +--void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, ++-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, + - size_t len) + -{ + - _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); +@@ -63,7 +64,7 @@ + #ifdef CONFIG_DEBUG_FILE + static char *last_path = NULL; + #endif /* CONFIG_DEBUG_FILE */ +-@@ -591,7 +567,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_ ++@@ -592,7 +566,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_ + } + + +@@ -72,7 +73,7 @@ + { + va_list ap; + char *buf; +-@@ -625,7 +601,7 @@ void wpa_msg(void *ctx, int level, const ++@@ -630,7 +604,7 @@ void wpa_msg(void *ctx, int level, const + } + + +@@ -83,14 +84,14 @@ + char *buf; + --- a/src/utils/wpa_debug.h + +++ b/src/utils/wpa_debug.h +-@@ -43,6 +43,17 @@ int wpa_debug_open_file(const char *path ++@@ -47,6 +47,17 @@ int wpa_debug_open_file(const char *path + int wpa_debug_reopen_file(void); + void wpa_debug_close_file(void); + + +/* internal */ + +void _wpa_hexdump(int level, const char *title, const u8 *buf, + + size_t len, int show); +-+void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, +++void _wpa_hexdump_ascii(int level, const char *title, const void *buf, + + size_t len, int show); + +extern int wpa_debug_show_keys; + + +@@ -101,7 +102,7 @@ + /** + * wpa_debug_printf_timestamp - Print timestamp for debug output + * +-@@ -63,9 +74,15 @@ void wpa_debug_print_timestamp(void); ++@@ -67,9 +78,15 @@ void wpa_debug_print_timestamp(void); + * + * Note: New line '\n' is added to the end of the text when printing to stdout. + */ +@@ -118,11 +119,11 @@ + /** + * wpa_hexdump - conditional hex dump + * @level: priority level (MSG_*) of the message +-@@ -77,7 +94,13 @@ PRINTF_FORMAT(2, 3); ++@@ -81,7 +98,13 @@ PRINTF_FORMAT(2, 3); + * output may be directed to stdout, stderr, and/or syslog based on + * configuration. The contents of buf is printed out has hex dump. + */ +--void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len); ++-void wpa_hexdump(int level, const char *title, const void *buf, size_t len); + +static inline void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) + +{ + + if (level < CONFIG_MSG_MIN_PRIORITY) +@@ -133,11 +134,11 @@ + + static inline void wpa_hexdump_buf(int level, const char *title, + const struct wpabuf *buf) +-@@ -99,7 +122,13 @@ static inline void wpa_hexdump_buf(int l ++@@ -103,7 +126,13 @@ static inline void wpa_hexdump_buf(int l + * like wpa_hexdump(), but by default, does not include secret keys (passwords, + * etc.) in debug output. + */ +--void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len); ++-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len); + +static inline void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) + +{ + + if (level < CONFIG_MSG_MIN_PRIORITY) +@@ -148,11 +149,11 @@ + + static inline void wpa_hexdump_buf_key(int level, const char *title, + const struct wpabuf *buf) +-@@ -121,8 +150,14 @@ static inline void wpa_hexdump_buf_key(i ++@@ -125,8 +154,14 @@ static inline void wpa_hexdump_buf_key(i + * the hex numbers and ASCII characters (for printable range) are shown. 16 + * bytes per line will be shown. + */ +--void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, ++-void wpa_hexdump_ascii(int level, const char *title, const void *buf, + - size_t len); + +static inline void wpa_hexdump_ascii(int level, const char *title, + + const u8 *buf, size_t len) +@@ -165,11 +166,11 @@ + + /** + * wpa_hexdump_ascii_key - conditional hex dump, hide keys +-@@ -138,8 +173,14 @@ void wpa_hexdump_ascii(int level, const ++@@ -142,8 +177,14 @@ void wpa_hexdump_ascii(int level, const + * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by + * default, does not include secret keys (passwords, etc.) in debug output. + */ +--void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, ++-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, + - size_t len); + +static inline void wpa_hexdump_ascii_key(int level, const char *title, + + const u8 *buf, size_t len) +@@ -182,7 +183,7 @@ + + /* + * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce +-@@ -174,7 +215,12 @@ void wpa_hexdump_ascii_key(int level, co ++@@ -178,7 +219,12 @@ void wpa_hexdump_ascii_key(int level, co + * + * Note: New line '\n' is added to the end of the text when printing to stdout. + */ +@@ -196,7 +197,7 @@ + + /** + * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors +-@@ -188,8 +234,13 @@ void wpa_msg(void *ctx, int level, const ++@@ -192,8 +238,13 @@ void wpa_msg(void *ctx, int level, const + * attached ctrl_iface monitors. In other words, it can be used for frequent + * events that do not need to be sent to syslog. + */ +diff --git a/package/hostapd/patches/460-indicate-features.patch b/package/hostapd/patches/460-indicate-features.patch +index 7a44da1..cee3e76 100644 +--- a/package/hostapd/patches/460-indicate-features.patch ++++ b/package/hostapd/patches/460-indicate-features.patch +@@ -1,23 +1,23 @@ + --- a/hostapd/main.c + +++ b/hostapd/main.c +-@@ -14,6 +14,7 @@ +- ++@@ -15,6 +15,7 @@ + #include "utils/common.h" + #include "utils/eloop.h" ++ #include "utils/uuid.h" + +#include "utils/build_features.h" + #include "crypto/random.h" + #include "crypto/tls.h" + #include "common/version.h" +-@@ -546,7 +547,7 @@ int main(int argc, char *argv[]) ++@@ -558,7 +559,7 @@ int main(int argc, char *argv[]) + + wpa_supplicant_event = hostapd_wpa_event; + for (;;) { +-- c = getopt(argc, argv, "b:Bde:f:hKP:Ttvg:G:"); +-+ c = getopt(argc, argv, "b:Bde:f:hKP:Ttg:G:v::"); ++- c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:"); +++ c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:g:G:v::"); + if (c < 0) + break; + switch (c) { +-@@ -583,6 +584,8 @@ int main(int argc, char *argv[]) ++@@ -595,6 +596,8 @@ int main(int argc, char *argv[]) + break; + #endif /* CONFIG_DEBUG_LINUX_TRACING */ + case 'v': +@@ -36,16 +36,16 @@ + #include "wpa_supplicant_i.h" + #include "driver_i.h" + #include "p2p_supplicant.h" +-@@ -161,7 +162,7 @@ int main(int argc, char *argv[]) ++@@ -176,7 +177,7 @@ int main(int argc, char *argv[]) + + for (;;) { + c = getopt(argc, argv, +-- "b:Bc:C:D:de:f:g:G:hH:i:I:KLNo:O:p:P:qsTtuvW"); +-+ "b:Bc:C:D:de:f:g:G:hH:i:I:KLNo:O:p:P:qsTtuv::W"); ++- "b:Bc:C:D:de:f:g:G:hH:i:I:KLm:No:O:p:P:qsTtuvW"); +++ "b:Bc:C:D:de:f:g:G:hH:i:I:KLm:No:O:p:P:qsTtuv::W"); + if (c < 0) + break; + switch (c) { +-@@ -259,8 +260,12 @@ int main(int argc, char *argv[]) ++@@ -279,8 +280,12 @@ int main(int argc, char *argv[]) + break; + #endif /* CONFIG_DBUS */ + case 'v': +diff --git a/package/hostapd/patches/470-hostapd_cli_ifdef.patch b/package/hostapd/patches/470-hostapd_cli_ifdef.patch +index 5ac0fdd..d4a0f12 100644 +--- a/package/hostapd/patches/470-hostapd_cli_ifdef.patch ++++ b/package/hostapd/patches/470-hostapd_cli_ifdef.patch +@@ -16,7 +16,7 @@ + " get_config show current configuration\n" + " help show this usage help\n" + " interface [ifname] show interfaces/select interface\n" +-@@ -352,7 +350,6 @@ static int hostapd_cli_cmd_sa_query(stru ++@@ -362,7 +360,6 @@ static int hostapd_cli_cmd_sa_query(stru + #endif /* CONFIG_IEEE80211W */ + + +@@ -24,7 +24,7 @@ + static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, + char *argv[]) + { +-@@ -578,7 +575,6 @@ static int hostapd_cli_cmd_wps_config(st ++@@ -588,7 +585,6 @@ static int hostapd_cli_cmd_wps_config(st + ssid_hex, argv[1]); + return wpa_ctrl_command(ctrl, buf); + } +@@ -32,7 +32,7 @@ + + + static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, +-@@ -903,7 +899,6 @@ static struct hostapd_cli_cmd hostapd_cl ++@@ -979,7 +975,6 @@ static struct hostapd_cli_cmd hostapd_cl + #ifdef CONFIG_IEEE80211W + { "sa_query", hostapd_cli_cmd_sa_query }, + #endif /* CONFIG_IEEE80211W */ +@@ -40,7 +40,7 @@ + { "wps_pin", hostapd_cli_cmd_wps_pin }, + { "wps_check_pin", hostapd_cli_cmd_wps_check_pin }, + { "wps_pbc", hostapd_cli_cmd_wps_pbc }, +-@@ -917,7 +912,6 @@ static struct hostapd_cli_cmd hostapd_cl ++@@ -993,7 +988,6 @@ static struct hostapd_cli_cmd hostapd_cl + { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin }, + { "wps_config", hostapd_cli_cmd_wps_config }, + { "wps_get_status", hostapd_cli_cmd_wps_get_status }, +diff --git a/package/hostapd/patches/471-wpa_cli_ifdef.patch b/package/hostapd/patches/471-wpa_cli_ifdef.patch +index cc84444..36b5a44 100644 +--- a/package/hostapd/patches/471-wpa_cli_ifdef.patch ++++ b/package/hostapd/patches/471-wpa_cli_ifdef.patch +@@ -10,4 +10,4 @@ + + + static const char *wpa_cli_version = + "wpa_cli v" VERSION_STR "\n" +- "Copyright (c) 2004-2013, Jouni Malinen and contributors"; ++ "Copyright (c) 2004-2014, Jouni Malinen and contributors"; +diff --git a/package/hostapd/patches/480-max_num_sta_probe.patch b/package/hostapd/patches/480-max_num_sta_probe.patch +index e5ca8b4..e238bf4 100644 +--- a/package/hostapd/patches/480-max_num_sta_probe.patch ++++ b/package/hostapd/patches/480-max_num_sta_probe.patch +@@ -1,6 +1,6 @@ + --- a/src/ap/beacon.c + +++ b/src/ap/beacon.c +-@@ -501,6 +501,10 @@ void handle_probe_req(struct hostapd_dat ++@@ -599,6 +599,10 @@ void handle_probe_req(struct hostapd_dat + return; + } + +@@ -9,5 +9,5 @@ + + " too many connected stations.", MAC2STR(mgmt->sa)); + + + #ifdef CONFIG_INTERWORKING +- if (elems.interworking && elems.interworking_len >= 1) { +- u8 ant = elems.interworking[0] & 0x0f; ++ if (hapd->conf->interworking && ++ elems.interworking && elems.interworking_len >= 1) { +diff --git a/package/hostapd/patches/490-scan_wait.patch b/package/hostapd/patches/490-scan_wait.patch +index 61715d6..3459a61 100644 +--- a/package/hostapd/patches/490-scan_wait.patch ++++ b/package/hostapd/patches/490-scan_wait.patch +@@ -1,15 +1,15 @@ + --- a/hostapd/main.c + +++ b/hostapd/main.c +-@@ -33,6 +33,8 @@ +- extern int wpa_debug_level; +- extern int wpa_debug_show_keys; +- extern int wpa_debug_timestamp; ++@@ -36,6 +36,8 @@ struct hapd_global { ++ }; ++ ++ static struct hapd_global global; + +static int daemonize = 0; + +static char *pid_file = NULL; + +- extern struct wpa_driver_ops *wpa_drivers[]; + +-@@ -147,6 +149,14 @@ static void hostapd_logger_cb(void *ctx, ++ #ifndef CONFIG_NO_HOSTAPD_LOGGER ++@@ -141,6 +143,14 @@ static void hostapd_logger_cb(void *ctx, + } + #endif /* CONFIG_NO_HOSTAPD_LOGGER */ + +@@ -24,7 +24,7 @@ + + /** + * hostapd_driver_init - Preparate driver interface +-@@ -165,6 +175,8 @@ static int hostapd_driver_init(struct ho ++@@ -159,6 +169,8 @@ static int hostapd_driver_init(struct ho + return -1; + } + +@@ -33,7 +33,7 @@ + /* Initialize the driver interface */ + if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) + b = NULL; +-@@ -381,8 +393,6 @@ static void hostapd_global_deinit(const ++@@ -372,8 +384,6 @@ static void hostapd_global_deinit(const + #endif /* CONFIG_NATIVE_WINDOWS */ + + eap_server_unregister_methods(); +@@ -42,7 +42,7 @@ + } + + +-@@ -408,11 +418,6 @@ static int hostapd_global_run(struct hap ++@@ -399,11 +409,6 @@ static int hostapd_global_run(struct hap + } + #endif /* EAP_SERVER_TNC */ + +@@ -54,7 +54,7 @@ + eloop_run(); + + return 0; +-@@ -521,8 +526,7 @@ int main(int argc, char *argv[]) ++@@ -533,8 +538,7 @@ int main(int argc, char *argv[]) + struct hapd_interfaces interfaces; + int ret = 1; + size_t i, j; +diff --git a/package/hostapd/patches/500-wpa_supplicant-add-new-config-params-to-be-used-with.patch b/package/hostapd/patches/500-wpa_supplicant-add-new-config-params-to-be-used-with.patch +index 544151e..5656970 100644 +--- a/package/hostapd/patches/500-wpa_supplicant-add-new-config-params-to-be-used-with.patch ++++ b/package/hostapd/patches/500-wpa_supplicant-add-new-config-params-to-be-used-with.patch +@@ -22,9 +22,9 @@ Signed-hostap: Antonio Quartulli + #include "common/defs.h" + #include "utils/list.h" + +-@@ -404,6 +405,11 @@ struct wpa_driver_associate_params { +- */ +- int freq; ++@@ -414,6 +415,11 @@ struct wpa_driver_associate_params { ++ * responsible for selecting with which BSS to associate. */ ++ const u8 *bssid; + + + int beacon_interval; + + int fixed_freq; +@@ -32,11 +32,11 @@ Signed-hostap: Antonio Quartulli + + int mcast_rate; + + + /** +- * bg_scan_period - Background scan period in seconds, 0 to disable +- * background scan, or -1 to indicate no change to default driver ++ * bssid_hint - BSSID of a proposed AP ++ * + --- a/wpa_supplicant/config.c + +++ b/wpa_supplicant/config.c +-@@ -14,6 +14,7 @@ ++@@ -15,6 +15,7 @@ + #include "rsn_supp/wpa.h" + #include "eap_peer/eap.h" + #include "p2p/p2p.h" +@@ -44,7 +44,7 @@ Signed-hostap: Antonio Quartulli + #include "config.h" + + +-@@ -1512,6 +1513,97 @@ static char * wpa_config_write_psk_list( ++@@ -1527,6 +1528,97 @@ static char * wpa_config_write_psk_list( + + #endif /* CONFIG_P2P */ + +@@ -142,7 +142,7 @@ Signed-hostap: Antonio Quartulli + /* Helper macros for network block parser */ + + #ifdef OFFSET +-@@ -1715,6 +1807,9 @@ static const struct parse_data ssid_fiel ++@@ -1733,6 +1825,9 @@ static const struct parse_data ssid_fiel + { INT(ap_max_inactivity) }, + { INT(dtim_period) }, + { INT(beacon_int) }, +@@ -162,7 +162,7 @@ Signed-hostap: Antonio Quartulli + + #define MAX_SSID_LEN 32 + +-@@ -620,6 +621,10 @@ struct wpa_ssid { ++@@ -636,6 +637,10 @@ struct wpa_ssid { + * dereferences since it may not be updated in all cases. + */ + void *parent_cred; +@@ -175,24 +175,11 @@ Signed-hostap: Antonio Quartulli + #endif /* CONFIG_SSID_H */ + --- a/wpa_supplicant/wpa_supplicant.c + +++ b/wpa_supplicant/wpa_supplicant.c +-@@ -1623,15 +1623,24 @@ void wpa_supplicant_associate(struct wpa +- params.ssid_len = ssid->ssid_len; +- } +- +-- if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set && +-- wpa_s->conf->ap_scan == 2) { +-- params.bssid = ssid->bssid; +-- params.fixed_bssid = 1; +-+ if (ssid->mode == WPAS_MODE_IBSS) { +-+ if (ssid->bssid_set && wpa_s->conf->ap_scan == 2) { +-+ params.bssid = ssid->bssid; +-+ params.fixed_bssid = 1; +-+ } +-+ if (ssid->frequency > 0 && params.freq == 0) +-+ /* Initial channel for IBSS */ +-+ params.freq = ssid->frequency; ++@@ -1791,6 +1791,13 @@ static void wpas_start_assoc_cb(struct w ++ params.beacon_int = ssid->beacon_int; ++ else ++ params.beacon_int = wpa_s->conf->beacon_int; + + params.fixed_freq = ssid->fixed_freq; +-+ params.beacon_interval = ssid->beacon_int; + + i = 0; + + while (i < NL80211_MAX_SUPP_RATES) { + + params.rates[i] = ssid->rates[i]; +@@ -201,9 +188,4 @@ Signed-hostap: Antonio Quartulli + + params.mcast_rate = ssid->mcast_rate; + } + +-- if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 && +-- params.freq == 0) +-- params.freq = ssid->frequency; /* Initial channel for IBSS */ + params.wpa_ie = wpa_ie; +- params.wpa_ie_len = wpa_ie_len; +- params.pairwise_suite = cipher_pairwise; +diff --git a/package/hostapd/patches/501-driver_nl80211-use-new-parameters-during-ibss-join.patch b/package/hostapd/patches/501-driver_nl80211-use-new-parameters-during-ibss-join.patch +index 565bbc9..c774682 100644 +--- a/package/hostapd/patches/501-driver_nl80211-use-new-parameters-during-ibss-join.patch ++++ b/package/hostapd/patches/501-driver_nl80211-use-new-parameters-during-ibss-join.patch +@@ -10,7 +10,7 @@ Signed-hostap: Antonio Quartulli + + --- a/src/drivers/driver_nl80211.c + +++ b/src/drivers/driver_nl80211.c +-@@ -7903,7 +7903,7 @@ static int wpa_driver_nl80211_ibss(struc ++@@ -8455,7 +8455,7 @@ static int wpa_driver_nl80211_ibss(struc + struct wpa_driver_associate_params *params) + { + struct nl_msg *msg; +@@ -19,9 +19,9 @@ Signed-hostap: Antonio Quartulli + int count = 0; + + wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); +-@@ -7936,6 +7936,37 @@ retry: +- wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); +- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); ++@@ -8494,6 +8494,37 @@ retry: ++ params->beacon_int); ++ } + + + if (params->fixed_freq) { + + wpa_printf(MSG_DEBUG, " * fixed_freq"); +diff --git a/package/hostapd/patches/502-wpa_s-support-htmode-param.patch b/package/hostapd/patches/502-wpa_s-support-htmode-param.patch +index adb20a2..fdba6d7 100644 +--- a/package/hostapd/patches/502-wpa_s-support-htmode-param.patch ++++ b/package/hostapd/patches/502-wpa_s-support-htmode-param.patch +@@ -16,7 +16,7 @@ Signed-off-by: Antonio Quartulli + + --- a/src/drivers/driver.h + +++ b/src/drivers/driver.h +-@@ -409,6 +409,8 @@ struct wpa_driver_associate_params { ++@@ -419,6 +419,8 @@ struct wpa_driver_associate_params { + int fixed_freq; + unsigned char rates[NL80211_MAX_SUPP_RATES]; + int mcast_rate; +@@ -24,10 +24,10 @@ Signed-off-by: Antonio Quartulli + + unsigned int htmode; + + /** +- * bg_scan_period - Background scan period in seconds, 0 to disable ++ * bssid_hint - BSSID of a proposed AP + --- a/src/drivers/driver_nl80211.c + +++ b/src/drivers/driver_nl80211.c +-@@ -7967,6 +7967,22 @@ retry: ++@@ -8525,6 +8525,22 @@ retry: + NLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate); + } + +@@ -52,7 +52,7 @@ Signed-off-by: Antonio Quartulli + goto nla_put_failure; + --- a/wpa_supplicant/config.c + +++ b/wpa_supplicant/config.c +-@@ -1544,6 +1544,71 @@ static char * wpa_config_write_mcast_rat ++@@ -1559,6 +1559,71 @@ static char * wpa_config_write_mcast_rat + } + #endif /* NO_CONFIG_WRITE */ + +@@ -124,7 +124,7 @@ Signed-off-by: Antonio Quartulli + static int wpa_config_parse_rates(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +-@@ -1810,6 +1875,7 @@ static const struct parse_data ssid_fiel ++@@ -1828,6 +1893,7 @@ static const struct parse_data ssid_fiel + { INT_RANGE(fixed_freq, 0, 1) }, + { FUNC(rates) }, + { FUNC(mcast_rate) }, +@@ -134,7 +134,7 @@ Signed-off-by: Antonio Quartulli + #undef OFFSET + --- a/wpa_supplicant/config_ssid.h + +++ b/wpa_supplicant/config_ssid.h +-@@ -625,6 +625,8 @@ struct wpa_ssid { ++@@ -641,6 +641,8 @@ struct wpa_ssid { + int fixed_freq; + unsigned char rates[NL80211_MAX_SUPP_RATES]; + double mcast_rate; +@@ -145,7 +145,7 @@ Signed-off-by: Antonio Quartulli + #endif /* CONFIG_SSID_H */ + --- a/wpa_supplicant/wpa_supplicant.c + +++ b/wpa_supplicant/wpa_supplicant.c +-@@ -1639,6 +1639,8 @@ void wpa_supplicant_associate(struct wpa ++@@ -1798,6 +1798,8 @@ static void wpas_start_assoc_cb(struct w + i++; + } + params.mcast_rate = ssid->mcast_rate; +diff --git a/package/hostapd/patches/510-wpa_supplicant_p2p_parse_ifcomb.patch b/package/hostapd/patches/510-wpa_supplicant_p2p_parse_ifcomb.patch +deleted file mode 100644 +index fe72ee2..0000000 +--- a/package/hostapd/patches/510-wpa_supplicant_p2p_parse_ifcomb.patch ++++ /dev/null +@@ -1,18 +0,0 @@ +---- a/src/drivers/driver_nl80211.c +-+++ b/src/drivers/driver_nl80211.c +-@@ -3157,10 +3157,12 @@ static int wiphy_info_iface_comb_process +- } +- +- if (combination_has_p2p && combination_has_mgd) { +-- info->p2p_concurrent = 1; +-- info->num_multichan_concurrent = +-+ int num_channels = +- nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]); +-- return 1; +-+ +-+ info->p2p_concurrent = 1; +-+ if (info->num_multichan_concurrent < num_channels) +-+ info->num_multichan_concurrent = num_channels; +- } +- +- return 0; +diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile +index 9a7093c..e19f30e 100644 +--- a/package/mac80211/Makefile ++++ b/package/mac80211/Makefile +@@ -1,5 +1,5 @@ + # +-# Copyright (C) 2007-2013 OpenWrt.org ++# Copyright (C) 2007-2014 OpenWrt.org + # + # This is free software, licensed under the GNU General Public License v2. + # See /LICENSE for more information. +@@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk + + PKG_NAME:=mac80211 + +-PKG_VERSION:=2014-01-23.1 ++PKG_VERSION:=2014-03-31 + PKG_RELEASE:=1 + PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources + PKG_BACKPORT_VERSION:= +-PKG_MD5SUM:=8db16edbdaf4abc2e9c2f3b6c86736a6 ++PKG_MD5SUM:=8b5cf82d6defc5867511014af4afc0b6 + + PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2 + PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION) +@@ -105,12 +105,12 @@ Generic IEEE 802.11 Networking Stack (mac80211) + endef + + PKG_LINUX_FIRMWARE_NAME:=linux-firmware +-PKG_LINUX_FIRMWARE_VERSION:=7d0c7a8cfd78388d90cc784a185b19dcbdbce824 ++PKG_LINUX_FIRMWARE_VERSION:=f8c22c692bdee57a20b092e647464ff6176df3ed + PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION).tar.bz2 + PKG_LINUX_FIRMWARE_PROTO:=git + PKG_LINUX_FIRMWARE_SOURCE_URL:=git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git + PKG_LINUX_FIRMWARE_SUBDIR:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION) +-PKG_LINUX_FIRMWARE_MIRROR_MD5SUM:=837a1a9456c1ec8b428cc0b2b08a331b ++PKG_LINUX_FIRMWARE_MIRROR_MD5SUM:=e219333f01835c6e556875a9e0deb3f9 + + define Download/linux-firmware + FILE:=$(PKG_LINUX_FIRMWARE_SOURCE) +@@ -124,7 +124,7 @@ endef + $(eval $(call Download,linux-firmware)) + + PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware +-PKG_ATH10K_LINUX_FIRMWARE_VERSION:=d86e78e5c6be34329936c8bd73a212700437be2e ++PKG_ATH10K_LINUX_FIRMWARE_VERSION:=38eeda3ae6f90fde5546bdd48ee4ff3090f238c0 + PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2 + PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git + PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git +@@ -606,6 +606,19 @@ Atheros IEEE 802.11ac family of chipsets. For now only + PCI is supported. + endef + ++define KernelPackage/ath10k/config ++ if PACKAGE_kmod-ath10k ++ ++ config ATH10K_STA_FW ++ bool "Firmware optimized for STA operation" ++ default n ++ help ++ Use the ath10k firmware optimized for wireless client instead ++ of access point operation. ++ ++ endif ++endef ++ + define KernelPackage/carl9170 + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Atheros AR9170 USB sticks +@@ -844,6 +857,13 @@ define KernelPackage/iwlagn/config + Download and install firmware for: + Intel Centrino Advanced-N 6230, Wireless-N 1030, Wireless-N 130 and Advanced-N 6235 + ++ config IWL7260_FW ++ bool "Intel 7260 Firmware" ++ default y ++ help ++ Download and install firmware for: ++ Intel Dual Band Wireless-N 7260 and Intel Dual Band Wireless-AC 7260 ++ + config IWL100_FW + bool "Intel 100 Firmware" + default y +@@ -1639,8 +1659,7 @@ define KernelPackage/wl18xx/install + $(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-conf.bin \ +- $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw.bin \ +- $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-2.bin \ ++ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-3.bin \ + $(1)/lib/firmware/ti-connectivity + endef + +@@ -1664,10 +1683,19 @@ endef + + define KernelPackage/ath10k/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 ++ifeq ($(CONFIG_ATH10K_STA_FW),y) ++ $(INSTALL_DATA) \ ++ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \ ++ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ ++ $(INSTALL_DATA) \ ++ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \ ++ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin ++else + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \ + $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/firmware-2.bin \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ ++endif + endef + + define KernelPackage/mwl8k/install +@@ -1714,6 +1742,9 @@ endif + ifneq ($(CONFIG_IWL6030_FW),) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2b-6.ucode $(1)/lib/firmware + endif ++ifneq ($(CONFIG_IWL7260_FW),) ++ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7260-7.ucode $(1)/lib/firmware ++endif + ifneq ($(CONFIG_IWL100_FW),) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-100-5.ucode $(1)/lib/firmware + endif +diff --git a/package/mac80211/files/regdb.txt b/package/mac80211/files/regdb.txt +index 2badb21..fcab208 100644 +--- a/package/mac80211/files/regdb.txt ++++ b/package/mac80211/files/regdb.txt +@@ -1,211 +1,216 @@ + # This is the world regulatory domain + country 00: +- (2402 - 2472 @ 40), (3, 20) ++ (2402 - 2472 @ 40), (20) + # Channel 12 - 13. +- (2457 - 2482 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS ++ (2457 - 2482 @ 40), (20), NO-IR + # Channel 14. Only JP enables this and for 802.11b only +- (2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM ++ (2474 - 2494 @ 20), (20), NO-IR + # Channel 36 - 48 +- (5170 - 5250 @ 80), (3, 20) ++ (5170 - 5250 @ 80), (20), NO-IR + # NB: 5260 MHz - 5700 MHz requies DFS + # Channel 149 - 165 +- (5735 - 5835 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS ++ (5735 - 5835 @ 80), (20), NO-IR + # IEEE 802.11ad (60GHz), channels 1..3 +- (57240 - 63720 @ 2160), (N/A, 0) ++ (57240 - 63720 @ 2160), (0) + + + country AD: + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country AE: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country AL: +- (2402 - 2482 @ 20), (N/A, 20) +- +-country AM: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (N/A, 18) +- (5250 - 5330 @ 20), (N/A, 18), DFS +- +-country AN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- +-country AR: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country AE: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country AL: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20.00) ++ (5250 - 5330 @ 80), (20.00), DFS ++ (5490 - 5710 @ 80), (27.00), DFS ++ ++country AM: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (18) ++ (5250 - 5330 @ 80), (18), DFS ++ ++country AN: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country AR: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country AT: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country AU: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country AW: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- +-country AZ: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 18) +- (5250 - 5330 @ 40), (N/A, 18), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5710 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country AW: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country AZ: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (18) ++ (5250 - 5330 @ 80), (18), DFS + + country BA: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country BB: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 23) +- (5250 - 5330 @ 40), (3, 23), DFS +- (5735 - 5835 @ 40), (3, 30) ++country BB: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (23) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) + +-country BD: +- (2402 - 2482 @ 40), (N/A, 20) ++country BD: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5735 - 5835 @ 80), (30) + + country BE: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country BG: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 23) +- (5250 - 5290 @ 40), (N/A, 23), DFS +- (5490 - 5710 @ 40), (N/A, 30), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country BH: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (N/A, 20) +- (5250 - 5330 @ 20), (N/A, 20), DFS +- (5735 - 5835 @ 20), (N/A, 20) ++country BH: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5735 - 5835 @ 80), (20) + + country BL: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 18) +- (5250 - 5330 @ 40), (N/A, 18), DFS +- +-country BN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5735 - 5835 @ 40), (N/A, 30) +- +-country BO: +- (2402 - 2482 @ 40), (N/A, 30) +- (5735 - 5835 @ 40), (N/A, 30) +- +-country BR: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country BY: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- +-country BZ: +- (2402 - 2482 @ 40), (N/A, 30) +- (5735 - 5835 @ 40), (N/A, 30) +- +-country CA: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 40), (18) ++ (5250 - 5330 @ 40), (18), DFS ++ ++country BN: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5735 - 5835 @ 80), (20) ++ ++country BO: DFS-JP ++ (2402 - 2482 @ 40), (30) ++ (5735 - 5835 @ 80), (30) ++ ++country BR: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country BY: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country BZ: DFS-JP ++ (2402 - 2482 @ 40), (30) ++ (5735 - 5835 @ 80), (30) ++ ++country CA: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country CH: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS +- # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country CL: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5735 - 5835 @ 40), (N/A, 20) +- +-country CN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 80), (N/A, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ # 60 gHz band channels 1-4, ref: Etsi En 302 567 ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country CL: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5735 - 5835 @ 80), (20) ++ ++country CN: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (23) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) + # 60 gHz band channels 1,4: 28dBm, channels 2,3: 44dBm + # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf +- (57240 - 59400 @ 2160), (N/A, 28) +- (59400 - 63720 @ 2160), (N/A, 44) +- (63720 - 65880 @ 2160), (N/A, 28) +- +-country CO: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country CR: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (57240 - 59400 @ 2160), (28) ++ (59400 - 63720 @ 2160), (44) ++ (63720 - 65880 @ 2160), (28) ++ ++country CO: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country CR: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country CY: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + # Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf + # and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf + # Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is + # implemented. + country CZ: DFS-ETSI +- (2400 - 2483.5 @ 40), (N/A, 100 mW) +- (5150 - 5250 @ 80), (N/A, 200 mW), NO-OUTDOOR +- (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS +- (5470 - 5725 @ 80), (N/A, 500 mW), DFS ++ (2400 - 2483.5 @ 40), (100 mW) ++ (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR ++ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR ++ (5470 - 5725 @ 80), (500 mW), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + # Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from + # http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf +@@ -221,542 +226,555 @@ country CZ: DFS-ETSI + + country DE: DFS-ETSI + # entries 279004 and 280006 +- (2400 - 2483.5 @ 40), (N/A, 100 mW) +- # entry 303005 +- (5150 - 5250 @ 80), (N/A, 100 mW), NO-OUTDOOR +- # entries 304002 and 305002 +- (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS ++ (2400 - 2483.5 @ 40), (100 mW) ++ # entry 303005, 304002 and 305002 ++ (5150 - 5350 @ 80), (100 mW), NO-OUTDOOR + # entries 308002, 309001 and 310003 +- (5470 - 5725 @ 80), (N/A, 500 mW), DFS ++ (5470 - 5725 @ 80), (500 mW), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country DK: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS +- # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country DO: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 23), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country DZ: +- (2402 - 2482 @ 40), (N/A, 20) +- +-country EC: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ # 60 gHz band channels 1-4, ref: Etsi En 302 567 ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country DO: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country DZ: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170.000 - 5250.000 @ 80.000), (23.00) ++ (5250.000 - 5330.000 @ 80.000), (23.00), DFS ++ (5490.000 - 5670.000 @ 80.000), (23.00), DFS ++ ++country EC: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country EE: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country EG: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (N/A, 20) +- (5250 - 5330 @ 20), (N/A, 20), DFS ++country EG: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS + + country ES: DFS-ETSI +- (2400 - 2483.5 @ 40), (N/A, 100 mW) +- (5150 - 5250 @ 80), (N/A, 100 mW), NO-OUTDOOR +- (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS +- (5470 - 5725 @ 80), (N/A, 500 mW), DFS ++ (2400 - 2483.5 @ 40), (100 mW) ++ (5150 - 5250 @ 80), (100 mW), NO-OUTDOOR ++ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR ++ (5470 - 5725 @ 80), (500 mW), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country FI: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country FR: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country GE: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 18) +- (5250 - 5330 @ 40), (N/A, 18), DFS ++country GE: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (18) ++ (5250 - 5330 @ 80), (18), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country GB: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country GD: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) ++country GD: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country GR: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country GL: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (N/A, 20) +- (5250 - 5330 @ 20), (N/A, 20), DFS +- (5490 - 5710 @ 20), (N/A, 27), DFS +- +-country GT: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 23), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country GU: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country HN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country GT: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country GU: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country HN: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country HK: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5710 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country HR: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country HT: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++country HT: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + + country HU: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country ID: ++country ID: DFS-JP + # ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5815 @ 80), (N/A, 20) ++ (2402 - 2482 @ 40), (20) ++ (5735 - 5815 @ 80), (23) + + country IE: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country IL: +- (2402 - 2482 @ 40), (N/A, 20) +- (5150 - 5250 @ 80), (N/A, 200 mW), NO-OUTDOOR +- (5250 - 5350 @ 80), (N/A, 200 mW), NO-OUTDOOR, DFS ++country IL: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5150 - 5350 @ 80), (200 mW), NO-OUTDOOR + +-country IN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5735 - 5835 @ 40), (N/A, 20) ++country IN: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5735 - 5835 @ 80), (20) + + country IS: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country IR: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) ++country IR: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5735 - 5835 @ 80), (30) + + country IT: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS +- # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country JM: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country JP: +- (2402 - 2482 @ 40), (N/A, 20) +- (2474 - 2494 @ 20), (N/A, 20), NO-OFDM +- (4910 - 4990 @ 40), (N/A, 23) +- (5030 - 5090 @ 40), (N/A, 23) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 160), (N/A, 23), DFS +- +-country JO: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 18) +- +-country KE: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) +- +-country KH: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- +-country KP: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5330 @ 40), (3, 20) +- (5160 - 5250 @ 40), (3, 20), DFS +- (5490 - 5630 @ 40), (3, 30), DFS +- (5735 - 5815 @ 40), (3, 30) +- +-country KR: +- (2402 - 2482 @ 20), (N/A, 20) +- (5170 - 5250 @ 80), (3, 20) +- (5250 - 5330 @ 80), (3, 20), DFS +- (5490 - 5630 @ 80), (3, 30), DFS +- (5735 - 5815 @ 80), (3, 30) +- +-country KW: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ # 60 gHz band channels 1-4, ref: Etsi En 302 567 ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country JM: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country JP: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (2474 - 2494 @ 20), (20), NO-OFDM ++ (4910 - 4990 @ 40), (23) ++ (5030 - 5090 @ 40), (23) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 160), (23), DFS ++ ++country JO: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (23) ++ (5735 - 5835 @ 80), (23) ++ ++country KE: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (23) ++ (5490 - 5570 @ 80), (30), DFS ++ (5735 - 5775 @ 40), (23) ++ ++country KH: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country KP: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5630 @ 80), (30), DFS ++ (5735 - 5815 @ 80), (30) ++ ++country KR: DFS-JP ++ (2402 - 2482 @ 20), (20) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (30), DFS ++ (5735 - 5815 @ 80), (30) ++ ++country KW: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS + + country KZ: +- (2402 - 2482 @ 40), (N/A, 20) ++ (2402 - 2482 @ 40), (20) + +-country LB: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) ++country LB: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country LI: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- +-country LK: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (3, 17) +- (5250 - 5330 @ 20), (3, 20), DFS +- (5490 - 5710 @ 20), (3, 20), DFS +- (5735 - 5835 @ 20), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country LK: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country LT: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country LU: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country LV: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country MC: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 18) +- (5250 - 5330 @ 40), (N/A, 18), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + +-country MA: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 23) +- (5735 - 5835 @ 80), (N/A, 23) ++country MA: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS + + country MO: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 23) +- (5250 - 5330 @ 40), (3, 23), DFS +- (5735 - 5835 @ 40), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 40), (23) ++ (5250 - 5330 @ 40), (23), DFS ++ (5735 - 5835 @ 40), (30) + + country MK: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country MT: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country MY: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 17) +- (5250 - 5330 @ 80), (N/A, 23), DFS +- (5735 - 5835 @ 80), (N/A, 30) +- +-country MX: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ # 60 gHz band channels 1-4, ref: Etsi En 302 567 ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country MY: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country MX: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country NL: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20), NO-OUTDOOR +- (5250 - 5330 @ 80), (N/A, 20), NO-OUTDOOR, DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5330 @ 80), (20), NO-OUTDOOR ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country NO: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS +- # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country NP: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) +- +-country NZ: +- (2402 - 2482 @ 40), (N/A, 30) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country OM: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country PA: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 23), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country PE: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country PG: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 23), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country PH: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country PK: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ # 60 gHz band channels 1-4, ref: Etsi En 302 567 ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country NP: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5735 - 5835 @ 80), (20) ++ ++country NZ: DFS-FCC ++ (2402 - 2482 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country OM: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country PA: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country PE: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country PG: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country PH: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country PK: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5735 - 5835 @ 80), (30) + + country PL: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country PT: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country PR: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++country PR: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + +-country QA: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) ++country QA: DFS-JP ++ (2402 - 2482 @ 40), (20) ++ (5735 - 5835 @ 80), (30) + + country RO: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + + # Source: + # http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf +-country RS: +- (2400 - 2483.5 @ 40), (N/A, 100 mW) +- (5150 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR +- (5470 - 5725 @ 20), (3, 1000 mW), DFS +- # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR +- +-country RU: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5330 @ 40), (N/A, 20) +- (5650 - 5710 @ 40), (N/A, 30) +- (5735 - 5835 @ 40), (N/A, 30) +- +-country RW: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5835 @ 40), (N/A, 30) +- +-country SA: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++country RS: DFS-ETSI ++ (2400 - 2483.5 @ 40), (100 mW) ++ (5150 - 5350 @ 40), (200 mW), NO-OUTDOOR ++ (5470 - 5725 @ 20), (1000 mW), DFS ++ # 60 gHz band channels 1-4, ref: Etsi En 302 567 ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR ++ ++country RU: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5650 - 5730 @ 80), (30), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country RW: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country SA: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + + country SE: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country SG: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++country SG: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country SI: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (N/A, 20) +- (5250 - 5330 @ 40), (N/A, 20), DFS +- (5490 - 5710 @ 40), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country SK: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + +-country SV: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (3, 17) +- (5250 - 5330 @ 20), (3, 23), DFS +- (5735 - 5835 @ 20), (3, 30) ++country SV: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) + + country SY: +- (2402 - 2482 @ 40), (N/A, 20) +- +-country TW: +- (2402 - 2472 @ 40), (3, 27) +- (5270 - 5330 @ 40), (3, 17), DFS +- (5490 - 5710 @ 80), (3, 30), DFS +- (5735 - 5815 @ 80), (3, 30) +- +-country TH: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country TT: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country TN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 20), (N/A, 20) +- (5250 - 5330 @ 20), (N/A, 20), DFS ++ (2402 - 2482 @ 40), (20) ++ ++country TW: DFS-JP ++ (2402 - 2472 @ 40), (30) ++ (5270 - 5330 @ 40), (17), DFS ++ (5490 - 5590 @ 80), (30), DFS ++ (5650 - 5710 @ 40), (30), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country TH: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country TT: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country TN: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS + + country TR: DFS-ETSI +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (N/A, 20) +- (5250 - 5330 @ 80), (N/A, 20), DFS +- (5490 - 5710 @ 80), (N/A, 27), DFS ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + # Source: + # #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874 +@@ -765,59 +783,63 @@ country TR: DFS-ETSI + # Listed 5GHz range is a lowest common denominator for all related + # rules in the referenced laws. Such a range is used because of + # disputable definitions there. +-country UA: +- (2400 - 2483.5 @ 40), (N/A, 20), NO-OUTDOOR +- (5150 - 5350 @ 40), (N/A, 20), NO-OUTDOOR ++country UA: DFS-ETSI ++ (2400 - 2483.5 @ 40), (20), NO-OUTDOOR ++ (5150 - 5350 @ 40), (20), NO-OUTDOOR ++ (5490 - 5670 @ 80), (20), DFS ++ (5735 - 5835 @ 80), (20) + # 60 gHz band channels 1-4, ref: Etsi En 302 567 +- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR ++ (57240 - 65880 @ 2160), (40), NO-OUTDOOR + + country US: DFS-FCC +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5600 @ 80), (3, 24), DFS +- (5650 - 5710 @ 40), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) + # 60g band + # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255 + # channels 1,2,3, EIRP=40dBm(43dBm peak) +- (57240 - 63720 @ 2160), (N/A, 40) +- +-country UY: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country UZ: +- (2402 - 2472 @ 40), (3, 27) +- (5170 - 5250 @ 40), (3, 17) +- (5250 - 5330 @ 40), (3, 20), DFS +- (5490 - 5710 @ 40), (3, 20), DFS +- (5735 - 5835 @ 40), (3, 30) +- +-country VE: +- (2402 - 2482 @ 40), (N/A, 20) +- (5735 - 5815 @ 40), (N/A, 23) +- +-country VN: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) ++ (57240 - 63720 @ 2160), (40) ++ ++country UY: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country UZ: DFS-FCC ++ (2402 - 2472 @ 40), (30) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country VE: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (23), DFS ++ (5735 - 5835 @ 80), (30) ++ ++country VN: DFS-FCC ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (17) ++ (5250 - 5330 @ 80), (24), DFS ++ (5490 - 5730 @ 80), (24), DFS ++ (5735 - 5835 @ 80), (30) + + country YE: +- (2402 - 2482 @ 40), (N/A, 20) +- +-country ZA: +- (2402 - 2482 @ 40), (N/A, 20) +- (5170 - 5250 @ 80), (3, 17) +- (5250 - 5330 @ 80), (3, 24), DFS +- (5490 - 5710 @ 80), (3, 24), DFS +- (5735 - 5835 @ 80), (3, 30) +- +-country ZW: +- (2402 - 2482 @ 40), (N/A, 20) ++ (2402 - 2482 @ 40), (20) ++ ++country ZA: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS ++ ++country ZW: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 80), (20) ++ (5250 - 5330 @ 80), (20), DFS ++ (5490 - 5710 @ 80), (27), DFS + +diff --git a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch +index 584fb05..8d97224 100644 +--- a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch ++++ b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch +@@ -18,8 +18,8 @@ Signed-off-by: Hauke Mehrtens + + --- a/backport-include/backport/leds-disabled.h + +++ b/backport-include/backport/leds-disabled.h +-@@ -163,6 +163,19 @@ static inline void led_trigger_event(str +- enum led_brightness event) ++@@ -176,6 +176,19 @@ static inline void led_trigger_blink_one ++ int invert) + { + } + + +diff --git a/package/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch b/package/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch +new file mode 100644 +index 0000000..55bffbc +--- /dev/null ++++ b/package/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch +@@ -0,0 +1,44 @@ ++From: Luis R. Rodriguez ++Date: Wed, 23 Oct 2013 14:55:36 -0400 ++Subject: [RFC] cfg80211: make genregdb.awk skip antenna gain ++ ++Now that wireless-regdb doesn't include ++antenna gain lets skip parsing it completely ++for when CONFIG_CFG80211_INTERNAL_REGDB is ++enabled. ++ ++Signed-off-by: Luis R. Rodriguez ++--- ++ net/wireless/genregdb.awk | 11 ++++------- ++ 1 file changed, 4 insertions(+), 7 deletions(-) ++ mode change 100644 => 100755 net/wireless/genregdb.awk ++ ++--- a/net/wireless/genregdb.awk +++++ b/net/wireless/genregdb.awk ++@@ -56,14 +56,11 @@ function parse_reg_rule() ++ end = $3 ++ bw = $5 ++ sub(/\),/, "", bw) ++- gain = $6 ++- sub(/\(/, "", gain) ++- sub(/,/, "", gain) ++- power = $7 ++- sub(/\)/, "", power) +++ power = $6 +++ sub(/\(/, "", power) ++ sub(/,/, "", power) ++ # power might be in mW... ++- units = $8 +++ units = $7 ++ sub(/\)/, "", units) ++ sub(/,/, "", units) ++ dfs_cac = $9 ++@@ -86,7 +83,7 @@ function parse_reg_rule() ++ sub(/\(/, "", dfs_cac) ++ sub(/\)/, "", dfs_cac) ++ flagstr = "" ++- for (i=8; i<=NF; i++) +++ for (i=7; i<=NF; i++) ++ flagstr = flagstr $i ++ split(flagstr, flagarray, ",") ++ flags = "" +diff --git a/package/mac80211/patches/060-no_local_ssb_bcma.patch b/package/mac80211/patches/060-no_local_ssb_bcma.patch +index f4b9470..95f14f4 100644 +--- a/package/mac80211/patches/060-no_local_ssb_bcma.patch ++++ b/package/mac80211/patches/060-no_local_ssb_bcma.patch +@@ -1,6 +1,6 @@ + --- a/.local-symbols + +++ b/.local-symbols +-@@ -379,42 +379,6 @@ USB_CDC_PHONET= ++@@ -402,42 +402,6 @@ USB_CDC_PHONET= + USB_IPHETH= + USB_SIERRA_NET= + USB_VL600= +diff --git a/package/mac80211/patches/070-add-missing-header.patch b/package/mac80211/patches/070-add-missing-header.patch +new file mode 100644 +index 0000000..9307804 +--- /dev/null ++++ b/package/mac80211/patches/070-add-missing-header.patch +@@ -0,0 +1,10 @@ ++--- a/compat/backport-3.15.c +++++ b/compat/backport-3.15.c ++@@ -11,6 +11,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ /** ++ * devm_kstrdup - Allocate resource managed space and +diff --git a/package/mac80211/patches/100-revert_aes_ccm_port.patch b/package/mac80211/patches/100-revert_aes_ccm_port.patch +index 4654bc8..ac7d6b3 100644 +--- a/package/mac80211/patches/100-revert_aes_ccm_port.patch ++++ b/package/mac80211/patches/100-revert_aes_ccm_port.patch +@@ -1,3 +1,104 @@ ++--- a/net/mac80211/wpa.c +++++ b/net/mac80211/wpa.c ++@@ -301,15 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee ++ } ++ ++ ++-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) +++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, +++ int encrypted) ++ { ++ __le16 mask_fc; ++ int a4_included, mgmt; ++ u8 qos_tid; ++- u16 len_a; +++ u8 *b_0, *aad; +++ u16 data_len, len_a; ++ unsigned int hdrlen; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ +++ memset(scratch, 0, 6 * AES_BLOCK_SIZE); +++ +++ b_0 = scratch + 3 * AES_BLOCK_SIZE; +++ aad = scratch + 4 * AES_BLOCK_SIZE; +++ ++ /* ++ * Mask FC: zero subtype b4 b5 b6 (if not mgmt) ++ * Retry, PwrMgt, MoreData; set Protected ++@@ -331,21 +338,20 @@ static void ccmp_special_blocks(struct s ++ else ++ qos_tid = 0; ++ ++- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC ++- * mode authentication are not allowed to collide, yet both are derived ++- * from this vector b_0. We only set L := 1 here to indicate that the ++- * data size can be represented in (L+1) bytes. The CCM layer will take ++- * care of storing the data length in the top (L+1) bytes and setting ++- * and clearing the other bits as is required to derive the two IVs. ++- */ ++- b_0[0] = 0x1; +++ data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; +++ if (encrypted) +++ data_len -= IEEE80211_CCMP_MIC_LEN; ++ +++ /* First block, b_0 */ +++ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ ++ /* Nonce: Nonce Flags | A2 | PN ++ * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) ++ */ ++ b_0[1] = qos_tid | (mgmt << 4); ++ memcpy(&b_0[2], hdr->addr2, ETH_ALEN); ++ memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); +++ /* l(m) */ +++ put_unaligned_be16(data_len, &b_0[14]); ++ ++ /* AAD (extra authenticate-only data) / masked 802.11 header ++ * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ ++@@ -401,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8 ++ u8 *pos; ++ u8 pn[6]; ++ u64 pn64; ++- u8 aad[2 * AES_BLOCK_SIZE]; ++- u8 b_0[AES_BLOCK_SIZE]; +++ u8 scratch[6 * AES_BLOCK_SIZE]; ++ ++ if (info->control.hw_key && ++ !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && ++@@ -455,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8 ++ return 0; ++ ++ pos += IEEE80211_CCMP_HDR_LEN; ++- ccmp_special_blocks(skb, pn, b_0, aad); ++- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, ++- skb_put(skb, IEEE80211_CCMP_MIC_LEN)); +++ ccmp_special_blocks(skb, pn, scratch, 0); +++ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, +++ pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); ++ ++ return 0; ++ } ++@@ -520,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee ++ } ++ ++ if (!(status->flag & RX_FLAG_DECRYPTED)) { ++- u8 aad[2 * AES_BLOCK_SIZE]; ++- u8 b_0[AES_BLOCK_SIZE]; +++ u8 scratch[6 * AES_BLOCK_SIZE]; ++ /* hardware didn't decrypt/verify MIC */ ++- ccmp_special_blocks(skb, pn, b_0, aad); +++ ccmp_special_blocks(skb, pn, scratch, 1); ++ ++ if (ieee80211_aes_ccm_decrypt( ++- key->u.ccmp.tfm, b_0, aad, +++ key->u.ccmp.tfm, scratch, ++ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, ++ data_len, ++- skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) +++ skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, +++ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) ++ return RX_DROP_UNUSABLE; ++ } ++ + --- a/net/mac80211/Kconfig + +++ b/net/mac80211/Kconfig + @@ -5,7 +5,6 @@ config MAC80211 +@@ -244,104 +345,3 @@ + u32 replays; /* dot11RSNAStatsCCMPReplays */ + } ccmp; + struct { +---- a/net/mac80211/wpa.c +-+++ b/net/mac80211/wpa.c +-@@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee +- } +- +- +--static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, +-+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, +- int encrypted) +- { +- __le16 mask_fc; +- int a4_included, mgmt; +- u8 qos_tid; +-- u16 len_a; +-+ u8 *b_0, *aad; +-+ u16 data_len, len_a; +- unsigned int hdrlen; +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +- +-+ memset(scratch, 0, 6 * AES_BLOCK_SIZE); +-+ +-+ b_0 = scratch + 3 * AES_BLOCK_SIZE; +-+ aad = scratch + 4 * AES_BLOCK_SIZE; +-+ +- /* +- * Mask FC: zero subtype b4 b5 b6 (if not mgmt) +- * Retry, PwrMgt, MoreData; set Protected +-@@ -332,21 +338,20 @@ static void ccmp_special_blocks(struct s +- else +- qos_tid = 0; +- +-- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC +-- * mode authentication are not allowed to collide, yet both are derived +-- * from this vector b_0. We only set L := 1 here to indicate that the +-- * data size can be represented in (L+1) bytes. The CCM layer will take +-- * care of storing the data length in the top (L+1) bytes and setting +-- * and clearing the other bits as is required to derive the two IVs. +-- */ +-- b_0[0] = 0x1; +-+ data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; +-+ if (encrypted) +-+ data_len -= IEEE80211_CCMP_MIC_LEN; +- +-+ /* First block, b_0 */ +-+ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ +- /* Nonce: Nonce Flags | A2 | PN +- * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) +- */ +- b_0[1] = qos_tid | (mgmt << 4); +- memcpy(&b_0[2], hdr->addr2, ETH_ALEN); +- memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); +-+ /* l(m) */ +-+ put_unaligned_be16(data_len, &b_0[14]); +- +- /* AAD (extra authenticate-only data) / masked 802.11 header +- * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ +-@@ -402,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8 +- u8 *pos; +- u8 pn[6]; +- u64 pn64; +-- u8 aad[2 * AES_BLOCK_SIZE]; +-- u8 b_0[AES_BLOCK_SIZE]; +-+ u8 scratch[6 * AES_BLOCK_SIZE]; +- +- if (info->control.hw_key && +- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && +-@@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8 +- return 0; +- +- pos += IEEE80211_CCMP_HDR_LEN; +-- ccmp_special_blocks(skb, pn, b_0, aad, 0); +-- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, +-- skb_put(skb, IEEE80211_CCMP_MIC_LEN)); +-+ ccmp_special_blocks(skb, pn, scratch, 0); +-+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, +-+ pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); +- +- return 0; +- } +-@@ -521,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee +- } +- +- if (!(status->flag & RX_FLAG_DECRYPTED)) { +-- u8 aad[2 * AES_BLOCK_SIZE]; +-- u8 b_0[AES_BLOCK_SIZE]; +-+ u8 scratch[6 * AES_BLOCK_SIZE]; +- /* hardware didn't decrypt/verify MIC */ +-- ccmp_special_blocks(skb, pn, b_0, aad, 1); +-+ ccmp_special_blocks(skb, pn, scratch, 1); +- +- if (ieee80211_aes_ccm_decrypt( +-- key->u.ccmp.tfm, b_0, aad, +-+ key->u.ccmp.tfm, scratch, +- skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, +- data_len, +-- skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) +-+ skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, +-+ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) +- return RX_DROP_UNUSABLE; +- } +- +diff --git a/package/mac80211/patches/150-disable_addr_notifier.patch b/package/mac80211/patches/150-disable_addr_notifier.patch +index 7b50154..3f749e9 100644 +--- a/package/mac80211/patches/150-disable_addr_notifier.patch ++++ b/package/mac80211/patches/150-disable_addr_notifier.patch +@@ -18,7 +18,7 @@ + static int ieee80211_ifa6_changed(struct notifier_block *nb, + unsigned long data, void *arg) + { +-@@ -1031,14 +1031,14 @@ int ieee80211_register_hw(struct ieee802 ++@@ -1036,14 +1036,14 @@ int ieee80211_register_hw(struct ieee802 + goto fail_pm_qos; + } + +@@ -35,7 +35,7 @@ + local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; + result = register_inet6addr_notifier(&local->ifa6_notifier); + if (result) +-@@ -1047,13 +1047,13 @@ int ieee80211_register_hw(struct ieee802 ++@@ -1052,13 +1052,13 @@ int ieee80211_register_hw(struct ieee802 + + return 0; + +@@ -52,7 +52,7 @@ + fail_ifa: + pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); +-@@ -1086,10 +1086,10 @@ void ieee80211_unregister_hw(struct ieee ++@@ -1103,10 +1103,10 @@ void ieee80211_unregister_hw(struct ieee + + pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); +diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch +index a1af6c2..90dd5e7 100644 +--- a/package/mac80211/patches/300-pending_work.patch ++++ b/package/mac80211/patches/300-pending_work.patch +@@ -1,4153 +1,239 @@ +-commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef +-Author: Felix Fietkau +-Date: Sun Apr 6 23:35:28 2014 +0200 +- +- ath9k_hw: reduce ANI firstep range for older chips +- +- Use 0-8 instead of 0-16, which is closer to the old implementation. +- Also drop the overwrite of the firstep_low parameter to improve +- stability. +- +- Signed-off-by: Felix Fietkau +- +-commit 584d297fd29fb39c76af25ae74ff9d5fe74c8a14 +-Author: Helmut Schaa +-Date: Wed Mar 12 10:37:55 2014 +0100 +- +- ath9k: Fix sequence number assignment for non-data frames +- +- Since commit 558ff225de80ac95b132d3a115ddadcd64498b4f (ath9k: fix +- ps-poll responses under a-mpdu sessions) non-data frames would have +- gotten a sequence number from a TIDs sequence counter instead of +- using the global sequence counter. +- +- This can lead to instable connections. +- +- To fix this only select the correct TID if we are processing a +- data frame. Furthermore, prevent non-data frames to get a sequence +- number from a TID sequence counter by adding a check to +- ath_tx_setup_buffer. +- +- Cc: Felix Fietkau +- Signed-off-by: Helmut Schaa +- +-commit 3a0f984b1cdcd6a9f8c441635ef3b05d58547f4e +-Author: Felix Fietkau +-Date: Tue Mar 11 14:03:32 2014 +0100 +- +- ath9k_hw: set ANI firstep as absolute values instead of relative +- +- On older chips, the INI value differ in similar ways as cycpwr_thr1, so +- convert it to absolute values as well. +- +- Since the ANI algorithm is different here compared to the old +- implementation (fewer steps, controlled at a different point in time), +- it makes sense to use values similar to what would be applied for newer +- chips, just without relying on INI defaults. +- +- Signed-off-by: Felix Fietkau +- +-commit 91d70d40400c569b49605b78fd7c43e9405694f4 +-Author: Felix Fietkau +-Date: Tue Mar 11 14:00:37 2014 +0100 +- +- ath9k_hw: set ANI cycpwr_thr1 as absolute values instead of relative +- +- The table was copied from the ANI implementation of AR9300. It assumes +- that the INI values contain a baseline value that is usable as reference +- from which to increase/decrease based on the noise immunity value. +- +- On older chips, the differences are bigger and especially AR5008/AR9001 +- are configured to much more sensitive values than what is useful. +- +- Improve ANI behavior by reverting to the absolute values used in the +- previous implementation (expressed as a simple formula instead of the +- old table). +- +- Signed-off-by: Felix Fietkau +- +-commit c977493766310a825f406836636ffd66e1447783 +-Author: Felix Fietkau +-Date: Mon Mar 10 19:52:56 2014 +0100 +- +- ath9k_hw: remove ANI function restrictions for AP mode +- +- The primary purpose of this piece of code was to selectively disable +- OFDM weak signal detection. The checks for this are elsewhere, and an +- earlier commit relaxed the restrictions for older chips, which are more +- sensitive to interference. +- +- Signed-off-by: Felix Fietkau +- +-commit 8d804f1af11e4e058b1e8453327777d73a585cb8 +-Author: Felix Fietkau +-Date: Sun Mar 9 11:25:43 2014 +0100 +- +- ath9k: clean up and enhance ANI debugfs file +- +- Unify scnprintf calls and include the current OFDM/CCK immunity level. +- +- Signed-off-by: Felix Fietkau +- +-commit 22e298b5a3a8a49e33805d4e351965123dede35b +-Author: Felix Fietkau +-Date: Sun Mar 9 10:58:47 2014 +0100 +- +- ath9k: fix ready time of the multicast buffer queue +- +- qi->tqi_readyTime is written directly to registers that expect +- microseconds as unit instead of TU. +- When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so +- convert it to microseconds before passing it to ath9k_hw. +- +- This should hopefully fix some Tx DMA issues with buffered multicast +- frames in AP mode. +- +- Cc: stable@vger.kernel.org +- Signed-off-by: Felix Fietkau +- +-commit fcb064fdd5a27bec8d24099bc0172468f34c97cb ++commit eefb1d6adc4c60d219182b8917e4567484ce07fc + Author: Felix Fietkau +-Date: Sun Mar 9 09:43:09 2014 +0100 +- +- ath9k_hw: fix unreachable code in baseband hang detection code +- +- The commit "ath9k: reduce baseband hang detection false positive rate" +- added a delay in the loop checking the baseband state, however it was +- unreachable due to previous 'continue' statements. +- +- Reported-by: Dan Carpenter +- Signed-off-by: Felix Fietkau +- +-commit 31959d8df39319e32c6d5ba9c135727be90cfad7 +-Author: Michal Kazior +-Date: Fri Mar 7 08:09:38 2014 +0100 +- +- mac80211: fix possible NULL dereference +- +- If chanctx is missing on a given vif then the band +- is assumed to be 2GHz. However if hw doesn't +- support 2GHz band then mac80211 ended up with a +- NULL dereference. +- +- This fixes a splat: +- +- [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 +- [ 4605.210789] IP: [] ieee80211_parse_bitrates+0x65/0x110 [mac80211] +- +- The splat was preceeded by WARN_ON(!chanctx_conf) +- in ieee80211_get_sdata_band(). +- +- Signed-off-by: Michal Kazior ++Date: Mon Apr 28 18:27:41 2014 +0200 + +-commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e +-Author: Michael Braun +-Date: Thu Mar 6 15:08:43 2014 +0100 +- +- mac80211: fix WPA with VLAN on AP side with ps-sta again +- +- commit de74a1d9032f4d37ea453ad2a647e1aff4cd2591 +- "mac80211: fix WPA with VLAN on AP side with ps-sta" +- fixed an issue where queued multicast packets would +- be sent out encrypted with the key of an other bss. +- +- commit "7cbf9d017dbb5e3276de7d527925d42d4c11e732" +- "mac80211: fix oops on mesh PS broadcast forwarding" +- essentially reverted it, because vif.type cannot be AP_VLAN +- due to the check to vif.type in ieee80211_get_buffered_bc before. +- +- As the later commit intended to fix the MESH case, fix it +- by checking for IFTYPE_AP instead of IFTYPE_AP_VLAN. +- +- Fixes: 7cbf9d017dbb +- Cc: # 3.10.x +- Cc: # 3.11.x +- Cc: # 3.12.x +- Cc: # 3.13.x +- Cc: +- Cc: +- Signed-off-by: Michael Braun +- +-commit 9d6ab9bdb9b368a6cf9519f0f92509b5b2c297ec +-Author: Johannes Berg +-Date: Mon Mar 3 14:19:08 2014 +0100 +- +- cfg80211: remove racy beacon_interval assignment +- +- In case of AP mode, the beacon interval is already reset to +- zero inside cfg80211_stop_ap(), and in the other modes it +- isn't relevant. Remove the assignment to remove a potential +- race since the assignment isn't properly locked. ++ ath9k: remove tid->paused flag + +- Reported-by: Michal Kazior +- Signed-off-by: Johannes Berg +- +-commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0 +-Author: Felix Fietkau +-Date: Fri Feb 28 18:52:56 2014 +0100 +- +- ath9k_hw: tweak noise immunity thresholds for older chipsets ++ There are some corner cases where the driver could get stuck with a full ++ tid queue that is paused, leading to a software tx queue hang. + +- Older chipsets are more sensitive to high PHY error counts, and the +- current noise immunity thresholds were based on tests run at QCA with +- newer chipsets. ++ Since the tx queueing rework, pausing per-tid queues on aggregation ++ session setup is no longer necessary. The driver will assign sequence ++ numbers to buffered frames when a new session is established, in order ++ to get the correct starting sequence number. + +- This patch brings back the values from the old ANI implementation for +- old chipsets, and it also disables weak signal detection on an earlier +- noise immunity level, to improve overall radio stability on affected +- devices. ++ mac80211 prevents new frames from entering the queue during setup. + + Signed-off-by: Felix Fietkau + +-commit 431e506da5953adc3b65af25f4b90873d528c115 ++commit 98a713933d8495f4078f561c1e651b738dd5b531 + Author: Felix Fietkau +-Date: Fri Feb 28 18:44:13 2014 +0100 ++Date: Sun Apr 27 14:49:03 2014 +0200 + +- ath9k_hw: toggle weak signal detection in AP mode on older chipsets +- +- The commit 80b4205b "ath9k: Fix OFDM weak signal detection for AP mode" +- prevented weak signal detection changes from taking effect in AP mode on +- all chipsets, claiming it is "not allowed". ++ ath9k_hw: do not lower ANI setting below default on AR913x + +- The main reason for not disabling weak signal detection in AP mode is +- that typically beacon RSSI is used to track whether it is needed to +- boost range, and this is unavailable in AP mode for obvious reasons. ++ When the amount of noise fluctuates strongly, low immunity settings ++ can sometimes disrupt signal detection on AR913x chips. When that ++ happens, no OFDM/CCK errors are reported anymore, and ANI tunes the ++ radio to the lowest immunity settings. ++ Usually rx/tx fails as well in that case. + +- The problem with not disabling weak signal detection is that older +- chipsets are very sensitive to high PHY error counts. When faced with +- heavy noise, this can lead to an excessive amount of "Failed to stop +- TX DMA" errors in the field. ++ To fix this, keep noise immunity settings at or above ANI default level, ++ which will keep radio parameters at or above INI values. + + Signed-off-by: Felix Fietkau + +-commit 98d1a6c5b14688ed030e81b889f607be308e0df9 ++commit 7cbb4c021bfd1e656f5b9953a947ab3c64e4e3b0 + Author: Felix Fietkau +-Date: Mon Feb 24 22:20:32 2014 +0100 ++Date: Thu Apr 10 10:49:01 2014 +0200 + +- ath9k: fix invalid descriptor discarding ++ mac80211: exclude AP_VLAN interfaces from tx power calculation + +- Only set sc->rx.discard_next to rx_stats->rs_more when actually +- discarding the current descriptor. +- +- Also, fix a detection of broken descriptors: +- First the code checks if the current descriptor is not done. +- Then it checks if the next descriptor is done. +- Add a check that afterwards checks the first descriptor again, because +- it might have been completed in the mean time. +- +- This fixes a regression introduced in +- commit 723e711356b5a8a95728a890e254e8b0d47b55cf +- "ath9k: fix handling of broken descriptors" ++ Their power value is initialized to zero. This patch fixes an issue ++ where the configured power drops to the minimum value when AP_VLAN ++ interfaces are created/removed. + + Cc: stable@vger.kernel.org +- Reported-by: Marco André Dinis +- Signed-off-by: Felix Fietkau +- +-commit 52a46300e782fe6994466523eb2b0b59091ea59f +-Author: Felix Fietkau +-Date: Mon Feb 24 11:43:50 2014 +0100 +- +- ath9k: reduce baseband hang detection false positive rate +- +- Check if the baseband state remains stable, and add a small delay +- between register reads. +- +- Signed-off-by: Felix Fietkau +- +-commit 118945bb12082e9d4edddc868d88143164e0f440 +-Author: Felix Fietkau +-Date: Sat Feb 22 14:55:23 2014 +0100 +- +- ath5k: set SURVEY_INFO_IN_USE on get_survey +- +- Only one channel is returned - the one currently being used. +- +- Signed-off-by: Felix Fietkau +- +-commit ee41f72476e1ea44283dfe1cbf75b9543a1e15c8 +-Author: Felix Fietkau +-Date: Sat Feb 22 14:44:52 2014 +0100 +- +- ath9k: make some hardware reset log messages debug-only +- +- On some chips, baseband watchdog hangs are more common than others, and +- the driver has support for handling them. +- Interrupts even after a watchdog hang are also quite common, so there's +- not much point in spamming the user's logfiles. +- + Signed-off-by: Felix Fietkau + +-commit b14fbb554fc65a2e0b5c41a319269b0350f187e7 ++commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9 + Author: Felix Fietkau +-Date: Sat Feb 22 14:35:25 2014 +0100 ++Date: Wed Apr 9 00:07:01 2014 +0200 + +- ath9k: do not set half/quarter channel flags in AR_PHY_MODE ++ mac80211: suppress BSS info change notifications for AP_VLAN + +- 5/10 MHz channel bandwidth is configured via the PLL clock, instead of +- the AR_PHY_MODE register. Using that register is AR93xx specific, and +- makes the mode incompatible with earlier chipsets. ++ Fixes warnings on tx power changes + +- In some early versions, these flags were apparently applied at the wrong +- point in time and thus did not cause connectivity issues, however now +- they are causing problems, as pointed out in this OpenWrt ticket: +- +- https://dev.openwrt.org/ticket/14916 +- +- Signed-off-by: Felix Fietkau +- +-commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5 +-Author: Felix Fietkau +-Date: Sat Feb 22 13:43:29 2014 +0100 +- +- ath9k: fix ps-poll responses under a-mpdu sessions +- +- When passing tx frames to the U-APSD queue for powersave poll responses, +- the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for +- proper sequence number accounting. +- +- This fixes high latency and connection stability issues with ath9k +- running as AP and a few kinds of mobile phones as client, when PS-Poll +- is heavily used +- +- Cc: stable@vger.kernel.org + Signed-off-by: Felix Fietkau + +-commit d5d87a37bbd6066b2c3c5d0bd0fe2a6e2ea45cc5 ++commit ec998e5991781ecdaad0911dc64f1c8d3749c308 + Author: Felix Fietkau +-Date: Fri Feb 21 11:39:59 2014 +0100 ++Date: Tue Apr 8 23:42:17 2014 +0200 + +- ath9k: list more reset causes in debugfs ++ ath9k: fix a scheduling while atomic bug in CSA handling + +- Number of MAC hangs and stuck beacons were missing ++ Commit "ath9k: prepare for multi-interface CSA support" added a call to ++ ieee80211_iterate_active_interfaces in atomic context (beacon tasklet), ++ which is crashing. ++ Use ieee80211_iterate_active_interfaces_atomic instead. + + Signed-off-by: Felix Fietkau + +-commit d84856012e0f10fe598a5ad3b7b869397a089e07 +-Author: Johannes Berg +-Date: Thu Feb 20 11:19:58 2014 +0100 +- +- mac80211: fix station wakeup powersave race +- +- Consider the following (relatively unlikely) scenario: +- 1) station goes to sleep while frames are buffered in driver +- 2) driver blocks wakeup (until no more frames are buffered) +- 3) station wakes up again +- 4) driver unblocks wakeup +- +- In this case, the current mac80211 code will do the following: +- 1) WLAN_STA_PS_STA set +- 2) WLAN_STA_PS_DRIVER set +- 3) - nothing - +- 4) WLAN_STA_PS_DRIVER cleared +- +- As a result, no frames will be delivered to the client, even +- though it is awake, until it sends another frame to us that +- triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end(). +- +- Since we now take the PS spinlock, we can fix this while at +- the same time removing the complexity with the pending skb +- queue function. This was broken since my commit 50a9432daeec +- ("mac80211: fix powersaving clients races") due to removing +- the clearing of WLAN_STA_PS_STA in the RX path. +- +- While at it, fix a cleanup path issue when a station is +- removed while the driver is still blocking its wakeup. +- +- Signed-off-by: Johannes Berg +- +-commit 798f2786602cbe93e6b928299614aa36ebf50692 +-Author: Johannes Berg +-Date: Mon Feb 17 20:49:03 2014 +0100 +- +- mac80211: insert stations before adding to driver +- +- There's a race condition in mac80211 because we add stations +- to the internal lists after adding them to the driver, which +- means that (for example) the following can happen: +- 1. a station connects and is added +- 2. first, it is added to the driver +- 3. then, it is added to the mac80211 lists +- +- If the station goes to sleep between steps 2 and 3, and the +- firmware/hardware records it as being asleep, mac80211 will +- never instruct the driver to wake it up again as it never +- realized it went to sleep since the RX path discarded the +- frame as a "spurious class 3 frame", no station entry was +- present yet. +- +- Fix this by adding the station in software first, and only +- then adding it to the driver. That way, any state that the +- driver changes will be reflected properly in mac80211's +- station state. The problematic part is the roll-back if the +- driver fails to add the station, in that case a bit more is +- needed. To not make that overly complex prevent starting BA +- sessions in the meantime. +- +- Signed-off-by: Johannes Berg +- +-commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe +-Author: Emmanuel Grumbach +-Date: Thu Feb 20 09:22:11 2014 +0200 +- +- mac80211: fix AP powersave TX vs. wakeup race +- +- There is a race between the TX path and the STA wakeup: while +- a station is sleeping, mac80211 buffers frames until it wakes +- up, then the frames are transmitted. However, the RX and TX +- path are concurrent, so the packet indicating wakeup can be +- processed while a packet is being transmitted. +- +- This can lead to a situation where the buffered frames list +- is emptied on the one side, while a frame is being added on +- the other side, as the station is still seen as sleeping in +- the TX path. +- +- As a result, the newly added frame will not be send anytime +- soon. It might be sent much later (and out of order) when the +- station goes to sleep and wakes up the next time. +- +- Additionally, it can lead to the crash below. +- +- Fix all this by synchronising both paths with a new lock. +- Both path are not fastpath since they handle PS situations. +- +- In a later patch we'll remove the extra skb queue locks to +- reduce locking overhead. +- +- BUG: unable to handle kernel +- NULL pointer dereference at 000000b0 +- IP: [] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] +- *pde = 00000000 +- Oops: 0000 [#1] SMP DEBUG_PAGEALLOC +- EIP: 0060:[] EFLAGS: 00210282 CPU: 1 +- EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211] +- EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000 +- ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0 +- DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 +- CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0 +- DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 +- DR6: ffff0ff0 DR7: 00000400 +- Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000) +- iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9 +- Stack: +- e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0 +- ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210 +- ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002 +- Call Trace: +- [] ieee80211_free_txskb+0x15/0x20 [mac80211] +- [] invoke_tx_handlers+0x1661/0x1780 [mac80211] +- [] ieee80211_tx+0x75/0x100 [mac80211] +- [] ieee80211_xmit+0x8f/0xc0 [mac80211] +- [] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] +- [] dev_hard_start_xmit+0x450/0x950 +- [] sch_direct_xmit+0xa9/0x250 +- [] __qdisc_run+0x4b/0x150 +- [] dev_queue_xmit+0x2c2/0xca0 +- +- Cc: stable@vger.kernel.org +- Reported-by: Yaara Rozenblum +- Signed-off-by: Emmanuel Grumbach +- Reviewed-by: Stanislaw Gruszka +- [reword commit log, use a separate lock] +- Signed-off-by: Johannes Berg +- +-commit 80e419de0dff38436b30d363311c625766193f86 +-Author: Inbal Hacohen +-Date: Wed Feb 12 09:32:27 2014 +0200 +- +- cfg80211: bugfix in regulatory user hint process +- +- After processing hint_user, we would want to schedule the +- timeout work only if we are actually waiting to CRDA. This happens +- when the status is not "IGNORE" nor "ALREADY_SET". +- +- Signed-off-by: Inbal Hacohen +- Signed-off-by: Johannes Berg +- +-commit 6514c93afede55284e2cb63359aadedb85884c80 +-Author: Jouni Malinen +-Date: Tue Feb 18 20:41:08 2014 +0200 +- +- ath9k: Enable U-APSD AP mode support +- +- mac80211 handles the actual operations, so ath9k can just indicate +- support for this. Based on initial tests, this combination seems to +- work fine. +- +- Signed-off-by: Jouni Malinen +- +-commit a63caf0a357ad5c1f08d6b7827dc76c451445017 +-Author: Stanislaw Gruszka +-Date: Wed Feb 19 13:15:17 2014 +0100 +- +- ath9k: protect tid->sched check +- +- We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That +- is race condition which can result of doing list_del(&tid->list) twice +- (second time with poisoned list node) and cause crash like shown below: +- +- [424271.637220] BUG: unable to handle kernel paging request at 00100104 +- [424271.637328] IP: [] ath_tx_aggr_sleep+0x62/0xe0 [ath9k] +- ... +- [424271.639953] Call Trace: +- [424271.639998] [] ? ath9k_get_survey+0x110/0x110 [ath9k] +- [424271.640083] [] ath9k_sta_notify+0x42/0x50 [ath9k] +- [424271.640177] [] sta_ps_start+0x8f/0x1c0 [mac80211] +- [424271.640258] [] ? free_compound_page+0x2e/0x40 +- [424271.640346] [] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211] +- [424271.640437] [] ? kmem_cache_free+0x1d8/0x1f0 +- [424271.640510] [] ? kfree_skbmem+0x34/0x90 +- [424271.640578] [] ? put_page+0x2c/0x40 +- [424271.640640] [] ? kfree_skbmem+0x34/0x90 +- [424271.640706] [] ? kfree_skbmem+0x34/0x90 +- [424271.640787] [] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211] +- [424271.640897] [] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211] +- [424271.641009] [] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211] +- [424271.641104] [] ? ip_output+0x7e/0xd0 +- [424271.641182] [] ieee80211_rx+0x307/0x7c0 [mac80211] +- [424271.641266] [] ath_rx_tasklet+0x88e/0xf70 [ath9k] +- [424271.641358] [] ? ieee80211_rx+0x1dc/0x7c0 [mac80211] +- [424271.641445] [] ath9k_tasklet+0xcb/0x130 [ath9k] +- +- Bug report: +- https://bugzilla.kernel.org/show_bug.cgi?id=70551 +- +- Reported-and-tested-by: Max Sydorenko +- Cc: stable@vger.kernel.org +- Signed-off-by: Stanislaw Gruszka +- +-commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41 ++commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef + Author: Felix Fietkau +-Date: Tue Feb 11 15:54:13 2014 +0100 ++Date: Sun Apr 6 23:35:28 2014 +0200 + +- mac80211: send control port protocol frames to the VO queue ++ ath9k_hw: reduce ANI firstep range for older chips + +- Improves reliability of wifi connections with WPA, since authentication +- frames are prioritized over normal traffic and also typically exempt +- from aggregation. ++ Use 0-8 instead of 0-16, which is closer to the old implementation. ++ Also drop the overwrite of the firstep_low parameter to improve ++ stability. + +- Cc: stable@vger.kernel.org + Signed-off-by: Felix Fietkau + +-commit d4426800f71e972feaa33e04c5801fc730627bdd +-Author: Stanislaw Gruszka +-Date: Mon Feb 10 22:38:28 2014 +0100 +- +- rtl8187: fix regression on MIPS without coherent DMA +- +- This patch fixes regression caused by commit a16dad77634 "MIPS: Fix +- potencial corruption". That commit fixes one corruption scenario in +- cost of adding another one, which actually start to cause crashes +- on Yeeloong laptop when rtl8187 driver is used. +- +- For correct DMA read operation on machines without DMA coherence, kernel +- have to invalidate cache, such it will refill later with new data that +- device wrote to memory, when that data is needed to process. We can only +- invalidate full cache line. Hence when cache line includes both dma +- buffer and some other data (written in cache, but not yet in main +- memory), the other data can not hit memory due to invalidation. That +- happen on rtl8187 where struct rtl8187_priv fields are located just +- before and after small buffers that are passed to USB layer and DMA +- is performed on them. +- +- To fix the problem we align buffers and reserve space after them to make +- them match cache line. +- +- This patch does not resolve all possible MIPS problems entirely, for +- that we have to assure that we always map cache aligned buffers for DMA, +- what can be complex or even not possible. But patch fixes visible and +- reproducible regression and seems other possible corruptions do not +- happen in practice, since Yeeloong laptop works stable without rtl8187 +- driver. +- +- Bug report: +- https://bugzilla.kernel.org/show_bug.cgi?id=54391 +- +- Reported-by: Petr Pisar +- Bisected-by: Tom Li +- Reported-and-tested-by: Tom Li +- Cc: stable@vger.kernel.org +- Signed-off-by: Stanislaw Gruszka +- +-commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442 +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:55 2014 +0530 +- +- ath9k: Calculate IQ-CAL median +- +- This patch adds a routine to calculate the median IQ correction +- values for AR955x, which is used for outlier detection. +- The normal method which is used for all other chips is +- bypassed for AR955x. +- +- Signed-off-by: Sujith Manoharan +- +-commit c52a6fce0820c8d0687443ab86058ae03b478c8f +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:54 2014 +0530 +- +- ath9k: Expand the IQ coefficient array +- +- This will be used for storing data for mutiple +- IQ calibration runs, for AR955x. +- +- Signed-off-by: Sujith Manoharan +- +-commit 034969ff5c2b6431d10e07c1938f0b916da85cc3 +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:53 2014 +0530 +- +- ath9k: Modify IQ calibration for AR955x +- +- IQ calibration post-processing for AR955x is different +- from other chips - instead of just doing it as part +- of AGC calibration once, it is triggered 3 times and +- a median is determined. This patch adds initial support +- for changing the calibration behavior for AR955x. +- +- Also, to simplify things, a helper routine to issue/poll +- AGC calibration is used. +- +- For non-AR955x chips, the iqcal_idx (which will be used +- in subsequent patches) is set to zero. +- +- Signed-off-by: Sujith Manoharan +- +-commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8 +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:52 2014 +0530 +- +- ath9k: Fix magnitude/phase calculation +- +- Incorrect values are programmed in the registers +- containing the IQ correction coefficients by the IQ-CAL +- post-processing code. Fix this. +- +- Signed-off-by: Sujith Manoharan +- +-commit 36f93484f96f79171dcecb67c5ef0c3de22531a6 +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:51 2014 +0530 +- +- ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes +- +- Use ar9003_hw_tx_iq_cal_outlier_detection instead. +- +- Signed-off-by: Sujith Manoharan +- +-commit 3af09a7f5d21dd5fd15b973ce6a91a575da30417 +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:50 2014 +0530 +- +- ath9k: Check explicitly for IQ calibration +- +- In chips like AR955x, the initvals contain the information +- whether IQ calibration is to be done in the HW when an +- AGC calibration is triggered. Check if IQ-CAL is enabled +- in the initvals before flagging 'txiqcal_done' as true. +- +- Signed-off-by: Sujith Manoharan +- +-commit cb4969634b93c4643a32cc3fbd27d2b288b25771 +-Author: Sujith Manoharan +-Date: Fri Feb 7 10:29:49 2014 +0530 +- +- ath9k: Fix IQ cal post processing for SoC +- +- Calibration data is not reused for SoC chips, so +- call ar9003_hw_tx_iq_cal_post_proc() with the correct +- argument. The 'is_reusable' flag is currently used +- only for PC-OEM chips, but it makes things clearer to +- specify it explicity. +- +- Signed-off-by: Sujith Manoharan +- +-commit e138e0ef9560c46ce93dbb22a728a57888e94d1c +-Author: Sujith Manoharan +-Date: Mon Feb 3 13:31:37 2014 +0530 + +- ath9k: Fix TX power calculation +- +- The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template" +- fixed the incorrect values in the eeprom templates, but if +- boards have already been calibrated with incorrect values, +- they would still be using the wrong TX power. Fix this by assigning +- a default value in such cases. +- +- Cc: Rajkumar Manoharan +- Signed-off-by: Sujith Manoharan +- +-commit b9f268b5b01331c3c82179abca551429450e9417 +-Author: Michal Kazior +-Date: Wed Jan 29 14:22:27 2014 +0100 +- +- cfg80211: consider existing DFS interfaces +- +- It was possible to break interface combinations in +- the following way: +- +- combo 1: iftype = AP, num_ifaces = 2, num_chans = 2, +- combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20 +- +- With the above interface combinations it was +- possible to: +- +- step 1. start AP on DFS channel by matching combo 2 +- step 2. start AP on non-DFS channel by matching combo 1 +- +- This was possible beacuse (step 2) did not consider +- if other interfaces require radar detection. +- +- The patch changes how cfg80211 tracks channels - +- instead of channel itself now a complete chandef +- is stored. +- +- Signed-off-by: Michal Kazior +- Signed-off-by: Johannes Berg +- +-commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28 +-Author: Antonio Quartulli +-Date: Wed Jan 29 17:53:43 2014 +0100 +- +- cfg80211: fix channel configuration in IBSS join +- +- When receiving an IBSS_JOINED event select the BSS object +- based on the {bssid, channel} couple rather than the bssid +- only. +- With the current approach if another cell having the same +- BSSID (but using a different channel) exists then cfg80211 +- picks up the wrong BSS object. +- The result is a mismatching channel configuration between +- cfg80211 and the driver, that can lead to any sort of +- problem. +- +- The issue can be triggered by having an IBSS sitting on +- given channel and then asking the driver to create a new +- cell using the same BSSID but with a different frequency. +- By passing the channel to cfg80211_get_bss() we can solve +- this ambiguity and retrieve/create the correct BSS object. +- All the users of cfg80211_ibss_joined() have been changed +- accordingly. +- +- Moreover WARN when cfg80211_ibss_joined() gets a NULL +- channel as argument and remove a bogus call of the same +- function in ath6kl (it does not make sense to call +- cfg80211_ibss_joined() with a zero BSSID on ibss-leave). +- +- Cc: Kalle Valo +- Cc: Arend van Spriel +- Cc: Bing Zhao +- Cc: Jussi Kivilinna +- Cc: libertas-dev@lists.infradead.org +- Acked-by: Kalle Valo +- Signed-off-by: Antonio Quartulli +- [minor code cleanup in ath6kl] +- Signed-off-by: Johannes Berg +- +-commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85 +-Author: Johannes Berg +-Date: Fri Jan 24 14:41:44 2014 +0100 +- +- mac80211: fix bufferable MMPDU RX handling +- +- Action, disassoc and deauth frames are bufferable, and as such don't +- have the PM bit in the frame control field reserved which means we +- need to react to the bit when receiving in such a frame. +- +- Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu() +- and using it for the RX path that currently ignores the PM bit in +- any non-data frames for doze->wake transitions, but listens to it in +- all frames for wake->doze transitions, both of which are wrong. +- +- Also use the new helper in the TX path to clean up the code. +- +- Signed-off-by: Johannes Berg +- +-commit fc0df6d2343636e3f48a069330d5b972e3d8659d +-Author: Janusz Dziedzic +-Date: Fri Jan 24 14:29:21 2014 +0100 +- +- cfg80211: set preset_chandef after channel switch +- +- Set preset_chandef in channel switch notification. +- In other case we will have old preset_chandef. +- +- Signed-off-by: Janusz Dziedzic +- Signed-off-by: Johannes Berg +- +-commit cdec895e2344987ff171cece96e25d7407a3ebf6 +-Author: Simon Wunderlich +-Date: Fri Jan 24 23:48:29 2014 +0100 +- +- mac80211: send ibss probe responses with noack flag +- +- Responding to probe requests for scanning clients will often create +- excessive retries, as it happens quite often that the scanning client +- already left the channel. Therefore do it like hostapd and send probe +- responses for wildcard SSID only once by using the noack flag. +- +- Signed-off-by: Simon Wunderlich +- [fix typo & 'wildcard SSID' in commit log] +- Signed-off-by: Johannes Berg +- +-commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b +-Author: Luciano Coelho +-Date: Tue Jan 28 17:09:08 2014 +0200 +- +- mac80211: ibss: remove unnecessary call to release channel +- +- The ieee80211_vif_use_channel() function calls +- ieee80211_vif_release_channel(), so there's no need to call it +- explicitly in __ieee80211_sta_join_ibss(). +- +- Signed-off-by: Luciano Coelho +- Signed-off-by: Johannes Berg +- +-commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7 +-Author: Michal Kazior +-Date: Wed Jan 29 07:56:21 2014 +0100 +- +- mac80211: add missing CSA locking +- +- The patch adds a missing sdata lock and adds a few +- lockdeps for easier maintenance. +- +- Signed-off-by: Michal Kazior +- Signed-off-by: Johannes Berg +- +-commit ad17ba7d14d225b109b73c177cd446afb8050598 +-Author: Michal Kazior +-Date: Wed Jan 29 07:56:20 2014 +0100 +- +- mac80211: fix sdata->radar_required locking +- +- radar_required setting wasn't protected by +- local->mtx in some places. This should prevent +- from scanning/radar detection/roc colliding. +- +- Signed-off-by: Michal Kazior +- Signed-off-by: Johannes Berg +- +-commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d +-Author: Michal Kazior +-Date: Wed Jan 29 07:56:19 2014 +0100 +- +- mac80211: move csa_active setting in STA CSA +- +- The sdata->vif.csa_active could be left set after, +- e.g. channel context constraints check fail in STA +- mode leaving the interface in a strange state for +- a brief period of time until it is disconnected. +- This was harmless but ugly. +- +- Signed-off-by: Michal Kazior +- Reviewed-by: Luciano Coelho +- Signed-off-by: Johannes Berg +- +-commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9 +-Author: Michal Kazior +-Date: Wed Jan 29 07:56:18 2014 +0100 +- +- mac80211: fix possible memory leak on AP CSA failure +- +- If CSA for AP interface failed and the interface +- was not stopped afterwards another CSA request +- would leak sdata->u.ap.next_beacon. +- +- Signed-off-by: Michal Kazior +- Reviewed-by: Luciano Coelho +- Signed-off-by: Johannes Berg +- +-commit 3a77ba08940682bf3d52cf14f980337324af9d4a +-Author: Johannes Berg +-Date: Sat Feb 1 00:33:29 2014 +0100 +- +- mac80211: fix fragmentation code, particularly for encryption +- +- The "new" fragmentation code (since my rewrite almost 5 years ago) +- erroneously sets skb->len rather than using skb_trim() to adjust +- the length of the first fragment after copying out all the others. +- This leaves the skb tail pointer pointing to after where the data +- originally ended, and thus causes the encryption MIC to be written +- at that point, rather than where it belongs: immediately after the +- data. +- +- The impact of this is that if software encryption is done, then +- a) encryption doesn't work for the first fragment, the connection +- becomes unusable as the first fragment will never be properly +- verified at the receiver, the MIC is practically guaranteed to +- be wrong +- b) we leak up to 8 bytes of plaintext (!) of the packet out into +- the air +- +- This is only mitigated by the fact that many devices are capable +- of doing encryption in hardware, in which case this can't happen +- as the tail pointer is irrelevant in that case. Additionally, +- fragmentation is not used very frequently and would normally have +- to be configured manually. +- +- Fix this by using skb_trim() properly. +- +- Cc: stable@vger.kernel.org +- Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation") +- Reported-by: Jouni Malinen +- Signed-off-by: Johannes Berg +- +-commit de5f242e0c10e841017e37eb8c38974a642dbca8 +-Author: Sujith Manoharan +-Date: Tue Jan 28 06:21:59 2014 +0530 +- +- ath9k: Fix build error on ARM +- +- Use mdelay instead of udelay to fix this error: +- +- ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined! +- make[1]: *** [__modpost] Error 1 +- make: *** [modules] Error 2 +- +- Reported-by: Josh Boyer +- Signed-off-by: Sujith Manoharan +- +-commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a +-Author: Geert Uytterhoeven +-Date: Sun Jan 26 11:53:21 2014 +0100 +- +- ath9k: Fix uninitialized variable in ath9k_has_tx_pending() +- +- drivers/net/wireless/ath/ath9k/main.c: In function ‘ath9k_has_tx_pending’: +- drivers/net/wireless/ath/ath9k/main.c:1869: warning: ‘npend’ may be used uninitialized in this function +- +- Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k: +- optimize ath9k_flush"). +- +- Signed-off-by: Geert Uytterhoeven +- +-commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6 +-Author: Emmanuel Grumbach +-Date: Mon Jan 27 11:07:42 2014 +0200 +- +- mac80211: release the channel in error path in start_ap +- +- When the driver cannot start the AP or when the assignement +- of the beacon goes wrong, we need to unassign the vif. +- +- Cc: stable@vger.kernel.org +- Signed-off-by: Emmanuel Grumbach +- Signed-off-by: Johannes Berg +- +-commit dfb6889a75c601aedb7450b7e606668e77da6679 +-Author: Johannes Berg +-Date: Wed Jan 22 11:14:19 2014 +0200 +- +- cfg80211: send scan results from work queue +- +- Due to the previous commit, when a scan finishes, it is in theory +- possible to hit the following sequence: +- 1. interface starts being removed +- 2. scan is cancelled by driver and cfg80211 is notified +- 3. scan done work is scheduled +- 4. interface is removed completely, rdev->scan_req is freed, +- event sent to userspace but scan done work remains pending +- 5. new scan is requested on another virtual interface +- 6. scan done work runs, freeing the still-running scan +- +- To fix this situation, hang on to the scan done message and block +- new scans while that is the case, and only send the message from +- the work function, regardless of whether the scan_req is already +- freed from interface removal. This makes step 5 above impossible +- and changes step 6 to be +- 5. scan done work runs, sending the scan done message +- +- As this can't work for wext, so we send the message immediately, +- but this shouldn't be an issue since we still return -EBUSY. +- +- Signed-off-by: Johannes Berg +- +-commit 45b7ab41fc08627d9a8428cb413d5d84662a9707 +-Author: Johannes Berg +-Date: Wed Jan 22 11:14:18 2014 +0200 +- +- cfg80211: fix scan done race +- +- When an interface/wdev is removed, any ongoing scan should be +- cancelled by the driver. This will make it call cfg80211, which +- only queues a work struct. If interface/wdev removal is quick +- enough, this can leave the scan request pending and processed +- only after the interface is gone, causing a use-after-free. +- +- Fix this by making sure the scan request is not pending after +- the interface is destroyed. We can't flush or cancel the work +- item due to locking concerns, but when it'll run it shouldn't +- find anything to do. This leaves a potential issue, if a new +- scan gets requested before the work runs, it prematurely stops +- the running scan, potentially causing another crash. I'll fix +- that in the next patch. +- +- This was particularly observed with P2P_DEVICE wdevs, likely +- because freeing them is quicker than freeing netdevs. +- +- Reported-by: Andrei Otcheretianski +- Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans") +- Signed-off-by: Johannes Berg +- +-commit ae04fa489ab31b5a10d3cc8399f52761175d4321 +-Author: Emmanuel Grumbach +-Date: Thu Jan 23 14:28:16 2014 +0200 +- +- mac80211: avoid deadlock revealed by lockdep +- +- sdata->u.ap.request_smps_work can’t be flushed synchronously +- under wdev_lock(wdev) since ieee80211_request_smps_ap_work +- itself locks the same lock. +- While at it, reset the driver_smps_mode when the ap is +- stopped to its default: OFF. +- +- This solves: +- +- ====================================================== +- [ INFO: possible circular locking dependency detected ] +- 3.12.0-ipeer+ #2 Tainted: G O +- ------------------------------------------------------- +- rmmod/2867 is trying to acquire lock: +- ((&sdata->u.ap.request_smps_work)){+.+...}, at: [] flush_work+0x0/0x90 +- +- but task is already holding lock: +- (&wdev->mtx){+.+.+.}, at: [] cfg80211_stop_ap+0x26/0x230 [cfg80211] +- +- which lock already depends on the new lock. +- +- the existing dependency chain (in reverse order) is: +- +- -> #1 (&wdev->mtx){+.+.+.}: +- [] lock_acquire+0x79/0xe0 +- [] mutex_lock_nested+0x4a/0x360 +- [] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211] +- [] process_one_work+0x198/0x450 +- [] worker_thread+0xf9/0x320 +- [] kthread+0x9f/0xb0 +- [] ret_from_kernel_thread+0x1b/0x28 +- +- -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}: +- [] __lock_acquire+0x183f/0x1910 +- [] lock_acquire+0x79/0xe0 +- [] flush_work+0x47/0x90 +- [] __cancel_work_timer+0x67/0xe0 +- [] cancel_work_sync+0xf/0x20 +- [] ieee80211_stop_ap+0x8c/0x340 [mac80211] +- [] cfg80211_stop_ap+0x8c/0x230 [cfg80211] +- [] cfg80211_leave+0x79/0x100 [cfg80211] +- [] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211] +- [] notifier_call_chain+0x59/0x130 +- [] __raw_notifier_call_chain+0x1e/0x30 +- [] raw_notifier_call_chain+0x1f/0x30 +- [] call_netdevice_notifiers_info+0x33/0x70 +- [] call_netdevice_notifiers+0x13/0x20 +- [] __dev_close_many+0x34/0xb0 +- [] dev_close_many+0x6e/0xc0 +- [] rollback_registered_many+0xa7/0x1f0 +- [] unregister_netdevice_many+0x14/0x60 +- [] ieee80211_remove_interfaces+0xe9/0x170 [mac80211] +- [] ieee80211_unregister_hw+0x56/0x110 [mac80211] +- [] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm] +- [] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi] +- [] iwl_opmode_deregister+0x6f/0x90 [iwlwifi] +- [] __exit_compat+0xd/0x19 [iwlmvm] +- [] SyS_delete_module+0x179/0x2b0 +- [] sysenter_do_call+0x12/0x32 +- +- Fixes: 687da132234f ("mac80211: implement SMPS for AP") +- Cc: [3.13] +- Reported-by: Ilan Peer +- Signed-off-by: Emmanuel Grumbach +- Signed-off-by: Johannes Berg +- +-commit 178b205e96217164fd7c30113464250d0b6f5eca +-Author: Johannes Berg +-Date: Thu Jan 23 16:32:29 2014 +0100 +- +- cfg80211: re-enable 5/10 MHz support +- +- Unfortunately I forgot this during the merge window, but the +- patch seems small enough to go in as a fix. The userspace API +- bug that was the reason for disabling it has long been fixed. +- +- Signed-off-by: Johannes Berg +- +-commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61 +-Author: Pontus Fuchs +-Date: Thu Jan 16 15:00:40 2014 +0100 +- +- nl80211: Reset split_start when netlink skb is exhausted +- +- When the netlink skb is exhausted split_start is left set. In the +- subsequent retry, with a larger buffer, the dump is continued from the +- failing point instead of from the beginning. +- +- This was causing my rt28xx based USB dongle to now show up when +- running "iw list" with an old iw version without split dump support. +- +- Cc: stable@vger.kernel.org +- Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps") +- Signed-off-by: Pontus Fuchs +- [avoid the entire workaround when state->split is set] +- Signed-off-by: Johannes Berg +- +-commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4 +-Author: Eliad Peller +-Date: Sun Jan 12 11:06:37 2014 +0200 +- +- mac80211: move roc cookie assignment earlier +- +- ieee80211_start_roc_work() might add a new roc +- to existing roc, and tell cfg80211 it has already +- started. +- +- However, this might happen before the roc cookie +- was set, resulting in REMAIN_ON_CHANNEL (started) +- event with null cookie. Consequently, it can make +- wpa_supplicant go out of sync. +- +- Fix it by setting the roc cookie earlier. +- +- Cc: stable@vger.kernel.org +- Signed-off-by: Eliad Peller +- Signed-off-by: Johannes Berg +- +-commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c +-Author: Johannes Berg +-Date: Fri Jan 24 14:06:29 2014 +0100 +- +- nl80211: send event when AP operation is stopped +- +- There are a few cases, e.g. suspend, where an AP interface is +- stopped by the kernel rather than by userspace request, most +- commonly when suspending. To let userspace know about this, +- send the NL80211_CMD_STOP_AP command as an event every time +- an AP interface is stopped. This also happens when userspace +- did in fact request the AP stop, but that's not a problem. +- +- For full-MAC drivers this may need to be extended to also +- cover cases where the device stopped the AP operation for +- some reason, this a bit more complicated because then all +- cfg80211 state also needs to be reset; such API is not part +- of this patch. +- +- Signed-off-by: Johannes Berg +- +-commit d5d567eda7704f190379ca852a8f9a4112e3eee3 +-Author: Johannes Berg +-Date: Thu Jan 23 16:20:29 2014 +0100 +- +- mac80211: add length check in ieee80211_is_robust_mgmt_frame() +- +- A few places weren't checking that the frame passed to the +- function actually has enough data even though the function +- clearly documents it must have a payload byte. Make this +- safer by changing the function to take an skb and checking +- the length inside. The old version is preserved for now as +- the rtl* drivers use it and don't have a correct skb. +- +- Signed-off-by: Johannes Berg +- +-commit f8f6d212a047fc65c7d3442dfc038f65517236fc +-Author: Johannes Berg +-Date: Fri Jan 24 10:53:53 2014 +0100 +- +- nl80211: fix scheduled scan RSSI matchset attribute confusion +- +- The scheduled scan matchsets were intended to be a list of filters, +- with the found BSS having to pass at least one of them to be passed +- to the host. When the RSSI attribute was added, however, this was +- broken and currently wpa_supplicant adds that attribute in its own +- matchset; however, it doesn't intend that to mean that anything +- that passes the RSSI filter should be passed to the host, instead +- it wants it to mean that everything needs to also have higher RSSI. +- +- This is semantically problematic because we have a list of filters +- like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which +- one should be OR'ed and which one AND'ed. +- +- To fix this, move the RSSI filter attribute into each matchset. As +- we need to stay backward compatible, treat a matchset with only the +- RSSI attribute as a "default RSSI filter" for all other matchsets, +- but only if there are other matchsets (an RSSI-only matchset by +- itself is still desirable.) +- +- To make driver implementation easier, keep a global min_rssi_thold +- for the entire request as well. The only affected driver is ath6kl. +- +- I found this when I looked into the code after Raja Mani submitted +- a patch fixing the n_match_sets calculation to disregard the RSSI, +- but that patch didn't address the semantic issue. +- +- Reported-by: Raja Mani +- Acked-by: Luciano Coelho +- Signed-off-by: Johannes Berg +- +-commit de553e8545e65a6dc4e45f43df7e1443d4291922 +-Author: Johannes Berg +-Date: Fri Jan 24 10:17:47 2014 +0100 +- +- nl80211: check nla_parse() return values +- +- If there's a policy, then nla_parse() return values must be +- checked, otherwise the policy is useless and there's nothing +- that ensures the attributes are actually what we expect them +- to be. +- +- Signed-off-by: Johannes Berg +- +-commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1 +-Author: Karl Beldan +-Date: Thu Jan 23 20:06:34 2014 +0100 +- +- mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec +- +- ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of +- the BA parameters. In the discussion [1] about this patch, Johannes +- recalled that it fixed some races with the DELBA and indeed this +- behavior was introduced in [2]. +- While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on +- their BA params TID AC violates the spec and is more a workaround for +- some drivers. Helmut expressed some concerns wrt such drivers, in +- particular DELBAs in rt2x00. +- +- ATM, DELBAs are sent after a driver has called (hence "purposely") +- ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some +- details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_* +- given to the driver ampdu_action supposed to call this function, which +- could prove handy to people trying to do the right thing in faulty +- drivers (if their fw/hw don't get in their way). +- +- [1] http://mid.gmane.org/1390391564-18481-1-git-send-email-karl.beldan@gmail.com +- [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames") +- +- Signed-off-by: Karl Beldan +- Cc: Helmut Schaa +- Cc: Emmanuel Grumbach +- Signed-off-by: Johannes Berg +---- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +-+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c +-@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struc +- if (nw_type & ADHOC_NETWORK) { +- ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", +- nw_type & ADHOC_CREATOR ? "creator" : "joiner"); +-- cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); +-+ cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL); +- cfg80211_put_bss(ar->wiphy, bss); +- return; +- } +-@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(st +- } +- +- if (vif->nw_type & ADHOC_NETWORK) { +-- if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) { +-+ if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) +- ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +- "%s: ath6k not in ibss mode\n", __func__); +-- return; +-- } +-- memset(bssid, 0, ETH_ALEN); +-- cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); +- return; +- } +- +-@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(s +- struct ath6kl_vif *vif = netdev_priv(dev); +- u16 interval; +- int ret, rssi_thold; +-+ int n_match_sets = request->n_match_sets; +-+ +-+ /* +-+ * If there's a matchset w/o an SSID, then assume it's just for +-+ * the RSSI (nothing else is currently supported) and ignore it. +-+ * The device only supports a global RSSI filter that we set below. +-+ */ +-+ if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len) +-+ n_match_sets = 0; +- +- if (ar->state != ATH6KL_STATE_ON) +- return -EIO; +-@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(s +- ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, +- request->n_ssids, +- request->match_sets, +-- request->n_match_sets); +-+ n_match_sets); +- if (ret < 0) +- return ret; +- +-- if (!request->n_match_sets) { +-+ if (!n_match_sets) { +- ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, +- ALL_BSS_FILTER, 0); +- if (ret < 0) +-@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(s +- +- if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, +- ar->fw_capabilities)) { +-- if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF) +-+ if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF) +- rssi_thold = 0; +-- else if (request->rssi_thold < -127) +-+ else if (request->min_rssi_thold < -127) +- rssi_thold = -127; +- else +-- rssi_thold = request->rssi_thold; +-+ rssi_thold = request->min_rssi_thold; +- +- ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx, +- rssi_thold); +---- a/drivers/net/wireless/ath/ath9k/hw.c +-+++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at +- if (AR_SREV_9300_20_OR_LATER(ah)) +- udelay(50); +- else if (AR_SREV_9100(ah)) +-- udelay(10000); +-+ mdelay(10); +- else +- udelay(100); +- +-@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav); +- bool ath9k_hw_check_alive(struct ath_hw *ah) +- { +- int count = 50; +-- u32 reg; +-+ u32 reg, last_val; +- +- if (AR_SREV_9300(ah)) +- return !ath9k_hw_detect_mac_hang(ah); +-@@ -1542,9 +1542,14 @@ bool ath9k_hw_check_alive(struct ath_hw +- if (AR_SREV_9285_12_OR_LATER(ah)) +- return true; +- +-+ last_val = REG_READ(ah, AR_OBS_BUS_1); +- do { +- reg = REG_READ(ah, AR_OBS_BUS_1); +-+ if (reg != last_val) +-+ return true; +- +-+ udelay(1); +-+ last_val = reg; +- if ((reg & 0x7E7FFFEF) == 0x00702400) +- continue; +- +-@@ -2051,9 +2056,8 @@ static bool ath9k_hw_set_power_awake(str +- +- REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, +- AR_RTC_FORCE_WAKE_EN); +-- +- if (AR_SREV_9100(ah)) +-- udelay(10000); +-+ mdelay(10); +- else +- udelay(50); +- +---- a/drivers/net/wireless/ath/ath9k/main.c +-+++ b/drivers/net/wireless/ath/ath9k/main.c +-@@ -451,7 +451,7 @@ void ath9k_tasklet(unsigned long data) +- * interrupts are enabled in the reset routine. +- */ +- atomic_inc(&ah->intr_ref_cnt); +-- ath_dbg(common, ANY, "FATAL: Skipping interrupts\n"); +-+ ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); +- goto out; +- } +- +-@@ -471,7 +471,7 @@ void ath9k_tasklet(unsigned long data) +- * interrupts are enabled in the reset routine. +- */ +- atomic_inc(&ah->intr_ref_cnt); +-- ath_dbg(common, ANY, +-+ ath_dbg(common, RESET, +- "BB_WATCHDOG: Skipping interrupts\n"); +- goto out; +- } +-@@ -484,7 +484,7 @@ void ath9k_tasklet(unsigned long data) +- type = RESET_TYPE_TX_GTT; +- ath9k_queue_reset(sc, type); +- atomic_inc(&ah->intr_ref_cnt); +-- ath_dbg(common, ANY, +-+ ath_dbg(common, RESET, +- "GTT: Skipping interrupts\n"); +- goto out; +- } +-@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str +- +- static bool ath9k_has_tx_pending(struct ath_softc *sc) +- { +-- int i, npend; +-+ int i, npend = 0; +- +- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { +- if (!ATH_TXQ_SETUP(sc, i)) +---- a/drivers/net/wireless/iwlwifi/mvm/scan.c +-+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c +-@@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid( +- * config match list. +- */ +- for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) { +-+ /* skip empty SSID matchsets */ +-+ if (!req->match_sets[i].ssid.ssid_len) +-+ continue; +- scan->direct_scan[i].id = WLAN_EID_SSID; +- scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len; +- memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid, +---- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +-+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +-@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80 +- /* During testing, hdr was NULL */ +- return false; +- } +-- if ((ieee80211_is_robust_mgmt_frame(hdr)) && +-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && +- (ieee80211_has_protected(hdr->frame_control))) +- rx_status->flag &= ~RX_FLAG_DECRYPTED; +- else +---- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +-+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +-@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80 +- /* In testing, hdr was NULL here */ +- return false; +- } +-- if ((ieee80211_is_robust_mgmt_frame(hdr)) && +-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && +- (ieee80211_has_protected(hdr->frame_control))) +- rx_status->flag &= ~RX_FLAG_DECRYPTED; +- else +---- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +-+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +-@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80 +- /* during testing, hdr was NULL here */ +- return false; +- } +-- if ((ieee80211_is_robust_mgmt_frame(hdr)) && +-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && +- (ieee80211_has_protected(hdr->frame_control))) +- rx_status->flag &= ~RX_FLAG_DECRYPTED; +- else +---- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +-+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +-@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee +- /* during testing, hdr could be NULL here */ +- return false; +- } +-- if ((ieee80211_is_robust_mgmt_frame(hdr)) && +-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && +- (ieee80211_has_protected(hdr->frame_control))) +- rx_status->flag &= ~RX_FLAG_DECRYPTED; +- else +---- a/include/linux/ieee80211.h +-+++ b/include/linux/ieee80211.h +-@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf +- } +- +- /** +-+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU +-+ * @fc: frame control field in little-endian byteorder +-+ */ +-+static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc) +-+{ +-+ /* IEEE 802.11-2012, definition of "bufferable management frame"; +-+ * note that this ignores the IBSS special case. */ +-+ return ieee80211_is_mgmt(fc) && +-+ (ieee80211_is_action(fc) || +-+ ieee80211_is_disassoc(fc) || +-+ ieee80211_is_deauth(fc)); +-+} +-+ +-+/** +- * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set +- * @seq_ctrl: frame sequence control bytes in little-endian byteorder +- */ +-@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc +- } +- +- /** +-- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame +-+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame +- * @hdr: the frame (buffer must include at least the first octet of payload) +- */ +--static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) +-+static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) +- { +- if (ieee80211_is_disassoc(hdr->frame_control) || +- ieee80211_is_deauth(hdr->frame_control)) +-@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m +- } +- +- /** +-+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame +-+ * @skb: the skb containing the frame, length will be checked +-+ */ +-+static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) +-+{ +-+ if (skb->len < 25) +-+ return false; +-+ return _ieee80211_is_robust_mgmt_frame((void *)skb->data); +-+} +-+ +-+/** +- * ieee80211_is_public_action - check if frame is a public action frame +- * @hdr: the frame +- * @len: length of the frame +---- a/include/net/cfg80211.h +-+++ b/include/net/cfg80211.h +-@@ -1395,9 +1395,11 @@ struct cfg80211_scan_request { +- * struct cfg80211_match_set - sets of attributes to match +- * +- * @ssid: SSID to be matched +-+ * @rssi_thold: don't report scan results below this threshold (in s32 dBm) +- */ +- struct cfg80211_match_set { +- struct cfg80211_ssid ssid; +-+ s32 rssi_thold; +- }; +- +- /** +-@@ -1420,7 +1422,8 @@ struct cfg80211_match_set { +- * @dev: the interface +- * @scan_start: start time of the scheduled scan +- * @channels: channels to scan +-- * @rssi_thold: don't report scan results below this threshold (in s32 dBm) +-+ * @min_rssi_thold: for drivers only supporting a single threshold, this +-+ * contains the minimum over all matchsets +- */ +- struct cfg80211_sched_scan_request { +- struct cfg80211_ssid *ssids; +-@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request { +- u32 flags; +- struct cfg80211_match_set *match_sets; +- int n_match_sets; +-- s32 rssi_thold; +-+ s32 min_rssi_thold; +- +- /* internal */ +- struct wiphy *wiphy; +-@@ -3130,8 +3133,8 @@ struct cfg80211_cached_keys; +- * @identifier: (private) Identifier used in nl80211 to identify this +- * wireless device if it has no netdev +- * @current_bss: (private) Used by the internal configuration code +-- * @channel: (private) Used by the internal configuration code to track +-- * the user-set AP, monitor and WDS channel +-+ * @chandef: (private) Used by the internal configuration code to track +-+ * the user-set channel definition. +- * @preset_chandef: (private) Used by the internal configuration code to +- * track the channel to be used for AP later +- * @bssid: (private) Used by the internal configuration code +-@@ -3195,9 +3198,7 @@ struct wireless_dev { +- +- struct cfg80211_internal_bss *current_bss; /* associated / joined */ +- struct cfg80211_chan_def preset_chandef; +-- +-- /* for AP and mesh channel tracking */ +-- struct ieee80211_channel *channel; +-+ struct cfg80211_chan_def chandef; +- +- bool ibss_fixed; +- bool ibss_dfs_possible; +-@@ -3879,6 +3880,7 @@ void cfg80211_michael_mic_failure(struct +- * +- * @dev: network device +- * @bssid: the BSSID of the IBSS joined +-+ * @channel: the channel of the IBSS joined +- * @gfp: allocation flags +- * +- * This function notifies cfg80211 that the device joined an IBSS or +-@@ -3888,7 +3890,8 @@ void cfg80211_michael_mic_failure(struct +- * with the locally generated beacon -- this guarantees that there is +- * always a scan result for this IBSS. cfg80211 will handle the rest. +- */ +--void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); +-+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, +-+ struct ieee80211_channel *channel, gfp_t gfp); +- +- /** +- * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate +---- a/include/uapi/linux/nl80211.h +-+++ b/include/uapi/linux/nl80211.h +-@@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr { +- * enum nl80211_sched_scan_match_attr - scheduled scan match attributes +- * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved +- * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, +-- * only report BSS with matching SSID. +-+ * only report BSS with matching SSID. +- * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a +-- * BSS in scan results. Filtering is turned off if not specified. +-+ * BSS in scan results. Filtering is turned off if not specified. Note that +-+ * if this attribute is in a match set of its own, then it is treated as +-+ * the default value for all matchsets with an SSID, rather than being a +-+ * matchset of its own without an RSSI filter. This is due to problems with +-+ * how this API was implemented in the past. Also, due to the same problem, +-+ * the only way to create a matchset with only an RSSI filter (with this +-+ * attribute) is if there's only a single matchset with the RSSI attribute. +- * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter +- * attribute number currently defined +- * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use +---- a/net/mac80211/agg-tx.c +-+++ b/net/mac80211/agg-tx.c +-@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request +- mgmt->u.action.u.addba_req.start_seq_num = +- cpu_to_le16(start_seq_num << 4); +- +-- ieee80211_tx_skb_tid(sdata, skb, tid); +-+ ieee80211_tx_skb(sdata, skb); +- } +- +- void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) +---- a/net/mac80211/cfg.c +-+++ b/net/mac80211/cfg.c +-@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wip +- /* TODO: make hostapd tell us what it wants */ +- sdata->smps_mode = IEEE80211_SMPS_OFF; +- sdata->needed_rx_chains = sdata->local->rx_chains; +-- sdata->radar_required = params->radar_required; +- +- mutex_lock(&local->mtx); +-+ sdata->radar_required = params->radar_required; +- err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, +- IEEE80211_CHANCTX_SHARED); +- mutex_unlock(&local->mtx); +-@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip +- IEEE80211_P2P_OPPPS_ENABLE_BIT; +- +- err = ieee80211_assign_beacon(sdata, ¶ms->beacon); +-- if (err < 0) +-+ if (err < 0) { +-+ ieee80211_vif_release_channel(sdata); +- return err; +-+ } +- changed |= err; +- +- err = drv_start_ap(sdata->local, sdata); +-@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip +- if (old) +- kfree_rcu(old, rcu_head); +- RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); +-+ ieee80211_vif_release_channel(sdata); +- return err; +- } +- +-@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc +- int err; +- +- sdata = IEEE80211_DEV_TO_SUB_IF(dev); +-+ sdata_assert_lock(sdata); +- +- /* don't allow changing the beacon while CSA is in place - offset +- * of channel switch counter may change +-@@ -1080,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiph +- struct probe_resp *old_probe_resp; +- struct cfg80211_chan_def chandef; +- +-+ sdata_assert_lock(sdata); +-+ +- old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); +- if (!old_beacon) +- return -ENOENT; +-@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; +- +-- cancel_work_sync(&sdata->u.ap.request_smps_work); +-- +- /* turn off carrier for this interface and dependent VLANs */ +- list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) +- netif_carrier_off(vlan->dev); +-@@ -1103,6 +1107,7 @@ static int ieee80211_stop_ap(struct wiph +- kfree_rcu(old_beacon, rcu_head); +- if (old_probe_resp) +- kfree_rcu(old_probe_resp, rcu_head); +-+ sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; +- +- __sta_info_flush(sdata, true); +- ieee80211_free_keys(sdata, true); +-@@ -1988,6 +1993,9 @@ static int ieee80211_change_bss(struct w +- +- band = ieee80211_get_sdata_band(sdata); +- +-+ if (WARN_ON(!wiphy->bands[band])) +-+ return -EINVAL; +-+ +- if (params->use_cts_prot >= 0) { +- sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; +- changed |= BSS_CHANGED_ERP_CTS_PROT; +-@@ -2638,6 +2646,24 @@ static int ieee80211_start_roc_work(stru +- INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); +- INIT_LIST_HEAD(&roc->dependents); +- +-+ /* +-+ * cookie is either the roc cookie (for normal roc) +-+ * or the SKB (for mgmt TX) +-+ */ +-+ if (!txskb) { +-+ /* local->mtx protects this */ +-+ local->roc_cookie_counter++; +-+ roc->cookie = local->roc_cookie_counter; +-+ /* wow, you wrapped 64 bits ... more likely a bug */ +-+ if (WARN_ON(roc->cookie == 0)) { +-+ roc->cookie = 1; +-+ local->roc_cookie_counter++; +-+ } +-+ *cookie = roc->cookie; +-+ } else { +-+ *cookie = (unsigned long)txskb; +-+ } +-+ +- /* if there's one pending or we're scanning, queue this one */ +- if (!list_empty(&local->roc_list) || +- local->scanning || local->radar_detect_enabled) +-@@ -2772,24 +2798,6 @@ static int ieee80211_start_roc_work(stru +- if (!queued) +- list_add_tail(&roc->list, &local->roc_list); +- +-- /* +-- * cookie is either the roc cookie (for normal roc) +-- * or the SKB (for mgmt TX) +-- */ +-- if (!txskb) { +-- /* local->mtx protects this */ +-- local->roc_cookie_counter++; +-- roc->cookie = local->roc_cookie_counter; +-- /* wow, you wrapped 64 bits ... more likely a bug */ +-- if (WARN_ON(roc->cookie == 0)) { +-- roc->cookie = 1; +-- local->roc_cookie_counter++; +-- } +-- *cookie = roc->cookie; +-- } else { +-- *cookie = (unsigned long)txskb; +-- } +-- +- return 0; +- } +- +-@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct +- if (!ieee80211_sdata_running(sdata)) +- goto unlock; +- +-- sdata->radar_required = sdata->csa_radar_required; +-+ sdata_assert_lock(sdata); +-+ +- mutex_lock(&local->mtx); +-+ sdata->radar_required = sdata->csa_radar_required; +- err = ieee80211_vif_change_channel(sdata, &changed); +- mutex_unlock(&local->mtx); +- if (WARN_ON(err < 0)) +-@@ -3022,13 +3032,13 @@ void ieee80211_csa_finalize_work(struct +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP: +- err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); +-+ kfree(sdata->u.ap.next_beacon); +-+ sdata->u.ap.next_beacon = NULL; +-+ +- if (err < 0) +- goto unlock; +- +- changed |= err; +-- kfree(sdata->u.ap.next_beacon); +-- sdata->u.ap.next_beacon = NULL; +-- +- ieee80211_bss_info_change_notify(sdata, err); +- break; +- case NL80211_IFTYPE_ADHOC: +-@@ -3066,7 +3076,7 @@ int ieee80211_channel_switch(struct wiph +- struct ieee80211_if_mesh __maybe_unused *ifmsh; +- int err, num_chanctx; +- +-- lockdep_assert_held(&sdata->wdev.mtx); +-+ sdata_assert_lock(sdata); +- +- if (!list_empty(&local->roc_list) || local->scanning) +- return -EBUSY; +---- a/net/mac80211/ht.c +-+++ b/net/mac80211/ht.c +-@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802 +- mgmt->u.action.u.delba.params = cpu_to_le16(params); +- mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); +- +-- ieee80211_tx_skb_tid(sdata, skb, tid); +-+ ieee80211_tx_skb(sdata, skb); +- } +- +- void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, +-@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru +- u.ap.request_smps_work); +- +- sdata_lock(sdata); +-- __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode); +-+ if (sdata_dereference(sdata->u.ap.beacon, sdata)) +-+ __ieee80211_request_smps_ap(sdata, +-+ sdata->u.ap.driver_smps_mode); +- sdata_unlock(sdata); +- } +- +---- a/net/mac80211/iface.c +-+++ b/net/mac80211/iface.c +-@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee +- +- ieee80211_roc_purge(local, sdata); +- +-- if (sdata->vif.type == NL80211_IFTYPE_STATION) +-+ switch (sdata->vif.type) { +-+ case NL80211_IFTYPE_STATION: +- ieee80211_mgd_stop(sdata); +-- +-- if (sdata->vif.type == NL80211_IFTYPE_ADHOC) +-+ break; +-+ case NL80211_IFTYPE_ADHOC: +- ieee80211_ibss_stop(sdata); +-- +-+ break; +-+ case NL80211_IFTYPE_AP: +-+ cancel_work_sync(&sdata->u.ap.request_smps_work); +-+ break; +-+ default: +-+ break; +-+ } +- +- /* +- * Remove all stations associated with this interface. +-@@ -827,7 +834,9 @@ static void ieee80211_do_stop(struct iee +- cancel_work_sync(&local->dynamic_ps_enable_work); +- +- cancel_work_sync(&sdata->recalc_smps); +-+ sdata_lock(sdata); +- sdata->vif.csa_active = false; +-+ sdata_unlock(sdata); +- cancel_work_sync(&sdata->csa_finalize_work); +- +- cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); +---- a/net/mac80211/rx.c +-+++ b/net/mac80211/rx.c +-@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m +- { +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +- +-- if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) +-+ if (is_multicast_ether_addr(hdr->addr1)) +- return 0; +- +-- return ieee80211_is_robust_mgmt_frame(hdr); +-+ return ieee80211_is_robust_mgmt_frame(skb); +- } +- +- +-@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust +- { +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +- +-- if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) +-+ if (!is_multicast_ether_addr(hdr->addr1)) +- return 0; +- +-- return ieee80211_is_robust_mgmt_frame(hdr); +-+ return ieee80211_is_robust_mgmt_frame(skb); +- } +- +- +-@@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str +- if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) +- return -1; +- +-- if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) +-+ if (!ieee80211_is_robust_mgmt_frame(skb)) +- return -1; /* not a robust management frame */ +- +- mmie = (struct ieee80211_mmie *) +-@@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info * +- sta->sta.addr, sta->sta.aid); +- +- if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { +-+ /* +-+ * Clear the flag only if the other one is still set +-+ * so that the TX path won't start TX'ing new frames +-+ * directly ... In the case that the driver flag isn't +-+ * set ieee80211_sta_ps_deliver_wakeup() will clear it. +-+ */ +-+ clear_sta_flag(sta, WLAN_STA_PS_STA); +- ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", +- sta->sta.addr, sta->sta.aid); +- return; +-@@ -1311,18 +1318,15 @@ ieee80211_rx_h_sta_process(struct ieee80 +- !ieee80211_has_morefrags(hdr->frame_control) && +- !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && +- (rx->sdata->vif.type == NL80211_IFTYPE_AP || +-- rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { +-+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && +-+ /* PM bit is only checked in frames where it isn't reserved, +-+ * in AP mode it's reserved in non-bufferable management frames +-+ * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) +-+ */ +-+ (!ieee80211_is_mgmt(hdr->frame_control) || +-+ ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { +- if (test_sta_flag(sta, WLAN_STA_PS_STA)) { +-- /* +-- * Ignore doze->wake transitions that are +-- * indicated by non-data frames, the standard +-- * is unclear here, but for example going to +-- * PS mode and then scanning would cause a +-- * doze->wake transition for the probe request, +-- * and that is clearly undesirable. +-- */ +-- if (ieee80211_is_data(hdr->frame_control) && +-- !ieee80211_has_pm(hdr->frame_control)) +-+ if (!ieee80211_has_pm(hdr->frame_control)) +- sta_ps_end(sta); +- } else { +- if (ieee80211_has_pm(hdr->frame_control)) +-@@ -1845,8 +1849,7 @@ static int ieee80211_drop_unencrypted_mg +- * having configured keys. +- */ +- if (unlikely(ieee80211_is_action(fc) && !rx->key && +-- ieee80211_is_robust_mgmt_frame( +-- (struct ieee80211_hdr *) rx->skb->data))) +-+ ieee80211_is_robust_mgmt_frame(rx->skb))) +- return -EACCES; +- } +- +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, +- if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) +- return 0; +- +-- if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) +-- skb->data)) +-+ if (!ieee80211_is_robust_mgmt_frame(skb)) +- return 0; +- +- return 1; +-@@ -478,6 +477,20 @@ ieee80211_tx_h_unicast_ps_buf(struct iee +- sta->sta.addr, sta->sta.aid, ac); +- if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) +- purge_old_ps_buffers(tx->local); +-+ +-+ /* sync with ieee80211_sta_ps_deliver_wakeup */ +-+ spin_lock(&sta->ps_lock); +-+ /* +-+ * STA woke up the meantime and all the frames on ps_tx_buf have +-+ * been queued to pending queue. No reordering can happen, go +-+ * ahead and Tx the packet. +-+ */ +-+ if (!test_sta_flag(sta, WLAN_STA_PS_STA) && +-+ !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { +-+ spin_unlock(&sta->ps_lock); +-+ return TX_CONTINUE; +-+ } +-+ +- if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { +- struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); +- ps_dbg(tx->sdata, +-@@ -492,6 +505,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; +- info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; +- skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); +-+ spin_unlock(&sta->ps_lock); +- +- if (!timer_pending(&local->sta_cleanup)) +- mod_timer(&local->sta_cleanup, +-@@ -525,9 +539,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t +- +- /* only deauth, disassoc and action are bufferable MMPDUs */ +- if (ieee80211_is_mgmt(hdr->frame_control) && +-- !ieee80211_is_deauth(hdr->frame_control) && +-- !ieee80211_is_disassoc(hdr->frame_control) && +-- !ieee80211_is_action(hdr->frame_control)) { +-+ !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { +- if (tx->flags & IEEE80211_TX_UNICAST) +- info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; +- return TX_CONTINUE; +-@@ -567,7 +579,7 @@ ieee80211_tx_h_select_key(struct ieee802 +- tx->key = key; +- else if (ieee80211_is_mgmt(hdr->frame_control) && +- is_multicast_ether_addr(hdr->addr1) && +-- ieee80211_is_robust_mgmt_frame(hdr) && +-+ ieee80211_is_robust_mgmt_frame(tx->skb) && +- (key = rcu_dereference(tx->sdata->default_mgmt_key))) +- tx->key = key; +- else if (is_multicast_ether_addr(hdr->addr1) && +-@@ -582,12 +594,12 @@ ieee80211_tx_h_select_key(struct ieee802 +- tx->key = NULL; +- else if (tx->skb->protocol == tx->sdata->control_port_protocol) +- tx->key = NULL; +-- else if (ieee80211_is_robust_mgmt_frame(hdr) && +-+ else if (ieee80211_is_robust_mgmt_frame(tx->skb) && +- !(ieee80211_is_action(hdr->frame_control) && +- tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) +- tx->key = NULL; +- else if (ieee80211_is_mgmt(hdr->frame_control) && +-- !ieee80211_is_robust_mgmt_frame(hdr)) +-+ !ieee80211_is_robust_mgmt_frame(tx->skb)) +- tx->key = NULL; +- else { +- I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); +-@@ -878,7 +890,7 @@ static int ieee80211_fragment(struct iee +- } +- +- /* adjust first fragment's length */ +-- skb->len = hdrlen + per_fragm; +-+ skb_trim(skb, hdrlen + per_fragm); +- return 0; +- } +- +-@@ -2900,7 +2912,7 @@ ieee80211_get_buffered_bc(struct ieee802 +- cpu_to_le16(IEEE80211_FCTL_MOREDATA); +- } +- +-- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +-+ if (sdata->vif.type == NL80211_IFTYPE_AP) +- sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); +- if (!ieee80211_tx_prepare(sdata, &tx, skb)) +- break; +---- a/net/mac80211/wpa.c +-+++ b/net/mac80211/wpa.c +-@@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee +- hdrlen = ieee80211_hdrlen(hdr->frame_control); +- +- if (!ieee80211_is_data(hdr->frame_control) && +-- !ieee80211_is_robust_mgmt_frame(hdr)) +-+ !ieee80211_is_robust_mgmt_frame(skb)) +- return RX_CONTINUE; +- +- data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - +---- a/net/wireless/ap.c +-+++ b/net/wireless/ap.c +-@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg +- err = rdev_stop_ap(rdev, dev); +- if (!err) { +- wdev->beacon_interval = 0; +-- wdev->channel = NULL; +-+ memset(&wdev->chandef, 0, sizeof(wdev->chandef)); +- wdev->ssid_len = 0; +- rdev_set_qos_map(rdev, dev, NULL); +-+ nl80211_send_ap_stopped(wdev); +- } +- +- return err; +---- a/net/wireless/core.c +-+++ b/net/wireless/core.c +-@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg +- +- rdev->opencount--; +- +-- WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && +-- !rdev->scan_req->notified); +-+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) { +-+ if (WARN_ON(!rdev->scan_req->notified)) +-+ rdev->scan_req->aborted = true; +-+ ___cfg80211_scan_done(rdev, false); +-+ } +- } +- +- static int cfg80211_rfkill_set_block(void *data, bool blocked) +-@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy) +- int i; +- u16 ifmodes = wiphy->interface_modes; +- +-- /* support for 5/10 MHz is broken due to nl80211 API mess - disable */ +-- wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ; +-- +- /* +- * There are major locking problems in nl80211/mac80211 for CSA, +- * disable for all drivers until this has been reworked. +-@@ -795,8 +795,6 @@ void cfg80211_leave(struct cfg80211_regi +- default: +- break; +- } +-- +-- wdev->beacon_interval = 0; +- } +- +- static int cfg80211_netdev_notifier_call(struct notifier_block *nb, +-@@ -875,8 +873,11 @@ static int cfg80211_netdev_notifier_call +- break; +- case NETDEV_DOWN: +- cfg80211_update_iface_num(rdev, wdev->iftype, -1); +-- WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && +-- !rdev->scan_req->notified); +-+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) { +-+ if (WARN_ON(!rdev->scan_req->notified)) +-+ rdev->scan_req->aborted = true; +-+ ___cfg80211_scan_done(rdev, false); +-+ } +- +- if (WARN_ON(rdev->sched_scan_req && +- rdev->sched_scan_req->dev == wdev->netdev)) { +---- a/net/wireless/core.h +-+++ b/net/wireless/core.h +-@@ -62,6 +62,7 @@ struct cfg80211_registered_device { +- struct rb_root bss_tree; +- u32 bss_generation; +- struct cfg80211_scan_request *scan_req; /* protected by RTNL */ +-+ struct sk_buff *scan_msg; +- struct cfg80211_sched_scan_request *sched_scan_req; +- unsigned long suspend_at; +- struct work_struct scan_done_wk; +-@@ -210,6 +211,7 @@ struct cfg80211_event { +- } dc; +- struct { +- u8 bssid[ETH_ALEN]; +-+ struct ieee80211_channel *channel; +- } ij; +- }; +- }; +-@@ -257,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg8021 +- struct net_device *dev, bool nowext); +- int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, +- struct net_device *dev, bool nowext); +--void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); +-+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, +-+ struct ieee80211_channel *channel); +- int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev); +- +-@@ -361,7 +364,8 @@ int cfg80211_validate_key_settings(struc +- struct key_params *params, int key_idx, +- bool pairwise, const u8 *mac_addr); +- void __cfg80211_scan_done(struct work_struct *wk); +--void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); +-+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, +-+ bool send_message); +- void __cfg80211_sched_scan_results(struct work_struct *wk); +- int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, +- bool driver_initiated); +-@@ -441,7 +445,8 @@ static inline unsigned int elapsed_jiffi +- void +- cfg80211_get_chan_state(struct wireless_dev *wdev, +- struct ieee80211_channel **chan, +-- enum cfg80211_chan_mode *chanmode); +-+ enum cfg80211_chan_mode *chanmode, +-+ u8 *radar_detect); +- +- int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, +- struct cfg80211_chan_def *chandef); +---- a/net/wireless/nl80211.c +-+++ b/net/wireless/nl80211.c +-@@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_ +- * We can then retry with the larger buffer. +- */ +- if ((ret == -ENOBUFS || ret == -EMSGSIZE) && +-- !skb->len && +-+ !skb->len && !state->split && +- cb->min_dump_alloc < 4096) { +- cb->min_dump_alloc = 4096; +-+ state->split_start = 0; +- rtnl_unlock(); +- return 1; +- } +-@@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b +- nla_for_each_nested(nl_txq_params, +- info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], +- rem_txq_params) { +-- nla_parse(tb, NL80211_TXQ_ATTR_MAX, +-- nla_data(nl_txq_params), +-- nla_len(nl_txq_params), +-- txq_params_policy); +-+ result = nla_parse(tb, NL80211_TXQ_ATTR_MAX, +-+ nla_data(nl_txq_params), +-+ nla_len(nl_txq_params), +-+ txq_params_policy); +-+ if (result) +-+ goto bad_res; +- result = parse_txq_params(tb, &txq_params); +- if (result) +- goto bad_res; +-@@ -3289,7 +3292,7 @@ static int nl80211_start_ap(struct sk_bu +- if (!err) { +- wdev->preset_chandef = params.chandef; +- wdev->beacon_interval = params.beacon_interval; +-- wdev->channel = params.chandef.chan; +-+ wdev->chandef = params.chandef; +- wdev->ssid_len = params.ssid_len; +- memcpy(wdev->ssid, params.ssid, wdev->ssid_len); +- } +-@@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf +- +- nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], +- rem_reg_rules) { +-- nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, +-- nla_data(nl_reg_rule), nla_len(nl_reg_rule), +-- reg_rule_policy); +-+ r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, +-+ nla_data(nl_reg_rule), nla_len(nl_reg_rule), +-+ reg_rule_policy); +-+ if (r) +-+ goto bad_reg; +- r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); +- if (r) +- goto bad_reg; +-@@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s +- if (!rdev->ops->scan) +- return -EOPNOTSUPP; +- +-- if (rdev->scan_req) { +-+ if (rdev->scan_req || rdev->scan_msg) { +- err = -EBUSY; +- goto unlock; +- } +-@@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru +- enum ieee80211_band band; +- size_t ie_len; +- struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; +-+ s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF; +- +- if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || +- !rdev->ops->sched_scan_start) +-@@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru +- if (n_ssids > wiphy->max_sched_scan_ssids) +- return -EINVAL; +- +-- if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) +-+ /* +-+ * First, count the number of 'real' matchsets. Due to an issue with +-+ * the old implementation, matchsets containing only the RSSI attribute +-+ * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default' +-+ * RSSI for all matchsets, rather than their own matchset for reporting +-+ * all APs with a strong RSSI. This is needed to be compatible with +-+ * older userspace that treated a matchset with only the RSSI as the +-+ * global RSSI for all other matchsets - if there are other matchsets. +-+ */ +-+ if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { +- nla_for_each_nested(attr, +- info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], +-- tmp) +-- n_match_sets++; +-+ tmp) { +-+ struct nlattr *rssi; +-+ +-+ err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, +-+ nla_data(attr), nla_len(attr), +-+ nl80211_match_policy); +-+ if (err) +-+ return err; +-+ /* add other standalone attributes here */ +-+ if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) { +-+ n_match_sets++; +-+ continue; +-+ } +-+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; +-+ if (rssi) +-+ default_match_rssi = nla_get_s32(rssi); +-+ } +-+ } +-+ +-+ /* However, if there's no other matchset, add the RSSI one */ +-+ if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF) +-+ n_match_sets = 1; +- +- if (n_match_sets > wiphy->max_match_sets) +- return -EINVAL; +-@@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru +- tmp) { +- struct nlattr *ssid, *rssi; +- +-- nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, +-- nla_data(attr), nla_len(attr), +-- nl80211_match_policy); +-+ err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, +-+ nla_data(attr), nla_len(attr), +-+ nl80211_match_policy); +-+ if (err) +-+ goto out_free; +- ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; +- if (ssid) { +-+ if (WARN_ON(i >= n_match_sets)) { +-+ /* this indicates a programming error, +-+ * the loop above should have verified +-+ * things properly +-+ */ +-+ err = -EINVAL; +-+ goto out_free; +-+ } +-+ +- if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { +- err = -EINVAL; +- goto out_free; +-@@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru +- nla_data(ssid), nla_len(ssid)); +- request->match_sets[i].ssid.ssid_len = +- nla_len(ssid); +-+ /* special attribute - old implemenation w/a */ +-+ request->match_sets[i].rssi_thold = +-+ default_match_rssi; +-+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; +-+ if (rssi) +-+ request->match_sets[i].rssi_thold = +-+ nla_get_s32(rssi); +- } +-- rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; +-- if (rssi) +-- request->rssi_thold = nla_get_u32(rssi); +-- else +-- request->rssi_thold = +-- NL80211_SCAN_RSSI_THOLD_OFF; +- i++; +- } +-+ +-+ /* there was no other matchset, so the RSSI one is alone */ +-+ if (i == 0) +-+ request->match_sets[0].rssi_thold = default_match_rssi; +-+ +-+ request->min_rssi_thold = INT_MAX; +-+ for (i = 0; i < n_match_sets; i++) +-+ request->min_rssi_thold = +-+ min(request->match_sets[i].rssi_thold, +-+ request->min_rssi_thold); +-+ } else { +-+ request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF; +- } +- +- if (info->attrs[NL80211_ATTR_IE]) { +-@@ -5751,7 +5810,7 @@ static int nl80211_start_radar_detection +- +- err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); +- if (!err) { +-- wdev->channel = chandef.chan; +-+ wdev->chandef = chandef; +- wdev->cac_started = true; +- wdev->cac_start_time = jiffies; +- } +-@@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s +- * directly to the enum ieee80211_band values used in cfg80211. +- */ +- BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); +-- nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) +-- { +-+ nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) { +- enum ieee80211_band band = nla_type(tx_rates); +-+ int err; +-+ +- if (band < 0 || band >= IEEE80211_NUM_BANDS) +- return -EINVAL; +- sband = rdev->wiphy.bands[band]; +- if (sband == NULL) +- return -EINVAL; +-- nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), +-- nla_len(tx_rates), nl80211_txattr_policy); +-+ err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), +-+ nla_len(tx_rates), nl80211_txattr_policy); +-+ if (err) +-+ return err; +- if (tb[NL80211_TXRATE_LEGACY]) { +- mask.control[band].legacy = rateset_to_mask( +- sband, +-@@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8 +- NL80211_MCGRP_SCAN, GFP_KERNEL); +- } +- +--void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, +-- struct wireless_dev *wdev) +-+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, +-+ struct wireless_dev *wdev, bool aborted) +- { +- struct sk_buff *msg; +- +- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +- if (!msg) +-- return; +-+ return NULL; +- +- if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, +-- NL80211_CMD_NEW_SCAN_RESULTS) < 0) { +-+ aborted ? NL80211_CMD_SCAN_ABORTED : +-+ NL80211_CMD_NEW_SCAN_RESULTS) < 0) { +- nlmsg_free(msg); +-- return; +-+ return NULL; +- } +- +-- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, +-- NL80211_MCGRP_SCAN, GFP_KERNEL); +-+ return msg; +- } +- +--void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, +-- struct wireless_dev *wdev) +-+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, +-+ struct sk_buff *msg) +- { +-- struct sk_buff *msg; +-- +-- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +- if (!msg) +- return; +- +-- if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, +-- NL80211_CMD_SCAN_ABORTED) < 0) { +-- nlmsg_free(msg); +-- return; +-- } +-- +- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, +- NL80211_MCGRP_SCAN, GFP_KERNEL); +- } +-@@ -11158,7 +11211,8 @@ void cfg80211_ch_switch_notify(struct ne +- wdev->iftype != NL80211_IFTYPE_MESH_POINT)) +- return; +- +-- wdev->channel = chandef->chan; +-+ wdev->chandef = *chandef; +-+ wdev->preset_chandef = *chandef; +- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); +- } +- EXPORT_SYMBOL(cfg80211_ch_switch_notify); +-@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct +- } +- EXPORT_SYMBOL(cfg80211_crit_proto_stopped); +- +-+void nl80211_send_ap_stopped(struct wireless_dev *wdev) +-+{ +-+ struct wiphy *wiphy = wdev->wiphy; +-+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); +-+ struct sk_buff *msg; +-+ void *hdr; +-+ +-+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +-+ if (!msg) +-+ return; +-+ +-+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP); +-+ if (!hdr) +-+ goto out; +-+ +-+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || +-+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || +-+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) +-+ goto out; +-+ +-+ genlmsg_end(msg, hdr); +-+ +-+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, +-+ NL80211_MCGRP_MLME, GFP_KERNEL); +-+ return; +-+ out: +-+ nlmsg_free(msg); +-+} +-+ +- /* initialisation/exit functions */ +- +- int nl80211_init(void) +---- a/net/wireless/nl80211.h +-+++ b/net/wireless/nl80211.h +-@@ -8,10 +8,10 @@ void nl80211_exit(void); +- void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); +- void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev); +--void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, +-- struct wireless_dev *wdev); +--void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, +-- struct wireless_dev *wdev); +-+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, +-+ struct wireless_dev *wdev, bool aborted); +-+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, +-+ struct sk_buff *msg); +- void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, +- struct net_device *netdev, u32 cmd); +- void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, +-@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg +- enum nl80211_radar_event event, +- struct net_device *netdev, gfp_t gfp); +- +-+void nl80211_send_ap_stopped(struct wireless_dev *wdev); +-+ +- void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); +- +- #endif /* __NET_WIRELESS_NL80211_H */ +---- a/net/wireless/scan.c +-+++ b/net/wireless/scan.c +-@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct +- dev->bss_generation++; +- } +- +--void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) +-+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, +-+ bool send_message) +- { +- struct cfg80211_scan_request *request; +- struct wireless_dev *wdev; +-+ struct sk_buff *msg; +- #ifdef CPTCFG_CFG80211_WEXT +- union iwreq_data wrqu; +- #endif +- +- ASSERT_RTNL(); +- +-- request = rdev->scan_req; +-+ if (rdev->scan_msg) { +-+ nl80211_send_scan_result(rdev, rdev->scan_msg); +-+ rdev->scan_msg = NULL; +-+ return; +-+ } +- +-+ request = rdev->scan_req; +- if (!request) +- return; +- +-@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802 +- if (wdev->netdev) +- cfg80211_sme_scan_done(wdev->netdev); +- +-- if (request->aborted) { +-- nl80211_send_scan_aborted(rdev, wdev); +-- } else { +-- if (request->flags & NL80211_SCAN_FLAG_FLUSH) { +-- /* flush entries from previous scans */ +-- spin_lock_bh(&rdev->bss_lock); +-- __cfg80211_bss_expire(rdev, request->scan_start); +-- spin_unlock_bh(&rdev->bss_lock); +-- } +-- nl80211_send_scan_done(rdev, wdev); +-+ if (!request->aborted && +-+ request->flags & NL80211_SCAN_FLAG_FLUSH) { +-+ /* flush entries from previous scans */ +-+ spin_lock_bh(&rdev->bss_lock); +-+ __cfg80211_bss_expire(rdev, request->scan_start); +-+ spin_unlock_bh(&rdev->bss_lock); +- } +- +-+ msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); +-+ +- #ifdef CPTCFG_CFG80211_WEXT +- if (wdev->netdev && !request->aborted) { +- memset(&wrqu, 0, sizeof(wrqu)); +-@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802 +- +- rdev->scan_req = NULL; +- kfree(request); +-+ +-+ if (!send_message) +-+ rdev->scan_msg = msg; +-+ else +-+ nl80211_send_scan_result(rdev, msg); +- } +- +- void __cfg80211_scan_done(struct work_struct *wk) +-@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st +- scan_done_wk); +- +- rtnl_lock(); +-- ___cfg80211_scan_done(rdev); +-+ ___cfg80211_scan_done(rdev, true); +- rtnl_unlock(); +- } +- +-@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev +- if (IS_ERR(rdev)) +- return PTR_ERR(rdev); +- +-- if (rdev->scan_req) { +-+ if (rdev->scan_req || rdev->scan_msg) { +- err = -EBUSY; +- goto out; +- } +-@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev +- if (IS_ERR(rdev)) +- return PTR_ERR(rdev); +- +-- if (rdev->scan_req) +-+ if (rdev->scan_req || rdev->scan_msg) +- return -EAGAIN; +- +- res = ieee80211_scan_results(rdev, info, extra, data->length); +---- a/net/wireless/sme.c +-+++ b/net/wireless/sme.c +-@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir +- ASSERT_RDEV_LOCK(rdev); +- ASSERT_WDEV_LOCK(wdev); +- +-- if (rdev->scan_req) +-+ if (rdev->scan_req || rdev->scan_msg) +- return -EBUSY; +- +- if (wdev->conn->params.channel) +---- a/net/mac80211/mlme.c +-+++ b/net/mac80211/mlme.c +-@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct +- } +- +- ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; +-- sdata->vif.csa_active = true; +- +- mutex_lock(&local->chanctx_mtx); +- if (local->use_chanctx) { +-@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct +- mutex_unlock(&local->chanctx_mtx); +- +- sdata->csa_chandef = csa_ie.chandef; +-+ sdata->vif.csa_active = true; +- +- if (csa_ie.mode) +- ieee80211_stop_queues_by_reason(&local->hw, +---- a/net/mac80211/chan.c +-+++ b/net/mac80211/chan.c +-@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required( +- { +- struct ieee80211_sub_if_data *sdata; +- +-+ lockdep_assert_held(&local->mtx); +-+ +- rcu_read_lock(); +- list_for_each_entry_rcu(sdata, &local->interfaces, list) { +- if (sdata->radar_required) { +---- a/net/mac80211/ibss.c +-+++ b/net/mac80211/ibss.c +-@@ -294,7 +294,6 @@ static void __ieee80211_sta_join_ibss(st +- } +- +- mutex_lock(&local->mtx); +-- ieee80211_vif_release_channel(sdata); +- if (ieee80211_vif_use_channel(sdata, &chandef, +- ifibss->fixed_channel ? +- IEEE80211_CHANCTX_SHARED : +-@@ -303,6 +302,7 @@ static void __ieee80211_sta_join_ibss(st +- mutex_unlock(&local->mtx); +- return; +- } +-+ sdata->radar_required = radar_required; +- mutex_unlock(&local->mtx); +- +- memcpy(ifibss->bssid, bssid, ETH_ALEN); +-@@ -318,7 +318,6 @@ static void __ieee80211_sta_join_ibss(st +- rcu_assign_pointer(ifibss->presp, presp); +- mgmt = (void *)presp->head; +- +-- sdata->radar_required = radar_required; +- sdata->vif.bss_conf.enable_beacon = true; +- sdata->vif.bss_conf.beacon_int = beacon_int; +- sdata->vif.bss_conf.basic_rates = basic_rates; +-@@ -386,7 +385,7 @@ static void __ieee80211_sta_join_ibss(st +- presp->head_len, 0, GFP_KERNEL); +- cfg80211_put_bss(local->hw.wiphy, bss); +- netif_carrier_on(sdata->dev); +-- cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); +-+ cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); +- } +- +- static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, +-@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct +- int err; +- u32 sta_flags; +- +-+ sdata_assert_lock(sdata); +-+ +- sta_flags = IEEE80211_STA_DISABLE_VHT; +- switch (ifibss->chandef.width) { +- case NL80211_CHAN_WIDTH_5: +-@@ -1471,6 +1472,11 @@ static void ieee80211_rx_mgmt_probe_req( +- memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); +- ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); +- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; +-+ +-+ /* avoid excessive retries for probe request to wildcard SSIDs */ +-+ if (pos[1] == 0) +-+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; +-+ +- ieee80211_tx_skb(sdata, skb); +- } +- +---- a/net/mac80211/mesh.c +-+++ b/net/mac80211/mesh.c +-@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct +- if (!ifmsh->mesh_id) +- return false; +- +-+ sdata_assert_lock(sdata); +-+ +- sta_flags = IEEE80211_STA_DISABLE_VHT; +- switch (sdata->vif.bss_conf.chandef.width) { +- case NL80211_CHAN_WIDTH_20_NOHT: +---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +-@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf +- struct brcmf_cfg80211_info *cfg = ifp->drvr->config; +- struct net_device *ndev = ifp->ndev; +- struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; +-+ struct ieee80211_channel *chan; +- s32 err = 0; +- +- if (ifp->vif->mode == WL_MODE_AP) { +-@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf +- } else if (brcmf_is_linkup(e)) { +- brcmf_dbg(CONN, "Linkup\n"); +- if (brcmf_is_ibssmode(ifp->vif)) { +-+ chan = ieee80211_get_channel(cfg->wiphy, cfg->channel); +- memcpy(profile->bssid, e->addr, ETH_ALEN); +- wl_inform_ibss(cfg, ndev, e->addr); +-- cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); +-+ cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL); +- clear_bit(BRCMF_VIF_STATUS_CONNECTING, +- &ifp->vif->sme_state); +- set_bit(BRCMF_VIF_STATUS_CONNECTED, +---- a/drivers/net/wireless/libertas/cfg.c +-+++ b/drivers/net/wireless/libertas/cfg.c +-@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_pri +- memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); +- priv->wdev->ssid_len = params->ssid_len; +- +-- cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL); +-+ cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan, +-+ GFP_KERNEL); +- +- /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */ +- priv->connect_status = LBS_CONNECTED; +---- a/drivers/net/wireless/mwifiex/cfg80211.c +-+++ b/drivers/net/wireless/mwifiex/cfg80211.c +-@@ -1881,7 +1881,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy +- params->privacy); +- done: +- if (!ret) { +-- cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); +-+ cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, +-+ params->chandef.chan, GFP_KERNEL); +- dev_dbg(priv->adapter->dev, +- "info: joined/created adhoc network with bssid" +- " %pM successfully\n", priv->cfg_bssid); +---- a/drivers/net/wireless/rndis_wlan.c +-+++ b/drivers/net/wireless/rndis_wlan.c +-@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(s +- bssid, req_ie, req_ie_len, +- resp_ie, resp_ie_len, GFP_KERNEL); +- } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) +-- cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); +-+ cfg80211_ibss_joined(usbdev->net, bssid, +-+ get_current_channel(usbdev, NULL), +-+ GFP_KERNEL); +- +- kfree(info); +- +---- a/net/wireless/ibss.c +-+++ b/net/wireless/ibss.c +-@@ -14,7 +14,8 @@ +- #include "rdev-ops.h" +- +- +--void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) +-+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, +-+ struct ieee80211_channel *channel) +- { +- struct wireless_dev *wdev = dev->ieee80211_ptr; +- struct cfg80211_bss *bss; +-@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d +- if (!wdev->ssid_len) +- return; +- +-- bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, +-- wdev->ssid, wdev->ssid_len, +-+ bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, +- WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); +- +- if (WARN_ON(!bss)) +-@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d +- #endif +- } +- +--void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) +-+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, +-+ struct ieee80211_channel *channel, gfp_t gfp) +- { +- struct wireless_dev *wdev = dev->ieee80211_ptr; +- struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); +- struct cfg80211_event *ev; +- unsigned long flags; +- +-- trace_cfg80211_ibss_joined(dev, bssid); +-+ trace_cfg80211_ibss_joined(dev, bssid, channel); +-+ +-+ if (WARN_ON(!channel)) +-+ return; +- +- ev = kzalloc(sizeof(*ev), gfp); +- if (!ev) +- return; +- +- ev->type = EVENT_IBSS_JOINED; +-- memcpy(ev->cr.bssid, bssid, ETH_ALEN); +-+ memcpy(ev->ij.bssid, bssid, ETH_ALEN); +-+ ev->ij.channel = channel; +- +- spin_lock_irqsave(&wdev->event_lock, flags); +- list_add_tail(&ev->list, &wdev->event_list); +-@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211 +- +- wdev->ibss_fixed = params->channel_fixed; +- wdev->ibss_dfs_possible = params->userspace_handles_dfs; +-+ wdev->chandef = params->chandef; +- #ifdef CPTCFG_CFG80211_WEXT +- wdev->wext.ibss.chandef = params->chandef; +- #endif +-@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct +- +- wdev->current_bss = NULL; +- wdev->ssid_len = 0; +-+ memset(&wdev->chandef, 0, sizeof(wdev->chandef)); +- #ifdef CPTCFG_CFG80211_WEXT +- if (!nowext) +- wdev->wext.ibss.ssid_len = 0; +---- a/net/wireless/trace.h +-+++ b/net/wireless/trace.h +-@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt, +- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) +- ); ++--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++@@ -1004,11 +1004,9 @@ static bool ar5008_hw_ani_control_new(st ++ case ATH9K_ANI_FIRSTEP_LEVEL:{ ++ u32 level = param; + +--DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, +-- TP_PROTO(struct net_device *netdev, const u8 *addr), +-- TP_ARGS(netdev, addr) +--); +-- +- DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, +- TP_PROTO(struct net_device *netdev, const u8 *addr), +- TP_ARGS(netdev, addr) +-@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r +- TP_ARGS(netdev, addr) +- ); ++- value = level * 2; +++ value = level; ++ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, ++ AR_PHY_FIND_SIG_FIRSTEP, value); ++- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, ++- AR_PHY_FIND_SIG_FIRSTEP_LOW, value); + +-+TRACE_EVENT(cfg80211_ibss_joined, +-+ TP_PROTO(struct net_device *netdev, const u8 *bssid, +-+ struct ieee80211_channel *channel), +-+ TP_ARGS(netdev, bssid, channel), +-+ TP_STRUCT__entry( +-+ NETDEV_ENTRY +-+ MAC_ENTRY(bssid) +-+ CHAN_ENTRY +-+ ), +-+ TP_fast_assign( +-+ NETDEV_ASSIGN; +-+ MAC_ASSIGN(bssid, bssid); +-+ CHAN_ASSIGN(channel); +-+ ), +-+ TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT, +-+ NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) +-+); +-+ +- TRACE_EVENT(cfg80211_probe_status, +- TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, +- bool acked), +---- a/net/wireless/util.c +-+++ b/net/wireless/util.c +-@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct +- ev->dc.reason, true); +- break; +- case EVENT_IBSS_JOINED: +-- __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid); +-+ __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, +-+ ev->ij.channel); +- break; +- } +- wdev_unlock(wdev); +-@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct +- */ +- mutex_lock_nested(&wdev_iter->mtx, 1); +- __acquire(wdev_iter->mtx); +-- cfg80211_get_chan_state(wdev_iter, &ch, &chmode); +-+ cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect); +- wdev_unlock(wdev_iter); ++ if (level != aniState->firstepLevel) { ++ ath_dbg(common, ANI, ++--- a/drivers/net/wireless/ath/ath9k/beacon.c +++++ b/drivers/net/wireless/ath/ath9k/beacon.c ++@@ -312,10 +312,9 @@ static void ath9k_csa_update_vif(void *d + +- switch (chmode) { +---- a/net/wireless/chan.c +-+++ b/net/wireless/chan.c +-@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct +- void +- cfg80211_get_chan_state(struct wireless_dev *wdev, +- struct ieee80211_channel **chan, +-- enum cfg80211_chan_mode *chanmode) +-+ enum cfg80211_chan_mode *chanmode, +-+ u8 *radar_detect) ++ void ath9k_csa_update(struct ath_softc *sc) + { +- *chan = NULL; +- *chanmode = CHAN_MODE_UNDEFINED; +-@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_ +- !wdev->ibss_dfs_possible) +- ? CHAN_MODE_SHARED +- : CHAN_MODE_EXCLUSIVE; +-+ +-+ /* consider worst-case - IBSS can try to return to the +-+ * original user-specified channel as creator */ +-+ if (wdev->ibss_dfs_possible) +-+ *radar_detect |= BIT(wdev->chandef.width); +- return; +- } +- break; +-@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_ +- case NL80211_IFTYPE_AP: +- case NL80211_IFTYPE_P2P_GO: +- if (wdev->cac_started) { +-- *chan = wdev->channel; +-+ *chan = wdev->chandef.chan; +- *chanmode = CHAN_MODE_SHARED; +-+ *radar_detect |= BIT(wdev->chandef.width); +- } else if (wdev->beacon_interval) { +-- *chan = wdev->channel; +-+ *chan = wdev->chandef.chan; +- *chanmode = CHAN_MODE_SHARED; +-+ +-+ if (cfg80211_chandef_dfs_required(wdev->wiphy, +-+ &wdev->chandef)) +-+ *radar_detect |= BIT(wdev->chandef.width); +- } +- return; +- case NL80211_IFTYPE_MESH_POINT: +- if (wdev->mesh_id_len) { +-- *chan = wdev->channel; +-+ *chan = wdev->chandef.chan; +- *chanmode = CHAN_MODE_SHARED; +-+ +-+ if (cfg80211_chandef_dfs_required(wdev->wiphy, +-+ &wdev->chandef)) +-+ *radar_detect |= BIT(wdev->chandef.width); +- } +- return; +- case NL80211_IFTYPE_MONITOR: +---- a/net/wireless/mesh.c +-+++ b/net/wireless/mesh.c +-@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211 +- if (!err) { +- memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); +- wdev->mesh_id_len = setup->mesh_id_len; +-- wdev->channel = setup->chandef.chan; +-+ wdev->chandef = setup->chandef; +- } +- +- return err; +-@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg +- err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, +- chandef->chan); +- if (!err) +-- wdev->channel = chandef->chan; +-+ wdev->chandef = *chandef; +- +- return err; +- } +-@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct +- err = rdev_leave_mesh(rdev, dev); +- if (!err) { +- wdev->mesh_id_len = 0; +-- wdev->channel = NULL; +-+ memset(&wdev->chandef, 0, sizeof(wdev->chandef)); +- rdev_set_qos_map(rdev, dev, NULL); +- } +- +---- a/net/wireless/mlme.c +-+++ b/net/wireless/mlme.c +-@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic +- if (WARN_ON(!wdev->cac_started)) +- return; +- +-- if (WARN_ON(!wdev->channel)) +-+ if (WARN_ON(!wdev->chandef.chan)) +- return; +- +- switch (event) { +---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +-@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power( +- break; +- } +- } +-+ +-+ if (is2GHz && !twiceMaxEdgePower) +-+ twiceMaxEdgePower = 60; +-+ +- return twiceMaxEdgePower; +- } +- +---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c +-@@ -23,10 +23,11 @@ +- #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT +- #define MAX_MAG_DELTA 11 +- #define MAX_PHS_DELTA 10 +-+#define MAXIQCAL 3 +- +- struct coeff { +-- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; +-- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; +-+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL]; +-+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL]; +- int iqc_coeff[2]; +- }; +- +-@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc +- if (q_q_coff > 63) +- q_q_coff = 63; +- +-- iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; +-+ iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff); +- +- ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n", +- chain_idx, iqc_coeff[0]); +-@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc +- if (q_q_coff > 63) +- q_q_coff = 63; +- +-- iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; +-+ iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff); +- +- ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n", +- chain_idx, iqc_coeff[1]); +-@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc +- return true; ++- ieee80211_iterate_active_interfaces(sc->hw, ++- IEEE80211_IFACE_ITER_NORMAL, ++- ath9k_csa_update_vif, ++- sc); +++ ieee80211_iterate_active_interfaces_atomic(sc->hw, +++ IEEE80211_IFACE_ITER_NORMAL, +++ ath9k_csa_update_vif, sc); + } + +--static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, +-+static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL], +-+ int nmeasurement, +- int max_delta) +- { +- int mp_max = -64, max_idx = 0; +-@@ -848,20 +850,20 @@ static void ar9003_hw_detect_outlier(int +- +- /* find min/max mismatch across all calibrated gains */ +- for (i = 0; i < nmeasurement; i++) { +-- if (mp_coeff[i] > mp_max) { +-- mp_max = mp_coeff[i]; +-+ if (mp_coeff[i][0] > mp_max) { +-+ mp_max = mp_coeff[i][0]; +- max_idx = i; +-- } else if (mp_coeff[i] < mp_min) { +-- mp_min = mp_coeff[i]; +-+ } else if (mp_coeff[i][0] < mp_min) { +-+ mp_min = mp_coeff[i][0]; +- min_idx = i; +- } +- } +- +- /* find average (exclude max abs value) */ +- for (i = 0; i < nmeasurement; i++) { +-- if ((abs(mp_coeff[i]) < abs(mp_max)) || +-- (abs(mp_coeff[i]) < abs(mp_min))) { +-- mp_avg += mp_coeff[i]; +-+ if ((abs(mp_coeff[i][0]) < abs(mp_max)) || +-+ (abs(mp_coeff[i][0]) < abs(mp_min))) { +-+ mp_avg += mp_coeff[i][0]; +- mp_count++; +- } +- } +-@@ -873,7 +875,7 @@ static void ar9003_hw_detect_outlier(int +- if (mp_count) +- mp_avg /= mp_count; +- else +-- mp_avg = mp_coeff[nmeasurement - 1]; +-+ mp_avg = mp_coeff[nmeasurement - 1][0]; +- +- /* detect outlier */ +- if (abs(mp_max - mp_min) > max_delta) { +-@@ -882,15 +884,16 @@ static void ar9003_hw_detect_outlier(int +- else +- outlier_idx = min_idx; +- +-- mp_coeff[outlier_idx] = mp_avg; +-+ mp_coeff[outlier_idx][0] = mp_avg; ++ void ath9k_beacon_tasklet(unsigned long data) ++--- a/net/mac80211/main.c +++++ b/net/mac80211/main.c ++@@ -152,6 +152,8 @@ static u32 ieee80211_hw_conf_chan(struct ++ list_for_each_entry_rcu(sdata, &local->interfaces, list) { ++ if (!rcu_access_pointer(sdata->vif.chanctx_conf)) ++ continue; +++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +++ continue; ++ power = min(power, sdata->vif.bss_conf.txpower); + } +- } +- +--static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, +-- struct coeff *coeff, +-- bool is_reusable) +-+static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah, +-+ struct coeff *coeff, +-+ bool is_reusable) +- { +- int i, im, nmeasurement; +-+ int magnitude, phase; +- u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; +- struct ath9k_hw_cal_data *caldata = ah->caldata; +- +-@@ -920,21 +923,30 @@ static void ar9003_hw_tx_iqcal_load_avg_ +- if (nmeasurement > MAX_MEASUREMENT) +- nmeasurement = MAX_MEASUREMENT; +- +-- /* detect outlier only if nmeasurement > 1 */ +-- if (nmeasurement > 1) { +-- /* Detect magnitude outlier */ +-- ar9003_hw_detect_outlier(coeff->mag_coeff[i], +-- nmeasurement, MAX_MAG_DELTA); +-- +-- /* Detect phase outlier */ +-- ar9003_hw_detect_outlier(coeff->phs_coeff[i], +-- nmeasurement, MAX_PHS_DELTA); +-+ /* +-+ * Skip normal outlier detection for AR9550. +-+ */ +-+ if (!AR_SREV_9550(ah)) { +-+ /* detect outlier only if nmeasurement > 1 */ +-+ if (nmeasurement > 1) { +-+ /* Detect magnitude outlier */ +-+ ar9003_hw_detect_outlier(coeff->mag_coeff[i], +-+ nmeasurement, +-+ MAX_MAG_DELTA); +-+ +-+ /* Detect phase outlier */ +-+ ar9003_hw_detect_outlier(coeff->phs_coeff[i], +-+ nmeasurement, +-+ MAX_PHS_DELTA); +-+ } +- } +- +- for (im = 0; im < nmeasurement; im++) { +-+ magnitude = coeff->mag_coeff[i][im][0]; +-+ phase = coeff->phs_coeff[i][im][0]; +- +-- coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | +-- ((coeff->phs_coeff[i][im] & 0x7f) << 7); +-+ coeff->iqc_coeff[0] = +-+ (phase & 0x7f) | ((magnitude & 0x7f) << 7); +- +- if ((im % 2) == 0) +- REG_RMW_FIELD(ah, tx_corr_coeff[im][i], +-@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru +- return true; +- } +- +--static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) +-+static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah, +-+ struct coeff *coeff, +-+ int i, int nmeasurement) +-+{ +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ int im, ix, iy, temp; +-+ +-+ for (im = 0; im < nmeasurement; im++) { +-+ for (ix = 0; ix < MAXIQCAL - 1; ix++) { +-+ for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) { +-+ if (coeff->mag_coeff[i][im][iy] < +-+ coeff->mag_coeff[i][im][ix]) { +-+ temp = coeff->mag_coeff[i][im][ix]; +-+ coeff->mag_coeff[i][im][ix] = +-+ coeff->mag_coeff[i][im][iy]; +-+ coeff->mag_coeff[i][im][iy] = temp; +-+ } +-+ if (coeff->phs_coeff[i][im][iy] < +-+ coeff->phs_coeff[i][im][ix]) { +-+ temp = coeff->phs_coeff[i][im][ix]; +-+ coeff->phs_coeff[i][im][ix] = +-+ coeff->phs_coeff[i][im][iy]; +-+ coeff->phs_coeff[i][im][iy] = temp; +-+ } +-+ } +-+ } +-+ coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2]; +-+ coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2]; +-+ +-+ ath_dbg(common, CALIBRATE, +-+ "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n", +-+ i, im, +-+ coeff->mag_coeff[i][im][0], +-+ coeff->phs_coeff[i][im][0]); +-+ } +-+} +-+ +-+static bool ar955x_tx_iq_cal_median(struct ath_hw *ah, +-+ struct coeff *coeff, +-+ int iqcal_idx, +-+ int nmeasurement) +-+{ +-+ int i; +-+ +-+ if ((iqcal_idx + 1) != MAXIQCAL) +-+ return false; +-+ +-+ for (i = 0; i < AR9300_MAX_CHAINS; i++) { +-+ __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement); +-+ } +-+ +-+ return true; +-+} +-+ +-+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, +-+ int iqcal_idx, +-+ bool is_reusable) ++ rcu_read_unlock(); ++@@ -203,7 +205,7 @@ void ieee80211_bss_info_change_notify(st + { +- struct ath_common *common = ath9k_hw_common(ah); +- const u32 txiqcal_status[AR9300_MAX_CHAINS] = { +-@@ -1004,10 +1072,11 @@ static void ar9003_hw_tx_iq_cal_post_pro +- AR_PHY_CHAN_INFO_TAB_1, +- AR_PHY_CHAN_INFO_TAB_2, +- }; +-- struct coeff coeff; +-+ static struct coeff coeff; +- s32 iq_res[6]; +- int i, im, j; +-- int nmeasurement; +-+ int nmeasurement = 0; +-+ bool outlier_detect = true; +- +- for (i = 0; i < AR9300_MAX_CHAINS; i++) { +- if (!(ah->txchainmask & (1 << i))) +-@@ -1065,17 +1134,23 @@ static void ar9003_hw_tx_iq_cal_post_pro +- goto tx_iqcal_fail; +- } +- +-- coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; +-- coeff.phs_coeff[i][im] = +-+ coeff.phs_coeff[i][im][iqcal_idx] = +-+ coeff.iqc_coeff[0] & 0x7f; +-+ coeff.mag_coeff[i][im][iqcal_idx] = +- (coeff.iqc_coeff[0] >> 7) & 0x7f; +- +-- if (coeff.mag_coeff[i][im] > 63) +-- coeff.mag_coeff[i][im] -= 128; +-- if (coeff.phs_coeff[i][im] > 63) +-- coeff.phs_coeff[i][im] -= 128; +-+ if (coeff.mag_coeff[i][im][iqcal_idx] > 63) +-+ coeff.mag_coeff[i][im][iqcal_idx] -= 128; +-+ if (coeff.phs_coeff[i][im][iqcal_idx] > 63) +-+ coeff.phs_coeff[i][im][iqcal_idx] -= 128; +- } +- } +-- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable); +-+ +-+ if (AR_SREV_9550(ah)) +-+ outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff, +-+ iqcal_idx, nmeasurement); +-+ if (outlier_detect) +-+ ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable); +- +- return; +- +-@@ -1409,7 +1484,7 @@ skip_tx_iqcal: +- } ++ struct ieee80211_local *local = sdata->local; + +- if (txiqcal_done) +-- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); +-+ ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable); +- else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) +- ar9003_hw_tx_iq_cal_reload(ah); ++- if (!changed) +++ if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ return; + +-@@ -1455,14 +1530,38 @@ skip_tx_iqcal: +- return true; +- } ++ drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); ++--- a/drivers/net/wireless/ath/ath9k/ani.c +++++ b/drivers/net/wireless/ath/ath9k/ani.c ++@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct ++ ATH9K_ANI_RSSI_THR_LOW, ++ ATH9K_ANI_RSSI_THR_HIGH); + +-+static bool do_ar9003_agc_cal(struct ath_hw *ah) +-+{ +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ bool status; +++ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL) +++ immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; + + +-+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, +-+ REG_READ(ah, AR_PHY_AGC_CONTROL) | +-+ AR_PHY_AGC_CONTROL_CAL); +-+ +-+ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, +-+ AR_PHY_AGC_CONTROL_CAL, +-+ 0, AH_WAIT_TIMEOUT); +-+ if (!status) { +-+ ath_dbg(common, CALIBRATE, +-+ "offset calibration failed to complete in %d ms," +-+ "noisy environment?\n", +-+ AH_WAIT_TIMEOUT / 1000); +-+ return false; +-+ } +-+ +-+ return true; +-+} +-+ +- static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, +- struct ath9k_channel *chan) +- { +- struct ath_common *common = ath9k_hw_common(ah); +- struct ath9k_hw_cal_data *caldata = ah->caldata; +- bool txiqcal_done = false; +-- bool is_reusable = true, status = true; +-+ bool status = true; +- bool run_agc_cal = false, sep_iq_cal = false; +-+ int i = 0; +- +- /* Use chip chainmask only for calibration */ +- ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); +-@@ -1485,7 +1584,12 @@ static bool ar9003_hw_init_cal_soc(struc +- * AGC calibration. Specifically, AR9550 in SoC chips. +- */ +- if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { +-- txiqcal_done = true; +-+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0, +-+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) { +-+ txiqcal_done = true; +-+ } else { +-+ txiqcal_done = false; +-+ } +- run_agc_cal = true; +- } else { +- sep_iq_cal = true; +-@@ -1512,27 +1616,37 @@ skip_tx_iqcal: +- if (AR_SREV_9330_11(ah)) +- ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); +- +-- /* Calibrate the AGC */ +-- REG_WRITE(ah, AR_PHY_AGC_CONTROL, +-- REG_READ(ah, AR_PHY_AGC_CONTROL) | +-- AR_PHY_AGC_CONTROL_CAL); +-- +-- /* Poll for offset calibration complete */ +-- status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, +-- AR_PHY_AGC_CONTROL_CAL, +-- 0, AH_WAIT_TIMEOUT); +-- } +-+ /* +-+ * For non-AR9550 chips, we just trigger AGC calibration +-+ * in the HW, poll for completion and then process +-+ * the results. +-+ * +-+ * For AR955x, we run it multiple times and use +-+ * median IQ correction. +-+ */ +-+ if (!AR_SREV_9550(ah)) { +-+ status = do_ar9003_agc_cal(ah); +-+ if (!status) +-+ return false; +- +-- if (!status) { +-- ath_dbg(common, CALIBRATE, +-- "offset calibration failed to complete in %d ms; noisy environment?\n", +-- AH_WAIT_TIMEOUT / 1000); +-- return false; +-+ if (txiqcal_done) +-+ ar9003_hw_tx_iq_cal_post_proc(ah, 0, false); +-+ } else { +-+ if (!txiqcal_done) { +-+ status = do_ar9003_agc_cal(ah); +-+ if (!status) +-+ return false; +-+ } else { +-+ for (i = 0; i < MAXIQCAL; i++) { +-+ status = do_ar9003_agc_cal(ah); +-+ if (!status) +-+ return false; +-+ ar9003_hw_tx_iq_cal_post_proc(ah, i, false); +-+ } +-+ } +-+ } +- } +- +-- if (txiqcal_done) +-- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); +-- +- /* Revert chainmask to runtime parameters */ +- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ++ if (!scan) ++ aniState->ofdmNoiseImmunityLevel = immunityLevel; + +---- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +-+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +-@@ -15,6 +15,8 @@ +- #ifndef RTL8187_H +- #define RTL8187_H ++@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct ++ BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW, ++ ATH9K_ANI_RSSI_THR_HIGH); + +-+#include +++ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL) +++ immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; + + +- #include "rtl818x.h" +- #include "leds.h" +- +-@@ -139,7 +141,10 @@ struct rtl8187_priv { +- u8 aifsn[4]; +- u8 rfkill_mask; +- struct { +-- __le64 buf; +-+ union { +-+ __le64 buf; +-+ u8 dummy1[L1_CACHE_BYTES]; +-+ } ____cacheline_aligned; +- struct sk_buff_head queue; +- } b_tx_status; /* This queue is used by both -b and non-b devices */ +- struct mutex io_mutex; +-@@ -147,7 +152,8 @@ struct rtl8187_priv { +- u8 bits8; +- __le16 bits16; +- __le32 bits32; +-- } *io_dmabuf; +-+ u8 dummy2[L1_CACHE_BYTES]; +-+ } *io_dmabuf ____cacheline_aligned; +- bool rfkill_off; +- u16 seqno; ++ if (ah->opmode == NL80211_IFTYPE_STATION && ++ BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW && ++ immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) ++--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++++ b/drivers/net/wireless/ath/ath9k/ath9k.h ++@@ -251,7 +251,6 @@ struct ath_atx_tid { ++ ++ s8 bar_index; ++ bool sched; ++- bool paused; ++ bool active; + }; +---- a/net/mac80211/wme.c +-+++ b/net/mac80211/wme.c +-@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80 +- return IEEE80211_AC_BE; +- } + +-+ if (skb->protocol == sdata->control_port_protocol) { +-+ skb->priority = 7; +-+ return ieee80211_downgrade_queue(sdata, skb); +-+ } +-+ +- /* use the data classifier to determine what 802.1d tag the +- * data frame has */ +- rcu_read_lock(); + --- a/drivers/net/wireless/ath/ath9k/xmit.c + +++ b/drivers/net/wireless/ath/ath9k/xmit.c +-@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_ +- for (tidno = 0, tid = &an->tid[tidno]; +- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { +- +-- if (!tid->sched) +-- continue; +-- +- ac = tid->ac; +- txq = ac->txq; +- +- ath_txq_lock(sc, txq); +- +-+ if (!tid->sched) { +-+ ath_txq_unlock(sc, txq); +-+ continue; +-+ } +-+ +- buffered = ath_tid_has_buffered(tid); +- +- tid->sched = false; +-@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc +- +- ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); +- +-- qi.tqi_readyTime = (cur_conf->beacon_interval * +-+ qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) * +- ATH_CABQ_READY_TIME) / 100; +- ath_txq_update(sc, qnum, &qi); +- +-@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff +- +- ATH_TXBUF_RESET(bf); +- +-- if (tid) { +-+ if (tid && ieee80211_is_data_present(hdr->frame_control)) { +- fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; +- seqno = tid->seq_next; +- hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); +-@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw +- txq->stopped = true; +- } +- +-+ if (txctl->an && ieee80211_is_data_present(hdr->frame_control)) +-+ tid = ath_get_skb_tid(sc, txctl->an, skb); +-+ +- if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) { +- ath_txq_unlock(sc, txq); +- txq = sc->tx.uapsdq; +- ath_txq_lock(sc, txq); +- } else if (txctl->an && +- ieee80211_is_data_present(hdr->frame_control)) { +-- tid = ath_get_skb_tid(sc, txctl->an, skb); +-- +- WARN_ON(tid->ac->txq != txctl->txq); +- +- if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) +---- a/drivers/net/wireless/ath/ath9k/init.c +-+++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -943,6 +943,7 @@ static void ath9k_set_hw_capab(struct at +- hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; +- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; +- hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; +-+ hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; +- +- hw->queues = 4; +- hw->max_rates = 4; +---- a/net/mac80211/ieee80211_i.h +-+++ b/net/mac80211/ieee80211_i.h +-@@ -1700,14 +1700,8 @@ void ieee80211_stop_queue_by_reason(stru +- void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); +- void ieee80211_add_pending_skb(struct ieee80211_local *local, +- struct sk_buff *skb); +--void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, +-- struct sk_buff_head *skbs, +-- void (*fn)(void *data), void *data); +--static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, +-- struct sk_buff_head *skbs) +--{ +-- ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); +--} +-+void ieee80211_add_pending_skbs(struct ieee80211_local *local, +-+ struct sk_buff_head *skbs); +- void ieee80211_flush_queues(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata); +- +---- a/net/mac80211/sta_info.c +-+++ b/net/mac80211/sta_info.c +-@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee +- return -ENOENT; +- } +- +--static void cleanup_single_sta(struct sta_info *sta) +-+static void __cleanup_single_sta(struct sta_info *sta) +- { +- int ac, i; +- struct tid_ampdu_tx *tid_tx; +-@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct st +- struct ieee80211_local *local = sdata->local; +- struct ps_data *ps; +- +-- if (test_sta_flag(sta, WLAN_STA_PS_STA)) { +-+ if (test_sta_flag(sta, WLAN_STA_PS_STA) || +-+ test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { +- if (sta->sdata->vif.type == NL80211_IFTYPE_AP || +- sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +- ps = &sdata->bss->ps; +-@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct st +- return; +- +- clear_sta_flag(sta, WLAN_STA_PS_STA); +-+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER); +- +- atomic_dec(&ps->num_sta_ps); +- sta_info_recalc_tim(sta); +-@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct st +- ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); +- kfree(tid_tx); +- } +-+} +- +-+static void cleanup_single_sta(struct sta_info *sta) +-+{ +-+ struct ieee80211_sub_if_data *sdata = sta->sdata; +-+ struct ieee80211_local *local = sdata->local; +-+ +-+ __cleanup_single_sta(sta); +- sta_info_free(local, sta); +- } +- +-@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i +- rcu_read_unlock(); +- +- spin_lock_init(&sta->lock); +-+ spin_lock_init(&sta->ps_lock); +- INIT_WORK(&sta->drv_unblock_wk, sta_unblock); +- INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); +- mutex_init(&sta->ampdu_mlme.mtx); +-@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct +- goto out_err; +- } +- +-- /* notify driver */ +-- err = sta_info_insert_drv_state(local, sdata, sta); +-- if (err) +-- goto out_err; +-- +- local->num_sta++; +- local->sta_generation++; +- smp_mb(); +- +-+ /* simplify things and don't accept BA sessions yet */ +-+ set_sta_flag(sta, WLAN_STA_BLOCK_BA); +-+ +- /* make the station visible */ +- sta_info_hash_add(local, sta); +- +- list_add_rcu(&sta->list, &local->sta_list); +- +-+ /* notify driver */ +-+ err = sta_info_insert_drv_state(local, sdata, sta); +-+ if (err) +-+ goto out_remove; +-+ +- set_sta_flag(sta, WLAN_STA_INSERTED); +-+ /* accept BA sessions now */ +-+ clear_sta_flag(sta, WLAN_STA_BLOCK_BA); +- +- ieee80211_recalc_min_chandef(sdata); +- ieee80211_sta_debugfs_add(sta); +-@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct +- mesh_accept_plinks_update(sdata); +- +- return 0; +-+ out_remove: +-+ sta_info_hash_del(local, sta); +-+ list_del_rcu(&sta->list); +-+ local->num_sta--; +-+ synchronize_net(); +-+ __cleanup_single_sta(sta); +- out_err: +- mutex_unlock(&local->sta_mtx); +- rcu_read_lock(); +-@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta +- } +- EXPORT_SYMBOL(ieee80211_find_sta); +- +--static void clear_sta_ps_flags(void *_sta) +-+/* powersave support code */ +-+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) +- { +-- struct sta_info *sta = _sta; +- struct ieee80211_sub_if_data *sdata = sta->sdata; +-+ struct ieee80211_local *local = sdata->local; +-+ struct sk_buff_head pending; +-+ int filtered = 0, buffered = 0, ac; +-+ unsigned long flags; +- struct ps_data *ps; +- +- if (sdata->vif.type == NL80211_IFTYPE_AP || +-@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st +- else +- return; +- +-- clear_sta_flag(sta, WLAN_STA_PS_DRIVER); +-- if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) +-- atomic_dec(&ps->num_sta_ps); +--} +-- +--/* powersave support code */ +--void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) +--{ +-- struct ieee80211_sub_if_data *sdata = sta->sdata; +-- struct ieee80211_local *local = sdata->local; +-- struct sk_buff_head pending; +-- int filtered = 0, buffered = 0, ac; +-- unsigned long flags; +-- +- clear_sta_flag(sta, WLAN_STA_SP); +- +- BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); +-@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str +- +- skb_queue_head_init(&pending); +- +-+ /* sync with ieee80211_tx_h_unicast_ps_buf */ +-+ spin_lock(&sta->ps_lock); +- /* Send all buffered frames to the station */ +- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +- int count = skb_queue_len(&pending), tmp; +-@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(str +- buffered += tmp - count; +- } +- +-- ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); +-+ ieee80211_add_pending_skbs(local, &pending); +-+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER); +-+ clear_sta_flag(sta, WLAN_STA_PS_STA); +-+ spin_unlock(&sta->ps_lock); +-+ +-+ atomic_dec(&ps->num_sta_ps); +- +- /* This station just woke up and isn't aware of our SMPS state */ +- if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, +---- a/net/mac80211/sta_info.h +-+++ b/net/mac80211/sta_info.h +-@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat { +- * @drv_unblock_wk: used for driver PS unblocking +- * @listen_interval: listen interval of this station, when we're acting as AP +- * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly +-+ * @ps_lock: used for powersave (when mac80211 is the AP) related locking +- * @ps_tx_buf: buffers (per AC) of frames to transmit to this station +- * when it leaves power saving state or polls +- * @tx_filtered: buffers (per AC) of frames we already tried to +-@@ -356,10 +357,8 @@ struct sta_info { +- /* use the accessors defined below */ +- unsigned long _flags; +- +-- /* +-- * STA powersave frame queues, no more than the internal +-- * locking required. +-- */ +-+ /* STA powersave lock and frame queues */ +-+ spinlock_t ps_lock; +- struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; +- struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; +- unsigned long driver_buffered_tids; +---- a/net/mac80211/util.c +-+++ b/net/mac80211/util.c +-@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ie +- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +- } +- +--void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, +-- struct sk_buff_head *skbs, +-- void (*fn)(void *data), void *data) +-+void ieee80211_add_pending_skbs(struct ieee80211_local *local, +-+ struct sk_buff_head *skbs) ++@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_ + { +- struct ieee80211_hw *hw = &local->hw; +- struct sk_buff *skb; +-@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struc +- __skb_queue_tail(&local->pending[queue], skb); +- } ++ struct ath_atx_ac *ac = tid->ac; + +-- if (fn) +-- fn(data); ++- if (tid->paused) ++- return; + - +- for (i = 0; i < hw->queues; i++) +- __ieee80211_wake_queue(hw, i, +- IEEE80211_QUEUE_STOP_REASON_SKB_ADD); +---- a/net/wireless/reg.c +-+++ b/net/wireless/reg.c +-@@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regu ++ if (tid->sched) + return; +- case NL80211_REGDOM_SET_BY_USER: +- treatment = reg_process_hint_user(reg_request); +-- if (treatment == REG_REQ_OK || +-+ if (treatment == REG_REQ_IGNORE || +- treatment == REG_REQ_ALREADY_SET) +- return; +- schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); +---- a/drivers/net/wireless/ath/ath9k/debug.c +-+++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -138,43 +138,41 @@ static ssize_t read_file_ani(struct file +- unsigned int len = 0, size = 1024; +- ssize_t retval = 0; +- char *buf; +-+ int i; +-+ struct { +-+ const char *name; +-+ unsigned int val; +-+ } ani_info[] = { +-+ { "ANI RESET", ah->stats.ast_ani_reset }, +-+ { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, +-+ { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, +-+ { "SPUR UP", ah->stats.ast_ani_spurup }, +-+ { "SPUR DOWN", ah->stats.ast_ani_spurup }, +-+ { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, +-+ { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, +-+ { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, +-+ { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh }, +-+ { "FIR-STEP UP", ah->stats.ast_ani_stepup }, +-+ { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown }, +-+ { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero }, +-+ { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs }, +-+ { "CCK ERRORS", ah->stats.ast_ani_cckerrs }, +-+ }; +- +- buf = kzalloc(size, GFP_KERNEL); +- if (buf == NULL) +- return -ENOMEM; +- +-- if (common->disable_ani) { +-- len += scnprintf(buf + len, size - len, "%s: %s\n", +-- "ANI", "DISABLED"); +-+ len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI", +-+ common->disable_ani ? "DISABLED" : "ENABLED"); +-+ +-+ if (common->disable_ani) +- goto exit; +-- } +- +-- len += scnprintf(buf + len, size - len, "%15s: %s\n", +-- "ANI", "ENABLED"); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "ANI RESET", ah->stats.ast_ani_reset); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "SPUR UP", ah->stats.ast_ani_spurup); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "SPUR DOWN", ah->stats.ast_ani_spurup); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "MRC-CCK ON", ah->stats.ast_ani_ccklow); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "MRC-CCK OFF", ah->stats.ast_ani_cckhigh); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "FIR-STEP UP", ah->stats.ast_ani_stepup); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "FIR-STEP DOWN", ah->stats.ast_ani_stepdown); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs); +-- len += scnprintf(buf + len, size - len, "%15s: %u\n", +-- "CCK ERRORS", ah->stats.ast_ani_cckerrs); +-+ for (i = 0; i < ARRAY_SIZE(ani_info); i++) +-+ len += scnprintf(buf + len, size - len, "%15s: %u\n", +-+ ani_info[i].name, ani_info[i].val); +-+ +- exit: +- if (len > size) +- len = size; +-@@ -866,6 +864,12 @@ static ssize_t read_file_reset(struct fi +- "%17s: %2d\n", "PLL RX Hang", +- sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); +- len += scnprintf(buf + len, sizeof(buf) - len, +-+ "%17s: %2d\n", "MAC Hang", +-+ sc->debug.stats.reset[RESET_TYPE_MAC_HANG]); +-+ len += scnprintf(buf + len, sizeof(buf) - len, +-+ "%17s: %2d\n", "Stuck Beacon", +-+ sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]); +-+ len += scnprintf(buf + len, sizeof(buf) - len, +- "%17s: %2d\n", "MCI Reset", +- sc->debug.stats.reset[RESET_TYPE_MCI]); +- +---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +-@@ -868,10 +868,6 @@ static void ar9003_hw_set_rfmode(struct +- +- if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +- rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); +-- if (IS_CHAN_QUARTER_RATE(chan)) +-- rfMode |= AR_PHY_MODE_QUARTER; +-- if (IS_CHAN_HALF_RATE(chan)) +-- rfMode |= AR_PHY_MODE_HALF; +- +- if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF)) +- REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, +---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +-+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +-@@ -706,6 +706,7 @@ ath5k_get_survey(struct ieee80211_hw *hw +- survey->channel = conf->chandef.chan; +- survey->noise = ah->ah_noise_floor; +- survey->filled = SURVEY_INFO_NOISE_DBM | +-+ SURVEY_INFO_IN_USE | +- SURVEY_INFO_CHANNEL_TIME | +- SURVEY_INFO_CHANNEL_TIME_BUSY | +- SURVEY_INFO_CHANNEL_TIME_RX | +---- a/drivers/net/wireless/ath/ath9k/recv.c +-+++ b/drivers/net/wireless/ath/ath9k/recv.c +-@@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx +- return NULL; +- +- /* +-- * mark descriptor as zero-length and set the 'more' +-- * flag to ensure that both buffers get discarded +-+ * Re-check previous descriptor, in case it has been filled +-+ * in the mean time. +- */ +-- rs->rs_datalen = 0; +-- rs->rs_more = true; +-+ ret = ath9k_hw_rxprocdesc(ah, ds, rs); +-+ if (ret == -EINPROGRESS) { +-+ /* +-+ * mark descriptor as zero-length and set the 'more' +-+ * flag to ensure that both buffers get discarded +-+ */ +-+ rs->rs_datalen = 0; +-+ rs->rs_more = true; +-+ } +- } +- +- list_del(&bf->list); +-@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struc +- struct ath_common *common = ath9k_hw_common(ah); +- struct ieee80211_hdr *hdr; +- bool discard_current = sc->rx.discard_next; +-- int ret = 0; +- +- /* +- * Discard corrupt descriptors which are marked in +- * ath_get_next_rx_buf(). +- */ +-- sc->rx.discard_next = rx_stats->rs_more; +- if (discard_current) +-- return -EINVAL; +-+ goto corrupt; +-+ +-+ sc->rx.discard_next = false; +- +- /* +- * Discard zero-length packets. +- */ +- if (!rx_stats->rs_datalen) { +- RX_STAT_INC(rx_len_err); +-- return -EINVAL; +-+ goto corrupt; +- } +- +-- /* +-- * rs_status follows rs_datalen so if rs_datalen is too large +-- * we can take a hint that hardware corrupted it, so ignore +-- * those frames. +-- */ +-+ /* +-+ * rs_status follows rs_datalen so if rs_datalen is too large +-+ * we can take a hint that hardware corrupted it, so ignore +-+ * those frames. +-+ */ +- if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { +- RX_STAT_INC(rx_len_err); +-- return -EINVAL; +-+ goto corrupt; +- } +- +- /* Only use status info from the last fragment */ +-@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struc +- * This is different from the other corrupt descriptor +- * condition handled above. +- */ +-- if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) { +-- ret = -EINVAL; +-- goto exit; +-- } +-+ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) +-+ goto corrupt; +- +- hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); +- +-@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struc +- if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) +- RX_STAT_INC(rx_spectral); +- +-- ret = -EINVAL; +-- goto exit; +-+ return -EINVAL; +- } +- +- /* +- * everything but the rate is checked here, the rate check is done +- * separately to avoid doing two lookups for a rate for each frame. +- */ +-- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) { +-- ret = -EINVAL; +-- goto exit; +-- } +-+ if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) +-+ return -EINVAL; +- +- if (ath_is_mybeacon(common, hdr)) { +- RX_STAT_INC(rx_beacons); +-@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc +- /* +- * This shouldn't happen, but have a safety check anyway. +- */ +-- if (WARN_ON(!ah->curchan)) { +-- ret = -EINVAL; +-- goto exit; +-- } +-+ if (WARN_ON(!ah->curchan)) +-+ return -EINVAL; +- +-- if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { +-- ret =-EINVAL; +-- goto exit; +-- } +-+ if (ath9k_process_rate(common, hw, rx_stats, rx_status)) +-+ return -EINVAL; +- +- ath9k_process_rssi(common, hw, rx_stats, rx_status); +- +-@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc +- sc->rx.num_pkts++; +- #endif +- +--exit: +-- sc->rx.discard_next = false; +-- return ret; +-+ return 0; +-+ +-+corrupt: +-+ sc->rx.discard_next = rx_stats->rs_more; +-+ return -EINVAL; +- } +- +- static void ath9k_rx_skb_postprocess(struct ath_common *common, +---- a/drivers/net/wireless/ath/ath9k/ani.c +-+++ b/drivers/net/wireless/ath/ath9k/ani.c +-@@ -176,16 +176,26 @@ static void ath9k_hw_set_ofdm_nil(struct +- if (ah->opmode == NL80211_IFTYPE_STATION && +- BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH) +- weak_sig = true; +-- +- /* +-- * OFDM Weak signal detection is always enabled for AP mode. +-+ * Newer chipsets are better at dealing with high PHY error counts - +-+ * keep weak signal detection enabled when no RSSI threshold is +-+ * available to determine if it is needed (mode != STA) +- */ +-- if (ah->opmode != NL80211_IFTYPE_AP && +-- aniState->ofdmWeakSigDetect != weak_sig) { +-- ath9k_hw_ani_control(ah, +-- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, +-- entry_ofdm->ofdm_weak_signal_on); +-- } +-+ else if (AR_SREV_9300_20_OR_LATER(ah) && +-+ ah->opmode != NL80211_IFTYPE_STATION) +-+ weak_sig = true; +-+ +-+ /* Older chipsets are more sensitive to high PHY error counts */ +-+ else if (!AR_SREV_9300_20_OR_LATER(ah) && +-+ aniState->ofdmNoiseImmunityLevel >= 8) +-+ weak_sig = false; +-+ +-+ if (aniState->ofdmWeakSigDetect != weak_sig) +-+ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, +-+ weak_sig); +-+ +-+ if (!AR_SREV_9300_20_OR_LATER(ah)) +-+ return; +- +- if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) { +- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; +-@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah, +- BUG_ON(aniState == NULL); +- ah->stats.ast_ani_reset++; + +-- /* only allow a subset of functions in AP mode */ +-- if (ah->opmode == NL80211_IFTYPE_AP) { +-- if (IS_CHAN_2GHZ(chan)) { +-- ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | +-- ATH9K_ANI_FIRSTEP_LEVEL); +-- if (AR_SREV_9300_20_OR_LATER(ah)) +-- ah->ani_function |= ATH9K_ANI_MRC_CCK; +-- } else +-- ah->ani_function = 0; +-- } +-- +- ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, +- aniState->ofdmNoiseImmunityLevel); +- cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, +-@@ -483,10 +482,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah +- +- ath_dbg(common, ANI, "Initialize ANI\n"); +- +-- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; +-- ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; +-- ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH; +-- ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW; +-+ if (AR_SREV_9300_20_OR_LATER(ah)) { +-+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; +-+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; +-+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH; +-+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW; +-+ } else { +-+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; +-+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD; +-+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD; +-+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD; +-+ } +- +- ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; +- ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; +---- a/drivers/net/wireless/ath/ath9k/ani.h +-+++ b/drivers/net/wireless/ath/ath9k/ani.h +-@@ -22,12 +22,16 @@ +- /* units are errors per second */ +- #define ATH9K_ANI_OFDM_TRIG_HIGH 3500 +- #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 +-+#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 ++@@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc * ++ ath_tx_tid_change_state(sc, txtid); + +- #define ATH9K_ANI_OFDM_TRIG_LOW 400 +- #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 +-+#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 +- +- #define ATH9K_ANI_CCK_TRIG_HIGH 600 +-+#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 +- #define ATH9K_ANI_CCK_TRIG_LOW 300 +-+#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 +- +- #define ATH9K_ANI_SPUR_IMMUNE_LVL 3 +- #define ATH9K_ANI_FIRSTEP_LVL 2 +---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +-@@ -26,10 +26,6 @@ static const int firstep_table[] = +- /* level: 0 1 2 3 4 5 6 7 8 */ +- { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ ++ txtid->active = true; ++- txtid->paused = true; ++ *ssn = txtid->seq_start = txtid->seq_next; ++ txtid->bar_index = -1; + +--static const int cycpwrThr1_table[] = +--/* level: 0 1 2 3 4 5 6 7 8 */ +-- { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ +-- +- /* +- * register values to turn OFDM weak signal detection OFF +- */ +-@@ -921,7 +917,7 @@ static bool ar5008_hw_ani_control_new(st +- struct ath_common *common = ath9k_hw_common(ah); +- struct ath9k_channel *chan = ah->curchan; +- struct ar5416AniState *aniState = &ah->ani; +-- s32 value, value2; +-+ s32 value; ++@@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc * + +- switch (cmd & ah->ani_function) { +- case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ +-@@ -1008,42 +1004,9 @@ static bool ar5008_hw_ani_control_new(st +- case ATH9K_ANI_FIRSTEP_LEVEL:{ +- u32 level = param; ++ ath_txq_lock(sc, txq); ++ txtid->active = false; ++- txtid->paused = false; ++ ath_tx_flush_tid(sc, txtid); ++ ath_tx_tid_change_state(sc, txtid); ++ ath_txq_unlock_complete(sc, txq); ++@@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc ++ ath_txq_lock(sc, txq); ++ ac->clear_ps_filter = true; + +-- if (level >= ARRAY_SIZE(firstep_table)) { +-- ath_dbg(common, ANI, +-- "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", +-- level, ARRAY_SIZE(firstep_table)); +-- return false; +-- } +-- +-- /* +-- * make register setting relative to default +-- * from INI file & cap value +-- */ +-- value = firstep_table[level] - +-- firstep_table[ATH9K_ANI_FIRSTEP_LVL] + +-- aniState->iniDef.firstep; +-- if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) +-- value = ATH9K_SIG_FIRSTEP_SETTING_MIN; +-- if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) +-- value = ATH9K_SIG_FIRSTEP_SETTING_MAX; +-+ value = level; +- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, +-- AR_PHY_FIND_SIG_FIRSTEP, +-- value); +-- /* +-- * we need to set first step low register too +-- * make register setting relative to default +-- * from INI file & cap value +-- */ +-- value2 = firstep_table[level] - +-- firstep_table[ATH9K_ANI_FIRSTEP_LVL] + +-- aniState->iniDef.firstepLow; +-- if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) +-- value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; +-- if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) +-- value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; +-- +-- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, +-- AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); +-+ AR_PHY_FIND_SIG_FIRSTEP, value); ++- if (!tid->paused && ath_tid_has_buffered(tid)) { +++ if (ath_tid_has_buffered(tid)) { ++ ath_tx_queue_tid(txq, tid); ++ ath_txq_schedule(sc, txq); ++ } ++@@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc ++ ath_txq_lock(sc, txq); + +- if (level != aniState->firstepLevel) { +- ath_dbg(common, ANI, +-@@ -1060,7 +1023,7 @@ static bool ar5008_hw_ani_control_new(st +- aniState->firstepLevel, +- level, +- ATH9K_ANI_FIRSTEP_LVL, +-- value2, +-+ value, +- aniState->iniDef.firstepLow); +- if (level > aniState->firstepLevel) +- ah->stats.ast_ani_stepup++; +-@@ -1073,41 +1036,13 @@ static bool ar5008_hw_ani_control_new(st +- case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ +- u32 level = param; ++ tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; ++- tid->paused = false; + +-- if (level >= ARRAY_SIZE(cycpwrThr1_table)) { +-- ath_dbg(common, ANI, +-- "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", +-- level, ARRAY_SIZE(cycpwrThr1_table)); +-- return false; +-- } +-- /* +-- * make register setting relative to default +-- * from INI file & cap value +-- */ +-- value = cycpwrThr1_table[level] - +-- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + +-- aniState->iniDef.cycpwrThr1; +-- if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) +-- value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; +-- if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) +-- value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; +-+ value = (level + 1) * 2; +- REG_RMW_FIELD(ah, AR_PHY_TIMING5, +-- AR_PHY_TIMING5_CYCPWR_THR1, +-- value); +-+ AR_PHY_TIMING5_CYCPWR_THR1, value); ++ if (ath_tid_has_buffered(tid)) { ++ ath_tx_queue_tid(txq, tid); ++@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struc ++ continue; + +-- /* +-- * set AR_PHY_EXT_CCA for extension channel +-- * make register setting relative to default +-- * from INI file & cap value +-- */ +-- value2 = cycpwrThr1_table[level] - +-- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + +-- aniState->iniDef.cycpwrThr1Ext; +-- if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) +-- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; +-- if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) +-- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; +-- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, +-- AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); +-+ if (IS_CHAN_HT40(ah->curchan)) +-+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, +-+ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value); ++ tid = ATH_AN_2_TID(an, i); ++- if (tid->paused) ++- continue; + +- if (level != aniState->spurImmunityLevel) { +- ath_dbg(common, ANI, +-@@ -1124,7 +1059,7 @@ static bool ar5008_hw_ani_control_new(st +- aniState->spurImmunityLevel, +- level, +- ATH9K_ANI_SPUR_IMMUNE_LVL, +-- value2, +-+ value, +- aniState->iniDef.cycpwrThr1Ext); +- if (level > aniState->spurImmunityLevel) +- ah->stats.ast_ani_spurup++; ++ ath_txq_lock(sc, tid->ac->txq); ++ while (nframes > 0) { ++@@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc * ++ list_del(&tid->list); ++ tid->sched = false; ++ ++- if (tid->paused) ++- continue; ++- ++ if (ath_tx_sched_aggr(sc, txq, tid, &stop)) ++ sent = true; ++ ++@@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc * ++ tid->baw_size = WME_MAX_BA; ++ tid->baw_head = tid->baw_tail = 0; ++ tid->sched = false; ++- tid->paused = false; ++ tid->active = false; ++ __skb_queue_head_init(&tid->buf_q); ++ __skb_queue_head_init(&tid->retry_q); +diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch +index 389a003..87f165a 100644 +--- a/package/mac80211/patches/310-ap_scan.patch ++++ b/package/mac80211/patches/310-ap_scan.patch +@@ -1,6 +1,6 @@ + --- a/net/mac80211/cfg.c + +++ b/net/mac80211/cfg.c +-@@ -2148,7 +2148,7 @@ static int ieee80211_scan(struct wiphy * ++@@ -2154,7 +2154,7 @@ static int ieee80211_scan(struct wiphy * + * the frames sent while scanning on other channel will be + * lost) + */ +diff --git a/package/mac80211/patches/400-ath_move_debug_code.patch b/package/mac80211/patches/400-ath_move_debug_code.patch +index 0dba7ac..4cc77af 100644 +--- a/package/mac80211/patches/400-ath_move_debug_code.patch ++++ b/package/mac80211/patches/400-ath_move_debug_code.patch +@@ -12,7 +12,7 @@ + ccflags-y += -D__CHECK_ENDIAN__ + --- a/drivers/net/wireless/ath/ath.h + +++ b/drivers/net/wireless/ath/ath.h +-@@ -282,13 +282,6 @@ void _ath_dbg(struct ath_common *common, ++@@ -295,13 +295,6 @@ void _ath_dbg(struct ath_common *common, + #endif /* CPTCFG_ATH_DEBUG */ + + /** Returns string describing opmode, or NULL if unknown mode. */ +diff --git a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch +index 63ab0db..acaa317 100644 +--- a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch ++++ b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch +@@ -8,7 +8,7 @@ + #include + + #include "hw.h" +-@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct ++@@ -448,8 +449,16 @@ static int ath9k_hw_init_macaddr(struct + common->macaddr[2 * i] = eeval >> 8; + common->macaddr[2 * i + 1] = eeval & 0xff; + } +diff --git a/package/mac80211/patches/403-ath_regd_optional.patch b/package/mac80211/patches/403-ath_regd_optional.patch +index 07c54cc..4a9b7e4 100644 +--- a/package/mac80211/patches/403-ath_regd_optional.patch ++++ b/package/mac80211/patches/403-ath_regd_optional.patch +@@ -58,7 +58,7 @@ + ---help--- + --- a/.local-symbols + +++ b/.local-symbols +-@@ -119,6 +119,7 @@ RTL8187_LEDS= ++@@ -120,6 +120,7 @@ RTL8187_LEDS= + ATH_COMMON= + ATH_CARDS= + ATH_DEBUG= +diff --git a/package/mac80211/patches/405-regd_no_assoc_hints.patch b/package/mac80211/patches/405-regd_no_assoc_hints.patch +index 6ad4fda..4fa611f 100644 +--- a/package/mac80211/patches/405-regd_no_assoc_hints.patch ++++ b/package/mac80211/patches/405-regd_no_assoc_hints.patch +@@ -1,6 +1,6 @@ + --- a/net/wireless/reg.c + +++ b/net/wireless/reg.c +-@@ -1878,6 +1878,8 @@ void regulatory_hint_country_ie(struct w ++@@ -2000,6 +2000,8 @@ void regulatory_hint_country_ie(struct w + enum environment_cap env = ENVIRON_ANY; + struct regulatory_request *request = NULL, *lr; + +@@ -9,7 +9,7 @@ + /* IE len must be evenly divisible by 2 */ + if (country_ie_len & 0x01) + return; +-@@ -2072,6 +2074,7 @@ static void restore_regulatory_settings( ++@@ -2194,6 +2196,7 @@ static void restore_regulatory_settings( + + void regulatory_hint_disconnect(void) + { +diff --git a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +index 1f71e0b..909a5f1 100644 +--- a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch ++++ b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -866,6 +866,7 @@ static const struct ieee80211_iface_limi ++@@ -652,6 +652,7 @@ static const struct ieee80211_iface_limi + #endif + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) }, +diff --git a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch +index 3487ab2..1f06994 100644 +--- a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch ++++ b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch +@@ -18,7 +18,7 @@ + goto end; + --- a/drivers/net/wireless/ath/ath5k/base.c + +++ b/drivers/net/wireless/ath/ath5k/base.c +-@@ -1934,7 +1934,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) ++@@ -1937,7 +1937,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) + } + + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + +@@ -27,7 +27,7 @@ + ah->opmode == NL80211_IFTYPE_MESH_POINT) { + u64 tsf = ath5k_hw_get_tsf64(ah); + u32 tsftu = TSF_TO_TU(tsf); +-@@ -2020,7 +2020,7 @@ ath5k_beacon_update_timers(struct ath5k_ ++@@ -2023,7 +2023,7 @@ ath5k_beacon_update_timers(struct ath5k_ + + intval = ah->bintval & AR5K_BEACON_PERIOD; + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +@@ -36,7 +36,7 @@ + intval /= ATH_BCBUF; /* staggered multi-bss beacons */ + if (intval < 15) + ATH5K_WARN(ah, "intval %u is too low, min 15\n", +-@@ -2487,6 +2487,7 @@ static const struct ieee80211_iface_limi ++@@ -2490,6 +2490,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_MESH_POINT) | + #endif + BIT(NL80211_IFTYPE_AP) }, +diff --git a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch +index 664cf45..36e0151 100644 +--- a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch ++++ b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/debug.c + +++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -1481,6 +1481,53 @@ void ath9k_deinit_debug(struct ath_softc ++@@ -1485,6 +1485,53 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_spectral_deinit_debug(sc); + } + +@@ -54,7 +54,7 @@ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +-@@ -1500,6 +1547,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1504,6 +1551,8 @@ int ath9k_init_debug(struct ath_hw *ah) + ath9k_tx99_init_debug(sc); + ath9k_spectral_init_debug(sc); + +diff --git a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch +index 96e7c6d..169eb9a 100644 +--- a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch ++++ b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch +@@ -81,7 +81,7 @@ + struct ath_ops reg_ops; + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -722,6 +722,8 @@ static int ath9k_init_softc(u16 devid, s ++@@ -518,6 +518,8 @@ static int ath9k_init_softc(u16 devid, s + ah->is_clk_25mhz = pdata->is_clk_25mhz; + ah->get_mac_revision = pdata->get_mac_revision; + ah->external_reset = pdata->external_reset; +diff --git a/package/mac80211/patches/502-ath9k_ahb_init.patch b/package/mac80211/patches/502-ath9k_ahb_init.patch +index 4edc63b..43c3260 100644 +--- a/package/mac80211/patches/502-ath9k_ahb_init.patch ++++ b/package/mac80211/patches/502-ath9k_ahb_init.patch +@@ -1,15 +1,15 @@ + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -1112,23 +1112,23 @@ static int __init ath9k_init(void) +- goto err_out; +- } ++@@ -892,23 +892,23 @@ static int __init ath9k_init(void) ++ { ++ int error; + + - error = ath_pci_init(); + + error = ath_ahb_init(); + if (error < 0) { + - pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; +- goto err_rate_unregister; ++ goto err_out; + } + + - error = ath_ahb_init(); +@@ -27,6 +27,6 @@ + - ath_pci_exit(); + + err_ahb_exit: + + ath_ahb_exit(); +- +- err_rate_unregister: +- ath_rate_control_unregister(); ++ err_out: ++ return error; ++ } +diff --git a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +index d7478ff..c818933 100644 +--- a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch ++++ b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -359,13 +359,8 @@ static void ath9k_hw_init_config(struct ++@@ -358,13 +358,8 @@ static void ath9k_hw_init_config(struct + + ah->config.rx_intr_mitigation = true; + +diff --git a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch +index ef0b9a1..e457267 100644 +--- a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch ++++ b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/ath9k.h + +++ b/drivers/net/wireless/ath/ath9k/ath9k.h +-@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc * ++@@ -89,7 +89,7 @@ int ath_descdma_setup(struct ath_softc * + (_l) &= ((_sz) - 1); \ + } while (0) + +diff --git a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch +index 8f3cc03..665d8aa 100644 +--- a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch ++++ b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/debug.c + +++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -1528,6 +1528,52 @@ static const struct file_operations fops ++@@ -1532,6 +1532,52 @@ static const struct file_operations fops + .owner = THIS_MODULE + }; + +@@ -35,7 +35,7 @@ + + return -EINVAL; + + + + common->chan_bw = chan_bw; +-+ if (!test_bit(SC_OP_INVALID, &sc->sc_flags)) +++ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) + + ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL); + + + + return count; +@@ -53,7 +53,7 @@ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +-@@ -1549,6 +1595,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1553,6 +1599,8 @@ int ath9k_init_debug(struct ath_hw *ah) + + debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_eeprom); +@@ -64,17 +64,17 @@ + debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, + --- a/drivers/net/wireless/ath/ath.h + +++ b/drivers/net/wireless/ath/ath.h +-@@ -130,6 +130,7 @@ struct ath_common { +- struct ieee80211_hw *hw; ++@@ -140,6 +140,7 @@ struct ath_common { + int debug_mask; + enum ath_device_state state; ++ unsigned long op_flags; + + u32 chan_bw; + + struct ath_ani ani; + + --- a/drivers/net/wireless/ath/ath9k/common.c + +++ b/drivers/net/wireless/ath/ath9k/common.c +-@@ -52,11 +52,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke ++@@ -296,11 +296,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke + /* + * Update internal channel flags. + */ +@@ -89,7 +89,7 @@ + + ichan->channel = chan->center_freq; + ichan->chan = chan; +-@@ -64,7 +66,19 @@ static void ath9k_cmn_update_ichannel(st ++@@ -308,7 +310,19 @@ static void ath9k_cmn_update_ichannel(st + if (chan->band == IEEE80211_BAND_5GHZ) + flags |= CHANNEL_5GHZ; + +@@ -110,7 +110,7 @@ + case NL80211_CHAN_WIDTH_5: + flags |= CHANNEL_QUARTER; + break; +-@@ -97,10 +111,11 @@ struct ath9k_channel *ath9k_cmn_get_chan ++@@ -341,10 +355,11 @@ struct ath9k_channel *ath9k_cmn_get_chan + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *curchan = chandef->chan; +diff --git a/package/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/mac80211/patches/513-ath9k_add_pci_ids.patch +index db4e6a1..540198f 100644 +--- a/package/mac80211/patches/513-ath9k_add_pci_ids.patch ++++ b/package/mac80211/patches/513-ath9k_add_pci_ids.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -614,6 +614,7 @@ int ath9k_hw_init(struct ath_hw *ah) ++@@ -613,6 +613,7 @@ int ath9k_hw_init(struct ath_hw *ah) + + /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ + switch (ah->hw_version.devid) { +diff --git a/package/mac80211/patches/520-mac80211_cur_txpower.patch b/package/mac80211/patches/520-mac80211_cur_txpower.patch +index 6df95bc..cb3f852 100644 +--- a/package/mac80211/patches/520-mac80211_cur_txpower.patch ++++ b/package/mac80211/patches/520-mac80211_cur_txpower.patch +@@ -1,6 +1,6 @@ + --- a/include/net/mac80211.h + +++ b/include/net/mac80211.h +-@@ -1711,6 +1711,7 @@ struct ieee80211_hw { ++@@ -1703,6 +1703,7 @@ struct ieee80211_hw { + u8 max_tx_aggregation_subframes; + u8 offchannel_tx_hw_queue; + u8 radiotap_mcs_details; +@@ -10,7 +10,7 @@ + u8 uapsd_queues; + --- a/net/mac80211/cfg.c + +++ b/net/mac80211/cfg.c +-@@ -2329,7 +2329,9 @@ static int ieee80211_get_tx_power(struct ++@@ -2335,7 +2335,9 @@ static int ieee80211_get_tx_power(struct + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); + +@@ -23,7 +23,7 @@ + *dbm = sdata->vif.bss_conf.txpower; + --- a/net/mac80211/main.c + +++ b/net/mac80211/main.c +-@@ -158,6 +158,7 @@ static u32 ieee80211_hw_conf_chan(struct ++@@ -160,6 +160,7 @@ static u32 ieee80211_hw_conf_chan(struct + + if (local->hw.conf.power_level != power) { + changed |= IEEE80211_CONF_CHANGE_POWER; +diff --git a/package/mac80211/patches/521-ath9k_cur_txpower.patch b/package/mac80211/patches/521-ath9k_cur_txpower.patch +index 0d6c360..24bc062 100644 +--- a/package/mac80211/patches/521-ath9k_cur_txpower.patch ++++ b/package/mac80211/patches/521-ath9k_cur_txpower.patch +@@ -14,7 +14,7 @@ + + out: + spin_unlock_bh(&sc->sc_pcu_lock); +-@@ -1371,6 +1375,7 @@ static int ath9k_config(struct ieee80211 ++@@ -1370,6 +1374,7 @@ static int ath9k_config(struct ieee80211 + sc->config.txpowlimit = 2 * conf->power_level; + ath9k_cmn_update_txpow(ah, sc->curtxpow, + sc->config.txpowlimit, &sc->curtxpow); +diff --git a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch +index 308ee6e..611f763 100644 +--- a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch ++++ b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch +@@ -1,6 +1,6 @@ + --- a/include/net/cfg80211.h + +++ b/include/net/cfg80211.h +-@@ -2156,6 +2156,7 @@ struct cfg80211_qos_map { ++@@ -2167,6 +2167,7 @@ struct cfg80211_qos_map { + * (as advertised by the nl80211 feature flag.) + * @get_tx_power: store the current TX power into the dbm variable; + * return 0 if successful +@@ -8,7 +8,7 @@ + * + * @set_wds_peer: set the WDS peer for a WDS interface + * +-@@ -2380,6 +2381,7 @@ struct cfg80211_ops { ++@@ -2396,6 +2397,7 @@ struct cfg80211_ops { + enum nl80211_tx_power_setting type, int mbm); + int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm); +@@ -18,7 +18,7 @@ + const u8 *addr); + --- a/include/net/mac80211.h + +++ b/include/net/mac80211.h +-@@ -1033,6 +1033,7 @@ enum ieee80211_smps_mode { ++@@ -1032,6 +1032,7 @@ enum ieee80211_smps_mode { + * + * @power_level: requested transmit power (in dBm), backward compatibility + * value only that is set to the minimum of all interfaces +@@ -26,7 +26,7 @@ + * + * @chandef: the channel definition to tune to + * @radar_enabled: whether radar detection is enabled +-@@ -1054,6 +1055,7 @@ struct ieee80211_conf { ++@@ -1053,6 +1054,7 @@ struct ieee80211_conf { + u32 flags; + int power_level, dynamic_ps_timeout; + int max_sleep_period; +@@ -36,9 +36,9 @@ + u8 ps_dtim_period; + --- a/include/uapi/linux/nl80211.h + +++ b/include/uapi/linux/nl80211.h +-@@ -1555,6 +1555,9 @@ enum nl80211_commands { +- * data is in the format defined for the payload of the QoS Map Set element +- * in IEEE Std 802.11-2012, 8.4.2.97. ++@@ -1579,6 +1579,9 @@ enum nl80211_commands { ++ * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. ++ * As specified in the &enum nl80211_tdls_peer_capability. + * + + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + + * transmit power to stay within regulatory limits. u32, dBi. +@@ -46,9 +46,9 @@ + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use + */ +-@@ -1883,6 +1886,8 @@ enum nl80211_attrs { ++@@ -1914,6 +1917,8 @@ enum nl80211_attrs { + +- NL80211_ATTR_QOS_MAP, ++ NL80211_ATTR_TDLS_PEER_CAPABILITY, + + + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + + +@@ -57,7 +57,7 @@ + __NL80211_ATTR_AFTER_LAST, + --- a/net/mac80211/cfg.c + +++ b/net/mac80211/cfg.c +-@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct ++@@ -2345,6 +2345,19 @@ static int ieee80211_get_tx_power(struct + return 0; + } + +@@ -77,7 +77,7 @@ + static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr) + { +-@@ -3924,6 +3937,7 @@ struct cfg80211_ops mac80211_config_ops ++@@ -4000,6 +4013,7 @@ const struct cfg80211_ops mac80211_confi + .set_wiphy_params = ieee80211_set_wiphy_params, + .set_tx_power = ieee80211_set_tx_power, + .get_tx_power = ieee80211_get_tx_power, +@@ -87,7 +87,7 @@ + CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) + --- a/net/mac80211/ieee80211_i.h + +++ b/net/mac80211/ieee80211_i.h +-@@ -1221,6 +1221,7 @@ struct ieee80211_local { ++@@ -1225,6 +1225,7 @@ struct ieee80211_local { + int dynamic_ps_forced_timeout; + + int user_power_level; /* in dBm, for all interfaces */ +@@ -102,34 +102,24 @@ + struct cfg80211_chan_def chandef = {}; + u32 changed = 0; + - int power; +-+ int power, ant_gain, max_power; +++ int power, max_power; + u32 offchannel_flag; + + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; +-@@ -156,8 +156,21 @@ static u32 ieee80211_hw_conf_chan(struct ++@@ -158,6 +158,12 @@ static u32 ieee80211_hw_conf_chan(struct + } + rcu_read_unlock(); + +-- if (local->hw.conf.power_level != power) { + + max_power = chandef.chan->max_reg_power; +-+ ant_gain = chandef.chan->max_antenna_gain; + + if (local->user_antenna_gain > 0) { +-+ if (local->user_antenna_gain > ant_gain) { +-+ max_power -= local->user_antenna_gain - ant_gain; +-+ ant_gain = 0; +-+ } else +-+ ant_gain -= local->user_antenna_gain; +++ max_power -= local->user_antenna_gain; + + power = min(power, max_power); + + } + + +-+ if (local->hw.conf.power_level != power || +-+ local->hw.conf.max_antenna_gain != ant_gain) { ++ if (local->hw.conf.power_level != power) { + changed |= IEEE80211_CONF_CHANGE_POWER; +-+ local->hw.conf.max_antenna_gain = ant_gain; + local->hw.cur_power_level = power; +- local->hw.conf.power_level = power; +- } +-@@ -584,6 +597,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( ++@@ -586,6 +592,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( + IEEE80211_RADIOTAP_MCS_HAVE_BW; + local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; +@@ -139,32 +129,30 @@ + local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; + --- a/net/wireless/nl80211.c + +++ b/net/wireless/nl80211.c +-@@ -384,6 +384,7 @@ static const struct nla_policy nl80211_p +- [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, +- [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, +- .len = IEEE80211_QOS_MAP_LEN_MAX }, ++@@ -385,6 +385,7 @@ static const struct nla_policy nl80211_p ++ [NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN }, ++ [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, ++ [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, + + [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, + }; + + /* policy for the key attributes */ +-@@ -2105,6 +2106,22 @@ static int nl80211_set_wiphy(struct sk_b +- goto bad_res; ++@@ -2116,6 +2117,20 @@ static int nl80211_set_wiphy(struct sk_b ++ return result; + } + + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { + + int idx, dbi = 0; + + +-+ if (!rdev->ops->set_antenna_gain) { +-+ result = -EOPNOTSUPP; +-+ goto bad_res; +-+ } +++ if (!rdev->ops->set_antenna_gain) +++ return -EOPNOTSUPP; + + + + idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; + + dbi = nla_get_u32(info->attrs[idx]); + + + + result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); + + if (result) +-+ goto bad_res; +++ return result; + + } + + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && +diff --git a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch +index 30aa9ee..b84a991 100644 +--- a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch ++++ b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath.h + +++ b/drivers/net/wireless/ath/ath.h +-@@ -74,6 +74,7 @@ struct ath_regulatory { ++@@ -83,6 +83,7 @@ struct ath_regulatory { + u16 max_power_level; + u16 current_rd; + int16_t power_limit; +@@ -10,7 +10,7 @@ + + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -2721,7 +2721,7 @@ void ath9k_hw_apply_txpower(struct ath_h ++@@ -2720,7 +2720,7 @@ void ath9k_hw_apply_txpower(struct ath_h + channel = chan->chan; + chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); + new_pwr = min_t(int, chan_pwr, reg->power_limit); +@@ -21,7 +21,7 @@ + if (ant_gain > max_gain) + --- a/drivers/net/wireless/ath/ath9k/main.c + +++ b/drivers/net/wireless/ath/ath9k/main.c +-@@ -1371,7 +1371,10 @@ static int ath9k_config(struct ieee80211 ++@@ -1370,7 +1370,10 @@ static int ath9k_config(struct ieee80211 + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { +diff --git a/package/mac80211/patches/530-ath9k_extra_leds.patch b/package/mac80211/patches/530-ath9k_extra_leds.patch +index 59f78d9..fb24f03 100644 +--- a/package/mac80211/patches/530-ath9k_extra_leds.patch ++++ b/package/mac80211/patches/530-ath9k_extra_leds.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/ath9k.h + +++ b/drivers/net/wireless/ath/ath9k/ath9k.h +-@@ -563,6 +563,9 @@ static inline int ath9k_dump_btcoex(stru ++@@ -554,6 +554,9 @@ static inline int ath9k_dump_btcoex(stru + void ath_init_leds(struct ath_softc *sc); + void ath_deinit_leds(struct ath_softc *sc); + void ath_fill_led_pin(struct ath_softc *sc); +@@ -10,7 +10,7 @@ + #else + static inline void ath_init_leds(struct ath_softc *sc) + { +-@@ -710,6 +713,13 @@ enum sc_op_flags { ++@@ -692,6 +695,13 @@ void ath_ant_comb_scan(struct ath_softc + #define PS_BEACON_SYNC BIT(4) + #define PS_WAIT_FOR_ANI BIT(5) + +@@ -24,8 +24,8 @@ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +-@@ -751,9 +761,8 @@ struct ath_softc { +- struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; ++@@ -731,9 +741,8 @@ struct ath_softc { ++ struct ath_beacon beacon; + + #ifdef CPTCFG_MAC80211_LEDS + - bool led_registered; +@@ -162,7 +162,7 @@ + void ath_fill_led_pin(struct ath_softc *sc) + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -1018,7 +1018,7 @@ int ath9k_init_device(u16 devid, struct ++@@ -806,7 +806,7 @@ int ath9k_init_device(u16 devid, struct + + #ifdef CPTCFG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ +@@ -173,7 +173,7 @@ + #endif + --- a/drivers/net/wireless/ath/ath9k/debug.c + +++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -1573,6 +1573,61 @@ static const struct file_operations fops ++@@ -1577,6 +1577,61 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + +@@ -235,7 +235,7 @@ + + int ath9k_init_debug(struct ath_hw *ah) + { +-@@ -1597,6 +1652,10 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1601,6 +1656,10 @@ int ath9k_init_debug(struct ath_hw *ah) + &fops_eeprom); + debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_chanbw); +diff --git a/package/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/mac80211/patches/542-ath9k_debugfs_diag.patch +index e1b6ff1..44aa905 100644 +--- a/package/mac80211/patches/542-ath9k_debugfs_diag.patch ++++ b/package/mac80211/patches/542-ath9k_debugfs_diag.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/debug.c + +++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -1629,6 +1629,50 @@ static const struct file_operations fops ++@@ -1633,6 +1633,50 @@ static const struct file_operations fops + #endif + + +@@ -51,7 +51,7 @@ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +-@@ -1656,6 +1700,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1660,6 +1704,8 @@ int ath9k_init_debug(struct ath_hw *ah) + debugfs_create_file("gpio_led", S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_gpio_led); + #endif +@@ -94,7 +94,7 @@ + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -1735,6 +1735,20 @@ fail: ++@@ -1734,6 +1734,20 @@ fail: + return -EINVAL; + } + +@@ -115,7 +115,7 @@ + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + struct ath9k_hw_cal_data *caldata, bool fastcc) + { +-@@ -1940,6 +1954,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++@@ -1939,6 +1953,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ar9003_hw_disable_phy_restart(ah); + + ath9k_hw_apply_gpio_override(ah); +@@ -125,7 +125,7 @@ + REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); + --- a/drivers/net/wireless/ath/ath9k/main.c + +++ b/drivers/net/wireless/ath/ath9k/main.c +-@@ -602,6 +602,11 @@ irqreturn_t ath_isr(int irq, void *dev) ++@@ -603,6 +603,11 @@ irqreturn_t ath_isr(int irq, void *dev) + ath9k_debug_sync_cause(sc, sync_cause); + status &= ah->imask; /* discard unasked-for bits */ + +diff --git a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch +index d26a5af..e2e18c9 100644 +--- a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch ++++ b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch +@@ -11,7 +11,7 @@ + int (*external_reset)(void); + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -2328,17 +2328,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw ++@@ -2327,17 +2327,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw + } + + eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); +@@ -58,7 +58,7 @@ + }; + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -722,6 +722,8 @@ static int ath9k_init_softc(u16 devid, s ++@@ -518,6 +518,8 @@ static int ath9k_init_softc(u16 devid, s + ah->is_clk_25mhz = pdata->is_clk_25mhz; + ah->get_mac_revision = pdata->get_mac_revision; + ah->external_reset = pdata->external_reset; +diff --git a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch +index b59c362..54f5ced 100644 +--- a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch ++++ b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch +@@ -55,7 +55,7 @@ + ops->spectral_scan_config = ar9003_hw_spectral_scan_config; + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -846,7 +846,8 @@ static void ath9k_init_txpower_limits(st ++@@ -643,7 +643,8 @@ static void ath9k_init_txpower_limits(st + if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); + +@@ -64,8 +64,8 @@ + + ah->curchan = curchan; + } + +- void ath9k_reload_chainmask_settings(struct ath_softc *sc) +-@@ -980,6 +981,18 @@ static void ath9k_set_hw_capab(struct at ++ static const struct ieee80211_iface_limit if_limits[] = { ++@@ -768,6 +769,18 @@ static void ath9k_set_hw_capab(struct at + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); + } + +@@ -84,7 +84,7 @@ + int ath9k_init_device(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +-@@ -1025,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct ++@@ -813,6 +826,8 @@ int ath9k_init_device(u16 devid, struct + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + +@@ -110,7 +110,7 @@ + static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) + --- a/drivers/net/wireless/ath/ath9k/link.c + +++ b/drivers/net/wireless/ath/ath9k/link.c +-@@ -307,6 +307,11 @@ void ath_ani_calibrate(unsigned long dat ++@@ -308,6 +308,11 @@ void ath_ani_calibrate(unsigned long dat + unsigned int timestamp = jiffies_to_msecs(jiffies); + u32 cal_interval, short_cal_interval, long_cal_interval; + unsigned long flags; +diff --git a/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch +index ffffe0c..579a633 100644 +--- a/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch ++++ b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch +@@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau + + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -863,15 +863,15 @@ void ath9k_reload_chainmask_settings(str ++@@ -649,15 +649,15 @@ static void ath9k_init_txpower_limits(st + + static const struct ieee80211_iface_limit if_limits[] = { + { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | +diff --git a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch +index 4a61db3..1bd0a54 100644 +--- a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch ++++ b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch +@@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau + return true; + } + +-@@ -1126,6 +1128,8 @@ static int ath9k_add_interface(struct ie ++@@ -1128,6 +1130,8 @@ static int ath9k_add_interface(struct ie + if (ath9k_uses_beacons(vif->type)) + ath9k_beacon_assign_slot(sc, vif); + +@@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau + an->sc = sc; + an->sta = NULL; + an->vif = vif; +-@@ -1170,6 +1174,29 @@ static int ath9k_change_interface(struct ++@@ -1172,6 +1176,29 @@ static int ath9k_change_interface(struct + return 0; + } + +@@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau + static void ath9k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +-@@ -1181,6 +1208,13 @@ static void ath9k_remove_interface(struc ++@@ -1183,6 +1210,13 @@ static void ath9k_remove_interface(struc + + mutex_lock(&sc->mutex); + +@@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau + sc->nvifs--; + sc->tx99_vif = NULL; + +-@@ -1649,6 +1683,70 @@ static void ath9k_bss_assoc_iter(void *d ++@@ -1649,6 +1683,72 @@ static void ath9k_bss_assoc_iter(void *d + ath9k_set_assoc_state(sc, vif); + } + +@@ -130,6 +130,7 @@ Signed-off-by: Felix Fietkau + +void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) + +{ + + struct ath_vif *avp = (void *)vif->drv_priv; +++ unsigned long flags; + + u32 tsf; + + + + if (!sc->p2p_ps_timer) +@@ -140,18 +141,19 @@ Signed-off-by: Felix Fietkau + + + + sc->p2p_ps_vif = avp; + + +-+ if (sc->ps_flags & PS_BEACON_SYNC) +-+ return; +-+ +-+ tsf = ath9k_hw_gettsf32(sc->sc_ah); +-+ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf); +-+ ath9k_update_p2p_ps_timer(sc, avp); +++ spin_lock_irqsave(&sc->sc_pm_lock, flags); +++ if (!(sc->ps_flags & PS_BEACON_SYNC)) { +++ tsf = ath9k_hw_gettsf32(sc->sc_ah); +++ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf); +++ ath9k_update_p2p_ps_timer(sc, avp); +++ } +++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags); + +} + + + static void ath9k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, +-@@ -1723,6 +1821,12 @@ static void ath9k_bss_info_changed(struc ++@@ -1723,6 +1823,12 @@ static void ath9k_bss_info_changed(struc + } + } + +@@ -166,7 +168,7 @@ Signed-off-by: Felix Fietkau + + --- a/drivers/net/wireless/ath/ath9k/ath9k.h + +++ b/drivers/net/wireless/ath/ath9k/ath9k.h +-@@ -115,6 +115,9 @@ int ath_descdma_setup(struct ath_softc * ++@@ -114,6 +114,9 @@ int ath_descdma_setup(struct ath_softc * + #define ATH_TXFIFO_DEPTH 8 + #define ATH_TX_ERROR 0x01 + +@@ -176,7 +178,7 @@ Signed-off-by: Felix Fietkau + #define IEEE80211_SEQ_SEQ_SHIFT 4 + #define IEEE80211_SEQ_MAX 4096 + #define IEEE80211_WEP_IVLEN 3 +-@@ -363,11 +366,15 @@ void ath9k_release_buffered_frames(struc ++@@ -366,11 +369,15 @@ void ath9k_release_buffered_frames(struc + /********/ + + struct ath_vif { +@@ -192,7 +194,7 @@ Signed-off-by: Felix Fietkau + }; + + struct ath9k_vif_iter_data { +-@@ -472,6 +479,8 @@ int ath_update_survey_stats(struct ath_s ++@@ -463,6 +470,8 @@ int ath_update_survey_stats(struct ath_s + void ath_update_survey_nf(struct ath_softc *sc, int channel); + void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); + void ath_ps_full_sleep(unsigned long data); +@@ -201,19 +203,19 @@ Signed-off-by: Felix Fietkau + + /**********/ + /* BTCOEX */ +-@@ -741,6 +750,9 @@ struct ath_softc { ++@@ -723,6 +732,9 @@ struct ath_softc { + struct completion paprd_complete; + wait_queue_head_t tx_wait; + + + struct ath_gen_timer *p2p_ps_timer; + + struct ath_vif *p2p_ps_vif; + + +- unsigned long sc_flags; + unsigned long driver_data; + ++ u8 gtt_cnt; + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -797,6 +797,9 @@ static int ath9k_init_softc(u16 devid, s ++@@ -593,6 +593,9 @@ static int ath9k_init_softc(u16 devid, s + if (ret) + goto err_btcoex; + +@@ -223,7 +225,7 @@ Signed-off-by: Felix Fietkau + ath9k_cmn_init_crypto(sc->sc_ah); + ath9k_init_misc(sc); + ath_fill_led_pin(sc); +-@@ -1082,6 +1085,9 @@ static void ath9k_deinit_softc(struct at ++@@ -870,6 +873,9 @@ static void ath9k_deinit_softc(struct at + { + int i = 0; + +diff --git a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch +index af94c9e..eddbc6c 100644 +--- a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch ++++ b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -217,6 +217,19 @@ void ath9k_hw_get_channel_centers(struct ++@@ -216,6 +216,19 @@ void ath9k_hw_get_channel_centers(struct + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); + } + +@@ -20,7 +20,7 @@ + /******************/ + /* Chip Revisions */ + /******************/ +-@@ -1337,6 +1350,9 @@ static bool ath9k_hw_set_reset(struct at ++@@ -1336,6 +1349,9 @@ static bool ath9k_hw_set_reset(struct at + if (AR_SREV_9100(ah)) + udelay(50); + +@@ -30,7 +30,7 @@ + return true; + } + +-@@ -1436,6 +1452,9 @@ static bool ath9k_hw_chip_reset(struct a ++@@ -1435,6 +1451,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); + ath9k_hw_init_pll(ah, chan); + +@@ -40,7 +40,7 @@ + return true; + } + +-@@ -1730,8 +1749,14 @@ static int ath9k_hw_do_fastcc(struct ath ++@@ -1729,8 +1748,14 @@ static int ath9k_hw_do_fastcc(struct ath + if (AR_SREV_9271(ah)) + ar9002_hw_load_ani_reg(ah, chan); + +@@ -55,7 +55,7 @@ + return -EINVAL; + } + +-@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++@@ -1958,6 +1983,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + if (AR_SREV_9565(ah) && common->bt_ant_diversity) + REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); + +diff --git a/package/mac80211/patches/567-ath9k-qca953x-support.patch b/package/mac80211/patches/567-ath9k-qca953x-support.patch +deleted file mode 100644 +index e73083a..0000000 +--- a/package/mac80211/patches/567-ath9k-qca953x-support.patch ++++ /dev/null +@@ -1,124 +0,0 @@ +---- a/drivers/net/wireless/ath/ath9k/ahb.c +-+++ b/drivers/net/wireless/ath/ath9k/ahb.c +-@@ -39,6 +39,10 @@ static const struct platform_device_id a +- .name = "qca955x_wmac", +- .driver_data = AR9300_DEVID_QCA955X, +- }, +-+ { +-+ .name = "qca953x_wmac", +-+ .driver_data = AR9300_DEVID_AR953X, +-+ }, +- {}, +- }; +- +---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +-@@ -4792,43 +4792,54 @@ static void ar9003_hw_power_control_over +- +- tempslope: +- if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { +-+ u8 txmask = (eep->baseEepHeader.txrxMask & 0xf0) >> 4; +-+ +- /* +- * AR955x has tempSlope register for each chain. +- * Check whether temp_compensation feature is enabled or not. +- */ +- if (eep->baseEepHeader.featureEnable & 0x1) { +- if (frequency < 4000) { +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19, +-- AR_PHY_TPC_19_ALPHA_THERM, +-- eep->base_ext2.tempSlopeLow); +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, +-- AR_PHY_TPC_19_ALPHA_THERM, +-- temp_slope); +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, +-- AR_PHY_TPC_19_ALPHA_THERM, +-- eep->base_ext2.tempSlopeHigh); +-+ if (txmask & BIT(0)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19, +-+ AR_PHY_TPC_19_ALPHA_THERM, +-+ eep->base_ext2.tempSlopeLow); +-+ if (txmask & BIT(1)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, +-+ AR_PHY_TPC_19_ALPHA_THERM, +-+ temp_slope); +-+ if (txmask & BIT(2)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, +-+ AR_PHY_TPC_19_ALPHA_THERM, +-+ eep->base_ext2.tempSlopeHigh); +- } else { +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19, +-- AR_PHY_TPC_19_ALPHA_THERM, +-- temp_slope); +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, +-- AR_PHY_TPC_19_ALPHA_THERM, +-- temp_slope1); +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, +-- AR_PHY_TPC_19_ALPHA_THERM, +-- temp_slope2); +-+ if (txmask & BIT(0)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19, +-+ AR_PHY_TPC_19_ALPHA_THERM, +-+ temp_slope); +-+ if (txmask & BIT(1)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, +-+ AR_PHY_TPC_19_ALPHA_THERM, +-+ temp_slope1); +-+ if (txmask & BIT(2)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, +-+ AR_PHY_TPC_19_ALPHA_THERM, +-+ temp_slope2); +- } +- } else { +- /* +- * If temp compensation is not enabled, +- * set all registers to 0. +- */ +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19, +-- AR_PHY_TPC_19_ALPHA_THERM, 0); +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, +-- AR_PHY_TPC_19_ALPHA_THERM, 0); +-- REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, +-- AR_PHY_TPC_19_ALPHA_THERM, 0); +-+ if (txmask & BIT(0)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19, +-+ AR_PHY_TPC_19_ALPHA_THERM, 0); +-+ if (txmask & BIT(1)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, +-+ AR_PHY_TPC_19_ALPHA_THERM, 0); +-+ if (txmask & BIT(2)) +-+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, +-+ AR_PHY_TPC_19_ALPHA_THERM, 0); +- } +- } else { +- REG_RMW_FIELD(ah, AR_PHY_TPC_19, +---- a/drivers/net/wireless/ath/ath9k/hw.c +-+++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -901,7 +901,7 @@ static void ath9k_hw_init_interrupt_mask +- AR_IMR_RXORN | +- AR_IMR_BCNMISC; +- +-- if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) +-+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) +- sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; +- +- if (AR_SREV_9300_20_OR_LATER(ah)) { +-@@ -3104,6 +3104,7 @@ static struct { +- { AR_SREV_VERSION_9462, "9462" }, +- { AR_SREV_VERSION_9550, "9550" }, +- { AR_SREV_VERSION_9565, "9565" }, +-+ { AR_SREV_VERSION_9531, "9531" }, +- }; +- +- /* For devices with external radios */ +---- a/drivers/net/wireless/ath/ath9k/mac.c +-+++ b/drivers/net/wireless/ath/ath9k/mac.c +-@@ -837,7 +837,7 @@ void ath9k_hw_enable_interrupts(struct a +- return; +- } +- +-- if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) +-+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) +- sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; +- +- async_mask = AR_INTR_MAC_IRQ; +diff --git a/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch +new file mode 100644 +index 0000000..d344957 +--- /dev/null ++++ b/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch +@@ -0,0 +1,62 @@ ++From 7a69da907de668fb22a30ae218062d6f081864ea Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sat, 17 Aug 2013 19:31:41 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: move rt2800_drv_data declaration into ++ rt2800lib.h ++ ++The rt2800_drv_data structure contains driver specific ++information. Move the declaration into the rt2800lib.h ++header which is a more logical place for it. Also fix ++the comment style to avoid checkpatch warning. ++ ++The patch contains no functional changes, it is in ++preparation for the next patch. ++ ++Signed-off-by: Gabor Juhos ++--- ++Changes since v1: --- ++--- ++ drivers/net/wireless/rt2x00/rt2800.h | 13 ------------- ++ drivers/net/wireless/rt2x00/rt2800lib.h | 11 +++++++++++ ++ 2 files changed, 11 insertions(+), 13 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -2958,17 +2958,4 @@ enum rt2800_eeprom_word { ++ */ ++ #define BCN_TBTT_OFFSET 64 ++ ++-/* ++- * RT2800 driver data structure ++- */ ++-struct rt2800_drv_data { ++- u8 calibration_bw20; ++- u8 calibration_bw40; ++- u8 bbp25; ++- u8 bbp26; ++- u8 txmixer_gain_24g; ++- u8 txmixer_gain_5g; ++- unsigned int tbtt_tick; ++-}; ++- ++ #endif /* RT2800_H */ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.h +++++ b/drivers/net/wireless/rt2x00/rt2800lib.h ++@@ -20,6 +20,17 @@ ++ #ifndef RT2800LIB_H ++ #define RT2800LIB_H ++ +++/* RT2800 driver data structure */ +++struct rt2800_drv_data { +++ u8 calibration_bw20; +++ u8 calibration_bw40; +++ u8 bbp25; +++ u8 bbp26; +++ u8 txmixer_gain_24g; +++ u8 txmixer_gain_5g; +++ unsigned int tbtt_tick; +++}; +++ ++ struct rt2800_ops { ++ void (*register_read)(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, u32 *value); +diff --git a/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch +new file mode 100644 +index 0000000..3b11b15 +--- /dev/null ++++ b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch +@@ -0,0 +1,80 @@ ++From a7f268af31dddf763fe3dbe9cbf96ea77e0540e0 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sat, 17 Aug 2013 19:31:41 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag ++ ++Some chipsets have more than 16KB of shared memory. ++Introduce a new rt2800 specific flag to indicate that ++and add a helper function which helps to check the ++presence of the new flag. ++ ++Also enable the new flag for the RT3593 chipset which ++has 24KB of shared memory. The flag can also be used ++for other chipsets, but none of those has been tested ++yet. ++ ++Signed-off-by: Gabor Juhos ++--- ++Changes since v1: ++ - don't enable the new flag for RT3071 and RT5592 ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++++ ++ drivers/net/wireless/rt2x00/rt2800lib.h | 13 +++++++++++++ ++ 2 files changed, 17 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7712,6 +7712,7 @@ static int rt2800_probe_rt(struct rt2x00 ++ ++ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) ++ { +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ int retval; ++ u32 reg; ++ ++@@ -7719,6 +7720,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ if (retval) ++ return retval; ++ +++ if (rt2x00_rt(rt2x00dev, RT3593)) +++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); +++ ++ /* ++ * Allocate eeprom data. ++ */ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.h +++++ b/drivers/net/wireless/rt2x00/rt2800lib.h ++@@ -20,6 +20,10 @@ ++ #ifndef RT2800LIB_H ++ #define RT2800LIB_H ++ +++enum rt2800_flag { +++ RT2800_HAS_HIGH_SHARED_MEM, +++}; +++ ++ /* RT2800 driver data structure */ ++ struct rt2800_drv_data { ++ u8 calibration_bw20; ++@@ -29,6 +33,8 @@ struct rt2800_drv_data { ++ u8 txmixer_gain_24g; ++ u8 txmixer_gain_5g; ++ unsigned int tbtt_tick; +++ +++ unsigned long rt2800_flags; ++ }; ++ ++ struct rt2800_ops { ++@@ -61,6 +67,13 @@ struct rt2800_ops { ++ __le32 *(*drv_get_txwi)(struct queue_entry *entry); ++ }; ++ +++static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); +++} +++ ++ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ u32 *value) +diff --git a/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch +new file mode 100644 +index 0000000..879b4cc +--- /dev/null ++++ b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch +@@ -0,0 +1,531 @@ ++From 250a1b520cd7fdc0df4fc3fedea9066913f49ecf Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sat, 17 Aug 2013 19:31:42 +0200 ++Subject: [PATCH] rt2x00: rt2800: serialize shared memory access ++ ++The shared memory of the rt2800 devices is accessible ++through the register offset range between 0x4000 and ++0x8000. The size of this range is 16KB only and on ++devices which have more than 16KB of shared memory either ++the low or the high part of the memory is accessible at a ++time. ++ ++Serialize all accesses to the shared memory by a mutex, ++in order to avoid concurrent use of that. ++ ++Signed-off-by: Gabor Juhos ++--- ++Changes since v1: --- ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 55 +++++++++++++++++++++++++++++- ++ drivers/net/wireless/rt2x00/rt2800lib.h | 32 +++++++++++++++++ ++ drivers/net/wireless/rt2x00/rt2800mmio.c | 26 ++++++++++++++ ++ drivers/net/wireless/rt2x00/rt2800mmio.h | 4 +++ ++ drivers/net/wireless/rt2x00/rt2800pci.c | 14 ++++++++ ++ drivers/net/wireless/rt2x00/rt2800soc.c | 3 ++ ++ drivers/net/wireless/rt2x00/rt2800usb.c | 31 +++++++++++++++++ ++ 7 files changed, 164 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -451,11 +451,13 @@ void rt2800_mcu_request(struct rt2x00_de ++ rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); ++ rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); ++ rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); ++ ++ reg = 0; ++ rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); ++ rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ mutex_unlock(&rt2x00dev->csr_mutex); ++@@ -674,7 +676,9 @@ int rt2800_load_firmware(struct rt2x00_d ++ * Wait for device to stabilize. ++ */ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) ++ break; ++ msleep(1); ++@@ -694,10 +698,16 @@ int rt2800_load_firmware(struct rt2x00_d ++ /* ++ * Initialize firmware. ++ */ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); +++ ++ if (rt2x00_is_usb(rt2x00dev)) { +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); +++ ++ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); ++ } ++ msleep(1); ++@@ -1001,8 +1011,10 @@ void rt2800_write_beacon(struct queue_en ++ ++ beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, ++ entry->skb->len + padding_len); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ /* ++ * Enable beaconing again. ++@@ -1027,6 +1039,8 @@ static inline void rt2800_clear_beacon_r ++ ++ beacon_base = rt2800_hw_beacon_base(rt2x00dev, index); ++ +++ rt2800_shared_mem_lock(rt2x00dev); +++ ++ /* ++ * For the Beacon base registers we only need to clear ++ * the whole TXWI which (when set to 0) will invalidate ++@@ -1034,6 +1048,8 @@ static inline void rt2800_clear_beacon_r ++ */ ++ for (i = 0; i < txwi_desc_size; i += sizeof(__le32)) ++ rt2800_register_write(rt2x00dev, beacon_base + i, 0); +++ +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ void rt2800_clear_beacon(struct queue_entry *entry) ++@@ -1217,7 +1233,9 @@ static void rt2800_delete_wcid_attr(stru ++ { ++ u32 offset; ++ offset = MAC_WCID_ATTR_ENTRY(wcid); +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, offset, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev, ++@@ -1230,11 +1248,13 @@ static void rt2800_config_wcid_attr_bssi ++ * The BSS Idx numbers is split in a main value of 3 bits, ++ * and a extended field for adding one additional bit to the value. ++ */ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7)); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, ++ (bssidx & 0x8) >> 3); ++ rt2800_register_write(rt2x00dev, offset, reg); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, ++@@ -1247,6 +1267,7 @@ static void rt2800_config_wcid_attr_ciph ++ ++ offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ if (crypto->cmd == SET_KEY) { ++ rt2800_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, ++@@ -1271,6 +1292,7 @@ static void rt2800_config_wcid_attr_ciph ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); ++ rt2800_register_write(rt2x00dev, offset, reg); ++ } +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ offset = MAC_IVEIV_ENTRY(key->hw_key_idx); ++ ++@@ -1280,8 +1302,11 @@ static void rt2800_config_wcid_attr_ciph ++ (crypto->cipher == CIPHER_AES)) ++ iveiv_entry.iv[3] |= 0x20; ++ iveiv_entry.iv[3] |= key->keyidx << 6; +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_multiwrite(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, ++@@ -1304,8 +1329,11 @@ int rt2800_config_shared_key(struct rt2x ++ sizeof(key_entry.rx_mic)); ++ ++ offset = SHARED_KEY_ENTRY(key->hw_key_idx); +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_multiwrite(rt2x00dev, offset, ++ &key_entry, sizeof(key_entry)); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ /* ++@@ -1320,10 +1348,12 @@ int rt2800_config_shared_key(struct rt2x ++ ++ offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, field, ++ (crypto->cmd == SET_KEY) * crypto->cipher); ++ rt2800_register_write(rt2x00dev, offset, reg); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ /* ++ * Update WCID information ++@@ -1393,8 +1423,11 @@ int rt2800_config_pairwise_key(struct rt ++ sizeof(key_entry.rx_mic)); ++ ++ offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_multiwrite(rt2x00dev, offset, ++ &key_entry, sizeof(key_entry)); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ /* ++@@ -4876,14 +4909,19 @@ static int rt2800_init_registers(struct ++ /* ++ * ASIC will keep garbage value after boot, clear encryption keys. ++ */ +++ rt2800_shared_mem_lock(rt2x00dev); ++ for (i = 0; i < 4; i++) ++ rt2800_register_write(rt2x00dev, ++ SHARED_KEY_MODE_ENTRY(i), 0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ for (i = 0; i < 256; i++) { ++ rt2800_config_wcid(rt2x00dev, NULL, i); ++ rt2800_delete_wcid_attr(rt2x00dev, i); +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ /* ++@@ -5009,8 +5047,10 @@ static int rt2800_wait_bbp_ready(struct ++ * BBP was enabled after firmware was loaded, ++ * but we need to reactivate it now. ++ */ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ msleep(1); ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++@@ -6706,11 +6746,19 @@ int rt2800_enable_radio(struct rt2x00_de ++ /* ++ * Send signal during boot time to initialize firmware. ++ */ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++- if (rt2x00_is_usb(rt2x00dev)) +++ rt2800_shared_mem_unlock(rt2x00dev); +++ +++ if (rt2x00_is_usb(rt2x00dev)) { +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); +++ } +++ ++ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); +++ ++ msleep(1); ++ ++ /* ++@@ -7716,6 +7764,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ int retval; ++ u32 reg; ++ +++ rt2800_shared_mem_init_lock(rt2x00dev); +++ ++ retval = rt2800_probe_rt(rt2x00dev); ++ if (retval) ++ return retval; ++@@ -7795,8 +7845,11 @@ void rt2800_get_tkip_seq(struct ieee8021 ++ u32 offset; ++ ++ offset = MAC_IVEIV_ENTRY(hw_key_idx); +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2800_register_multiread(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16)); ++ memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32)); ++--- a/drivers/net/wireless/rt2x00/rt2800lib.h +++++ b/drivers/net/wireless/rt2x00/rt2800lib.h ++@@ -35,6 +35,11 @@ struct rt2800_drv_data { ++ unsigned int tbtt_tick; ++ ++ unsigned long rt2800_flags; +++ +++ union { +++ spinlock_t spin; +++ struct mutex mutex; +++ } shmem_lock; ++ }; ++ ++ struct rt2800_ops { ++@@ -65,6 +70,10 @@ struct rt2800_ops { ++ const u8 *data, const size_t len); ++ int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); ++ __le32 *(*drv_get_txwi)(struct queue_entry *entry); +++ +++ void (*shmem_init_lock)(struct rt2x00_dev *rt2x00dev); +++ void (*shmem_lock)(struct rt2x00_dev *rt2x00dev); +++ void (*shmem_unlock)(struct rt2x00_dev *rt2x00dev); ++ }; ++ ++ static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev) ++@@ -74,6 +83,29 @@ static inline bool rt2800_has_high_share ++ return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++ } ++ +++static inline void rt2800_shared_mem_init_lock(struct rt2x00_dev *rt2x00dev) +++{ +++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; +++ +++ rt2800ops->shmem_init_lock(rt2x00dev); +++} +++ +++static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev) +++{ +++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; +++ +++ if (rt2800_has_high_shared_mem(rt2x00dev)) +++ rt2800ops->shmem_lock(rt2x00dev); +++} +++ +++static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev) +++{ +++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; +++ +++ if (rt2800_has_high_shared_mem(rt2x00dev)) +++ rt2800ops->shmem_unlock(rt2x00dev); +++} +++ ++ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ u32 *value) ++--- a/drivers/net/wireless/rt2x00/rt2800mmio.c +++++ b/drivers/net/wireless/rt2x00/rt2800mmio.c ++@@ -820,8 +820,10 @@ int rt2800mmio_init_registers(struct rt2 ++ rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); ++ rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); ++ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ if (rt2x00_is_pcie(rt2x00dev) && ++ (rt2x00_rt(rt2x00dev, RT3090) || ++@@ -865,6 +867,30 @@ int rt2800mmio_enable_radio(struct rt2x0 ++ } ++ EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio); ++ +++void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ spin_lock_init(&drv_data->shmem_lock.spin); +++} +++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_init_lock); +++ +++void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ spin_lock_bh(&drv_data->shmem_lock.spin); +++} +++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_lock); +++ +++void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ spin_unlock_bh(&drv_data->shmem_lock.spin); +++} +++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_unlock); +++ ++ MODULE_AUTHOR(DRV_PROJECT); ++ MODULE_VERSION(DRV_VERSION); ++ MODULE_DESCRIPTION("rt2800 MMIO library"); ++--- a/drivers/net/wireless/rt2x00/rt2800mmio.h +++++ b/drivers/net/wireless/rt2x00/rt2800mmio.h ++@@ -160,4 +160,8 @@ int rt2800mmio_init_registers(struct rt2 ++ /* Device state switch handlers. */ ++ int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev); ++ +++void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev); +++void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev); +++void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev); +++ ++ #endif /* RT2800MMIO_H */ ++--- a/drivers/net/wireless/rt2x00/rt2800pci.c +++++ b/drivers/net/wireless/rt2x00/rt2800pci.c ++@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct ++ return; ++ ++ for (i = 0; i < 200; i++) { +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || ++@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct ++ if (i == 200) ++ rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n"); ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ ++ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) ++@@ -184,6 +188,8 @@ static int rt2800pci_write_firmware(stru ++ */ ++ reg = 0; ++ rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg); ++ ++ /* ++@@ -197,6 +203,7 @@ static int rt2800pci_write_firmware(stru ++ ++ rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ return 0; ++ } ++@@ -213,8 +220,10 @@ static int rt2800pci_enable_radio(struct ++ return retval; ++ ++ /* After resume MCU_BOOT_SIGNAL will trash these. */ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); ++@@ -233,10 +242,12 @@ static int rt2800pci_set_state(struct rt ++ 0, 0x02); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); ++ } else if (state == STATE_SLEEP) { +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ++ 0xffffffff); ++ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ++ 0xffffffff); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, ++ 0xff, 0x01); ++ } ++@@ -337,6 +348,9 @@ static const struct rt2800_ops rt2800pci ++ .drv_write_firmware = rt2800pci_write_firmware, ++ .drv_init_registers = rt2800mmio_init_registers, ++ .drv_get_txwi = rt2800mmio_get_txwi, +++ .shmem_init_lock = rt2800mmio_shmem_init_lock, +++ .shmem_lock = rt2800mmio_shmem_lock, +++ .shmem_unlock = rt2800mmio_shmem_unlock, ++ }; ++ ++ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { ++--- a/drivers/net/wireless/rt2x00/rt2800soc.c +++++ b/drivers/net/wireless/rt2x00/rt2800soc.c ++@@ -176,6 +176,9 @@ static const struct rt2800_ops rt2800soc ++ .drv_write_firmware = rt2800soc_write_firmware, ++ .drv_init_registers = rt2800mmio_init_registers, ++ .drv_get_txwi = rt2800mmio_get_txwi, +++ .shmem_init_lock = rt2800mmio_shmem_init_lock, +++ .shmem_lock = rt2800mmio_shmem_lock, +++ .shmem_unlock = rt2800mmio_shmem_unlock, ++ }; ++ ++ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { ++--- a/drivers/net/wireless/rt2x00/rt2800usb.c +++++ b/drivers/net/wireless/rt2x00/rt2800usb.c ++@@ -51,6 +51,27 @@ static bool rt2800usb_hwcrypt_disabled(s ++ return modparam_nohwcrypt; ++ } ++ +++static void rt2800usb_shmem_init_lock(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ mutex_init(&drv_data->shmem_lock.mutex); +++} +++ +++static void rt2800usb_shmem_lock(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ mutex_lock(&drv_data->shmem_lock.mutex); +++} +++ +++static void rt2800usb_shmem_unlock(struct rt2x00_dev *rt2x00dev) +++{ +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +++ +++ mutex_unlock(&drv_data->shmem_lock.mutex); +++} +++ ++ /* ++ * Queue handlers. ++ */ ++@@ -260,8 +281,10 @@ static int rt2800usb_write_firmware(stru ++ rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, ++ data + offset, length); ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ /* ++ * Send firmware request to device to load firmware, ++@@ -276,7 +299,10 @@ static int rt2800usb_write_firmware(stru ++ } ++ ++ msleep(10); +++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ return 0; ++ } ++@@ -294,8 +320,10 @@ static int rt2800usb_init_registers(stru ++ if (rt2800_wait_csr_ready(rt2x00dev)) ++ return -EBUSY; ++ +++ rt2800_shared_mem_lock(rt2x00dev); ++ rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); +++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ reg = 0; ++ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); ++@@ -810,6 +838,9 @@ static const struct rt2800_ops rt2800usb ++ .drv_write_firmware = rt2800usb_write_firmware, ++ .drv_init_registers = rt2800usb_init_registers, ++ .drv_get_txwi = rt2800usb_get_txwi, +++ .shmem_init_lock = rt2800usb_shmem_init_lock, +++ .shmem_lock = rt2800usb_shmem_lock, +++ .shmem_unlock = rt2800usb_shmem_unlock, ++ }; ++ ++ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { +diff --git a/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch +new file mode 100644 +index 0000000..38dbb43 +--- /dev/null ++++ b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch +@@ -0,0 +1,131 @@ ++From dcfe3dd46242050f100162dce2bcad24d2c942c6 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sat, 17 Aug 2013 19:31:42 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix beacon generation on RT3593 ++ ++On the RT3593 chipset, the beacon registers are located ++in the high 8KB part of the shared memory. ++ ++The high part of the shared memory is only accessible ++if it is explicitly selected. Add a helper function ++in order to be able to control the SHR_MSEL bit in ++the PBF_SYS_CTRL register. Also add a few more helper ++functions and use those to select the correct part of ++the shared memory before and after accessing the beacon ++registers. ++ ++The base addresses of the beacon registers are also ++different from the actually used values, so fix the ++'rt2800_hw_beacon_base' function to return the correct ++values. ++ ++Signed-off-by: Gabor Juhos ++--- ++Changes since v1: --- ++--- ++ drivers/net/wireless/rt2x00/rt2800.h | 3 +++ ++ drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++ ++ 2 files changed, 47 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -572,6 +572,7 @@ ++ #define PBF_SYS_CTRL 0x0400 ++ #define PBF_SYS_CTRL_READY FIELD32(0x00000080) ++ #define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) +++#define PBF_SYS_CTRL_SHR_MSEL FIELD32(0x00080000) ++ ++ /* ++ * HOST-MCU shared memory ++@@ -2024,6 +2025,8 @@ struct mac_iveiv_entry { ++ (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ ++ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) ++ +++#define HW_BEACON_BASE_HIGH(__index) (0x4000 + (__index) * 512) +++ ++ #define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64) ++ ++ /* ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(st ++ return false; ++ } ++ +++static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev, +++ bool high) +++{ +++ u32 reg; +++ +++ if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev))) +++ return; +++ +++ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); +++ rt2x00_set_field32(®, PBF_SYS_CTRL_SHR_MSEL, high); +++ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); +++} +++ +++static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev) +++{ +++ if (rt2x00_rt(rt2x00dev, RT3593)) +++ return true; +++ +++ return false; +++} +++ +++static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev) +++{ +++ if (rt2800_beacon_uses_high_mem(rt2x00dev)) +++ rt2800_shared_mem_select(rt2x00dev, true); +++} +++ +++static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev) +++{ +++ if (rt2800_beacon_uses_high_mem(rt2x00dev)) +++ rt2800_shared_mem_select(rt2x00dev, false); +++} +++ ++ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, const u8 value) ++ { ++@@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry); ++ static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, ++ unsigned int index) ++ { +++ if (rt2x00_rt(rt2x00dev, RT3593)) +++ return HW_BEACON_BASE_HIGH(index); +++ ++ return HW_BEACON_BASE(index); ++ } ++ ++@@ -1012,8 +1048,12 @@ void rt2800_write_beacon(struct queue_en ++ beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); ++ ++ rt2800_shared_mem_lock(rt2x00dev); +++ +++ rt2800_select_beacon_mem(rt2x00dev); ++ rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, ++ entry->skb->len + padding_len); +++ rt2800_deselect_beacon_mem(rt2x00dev); +++ ++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ /* ++@@ -1041,6 +1081,8 @@ static inline void rt2800_clear_beacon_r ++ ++ rt2800_shared_mem_lock(rt2x00dev); ++ +++ rt2800_select_beacon_mem(rt2x00dev); +++ ++ /* ++ * For the Beacon base registers we only need to clear ++ * the whole TXWI which (when set to 0) will invalidate ++@@ -1049,6 +1091,8 @@ static inline void rt2800_clear_beacon_r ++ for (i = 0; i < txwi_desc_size; i += sizeof(__le32)) ++ rt2800_register_write(rt2x00dev, beacon_base + i, 0); ++ +++ rt2800_deselect_beacon_mem(rt2x00dev); +++ ++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ +diff --git a/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch +new file mode 100644 +index 0000000..3d97169 +--- /dev/null ++++ b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch +@@ -0,0 +1,62 @@ ++From a058825fa7b53fab3b003d8928b60e5b686b3421 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 4 Aug 2013 14:36:11 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: add hw_beacon_count field to struct ++ rt2800_drv_data ++ ++Some chipsets can handle more than 8 beacons at once. ++Add a new field to the rt2800_drv_data structure which ++will hold the number of supported beacons of the given ++chipset. ++ ++Update the rt2x00_init_registers function to get the ++beacon count from the new field instead of using a ++hardcoded value. ++ ++In order to keep the current behaviour, initialize the ++new field with the actually used value. ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- ++ drivers/net/wireless/rt2x00/rt2800lib.h | 1 + ++ 2 files changed, 5 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -4584,6 +4584,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); ++ */ ++ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) ++ { +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ u32 reg; ++ u16 eeprom; ++ unsigned int i; ++@@ -4971,7 +4972,7 @@ static int rt2800_init_registers(struct ++ /* ++ * Clear all beacons ++ */ ++- for (i = 0; i < 8; i++) +++ for (i = 0; i < drv_data->hw_beacon_count; i++) ++ rt2800_clear_beacon_register(rt2x00dev, i); ++ ++ if (rt2x00_is_usb(rt2x00dev)) { ++@@ -7817,6 +7818,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++ +++ drv_data->hw_beacon_count = 8; +++ ++ /* ++ * Allocate eeprom data. ++ */ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.h +++++ b/drivers/net/wireless/rt2x00/rt2800lib.h ++@@ -33,6 +33,7 @@ struct rt2800_drv_data { ++ u8 txmixer_gain_24g; ++ u8 txmixer_gain_5g; ++ unsigned int tbtt_tick; +++ unsigned int hw_beacon_count; ++ ++ unsigned long rt2800_flags; ++ +diff --git a/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch +new file mode 100644 +index 0000000..8c52713 +--- /dev/null ++++ b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch +@@ -0,0 +1,67 @@ ++From 1bfa43ca8f30be53ce4fa79cfc3e219642a812b6 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 2 Sep 2013 10:58:32 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: init additional beacon offset registers ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++ ++ drivers/net/wireless/rt2x00/rt2800lib.c | 24 ++++++++++++++++++++++++ ++ 2 files changed, 38 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -627,6 +627,20 @@ ++ */ ++ #define PBF_DBG 0x043c ++ +++/* BCN_OFFSET2 */ +++#define BCN_OFFSET2 0x0444 +++#define BCN_OFFSET2_BCN8 FIELD32(0x000000ff) +++#define BCN_OFFSET2_BCN9 FIELD32(0x0000ff00) +++#define BCN_OFFSET2_BCN10 FIELD32(0x00ff0000) +++#define BCN_OFFSET2_BCN11 FIELD32(0xff000000) +++ +++/* BCN_OFFSET3 */ +++#define BCN_OFFSET3 0x0448 +++#define BCN_OFFSET3_BCN12 FIELD32(0x000000ff) +++#define BCN_OFFSET3_BCN13 FIELD32(0x0000ff00) +++#define BCN_OFFSET3_BCN14 FIELD32(0x00ff0000) +++#define BCN_OFFSET3_BCN15 FIELD32(0xff000000) +++ ++ /* ++ * RF registers ++ */ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -4618,6 +4618,30 @@ static int rt2800_init_registers(struct ++ rt2800_get_beacon_offset(rt2x00dev, 7)); ++ rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg); ++ +++ if (drv_data->hw_beacon_count == 16) { +++ rt2800_register_read(rt2x00dev, BCN_OFFSET2, ®); +++ rt2x00_set_field32(®, BCN_OFFSET2_BCN8, +++ rt2800_get_beacon_offset(rt2x00dev, 8)); +++ rt2x00_set_field32(®, BCN_OFFSET2_BCN9, +++ rt2800_get_beacon_offset(rt2x00dev, 9)); +++ rt2x00_set_field32(®, BCN_OFFSET2_BCN10, +++ rt2800_get_beacon_offset(rt2x00dev, 10)); +++ rt2x00_set_field32(®, BCN_OFFSET2_BCN11, +++ rt2800_get_beacon_offset(rt2x00dev, 11)); +++ rt2800_register_write(rt2x00dev, BCN_OFFSET2, reg); +++ +++ rt2800_register_read(rt2x00dev, BCN_OFFSET3, ®); +++ rt2x00_set_field32(®, BCN_OFFSET3_BCN12, +++ rt2800_get_beacon_offset(rt2x00dev, 12)); +++ rt2x00_set_field32(®, BCN_OFFSET3_BCN13, +++ rt2800_get_beacon_offset(rt2x00dev, 13)); +++ rt2x00_set_field32(®, BCN_OFFSET3_BCN14, +++ rt2800_get_beacon_offset(rt2x00dev, 14)); +++ rt2x00_set_field32(®, BCN_OFFSET3_BCN15, +++ rt2800_get_beacon_offset(rt2x00dev, 15)); +++ rt2800_register_write(rt2x00dev, BCN_OFFSET3, reg); +++ } +++ ++ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); ++ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); ++ +diff --git a/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch +new file mode 100644 +index 0000000..66e8245 +--- /dev/null ++++ b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch +@@ -0,0 +1,24 @@ ++From 9bea8b61f6025cd633bd5ac71be258620b49bcb3 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 2 Sep 2013 11:00:06 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix max supported beacon count for RT3593 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- ++ 1 file changed, 4 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7842,7 +7842,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++ ++- drv_data->hw_beacon_count = 8; +++ if (rt2x00_rt(rt2x00dev, RT3593)) +++ drv_data->hw_beacon_count = 16; +++ else +++ drv_data->hw_beacon_count = 8; ++ ++ /* ++ * Allocate eeprom data. +diff --git a/package/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch b/package/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch +new file mode 100644 +index 0000000..8a10c6e +--- /dev/null ++++ b/package/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch +@@ -0,0 +1,30 @@ ++From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:26 +0100 ++Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/Kconfig | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/Kconfig +++++ b/drivers/net/wireless/rt2x00/Kconfig ++@@ -210,7 +210,7 @@ endif ++ config RT2800SOC ++ tristate "Ralink WiSoC support" ++ depends on m ++- depends on SOC_RT288X || SOC_RT305X +++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 ++ select RT2X00_LIB_SOC ++ select RT2X00_LIB_MMIO ++ select RT2X00_LIB_CRYPTO ++@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI ++ ++ config RT2X00_LIB_SOC ++ tristate "RT2x00 SoC support" ++- depends on SOC_RT288X || SOC_RT305X +++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 ++ depends on m ++ select RT2X00_LIB ++ +diff --git a/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch +new file mode 100644 +index 0000000..e9d847a +--- /dev/null ++++ b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch +@@ -0,0 +1,20 @@ ++From 4f16582c93a71eba9d389e0f0a8aa9099a9587cd Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:26 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7812,6 +7812,7 @@ static int rt2800_probe_rt(struct rt2x00 ++ case RT3390: ++ case RT3572: ++ case RT3593: +++ case RT3883: ++ case RT5390: ++ case RT5392: ++ case RT5592: +diff --git a/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch +new file mode 100644 +index 0000000..b096f9f +--- /dev/null ++++ b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch +@@ -0,0 +1,112 @@ ++From ecb394ccf248d8652c463133c4f404458a57a9c1 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:26 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800.h | 4 +- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 65 +++++++++++++++++++++++++++++++ ++ 2 files changed, 68 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -48,7 +48,8 @@ ++ * RF2853 2.4G/5G 3T3R ++ * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) ++ * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) ++- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) +++ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593) +++ * RF3853 2.4G/5G 3T3R(RT3883/RT3662) ++ * RF5592 2.4G/5G 2T2R ++ * RF3070 2.4G 1T1R ++ * RF5360 2.4G 1T1R ++@@ -71,6 +72,7 @@ ++ #define RF5592 0x000f ++ #define RF3070 0x3070 ++ #define RF3290 0x3290 +++#define RF3853 0x3853 ++ #define RF5360 0x5360 ++ #define RF5370 0x5370 ++ #define RF5372 0x5372 ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7432,6 +7432,66 @@ static const struct rf_channel rf_vals_3 ++ {173, 0x61, 0, 9}, ++ }; ++ +++static const struct rf_channel rf_vals_3853[] = { +++ {1, 241, 6, 2}, +++ {2, 241, 6, 7}, +++ {3, 242, 6, 2}, +++ {4, 242, 6, 7}, +++ {5, 243, 6, 2}, +++ {6, 243, 6, 7}, +++ {7, 244, 6, 2}, +++ {8, 244, 6, 7}, +++ {9, 245, 6, 2}, +++ {10, 245, 6, 7}, +++ {11, 246, 6, 2}, +++ {12, 246, 6, 7}, +++ {13, 247, 6, 2}, +++ {14, 248, 6, 4}, +++ +++ {36, 0x56, 8, 4}, +++ {38, 0x56, 8, 6}, +++ {40, 0x56, 8, 8}, +++ {44, 0x57, 8, 0}, +++ {46, 0x57, 8, 2}, +++ {48, 0x57, 8, 4}, +++ {52, 0x57, 8, 8}, +++ {54, 0x57, 8, 10}, +++ {56, 0x58, 8, 0}, +++ {60, 0x58, 8, 4}, +++ {62, 0x58, 8, 6}, +++ {64, 0x58, 8, 8}, +++ +++ {100, 0x5b, 8, 8}, +++ {102, 0x5b, 8, 10}, +++ {104, 0x5c, 8, 0}, +++ {108, 0x5c, 8, 4}, +++ {110, 0x5c, 8, 6}, +++ {112, 0x5c, 8, 8}, +++ {114, 0x5c, 8, 10}, +++ {116, 0x5d, 8, 0}, +++ {118, 0x5d, 8, 2}, +++ {120, 0x5d, 8, 4}, +++ {124, 0x5d, 8, 8}, +++ {126, 0x5d, 8, 10}, +++ {128, 0x5e, 8, 0}, +++ {132, 0x5e, 8, 4}, +++ {134, 0x5e, 8, 6}, +++ {136, 0x5e, 8, 8}, +++ {140, 0x5f, 8, 0}, +++ +++ {149, 0x5f, 8, 9}, +++ {151, 0x5f, 8, 11}, +++ {153, 0x60, 8, 1}, +++ {157, 0x60, 8, 5}, +++ {159, 0x60, 8, 7}, +++ {161, 0x60, 8, 9}, +++ {165, 0x61, 8, 1}, +++ {167, 0x61, 8, 3}, +++ {169, 0x61, 8, 5}, +++ {171, 0x61, 8, 7}, +++ {173, 0x61, 8, 9}, +++}; +++ ++ static const struct rf_channel rf_vals_5592_xtal20[] = { ++ /* Channel, N, K, mod, R */ ++ {1, 482, 4, 10, 3}, ++@@ -7660,6 +7720,11 @@ static int rt2800_probe_hw_mode(struct r ++ spec->channels = rf_vals_3x; ++ break; ++ +++ case RF3853: +++ spec->num_channels = ARRAY_SIZE(rf_vals_3853); +++ spec->channels = rf_vals_3853; +++ break; +++ ++ case RF5592: ++ rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); ++ if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { +diff --git a/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch +new file mode 100644 +index 0000000..4c9a3b4 +--- /dev/null ++++ b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch +@@ -0,0 +1,28 @@ ++From f8e3fcf18e1f2d7f9e6a9680c5452da090f33d88 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Thu, 1 Aug 2013 14:40:44 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++ ++ 1 file changed, 2 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -4349,6 +4349,7 @@ void rt2800_vco_calibration(struct rt2x0 ++ case RF3053: ++ case RF3070: ++ case RF3290: +++ case RF3853: ++ case RF5360: ++ case RF5370: ++ case RF5372: ++@@ -7839,6 +7840,7 @@ static int rt2800_probe_hw_mode(struct r ++ case RF3053: ++ case RF3070: ++ case RF3290: +++ case RF3853: ++ case RF5360: ++ case RF5370: ++ case RF5372: +diff --git a/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch +new file mode 100644 +index 0000000..e3460ff +--- /dev/null ++++ b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch +@@ -0,0 +1,235 @@ ++From 6e3a17190815c6aa4dc53c2cfe9125fb1154f187 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:27 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for ++ RF3853 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++++++++ ++ 1 file changed, 208 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -2605,6 +2605,211 @@ static void rt2800_config_channel_rf3053 ++ } ++ } ++ +++static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev, +++ struct ieee80211_conf *conf, +++ struct rf_channel *rf, +++ struct channel_info *info) +++{ +++ u8 rfcsr; +++ u8 bbp; +++ u8 pwr1, pwr2, pwr3; +++ +++ const bool txbf_enabled = false; /* TODO */ +++ +++ /* TODO: add band selection */ +++ +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); +++ else if (rf->channel < 132) +++ rt2800_rfcsr_write(rt2x00dev, 6, 0x80); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); +++ +++ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +++ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); +++ +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 11, 0x46); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48); +++ +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 12, 0x52); +++ +++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12); +++ +++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +++ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); +++ +++ switch (rt2x00dev->default_ant.tx_chain_num) { +++ case 3: +++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +++ /* fallthrough */ +++ case 2: +++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +++ /* fallthrough */ +++ case 1: +++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +++ break; +++ } +++ +++ switch (rt2x00dev->default_ant.rx_chain_num) { +++ case 3: +++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +++ /* fallthrough */ +++ case 2: +++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +++ /* fallthrough */ +++ case 1: +++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +++ break; +++ } +++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +++ +++ rt2800_adjust_freq_offset(rt2x00dev); +++ +++ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +++ if (!conf_is_ht40(conf)) +++ rfcsr &= ~(0x06); +++ else +++ rfcsr |= 0x06; +++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); +++ +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +++ +++ if (conf_is_ht40(conf)) +++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8); +++ +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20); +++ +++ /* loopback RF_BS */ +++ rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr); +++ if (rf->channel <= 14) +++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1); +++ else +++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0); +++ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr); +++ +++ if (rf->channel <= 14) +++ rfcsr = 0x23; +++ else if (rf->channel < 100) +++ rfcsr = 0x36; +++ else if (rf->channel < 132) +++ rfcsr = 0x32; +++ else +++ rfcsr = 0x30; +++ +++ if (txbf_enabled) +++ rfcsr |= 0x40; +++ +++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); +++ +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); +++ +++ if (rf->channel <= 14) +++ rfcsr = 0xbb; +++ else if (rf->channel < 100) +++ rfcsr = 0xeb; +++ else if (rf->channel < 132) +++ rfcsr = 0xb3; +++ else +++ rfcsr = 0x9b; +++ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr); +++ +++ if (rf->channel <= 14) +++ rfcsr = 0x8e; +++ else +++ rfcsr = 0x8a; +++ +++ if (txbf_enabled) +++ rfcsr |= 0x20; +++ +++ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); +++ +++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86); +++ +++ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 51, 0x75); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51); +++ +++ rt2800_rfcsr_read(rt2x00dev, 52, &rfcsr); +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 52, 0x45); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05); +++ +++ if (rf->channel <= 14) { +++ pwr1 = info->default_power1 & 0x1f; +++ pwr2 = info->default_power2 & 0x1f; +++ pwr3 = info->default_power3 & 0x1f; +++ } else { +++ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) | +++ (info->default_power1 & 0x7); +++ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) | +++ (info->default_power2 & 0x7); +++ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) | +++ (info->default_power3 & 0x7); +++ } +++ +++ rt2800_rfcsr_write(rt2x00dev, 53, pwr1); +++ rt2800_rfcsr_write(rt2x00dev, 54, pwr2); +++ rt2800_rfcsr_write(rt2x00dev, 55, pwr3); +++ +++ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n", +++ rf->channel, pwr1, pwr2, pwr3); +++ +++ bbp = (info->default_power1 >> 5) | +++ ((info->default_power2 & 0xe0) >> 1); +++ rt2800_bbp_write(rt2x00dev, 109, bbp); +++ +++ rt2800_bbp_read(rt2x00dev, 110, &bbp); +++ bbp &= 0x0f; +++ bbp |= (info->default_power3 & 0xe0) >> 1; +++ rt2800_bbp_write(rt2x00dev, 110, bbp); +++ +++ rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr); +++ if (rf->channel <= 14) +++ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); +++ else +++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e); +++ +++ /* Enable RF tuning */ +++ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +++ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +++ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); +++ +++ udelay(2000); +++ +++ rt2800_bbp_read(rt2x00dev, 49, &bbp); +++ /* clear update flag */ +++ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe); +++ rt2800_bbp_write(rt2x00dev, 49, bbp); +++ +++ /* TODO: add calibration for TxBF */ +++} +++ ++ #define POWER_BOUND 0x27 ++ #define POWER_BOUND_5G 0x2b ++ ++@@ -3217,6 +3422,9 @@ static void rt2800_config_channel(struct ++ case RF3322: ++ rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); ++ break; +++ case RF3853: +++ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info); +++ break; ++ case RF3070: ++ case RF5360: ++ case RF5370: +diff --git a/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch +new file mode 100644 +index 0000000..8719425 +--- /dev/null ++++ b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch +@@ -0,0 +1,20 @@ ++From afd38ae82226551bf879b6c7c4b620c271fee9d2 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Thu, 1 Aug 2013 14:42:05 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7398,6 +7398,7 @@ static int rt2800_init_eeprom(struct rt2 ++ case RF3290: ++ case RF3320: ++ case RF3322: +++ case RF3853: ++ case RF5360: ++ case RF5370: ++ case RF5372: +diff --git a/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch +new file mode 100644 +index 0000000..8632ddd +--- /dev/null ++++ b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch +@@ -0,0 +1,77 @@ ++From 0094872a5e8e4664c6ea1b2dfa487063d39ae363 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:26 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for ++ RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++ ++ drivers/net/wireless/rt2x00/rt2800lib.c | 19 ++++++++++++++++--- ++ 2 files changed, 30 insertions(+), 3 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -1586,6 +1586,20 @@ ++ #define TX_PWR_CFG_9_STBC7_CH2 FIELD32(0x00000f00) ++ ++ /* +++ * TX_TXBF_CFG: +++ */ +++#define TX_TXBF_CFG_0 0x138c +++#define TX_TXBF_CFG_1 0x13a4 +++#define TX_TXBF_CFG_2 0x13a8 +++#define TX_TXBF_CFG_3 0x13ac +++ +++/* +++ * TX_FBK_CFG_3S: +++ */ +++#define TX_FBK_CFG_3S_0 0x13c4 +++#define TX_FBK_CFG_3S_1 0x13c8 +++ +++/* ++ * RX_FILTER_CFG: RX configuration register. ++ */ ++ #define RX_FILTER_CFG 0x1400 ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -4973,6 +4973,12 @@ static int rt2800_init_registers(struct ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, ++ 0x00000000); ++ } +++ } else if (rt2x00_rt(rt2x00dev, RT3883)) { +++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); +++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); +++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000); +++ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21); +++ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40); ++ } else if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392) || ++ rt2x00_rt(rt2x00dev, RT5592)) { ++@@ -5003,9 +5009,11 @@ static int rt2800_init_registers(struct ++ ++ rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); ++- if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || ++- rt2x00_rt(rt2x00dev, RT2883) || ++- rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) +++ if (rt2x00_rt(rt2x00dev, RT3883)) +++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 3); +++ else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || +++ rt2x00_rt(rt2x00dev, RT2883) || +++ rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); ++ else ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); ++@@ -5158,6 +5166,11 @@ static int rt2800_init_registers(struct ++ reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; ++ rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); ++ +++ if (rt2x00_rt(rt2x00dev, RT3883)) { +++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008); +++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413); +++ } +++ ++ rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); ++ rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); ++ rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, +diff --git a/package/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch b/package/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch +new file mode 100644 +index 0000000..837c025 +--- /dev/null ++++ b/package/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch +@@ -0,0 +1,30 @@ ++From 6c2d32478159fffff0b85abb6817a21bb2338231 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:27 +0100 ++Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800soc.c | 9 ++++++++- ++ 1 file changed, 8 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800soc.c +++++ b/drivers/net/wireless/rt2x00/rt2800soc.c ++@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s ++ ++ static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev) ++ { +++ u32 reg; +++ ++ rt2800_disable_radio(rt2x00dev); ++ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); ++- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); +++ +++ reg = 0; +++ if (rt2x00_rt(rt2x00dev, RT3883)) +++ rt2x00_set_field32(®, TX_PIN_CFG_RFTR_EN, 1); +++ +++ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg); ++ } ++ ++ static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, +diff --git a/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch +new file mode 100644 +index 0000000..967e36a +--- /dev/null ++++ b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch +@@ -0,0 +1,71 @@ ++From 84833056aa7dd25f5b097e31c78f2a0914c5160c Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:26 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for ++ RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++ ++ 1 file changed, 44 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -5776,6 +5776,47 @@ static void rt2800_init_bbp_3593(struct ++ rt2800_bbp_write(rt2x00dev, 103, 0xc0); ++ } ++ +++static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev) +++{ +++ rt2800_init_bbp_early(rt2x00dev); +++ +++ rt2800_bbp_write(rt2x00dev, 4, 0x50); +++ rt2800_bbp_write(rt2x00dev, 47, 0x48); +++ +++ rt2800_bbp_write(rt2x00dev, 86, 0x46); +++ rt2800_bbp_write(rt2x00dev, 88, 0x90); +++ +++ rt2800_bbp_write(rt2x00dev, 92, 0x02); +++ +++ rt2800_bbp_write(rt2x00dev, 103, 0xc0); +++ rt2800_bbp_write(rt2x00dev, 104, 0x92); +++ rt2800_bbp_write(rt2x00dev, 105, 0x34); +++ rt2800_bbp_write(rt2x00dev, 106, 0x12); +++ rt2800_bbp_write(rt2x00dev, 120, 0x50); +++ rt2800_bbp_write(rt2x00dev, 137, 0x0f); +++ rt2800_bbp_write(rt2x00dev, 163, 0x9d); +++ +++ /* Set ITxBF timeout to 0x9C40=1000msec */ +++ rt2800_bbp_write(rt2x00dev, 179, 0x02); +++ rt2800_bbp_write(rt2x00dev, 180, 0x00); +++ rt2800_bbp_write(rt2x00dev, 182, 0x40); +++ rt2800_bbp_write(rt2x00dev, 180, 0x01); +++ rt2800_bbp_write(rt2x00dev, 182, 0x9c); +++ +++ rt2800_bbp_write(rt2x00dev, 179, 0x00); +++ +++ /* Reprogram the inband interface to put right values in RXWI */ +++ rt2800_bbp_write(rt2x00dev, 142, 0x04); +++ rt2800_bbp_write(rt2x00dev, 143, 0x3b); +++ rt2800_bbp_write(rt2x00dev, 142, 0x06); +++ rt2800_bbp_write(rt2x00dev, 143, 0xa0); +++ rt2800_bbp_write(rt2x00dev, 142, 0x07); +++ rt2800_bbp_write(rt2x00dev, 143, 0xa1); +++ rt2800_bbp_write(rt2x00dev, 142, 0x08); +++ rt2800_bbp_write(rt2x00dev, 143, 0xa2); +++ rt2800_bbp_write(rt2x00dev, 148, 0xc8); +++} +++ ++ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) ++ { ++ int ant, div_mode; ++@@ -5994,6 +6035,9 @@ static void rt2800_init_bbp(struct rt2x0 ++ case RT3593: ++ rt2800_init_bbp_3593(rt2x00dev); ++ return; +++ case RT3883: +++ rt2800_init_bbp_3883(rt2x00dev); +++ return; ++ case RT5390: ++ case RT5392: ++ rt2800_init_bbp_53xx(rt2x00dev); +diff --git a/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch +new file mode 100644 +index 0000000..c568b99 +--- /dev/null ++++ b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch +@@ -0,0 +1,178 @@ ++From 99c659cf345640fd0f733cbcaf4583cc2c868ec0 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 29 Apr 2013 13:21:48 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800.h | 1 + ++ drivers/net/wireless/rt2x00/rt2800lib.c | 141 +++++++++++++++++++++++++++++++ ++ 2 files changed, 142 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -2169,6 +2169,7 @@ struct mac_iveiv_entry { ++ /* ++ * RFCSR 2: ++ */ +++#define RFCSR2_RESCAL_BP FIELD8(0x40) ++ #define RFCSR2_RESCAL_EN FIELD8(0x80) ++ ++ /* ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -6811,6 +6811,144 @@ static void rt2800_init_rfcsr_3593(struc ++ /* TODO: enable stream mode support */ ++ } ++ +++static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev) +++{ +++ u8 rfcsr; +++ +++ /* TODO: get the actual ECO value from the SoC */ +++ const unsigned int eco = 5; +++ +++ rt2800_rf_init_calibration(rt2x00dev, 2); +++ +++ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0); +++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03); +++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50); +++ rt2800_rfcsr_write(rt2x00dev, 3, 0x20); +++ rt2800_rfcsr_write(rt2x00dev, 4, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 5, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); +++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b); +++ rt2800_rfcsr_write(rt2x00dev, 9, 0x08); +++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); +++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48); +++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a); +++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12); +++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +++ +++ /* RFCSR 17 will be initialized later based on the +++ * frequency offset stored in the EEPROM +++ */ +++ +++ rt2800_rfcsr_write(rt2x00dev, 18, 0x40); +++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +++ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0); +++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 29, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20); +++ rt2800_rfcsr_write(rt2x00dev, 35, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 37, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 38, 0x86); +++ rt2800_rfcsr_write(rt2x00dev, 39, 0x23); +++ rt2800_rfcsr_write(rt2x00dev, 40, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 41, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 42, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 43, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93); +++ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); +++ rt2800_rfcsr_write(rt2x00dev, 46, 0x60); +++ rt2800_rfcsr_write(rt2x00dev, 47, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 48, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); +++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86); +++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51); +++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05); +++ rt2800_rfcsr_write(rt2x00dev, 53, 0x76); +++ rt2800_rfcsr_write(rt2x00dev, 54, 0x76); +++ rt2800_rfcsr_write(rt2x00dev, 55, 0x76); +++ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); +++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e); +++ rt2800_rfcsr_write(rt2x00dev, 58, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 59, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 60, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 61, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00); +++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00); +++ +++ /* TODO: rx filter calibration? */ +++ +++ rt2800_bbp_write(rt2x00dev, 137, 0x0f); +++ +++ rt2800_bbp_write(rt2x00dev, 163, 0x9d); +++ +++ rt2800_bbp_write(rt2x00dev, 105, 0x05); +++ +++ rt2800_bbp_write(rt2x00dev, 179, 0x02); +++ rt2800_bbp_write(rt2x00dev, 180, 0x00); +++ rt2800_bbp_write(rt2x00dev, 182, 0x40); +++ rt2800_bbp_write(rt2x00dev, 180, 0x01); +++ rt2800_bbp_write(rt2x00dev, 182, 0x9c); +++ +++ rt2800_bbp_write(rt2x00dev, 179, 0x00); +++ +++ rt2800_bbp_write(rt2x00dev, 142, 0x04); +++ rt2800_bbp_write(rt2x00dev, 143, 0x3b); +++ rt2800_bbp_write(rt2x00dev, 142, 0x06); +++ rt2800_bbp_write(rt2x00dev, 143, 0xa0); +++ rt2800_bbp_write(rt2x00dev, 142, 0x07); +++ rt2800_bbp_write(rt2x00dev, 143, 0xa1); +++ rt2800_bbp_write(rt2x00dev, 142, 0x08); +++ rt2800_bbp_write(rt2x00dev, 143, 0xa2); +++ rt2800_bbp_write(rt2x00dev, 148, 0xc8); +++ +++ if (eco == 5) { +++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8); +++ rt2800_rfcsr_write(rt2x00dev, 33, 0x32); +++ } +++ +++ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); +++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0); +++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); +++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); +++ msleep(1); +++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0); +++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); +++ +++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +++ +++ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +++ rfcsr |= 0xc0; +++ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); +++ +++ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); +++ rfcsr |= 0x20; +++ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); +++ +++ rt2800_rfcsr_read(rt2x00dev, 46, &rfcsr); +++ rfcsr |= 0x20; +++ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr); +++ +++ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr); +++ rfcsr &= ~0xee; +++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); +++} +++ ++ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) ++ { ++ rt2800_rf_init_calibration(rt2x00dev, 2); ++@@ -7042,6 +7180,9 @@ static void rt2800_init_rfcsr(struct rt2 ++ case RT3390: ++ rt2800_init_rfcsr_3390(rt2x00dev); ++ break; +++ case RT3883: +++ rt2800_init_rfcsr_3883(rt2x00dev); +++ break; ++ case RT3572: ++ rt2800_init_rfcsr_3572(rt2x00dev); ++ break; +diff --git a/package/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch b/package/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch +new file mode 100644 +index 0000000..57af961 +--- /dev/null ++++ b/package/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch +@@ -0,0 +1,22 @@ ++From 86022438ffeb1b87dfcd018bf477fdbb43076691 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Wed, 8 May 2013 19:35:33 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: use the extended EEPROM map for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -342,7 +342,8 @@ static unsigned int rt2800_eeprom_word_i ++ wiphy_name(rt2x00dev->hw->wiphy), word)) ++ return 0; ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ map = rt2800_eeprom_map_ext; ++ else ++ map = rt2800_eeprom_map; +diff --git a/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch +new file mode 100644 +index 0000000..47eece0 +--- /dev/null ++++ b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch +@@ -0,0 +1,21 @@ ++From 4cf5403f02fa65dc2207f61d223cffa9ae50e907 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Thu, 1 Aug 2013 14:48:21 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: force rf type to RF3853 on RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++ ++ 1 file changed, 2 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7579,6 +7579,8 @@ static int rt2800_init_eeprom(struct rt2 ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) ++ rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +++ else if (rt2x00_rt(rt2x00dev, RT3883)) +++ rf = RF3853; ++ else ++ rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); ++ +diff --git a/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch +new file mode 100644 +index 0000000..d9cbb33 +--- /dev/null ++++ b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch +@@ -0,0 +1,136 @@ ++From 269f19c848a2380db03a3f207cafb88e28d71c53 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:28 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 72 +++++++++++++++++++++++++++++-- ++ 1 file changed, 69 insertions(+), 3 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -3385,6 +3385,36 @@ static char rt2800_txpower_to_dev(struct ++ return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); ++ } ++ +++static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev, +++ struct rf_channel *rf) +++{ +++ u8 bbp; +++ +++ bbp = (rf->channel > 14) ? 0x48 : 0x38; +++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp); +++ +++ rt2800_bbp_write(rt2x00dev, 69, 0x12); +++ +++ if (rf->channel <= 14) { +++ rt2800_bbp_write(rt2x00dev, 70, 0x0a); +++ } else { +++ /* Disable CCK packet detection */ +++ rt2800_bbp_write(rt2x00dev, 70, 0x00); +++ } +++ +++ rt2800_bbp_write(rt2x00dev, 73, 0x10); +++ +++ if (rf->channel > 14) { +++ rt2800_bbp_write(rt2x00dev, 62, 0x1d); +++ rt2800_bbp_write(rt2x00dev, 63, 0x1d); +++ rt2800_bbp_write(rt2x00dev, 64, 0x1d); +++ } else { +++ rt2800_bbp_write(rt2x00dev, 62, 0x2d); +++ rt2800_bbp_write(rt2x00dev, 63, 0x2d); +++ rt2800_bbp_write(rt2x00dev, 64, 0x2d); +++ } +++} +++ ++ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_conf *conf, ++ struct rf_channel *rf, ++@@ -3403,6 +3433,12 @@ static void rt2800_config_channel(struct ++ rt2800_txpower_to_dev(rt2x00dev, rf->channel, ++ info->default_power3); ++ +++ switch (rt2x00dev->chip.rt) { +++ case RT3883: +++ rt3883_bbp_adjust(rt2x00dev, rf); +++ break; +++ } +++ ++ switch (rt2x00dev->chip.rf) { ++ case RF2020: ++ case RF3020: ++@@ -3484,6 +3520,15 @@ static void rt2800_config_channel(struct ++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 77, 0x98); +++ } else if (rt2x00_rt(rt2x00dev, RT3883)) { +++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +++ +++ if (rt2x00dev->default_ant.rx_chain_num > 1) +++ rt2800_bbp_write(rt2x00dev, 86, 0x46); +++ else +++ rt2800_bbp_write(rt2x00dev, 86, 0); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); ++@@ -3496,6 +3541,7 @@ static void rt2800_config_channel(struct ++ !rt2x00_rt(rt2x00dev, RT5392)) { ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt2800_bbp_write(rt2x00dev, 82, 0x62); +++ rt2800_bbp_write(rt2x00dev, 82, 0x62); ++ rt2800_bbp_write(rt2x00dev, 75, 0x46); ++ } else { ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++@@ -3504,19 +3550,22 @@ static void rt2800_config_channel(struct ++ rt2800_bbp_write(rt2x00dev, 82, 0x84); ++ rt2800_bbp_write(rt2x00dev, 75, 0x50); ++ } ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ rt2800_bbp_write(rt2x00dev, 83, 0x8a); ++ } ++ ++ } else { ++ if (rt2x00_rt(rt2x00dev, RT3572)) ++ rt2800_bbp_write(rt2x00dev, 82, 0x94); ++- else if (rt2x00_rt(rt2x00dev, RT3593)) +++ else if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ rt2800_bbp_write(rt2x00dev, 82, 0x82); ++ else ++ rt2800_bbp_write(rt2x00dev, 82, 0xf2); ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ rt2800_bbp_write(rt2x00dev, 83, 0x9a); ++ ++ if (rt2x00_has_cap_external_lna_a(rt2x00dev)) ++@@ -3638,6 +3687,23 @@ static void rt2800_config_channel(struct ++ ++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); ++ +++ usleep_range(1000, 1500); +++ } +++ +++ if (rt2x00_rt(rt2x00dev, RT3883)) { +++ if (!conf_is_ht40(conf)) +++ rt2800_bbp_write(rt2x00dev, 105, 0x34); +++ else +++ rt2800_bbp_write(rt2x00dev, 105, 0x04); +++ +++ /* AGC init */ +++ if (rf->channel <= 14) +++ reg = 0x2e + rt2x00dev->lna_gain; +++ else +++ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3); +++ +++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); +++ ++ usleep_range(1000, 1500); ++ } ++ +diff --git a/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch +new file mode 100644 +index 0000000..c927e45 +--- /dev/null ++++ b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch +@@ -0,0 +1,30 @@ ++From e37d93abaabe3ab72b0332a18092acc162307274 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 30 Sep 2013 13:57:26 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix txpower_to_dev function for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++-- ++ 1 file changed, 4 insertions(+), 2 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -3372,13 +3372,15 @@ static char rt2800_txpower_to_dev(struct ++ unsigned int channel, ++ char txpower) ++ { ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); ++ ++ if (channel <= 14) ++ return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ return clamp_t(char, txpower, MIN_A_TXPOWER_3593, ++ MAX_A_TXPOWER_3593); ++ else +diff --git a/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch +new file mode 100644 +index 0000000..df826e5 +--- /dev/null ++++ b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch +@@ -0,0 +1,23 @@ ++From c4d79e344bd580d85821390d49f92dced7d8e125 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:29 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: use correct txpower calculation function ++ for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -4582,7 +4582,8 @@ static void rt2800_config_txpower(struct ++ struct ieee80211_channel *chan, ++ int power_level) ++ { ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); ++ else ++ rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level); +diff --git a/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch +new file mode 100644 +index 0000000..8a43df2 +--- /dev/null ++++ b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch +@@ -0,0 +1,33 @@ ++From caea0671cd8fd9ade4f5969cbe0ee545e94ae105 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sat, 24 Aug 2013 11:49:55 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: hardcode txmixer gain values to zero for ++ RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++-- ++ 1 file changed, 4 insertions(+), 2 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7461,7 +7461,8 @@ static u8 rt2800_get_txmixer_gain_24g(st ++ { ++ u16 word; ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ return 0; ++ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); ++@@ -7475,7 +7476,8 @@ static u8 rt2800_get_txmixer_gain_5g(str ++ { ++ u16 word; ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ return 0; ++ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); +diff --git a/package/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch b/package/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch +new file mode 100644 +index 0000000..53435aa +--- /dev/null ++++ b/package/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch +@@ -0,0 +1,20 @@ ++From 11c40fb47c4a4dd6ad060c2ae127ced89ffb9fe1 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Thu, 18 Apr 2013 14:33:33 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: use correct [RT]XWI size for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -558,6 +558,7 @@ void rt2800_get_txwi_rxwi_size(struct rt ++ { ++ switch (rt2x00dev->chip.rt) { ++ case RT3593: +++ case RT3883: ++ *txwi_size = TXWI_DESC_SIZE_4WORDS; ++ *rxwi_size = RXWI_DESC_SIZE_5WORDS; ++ break; +diff --git a/package/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch b/package/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch +new file mode 100644 +index 0000000..08f3f88 +--- /dev/null ++++ b/package/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch +@@ -0,0 +1,22 @@ ++From b403bdfa00665ce6b53583bdb837ffad0b91c09f Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:29 +0100 ++Subject: [PATCH] rt2x00: rt2800lib: use correct beacon base for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -983,7 +983,8 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry); ++ static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, ++ unsigned int index) ++ { ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ return HW_BEACON_BASE_HIGH(index); ++ ++ return HW_BEACON_BASE(index); +diff --git a/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch +new file mode 100644 +index 0000000..cb7a0ae +--- /dev/null ++++ b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch +@@ -0,0 +1,22 @@ ++From 74b7eaf75fc6eb86292056ef705e543f9cd6086b Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 18 Aug 2013 09:57:58 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: use correct beacon count for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -8393,7 +8393,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ drv_data->hw_beacon_count = 16; ++ else ++ drv_data->hw_beacon_count = 8; +diff --git a/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch +new file mode 100644 +index 0000000..0919f90 +--- /dev/null ++++ b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch +@@ -0,0 +1,22 @@ ++From fa5ad9c025610c22048add2f0ad03f62b6ca1e74 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 30 Sep 2013 16:53:33 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -1917,7 +1917,8 @@ void rt2800_config_ant(struct rt2x00_dev ++ rt2800_bbp_write(rt2x00dev, 3, r3); ++ rt2800_bbp_write(rt2x00dev, 1, r1); ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) { +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) { ++ if (ant->rx_chain_num == 1) ++ rt2800_bbp_write(rt2x00dev, 86, 0x00); ++ else +diff --git a/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch +new file mode 100644 +index 0000000..e38ba78 +--- /dev/null ++++ b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch +@@ -0,0 +1,32 @@ ++From 6d668fef3a1baa60bdd715ee062ddb6333d2647c Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 30 Sep 2013 16:58:23 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++-- ++ 1 file changed, 4 insertions(+), 2 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -1940,7 +1940,8 @@ static void rt2800_config_lna_gain(struc ++ rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); ++ } else if (libconf->rf.channel <= 128) { ++- if (rt2x00_rt(rt2x00dev, RT3593)) { +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, ++ EEPROM_EXT_LNA2_A1); ++@@ -1950,7 +1951,8 @@ static void rt2800_config_lna_gain(struc ++ EEPROM_RSSI_BG2_LNA_A1); ++ } ++ } else { ++- if (rt2x00_rt(rt2x00dev, RT3593)) { +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, ++ EEPROM_EXT_LNA2_A2); +diff --git a/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch +new file mode 100644 +index 0000000..4684599 +--- /dev/null ++++ b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch +@@ -0,0 +1,44 @@ ++From c49b2d829aa1c816a46a577cdec6d2ff14d9f06e Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Tue, 1 Oct 2013 15:40:08 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++++-- ++ 1 file changed, 9 insertions(+), 2 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -4781,7 +4781,8 @@ static u8 rt2800_get_default_vgc(struct ++ else ++ vgc = 0x2e + rt2x00dev->lna_gain; ++ } else { /* 5GHZ band */ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; ++ else if (rt2x00_rt(rt2x00dev, RT5592)) ++ vgc = 0x24 + (2 * rt2x00dev->lna_gain); ++@@ -4801,7 +4802,8 @@ static inline void rt2800_set_vgc(struct ++ { ++ if (qual->vgc_level != vgc_level) { ++ if (rt2x00_rt(rt2x00dev, RT3572) || ++- rt2x00_rt(rt2x00dev, RT3593)) { +++ rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, ++ vgc_level); ++ } else if (rt2x00_rt(rt2x00dev, RT5592)) { ++@@ -4848,6 +4850,11 @@ void rt2800_link_tuner(struct rt2x00_dev ++ } ++ break; ++ +++ case RT3883: +++ if (qual->rssi > -65) +++ vgc += 0x10; +++ break; +++ ++ case RT5592: ++ if (qual->rssi > -65) ++ vgc += 0x20; +diff --git a/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch +new file mode 100644 +index 0000000..bc1548d +--- /dev/null ++++ b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch +@@ -0,0 +1,42 @@ ++From 1616650aea676541d4dc8adc6f4219856d193c8b Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Tue, 1 Oct 2013 17:27:57 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 9 ++++++--- ++ 1 file changed, 6 insertions(+), 3 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -7598,7 +7598,8 @@ static int rt2800_validate_eeprom(struct ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); ++ if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) ++ rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); ++- if (!rt2x00_rt(rt2x00dev, RT3593)) { +++ if (!rt2x00_rt(rt2x00dev, RT3593) && +++ !rt2x00_rt(rt2x00dev, RT3883)) { ++ if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || ++ rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) ++ rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, ++@@ -7618,7 +7619,8 @@ static int rt2800_validate_eeprom(struct ++ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); ++ if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) ++ rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); ++- if (!rt2x00_rt(rt2x00dev, RT3593)) { +++ if (!rt2x00_rt(rt2x00dev, RT3593) && +++ !rt2x00_rt(rt2x00dev, RT3883)) { ++ if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || ++ rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) ++ rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, ++@@ -7626,7 +7628,8 @@ static int rt2800_validate_eeprom(struct ++ } ++ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) { +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word); ++ if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 || ++ rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff) +diff --git a/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch +new file mode 100644 +index 0000000..d6295f4 +--- /dev/null ++++ b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch +@@ -0,0 +1,22 @@ ++From e3871034a0e7c8a95152dc3eafbcc4535398cbdc Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Wed, 2 Oct 2013 10:11:59 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 +++ ++ 1 file changed, 3 insertions(+) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -3959,6 +3959,9 @@ static u8 rt2800_compensate_txpower(stru ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return min_t(u8, txpower, 0xc); ++ +++ if (rt2x00_rt(rt2x00dev, RT3883)) +++ return min_t(u8, txpower, 0xf); +++ ++ if (rt2x00_has_cap_power_limit(rt2x00dev)) { ++ /* ++ * Check if eirp txpower exceed txpower_limit. +diff --git a/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch +new file mode 100644 +index 0000000..c5f226a +--- /dev/null ++++ b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch +@@ -0,0 +1,23 @@ ++From f6734ec72da936989a8ce4186b3ede28fbc47836 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 18 Aug 2013 21:57:34 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: enable RT2800_HAS_HIGH_SHARED_MEM for ++ RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -8406,7 +8406,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ if (retval) ++ return retval; ++ ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++ ++ if (rt2x00_rt(rt2x00dev, RT3593) || +diff --git a/package/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch b/package/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch +new file mode 100644 +index 0000000..dc06e6a +--- /dev/null ++++ b/package/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch +@@ -0,0 +1,22 @@ ++From f1acfc2f397e86548ae1b479c198d4bef57050f6 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 29 Sep 2013 18:10:34 +0200 ++Subject: [PATCH] rt2x00: rt2800lib: use high memory for beacons on RT3883 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800lib.c +++++ b/drivers/net/wireless/rt2x00/rt2800lib.c ++@@ -97,7 +97,8 @@ static inline void rt2800_shared_mem_sel ++ ++ static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev) ++ { ++- if (rt2x00_rt(rt2x00dev, RT3593)) +++ if (rt2x00_rt(rt2x00dev, RT3593) || +++ rt2x00_rt(rt2x00dev, RT3883)) ++ return true; ++ ++ return false; +diff --git a/package/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch b/package/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch +new file mode 100644 +index 0000000..79334dd +--- /dev/null ++++ b/package/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch +@@ -0,0 +1,136 @@ ++From 5e67d4f8a46d19748b501c2ef86de3f50d3cfd51 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Sun, 24 Mar 2013 19:26:27 +0100 ++Subject: [PATCH] rt2x00: rt2800mmio: add a workaround for spurious ++ TX_FIFO_STATUS interrupts ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/wireless/rt2x00/rt2800mmio.c | 72 +++++++++++++++++++++++++----- ++ drivers/net/wireless/rt2x00/rt2x00.h | 5 +++ ++ 2 files changed, 65 insertions(+), 12 deletions(-) ++ ++--- a/drivers/net/wireless/rt2x00/rt2800mmio.c +++++ b/drivers/net/wireless/rt2x00/rt2800mmio.c ++@@ -415,9 +415,9 @@ void rt2800mmio_autowake_tasklet(unsigne ++ } ++ EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet); ++ ++-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) +++static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev, +++ u32 status) ++ { ++- u32 status; ++ int i; ++ ++ /* ++@@ -438,29 +438,77 @@ static void rt2800mmio_txstatus_interrup ++ * Since we have only one producer and one consumer we don't ++ * need to lock the kfifo. ++ */ ++- for (i = 0; i < rt2x00dev->tx->limit; i++) { ++- rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); ++- ++- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) ++- break; ++- +++ i = 0; +++ do { ++ if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) { ++- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); +++ rt2x00_warn(rt2x00dev, +++ "TX status FIFO overrun, drop TX status report\n"); ++ break; ++ } ++- } +++ +++ if (++i >= rt2x00dev->tx->limit) +++ break; +++ +++ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); +++ } while (rt2x00_get_field32(status, TX_STA_FIFO_VALID)); ++ ++ /* Schedule the tasklet for processing the tx status. */ ++ tasklet_schedule(&rt2x00dev->txstatus_tasklet); ++ } ++ +++#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES 4 +++ +++static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev, +++ u32 txstatus) +++{ +++ if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) { +++ rt2x00dev->txstatus_irq_retries = 0; +++ return false; +++ } +++ +++ rt2x00dev->txstatus_irq_retries++; +++ +++ /* Ensure that we don't go into an infinite IRQ loop. */ +++ if (rt2x00dev->txstatus_irq_retries >= +++ RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) { +++ rt2x00_warn(rt2x00dev, +++ "%u spurious TX_FIFO_STATUS interrupt(s)\n", +++ rt2x00dev->txstatus_irq_retries); +++ rt2x00dev->txstatus_irq_retries = 0; +++ return false; +++ } +++ +++ return true; +++} +++ ++ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance) ++ { ++ struct rt2x00_dev *rt2x00dev = dev_instance; ++ u32 reg, mask; +++ u32 txstatus = 0; ++ ++- /* Read status and ACK all interrupts */ +++ /* Read status */ ++ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +++ +++ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { +++ /* Due to unknown reason the hardware generates a +++ * TX_FIFO_STATUS interrupt before the TX_STA_FIFO +++ * register contain valid data. Read the TX status +++ * here to see if we have to process the actual +++ * request. +++ */ +++ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus); +++ if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) { +++ /* Remove the TX_FIFO_STATUS bit so it won't be +++ * processed in this turn. The hardware will +++ * generate another IRQ for us. +++ */ +++ rt2x00_set_field32(®, +++ INT_SOURCE_CSR_TX_FIFO_STATUS, 0); +++ } +++ } +++ +++ /* ACK interrupts */ ++ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); ++ ++ if (!reg) ++@@ -477,7 +525,7 @@ irqreturn_t rt2800mmio_interrupt(int irq ++ mask = ~reg; ++ ++ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { ++- rt2800mmio_txstatus_interrupt(rt2x00dev); +++ rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus); ++ /* ++ * Never disable the TX_FIFO_STATUS interrupt. ++ */ ++--- a/drivers/net/wireless/rt2x00/rt2x00.h +++++ b/drivers/net/wireless/rt2x00/rt2x00.h ++@@ -986,6 +986,11 @@ struct rt2x00_dev { ++ int rf_channel; ++ ++ /* +++ * Counter for tx status irq retries (rt2800pci). +++ */ +++ unsigned int txstatus_irq_retries; +++ +++ /* ++ * Protect the interrupt mask register. ++ */ ++ spinlock_t irqmask_lock; +diff --git a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +index 2bbc6f1..c7d71e2 100644 +--- a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch ++++ b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +@@ -1,6 +1,6 @@ + --- a/.local-symbols + +++ b/.local-symbols +-@@ -279,6 +279,7 @@ RT2X00_LIB_FIRMWARE= ++@@ -280,6 +280,7 @@ RT2X00_LIB_FIRMWARE= + RT2X00_LIB_CRYPTO= + RT2X00_LIB_LEDS= + RT2X00_LIB_DEBUGFS= +@@ -48,16 +48,16 @@ + obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o + --- a/drivers/net/wireless/rt2x00/rt2800lib.h + +++ b/drivers/net/wireless/rt2x00/rt2800lib.h +-@@ -20,6 +20,8 @@ +- #ifndef RT2800LIB_H +- #define RT2800LIB_H ++@@ -43,6 +43,8 @@ struct rt2800_drv_data { ++ } shmem_lock; ++ }; + + +#include "rt2800.h" + + + struct rt2800_ops { + void (*register_read)(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value); +-@@ -119,6 +121,15 @@ static inline int rt2800_read_eeprom(str ++@@ -176,6 +178,15 @@ static inline int rt2800_read_eeprom(str + { + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + +@@ -75,7 +75,7 @@ + + --- a/drivers/net/wireless/rt2x00/rt2800soc.c + +++ b/drivers/net/wireless/rt2x00/rt2800soc.c +-@@ -95,19 +95,6 @@ static int rt2800soc_set_device_state(st ++@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st + return retval; + } + +@@ -95,7 +95,7 @@ + /* Firmware functions */ + static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) + { +-@@ -171,7 +158,6 @@ static const struct rt2800_ops rt2800soc ++@@ -178,7 +165,6 @@ static const struct rt2800_ops rt2800soc + .register_multiread = rt2x00mmio_register_multiread, + .register_multiwrite = rt2x00mmio_register_multiwrite, + .regbusy_read = rt2x00mmio_regbusy_read, +diff --git a/package/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/mac80211/patches/608-add_platform_data_mac_addr.patch +index a910cc3..1db09a3 100644 +--- a/package/mac80211/patches/608-add_platform_data_mac_addr.patch ++++ b/package/mac80211/patches/608-add_platform_data_mac_addr.patch +@@ -31,7 +31,7 @@ + { + --- a/drivers/net/wireless/rt2x00/rt2x00.h + +++ b/drivers/net/wireless/rt2x00/rt2x00.h +-@@ -1401,6 +1401,7 @@ static inline void rt2x00debug_dump_fram ++@@ -1406,6 +1406,7 @@ static inline void rt2x00debug_dump_fram + */ + u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif); +diff --git a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +index 83fbcd0..3d32ecc 100644 +--- a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch ++++ b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +@@ -1,14 +1,15 @@ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -3176,11 +3176,17 @@ static void rt2800_config_channel(struct ++@@ -3506,11 +3506,18 @@ static void rt2800_config_channel(struct + /* + * Change BBP settings + */ +-+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +-+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +-+ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + + + if (rt2x00_rt(rt2x00dev, RT3352)) { +++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +++ + rt2800_bbp_write(rt2x00dev, 27, 0x0); + rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 27, 0x20); +@@ -18,22 +19,7 @@ + } else if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rf->channel > 14) { + /* Disable CCK Packet detection on 5GHz */ +-@@ -3194,14 +3200,8 @@ static void rt2800_config_channel(struct +- else +- rt2800_bbp_write(rt2x00dev, 105, 0x34); +- +-- rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +-- rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +-- rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +- rt2800_bbp_write(rt2x00dev, 77, 0x98); +- } else { +-- rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +-- rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +-- rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +- rt2800_bbp_write(rt2x00dev, 86, 0); +- } +- +-@@ -6125,6 +6125,12 @@ static void rt2800_init_rfcsr_3290(struc ++@@ -6586,6 +6593,12 @@ static void rt2800_init_rfcsr_3290(struc + + static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) + { +@@ -46,7 +32,7 @@ + rt2800_rf_init_calibration(rt2x00dev, 30); + + rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); +-@@ -6160,15 +6166,30 @@ static void rt2800_init_rfcsr_3352(struc ++@@ -6621,15 +6634,30 @@ static void rt2800_init_rfcsr_3352(struc + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +@@ -80,7 +66,7 @@ + rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); +-@@ -6176,15 +6197,20 @@ static void rt2800_init_rfcsr_3352(struc ++@@ -6637,15 +6665,20 @@ static void rt2800_init_rfcsr_3352(struc + rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); + rt2800_rfcsr_write(rt2x00dev, 48, 0x14); + rt2800_rfcsr_write(rt2x00dev, 49, 0x00); +@@ -110,7 +96,7 @@ + rt2800_rfcsr_write(rt2x00dev, 59, 0x00); + rt2800_rfcsr_write(rt2x00dev, 60, 0x00); + rt2800_rfcsr_write(rt2x00dev, 61, 0x00); +-@@ -7051,6 +7077,7 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7666,6 +7699,7 @@ static int rt2800_init_eeprom(struct rt2 + * RT53xx: defined in "EEPROM_CHIP_ID" field + */ + if (rt2x00_rt(rt2x00dev, RT3290) || +@@ -118,7 +104,7 @@ + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +-@@ -7142,7 +7169,8 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7760,7 +7794,8 @@ static int rt2800_init_eeprom(struct rt2 + /* + * Detect if this device has Bluetooth co-existence. + */ +@@ -128,7 +114,7 @@ + __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); + + /* +-@@ -7171,6 +7199,22 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7789,6 +7824,22 @@ static int rt2800_init_eeprom(struct rt2 + EIRP_MAX_TX_POWER_LIMIT) + __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); + +@@ -153,7 +139,7 @@ + + --- a/drivers/net/wireless/rt2x00/rt2800.h + +++ b/drivers/net/wireless/rt2x00/rt2800.h +-@@ -2299,6 +2299,12 @@ struct mac_iveiv_entry { ++@@ -2333,6 +2333,12 @@ struct mac_iveiv_entry { + #define RFCSR36_RF_BS FIELD8(0x80) + + /* +@@ -166,7 +152,7 @@ + * RFCSR 38: + */ + #define RFCSR38_RX_LO1_EN FIELD8(0x20) +-@@ -2310,6 +2316,18 @@ struct mac_iveiv_entry { ++@@ -2344,6 +2350,18 @@ struct mac_iveiv_entry { + #define RFCSR39_RX_LO2_EN FIELD8(0x80) + + /* +@@ -185,7 +171,7 @@ + * RFCSR 49: + */ + #define RFCSR49_TX FIELD8(0x3f) +-@@ -2322,6 +2340,8 @@ struct mac_iveiv_entry { ++@@ -2356,6 +2374,8 @@ struct mac_iveiv_entry { + * RFCSR 50: + */ + #define RFCSR50_TX FIELD8(0x3f) +@@ -194,7 +180,7 @@ + #define RFCSR50_EP FIELD8(0xc0) + /* bits for RT3593 */ + #define RFCSR50_TX_LO1_EN FIELD8(0x20) +-@@ -2469,6 +2489,8 @@ enum rt2800_eeprom_word { ++@@ -2503,6 +2523,8 @@ enum rt2800_eeprom_word { + * INTERNAL_TX_ALC: 0: disable, 1: enable + * BT_COEXIST: 0: disable, 1: enable + * DAC_TEST: 0: disable, 1: enable +@@ -203,7 +189,7 @@ + */ + #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) + #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) +-@@ -2485,6 +2507,8 @@ enum rt2800_eeprom_word { ++@@ -2519,6 +2541,8 @@ enum rt2800_eeprom_word { + #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) + #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) + #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) +diff --git a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +index 478a0f2..c69344c 100644 +--- a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch ++++ b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7491,6 +7491,27 @@ static const struct rf_channel rf_vals_5 ++@@ -8176,6 +8176,27 @@ static const struct rf_channel rf_vals_5 + {196, 83, 0, 12, 1}, + }; + +@@ -28,7 +28,7 @@ + static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + { + struct hw_mode_spec *spec = &rt2x00dev->spec; +-@@ -7579,7 +7600,10 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8263,7 +8284,10 @@ static int rt2800_probe_hw_mode(struct r + case RF5390: + case RF5392: + spec->num_channels = 14; +@@ -40,7 +40,7 @@ + break; + + case RF3052: +-@@ -7755,6 +7779,19 @@ static int rt2800_probe_rt(struct rt2x00 ++@@ -8446,6 +8470,19 @@ static int rt2800_probe_rt(struct rt2x00 + return 0; + } + +@@ -59,8 +59,8 @@ + + + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) + { +- int retval; +-@@ -7784,6 +7821,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++@@ -8488,6 +8525,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + + /* +diff --git a/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +index f6b4808..119e95c 100644 +--- a/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch ++++ b/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +@@ -13,7 +13,7 @@ Signed-off-by: John Crispin + + --- a/drivers/net/wireless/rt2x00/rt2800soc.c + +++ b/drivers/net/wireless/rt2x00/rt2800soc.c +-@@ -227,11 +227,18 @@ static int rt2800soc_probe(struct platfo ++@@ -237,11 +237,18 @@ static int rt2800soc_probe(struct platfo + return rt2x00soc_probe(pdev, &rt2800soc_ops); + } + +diff --git a/package/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/mac80211/patches/616-rt2x00-support-rt5350.patch +index 3bafa16..2cc136c 100644 +--- a/package/mac80211/patches/616-rt2x00-support-rt5350.patch ++++ b/package/mac80211/patches/616-rt2x00-support-rt5350.patch +@@ -1,16 +1,16 @@ + --- a/drivers/net/wireless/rt2x00/rt2800.h + +++ b/drivers/net/wireless/rt2x00/rt2800.h +-@@ -71,6 +71,7 @@ +- #define RF5592 0x000f ++@@ -73,6 +73,7 @@ + #define RF3070 0x3070 + #define RF3290 0x3290 ++ #define RF3853 0x3853 + +#define RF5350 0x5350 + #define RF5360 0x5360 + #define RF5370 0x5370 + #define RF5372 0x5372 + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -2704,6 +2704,13 @@ static void rt2800_config_channel_rf53xx ++@@ -2994,6 +2994,13 @@ static void rt2800_config_channel_rf53xx + + rt2800_rfcsr_write(rt2x00dev, 59, + r59_non_bt[idx]); +@@ -24,15 +24,15 @@ + } + } + } +-@@ -3141,6 +3148,7 @@ static void rt2800_config_channel(struct +- rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); ++@@ -3472,6 +3479,7 @@ static void rt2800_config_channel(struct ++ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info); + break; + case RF3070: + + case RF5350: + case RF5360: + case RF5370: + case RF5372: +-@@ -3158,6 +3166,7 @@ static void rt2800_config_channel(struct ++@@ -3489,6 +3497,7 @@ static void rt2800_config_channel(struct + if (rt2x00_rf(rt2x00dev, RF3070) || + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || +@@ -40,7 +40,7 @@ + rt2x00_rf(rt2x00dev, RF5360) || + rt2x00_rf(rt2x00dev, RF5370) || + rt2x00_rf(rt2x00dev, RF5372) || +-@@ -3398,7 +3407,8 @@ static void rt2800_config_channel(struct ++@@ -3766,7 +3775,8 @@ static void rt2800_config_channel(struct + /* + * Clear update flag + */ +@@ -50,15 +50,15 @@ + rt2800_bbp_read(rt2x00dev, 49, &bbp); + rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); + rt2800_bbp_write(rt2x00dev, 49, bbp); +-@@ -4272,6 +4282,7 @@ void rt2800_vco_calibration(struct rt2x0 +- case RF3053: ++@@ -4645,6 +4655,7 @@ void rt2800_vco_calibration(struct rt2x0 + case RF3070: + case RF3290: ++ case RF3853: + + case RF5350: + case RF5360: + case RF5370: + case RF5372: +-@@ -4668,6 +4679,8 @@ static int rt2800_init_registers(struct ++@@ -5079,6 +5090,8 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +@@ -67,7 +67,7 @@ + } else { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +-@@ -5309,9 +5322,13 @@ static void rt2800_init_bbp_3352(struct ++@@ -5734,9 +5747,13 @@ static void rt2800_init_bbp_3352(struct + + rt2800_bbp_write(rt2x00dev, 82, 0x62); + +@@ -84,7 +84,7 @@ + + rt2800_bbp_write(rt2x00dev, 86, 0x38); + +-@@ -5325,9 +5342,13 @@ static void rt2800_init_bbp_3352(struct ++@@ -5750,9 +5767,13 @@ static void rt2800_init_bbp_3352(struct + + rt2800_bbp_write(rt2x00dev, 104, 0x92); + +@@ -101,7 +101,7 @@ + + rt2800_bbp_write(rt2x00dev, 120, 0x50); + +-@@ -5352,6 +5373,13 @@ static void rt2800_init_bbp_3352(struct ++@@ -5777,6 +5798,13 @@ static void rt2800_init_bbp_3352(struct + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + + rt2800_bbp_write(rt2x00dev, 148, 0xc8); +@@ -115,7 +115,7 @@ + } + + static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) +-@@ -5652,6 +5680,7 @@ static void rt2800_init_bbp(struct rt2x0 ++@@ -6118,6 +6146,7 @@ static void rt2800_init_bbp(struct rt2x0 + rt2800_init_bbp_3290(rt2x00dev); + break; + case RT3352: +@@ -123,8 +123,8 @@ + rt2800_init_bbp_3352(rt2x00dev); + break; + case RT3390: +-@@ -6462,6 +6491,76 @@ static void rt2800_init_rfcsr_3593(struc +- /* TODO: enable stream mode support */ ++@@ -7069,6 +7098,76 @@ static void rt2800_init_rfcsr_3883(struc ++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); + } + + +static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev) +@@ -200,7 +200,7 @@ + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) + { + rt2800_rf_init_calibration(rt2x00dev, 2); +-@@ -6699,6 +6798,9 @@ static void rt2800_init_rfcsr(struct rt2 ++@@ -7309,6 +7408,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3593: + rt2800_init_rfcsr_3593(rt2x00dev); + break; +@@ -210,7 +210,7 @@ + case RT5390: + rt2800_init_rfcsr_5390(rt2x00dev); + break; +-@@ -6948,6 +7050,12 @@ static int rt2800_validate_eeprom(struct ++@@ -7568,6 +7670,12 @@ static int rt2800_validate_eeprom(struct + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); +@@ -223,24 +223,24 @@ + } else if (rt2x00_rt(rt2x00dev, RT2860) || + rt2x00_rt(rt2x00dev, RT2872)) { + /* +-@@ -7081,6 +7189,8 @@ static int rt2800_init_eeprom(struct rt2 +- rt2x00_rt(rt2x00dev, RT5390) || +- rt2x00_rt(rt2x00dev, RT5392)) ++@@ -7706,6 +7814,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); ++ else if (rt2x00_rt(rt2x00dev, RT3883)) ++ rf = RF3853; + + else if (rt2x00_rt(rt2x00dev, RT5350)) + + rf = RF5350; + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + +-@@ -7099,6 +7209,7 @@ static int rt2800_init_eeprom(struct rt2 +- case RF3290: ++@@ -7725,6 +7835,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF3320: + case RF3322: ++ case RF3853: + + case RF5350: + case RF5360: + case RF5370: + case RF5372: +-@@ -7594,6 +7705,7 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8279,6 +8390,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3290: + case RF3320: + case RF3322: +@@ -248,18 +248,18 @@ + case RF5360: + case RF5370: + case RF5372: +-@@ -7726,6 +7838,7 @@ static int rt2800_probe_hw_mode(struct r +- case RF3053: ++@@ -8417,6 +8529,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3070: + case RF3290: ++ case RF3853: + + case RF5350: + case RF5360: + case RF5370: + case RF5372: +-@@ -7764,6 +7877,7 @@ static int rt2800_probe_rt(struct rt2x00 +- case RT3390: ++@@ -8456,6 +8569,7 @@ static int rt2800_probe_rt(struct rt2x00 + case RT3572: + case RT3593: ++ case RT3883: + + case RT5350: + case RT5390: + case RT5392: +diff --git a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch +index f9186d8..fc56847 100644 +--- a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch ++++ b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch +@@ -8,7 +8,7 @@ + + #include "rt2x00.h" + #include "rt2800lib.h" +-@@ -7298,6 +7299,17 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7924,6 +7925,17 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + +diff --git a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +index 5e67344..a33c01f 100644 +--- a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch ++++ b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +@@ -1,15 +1,11 @@ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7186,10 +7186,11 @@ static int rt2800_init_eeprom(struct rt2 +- * RT53xx: defined in "EEPROM_CHIP_ID" field +- */ +- if (rt2x00_rt(rt2x00dev, RT3290) || +-- rt2x00_rt(rt2x00dev, RT3352) || ++@@ -7813,6 +7813,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + + else if (rt2x00_rt(rt2x00dev, RT3352)) + + rf = RF3322; ++ else if (rt2x00_rt(rt2x00dev, RT3883)) ++ rf = RF3853; + else if (rt2x00_rt(rt2x00dev, RT5350)) +- rf = RF5350; +- else +diff --git a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch +index 484c075..752fb0e 100644 +--- a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch ++++ b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/mwl8k.c + +++ b/drivers/net/wireless/mwl8k.c +-@@ -5529,6 +5529,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") ++@@ -5714,6 +5714,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") + MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); + + static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { +diff --git a/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch b/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch +deleted file mode 100644 +index a8af257..0000000 +--- a/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch ++++ /dev/null +@@ -1,109 +0,0 @@ +-Move the wl1251 part of the wl12xx platform data structure into a new +-structure specifically for wl1251. Change the platform data built-in +-block and board files accordingly. +- +-Cc: Tony Lindgren +-Signed-off-by: Luciano Coelho +-Acked-by: Tony Lindgren +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wilink_platform_data.c +-+++ b/drivers/net/wireless/ti/wilink_platform_data.c +-@@ -23,17 +23,17 @@ +- #include +- #include +- +--static struct wl12xx_platform_data *platform_data; +-+static struct wl12xx_platform_data *wl12xx_platform_data; +- +- int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) +- { +-- if (platform_data) +-+ if (wl12xx_platform_data) +- return -EBUSY; +- if (!data) +- return -EINVAL; +- +-- platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); +-- if (!platform_data) +-+ wl12xx_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); +-+ if (!wl12xx_platform_data) +- return -ENOMEM; +- +- return 0; +-@@ -41,9 +41,34 @@ int __init wl12xx_set_platform_data(cons +- +- struct wl12xx_platform_data *wl12xx_get_platform_data(void) +- { +-- if (!platform_data) +-+ if (!wl12xx_platform_data) +- return ERR_PTR(-ENODEV); +- +-- return platform_data; +-+ return wl12xx_platform_data; +- } +- EXPORT_SYMBOL(wl12xx_get_platform_data); +-+ +-+static struct wl1251_platform_data *wl1251_platform_data; +-+ +-+int __init wl1251_set_platform_data(const struct wl1251_platform_data *data) +-+{ +-+ if (wl1251_platform_data) +-+ return -EBUSY; +-+ if (!data) +-+ return -EINVAL; +-+ +-+ wl1251_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); +-+ if (!wl1251_platform_data) +-+ return -ENOMEM; +-+ +-+ return 0; +-+} +-+ +-+struct wl1251_platform_data *wl1251_get_platform_data(void) +-+{ +-+ if (!wl1251_platform_data) +-+ return ERR_PTR(-ENODEV); +-+ +-+ return wl1251_platform_data; +-+} +-+EXPORT_SYMBOL(wl1251_get_platform_data); +---- a/drivers/net/wireless/ti/wl1251/sdio.c +-+++ b/drivers/net/wireless/ti/wl1251/sdio.c +-@@ -227,7 +227,7 @@ static int wl1251_sdio_probe(struct sdio +- struct wl1251 *wl; +- struct ieee80211_hw *hw; +- struct wl1251_sdio *wl_sdio; +-- const struct wl12xx_platform_data *wl12xx_board_data; +-+ const struct wl1251_platform_data *wl1251_board_data; +- +- hw = wl1251_alloc_hw(); +- if (IS_ERR(hw)) +-@@ -254,11 +254,11 @@ static int wl1251_sdio_probe(struct sdio +- wl->if_priv = wl_sdio; +- wl->if_ops = &wl1251_sdio_ops; +- +-- wl12xx_board_data = wl12xx_get_platform_data(); +-- if (!IS_ERR(wl12xx_board_data)) { +-- wl->set_power = wl12xx_board_data->set_power; +-- wl->irq = wl12xx_board_data->irq; +-- wl->use_eeprom = wl12xx_board_data->use_eeprom; +-+ wl1251_board_data = wl1251_get_platform_data(); +-+ if (!IS_ERR(wl1251_board_data)) { +-+ wl->set_power = wl1251_board_data->set_power; +-+ wl->irq = wl1251_board_data->irq; +-+ wl->use_eeprom = wl1251_board_data->use_eeprom; +- } +- +- if (wl->irq) { +---- a/drivers/net/wireless/ti/wl1251/spi.c +-+++ b/drivers/net/wireless/ti/wl1251/spi.c +-@@ -241,7 +241,7 @@ static const struct wl1251_if_operations +- +- static int wl1251_spi_probe(struct spi_device *spi) +- { +-- struct wl12xx_platform_data *pdata; +-+ struct wl1251_platform_data *pdata; +- struct ieee80211_hw *hw; +- struct wl1251 *wl; +- int ret; +diff --git a/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch +new file mode 100644 +index 0000000..967768a +--- /dev/null ++++ b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch +@@ -0,0 +1,139 @@ ++When running with DT, we no longer have a board file that can set up the ++platform data for wlcore. Allow this data to be passed from DT. ++ ++Since some platforms use a gpio-irq, add support for passing either the ++irq number or the gpio number. For the latter case, the driver will ++request the gpio and convert it to the irq number. If an irq is ++specified, it'll be used as is. ++ ++[Arik - the pdev_data pointer does not belong to us and is freed when ++the device is released. Dereference to our private data first.] ++ ++Signed-off-by: Ido Yariv ++Signed-off-by: Arik Nemtsov ++--- ++ drivers/net/wireless/ti/wlcore/sdio.c | 71 ++++++++++++++++++++++++++++++++--- ++ include/linux/wl12xx.h | 3 +- ++ 2 files changed, 67 insertions(+), 7 deletions(-) ++ ++--- a/drivers/net/wireless/ti/wlcore/sdio.c +++++ b/drivers/net/wireless/ti/wlcore/sdio.c ++@@ -34,6 +34,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "wlcore.h" ++ #include "wl12xx_80211.h" ++@@ -214,6 +215,61 @@ static struct wl1271_if_operations sdio_ ++ .set_block_size = wl1271_sdio_set_block_size, ++ }; ++ +++static const struct of_device_id wlcore_of_match[] = { +++ { +++ .compatible = "wlcore", +++ }, +++ {} +++}; +++MODULE_DEVICE_TABLE(of, wlcore_of_match); +++ +++static struct wl12xx_platform_data *get_platform_data(struct device *dev) +++{ +++ struct wl12xx_platform_data *pdata; +++ struct device_node *np; +++ u32 gpio; +++ +++ pdata = wl12xx_get_platform_data(); +++ if (!IS_ERR(pdata)) +++ return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL); +++ +++ np = of_find_matching_node(NULL, wlcore_of_match); +++ if (!np) { +++ dev_err(dev, "No platform data set\n"); +++ return NULL; +++ } +++ +++ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); +++ if (!pdata) { +++ dev_err(dev, "Can't allocate platform data\n"); +++ return NULL; +++ } +++ +++ if (of_property_read_u32(np, "irq", &pdata->irq)) { +++ if (!of_property_read_u32(np, "gpio", &gpio) && +++ !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) { +++ pdata->gpio = gpio; +++ pdata->irq = gpio_to_irq(gpio); +++ } +++ } +++ +++ /* Optional fields */ +++ pdata->use_eeprom = of_property_read_bool(np, "use-eeprom"); +++ of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock); +++ of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock); +++ of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks); +++ +++ return pdata; +++} +++ +++static void del_platform_data(struct wl12xx_platform_data *pdata) +++{ +++ if (pdata->gpio) +++ gpio_free(pdata->gpio); +++ +++ kfree(pdata); +++} +++ ++ static int wl1271_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++ { ++@@ -248,12 +304,9 @@ static int wl1271_probe(struct sdio_func ++ /* Use block mode for transferring over one block size of data */ ++ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; ++ ++- pdev_data->pdata = wl12xx_get_platform_data(); ++- if (IS_ERR(pdev_data->pdata)) { ++- ret = PTR_ERR(pdev_data->pdata); ++- dev_err(glue->dev, "missing wlan platform data: %d\n", ret); +++ pdev_data->pdata = get_platform_data(&func->dev); +++ if (!(pdev_data->pdata)) ++ goto out_free_glue; ++- } ++ ++ /* if sdio can keep power while host is suspended, enable wow */ ++ mmcflags = sdio_get_host_pm_caps(func); ++@@ -282,7 +335,7 @@ static int wl1271_probe(struct sdio_func ++ if (!glue->core) { ++ dev_err(glue->dev, "can't allocate platform_device"); ++ ret = -ENOMEM; ++- goto out_free_glue; +++ goto out_free_pdata; ++ } ++ ++ glue->core->dev.parent = &func->dev; ++@@ -316,6 +369,9 @@ static int wl1271_probe(struct sdio_func ++ out_dev_put: ++ platform_device_put(glue->core); ++ +++out_free_pdata: +++ del_platform_data(pdev_data->pdata); +++ ++ out_free_glue: ++ kfree(glue); ++ ++@@ -329,11 +385,14 @@ out: ++ static void wl1271_remove(struct sdio_func *func) ++ { ++ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); +++ struct wlcore_platdev_data *pdev_data = glue->core->dev.platform_data; +++ struct wl12xx_platform_data *pdata = pdev_data->pdata; ++ ++ /* Undo decrement done above in wl1271_probe */ ++ pm_runtime_get_noresume(&func->dev); ++ ++ platform_device_unregister(glue->core); +++ del_platform_data(pdata); ++ kfree(glue); ++ } ++ +diff --git a/package/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch b/package/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch +new file mode 100644 +index 0000000..77647bb +--- /dev/null ++++ b/package/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch +@@ -0,0 +1,47 @@ ++From fde3f0a7f3112527a18e06e32efdd9a354c91b02 Mon Sep 17 00:00:00 2001 ++From: Eliad Peller ++Date: Tue, 18 Mar 2014 13:19:48 +0200 ++Subject: [PATCH] wl18xx: align event mailbox with current fw ++ ++Some fields are missing from the event mailbox ++struct definitions, which cause issues when ++trying to handle some events. ++ ++Add the missing fields in order to align the ++struct size (without adding actual support ++for the new fields). ++ ++Signed-off-by: Eliad Peller ++--- ++ drivers/net/wireless/ti/wl18xx/event.h | 20 ++++++++++++++++++++ ++ 1 file changed, 20 insertions(+) ++ ++--- a/drivers/net/wireless/ti/wl18xx/event.h +++++ b/drivers/net/wireless/ti/wl18xx/event.h ++@@ -68,6 +68,26 @@ struct wl18xx_event_mailbox { ++ ++ /* bitmap of inactive stations (by HLID) */ ++ __le32 inactive_sta_bitmap; +++ +++ /* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */ +++ u8 rx_ba_role_id; +++ u8 rx_ba_link_id; +++ u8 rx_ba_win_size; +++ u8 padding; +++ +++ /* smart config */ +++ u8 sc_ssid_len; +++ u8 sc_pwd_len; +++ u8 sc_token_len; +++ u8 padding1; +++ u8 sc_ssid[32]; +++ u8 sc_pwd[32]; +++ u8 sc_token[32]; +++ +++ /* smart config sync channel */ +++ u8 sc_sync_channel; +++ u8 sc_sync_band; +++ u8 padding2[2]; ++ } __packed; ++ ++ int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, +diff --git a/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch b/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch +deleted file mode 100644 +index f2789a9..0000000 +--- a/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch ++++ /dev/null +@@ -1,118 +0,0 @@ +-The platform_quirk element in the platform data was used to change the +-way the IRQ is triggered. When set, the EDGE_IRQ quirk would change +-the irqflags used and treat edge trigger differently from the rest. +- +-Instead of hiding this irq flag setting behind the quirk, have the +-board files set the flags during initialization. This will be more +-meaningful than driver-specific quirks when we switch to DT. +- +-Additionally, fix missing gpio_request() calls in the boarding files +-(so that setting the flags actually works). +- +-Cc: Tony Lindgren +-Cc: Sekhar Nori +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +-Acked-by: Sekhar Nori +- +---- a/drivers/net/wireless/ti/wlcore/debugfs.c +-+++ b/drivers/net/wireless/ti/wlcore/debugfs.c +-@@ -502,7 +502,7 @@ static ssize_t driver_state_read(struct +- DRIVER_STATE_PRINT_HEX(irq); +- /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */ +- DRIVER_STATE_PRINT_HEX(hw_pg_ver); +-- DRIVER_STATE_PRINT_HEX(platform_quirks); +-+ DRIVER_STATE_PRINT_HEX(irq_flags); +- DRIVER_STATE_PRINT_HEX(chip.id); +- DRIVER_STATE_PRINT_STR(chip.fw_ver_str); +- DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str); +---- a/drivers/net/wireless/ti/wlcore/main.c +-+++ b/drivers/net/wireless/ti/wlcore/main.c +-@@ -27,6 +27,7 @@ +- #include +- #include +- #include +-+#include +- +- #include "wlcore.h" +- #include "debug.h" +-@@ -528,7 +529,7 @@ static int wlcore_irq_locked(struct wl12 +- * In case edge triggered interrupt must be used, we cannot iterate +- * more than once without introducing race conditions with the hardirq. +- */ +-- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) +-+ if (wl->irq_flags & IRQF_TRIGGER_RISING) +- loopcount = 1; +- +- wl1271_debug(DEBUG_IRQ, "IRQ work"); +-@@ -5934,7 +5935,6 @@ struct ieee80211_hw *wlcore_alloc_hw(siz +- wl->ap_ps_map = 0; +- wl->ap_fw_ps_map = 0; +- wl->quirks = 0; +-- wl->platform_quirks = 0; +- wl->system_hlid = WL12XX_SYSTEM_HLID; +- wl->active_sta_count = 0; +- wl->active_link_count = 0; +-@@ -6075,7 +6075,7 @@ static void wlcore_nvs_cb(const struct f +- struct platform_device *pdev = wl->pdev; +- struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev); +- struct wl12xx_platform_data *pdata = pdev_data->pdata; +-- unsigned long irqflags; +-+ +- int ret; +- irq_handler_t hardirq_fn = NULL; +- +-@@ -6103,29 +6103,19 @@ static void wlcore_nvs_cb(const struct f +- wlcore_adjust_conf(wl); +- +- wl->irq = platform_get_irq(pdev, 0); +-- wl->platform_quirks = pdata->platform_quirks; +- wl->if_ops = pdev_data->if_ops; +- +--#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) +-- irqflags = IRQF_TRIGGER_RISING; +-+ wl->irq_flags = irq_get_trigger_type(wl->irq) | IRQF_ONESHOT; +- hardirq_fn = wlcore_hardirq; +--#else +-- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) { +-- irqflags = IRQF_TRIGGER_RISING; +-- hardirq_fn = wlcore_hardirq; +-- } else { +-- irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; +-- } +--#endif +- +- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) +- ret = compat_request_threaded_irq(&wl->irq_compat, wl->irq, +- hardirq_fn, wlcore_irq, +-- irqflags, +-+ wl->irqflags, +- pdev->name, wl); +- #else +- ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq, +-- irqflags, pdev->name, wl); +-+ wl->irq_flags, pdev->name, wl); +- #endif +- if (ret < 0) { +- wl1271_error("request_irq() failed: %d", ret); +---- a/drivers/net/wireless/ti/wlcore/wlcore.h +-+++ b/drivers/net/wireless/ti/wlcore/wlcore.h +-@@ -188,6 +188,8 @@ struct wl1271 { +- +- int irq; +- +-+ int irq_flags; +-+ +- spinlock_t wl_lock; +- +- enum wlcore_state state; +-@@ -395,9 +397,6 @@ struct wl1271 { +- /* Quirks of specific hardware revisions */ +- unsigned int quirks; +- +-- /* Platform limitations */ +-- unsigned int platform_quirks; +-- +- /* number of currently active RX BA sessions */ +- int ba_rx_session_count; +- +diff --git a/package/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch +new file mode 100644 +index 0000000..3d501b2 +--- /dev/null ++++ b/package/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch +@@ -0,0 +1,36 @@ ++From 4101e8dc540d19f1f6c24930629149191786e4cd Mon Sep 17 00:00:00 2001 ++From: Arik Nemtsov ++Date: Mon, 9 Sep 2013 16:48:59 +0300 ++Subject: [PATCH 27/75] wlcore: don't switch channels on disconnected STA vifs ++ ++Sending the FW a channel switch command on a disconnected vif may result ++in a beacon loss event. Avoid this edge case. ++ ++Signed-off-by: Arik Nemtsov ++--- ++ drivers/net/wireless/ti/wlcore/main.c | 7 +++++++ ++ 1 file changed, 7 insertions(+) ++ ++--- a/drivers/net/wireless/ti/wlcore/main.c +++++ b/drivers/net/wireless/ti/wlcore/main.c ++@@ -5181,6 +5181,10 @@ static void wl12xx_op_channel_switch(str ++ if (unlikely(wl->state == WLCORE_STATE_OFF)) { ++ wl12xx_for_each_wlvif_sta(wl, wlvif) { ++ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); +++ +++ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) +++ continue; +++ ++ ieee80211_chswitch_done(vif, false); ++ } ++ goto out; ++@@ -5196,6 +5200,9 @@ static void wl12xx_op_channel_switch(str ++ wl12xx_for_each_wlvif_sta(wl, wlvif) { ++ unsigned long delay_usec; ++ +++ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) +++ continue; +++ ++ ret = wl->ops->channel_switch(wl, wlvif, ch_switch); ++ if (ret) ++ goto out_sleep; +diff --git a/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch b/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch +deleted file mode 100644 +index 6394377..0000000 +--- a/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch ++++ /dev/null +@@ -1,48 +0,0 @@ +-The pwr_in_suspend flag depends on the MMC settings which can be +-retrieved from the SDIO subsystem, so it doesn't need to be part of +-the platform data structure. Move it to the platform device data that +-is passed from SDIO to wlcore. +- +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wlcore/main.c +-+++ b/drivers/net/wireless/ti/wlcore/main.c +-@@ -6074,7 +6074,6 @@ static void wlcore_nvs_cb(const struct f +- struct wl1271 *wl = context; +- struct platform_device *pdev = wl->pdev; +- struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev); +-- struct wl12xx_platform_data *pdata = pdev_data->pdata; +- +- int ret; +- irq_handler_t hardirq_fn = NULL; +-@@ -6127,7 +6126,7 @@ static void wlcore_nvs_cb(const struct f +- if (!ret) { +- wl->irq_wake_enabled = true; +- device_init_wakeup(wl->dev, 1); +-- if (pdata->pwr_in_suspend) +-+ if (pdev_data->pwr_in_suspend) +- wl->hw->wiphy->wowlan = &wlcore_wowlan_support; +- } +- #endif +---- a/drivers/net/wireless/ti/wlcore/sdio.c +-+++ b/drivers/net/wireless/ti/wlcore/sdio.c +-@@ -260,7 +260,7 @@ static int wl1271_probe(struct sdio_func +- dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); +- +- if (mmcflags & MMC_PM_KEEP_POWER) +-- pdev_data->pdata->pwr_in_suspend = true; +-+ pdev_data->pwr_in_suspend = true; +- +- sdio_set_drvdata(func, glue); +- +---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +-+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h +-@@ -209,6 +209,7 @@ struct wl1271_if_operations { +- struct wlcore_platdev_data { +- struct wl12xx_platform_data *pdata; +- struct wl1271_if_operations *if_ops; +-+ bool pwr_in_suspend; +- }; +- +- #define MAX_NUM_KEYS 14 +diff --git a/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch b/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch +deleted file mode 100644 +index 4b20932..0000000 +--- a/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch ++++ /dev/null +@@ -1,131 +0,0 @@ +-Instead of defining an enumeration with the FW specific values for the +-different clock rates, use the actual frequency instead. Also add a +-boolean to specify whether the clock is XTAL or not. +- +-Change all board files to reflect this. +- +-Additionally, this reverts commit 26f45c (ARM: OMAP2+: Legacy support +-for wl12xx when booted with devicetree), since this is not be needed +-anymore, now that DT support for WiLink is implemented. +- +-Cc: Tony Lindgren +-Cc: Sekhar Nori +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wl12xx/main.c +-+++ b/drivers/net/wireless/ti/wl12xx/main.c +-@@ -1711,6 +1711,43 @@ static struct ieee80211_sta_ht_cap wl12x +- }, +- }; +- +-+static const struct wl12xx_clock wl12xx_refclock_table[] = { +-+ { 19200000, false, WL12XX_REFCLOCK_19 }, +-+ { 26000000, false, WL12XX_REFCLOCK_26 }, +-+ { 26000000, true, WL12XX_REFCLOCK_26_XTAL }, +-+ { 38400000, false, WL12XX_REFCLOCK_38 }, +-+ { 38400000, true, WL12XX_REFCLOCK_38_XTAL }, +-+ { 52000000, false, WL12XX_REFCLOCK_52 }, +-+ { 0, false, 0 } +-+}; +-+ +-+static const struct wl12xx_clock wl12xx_tcxoclock_table[] = { +-+ { 16368000, true, WL12XX_TCXOCLOCK_16_368 }, +-+ { 16800000, true, WL12XX_TCXOCLOCK_16_8 }, +-+ { 19200000, true, WL12XX_TCXOCLOCK_19_2 }, +-+ { 26000000, true, WL12XX_TCXOCLOCK_26 }, +-+ { 32736000, true, WL12XX_TCXOCLOCK_32_736 }, +-+ { 33600000, true, WL12XX_TCXOCLOCK_33_6 }, +-+ { 38400000, true, WL12XX_TCXOCLOCK_38_4 }, +-+ { 52000000, true, WL12XX_TCXOCLOCK_52 }, +-+ { 0, false, 0 } +-+}; +-+ +-+static int wl12xx_get_clock_idx(const struct wl12xx_clock *table, +-+ u32 freq, bool xtal) +-+{ +-+ int i = 0; +-+ +-+ while(table[i].freq != 0) { +-+ if ((table[i].freq == freq) && +-+ (table[i].xtal == xtal)) +-+ return table[i].hw_idx; +-+ i++; +-+ }; +-+ +-+ return -EINVAL; +-+} +-+ +- static int wl12xx_setup(struct wl1271 *wl) +- { +- struct wl12xx_priv *priv = wl->priv; +-@@ -1732,7 +1769,16 @@ static int wl12xx_setup(struct wl1271 *w +- wl12xx_conf_init(wl); +- +- if (!fref_param) { +-- priv->ref_clock = pdata->board_ref_clock; +-+ priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table, +-+ pdata->ref_clock_freq, +-+ pdata->ref_clock_xtal); +-+ if (priv->ref_clock < 0) { +-+ wl1271_error("Invalid ref_clock frequency (%d Hz, %s)", +-+ pdata->ref_clock_freq, +-+ pdata->ref_clock_xtal ? "XTAL" : "not XTAL"); +-+ +-+ return priv->ref_clock; +-+ } +- } else { +- if (!strcmp(fref_param, "19.2")) +- priv->ref_clock = WL12XX_REFCLOCK_19; +-@@ -1751,7 +1797,15 @@ static int wl12xx_setup(struct wl1271 *w +- } +- +- if (!tcxo_param) { +-- priv->tcxo_clock = pdata->board_tcxo_clock; +-+ priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table, +-+ pdata->tcxo_clock_freq, +-+ true); +-+ if (priv->tcxo_clock < 0) { +-+ wl1271_error("Invalid tcxo_clock frequency (%d Hz)", +-+ pdata->tcxo_clock_freq); +-+ +-+ return priv->tcxo_clock; +-+ } +- } else { +- if (!strcmp(tcxo_param, "19.2")) +- priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2; +---- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +-+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h +-@@ -79,4 +79,32 @@ struct wl12xx_priv { +- struct wl127x_rx_mem_pool_addr *rx_mem_addr; +- }; +- +-+/* Reference clock values */ +-+enum { +-+ WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ +-+ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ +-+ WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ +-+ WL12XX_REFCLOCK_52 = 3, /* 52 MHz */ +-+ WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */ +-+ WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */ +-+}; +-+ +-+/* TCXO clock values */ +-+enum { +-+ WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */ +-+ WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */ +-+ WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */ +-+ WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */ +-+ WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */ +-+ WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */ +-+ WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */ +-+ WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */ +-+}; +-+ +-+struct wl12xx_clock { +-+ u32 freq; +-+ bool xtal; +-+ u8 hw_idx; +-+}; +-+ +- #endif /* __WL12XX_PRIV_H__ */ +diff --git a/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch b/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch +deleted file mode 100644 +index 9e1d190..0000000 +--- a/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch ++++ /dev/null +@@ -1,118 +0,0 @@ +-If platform data is not available, try to get the required information +-from the device tree. Register an OF match table and parse the +-appropriate device tree nodes. +- +-Parse interrupt property only, for now. +- +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wlcore/sdio.c +-+++ b/drivers/net/wireless/ti/wlcore/sdio.c +-@@ -30,7 +30,7 @@ +- #include +- #include +- #include +--#include +-+#include +- #include +- #include +- #include +-@@ -214,6 +214,43 @@ static struct wl1271_if_operations sdio_ +- .set_block_size = wl1271_sdio_set_block_size, +- }; +- +-+static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev) +-+{ +-+ struct wl12xx_platform_data *pdata; +-+ struct device_node *np = dev->of_node; +-+ +-+ if (!np) { +-+ np = of_find_matching_node(NULL, dev->driver->of_match_table); +-+ if (!np) { +-+ dev_notice(dev, "device tree node not available\n"); +-+ pdata = ERR_PTR(-ENODEV); +-+ goto out; +-+ } +-+ } +-+ +-+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); +-+ if (!pdata) { +-+ dev_err(dev, "can't allocate platform data\n"); +-+ pdata = ERR_PTR(-ENODEV); +-+ goto out; +-+ } +-+ +-+ pdata->irq = irq_of_parse_and_map(np, 0); +-+ if (pdata->irq < 0) { +-+ dev_err(dev, "can't get interrupt gpio from the device tree\n"); +-+ goto out_free; +-+ } +-+ +-+ goto out; +-+ +-+out_free: +-+ kfree(pdata); +-+ pdata = ERR_PTR(-ENODEV); +-+ +-+out: +-+ return pdata; +-+} +-+ +- static int wl1271_probe(struct sdio_func *func, +- const struct sdio_device_id *id) +- { +-@@ -248,11 +285,22 @@ static int wl1271_probe(struct sdio_func +- /* Use block mode for transferring over one block size of data */ +- func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; +- +-+ /* The pdata allocated here is freed when the device is freed, +-+ * so we don't need an additional out label to free it in case +-+ * of error further on. +-+ */ +-+ +-+ /* Try to get legacy platform data from the board file */ +- pdev_data->pdata = wl12xx_get_platform_data(); +- if (IS_ERR(pdev_data->pdata)) { +-- ret = PTR_ERR(pdev_data->pdata); +-- dev_err(glue->dev, "missing wlan platform data: %d\n", ret); +-- goto out_free_glue; +-+ dev_info(&func->dev, +-+ "legacy platform data not found, trying device tree\n"); +-+ +-+ pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev); +-+ if (IS_ERR(pdev_data->pdata)) { +-+ dev_err(&func->dev, "can't get platform data\n"); +-+ goto out_free_glue; +-+ } +- } +- +- /* if sdio can keep power while host is suspended, enable wow */ +-@@ -386,16 +434,25 @@ static const struct dev_pm_ops wl1271_sd +- }; +- #endif +- +-+static const struct of_device_id wlcore_sdio_of_match_table[] = { +-+ { .compatible = "ti,wilink6" }, +-+ { .compatible = "ti,wilink7" }, +-+ { .compatible = "ti,wilink8" }, +-+ { } +-+}; +-+MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table); +-+ +- static struct sdio_driver wl1271_sdio_driver = { +- .name = "wl1271_sdio", +- .id_table = wl1271_devices, +- .probe = wl1271_probe, +- .remove = wl1271_remove, +--#ifdef CONFIG_PM +- .drv = { +-+#ifdef CONFIG_PM +- .pm = &wl1271_sdio_pm_ops, +-- }, +- #endif +-+ .of_match_table = of_match_ptr(wlcore_sdio_of_match_table), +-+ }, +- }; +- +- static int __init wl1271_init(void) +diff --git a/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch b/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch +deleted file mode 100644 +index be1f9ad..0000000 +--- a/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch ++++ /dev/null +@@ -1,50 +0,0 @@ +-Add refclock and tcxoclock as clock providers in WiLink. These clocks +-are not accesible outside the WiLink module, but they are registered +-in the clock framework anyway. Only the WiLink chip consumes these +-clocks. +- +-In theory, the WiLink chip could be connected to external clocks +-instead of using these internal clocks, so make the clock consumer +-code generic enough. If external clocks are used, then the internal +-clock device tree nodes are not necessary, but the external ones must +-be specified. +- +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wlcore/sdio.c +-+++ b/drivers/net/wireless/ti/wlcore/sdio.c +-@@ -34,6 +34,7 @@ +- #include +- #include +- #include +-+#include +- +- #include "wlcore.h" +- #include "wl12xx_80211.h" +-@@ -214,10 +215,15 @@ static struct wl1271_if_operations sdio_ +- .set_block_size = wl1271_sdio_set_block_size, +- }; +- +-+static const struct of_device_id wlcore_sdio_of_clk_match_table[] = { +-+ { .compatible = "ti,wilink-clock" }, +-+}; +-+ +- static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev) +- { +- struct wl12xx_platform_data *pdata; +- struct device_node *np = dev->of_node; +-+ struct device_node *clock_node; +- +- if (!np) { +- np = of_find_matching_node(NULL, dev->driver->of_match_table); +-@@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlco +- goto out_free; +- } +- +-+ for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table) +-+ of_fixed_clk_setup(clock_node); +-+ +- goto out; +- +- out_free: +diff --git a/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch b/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch +deleted file mode 100644 +index 09ff4af..0000000 +--- a/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch ++++ /dev/null +@@ -1,90 +0,0 @@ +-Read the clock nodes from the device tree and use them to set the +-frequency for the refclock and the tcxo clock. +- +-Also, call sdio_set_drvdata() earlier, so the glue is already set in +-the driver data when we call wlcore_get_pdata_from_of() and we don't +-need to pass it as a parameter. +- +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wlcore/sdio.c +-+++ b/drivers/net/wireless/ti/wlcore/sdio.c +-@@ -53,6 +53,7 @@ static bool dump = false; +- struct wl12xx_sdio_glue { +- struct device *dev; +- struct platform_device *core; +-+ struct clk *refclock, *tcxoclock; +- }; +- +- static const struct sdio_device_id wl1271_devices[] = { +-@@ -224,6 +225,7 @@ static struct wl12xx_platform_data *wlco +- struct wl12xx_platform_data *pdata; +- struct device_node *np = dev->of_node; +- struct device_node *clock_node; +-+ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(dev_to_sdio_func(dev)); +- +- if (!np) { +- np = of_find_matching_node(NULL, dev->driver->of_match_table); +-@@ -250,6 +252,26 @@ static struct wl12xx_platform_data *wlco +- for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table) +- of_fixed_clk_setup(clock_node); +- +-+ /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */ +-+ glue->refclock = of_clk_get_by_name(np, "refclock"); +-+ if (IS_ERR(glue->refclock)) { +-+ dev_err(dev, "couldn't find refclock on the device tree\n"); +-+ glue->refclock = NULL; +-+ } else { +-+ clk_prepare_enable(glue->refclock); +-+ pdata->ref_clock_freq = clk_get_rate(glue->refclock); +-+ } +-+ +-+ /* TODO: make sure we have this when needed (ie. for WL7) */ +-+ glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock"); +-+ if (IS_ERR(glue->tcxoclock)) { +-+ dev_err(dev, "couldn't find tcxoclock on the device tree\n"); +-+ glue->tcxoclock = NULL; +-+ } else { +-+ clk_prepare_enable(glue->tcxoclock); +-+ pdata->ref_clock_freq = clk_get_rate(glue->tcxoclock); +-+ } +-+ +- goto out; +- +- out_free: +-@@ -294,6 +316,8 @@ static int wl1271_probe(struct sdio_func +- /* Use block mode for transferring over one block size of data */ +- func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; +- +-+ sdio_set_drvdata(func, glue); +-+ +- /* The pdata allocated here is freed when the device is freed, +- * so we don't need an additional out label to free it in case +- * of error further on. +-@@ -319,8 +343,6 @@ static int wl1271_probe(struct sdio_func +- if (mmcflags & MMC_PM_KEEP_POWER) +- pdev_data->pwr_in_suspend = true; +- +-- sdio_set_drvdata(func, glue); +-- +- /* Tell PM core that we don't need the card to be powered now */ +- pm_runtime_put_noidle(&func->dev); +- +-@@ -387,6 +409,16 @@ static void wl1271_remove(struct sdio_fu +- { +- struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); +- +-+ if (glue->refclock) { +-+ clk_disable_unprepare(glue->refclock); +-+ clk_put(glue->refclock); +-+ } +-+ +-+ if (glue->tcxoclock) { +-+ clk_disable_unprepare(glue->tcxoclock); +-+ clk_put(glue->tcxoclock); +-+ } +-+ +- /* Undo decrement done above in wl1271_probe */ +- pm_runtime_get_noresume(&func->dev); +- +diff --git a/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch b/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch +deleted file mode 100644 +index 6b09177..0000000 +--- a/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch ++++ /dev/null +@@ -1,96 +0,0 @@ +-The fref and the tcxo clocks settings are optional in some platforms. +-WiLink8 doesn't need either, so we don't check the values. WiLink 6 +-only needs the fref clock, so we check that it is valid or return with +-an error. WiLink7 needs both clocks, if either is not available we +-return with an error. +- +-Signed-off-by: Luciano Coelho +-Reviewed-by: Felipe Balbi +- +---- a/drivers/net/wireless/ti/wl12xx/main.c +-+++ b/drivers/net/wireless/ti/wl12xx/main.c +-@@ -930,6 +930,11 @@ static int wl128x_boot_clk(struct wl1271 +- u16 sys_clk_cfg; +- int ret; +- +-+ if ((priv->ref_clock < 0) || (priv->tcxo_clock < 0)) { +-+ wl1271_error("Missing fref and/or tcxo clock settings\n"); +-+ return -EINVAL; +-+ } +-+ +- /* For XTAL-only modes, FREF will be used after switching from TCXO */ +- if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || +- priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) { +-@@ -979,6 +984,11 @@ static int wl127x_boot_clk(struct wl1271 +- u32 clk; +- int ret; +- +-+ if (priv->ref_clock < 0) { +-+ wl1271_error("Missing fref clock settings\n"); +-+ return -EINVAL; +-+ } +-+ +- if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) +- wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; +- +-@@ -1768,7 +1778,7 @@ static int wl12xx_setup(struct wl1271 *w +- wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap); +- wl12xx_conf_init(wl); +- +-- if (!fref_param) { +-+ if (!fref_param && (pdata->ref_clock_freq > 0)) { +- priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table, +- pdata->ref_clock_freq, +- pdata->ref_clock_xtal); +-@@ -1779,6 +1789,8 @@ static int wl12xx_setup(struct wl1271 *w +- +- return priv->ref_clock; +- } +-+ } else if (!fref_param) { +-+ priv->ref_clock = -EINVAL; +- } else { +- if (!strcmp(fref_param, "19.2")) +- priv->ref_clock = WL12XX_REFCLOCK_19; +-@@ -1796,7 +1808,7 @@ static int wl12xx_setup(struct wl1271 *w +- wl1271_error("Invalid fref parameter %s", fref_param); +- } +- +-- if (!tcxo_param) { +-+ if (!fref_param && (pdata->tcxo_clock_freq > 0)) { +- priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table, +- pdata->tcxo_clock_freq, +- true); +-@@ -1806,7 +1818,9 @@ static int wl12xx_setup(struct wl1271 *w +- +- return priv->tcxo_clock; +- } +-- } else { +-+ } else if (!fref_param) { +-+ priv->tcxo_clock = -EINVAL; +-+ }else { +- if (!strcmp(tcxo_param, "19.2")) +- priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2; +- else if (!strcmp(tcxo_param, "26")) +---- a/drivers/net/wireless/ti/wlcore/sdio.c +-+++ b/drivers/net/wireless/ti/wlcore/sdio.c +-@@ -252,20 +252,16 @@ static struct wl12xx_platform_data *wlco +- for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table) +- of_fixed_clk_setup(clock_node); +- +-- /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */ +- glue->refclock = of_clk_get_by_name(np, "refclock"); +- if (IS_ERR(glue->refclock)) { +-- dev_err(dev, "couldn't find refclock on the device tree\n"); +- glue->refclock = NULL; +- } else { +- clk_prepare_enable(glue->refclock); +- pdata->ref_clock_freq = clk_get_rate(glue->refclock); +- } +- +-- /* TODO: make sure we have this when needed (ie. for WL7) */ +- glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock"); +- if (IS_ERR(glue->tcxoclock)) { +-- dev_err(dev, "couldn't find tcxoclock on the device tree\n"); +- glue->tcxoclock = NULL; +- } else { +- clk_prepare_enable(glue->tcxoclock);