select PACKAGE_libopenssl
endchoice
+
+config WPA_RFKILL_SUPPORT
+ bool "Add rfkill support"
+ depends PACKAGE_wpa-supplicant || PACKAGE_wpa-supplicant-mini || PACKAGE_wpad || PACKAGE_wpad-mini
+ default n
include $(TOPDIR)/rules.mk
PKG_NAME:=hostapd
-PKG_VERSION:=20100418
-PKG_RELEASE:=2
-PKG_REV:=0b86f67a2970403d1b1b6d34ce49f5485ef5dbb3
+PKG_VERSION:=20100705
+PKG_RELEASE:=1
+PKG_REV:=2f1ce78bf78cecd7021385b04a4f55f22e76ab97
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=git://w1.fi/srv/git/hostap.git
CONFIG_PACKAGE_kmod-madwifi \
CONFIG_PACKAGE_hostapd \
CONFIG_PACKAGE_hostapd-mini \
- CONFIG_PACKAGE_kmod-hostap
+ CONFIG_PACKAGE_kmod-hostap \
+ CONFIG_WPA_RFKILL_SUPPORT
LOCAL_TYPE=$(strip \
$(if $(findstring wpad,$(BUILD_VARIANT)),wpad, \
CONFIG_DRIVER_MADWIFI=$(CONFIG_PACKAGE_kmod-madwifi) \
CONFIG_DRIVER_HOSTAP=$(CONFIG_PACKAGE_kmod-hostap) \
CONFIG_IEEE80211N=$(HOSTAPD_IEEE80211N) \
- CONFIG_IEEE80211W=$(CONFIG_PACKAGE_kmod-ath9k)
+ CONFIG_IEEE80211W=$(CONFIG_PACKAGE_kmod-ath9k) \
+ $(if $(CONFIG_WPA_RFKILL_SUPPORT),NEED_RFKILL=y)
ifneq ($(LOCAL_TYPE),hostapd)
ifdef CONFIG_WPA_SUPPLICANT_OPENSSL
CONFIG_DRIVER_ROBOSWITCH=$(CONFIG_PACKAGE_kmod-switch)
endif
-DRV_DEPENDS:=+PACKAGE_kmod-mac80211:libnl-tiny +PACKAGE_kmod-mac80211:crda @(!(TARGET_avr32||TARGET_etrax)||BROKEN)
+DRV_DEPENDS:=+PACKAGE_kmod-mac80211:libnl-tiny @(!(TARGET_avr32||TARGET_etrax)||BROKEN)
define Package/hostapd/Default
SECTION:=net
define Package/hostapd-utils
$(call Package/hostapd/Default)
TITLE+= (utils)
- DEPENDS:=@PACKAGE_hostapd||PACKAGE_hostapd-mini
+ DEPENDS:=@PACKAGE_hostapd||PACKAGE_hostapd-mini||PACKAGE_wpad||PACKAGE_wpad-mini
endef
define Package/hostapd-utils/description
define Package/wpa-cli
SECTION:=net
CATEGORY:=Network
- DEPENDS:=wpa-supplicant
+ DEPENDS:=@PACKAGE_wpa-supplicant||PACKAGE_wpad-mini||PACKAGE_wpad
TITLE:=WPA Supplicant command line interface
MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
endef
define Build/Compile/wpad
echo ` \
$(call Build/RunMake,hostapd,-s MULTICALL=1 dump_cflags); \
- $(call Build/RunMake,wpa_supplicant,-s dump_cflags) | \
+ $(call Build/RunMake,wpa_supplicant,-s MULTICALL=1 dump_cflags) | \
sed -e 's,-n ,,g' -e 's,$(TARGET_CFLAGS),,' \
` > $(PKG_BUILD_DIR)/.cflags
$(call Build/RunMake,hostapd, \
ifneq ($(LOCAL_TYPE),supplicant)
define Package/hostapd-utils/install
- $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/hotplug.d/button
$(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd_cli $(1)/usr/sbin/
+ $(INSTALL_DATA) ./files/wps-hotplug.sh $(1)/etc/hotplug.d/button/50-wps
endef
endif
CONFIG_INTERNAL_LIBTOMMATH=y
CONFIG_INTERNAL_AES=y
NEED_AES_DEC=y
+
+CONFIG_WPS=y
hostapd_set_bss_options() {
local var="$1"
local vif="$2"
- local enc wpa_group_rekey
+ local enc wpa_group_rekey wps_possible
config_get enc "$vif" encryption
config_get wpa_group_rekey "$vif" wpa_group_rekey
else
append "$var" "wpa_passphrase=$psk" "$N"
fi
+ wps_possible=1
;;
*wpa*)
# required fields? formats?
config_get ssid "$vif" ssid
config_get bridge "$vif" bridge
config_get ieee80211d "$vif" ieee80211d
+ config_get iapp_interface "$vif" iapp_interface
+
+ config_get_bool wps_pbc "$vif" wps_pushbutton 0
+ [ -n "$wps_possible" -a "$wps_pbc" -gt 0 ] && {
+ append "$var" "eap_server=1" "$N"
+ append "$var" "wps_state=2" "$N"
+ append "$var" "ap_setup_locked=1" "$N"
+ append "$var" "config_methods=push_button" "$N"
+ }
append "$var" "ssid=$ssid" "$N"
[ -n "$bridge" ] && append "$var" "bridge=$bridge" "$N"
[ -n "$ieee80211d" ] && append "$var" "ieee80211d=$ieee80211d" "$N"
+ [ -n "$iapp_interface" ] && append "$var" $(uci_get_state network "$iapp_interface" ifname "$iapp_interface") "$N"
[ "$wpa" -ge "2" ] && config_get ieee80211w "$vif" ieee80211w
case "$ieee80211w" in
#CONFIG_EAP_TNC=y
# Wi-Fi Protected Setup (WPS)
-#CONFIG_WPS=y
+CONFIG_WPS=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
local vif="$1"
local driver="$2"
local key="$key"
+ local options="$3"
# wpa_supplicant should use wext for mac80211 cards
[ "$driver" = "mac80211" ] && driver='wext'
}
EOF
[ -z "$proto" -a "$key_mgmt" != "NONE" ] || \
- wpa_supplicant ${bridge:+ -b $bridge} -B -P "/var/run/wifi-${ifname}.pid" -D ${driver:-wext} -i "$ifname" -c /var/run/wpa_supplicant-$ifname.conf
+ wpa_supplicant ${bridge:+ -b $bridge} -B -P "/var/run/wifi-${ifname}.pid" -D ${driver:-wext} -i "$ifname" -c /var/run/wpa_supplicant-$ifname.conf $options
}
--- /dev/null
+if [ "$ACTION" = "pressed" -a "$BUTTON" = "wps" ]; then
+ for dir in /var/run/hostapd-*; do
+ [ -d "$dir" ] || continue
+ hostapd_cli -p "$dir" wps_pbc
+ done
+fi
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -659,7 +659,6 @@ static int setup_interface(struct hostap
+@@ -660,7 +660,6 @@ static int setup_interface(struct hostap
country[3] = '\0';
if (hostapd_set_country(hapd, country) < 0) {
wpa_printf(MSG_ERROR, "Failed to set country code");
/* hostapd.c */
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -754,6 +754,9 @@ int hostapd_setup_interface_complete(str
+@@ -755,6 +755,9 @@ int hostapd_setup_interface_complete(str
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
ifndef CONFIG_OS
ifdef CONFIG_NATIVE_WINDOWS
-@@ -579,6 +580,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
+@@ -581,6 +582,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
LIBS += -ldl -rdynamic
endif
endif
ifdef CONFIG_AP
-@@ -631,6 +636,12 @@ CFLAGS += -DEAP_SERVER_WSC
+@@ -635,6 +640,12 @@ CFLAGS += -DEAP_SERVER_WSC
OBJS += ../src/ap/wps_hostapd.o
OBJS += ../src/eap_server/eap_server_wsc.o
endif
endif
ifdef NEED_RSN_AUTHENTICATOR
-@@ -1262,6 +1273,12 @@ BCHECK=../src/drivers/build.wpa_supplica
+@@ -1270,6 +1281,12 @@ BCHECK=../src/drivers/build.wpa_supplica
wpa_priv: $(BCHECK) $(OBJS_priv)
$(LDO) $(LDFLAGS) -o wpa_priv $(OBJS_priv) $(LIBS)
wpa_supplicant: .config $(BCHECK) $(OBJS) $(EXTRA_progs)
$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
-@@ -1321,6 +1338,12 @@ endif
+@@ -1329,6 +1346,12 @@ endif
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
wpa_cli.exe: wpa_cli
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -2449,8 +2449,8 @@ union wpa_event_data {
+@@ -2465,8 +2465,8 @@ union wpa_event_data {
* Driver wrapper code should call this function whenever an event is received
* from the driver.
*/
for (;;) {
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
-@@ -1577,8 +1577,8 @@ static void ft_rx_action(struct wpa_supp
+@@ -1582,8 +1582,8 @@ static void ft_rx_action(struct wpa_supp
#endif /* CONFIG_IEEE80211R */
u16 reason_code = 0;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -2223,6 +2223,9 @@ struct wpa_supplicant * wpa_supplicant_g
+@@ -2228,6 +2228,9 @@ struct wpa_supplicant * wpa_supplicant_g
return NULL;
}
/**
* wpa_supplicant_init - Initialize %wpa_supplicant
-@@ -2241,6 +2244,7 @@ struct wpa_global * wpa_supplicant_init(
+@@ -2246,6 +2249,7 @@ struct wpa_global * wpa_supplicant_init(
if (params == NULL)
return NULL;
--- a/src/tls/x509v3.c
+++ b/src/tls/x509v3.c
-@@ -1832,8 +1832,11 @@ int x509_certificate_chain_validate(stru
+@@ -1854,8 +1854,11 @@ int x509_certificate_chain_validate(stru
if (chain_trusted)
continue;
size_t max_ssids;
enum wpa_states prev_state;
-@@ -311,6 +312,16 @@ static void wpa_supplicant_scan(void *el
+@@ -316,6 +317,16 @@ static void wpa_supplicant_scan(void *el
wpa_s->wpa_state == WPA_INACTIVE)
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
/* Find the starting point from which to continue scanning */
ssid = wpa_s->conf->ssid;
if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
-@@ -374,6 +385,9 @@ static void wpa_supplicant_scan(void *el
+@@ -379,6 +390,9 @@ static void wpa_supplicant_scan(void *el
int_array_sort_unique(params.freqs);
}
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
-@@ -958,7 +958,7 @@ static void wpa_supplicant_event_scan_re
+@@ -963,7 +963,7 @@ static void wpa_supplicant_event_scan_re
wpa_printf(MSG_DEBUG, "Setup a new network");
wpa_supplicant_associate(wpa_s, NULL, ssid);
} else {
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -4576,9 +4576,11 @@ static int i802_set_wds_sta(void *priv,
+@@ -4652,9 +4652,11 @@ static int i802_set_wds_sta(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
" aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
if (val) {
} else {
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
-@@ -1614,6 +1614,9 @@ static void handle_assoc_cb(struct hosta
+@@ -1627,6 +1627,9 @@ static void handle_assoc_cb(struct hosta
"Could not add STA to kernel driver");
}
/* clear to get error below if setting is invalid */
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -4566,7 +4566,8 @@ static int i802_set_sta_vlan(void *priv,
+@@ -4642,7 +4642,8 @@ static int i802_set_sta_vlan(void *priv,
}
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
-@@ -4580,6 +4581,10 @@ static int i802_set_wds_sta(void *priv,
+@@ -4656,6 +4657,10 @@ static int i802_set_wds_sta(void *priv,
if (nl80211_create_iface(drv, name, NL80211_IFTYPE_AP_VLAN,
NULL, 1) < 0)
return -1;
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -715,6 +715,16 @@ int hostapd_setup_interface_complete(str
+@@ -716,6 +716,16 @@ int hostapd_setup_interface_complete(str
}
}
* @freq: Frequency (in MHz) of the channel
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -4263,6 +4263,29 @@ static int i802_set_rate_sets(void *priv
+@@ -4339,6 +4339,29 @@ static int i802_set_rate_sets(void *priv
return -ENOBUFS;
}
#endif /* HOSTAPD */
-@@ -5372,6 +5395,7 @@ const struct wpa_driver_ops wpa_driver_n
+@@ -5448,6 +5471,7 @@ const struct wpa_driver_ops wpa_driver_n
.set_tx_queue_params = i802_set_tx_queue_params,
.set_sta_vlan = i802_set_sta_vlan,
.set_wds_sta = i802_set_wds_sta,
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -1119,7 +1119,6 @@ nla_put_failure:
+@@ -1135,7 +1135,6 @@ nla_put_failure:
}
struct wiphy_info_data {
int max_scan_ssids;
int ap_supported;
-@@ -1231,7 +1230,6 @@ static int wpa_driver_nl80211_capa(struc
+@@ -1247,7 +1246,6 @@ static int wpa_driver_nl80211_capa(struc
return 0;
}
static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv,
-@@ -1371,6 +1369,7 @@ static void * wpa_driver_nl80211_init(vo
+@@ -1411,6 +1409,7 @@ static void * wpa_driver_nl80211_init(vo
drv->monitor_ifidx = -1;
drv->monitor_sock = -1;
drv->ioctl_sock = -1;
if (wpa_driver_nl80211_init_nl(drv, ctx)) {
os_free(drv);
-@@ -1468,24 +1467,23 @@ wpa_driver_nl80211_finish_drv_init(struc
+@@ -1530,32 +1529,32 @@ wpa_driver_nl80211_finish_drv_init(struc
drv->ifindex = if_nametoindex(bss->ifname);
drv->first_bss.ifindex = drv->ifindex;
- wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to "
- "use managed mode");
- }
--
-- if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
-- wpa_printf(MSG_ERROR, "Could not set interface '%s' UP",
-- bss->ifname);
-- return -1;
-- }
+ if (drv->nlmode == NL80211_IFTYPE_STATION) {
-+ if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0)
-+ wpa_printf(MSG_DEBUG, "nl80211: Could not configure "
-+ "driver to use managed mode");
-+
-+ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
-+ wpa_printf(MSG_ERROR, "Could not set interface '%s' UP",
-+ bss->ifname);
-+ return -1;
++ if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) {
++ wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to "
++ "use managed mode");
+ }
+- if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
+- 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 {
+- wpa_printf(MSG_ERROR, "nl80211: Could not set "
+- "interface '%s' UP", bss->ifname);
+- return -1;
++ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
++ 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 {
++ wpa_printf(MSG_ERROR, "nl80211: Could not set "
++ "interface '%s' UP", bss->ifname);
++ return -1;
++ }
+ }
+- }
+
- if (wpa_driver_nl80211_capa(drv))
- return -1;
+ if (wpa_driver_nl80211_capa(drv))
if (nl80211_register_action_frames(drv) < 0) {
wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
-@@ -2143,13 +2141,9 @@ static int wpa_driver_nl80211_set_key(co
+@@ -2219,13 +2218,9 @@ static int wpa_driver_nl80211_set_key(co
*/
if (ret || !set_tx || alg == WPA_ALG_NONE)
return ret;
msg = nlmsg_alloc();
if (!msg)
-@@ -2990,7 +2984,8 @@ static void nl80211_remove_iface(struct
+@@ -3066,7 +3061,8 @@ static void nl80211_remove_iface(struct
#ifdef HOSTAPD
/* stop listening for EAPOL on this interface */
#endif /* HOSTAPD */
msg = nlmsg_alloc();
-@@ -3063,7 +3058,8 @@ static int nl80211_create_iface_once(str
+@@ -3139,7 +3135,8 @@ static int nl80211_create_iface_once(str
#ifdef HOSTAPD
/* start listening for EAPOL on this interface */
#endif /* HOSTAPD */
if (addr && iftype != NL80211_IFTYPE_MONITOR &&
-@@ -4766,6 +4762,7 @@ static void *i802_init(struct hostapd_da
+@@ -4842,6 +4839,7 @@ static void *i802_init(struct hostapd_da
return NULL;
drv = bss->drv;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -543,10 +543,16 @@ void wpa_supplicant_set_state(struct wpa
+@@ -545,10 +545,16 @@ void wpa_supplicant_set_state(struct wpa
wpa_s->reassociated_connection = 1;
wpa_drv_set_operstate(wpa_s, 1);
wpa_s->after_wps = 0;
--- /dev/null
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -75,7 +75,9 @@ struct wpa_driver_nl80211_data {
+ int ifindex;
+ int if_removed;
+ int if_disabled;
++#ifdef CONFIG_RFKILL
+ struct rfkill_data *rfkill;
++#endif
+ struct wpa_driver_capa capa;
+ int has_capability;
+
+@@ -1361,7 +1363,7 @@ err1:
+ return -1;
+ }
+
+-
++#ifdef CONFIG_RFKILL
+ static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
+ {
+ wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
+@@ -1383,6 +1385,7 @@ static void wpa_driver_nl80211_rfkill_un
+ }
+ /* rtnetlink ifup handler will report interface as enabled */
+ }
++#endif /* CONFIG_RFKILL */
+
+
+ /**
+@@ -1396,7 +1399,9 @@ static void * wpa_driver_nl80211_init(vo
+ {
+ struct wpa_driver_nl80211_data *drv;
+ struct netlink_config *cfg;
++#ifdef CONFIG_RFKILL
+ struct rfkill_config *rcfg;
++#endif
+ struct i802_bss *bss;
+
+ drv = os_zalloc(sizeof(*drv));
+@@ -1434,6 +1439,7 @@ static void * wpa_driver_nl80211_init(vo
+ goto failed;
+ }
+
++#ifdef CONFIG_RFKILL
+ rcfg = os_zalloc(sizeof(*rcfg));
+ if (rcfg == NULL)
+ goto failed;
+@@ -1446,6 +1452,7 @@ static void * wpa_driver_nl80211_init(vo
+ wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
+ os_free(rcfg);
+ }
++#endif /* CONFIG_RFKILL */
+
+ if (wpa_driver_nl80211_finish_drv_init(drv))
+ goto failed;
+@@ -1453,7 +1460,9 @@ static void * wpa_driver_nl80211_init(vo
+ return bss;
+
+ failed:
++#ifdef CONFIG_RFKILL
+ rfkill_deinit(drv->rfkill);
++#endif
+ netlink_deinit(drv->netlink);
+ if (drv->ioctl_sock >= 0)
+ close(drv->ioctl_sock);
+@@ -1514,10 +1523,12 @@ static int nl80211_register_action_frame
+ }
+
+
++#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 int
+@@ -1536,13 +1547,16 @@ wpa_driver_nl80211_finish_drv_init(struc
+ }
+
+ if (linux_set_iface_flags(drv->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;
+@@ -1567,8 +1581,10 @@ wpa_driver_nl80211_finish_drv_init(struc
+ }
+
+ if (send_rfkill_event) {
++#ifdef CONFIG_RFKILL
+ eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
+ drv, drv->ctx);
++#endif
+ }
+
+ return 0;
+@@ -1647,7 +1663,9 @@ static void wpa_driver_nl80211_deinit(vo
+
+ netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
+ netlink_deinit(drv->netlink);
++#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
+@@ -700,7 +700,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");
+@@ -722,7 +722,7 @@ static void wpa_driver_wext_rfkill_unblo
+ }
+ /* rtnetlink ifup handler will report interface as enabled */
+ }
+-
++#endif /* CONFIG_RFKILL */
+
+ /**
+ * wpa_driver_wext_init - Initialize WE driver interface
+@@ -735,7 +735,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;
+
+@@ -769,6 +771,7 @@ void * wpa_driver_wext_init(void *ctx, c
+ goto err2;
+ }
+
++#ifdef CONFIG_RFKILL
+ rcfg = os_zalloc(sizeof(*rcfg));
+ if (rcfg == NULL)
+ goto err3;
+@@ -781,6 +784,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;
+
+@@ -792,7 +796,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);
+@@ -802,10 +808,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)
+@@ -813,13 +821,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;
+@@ -867,8 +878,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;
+@@ -898,7 +911,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
+@@ -31,7 +31,6 @@ NEED_SME=y
+ NEED_AP_MLME=y
+ NEED_NETLINK=y
+ NEED_LINUX_IOCTL=y
+-NEED_RFKILL=y
+ DRV_LIBS += -lnl
+
+ ifdef CONFIG_LIBNL20
+@@ -78,7 +77,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
+ CONFIG_WIRELESS_EXTENSION=y
+ NEED_NETLINK=y
+ NEED_LINUX_IOCTL=y
+-NEED_RFKILL=y
+ endif
+
+ ifdef CONFIG_DRIVER_HERMES
+@@ -166,6 +164,7 @@ endif
+
+ ifdef NEED_RFKILL
+ DRV_OBJS += ../src/drivers/rfkill.o
++DRV_WPA_CFLAGS += -DCONFIG_RFKILL
+ endif
+
+
+--- a/src/drivers/driver_wext.h
++++ b/src/drivers/driver_wext.h
+@@ -27,7 +27,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;
+++ /dev/null
-From: Jouni Malinen <jouni.malinen@atheros.com>
-Date: Tue, 26 Oct 2010 13:30:28 +0000 (+0300)
-Subject: hostapd: Set operstate UP when initializing AP mode
-X-Git-Url: http://w1.fi/gitweb/gitweb.cgi?p=hostap.git;a=commitdiff_plain;h=e11f5a2cbc333113a3a1cc1aeea7f698c3936ca3
-
-hostapd: Set operstate UP when initializing AP mode
-
-This is needed to avoid problems with other applications setting and
-leaving the interface to IF_OPER_DORMANT state. In AP mode, the interface
-is ready immediately after the keys are set, so we better make sure the
-DORMANT state does not prevent normal operations after that.
----
-
---- a/src/ap/hostapd.c
-+++ b/src/ap/hostapd.c
-@@ -622,6 +622,9 @@ static int hostapd_setup_bss(struct host
-
- ieee802_11_set_beacon(hapd);
-
-+ if (hapd->driver && hapd->driver->set_operstate)
-+ hapd->driver->set_operstate(hapd->drv_priv, 1);
-+
- return 0;
- }
-
---- a/src/drivers/driver_wext.c
-+++ b/src/drivers/driver_wext.c
-@@ -2245,11 +2245,14 @@ int wpa_driver_wext_set_operstate(void *
- {
- struct wpa_driver_wext_data *drv = priv;
-
-- wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
-- __func__, drv->operstate, state, state ? "UP" : "DORMANT");
-- drv->operstate = state;
-- return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
-- state ? IF_OPER_UP : IF_OPER_DORMANT);
-+ if (drv != NULL)
-+ {
-+ wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
-+ __func__, drv->operstate, state, state ? "UP" : "DORMANT");
-+ drv->operstate = state;
-+ return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
-+ state ? IF_OPER_UP : IF_OPER_DORMANT);
-+ }
- }
-
-
--- /dev/null
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -410,6 +410,10 @@ static void wpa_driver_nl80211_event_rtm
+ return;
+ }
+
++ if (ifi->ifi_family == AF_BRIDGE &&
++ drv->nlmode != NL80211_IFTYPE_AP)
++ return;
++
+ wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
+ "(%s%s%s%s)",
+ drv->operstate, ifi->ifi_flags,
+@@ -481,6 +485,10 @@ static void wpa_driver_nl80211_event_rtm
+ attrlen = len;
+ attr = (struct rtattr *) buf;
+
++ if (ifi->ifi_family == AF_BRIDGE &&
++ drv->nlmode != NL80211_IFTYPE_AP)
++ return;
++
+ rta_len = RTA_ALIGN(sizeof(struct rtattr));
+ while (RTA_OK(attr, attrlen)) {
+ if (attr->rta_type == IFLA_IFNAME) {
+@@ -1347,6 +1355,11 @@ static int wpa_driver_nl80211_init_nl(st
+ eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event),
+ wpa_driver_nl80211_event_receive, drv, ctx);
+
++#ifdef HOSTAPD
++ drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
++ drv->if_indices = drv->default_if_indices;
++#endif
++
+ return 0;
+
+ err4:
+@@ -4867,8 +4880,6 @@ static void *i802_init(struct hostapd_da
+ br_ifindex = 0;
+ }
+
+- drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
+- drv->if_indices = drv->default_if_indices;
+ for (i = 0; i < params->num_bridge; i++) {
+ if (params->bridge[i]) {
+ ifindex = if_nametoindex(params->bridge[i]);
--- /dev/null
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -42,37 +42,8 @@ static int hostapd_setup_encryption(char
+
+ extern int wpa_debug_level;
+
+-
+-int hostapd_reload_config(struct hostapd_iface *iface)
++static int hostapd_reload_bss(struct hostapd_data *hapd)
+ {
+- struct hostapd_data *hapd = iface->bss[0];
+- struct hostapd_config *newconf, *oldconf;
+- size_t j;
+-
+- if (iface->config_read_cb == NULL)
+- return -1;
+- newconf = iface->config_read_cb(iface->config_fname);
+- if (newconf == NULL)
+- return -1;
+-
+- /*
+- * Deauthenticate all stations since the new configuration may not
+- * allow them to use the BSS anymore.
+- */
+- for (j = 0; j < iface->num_bss; j++)
+- hostapd_flush_old_stations(iface->bss[j]);
+-
+-#ifndef CONFIG_NO_RADIUS
+- /* TODO: update dynamic data based on changed configuration
+- * items (e.g., open/close sockets, etc.) */
+- radius_client_flush(hapd->radius, 0);
+-#endif /* CONFIG_NO_RADIUS */
+-
+- oldconf = hapd->iconf;
+- hapd->iconf = newconf;
+- hapd->conf = &newconf->bss[0];
+- iface->conf = newconf;
+-
+ if (hostapd_setup_wpa_psk(hapd->conf)) {
+ wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
+ "after reloading configuration");
+@@ -110,10 +81,46 @@ int hostapd_reload_config(struct hostapd
+ wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
+ /* try to continue */
+ }
++ wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
++}
++
++int hostapd_reload_config(struct hostapd_iface *iface)
++{
++ struct hostapd_data *hapd = iface->bss[0];
++ struct hostapd_config *newconf, *oldconf;
++ size_t j;
++
++ if (iface->config_read_cb == NULL)
++ return -1;
++ newconf = iface->config_read_cb(iface->config_fname);
++ if (newconf == NULL)
++ return -1;
++
++ /*
++ * Deauthenticate all stations since the new configuration may not
++ * allow them to use the BSS anymore.
++ */
++ for (j = 0; j < iface->num_bss; j++)
++ hostapd_flush_old_stations(iface->bss[j]);
++
++#ifndef CONFIG_NO_RADIUS
++ /* TODO: update dynamic data based on changed configuration
++ * items (e.g., open/close sockets, etc.) */
++ radius_client_flush(hapd->radius, 0);
++#endif /* CONFIG_NO_RADIUS */
++
++ oldconf = hapd->iconf;
++ iface->conf = newconf;
++
++ for (j = 0; j < iface->num_bss; j++) {
++ hapd = iface->bss[j];
++ hapd->iconf = newconf;
++ hapd->conf = &newconf->bss[j];
++ hostapd_reload_bss(hapd);
++ }
+
+ hostapd_config_free(oldconf);
+
+- wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
+
+ return 0;
+ }
--- /dev/null
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -112,6 +112,10 @@ int hostapd_reload_config(struct hostapd
+ oldconf = hapd->iconf;
+ iface->conf = newconf;
+
++ iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
++ if (iface->current_mode)
++ hostapd_prepare_rates(hapd, iface->current_mode);
++
+ for (j = 0; j < iface->num_bss; j++) {
+ hapd = iface->bss[j];
+ hapd->iconf = newconf;
--- /dev/null
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -1604,23 +1604,41 @@ wpa_driver_nl80211_finish_drv_init(struc
+ }
+
+
+-static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
++static int wpa_driver_nl80211_del_bss_beacon(struct i802_bss *bss)
+ {
++ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+
++ bss->beacon_set = 0;
++
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
+ 0, NL80211_CMD_DEL_BEACON, 0);
+- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+ return send_and_recv_msgs(drv, msg, NULL, NULL);
+ nla_put_failure:
++ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
+
++static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
++{
++ struct i802_bss *bss;
++
++ for (bss = &drv->first_bss; bss; bss = bss->next)
++ wpa_driver_nl80211_del_bss_beacon(bss);
++}
++
++static int wpa_driver_nl80211_stop_ap(void *priv)
++{
++ struct i802_bss *bss = priv;
++
++ wpa_driver_nl80211_del_beacon(bss->drv);
++}
+
+ /**
+ * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
+@@ -5512,4 +5530,5 @@ const struct wpa_driver_ops wpa_driver_n
+ .send_ft_action = nl80211_send_ft_action,
+ .signal_monitor = nl80211_signal_monitor,
+ .send_frame = nl80211_send_frame,
++ .stop_ap = wpa_driver_nl80211_stop_ap,
+ };
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1774,6 +1774,8 @@ struct wpa_driver_ops {
+ */
+ int (*send_frame)(void *priv, const u8 *data, size_t data_len,
+ int encrypt);
++
++ int (*stop_ap)(void *priv);
+ };
+
+
--- /dev/null
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -35,6 +35,7 @@
+ #include "ap/wps_hostapd.h"
+ #include "ap/ctrl_iface_ap.h"
+ #include "ctrl_iface.h"
++#include "config_file.h"
+
+
+ struct wpa_ctrl_dst {
+@@ -45,6 +46,7 @@ struct wpa_ctrl_dst {
+ int errors;
+ };
+
++static char *reload_opts = NULL;
+
+ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ const char *buf, size_t len);
+@@ -315,6 +317,66 @@ static int hostapd_ctrl_iface_wps_oob(st
+ #endif /* CONFIG_WPS_OOB */
+ #endif /* CONFIG_WPS */
+
++static int hostapd_ctrl_iface_set_down(struct hostapd_data *hapd)
++{
++ if (hapd->driver->stop_ap)
++ hapd->driver->stop_ap(hapd->drv_priv);
++ return 0;
++}
++
++static char *get_option(char *opt, char *str)
++{
++ int len = strlen(str);
++
++ if (!strncmp(opt, str, len))
++ return opt + len;
++ else
++ return NULL;
++}
++
++static struct hostapd_config *hostapd_ctrl_iface_config_read(const char *fname)
++{
++ struct hostapd_config *conf;
++ char *opt, *val;
++
++ conf = hostapd_config_read(fname);
++ if (!conf)
++ return NULL;
++
++ for (opt = strtok(reload_opts, " ");
++ opt;
++ opt = strtok(NULL, " ")) {
++
++ if ((val = get_option(opt, "channel=")))
++ conf->channel = atoi(val);
++ else if ((val = get_option(opt, "ht_capab=")))
++ conf->ht_capab = atoi(val);
++ else if ((val = get_option(opt, "ht_capab_mask=")))
++ conf->ht_capab &= atoi(val);
++ else if ((val = get_option(opt, "sec_chan=")))
++ conf->secondary_channel = atoi(val);
++ else if ((val = get_option(opt, "hwmode=")))
++ conf->hw_mode = atoi(val);
++ else if ((val = get_option(opt, "ieee80211n=")))
++ conf->ieee80211n = atoi(val);
++ else
++ break;
++ }
++
++ return conf;
++}
++
++static int hostapd_ctrl_iface_reload(struct hostapd_data *hapd, char *txt)
++{
++ struct hostapd_iface *iface = hapd->iface;
++
++ iface->config_read_cb = hostapd_ctrl_iface_config_read;
++ reload_opts = txt;
++
++ hostapd_reload_config(iface);
++
++ iface->config_read_cb = hostapd_config_read;
++}
+
+ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+@@ -379,6 +441,10 @@ static void hostapd_ctrl_iface_receive(i
+ reply_len += res;
+ }
+ #endif /* CONFIG_NO_RADIUS */
++ } else if (os_strcmp(buf, "DOWN") == 0) {
++ hostapd_ctrl_iface_set_down(hapd);
++ } else if (os_strncmp(buf, "RELOAD ", 7) == 0) {
++ hostapd_ctrl_iface_reload(hapd, buf + 7);
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+ reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
+ reply_size);
--- /dev/null
+--- a/wpa_supplicant/wpa_supplicant_i.h
++++ b/wpa_supplicant/wpa_supplicant_i.h
+@@ -98,6 +98,8 @@ struct wpa_interface {
+ * receiving of EAPOL frames from an additional interface.
+ */
+ const char *bridge_ifname;
++
++ const char *hostapd_ctrl;
+ };
+
+ /**
+@@ -316,6 +318,8 @@ struct wpa_supplicant {
+ #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+ char bridge_ifname[16];
+
++ struct wpa_ctrl *hostapd;
++
+ char *confname;
+ struct wpa_config *conf;
+ int countermeasures;
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -51,6 +51,11 @@ OBJS_p += ../src/utils/wpa_debug.o
+ OBJS_p += ../src/utils/wpabuf.o
+ OBJS_c = wpa_cli.o ../src/common/wpa_ctrl.o
+
++ifdef MULTICALL
++OBJS += ../src/common/wpa_ctrl.o
++CFLAGS += -DMULTICALL
++endif
++
+ -include .config
+ -include $(if $(MULTICALL),../hostapd/.config)
+
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -120,6 +120,55 @@ extern int wpa_debug_show_keys;
+ extern int wpa_debug_timestamp;
+ extern struct wpa_driver_ops *wpa_drivers[];
+
++#ifdef MULTICALL
++static int hostapd_stop(struct wpa_supplicant *wpa_s)
++{
++ const char *cmd = "DOWN";
++ char buf[256];
++ int len = sizeof(buf);
++
++ if (wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL) < 0) {
++ wpa_printf(MSG_ERROR, "\nFailed to stop hostapd AP interfaces\n");
++ return -1;
++ }
++ return 0;
++}
++
++static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
++{
++ char *cmd = NULL;
++ char buf[256];
++ int len = sizeof(buf);
++ int channel, hw_mode;
++ int ret;
++
++ if (!bss)
++ return;
++
++ if (bss->freq < 4000) {
++ hw_mode = HOSTAPD_MODE_IEEE80211G;
++ channel = (bss->freq - 2407) / 5;
++ } else {
++ hw_mode = HOSTAPD_MODE_IEEE80211A;
++ channel = (bss->freq - 5000) / 5;
++ }
++
++ if (asprintf(&cmd, "RELOAD channel=%d sec_chan=0 hw_mode=%d ieee80211n=%d",
++ channel, hw_mode, !!bss->ht_capab) < 0) {
++ return -1;
++ }
++
++ ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
++ free(cmd);
++
++ if (ret < 0) {
++ wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n");
++ return -1;
++ }
++ return 0;
++}
++#endif
++
+ /* Configure default/group WEP keys for static WEP */
+ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+ {
+@@ -548,8 +597,16 @@ void wpa_supplicant_set_state(struct wpa
+ #ifndef IEEE8021X_EAPOL
+ wpa_drv_set_supp_port(wpa_s, 1);
+ #endif
++#ifdef MULTICALL
++ if (wpa_s->hostapd)
++ hostapd_reload(wpa_s, wpa_s->current_bss);
++#endif
+ } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
+ state == WPA_ASSOCIATED) {
++#ifdef MULTICALL
++ if (wpa_s->hostapd)
++ hostapd_stop(wpa_s);
++#endif
+ wpa_s->new_connection = 1;
+ wpa_drv_set_operstate(wpa_s, 0);
+ #ifndef IEEE8021X_EAPOL
+@@ -1957,6 +2014,21 @@ static int wpa_supplicant_init_iface(str
+ os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
+ sizeof(wpa_s->bridge_ifname));
+ }
++#ifdef MULTICALL
++ if (iface->hostapd_ctrl) {
++ char *cmd = "DOWN";
++ char buf[256];
++ int len = sizeof(buf);
++
++ wpa_s->hostapd = wpa_ctrl_open(iface->hostapd_ctrl);
++ if (!wpa_s->hostapd) {
++ wpa_printf(MSG_ERROR, "\nFailed to connect to hostapd\n");
++ return -1;
++ }
++ if (hostapd_stop(wpa_s) < 0)
++ return -1;
++ }
++#endif
+
+ /* RSNA Supplicant Key Management - INITIALIZE */
+ eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
+--- a/wpa_supplicant/bss.c
++++ b/wpa_supplicant/bss.c
+@@ -17,6 +17,7 @@
+ #include "utils/common.h"
+ #include "utils/eloop.h"
+ #include "common/ieee802_11_defs.h"
++#include "common/ieee802_11_common.h"
+ #include "drivers/driver.h"
+ #include "wpa_supplicant_i.h"
+ #include "config.h"
+@@ -89,6 +90,8 @@ struct wpa_bss * wpa_bss_get(struct wpa_
+
+ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src)
+ {
++ struct ieee80211_ht_capabilities *capab;
++ struct ieee802_11_elems elems;
+ os_time_t usec;
+
+ dst->flags = src->flags;
+@@ -101,6 +104,12 @@ static void wpa_bss_copy_res(struct wpa_
+ dst->level = src->level;
+ dst->tsf = src->tsf;
+
++ memset(&elems, 0, sizeof(elems));
++ ieee802_11_parse_elems((u8 *) (src + 1), src->ie_len, &elems, 0);
++ capab = (struct ieee80211_ht_capabilities *) elems.ht_capabilities;
++ if (capab)
++ dst->ht_capab = le_to_host16(capab->ht_capabilities_info);
++
+ os_get_time(&dst->last_update);
+ dst->last_update.sec -= src->age / 1000;
+ usec = (src->age % 1000) * 1000;
+--- a/wpa_supplicant/bss.h
++++ b/wpa_supplicant/bss.h
+@@ -56,6 +56,7 @@ struct wpa_bss {
+ unsigned int flags;
+ u8 bssid[ETH_ALEN];
+ u8 ssid[32];
++ u16 ht_capab;
+ size_t ssid_len;
+ int freq;
+ u16 beacon_int;
+--- a/wpa_supplicant/main.c
++++ b/wpa_supplicant/main.c
+@@ -31,7 +31,7 @@ static void usage(void)
+ "usage:\n"
+ " wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] "
+ "[-g<global ctrl>] \\\n"
+- " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
++ " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-H<hostapd path>]"
+ "[-p<driver_param>] \\\n"
+ " [-b<br_ifname>] [-f<debug file>] \\\n"
+ " [-o<override driver>] [-O<override ctrl>] \\\n"
+@@ -67,6 +67,7 @@ static void usage(void)
+ #endif /* CONFIG_DEBUG_SYSLOG */
+ printf(" -t = include timestamp in debug messages\n"
+ " -h = show this help text\n"
++ " -H = connect to a hostapd instance to manage state changes\n"
+ " -L = show license (GPL and BSD)\n"
+ " -o = override driver parameter for new interfaces\n"
+ " -O = override ctrl_interface parameter for new interfaces\n"
+@@ -143,7 +144,7 @@ int main(int argc, char *argv[])
+ wpa_supplicant_fd_workaround();
+
+ for (;;) {
+- c = getopt(argc, argv, "b:Bc:C:D:df:g:hi:KLNo:O:p:P:qstuvW");
++ c = getopt(argc, argv, "b:Bc:C:D:df:g:hH:i:KLNo:O:p:P:qstuvW");
+ if (c < 0)
+ break;
+ switch (c) {
+@@ -184,6 +185,9 @@ int main(int argc, char *argv[])
+ usage();
+ exitcode = 0;
+ goto out;
++ case 'H':
++ iface->hostapd_ctrl = optarg;
++ break;
+ case 'i':
+ iface->ifname = optarg;
+ break;
--- /dev/null
+From: Jouni Malinen <jouni.malinen@atheros.com>
+Date: Tue, 26 Oct 2010 13:30:28 +0000 (+0300)
+Subject: hostapd: Set operstate UP when initializing AP mode
+X-Git-Url: http://w1.fi/gitweb/gitweb.cgi?p=hostap.git;a=commitdiff_plain;h=e11f5a2cbc333113a3a1cc1aeea7f698c3936ca3
+
+hostapd: Set operstate UP when initializing AP mode
+
+This is needed to avoid problems with other applications setting and
+leaving the interface to IF_OPER_DORMANT state. In AP mode, the interface
+is ready immediately after the keys are set, so we better make sure the
+DORMANT state does not prevent normal operations after that.
+---
+
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -622,6 +622,9 @@ static int hostapd_setup_bss(struct host
+
+ ieee802_11_set_beacon(hapd);
+
++ if (hapd->driver && hapd->driver->set_operstate)
++ hapd->driver->set_operstate(hapd->drv_priv, 1);
++
+ return 0;
+ }
+
+--- a/src/drivers/driver_wext.c
++++ b/src/drivers/driver_wext.c
+@@ -2245,11 +2245,14 @@ int wpa_driver_wext_set_operstate(void *
+ {
+ struct wpa_driver_wext_data *drv = priv;
+
+- wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
+- __func__, drv->operstate, state, state ? "UP" : "DORMANT");
+- drv->operstate = state;
+- return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
+- state ? IF_OPER_UP : IF_OPER_DORMANT);
++ if (drv != NULL)
++ {
++ wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
++ __func__, drv->operstate, state, state ? "UP" : "DORMANT");
++ drv->operstate = state;
++ return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
++ state ? IF_OPER_UP : IF_OPER_DORMANT);
++ }
+ }
+
+
include $(TOPDIR)/rules.mk
PKG_NAME:=iw
-PKG_VERSION:=0.9.19
+PKG_VERSION:=0.9.21
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=http://wireless.kernel.org/download/iw/
-PKG_MD5SUM:=3b88743f9c6ce8a7e2f5fd7d18fdea42
+PKG_MD5SUM:=726db5f1fd6bc316434414770513ef81
PKG_BUILD_DEPENDS:=mac80211
include $(INCLUDE_DIR)/package.mk
LIBS="-lm -lnl-tiny" \
V=1
-ifneq ($(CONFIG_LINUX_2_6),)
- define Package/iw/install
+define Package/iw/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iw $(1)/usr/sbin/
- endef
-endif
+endef
$(eval $(call BuildPackage,iw))
--- /dev/null
+--- a/nl80211.h
++++ b/nl80211.h
+@@ -295,7 +295,9 @@
+ * auth and assoc steps. For this, you need to specify the SSID in a
+ * %NL80211_ATTR_SSID attribute, and can optionally specify the association
+ * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
+- * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
++ * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
++ * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
++ * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
+ * It is also sent as an event, with the BSSID and response IEs when the
+ * connection is established or failed to be established. This can be
+ * determined by the STATUS_CODE attribute.
+@@ -313,8 +315,8 @@
+ * channel for the specified amount of time. This can be used to do
+ * off-channel operations like transmit a Public Action frame and wait for
+ * a response while being associated to an AP on another channel.
+- * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which
+- * radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
++ * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus
++ * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
+ * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
+ * optionally used to specify additional channel parameters.
+ * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
+@@ -385,6 +387,8 @@
+ * of any other interfaces, and other interfaces will again take
+ * precedence when they are used.
+ *
++ * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
++ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+@@ -487,6 +491,7 @@ enum nl80211_commands {
+ NL80211_CMD_NOTIFY_CQM,
+
+ NL80211_CMD_SET_CHANNEL,
++ NL80211_CMD_SET_WDS_PEER,
+
+ /* add new commands above here */
+
+@@ -686,6 +691,15 @@ enum nl80211_commands {
+ * request, the driver will assume that the port is unauthorized until
+ * authorized by user space. Otherwise, port is marked authorized by
+ * default in station mode.
++ * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the
++ * ethertype that will be used for key negotiation. It can be
++ * specified with the associate and connect commands. If it is not
++ * specified, the value defaults to 0x888E (PAE, 802.1X). This
++ * attribute is also used as a flag in the wiphy information to
++ * indicate that protocols other than PAE are supported.
++ * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with
++ * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom
++ * ethertype frames used for key negotiation must not be encrypted.
+ *
+ * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+ * We recommend using nested, driver-specific attributes within this.
+@@ -787,6 +801,11 @@ enum nl80211_commands {
+ * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
+ * for non-automatic settings.
+ *
++ * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
++ * means support for per-station GTKs.
++ *
++ * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS
++ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+ */
+@@ -951,6 +970,13 @@ enum nl80211_attrs {
+ NL80211_ATTR_RX_FRAME_TYPES,
+ NL80211_ATTR_FRAME_TYPE,
+
++ NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
++ NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT,
++
++ NL80211_ATTR_SUPPORT_IBSS_RSN,
++
++ NL80211_ATTR_MCAST_RATE,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+@@ -1006,6 +1032,8 @@ enum nl80211_attrs {
+ * @NL80211_IFTYPE_WDS: wireless distribution interface
+ * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
+ * @NL80211_IFTYPE_MESH_POINT: mesh point
++ * @NL80211_IFTYPE_P2P_CLIENT: P2P client
++ * @NL80211_IFTYPE_P2P_GO: P2P group owner
+ * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+ * @NUM_NL80211_IFTYPES: number of defined interface types
+ *
+@@ -1022,6 +1050,8 @@ enum nl80211_iftype {
+ NL80211_IFTYPE_WDS,
+ NL80211_IFTYPE_MONITOR,
+ NL80211_IFTYPE_MESH_POINT,
++ NL80211_IFTYPE_P2P_CLIENT,
++ NL80211_IFTYPE_P2P_GO,
+
+ /* keep last */
+ NUM_NL80211_IFTYPES,
+@@ -1111,6 +1141,8 @@ enum nl80211_rate_info {
+ * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
+ * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
+ * station)
++ * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
++ * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
+ */
+ enum nl80211_sta_info {
+ __NL80211_STA_INFO_INVALID,
+@@ -1124,6 +1156,8 @@ enum nl80211_sta_info {
+ NL80211_STA_INFO_TX_BITRATE,
+ NL80211_STA_INFO_RX_PACKETS,
+ NL80211_STA_INFO_TX_PACKETS,
++ NL80211_STA_INFO_TX_RETRIES,
++ NL80211_STA_INFO_TX_FAILED,
+
+ /* keep last */
+ __NL80211_STA_INFO_AFTER_LAST,
+@@ -1382,6 +1416,17 @@ enum nl80211_reg_rule_flags {
+ * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
+ * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
++ * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
++ * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
++ * spent on this channel
++ * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
++ * channel was sensed busy (either due to activity or energy detect)
++ * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
++ * channel was sensed busy
++ * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
++ * receiving data
++ * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
++ * transmitting data
+ * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
+ * currently defined
+ * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
+@@ -1390,6 +1435,12 @@ enum nl80211_survey_info {
+ __NL80211_SURVEY_INFO_INVALID,
+ NL80211_SURVEY_INFO_FREQUENCY,
+ NL80211_SURVEY_INFO_NOISE,
++ NL80211_SURVEY_INFO_IN_USE,
++ NL80211_SURVEY_INFO_CHANNEL_TIME,
++ NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
++ NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
++ NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
++ NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
+
+ /* keep last */
+ __NL80211_SURVEY_INFO_AFTER_LAST,
+@@ -1636,11 +1687,14 @@ enum nl80211_auth_type {
+ * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
+ * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
+ * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
++ * @NUM_NL80211_KEYTYPES: number of defined key types
+ */
+ enum nl80211_key_type {
+ NL80211_KEYTYPE_GROUP,
+ NL80211_KEYTYPE_PAIRWISE,
+ NL80211_KEYTYPE_PEERKEY,
++
++ NUM_NL80211_KEYTYPES
+ };
+
+ /**
+@@ -1671,6 +1725,9 @@ enum nl80211_wpa_versions {
+ * CCMP keys, each six bytes in little endian
+ * @NL80211_KEY_DEFAULT: flag indicating default key
+ * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
++ * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
++ * specified the default depends on whether a MAC address was
++ * given with the command using the key or not (u32)
+ * @__NL80211_KEY_AFTER_LAST: internal
+ * @NL80211_KEY_MAX: highest key attribute
+ */
+@@ -1682,6 +1739,7 @@ enum nl80211_key_attributes {
+ NL80211_KEY_SEQ,
+ NL80211_KEY_DEFAULT,
+ NL80211_KEY_DEFAULT_MGMT,
++ NL80211_KEY_TYPE,
+
+ /* keep last */
+ __NL80211_KEY_AFTER_LAST,
+++ /dev/null
---- a/nl80211.h
-+++ b/nl80211.h
-@@ -270,6 +270,35 @@
- * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
- * associated with this wiphy must be down and will follow.
- *
-+ * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified
-+ * channel for the specified amount of time. This can be used to do
-+ * off-channel operations like transmit a Public Action frame and wait for
-+ * a response while being associated to an AP on another channel.
-+ * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which
-+ * radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
-+ * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
-+ * optionally used to specify additional channel parameters.
-+ * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
-+ * to remain on the channel. This command is also used as an event to
-+ * notify when the requested duration starts (it may take a while for the
-+ * driver to schedule this time due to other concurrent needs for the
-+ * radio).
-+ * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
-+ * that will be included with any events pertaining to this request;
-+ * the cookie is also used to cancel the request.
-+ * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a
-+ * pending remain-on-channel duration if the desired operation has been
-+ * completed prior to expiration of the originally requested duration.
-+ * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the
-+ * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to
-+ * uniquely identify the request.
-+ * This command is also used as an event to notify when a requested
-+ * remain-on-channel duration has expired.
-+ *
-+ * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX
-+ * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
-+ * and @NL80211_ATTR_TX_RATES the set of allowed rates.
-+ *
- * @NL80211_CMD_MAX: highest used command number
- * @__NL80211_CMD_AFTER_LAST: internal use
- */
-@@ -349,6 +378,15 @@ enum nl80211_commands {
- NL80211_CMD_GET_SURVEY,
- NL80211_CMD_NEW_SURVEY_RESULTS,
-
-+ NL80211_CMD_SET_PMKSA,
-+ NL80211_CMD_DEL_PMKSA,
-+ NL80211_CMD_FLUSH_PMKSA,
-+
-+ NL80211_CMD_REMAIN_ON_CHANNEL,
-+ NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
-+
-+ NL80211_CMD_SET_TX_BITRATE_MASK,
-+
- /* add new commands above here */
-
- /* used to define NL80211_CMD_MAX below */
-@@ -398,6 +436,8 @@ enum nl80211_commands {
- * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
- * larger than or equal to this use RTS/CTS handshake); allowed range:
- * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32
-+ * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11
-+ * section 7.3.2.9; dot11CoverageClass; u8
- *
- * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
- * @NL80211_ATTR_IFNAME: network interface name
-@@ -598,6 +638,21 @@ enum nl80211_commands {
- * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
- * containing info as possible, see &enum survey_info.
- *
-+ * @NL80211_ATTR_PMKID: PMK material for PMKSA caching.
-+ * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
-+ * cache, a wiphy attribute.
-+ *
-+ * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32.
-+ *
-+ * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects.
-+ *
-+ * @NL80211_ATTR_TX_RATES: Nested set of attributes
-+ * (enum nl80211_tx_rate_attributes) describing TX rates per band. The
-+ * enum nl80211_band value is used as the index (nla_type() of the nested
-+ * data. If a band is not included, it will be configured to allow all
-+ * rates based on negotiated supported rates information. This attribute
-+ * is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
-+ *
- * @NL80211_ATTR_MAX: highest attribute number currently defined
- * @__NL80211_ATTR_AFTER_LAST: internal use
- */
-@@ -732,6 +787,17 @@ enum nl80211_attrs {
-
- NL80211_ATTR_SURVEY_INFO,
-
-+ NL80211_ATTR_PMKID,
-+ NL80211_ATTR_MAX_NUM_PMKIDS,
-+
-+ NL80211_ATTR_DURATION,
-+
-+ NL80211_ATTR_COOKIE,
-+
-+ NL80211_ATTR_WIPHY_COVERAGE_CLASS,
-+
-+ NL80211_ATTR_TX_RATES,
-+
- /* add attributes here, update the policy in nl80211.c */
-
- __NL80211_ATTR_AFTER_LAST,
-@@ -1312,13 +1378,20 @@ enum nl80211_channel_type {
- * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
- * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
- * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
-- * raw information elements from the probe response/beacon (bin)
-+ * raw information elements from the probe response/beacon (bin);
-+ * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
-+ * from a Probe Response frame; otherwise they are from a Beacon frame.
-+ * However, if the driver does not indicate the source of the IEs, these
-+ * IEs may be from either frame subtype.
- * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
- * in mBm (100 * dBm) (s32)
- * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
- * in unspecified units, scaled to 0..100 (u8)
- * @NL80211_BSS_STATUS: status, if this BSS is "used"
- * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
-+ * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information
-+ * elements from a Beacon frame (bin); not present if no Beacon frame has
-+ * yet been received
- * @__NL80211_BSS_AFTER_LAST: internal
- * @NL80211_BSS_MAX: highest BSS attribute
- */
-@@ -1334,6 +1407,7 @@ enum nl80211_bss {
- NL80211_BSS_SIGNAL_UNSPEC,
- NL80211_BSS_STATUS,
- NL80211_BSS_SEEN_MS_AGO,
-+ NL80211_BSS_BEACON_IES,
-
- /* keep last */
- __NL80211_BSS_AFTER_LAST,
-@@ -1431,4 +1505,33 @@ enum nl80211_key_attributes {
- NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
- };
-
-+/**
-+ * enum nl80211_tx_rate_attributes - TX rate set attributes
-+ * @__NL80211_TXRATE_INVALID: invalid
-+ * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection
-+ * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
-+ * 1 = 500 kbps) but without the IE length restriction (at most
-+ * %NL80211_MAX_SUPP_RATES in a single array).
-+ * @__NL80211_TXRATE_AFTER_LAST: internal
-+ * @NL80211_TXRATE_MAX: highest TX rate attribute
-+ */
-+enum nl80211_tx_rate_attributes {
-+ __NL80211_TXRATE_INVALID,
-+ NL80211_TXRATE_LEGACY,
-+
-+ /* keep last */
-+ __NL80211_TXRATE_AFTER_LAST,
-+ NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
-+};
-+
-+/**
-+ * enum nl80211_band - Frequency band
-+ * @NL80211_BAND_2GHZ - 2.4 GHz ISM band
-+ * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz)
-+ */
-+enum nl80211_band {
-+ NL80211_BAND_2GHZ,
-+ NL80211_BAND_5GHZ,
-+};
-+
- #endif /* __LINUX_NL80211_H */
+++ /dev/null
---- a/info.c
-+++ b/info.c
-@@ -156,6 +156,14 @@ static int print_phy_handler(struct nl_m
- printf("\tRTS threshold: %d\n", rts);
- }
-
-+ if (tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
-+ unsigned char coverage;
-+
-+ coverage = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
-+ /* See handle_distance() for an explanation where the '450' comes from */
-+ printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage);
-+ }
-+
- if (!tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES])
- goto commands;
-
---- a/phy.c
-+++ b/phy.c
-@@ -164,3 +164,61 @@ static int handle_netns(struct nl80211_s
- COMMAND(set, netns, "<pid>",
- NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
- "Put this wireless device into a different network namespace");
-+
-+static int handle_coverage(struct nl80211_state *state,
-+ struct nl_cb *cb,
-+ struct nl_msg *msg,
-+ int argc, char **argv)
-+{
-+ unsigned int coverage;
-+
-+ if (argc != 1)
-+ return 1;
-+
-+ coverage = strtoul(argv[0], NULL, 10);
-+ if (coverage > 255)
-+ return 1;
-+
-+ NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
-+
-+ return 0;
-+ nla_put_failure:
-+ return -ENOBUFS;
-+}
-+COMMAND(set, coverage, "<coverage class>",
-+ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
-+ "Set coverage class (1 for every 3 usec of air propagation time).\n"
-+ "Valid values: 0 - 255.");
-+
-+static int handle_distance(struct nl80211_state *state,
-+ struct nl_cb *cb,
-+ struct nl_msg *msg,
-+ int argc, char **argv)
-+{
-+ unsigned int distance, coverage;
-+
-+ if (argc != 1)
-+ return 1;
-+
-+ distance = strtoul(argv[0], NULL, 10);
-+
-+ /*
-+ * Divide double the distance by the speed of light in m/usec (300) to
-+ * get round-trip time in microseconds and then divide the result by
-+ * three to get coverage class as specified in IEEE 802.11-2007 table
-+ * 7-27. Values are rounded upwards.
-+ */
-+ coverage = (distance + 449) / 450;
-+ if (coverage > 255)
-+ return 1;
-+
-+ NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
-+
-+ return 0;
-+ nla_put_failure:
-+ return -ENOBUFS;
-+}
-+COMMAND(set, distance, "<distance>",
-+ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
-+ "Set appropriate coverage class for given link distance in meters.\n"
-+ "Valid values: 0 - 114750");
--- /dev/null
+--- a/survey.c
++++ b/survey.c
+@@ -44,8 +44,9 @@ static int print_survey_handler(struct n
+ }
+
+ if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
+- printf("\tfrequency:\t%u MHz\n",
+- nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]));
++ printf("\tfrequency:\t%u MHz%s\n",
++ nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]),
++ sinfo[NL80211_SURVEY_INFO_IN_USE] ? " [in use]" : "");
+ if (sinfo[NL80211_SURVEY_INFO_NOISE])
+ printf("\tnoise:\t\t%d dBm\n",
+ (int8_t)nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]));
+++ /dev/null
---- a/interface.c
-+++ b/interface.c
-@@ -260,6 +260,27 @@ static int print_iface_handler(struct nl
- printf("%s\tifindex %d\n", indent, nla_get_u32(tb_msg[NL80211_ATTR_IFINDEX]));
- if (tb_msg[NL80211_ATTR_IFTYPE])
- printf("%s\ttype %s\n", indent, iftype_name(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE])));
-+ if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
-+ const char *mode;
-+
-+ if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
-+ switch(nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
-+ case NL80211_CHAN_HT20:
-+ mode = "HT20";
-+ break;
-+ case NL80211_CHAN_HT40PLUS:
-+ mode = "HT40+";
-+ break;
-+ case NL80211_CHAN_HT40MINUS:
-+ mode = "HT40-";
-+ break;
-+ default:
-+ mode = "";
-+ }
-+
-+ printf("%s\tfrequency %d MHz %s\n", indent, nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]), mode);
-+ }
-+
-
- return NL_SKIP;
- }
--- /dev/null
+--- a/survey.c
++++ b/survey.c
+@@ -44,12 +44,27 @@ static int print_survey_handler(struct n
+ }
+
+ if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
+- printf("\tfrequency:\t%u MHz%s\n",
++ printf("\tfrequency:\t\t\t%u MHz%s\n",
+ nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]),
+ sinfo[NL80211_SURVEY_INFO_IN_USE] ? " [in use]" : "");
+ if (sinfo[NL80211_SURVEY_INFO_NOISE])
+- printf("\tnoise:\t\t%d dBm\n",
++ printf("\tnoise:\t\t\t\t%d dBm\n",
+ (int8_t)nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]));
++ if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME])
++ printf("\tchannel active time:\t\t%lld ms\n",
++ (int64_t)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]));
++ if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY])
++ printf("\tchannel busy time:\t\t%lld ms\n",
++ (int64_t)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]));
++ if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY])
++ printf("\textension channel busy time:\t%lld ms\n",
++ (int64_t)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY]));
++ if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX])
++ printf("\tchannel receive time:\t\t%lld ms\n",
++ (int64_t)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]));
++ if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX])
++ printf("\tchannel transmit time:\t\t%lld ms\n",
++ (int64_t)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]));
+ return NL_SKIP;
+ }
+
--- /dev/null
+--- a/ibss.c
++++ b/ibss.c
+@@ -83,6 +83,20 @@ static int join_ibss(struct nl80211_stat
+ argc--;
+ }
+
++ /* multicast rate */
++ if (argc > 1 && strcmp(argv[0], "mcast-rate") == 0) {
++ argv++;
++ argc--;
++
++ rate = strtod(argv[0], &end);
++ if (*end != '\0')
++ return 1;
++
++ NLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, (int) rate * 10);
++ argv++;
++ argc--;
++ }
++
+ if (!argc)
+ return 0;
+
+@@ -109,7 +123,7 @@ COMMAND(ibss, leave, NULL,
+ "Leave the current IBSS cell.");
+ COMMAND(ibss, join,
+ "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] "
+- "[basic-rates <rate in Mbps,rate2,...>] [key d:0:abcde]",
++ "[basic-rates <rate in Mbps,rate2,...>] [mcast-rate <rate in Mbps>] [key d:0:abcde]",
+ NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
+ "Join the IBSS cell with the given SSID, if it doesn't exist create\n"
+ "it on the given frequency. When fixed frequency is requested, don't\n"
PKG_NAME:=mac80211
-PKG_VERSION:=2010-09-14
+PKG_VERSION:=2010-10-19
PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
# http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \
# http://wireless.kernel.org/download/compat-wireless-2.6
-PKG_MD5SUM:=88511287e013ff0f2843b3679f52f335
+PKG_MD5SUM:=3bad1752f0154baa57a4d94774bd2ccf
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_kmod-mac80211 \
CONFIG_PACKAGE_MAC80211_DEBUGFS \
- CONFIG_PACKAGE_ATH9K_USE_MINSTREL \
CONFIG_PACKAGE_ATH_DEBUG \
CONFIG_ATH_USER_REGD \
define KernelPackage/cfg80211
$(call KernelPackage/mac80211/Default)
TITLE:=cfg80211 - wireless configuration API
- DEPENDS+= +wireless-tools +iw @!LINUX_2_6_25 +crda
+ DEPENDS+= +wireless-tools +iw @!LINUX_2_6_25 @!LINUX_2_4 +crda
ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.33)),1)
FILES:= \
$(PKG_BUILD_DIR)/compat/compat.ko \
define KernelPackage/p54-common
$(call KernelPackage/p54/Default)
- DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211
+ DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-crc-ccitt
TITLE+= (COMMON)
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54common.ko
AUTOLOAD:=$(call AutoLoad,30,p54common)
Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
endef
-define KernelPackage/ath9k/config
- menu "Configuration"
- depends PACKAGE_kmod-ath9k
-
- config PACKAGE_ATH9K_USE_MINSTREL
- bool "use the new minstrel_ht rate control for ath9k"
- default y
-
- endmenu
-endef
-
define KernelPackage/carl9170
$(call KernelPackage/mac80211/Default)
TITLE:=Driver for Atheros AR9170 USB sticks
-D__CONFIG_MAC80211_RC_DEFAULT=minstrel \
-DCONFIG_MAC80211_RC_MINSTREL_HT \
$(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \
- $(if $(CONFIG_PACKAGE_ATH9K_USE_MINSTREL),-DATH9K_USE_MINSTREL) \
$(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \
$(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \
$(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \
config_set "$device" vifs "${ap:+$ap }${adhoc:+$adhoc }${sta:+$sta }${monitor:+$monitor }${mesh:+$mesh}"
}
+list_phy_interfaces() {
+ local phy="$1"
+ if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
+ ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
+ else
+ ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
+ fi
+}
disable_mac80211() (
local device="$1"
done
include /lib/network
- for wdev in $(ls /sys/class/ieee80211/${phy}/device/net 2>/dev/null); do
+ for wdev in $(list_phy_interfaces "$phy"); do
[ -f "/var/run/$wdev.pid" ] && kill $(cat /var/run/$wdev.pid) >&/dev/null 2>&1
for pid in `pidof wpa_supplicant`; do
grep "$wdev" /proc/$pid/cmdline >/dev/null && \
local macidx=0
local apidx=0
fixed=""
+ local hostapd_ctrl=""
[ -n "$country" ] && iw reg set "$country"
[ "$channel" = "auto" -o "$channel" = "0" ] || {
config_get mode "$vif" mode
config_get ifname "$vif" ifname
[ "$mode" = "ap" ] || continue
+ hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd-$phy/$ifname}"
mac80211_start_vif "$vif" "$ifname"
done
}
adhoc)
config_get bssid "$vif" bssid
config_get ssid "$vif" ssid
- iw dev "$ifname" ibss join "$ssid" $freq ${fixed:+fixed-freq} $bssid
+ config_get mcast_rate "$vif" mcast_rate
+ local mcval=""
+ [ -n "$mcast_rate" ] && {
+ mcval="$(($mcast_rate / 1000))"
+ mcsub="$(( ($mcast_rate / 100) % 10 ))"
+ [ "$mcsub" -gt 0 ] && mcval="$mcval.$mcsub"
+ }
+ iw dev "$ifname" ibss join "$ssid" $freq ${fixed:+fixed-freq} $bssid ${mcval:+mcast-rate $mcval}
;;
sta)
if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
- wpa_supplicant_setup_vif "$vif" wext || {
+ wpa_supplicant_setup_vif "$vif" nl80211 "${hostapd_ctrl:+-H $hostapd_ctrl}" || {
echo "enable_mac80211($device): Failed to set up wpa_supplicant for interface $ifname" >&2
# make sure this wifi interface won't accidentally stay open without encryption
ifconfig "$ifname" down
list=" list ht_capab"
[ "$(($ht_cap & 1))" -eq 1 ] && append ht_capab "$list LDPC" "$N"
+ [ "$(($ht_cap & 16))" -eq 16 ] && append ht_capab "$list GF" "$N"
[ "$(($ht_cap & 32))" -eq 32 ] && append ht_capab "$list SHORT-GI-20" "$N"
[ "$(($ht_cap & 64))" -eq 64 ] && append ht_capab "$list SHORT-GI-40" "$N"
[ "$(($ht_cap & 128))" -eq 128 ] && append ht_capab "$list TX-STBC" "$N"
--- a/config.mk
+++ b/config.mk
-@@ -297,8 +297,8 @@ endif #CONFIG_SSB
+@@ -300,8 +300,8 @@ endif #CONFIG_SSB
CONFIG_P54_PCI=m
ifeq ($(CONFIG_MAC80211),y)
$(error "ERROR: you have MAC80211 compiled into the kernel, CONFIG_MAC80211=y, as such you cannot replace its mac80211 driver. You need this set to CONFIG_MAC80211=m. If you are using Fedora upgrade your kernel as later version should this set as modular. For further information on Fedora see https://bugzilla.redhat.com/show_bug.cgi?id=470143. If you are using your own kernel recompile it and make mac80211 modular")
-@@ -572,8 +572,8 @@ endif #CONFIG_COMPAT_KERNEL_27
+@@ -585,8 +585,8 @@ endif #CONFIG_COMPAT_KERNEL_27
# We need the backported rfkill module on kernel < 2.6.31.
# In more recent kernel versions use the in kernel rfkill module.
ifdef CONFIG_COMPAT_KERNEL_31
obj-$(CONFIG_COMPAT_NETWORK_MODULES) += drivers/net/
-obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/ssb/ drivers/misc/eeprom/
+obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
- endif
- obj-$(CONFIG_COMPAT_BLUETOOTH) += net/bluetooth/
+ ifeq ($(CONFIG_STAGING_EXCLUDE_BUILD),)
+ obj-$(CONFIG_COMPAT_STAGING) += drivers/staging/ath6kl/
--- a/config.mk
+++ b/config.mk
@@ -9,7 +9,6 @@ ifeq ($(wildcard $(KLIB_BUILD)/.config),
else
include $(KLIB_BUILD)/.config
endif
-@@ -280,21 +279,6 @@ endif #CONFIG_WEXT_PRIV
- endif #CONFIG_WEXT_SPY
+@@ -283,21 +282,6 @@ CONFIG_IPW2200_QOS=y
+ # % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
endif #CONFIG_WIRELESS_EXT
-ifdef CONFIG_SSB
CONFIG_P54_PCI=m
# CONFIG_B44=m
-@@ -474,7 +458,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -485,7 +469,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
ifdef CONFIG_MMC
endif
# mac80211 test driver
-@@ -311,13 +311,13 @@ endif #CONFIG_CRC_ITU_T
+@@ -314,13 +314,13 @@ endif #CONFIG_CRC_ITU_T
CONFIG_MWL8K=m
# Ethernet drivers go here
endif #CONFIG_COMPAT_KERNEL_27
ifdef CONFIG_WIRELESS_EXT
-@@ -372,17 +372,17 @@ CONFIG_ZD1211RW=m
+@@ -371,17 +371,17 @@ CONFIG_ZD1211RW=m
# Note: this depends on CONFIG_USB_NET_RNDIS_HOST and CONFIG_USB_NET_CDCETHER
# it also requires new RNDIS_HOST and CDC_ETHER modules which we add
ifdef CONFIG_COMPAT_KERNEL_29
# enable mesh networking too
CONFIG_MAC80211_MESH=y
-@@ -233,7 +233,7 @@ CONFIG_B43_PCI_AUTOSELECT=y
+@@ -240,7 +240,7 @@ CONFIG_B43_PCI_AUTOSELECT=y
ifdef CONFIG_PCMCIA
CONFIG_B43_PCMCIA=y
endif #CONFIG_PCMCIA
CONFIG_B43_PHY_LP=y
CONFIG_B43_NPHY=y
# CONFIG_B43_FORCE_PIO=y
-@@ -242,7 +242,7 @@ CONFIG_B43_NPHY=y
+@@ -249,7 +249,7 @@ CONFIG_B43_NPHY=y
CONFIG_B43LEGACY=m
CONFIG_B43LEGACY_HWRNG=y
CONFIG_B43LEGACY_PCI_AUTOSELECT=y
# CONFIG_B43LEGACY_DEBUG=y
CONFIG_B43LEGACY_DMA=y
CONFIG_B43LEGACY_PIO=y
-@@ -529,7 +529,7 @@ endif
+@@ -542,7 +542,7 @@ endif
# p54
CONFIG_P54_COMMON=m
void ath_deinit_leds(struct ath_softc *sc)
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
-@@ -871,6 +871,7 @@ static void ath9k_led_brightness_work(st
+@@ -860,6 +860,7 @@ static void ath9k_led_brightness_work(st
}
}
static void ath9k_led_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
-@@ -882,6 +883,7 @@ static void ath9k_led_brightness(struct
+@@ -871,6 +872,7 @@ static void ath9k_led_brightness(struct
ieee80211_queue_delayed_work(priv->hw,
&led->brightness_work, 0);
}
static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
{
-@@ -894,6 +896,7 @@ static void ath9k_led_stop_brightness(st
+@@ -883,6 +885,7 @@ static void ath9k_led_stop_brightness(st
static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
char *trigger)
{
int ret;
led->priv = priv;
-@@ -911,14 +914,19 @@ static int ath9k_register_led(struct ath
+@@ -900,14 +903,19 @@ static int ath9k_register_led(struct ath
INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
return ret;
else
include $(KLIB_BUILD)/.config
endif
-@@ -214,7 +214,7 @@ CONFIG_B43=m
+@@ -221,7 +221,7 @@ CONFIG_B43=m
CONFIG_B43_HWRNG=y
CONFIG_B43_PCI_AUTOSELECT=y
ifdef CONFIG_PCMCIA
--- a/config.mk
+++ b/config.mk
-@@ -441,7 +441,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -452,7 +452,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
ifdef CONFIG_MMC
--- a/config.mk
+++ b/config.mk
-@@ -218,7 +218,7 @@ ifdef CONFIG_PCMCIA
+@@ -225,7 +225,7 @@ ifdef CONFIG_PCMCIA
endif #CONFIG_PCMCIA
# CONFIG_B43_LEDS=y
CONFIG_B43_PHY_LP=y
--- a/config.mk
+++ b/config.mk
-@@ -271,12 +271,12 @@ CONFIG_RTL8180=m
+@@ -274,12 +274,12 @@ CONFIG_RTL8180=m
CONFIG_ADM8211=m
# CONFIG_RT2800PCI_RT30XX=y
# CONFIG_RT2800PCI_RT35XX=y
# CONFIG_RT2800PCI_SOC=y
-@@ -391,7 +391,7 @@ CONFIG_RT2800USB_RT30XX=y
+@@ -402,7 +402,7 @@ CONFIG_RT2800USB_RT30XX=y
CONFIG_RT2800USB_RT35XX=y
CONFIG_RT2800USB_UNKNOWN=y
endif #CONFIG_CRC_CCITT
@@ -112,7 +112,7 @@ CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
# This is the one used by our compat-wireless net/mac80211/rate.c
# in case you have and old kernel which is overriding this to pid.
- CONFIG_COMPAT_MAC80211_RC_DEFAULT=minstrel
+ CONFIG_COMPAT_MAC80211_RC_DEFAULT=minstrel_ht
-CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_PID=y
CONFIG_MAC80211_RC_MINSTREL=y
+++ /dev/null
---- a/drivers/net/wireless/ath/carl9170/main.c
-+++ b/drivers/net/wireless/ath/carl9170/main.c
-@@ -811,16 +811,34 @@ out:
- }
-
- static u64 carl9170_op_prepare_multicast(struct ieee80211_hw *hw,
-- struct netdev_hw_addr_list *mc_list)
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
-+ struct netdev_hw_addr_list *mc_list)
-+#else
-+ int mc_count, struct dev_addr_list *ha)
-+#endif
- {
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
- struct netdev_hw_addr *ha;
-+#else
-+ int i;
-+#endif
- u64 mchash;
-
- /* always get broadcast frames */
- mchash = 1ULL << (0xff >> 2);
-
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
- netdev_hw_addr_list_for_each(ha, mc_list)
- mchash |= 1ULL << (ha->addr[5] >> 2);
-+#else
-+ for (i = 0; i < mc_count; i++) {
-+ if (!ha)
-+ break;
-+
-+ mchash |= 1ULL << (ha->dmi_addr[5] >> 2);
-+ ha = ha->next;
-+ }
-+#endif
-
- return mchash;
- }
--- /dev/null
+--- a/config.mk
++++ b/config.mk
+@@ -204,7 +204,7 @@ CONFIG_ATH9K_COMMON=m
+ # as default once we get minstrel properly tested and blessed by
+ # our systems engineering team. CCK rates also need to be used
+ # for long range considerations.
+-CONFIG_ATH9K_RATE_CONTROL=y
++# CONFIG_ATH9K_RATE_CONTROL=y
+
+
+ CONFIG_COMPAT_IWLWIFI=m
+++ /dev/null
---- a/include/linux/compat-2.6.33.h
-+++ b/include/linux/compat-2.6.33.h
-@@ -98,6 +98,12 @@ int pccard_loop_tuple(struct pcmcia_sock
- #define kfifo_out(a, b, c) __kfifo_get(*a, b, c)
- #define kfifo_len(a) __kfifo_len(*a)
-
-+#define list_for_each_entry_continue_rcu(pos, head, member) \
-+ for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \
-+ prefetch(pos->member.next), &pos->member != (head); \
-+ pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
-+
-+
- #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) */
-
- #endif /* LINUX_26_33_COMPAT_H */
--- a/include/linux/compat-2.6.36.h
+++ b/include/linux/compat-2.6.36.h
-@@ -15,6 +15,8 @@ struct va_format {
-
- #define device_rename(dev, new_name) device_rename(dev, (char *)new_name)
+@@ -56,6 +56,8 @@ static inline int pcmcia_write_config_by
+ return pcmcia_access_configuration_register(p_dev, ®);
+ }
+#define PCI_EEPROM_WIDTH_93C86 8
+
#if 0
extern void usb_poison_urb(struct urb *urb);
#endif
+--- a/config.mk
++++ b/config.mk
+@@ -389,7 +389,7 @@ endif #CONFIG_COMPAT_KERNEL_29
+ # This activates a threading fix for usb urb.
+ # this is mainline commit: b3e670443b7fb8a2d29831b62b44a039c283e351
+ # This fix will be included in some stable releases.
+-CONFIG_COMPAT_USB_URB_THREAD_FIX=y
++# CONFIG_COMPAT_USB_URB_THREAD_FIX=y
+
+ CONFIG_ATH9K_HTC=m
+ # CONFIG_ATH9K_HTC_DEBUGFS=y
+++ /dev/null
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -2574,9 +2574,8 @@ void cfg80211_cqm_rssi_notify(struct net
- wiphy_printk(KERN_NOTICE, wiphy, format, ##args)
- #define wiphy_info(wiphy, format, args...) \
- wiphy_printk(KERN_INFO, wiphy, format, ##args)
--
--int wiphy_debug(const struct wiphy *wiphy, const char *format, ...)
-- __attribute__ ((format (printf, 2, 3)));
-+#define wiphy_debug(wiphy, format, args...) \
-+ wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
-
- #if defined(DEBUG)
- #define wiphy_dbg(wiphy, format, args...) \
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -936,52 +936,3 @@ static void __exit cfg80211_exit(void)
- destroy_workqueue(cfg80211_wq);
- }
- module_exit(cfg80211_exit);
--
--static int ___wiphy_printk(const char *level, const struct wiphy *wiphy,
-- struct va_format *vaf)
--{
-- if (!wiphy)
-- return printk("%s(NULL wiphy *): %pV", level, vaf);
--
-- return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf);
--}
--
--int __wiphy_printk(const char *level, const struct wiphy *wiphy,
-- const char *fmt, ...)
--{
-- struct va_format vaf;
-- va_list args;
-- int r;
--
-- va_start(args, fmt);
--
-- vaf.fmt = fmt;
-- vaf.va = &args;
--
-- r = ___wiphy_printk(level, wiphy, &vaf);
-- va_end(args);
--
-- return r;
--}
--EXPORT_SYMBOL(__wiphy_printk);
--
--#define define_wiphy_printk_level(func, kern_level) \
--int func(const struct wiphy *wiphy, const char *fmt, ...) \
--{ \
-- struct va_format vaf; \
-- va_list args; \
-- int r; \
-- \
-- va_start(args, fmt); \
-- \
-- vaf.fmt = fmt; \
-- vaf.va = &args; \
-- \
-- r = ___wiphy_printk(kern_level, wiphy, &vaf); \
-- va_end(args); \
-- \
-- return r; \
--} \
--EXPORT_SYMBOL(func);
--
--define_wiphy_printk_level(wiphy_debug, KERN_DEBUG);
+++ /dev/null
-[PATCH] mac80211: hoist sta->lock from reorder release timer
-
-The patch "mac80211: AMPDU rx reorder timeout timer" clashes
-with "mac80211: use netif_receive_skb in ieee80211_rx callpath"
-
-The timer itself is part of the station's private struct and
-it gets killed whenever the station is removed. Therefore
-the extra sta->lock protection (that can interferes with the
-tx path) is not necessary.
-
-Reported-by: Ming Lei <tom.leiming@gmail.com>
-Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
----
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_exp
- timer_to_tid[0]);
-
- rcu_read_lock();
-- spin_lock(&sta->lock);
- ieee80211_release_reorder_timeout(sta, *ptid);
-- spin_unlock(&sta->lock);
- rcu_read_unlock();
- }
-
#include <asm/unaligned.h>
#include "hw.h"
-@@ -451,8 +452,16 @@ static int ath9k_hw_init_macaddr(struct
+@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct
common->macaddr[2 * i] = eeval >> 8;
common->macaddr[2 * i + 1] = eeval & 0xff;
}
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
-@@ -18,6 +18,9 @@
- #include <net/cfg80211.h>
- #include <net/mac80211.h>
- #include "regd.h"
-+
-+#ifndef ATH_USER_REGD
-+
- #include "regd_common.h"
+@@ -185,6 +185,10 @@ ath_reg_apply_beaconing_flags(struct wip
+ u32 bandwidth = 0;
+ int r;
- /*
-@@ -587,3 +590,5 @@ u32 ath_regd_get_band_ctl(struct ath_reg
- }
- }
- EXPORT_SYMBOL(ath_regd_get_band_ctl);
-+
++#ifdef ATH_USER_REGD
++ return;
+#endif
---- a/drivers/net/wireless/ath/regd.h
-+++ b/drivers/net/wireless/ath/regd.h
-@@ -249,6 +249,41 @@ enum CountryCode {
- CTRY_BELGIUM2 = 5002
- };
++
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+ if (!wiphy->bands[band])
+@@ -244,6 +248,10 @@ ath_reg_apply_active_scan_flags(struct w
+ u32 bandwidth = 0;
+ int r;
+#ifdef ATH_USER_REGD
++ return;
++#endif
+
-+static inline bool
-+ath_is_world_regd(struct ath_regulatory *reg)
-+{
-+ return true;
-+}
-+
-+static inline int
-+ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
-+ int (*reg_notifier)(struct wiphy *wiphy,
-+ struct regulatory_request *request))
-+{
-+ return 0;
-+}
-+
-+
-+static inline u32
-+ath_regd_get_band_ctl(struct ath_regulatory *reg,
-+ enum ieee80211_band band)
-+{
-+ return SD_NO_CTL;
-+}
+ sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+
+ /*
+@@ -291,6 +299,10 @@ static void ath_reg_apply_radar_flags(st
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++#ifdef ATH_USER_REGD
++ return;
++#endif
+
-+static inline int
-+ath_reg_notifier_apply(struct wiphy *wiphy,
-+ struct regulatory_request *request,
-+ struct ath_regulatory *reg)
-+{
+ if (!wiphy->bands[IEEE80211_BAND_5GHZ])
+ return;
+
+@@ -449,6 +461,10 @@ ath_regd_init_wiphy(struct ath_regulator
+ {
+ const struct ieee80211_regdomain *regd;
+
++#ifdef ATH_USER_REGD
+ return 0;
-+}
-+
-+
-+#else
++#endif
+
- bool ath_is_world_regd(struct ath_regulatory *reg);
- int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
- int (*reg_notifier)(struct wiphy *wiphy,
-@@ -260,3 +295,5 @@ int ath_reg_notifier_apply(struct wiphy
- struct ath_regulatory *reg);
+ wiphy->reg_notifier = reg_notifier;
+ wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
- #endif
-+
-+#endif
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -540,6 +540,7 @@ static int ath9k_init_softc(u16 devid, s
+@@ -559,6 +559,7 @@ static int ath9k_init_softc(u16 devid, s
{
struct ath_hw *ah = NULL;
struct ath_common *common;
int ret = 0, i;
int csz = 0;
-@@ -551,6 +552,10 @@ static int ath9k_init_softc(u16 devid, s
+@@ -570,6 +571,10 @@ static int ath9k_init_softc(u16 devid, s
ah->hw_version.subsysid = subsysid;
sc->sc_ah = ah;
common->bus_ops = bus_ops;
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -422,10 +422,6 @@ static void ath9k_hw_init_defaults(struc
+@@ -420,10 +420,6 @@ static void ath9k_hw_init_defaults(struc
ah->hw_version.magic = AR5416_MAGIC;
ah->hw_version.subvendorid = 0;
#include "hw.h"
#include "hw-ops.h"
#include "rc.h"
-@@ -436,18 +438,23 @@ static void ath9k_hw_init_defaults(struc
+@@ -434,18 +436,23 @@ static void ath9k_hw_init_defaults(struc
static int ath9k_hw_init_macaddr(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1427,7 +1427,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1420,7 +1420,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
if (ah->config.rx_intr_mitigation) {
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
#include "ath9k.h"
static char *dev_info = "ath9k";
-@@ -555,6 +556,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -574,6 +575,8 @@ static int ath9k_init_softc(u16 devid, s
pdata = (struct ath9k_platform_data *) sc->dev->platform_data;
if (!pdata)
ah->ah_flags |= AH_USE_EEPROM;
common = ath9k_hw_common(ah);
common->ops = &ath9k_common_ops;
-@@ -677,6 +680,24 @@ void ath9k_set_hw_capab(struct ath_softc
+@@ -704,6 +707,24 @@ void ath9k_set_hw_capab(struct ath_softc
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
const struct ath_bus_ops *bus_ops)
{
-@@ -695,6 +716,9 @@ int ath9k_init_device(u16 devid, struct
+@@ -723,6 +744,9 @@ int ath9k_init_device(u16 devid, struct
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
ath9k_reg_notifier);
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -643,6 +643,8 @@ struct ath_softc {
+@@ -635,6 +635,8 @@ struct ath_softc {
int beacon_interval;
sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -460,6 +460,7 @@ void ath9k_btcoex_timer_pause(struct ath
+@@ -455,6 +455,7 @@ void ath9k_btcoex_timer_pause(struct ath
#define ATH_LED_PIN_DEF 1
#define ATH_LED_PIN_9287 8
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -861,6 +861,53 @@ static const struct file_operations fops
+ .owner = THIS_MODULE
+ };
+
++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
++ int bytes = 0;
++ int pos = *ppos;
++ int size = 4096;
++ u16 val;
++ int i;
++
++ if (AR_SREV_9300_20_OR_LATER(ah))
++ size = 16384;
++
++ if (*ppos < 0)
++ return -EINVAL;
++
++ if (count > size - *ppos)
++ count = size - *ppos;
++
++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
++ void *from = &val;
++
++ if (!common->bus_ops->eeprom_read(common, i, &val))
++ val = 0xffff;
++
++ if (*ppos % 2) {
++ from++;
++ bytes = 1;
++ } else if (count == 1) {
++ bytes = 1;
++ } else {
++ bytes = 2;
++ }
++ copy_to_user(user_buf, from, bytes);
++ user_buf += bytes;
++ }
++ return *ppos - pos;
++}
++
++static const struct file_operations fops_eeprom = {
++ .read = read_file_eeprom,
++ .open = ath9k_debugfs_open,
++ .owner = THIS_MODULE
++};
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -920,6 +967,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+ sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
+ goto err;
+
++ if (!debugfs_create_file("eeprom", S_IRUSR,
++ sc->debug.debugfs_phy, sc, &fops_eeprom))
++ goto err;
++
+ sc->debug.regidx = 0;
+ return 0;
+ err:
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -661,7 +661,11 @@ void ath9k_set_hw_capab(struct ath_softc
- hw->sta_data_size = sizeof(struct ath_node);
- hw->vif_data_size = sizeof(struct ath_vif);
-
-+#ifdef ATH9K_USE_MINSTREL
-+ hw->rate_control_algorithm = "minstrel_ht";
-+#else
- hw->rate_control_algorithm = "ath9k_rate_control";
-+#endif
-
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -177,8 +177,8 @@ void ath_descdma_cleanup(struct ath_soft
+
+ /* returns delimiter padding required given the packet length */
+ #define ATH_AGGR_GET_NDELIM(_len) \
+- (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
+- (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
++ (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \
++ DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
+
+ #define BAW_WITHIN(_start, _bawsz, _seqno) \
+ ((((_seqno) - (_start)) & 4095) < (_bawsz))
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -254,7 +254,7 @@ struct ath_atx_tid {
- struct list_head buf_q;
- struct ath_node *an;
- struct ath_atx_ac *ac;
-- struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
-+ unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
- u16 seq_start;
- u16 seq_next;
- u16 baw_size;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -168,9 +168,9 @@ static void ath_tx_update_baw(struct ath
- index = ATH_BA_INDEX(tid->seq_start, seqno);
- cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-
-- tid->tx_buf[cindex] = NULL;
-+ __clear_bit(cindex, tid->tx_buf);
-
-- while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
-+ while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
- INCR(tid->seq_start, IEEE80211_SEQ_MAX);
- INCR(tid->baw_head, ATH_TID_MAX_BUFS);
- }
-@@ -186,9 +186,7 @@ static void ath_tx_addto_baw(struct ath_
-
- index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
- cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
--
-- BUG_ON(tid->tx_buf[cindex] != NULL);
-- tid->tx_buf[cindex] = bf;
-+ __set_bit(cindex, tid->tx_buf);
-
- if (index >= ((tid->baw_tail - tid->baw_head) &
- (ATH_TID_MAX_BUFS - 1))) {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -124,7 +124,8 @@ static void ath_tx_resume_tid(struct ath
- {
- struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-
-- WARN_ON(!tid->paused);
-+ if (!tid->paused)
-+ return;
-
- spin_lock_bh(&txq->axq_lock);
- tid->paused = false;
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -2133,6 +2133,7 @@ static void ath9k_hw_ar9300_set_txpower(
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+ {
++ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath_common *common = ath9k_hw_common(ah);
+ u8 targetPowerValT2[ar9300RateSize];
+ unsigned int i = 0;
+@@ -2180,6 +2181,7 @@ static void ath9k_hw_ar9300_set_txpower(
+ i = ALL_TARGET_HT20_0_8_16; /* ht20 */
+
+ ah->txpower_limit = targetPowerValT2[i];
++ regulatory->max_power_level = ratesArray[i];
+
+ ar9003_hw_calibration_apply(ah, chan->channel);
+ }
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -784,17 +784,23 @@ static void ath_tx_sched_aggr(struct ath
- status != ATH_AGGR_BAW_CLOSED);
- }
-
--void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-- u16 tid, u16 *ssn)
-+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-+ u16 tid, u16 *ssn)
- {
- struct ath_atx_tid *txtid;
- struct ath_node *an;
-
- an = (struct ath_node *)sta->drv_priv;
- txtid = ATH_AN_2_TID(an, tid);
-+
-+ if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
-+ return -EAGAIN;
-+
- txtid->state |= AGGR_ADDBA_PROGRESS;
- txtid->paused = true;
- *ssn = txtid->seq_start;
-+
-+ return 0;
- }
-
- void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -346,8 +346,8 @@ void ath_tx_tasklet(struct ath_softc *sc
- void ath_tx_edma_tasklet(struct ath_softc *sc);
- void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
- bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
--void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-- u16 tid, u16 *ssn);
-+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-+ u16 tid, u16 *ssn);
- void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
- void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
- void ath9k_enable_ps(struct ath_softc *sc);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1968,8 +1968,9 @@ static int ath9k_ampdu_action(struct iee
- break;
- case IEEE80211_AMPDU_TX_START:
- ath9k_ps_wakeup(sc);
-- ath_tx_aggr_start(sc, sta, tid, ssn);
-- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-+ ret = ath_tx_aggr_start(sc, sta, tid, ssn);
-+ if (!ret)
-+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
- ath9k_ps_restore(sc);
- break;
- case IEEE80211_AMPDU_TX_STOP:
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/eeprom.h
++++ b/drivers/net/wireless/ath/ath9k/eeprom.h
+@@ -680,7 +680,8 @@ struct eeprom_ops {
+ void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
+ void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+ u16 cfgCtl, u8 twiceAntennaReduction,
+- u8 twiceMaxRegulatoryPower, u8 powerLimit);
++ u8 twiceMaxRegulatoryPower, u8 powerLimit,
++ bool test);
+ u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
+ };
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(stru
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+- u8 powerLimit)
++ u8 powerLimit, bool test)
+ {
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+@@ -751,15 +751,20 @@ static void ath9k_hw_4k_set_txpower(stru
+
+ ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+
++ regulatory->max_power_level = 0;
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
++
++ if (ratesArray[i] > regulatory->max_power_level)
++ regulatory->max_power_level = ratesArray[i];
+ }
+
++ if (test)
++ return;
+
+ /* Update regulatory */
+-
+ i = rate6mb;
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(
+ struct ath9k_channel *chan, u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+- u8 powerLimit)
++ u8 powerLimit, bool test)
+ {
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+@@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(
+
+ ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
+
++ regulatory->max_power_level = 0;
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR9287_MAX_RATE_POWER)
+ ratesArray[i] = AR9287_MAX_RATE_POWER;
++
++ if (ratesArray[i] > regulatory->max_power_level)
++ regulatory->max_power_level = ratesArray[i];
+ }
+
++ if (test)
++ return;
++
++ if (IS_CHAN_2GHZ(chan))
++ i = rate1l;
++ else
++ i = rate6mb;
++
++ regulatory->max_power_level = ratesArray[i];
++
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+@@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+-
+- if (IS_CHAN_2GHZ(chan))
+- i = rate1l;
+- else
+- i = rate6mb;
+-
+- if (AR_SREV_9280_20_OR_LATER(ah))
+- regulatory->max_power_level =
+- ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
+- else
+- regulatory->max_power_level = ratesArray[i];
+ }
+
+ static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(str
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+- u8 powerLimit)
++ u8 powerLimit, bool test)
+ {
+ #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -1285,12 +1285,44 @@ static void ath9k_hw_def_set_txpower(str
+
+ ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+
++ regulatory->max_power_level = 0;
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
++ if (ratesArray[i] > regulatory->max_power_level)
++ regulatory->max_power_level = ratesArray[i];
+ }
+
++ if (!test) {
++ i = rate6mb;
++
++ if (IS_CHAN_HT40(chan))
++ i = rateHt40_0;
++ else if (IS_CHAN_HT20(chan))
++ i = rateHt20_0;
++
++ regulatory->max_power_level = ratesArray[i];
++ }
++
++ switch(ar5416_get_ntxchains(ah->txchainmask)) {
++ case 1:
++ break;
++ case 2:
++ regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
++ break;
++ case 3:
++ regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
++ break;
++ default:
++ ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
++ "Invalid chainmask configuration\n");
++ break;
++ }
++
++ if (test)
++ return;
++
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++) {
+ int8_t pwr_table_offset;
+@@ -1387,34 +1419,6 @@ static void ath9k_hw_def_set_txpower(str
+ REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+ ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+ | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+-
+- i = rate6mb;
+-
+- if (IS_CHAN_HT40(chan))
+- i = rateHt40_0;
+- else if (IS_CHAN_HT20(chan))
+- i = rateHt20_0;
+-
+- if (AR_SREV_9280_20_OR_LATER(ah))
+- regulatory->max_power_level =
+- ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
+- else
+- regulatory->max_power_level = ratesArray[i];
+-
+- switch(ar5416_get_ntxchains(ah->txchainmask)) {
+- case 1:
+- break;
+- case 2:
+- regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+- break;
+- case 3:
+- regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+- break;
+- default:
+- ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
+- "Invalid chainmask configuration\n");
+- break;
+- }
+ }
+
+ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -2131,7 +2131,7 @@ static void ath9k_hw_ar9300_set_txpower(
+ struct ath9k_channel *chan, u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+- u8 powerLimit)
++ u8 powerLimit, bool test)
+ {
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -2145,7 +2145,16 @@ static void ath9k_hw_ar9300_set_txpower(
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+- while (i < ar9300RateSize) {
++ regulatory->max_power_level = 0;
++ for (i = 0; i < ar9300RateSize; i++) {
++ if (targetPowerValT2[i] > regulatory->max_power_level)
++ regulatory->max_power_level = targetPowerValT2[i];
++ }
++
++ if (test)
++ return;
++
++ for (i = 0; i < ar9300RateSize; i++) {
+ ath_print(common, ATH_DBG_EEPROM,
+ "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
+ i++;
+@@ -2160,9 +2169,6 @@ static void ath9k_hw_ar9300_set_txpower(
+ i++;
+ }
+
+- /* Write target power array to registers */
+- ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
+-
+ /*
+ * This is the TX power we send back to driver core,
+ * and it can use to pass to userspace to display our
+@@ -2181,8 +2187,10 @@ static void ath9k_hw_ar9300_set_txpower(
+ i = ALL_TARGET_HT20_0_8_16; /* ht20 */
+
+ ah->txpower_limit = targetPowerValT2[i];
+- regulatory->max_power_level = ratesArray[i];
++ regulatory->max_power_level = targetPowerValT2[i];
+
++ /* Write target power array to registers */
++ ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
+ ar9003_hw_calibration_apply(ah, chan->channel);
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1178,7 +1178,7 @@ static bool ath9k_hw_channel_change(stru
+ channel->max_antenna_gain * 2,
+ channel->max_power * 2,
+ min((u32) MAX_RATE_POWER,
+- (u32) regulatory->power_limit));
++ (u32) regulatory->power_limit), false);
+
+ ath9k_hw_rfbus_done(ah);
+
+@@ -2177,7 +2177,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
+ }
+ EXPORT_SYMBOL(ath9k_hw_disable);
+
+-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
++void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+ {
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath9k_channel *chan = ah->curchan;
+@@ -2190,7 +2190,7 @@ void ath9k_hw_set_txpowerlimit(struct at
+ channel->max_antenna_gain * 2,
+ channel->max_power * 2,
+ min((u32) MAX_RATE_POWER,
+- (u32) regulatory->power_limit));
++ (u32) regulatory->power_limit), test);
+ }
+ EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
+
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -860,7 +860,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *
+ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
+ bool ath9k_hw_phy_disable(struct ath_hw *ah);
+ bool ath9k_hw_disable(struct ath_hw *ah);
+-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
++void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
+ void ath9k_hw_setopmode(struct ath_hw *ah);
+ void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
+ void ath9k_hw_setbssidmask(struct ath_hw *ah);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -24,7 +24,7 @@ static void ath_update_txpow(struct ath_
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (sc->curtxpow != sc->config.txpowlimit) {
+- ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
++ ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+ /* read back in case value is clamped */
+ sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
+ }
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct
+ channel->max_antenna_gain * 2,
+ channel->max_power * 2,
+ min((u32) MAX_RATE_POWER,
+- (u32) regulatory->power_limit));
++ (u32) regulatory->power_limit), false);
+
+ return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -875,7 +875,7 @@ static int ar5008_hw_process_ini(struct
+ channel->max_antenna_gain * 2,
+ channel->max_power * 2,
+ min((u32) MAX_RATE_POWER,
+- (u32) regulatory->power_limit));
++ (u32) regulatory->power_limit), false);
+
+ /* Write analog registers */
+ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9
+ struct ath_hw *ah = priv->ah;
+
+ if (priv->curtxpow != priv->txpowlimit) {
+- ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
++ ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
+ /* read back in case value is clamped */
+ priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
+ }
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath
- struct ath_tx_status *ts, int txok);
- static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
- int nbad, int txok, bool update_rc);
-+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-+ int seqno);
-
- enum {
- MCS_HT20,
-@@ -144,18 +146,23 @@ static void ath_tx_flush_tid(struct ath_
- struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
- struct ath_buf *bf;
- struct list_head bf_head;
-- INIT_LIST_HEAD(&bf_head);
-+ struct ath_tx_status ts;
-
-- WARN_ON(!tid->paused);
-+ INIT_LIST_HEAD(&bf_head);
-
-+ memset(&ts, 0, sizeof(ts));
- spin_lock_bh(&txq->axq_lock);
-- tid->paused = false;
-
- while (!list_empty(&tid->buf_q)) {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-- BUG_ON(bf_isretried(bf));
- list_move_tail(&bf->list, &bf_head);
-- ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
-+
-+ if (bf_isretried(bf)) {
-+ ath_tx_update_baw(sc, tid, bf->bf_seqno);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-+ } else {
-+ ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
-+ }
- }
-
- spin_unlock_bh(&txq->axq_lock);
-@@ -430,7 +437,7 @@ static void ath_tx_complete_aggr(struct
- list_move_tail(&bf->list, &bf_head);
- }
-
-- if (!txpending) {
-+ if (!txpending || (tid->state & AGGR_CLEANUP)) {
- /*
- * complete the acked-ones/xretried ones; update
- * block-ack window
-@@ -451,6 +458,7 @@ static void ath_tx_complete_aggr(struct
- !txfail, sendbar);
- } else {
- /* retry the un-acked ones */
-+
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
- if (bf->bf_next == NULL && bf_last->bf_stale) {
- struct ath_buf *tbf;
-@@ -509,15 +517,12 @@ static void ath_tx_complete_aggr(struct
- }
-
- if (tid->state & AGGR_CLEANUP) {
-+ ath_tx_flush_tid(sc, tid);
-+
- if (tid->baw_head == tid->baw_tail) {
- tid->state &= ~AGGR_ADDBA_COMPLETE;
- tid->state &= ~AGGR_CLEANUP;
--
-- /* send buffered frames as singles */
-- ath_tx_flush_tid(sc, tid);
- }
-- rcu_read_unlock();
-- return;
- }
-
- rcu_read_unlock();
-@@ -808,12 +813,6 @@ void ath_tx_aggr_stop(struct ath_softc *
- struct ath_node *an = (struct ath_node *)sta->drv_priv;
- struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
- struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
-- struct ath_tx_status ts;
-- struct ath_buf *bf;
-- struct list_head bf_head;
--
-- memset(&ts, 0, sizeof(ts));
-- INIT_LIST_HEAD(&bf_head);
-
- if (txtid->state & AGGR_CLEANUP)
- return;
-@@ -823,31 +822,22 @@ void ath_tx_aggr_stop(struct ath_softc *
- return;
- }
-
-- /* drop all software retried frames and mark this TID */
- spin_lock_bh(&txq->axq_lock);
- txtid->paused = true;
-- while (!list_empty(&txtid->buf_q)) {
-- bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
-- if (!bf_isretried(bf)) {
-- /*
-- * NB: it's based on the assumption that
-- * software retried frame will always stay
-- * at the head of software queue.
-- */
-- break;
-- }
-- list_move_tail(&bf->list, &bf_head);
-- ath_tx_update_baw(sc, txtid, bf->bf_seqno);
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-- }
-- spin_unlock_bh(&txq->axq_lock);
-
-- if (txtid->baw_head != txtid->baw_tail) {
-+ /*
-+ * If frames are still being transmitted for this TID, they will be
-+ * cleaned up during tx completion. To prevent race conditions, this
-+ * TID can only be reused after all in-progress subframes have been
-+ * completed.
-+ */
-+ if (txtid->baw_head != txtid->baw_tail)
- txtid->state |= AGGR_CLEANUP;
-- } else {
-+ else
- txtid->state &= ~AGGR_ADDBA_COMPLETE;
-- ath_tx_flush_tid(sc, txtid);
-- }
-+ spin_unlock_bh(&txq->axq_lock);
-+
-+ ath_tx_flush_tid(sc, txtid);
- }
-
- void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -650,6 +650,37 @@ err_hw:
+ return ret;
+ }
+
++static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
++{
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_channel *chan;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++ int i;
++
++ sband = &sc->sbands[band];
++ for (i = 0; i < sband->n_channels; i++) {
++ chan = &sband->channels[i];
++ ah->curchan = &ah->channels[chan->hw_value];
++ ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
++ ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
++ chan->max_power = reg->max_power_level / 2;
++ }
++}
++
++static void ath9k_init_txpower_limits(struct ath_softc *sc)
++{
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath9k_channel *curchan = ah->curchan;
++
++ if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
++ ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
++ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
++ ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
++
++ ah->curchan = curchan;
++}
++
+ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+ {
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+@@ -765,6 +796,8 @@ int ath9k_init_device(u16 devid, struct
+ if (error != 0)
+ goto error_rx;
+
++ ath9k_init_txpower_limits(sc);
++
+ /* Register with mac80211 */
+ error = ieee80211_register_hw(hw);
+ if (error)
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct
+ /*
+ * Update internal channel flags.
+ */
+-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
+- struct ath9k_channel *ichan)
++void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
++ struct ieee80211_channel *chan,
++ enum nl80211_channel_type channel_type)
+ {
+- struct ieee80211_channel *chan = hw->conf.channel;
+- struct ieee80211_conf *conf = &hw->conf;
+-
+ ichan->channel = chan->center_freq;
+ ichan->chan = chan;
+
+@@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ie
+ ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
+ }
+
+- if (conf_is_ht(conf))
+- ichan->chanmode = ath9k_get_extchanmode(chan,
+- conf->channel_type);
++ if (channel_type != NL80211_CHAN_NO_HT)
++ ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
+ }
+ EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
+
+@@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curc
+
+ chan_idx = curchan->hw_value;
+ channel = &ah->channels[chan_idx];
+- ath9k_cmn_update_ichannel(hw, channel);
++ ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
+
+ return channel;
+ }
+--- a/drivers/net/wireless/ath/ath9k/common.h
++++ b/drivers/net/wireless/ath/ath9k/common.h
+@@ -62,8 +62,9 @@ enum ath_stomp_type {
+
+ int ath9k_cmn_padpos(__le16 frame_control);
+ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
+-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
+- struct ath9k_channel *ichan);
++void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
++ struct ieee80211_channel *chan,
++ enum nl80211_channel_type channel_type);
+ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
+ struct ath_hw *ah);
+ int ath9k_cmn_count_streams(unsigned int chainmask, int max);
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -1405,7 +1405,9 @@ static int ath9k_htc_config(struct ieee8
+ ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
+ curchan->center_freq);
+
+- ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
++ ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
++ hw->conf.channel,
++ hw->conf.channel_type);
+
+ if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
+ ath_print(common, ATH_DBG_FATAL,
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -897,6 +897,53 @@ static const struct file_operations fops
- .owner = THIS_MODULE
- };
-
-+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ int bytes = 0;
-+ int pos = *ppos;
-+ int size = 4096;
-+ u16 val;
-+ int i;
-+
-+ if (AR_SREV_9300_20_OR_LATER(ah))
-+ size = 16384;
-+
-+ if (*ppos < 0)
-+ return -EINVAL;
-+
-+ if (count > size - *ppos)
-+ count = size - *ppos;
-+
-+ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
-+ void *from = &val;
-+
-+ if (!common->bus_ops->eeprom_read(common, i, &val))
-+ val = 0xffff;
-+
-+ if (*ppos % 2) {
-+ from++;
-+ bytes = 1;
-+ } else if (count == 1) {
-+ bytes = 1;
-+ } else {
-+ bytes = 2;
-+ }
-+ copy_to_user(user_buf, from, bytes);
-+ user_buf += bytes;
-+ }
-+ return *ppos - pos;
-+}
-+
-+static const struct file_operations fops_eeprom = {
-+ .read = read_file_eeprom,
-+ .open = ath9k_debugfs_open,
-+ .owner = THIS_MODULE
-+};
-+
- int ath9k_init_debug(struct ath_hw *ah)
- {
- struct ath_common *common = ath9k_hw_common(ah);
-@@ -960,6 +1007,10 @@ int ath9k_init_debug(struct ath_hw *ah)
- sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
- goto err;
-
-+ if (!debugfs_create_file("eeprom", S_IRUSR,
-+ sc->debug.debugfs_phy, sc, &fops_eeprom))
-+ goto err;
-+
- sc->debug.regidx = 0;
- return 0;
- err:
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -309,7 +309,6 @@ struct ath_rx {
+ u8 rxotherant;
+ u32 *rxlink;
+ unsigned int rxfilter;
+- spinlock_t rxflushlock;
+ spinlock_t rxbuflock;
+ struct list_head rxbuf;
+ struct ath_descdma rxdma;
+@@ -600,9 +599,9 @@ struct ath_softc {
+ struct ath_hw *sc_ah;
+ void __iomem *mem;
+ int irq;
+- spinlock_t sc_resetlock;
+ spinlock_t sc_serial_rw;
+ spinlock_t sc_pm_lock;
++ spinlock_t sc_pcu_lock;
+ struct mutex mutex;
+ struct work_struct paprd_work;
+ struct work_struct hw_check_work;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -228,6 +228,8 @@ int ath_set_channel(struct ath_softc *sc
+
+ ath9k_ps_wakeup(sc);
+
++ spin_lock_bh(&sc->sc_pcu_lock);
++
+ /*
+ * This is only performed if the channel settings have
+ * actually changed.
+@@ -239,6 +241,7 @@ int ath_set_channel(struct ath_softc *sc
+ */
+ ath9k_hw_disable_interrupts(ah);
+ ath_drain_all_txq(sc, false);
++
+ stopped = ath_stoprecv(sc);
+
+ /* XXX: do not flush receive queue here. We don't want
+@@ -257,18 +260,14 @@ int ath_set_channel(struct ath_softc *sc
+ channel->center_freq, conf_is_ht40(conf),
+ fastcc);
+
+- spin_lock_bh(&sc->sc_resetlock);
+-
+ r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+ if (r) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to reset channel (%u MHz), "
+ "reset status %d\n",
+ channel->center_freq, r);
+- spin_unlock_bh(&sc->sc_resetlock);
+ goto ps_restore;
+ }
+- spin_unlock_bh(&sc->sc_resetlock);
+
+ if (ath_startrecv(sc) != 0) {
+ ath_print(common, ATH_DBG_FATAL,
+@@ -287,6 +286,8 @@ int ath_set_channel(struct ath_softc *sc
+ }
+
+ ps_restore:
++ spin_unlock_bh(&sc->sc_pcu_lock);
++
+ ath9k_ps_restore(sc);
+ return r;
+ }
+@@ -600,6 +601,8 @@ void ath9k_tasklet(unsigned long data)
+ return;
+ }
+
++ spin_lock_bh(&sc->sc_pcu_lock);
++
+ if (!ath9k_hw_check_alive(ah))
+ ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+
+@@ -610,15 +613,12 @@ void ath9k_tasklet(unsigned long data)
+ rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+
+ if (status & rxmask) {
+- spin_lock_bh(&sc->rx.rxflushlock);
+-
+ /* Check for high priority Rx first */
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+ (status & ATH9K_INT_RXHP))
+ ath_rx_tasklet(sc, 0, true);
+
+ ath_rx_tasklet(sc, 0, false);
+- spin_unlock_bh(&sc->rx.rxflushlock);
+ }
+
+ if (status & ATH9K_INT_TX) {
+@@ -644,6 +644,8 @@ void ath9k_tasklet(unsigned long data)
+
+ /* re-enable hardware interrupt */
+ ath9k_hw_enable_interrupts(ah);
++
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ ath9k_ps_restore(sc);
+ }
+
+@@ -871,12 +873,13 @@ void ath_radio_enable(struct ath_softc *
+ int r;
+
+ ath9k_ps_wakeup(sc);
++ spin_lock_bh(&sc->sc_pcu_lock);
++
+ ath9k_hw_configpcipowersave(ah, 0, 0);
+
+ if (!ah->curchan)
+ ah->curchan = ath_get_curchannel(sc, sc->hw);
+
+- spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+ if (r) {
+ ath_print(common, ATH_DBG_FATAL,
+@@ -884,15 +887,14 @@ void ath_radio_enable(struct ath_softc *
+ "reset status %d\n",
+ channel->center_freq, r);
+ }
+- spin_unlock_bh(&sc->sc_resetlock);
+
+ ath_update_txpow(sc);
+ if (ath_startrecv(sc) != 0) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to restart recv logic\n");
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ return;
+ }
+-
+ if (sc->sc_flags & SC_OP_BEACONS)
+ ath_beacon_config(sc, NULL); /* restart beacons */
+
+@@ -905,6 +907,8 @@ void ath_radio_enable(struct ath_softc *
+ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
+
+ ieee80211_wake_queues(hw);
++ spin_unlock_bh(&sc->sc_pcu_lock);
++
+ ath9k_ps_restore(sc);
+ }
+
+@@ -915,6 +919,8 @@ void ath_radio_disable(struct ath_softc
+ int r;
+
+ ath9k_ps_wakeup(sc);
++ spin_lock_bh(&sc->sc_pcu_lock);
++
+ ieee80211_stop_queues(hw);
+
+ /*
+@@ -930,13 +936,13 @@ void ath_radio_disable(struct ath_softc
+ ath9k_hw_disable_interrupts(ah);
+
+ ath_drain_all_txq(sc, false); /* clear pending tx frames */
++
+ ath_stoprecv(sc); /* turn off frame recv */
+ ath_flushrecv(sc); /* flush recv queue */
+
+ if (!ah->curchan)
+ ah->curchan = ath_get_curchannel(sc, hw);
+
+- spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+ if (r) {
+ ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
+@@ -944,11 +950,14 @@ void ath_radio_disable(struct ath_softc
+ "reset status %d\n",
+ channel->center_freq, r);
+ }
+- spin_unlock_bh(&sc->sc_resetlock);
+
+ ath9k_hw_phy_disable(ah);
++
+ ath9k_hw_configpcipowersave(ah, 1, 1);
++
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ ath9k_ps_restore(sc);
++
+ ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
+ }
+
+@@ -962,19 +971,20 @@ int ath_reset(struct ath_softc *sc, bool
+ /* Stop ANI */
+ del_timer_sync(&common->ani.timer);
+
++ spin_lock_bh(&sc->sc_pcu_lock);
++
+ ieee80211_stop_queues(hw);
+
+ ath9k_hw_disable_interrupts(ah);
+ ath_drain_all_txq(sc, retry_tx);
++
+ ath_stoprecv(sc);
+ ath_flushrecv(sc);
+
+- spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
+ if (r)
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to reset hardware; reset status %d\n", r);
+- spin_unlock_bh(&sc->sc_resetlock);
+
+ if (ath_startrecv(sc) != 0)
+ ath_print(common, ATH_DBG_FATAL,
+@@ -1004,6 +1014,7 @@ int ath_reset(struct ath_softc *sc, bool
+ }
+
+ ieee80211_wake_queues(hw);
++ spin_unlock_bh(&sc->sc_pcu_lock);
+
+ /* Start ANI */
+ ath_start_ani(common);
+@@ -1142,17 +1153,16 @@ static int ath9k_start(struct ieee80211_
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+- spin_lock_bh(&sc->sc_resetlock);
++ spin_lock_bh(&sc->sc_pcu_lock);
+ r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
+ if (r) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to reset hardware; reset status %d "
+ "(freq %u MHz)\n", r,
+ curchan->center_freq);
+- spin_unlock_bh(&sc->sc_resetlock);
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ goto mutex_unlock;
+ }
+- spin_unlock_bh(&sc->sc_resetlock);
+
+ /*
+ * This is needed only to setup initial state
+@@ -1171,8 +1181,10 @@ static int ath9k_start(struct ieee80211_
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to start recv logic\n");
+ r = -EIO;
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ goto mutex_unlock;
+ }
++ spin_unlock_bh(&sc->sc_pcu_lock);
+
+ /* Setup our intr mask. */
+ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
+@@ -1367,6 +1379,8 @@ static void ath9k_stop(struct ieee80211_
+ ath9k_btcoex_timer_pause(sc);
+ }
+
++ spin_lock_bh(&sc->sc_pcu_lock);
++
+ /* make sure h/w will not generate any interrupt
+ * before setting the invalid flag. */
+ ath9k_hw_disable_interrupts(ah);
+@@ -1381,6 +1395,9 @@ static void ath9k_stop(struct ieee80211_
+ /* disable HAL and put h/w to sleep */
+ ath9k_hw_disable(ah);
+ ath9k_hw_configpcipowersave(ah, 1, 1);
++
++ spin_unlock_bh(&sc->sc_pcu_lock);
++
+ ath9k_ps_restore(sc);
+
+ /* Finally, put the chip in FULL SLEEP mode */
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct a
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
+ sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
+
+- spin_unlock_bh(&sc->rx.rxbuflock);
+-
+ ath_opmode_init(sc);
+
+ ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
++
++ spin_unlock_bh(&sc->rx.rxbuflock);
+ }
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.rxbuflock);
+ ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
+ ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
+- spin_unlock_bh(&sc->rx.rxbuflock);
+ }
+
+ int ath_rx_init(struct ath_softc *sc, int nbufs)
+@@ -319,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, in
+ struct ath_buf *bf;
+ int error = 0;
+
+- spin_lock_init(&sc->rx.rxflushlock);
++ spin_lock_init(&sc->sc_pcu_lock);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+ spin_lock_init(&sc->rx.rxbuflock);
+
+@@ -506,9 +504,9 @@ int ath_startrecv(struct ath_softc *sc)
+ ath9k_hw_rxena(ah);
+
+ start_recv:
+- spin_unlock_bh(&sc->rx.rxbuflock);
+ ath_opmode_init(sc);
+ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
++ spin_unlock_bh(&sc->rx.rxbuflock);
+
+ return 0;
+ }
+@@ -518,6 +516,7 @@ bool ath_stoprecv(struct ath_softc *sc)
+ struct ath_hw *ah = sc->sc_ah;
+ bool stopped;
+
++ spin_lock_bh(&sc->rx.rxbuflock);
+ ath9k_hw_stoppcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ stopped = ath9k_hw_stopdmarecv(ah);
+@@ -526,19 +525,18 @@ bool ath_stoprecv(struct ath_softc *sc)
+ ath_edma_stop_recv(sc);
+ else
+ sc->rx.rxlink = NULL;
++ spin_unlock_bh(&sc->rx.rxbuflock);
+
+ return stopped;
+ }
+
+ void ath_flushrecv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.rxflushlock);
+ sc->sc_flags |= SC_OP_RXFLUSH;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+- spin_unlock_bh(&sc->rx.rxflushlock);
+ }
+
+ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -588,7 +588,6 @@ static int ath9k_init_softc(u16 devid, s
+ spin_lock_init(&common->cc_lock);
+
+ spin_lock_init(&sc->wiphy_lock);
+- spin_lock_init(&sc->sc_resetlock);
+ spin_lock_init(&sc->sc_serial_rw);
+ spin_lock_init(&sc->sc_pm_lock);
+ mutex_init(&sc->mutex);
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1142,13 +1142,11 @@ void ath_drain_all_txq(struct ath_softc
+ ath_print(common, ATH_DBG_FATAL,
+ "Failed to stop TX DMA. Resetting hardware!\n");
+
+- spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
+ if (r)
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to reset hardware; reset status %d\n",
+ r);
+- spin_unlock_bh(&sc->sc_resetlock);
+ }
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -183,6 +183,9 @@ static void ath_update_survey_stats(stru
+ struct ath_cycle_counters *cc = &common->cc_survey;
+ unsigned int div = common->clockrate * 1000;
+
++ if (!ah->curchan)
++ return;
++
+ if (ah->power_mode == ATH9K_PM_AWAKE)
+ ath_hw_cycle_counters_update(common);
+
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -57,7 +57,7 @@ MODULE_PARM_DESC(blink, "Enable LED blin
- * on 5 MHz steps, we support the channels which we know
- * we have calibration data for all cards though to make
- * this static */
--static struct ieee80211_channel ath9k_2ghz_chantable[] = {
-+static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
- CHAN2G(2412, 0), /* Channel 1 */
- CHAN2G(2417, 1), /* Channel 2 */
- CHAN2G(2422, 2), /* Channel 3 */
-@@ -78,7 +78,7 @@ static struct ieee80211_channel ath9k_2g
- * on 5 MHz steps, we support the channels which we know
- * we have calibration data for all cards though to make
- * this static */
--static struct ieee80211_channel ath9k_5ghz_chantable[] = {
-+static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
- /* _We_ call this UNII 1 */
- CHAN5G(5180, 14), /* Channel 36 */
- CHAN5G(5200, 15), /* Channel 40 */
-@@ -478,10 +478,17 @@ err:
- return -EIO;
- }
-
--static void ath9k_init_channels_rates(struct ath_softc *sc)
-+static int ath9k_init_channels_rates(struct ath_softc *sc)
- {
-+ void *channels;
-+
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
-- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
-+ channels = kmemdup(ath9k_2ghz_chantable,
-+ sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
-+ if (!channels)
-+ return -ENOMEM;
-+
-+ sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
- sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
- sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
- ARRAY_SIZE(ath9k_2ghz_chantable);
-@@ -491,7 +498,15 @@ static void ath9k_init_channels_rates(st
- }
-
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
-- sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
-+ channels = kmemdup(ath9k_5ghz_chantable,
-+ sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
-+ if (!channels) {
-+ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
-+ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
-+ return -ENOMEM;
-+ }
-+
-+ sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
- sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
- sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
- ARRAY_SIZE(ath9k_5ghz_chantable);
-@@ -500,6 +515,7 @@ static void ath9k_init_channels_rates(st
- sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
- ARRAY_SIZE(ath9k_legacy_rates) - 4;
- }
-+ return 0;
- }
-
- static void ath9k_init_misc(struct ath_softc *sc)
-@@ -603,8 +619,11 @@ static int ath9k_init_softc(u16 devid, s
- if (ret)
- goto err_btcoex;
-
-+ ret = ath9k_init_channels_rates(sc);
-+ if (ret)
-+ goto err_btcoex;
-+
- ath9k_init_crypto(sc);
-- ath9k_init_channels_rates(sc);
- ath9k_init_misc(sc);
-
- return 0;
-@@ -786,6 +805,12 @@ static void ath9k_deinit_softc(struct at
- {
- int i = 0;
-
-+ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
-+ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
-+
-+ if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
-+ kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
-+
- if ((sc->btcoex.no_stomp_timer) &&
- sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
- ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -544,7 +544,7 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(
- if (conf_is_ht40(conf))
- return clockrate * 2;
-
-- return clockrate * 2;
-+ return clockrate;
- }
-
- static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -237,13 +237,15 @@ static int ar9002_hw_proc_txdesc(struct
+ status = ACCESS_ONCE(ads->ds_txstatus1);
+ if (status & AR_FrmXmitOK)
+ ts->ts_status |= ATH9K_TX_ACKED;
+- if (status & AR_ExcessiveRetries)
+- ts->ts_status |= ATH9K_TXERR_XRETRY;
+- if (status & AR_Filtered)
+- ts->ts_status |= ATH9K_TXERR_FILT;
+- if (status & AR_FIFOUnderrun) {
+- ts->ts_status |= ATH9K_TXERR_FIFO;
+- ath9k_hw_updatetxtriglevel(ah, true);
++ else {
++ if (status & AR_ExcessiveRetries)
++ ts->ts_status |= ATH9K_TXERR_XRETRY;
++ if (status & AR_Filtered)
++ ts->ts_status |= ATH9K_TXERR_FILT;
++ if (status & AR_FIFOUnderrun) {
++ ts->ts_status |= ATH9K_TXERR_FIFO;
++ ath9k_hw_updatetxtriglevel(ah, true);
++ }
+ }
+ if (status & AR_TxTimerExpired)
+ ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -673,6 +673,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ u16 aggr_limit = 0, al = 0, bpad = 0,
+ al_delta, h_baw = tid->baw_size / 2;
+ enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
++ struct ieee80211_tx_info *tx_info;
+
+ bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
+
+@@ -699,6 +700,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ break;
+ }
+
++ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
++ if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
++ !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
++ break;
++
+ /* do not exceed subframe limit */
+ if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
+ status = ATH_AGGR_LIMITED;
--- /dev/null
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -506,7 +506,9 @@ minstrel_ht_set_rate(struct minstrel_pri
+ if (!mr->retry_updated)
+ minstrel_calc_retransmit(mp, mi, index);
+
+- if (mr->probability < MINSTREL_FRAC(20, 100))
++ if (sample)
++ rate->count = 1;
++ else if (mr->probability < MINSTREL_FRAC(20, 100))
+ rate->count = 2;
+ else if (rtscts)
+ rate->count = mr->retry_count_rtscts;
--- /dev/null
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -407,8 +407,8 @@ minstrel_ht_tx_status(void *priv, struct
+ mi->ampdu_len += info->status.ampdu_len;
+
+ if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
+- mi->sample_wait = 4 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
+- mi->sample_tries = 3;
++ mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
++ mi->sample_tries = 2;
+ mi->sample_count--;
+ }
+
+@@ -564,7 +564,7 @@ minstrel_get_sample_rate(struct minstrel
+ */
+ if (minstrel_get_duration(sample_idx) >
+ minstrel_get_duration(mi->max_tp_rate)) {
+- if (mr->sample_skipped < 10)
++ if (mr->sample_skipped < 20)
+ goto next;
+
+ if (mi->sample_slow++ > 2)
+@@ -588,6 +588,7 @@ minstrel_ht_get_rate(void *priv, struct
+ struct minstrel_ht_sta *mi = &msp->ht;
+ struct minstrel_priv *mp = priv;
+ int sample_idx;
++ bool sample = false;
+
+ if (rate_control_send_low(sta, priv_sta, txrc))
+ return;
+@@ -598,10 +599,11 @@ minstrel_ht_get_rate(void *priv, struct
+ info->flags |= mi->tx_flags;
+ sample_idx = minstrel_get_sample_rate(mp, mi);
+ if (sample_idx >= 0) {
++ sample = true;
+ minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
+ txrc, true, false);
+ minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
+- txrc, false, true);
++ txrc, false, false);
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ } else {
+ minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
+@@ -609,7 +611,7 @@ minstrel_ht_get_rate(void *priv, struct
+ minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
+ txrc, false, true);
+ }
+- minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, true);
++ minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, !sample);
+
+ ar[3].count = 0;
+ ar[3].idx = -1;
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -581,7 +581,7 @@ void ath_hw_check(struct work_struct *wo
+
+ msleep(1);
+ }
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+
+ out:
+ ath9k_ps_restore(sc);
+@@ -599,7 +599,7 @@ void ath9k_tasklet(unsigned long data)
+ ath9k_ps_wakeup(sc);
+
+ if (status & ATH9K_INT_FATAL) {
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ ath9k_ps_restore(sc);
+ return;
+ }
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2161,7 +2161,7 @@ static void ath_tx_complete_poll_work(st
+ ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+ "tx hung, resetting the chip\n");
+ ath9k_ps_wakeup(sc);
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ ath9k_ps_restore(sc);
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -370,7 +370,7 @@ void ath_beacon_tasklet(unsigned long da
+ ath_print(common, ATH_DBG_BSTUCK,
+ "beacon is officially stuck\n");
+ sc->sc_flags |= SC_OP_TSF_RESET;
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ }
+
+ return;
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1089,15 +1089,6 @@ void ath_draintxq(struct ath_softc *sc,
+ txq->axq_tx_inprogress = false;
+ spin_unlock_bh(&txq->axq_lock);
+
+- /* flush any pending frames if aggregation is enabled */
+- if (sc->sc_flags & SC_OP_TXAGGR) {
+- if (!retry_tx) {
+- spin_lock_bh(&txq->axq_lock);
+- ath_txq_drain_pending_buffers(sc, txq);
+- spin_unlock_bh(&txq->axq_lock);
+- }
+- }
+-
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(&txq->txq_fifo_pending)) {
+@@ -1118,6 +1109,15 @@ void ath_draintxq(struct ath_softc *sc,
+ }
+ spin_unlock_bh(&txq->axq_lock);
+ }
++
++ /* flush any pending frames if aggregation is enabled */
++ if (sc->sc_flags & SC_OP_TXAGGR) {
++ if (!retry_tx) {
++ spin_lock_bh(&txq->axq_lock);
++ ath_txq_drain_pending_buffers(sc, txq);
++ spin_unlock_bh(&txq->axq_lock);
++ }
++ }
+ }
+
+ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
--- /dev/null
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -804,6 +804,8 @@ enum nl80211_commands {
+ * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
+ * means support for per-station GTKs.
+ *
++ * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS
++ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+ */
+@@ -973,6 +975,8 @@ enum nl80211_attrs {
+
+ NL80211_ATTR_SUPPORT_IBSS_RSN,
+
++ NL80211_ATTR_MCAST_RATE,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -924,6 +924,7 @@ struct cfg80211_disassoc_request {
+ * @privacy: this is a protected network, keys will be configured
+ * after joining
+ * @basic_rates: bitmap of basic rates to use when creating the IBSS
++ * @mcast_rate: multicast tx rate (in 100 kbps)
+ */
+ struct cfg80211_ibss_params {
+ u8 *ssid;
+@@ -935,6 +936,7 @@ struct cfg80211_ibss_params {
+ u32 basic_rates;
+ bool channel_fixed;
+ bool privacy;
++ int mcast_rate;
+ };
+
+ /**
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -167,6 +167,7 @@ static const struct nla_policy nl80211_p
+ [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
+ [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
+ [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
++ [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
+ };
+
+ /* policy for the key attributes */
+@@ -3652,6 +3653,9 @@ static int nl80211_join_ibss(struct sk_b
+ return -EINVAL;
+ }
+ }
++ if (info->attrs[NL80211_ATTR_MCAST_RATE])
++ ibss.mcast_rate =
++ nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
+
+ if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
+ connkeys = nl80211_parse_connkeys(rdev,
--- /dev/null
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -914,6 +914,7 @@ int ieee80211_ibss_join(struct ieee80211
+
+ sdata->u.ibss.privacy = params->privacy;
+ sdata->u.ibss.basic_rates = params->basic_rates;
++ sdata->vif.bss_conf.mcast_rate = params->mcast_rate;
+
+ sdata->vif.bss_conf.beacon_int = params->beacon_interval;
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -244,6 +244,7 @@ struct ieee80211_bss_conf {
+ u16 assoc_capability;
+ u64 timestamp;
+ u32 basic_rates;
++ u32 mcast_rate;
+ u16 ht_operation_mode;
+ s32 cqm_rssi_thold;
+ u32 cqm_rssi_hyst;
+@@ -2644,7 +2645,7 @@ enum rate_control_changed {
+ * @rate_idx_mask: user-requested rate mask (not MCS for now)
+ * @skb: the skb that will be transmitted, the control information in it needs
+ * to be filled in
+- * @ap: whether this frame is sent out in AP mode
++ * @bss: whether this frame is sent out in AP or IBSS mode
+ */
+ struct ieee80211_tx_rate_control {
+ struct ieee80211_hw *hw;
+@@ -2655,7 +2656,7 @@ struct ieee80211_tx_rate_control {
+ bool rts, short_preamble;
+ u8 max_rate_idx;
+ u32 rate_idx_mask;
+- bool ap;
++ bool bss;
+ };
+
+ struct rate_control_ops {
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -210,10 +210,20 @@ static bool rc_no_data_or_no_ack(struct
+ return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc));
+ }
+
+-static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx)
++static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u32 mcast_rate,
++ struct ieee80211_supported_band *sband)
+ {
+ u8 i;
+
++ if (mcast_rate) {
++ for (i = 0; i < sband->n_bitrates; i++) {
++ if (sband->bitrates[i].bitrate == mcast_rate) {
++ *idx = i;
++ return;
++ }
++ }
++ }
++
+ if (basic_rates == 0)
+ return; /* assume basic rates unknown and accept rate */
+ if (*idx < 0)
+@@ -221,7 +231,7 @@ static void rc_send_low_broadcast(s8 *id
+ if (basic_rates & (1 << *idx))
+ return; /* selected rate is a basic rate */
+
+- for (i = *idx + 1; i <= max_rate_idx; i++) {
++ for (i = *idx + 1; i <= sband->n_bitrates; i++) {
+ if (basic_rates & (1 << i)) {
+ *idx = i;
+ return;
+@@ -242,10 +252,11 @@ bool rate_control_send_low(struct ieee80
+ info->control.rates[0].count =
+ (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
+ 1 : txrc->hw->max_rate_tries;
+- if (!sta && txrc->ap)
++ if (!sta && txrc->bss)
+ rc_send_low_broadcast(&info->control.rates[0].idx,
+ txrc->bss_conf->basic_rates,
+- txrc->sband->n_bitrates);
++ txrc->bss_conf->mcast_rate,
++ txrc->sband);
+ return true;
+ }
+ return false;
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -622,7 +622,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
+ txrc.max_rate_idx = -1;
+ else
+ txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+- txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP;
++ txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
++ tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
+
+ /* set up RTS protection if desired */
+ if (len > tx->local->hw.wiphy->rts_threshold) {
+@@ -2312,7 +2313,7 @@ struct sk_buff *ieee80211_beacon_get_tim
+ txrc.max_rate_idx = -1;
+ else
+ txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+- txrc.ap = true;
++ txrc.bss = true;
+ rate_control_get_rate(sdata, NULL, &txrc);
+
+ info->control.vif = vif;
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
-@@ -585,6 +585,10 @@ static void rt2800pci_kill_tx_queue(stru
+@@ -593,6 +593,10 @@ static void rt2800pci_kill_tx_queue(stru
return;
}
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
-@@ -704,6 +704,7 @@ struct b43_wldev {
+@@ -705,6 +705,7 @@ struct b43_wldev {
bool qos_enabled; /* TRUE, if QoS is used. */
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
bool use_pio; /* TRUE if next init should use PIO */
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
-@@ -12,7 +12,7 @@ b43-y += xmit.o
+@@ -14,7 +14,7 @@ b43-y += xmit.o
b43-y += lo.o
b43-y += wa.o
b43-y += dma.o
+++ /dev/null
-diff --git a/include/linux/compat-2.6.31.h b/include/linux/compat-2.6.31.h
-index 54ddefd..6c454cb 100644
---- a/include/linux/compat-2.6.31.h
-+++ b/include/linux/compat-2.6.31.h
-@@ -191,6 +191,17 @@ void compat_synchronize_threaded_irq(struct compat_threaded_irq *comp)
- cancel_work_sync(&comp->work);
- }
-
-+/**
-+ * list_entry_rcu - get the struct for this entry
-+ * @ptr: the &struct list_head pointer.
-+ * @type: the type of the struct this is embedded in.
-+ * @member: the name of the list_struct within the struct.
-+ *
-+ * This primitive may safely run concurrently with the _rcu list-mutation
-+ * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
-+ */
-+#define list_entry_rcu(ptr, type, member) \
-+ container_of(rcu_dereference(ptr), type, member)
-
- #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) */
-
-diff --git a/include/linux/compat-2.6.33.h b/include/linux/compat-2.6.33.h
-index e4dff72..e7e20d9 100644
---- a/include/linux/compat-2.6.33.h
-+++ b/include/linux/compat-2.6.33.h
-@@ -98,6 +98,20 @@ int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
- #define kfifo_out(a, b, c) __kfifo_get(*a, b, c)
- #define kfifo_len(a) __kfifo_len(*a)
-
-+/**
-+ * list_for_each_entry_continue_rcu - continue iteration over list of given type
-+ * @pos: the type * to use as a loop cursor.
-+ * @head: the head for your list.
-+ * @member: the name of the list_struct within the struct.
-+ *
-+ * Continue to iterate over list of given type, continuing after
-+ * the current position.
-+ */
-+#define list_for_each_entry_continue_rcu(pos, head, member) \
-+ for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \
-+ prefetch(pos->member.next), &pos->member != (head); \
-+ pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
-+
- #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) */
-
- #endif /* LINUX_26_33_COMPAT_H */
--- /dev/null
+--- a/scripts/admin-clean.sh
++++ b/scripts/admin-clean.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ if [ -d net ] ; then
+ make clean
+ fi
+--- a/scripts/admin-refresh.sh
++++ b/scripts/admin-refresh.sh
+@@ -1,3 +1,3 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ ./scripts/admin-clean.sh $@
+ ./scripts/admin-update.sh $@
+--- a/scripts/admin-update.sh
++++ b/scripts/admin-update.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright 2007, 2008, 2010 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+--- a/scripts/athenable
++++ b/scripts/athenable
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+--- a/scripts/athload
++++ b/scripts/athload
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+ # Loads ath5k or madwifi
+--- a/scripts/b43enable
++++ b/scripts/b43enable
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+--- a/scripts/b43load
++++ b/scripts/b43load
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+ # Loads new broadcom drivers (b43 and b43legacy) or the old ones (bcm43xx)
+--- a/scripts/btload.sh
++++ b/scripts/btload.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ MODULES="bluetooth btusb l2cap sco hidp rfcomm bnep"
+ for i in $MODULES; do
+ echo Loading $i...
+--- a/scripts/btunload.sh
++++ b/scripts/btunload.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ MODULES="hidp rfcomm bnep l2cap sco btusb bluetooth"
+ echo Stoping bluetooth service..
+ /etc/init.d/bluetooth stop
+--- a/scripts/check_config.sh
++++ b/scripts/check_config.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # This script checks the compat-wireless configuration file and if changes were made
+ # regenerates the compat_autoconf header.
+
+--- a/scripts/check_depmod
++++ b/scripts/check_depmod
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2009 Luis R. Rodriguez <mcgrof@gmail.com>
+ #
+ # Ensures your distribution likes to prefer updates/ over the kernel/
+--- a/scripts/compress_modules
++++ b/scripts/compress_modules
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # To be used by distributions using compressed modules
+
+ COMPRESSION_FOUND="n"
+--- a/scripts/driver-select
++++ b/scripts/driver-select
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2009 Luis R. Rodriguez <mcgrof@gmail.com>
+ #
+ # This script allows you to select your compat-wireless driver and
+--- a/scripts/gen-compat-autoconf.sh
++++ b/scripts/gen-compat-autoconf.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+--- a/scripts/gen-stable-release.sh
++++ b/scripts/gen-stable-release.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2009 Luis R. Rodriguez <mcgrof@gmail.com>
+ #
+ # You can use this to make stable compat-wireless releases
+--- a/scripts/iwl-enable
++++ b/scripts/iwl-enable
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright 2007 Luis R. Rodriguez <lrodriguez@atheros.com>
+ #
+--- a/scripts/iwl-load
++++ b/scripts/iwl-load
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2008 Luis R. Rodriguez <lrodriguez@atheros.com>
+ #
+ # Loads new Intel iwl (iwlagn) or the old ones (iwl4965)
+--- a/scripts/load.sh
++++ b/scripts/load.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ MODULES="ipw2100 ipw2200 libertas_cs usb8xxx"
+ MODULES="$MODULES p54pci p54usb"
+ MODULES="$MODULES adm8211 zd1211rw"
+--- a/scripts/modlib.sh
++++ b/scripts/modlib.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ #
+--- a/scripts/skip-colors
++++ b/scripts/skip-colors
+@@ -1,2 +1,2 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ perl -pe 's|(\e)\[(\d+)(;*)(\d*)(\w)||g'
+--- a/scripts/unload.sh
++++ b/scripts/unload.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+
+ # The old stack drivers and the mac80211 rc80211_simple modules
+ # which is no longer on recent kernels (its internal)
+--- a/scripts/update-initramfs
++++ b/scripts/update-initramfs
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ # Copyright 2009 Luis R. Rodriguez <mcgrof@gmail.com>
+ #
+ # Since we provide ssb, the Ethernet module b44 some people may
+--- a/scripts/wlload.sh
++++ b/scripts/wlload.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ MODULES="ipw2100 ipw2200 libertas_cs usb8xxx"
+ MODULES="$MODULES p54pci p54usb"
+ MODULES="$MODULES adm8211 zd1211rw"
+--- a/scripts/wlunload.sh
++++ b/scripts/wlunload.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+
+ # The old stack drivers and the mac80211 rc80211_simple modules
+ # which is no longer on recent kernels (its internal)