提交 8732baaf 编写于 作者: J John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

Conflicts:
	drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
...@@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com> ...@@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com>
M: Franky (Zhenhui) Lin <frankyl@broadcom.com> M: Franky (Zhenhui) Lin <frankyl@broadcom.com>
M: Kan Yan <kanyan@broadcom.com> M: Kan Yan <kanyan@broadcom.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: brcm80211-dev-list@broadcom.com
S: Supported S: Supported
F: drivers/net/wireless/brcm80211/ F: drivers/net/wireless/brcm80211/
......
...@@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = { ...@@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = {
static const struct bcma_device_id_name bcma_bcm_device_names[] = { static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_OOB_ROUTER, "OOB Router" }, { BCMA_CORE_OOB_ROUTER, "OOB Router" },
{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
{ BCMA_CORE_ALTA, "ALTA (I2S)" },
{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
{ BCMA_CORE_INVALID, "Invalid" }, { BCMA_CORE_INVALID, "Invalid" },
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" }, { BCMA_CORE_CHIPCOMMON, "ChipCommon" },
{ BCMA_CORE_ILINE20, "ILine 20" }, { BCMA_CORE_ILINE20, "ILine 20" },
......
...@@ -53,6 +53,11 @@ ...@@ -53,6 +53,11 @@
#define DEFAULT_BG_SCAN_PERIOD 60 #define DEFAULT_BG_SCAN_PERIOD 60
struct ath6kl_cfg80211_match_probe_ssid {
struct cfg80211_ssid ssid;
u8 flag;
};
static struct ieee80211_rate ath6kl_rates[] = { static struct ieee80211_rate ath6kl_rates[] = {
RATETAB_ENT(10, 0x1, 0), RATETAB_ENT(10, 0x1, 0),
RATETAB_ENT(20, 0x2, 0), RATETAB_ENT(20, 0x2, 0),
...@@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ...@@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif->nw_type = vif->next_mode; vif->nw_type = vif->next_mode;
/* enable enhanced bmiss detection if applicable */
ath6kl_cfg80211_sta_bmiss_enhance(vif, true);
if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
nw_subtype = SUBTYPE_P2PCLIENT; nw_subtype = SUBTYPE_P2PCLIENT;
...@@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, ...@@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
} }
} }
/*
* Send a disconnect command to target when a disconnect event is
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
* request from host) to make the firmware stop trying to connect even
* after giving disconnect event. There will be one more disconnect
* event for this disconnect command with reason code DISCONNECT_CMD
* which will be notified to cfg80211.
*/
if (reason != DISCONNECT_CMD) {
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
return;
}
clear_bit(CONNECT_PEND, &vif->flags); clear_bit(CONNECT_PEND, &vif->flags);
if (vif->sme_state == SME_CONNECTING) { if (vif->sme_state == SME_CONNECTING) {
...@@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, ...@@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
WLAN_STATUS_UNSPECIFIED_FAILURE, WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL); GFP_KERNEL);
} else if (vif->sme_state == SME_CONNECTED) { } else if (vif->sme_state == SME_CONNECTED) {
cfg80211_disconnected(vif->ndev, reason, cfg80211_disconnected(vif->ndev, proto_reason,
NULL, 0, GFP_KERNEL); NULL, 0, GFP_KERNEL);
} }
vif->sme_state = SME_DISCONNECTED; vif->sme_state = SME_DISCONNECTED;
/*
* Send a disconnect command to target when a disconnect event is
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
* request from host) to make the firmware stop trying to connect even
* after giving disconnect event. There will be one more disconnect
* event for this disconnect command with reason code DISCONNECT_CMD
* which won't be notified to cfg80211.
*/
if (reason != DISCONNECT_CMD)
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
} }
static int ath6kl_set_probed_ssids(struct ath6kl *ar, static int ath6kl_set_probed_ssids(struct ath6kl *ar,
struct ath6kl_vif *vif, struct ath6kl_vif *vif,
struct cfg80211_ssid *ssids, int n_ssids) struct cfg80211_ssid *ssids, int n_ssids,
struct cfg80211_match_set *match_set,
int n_match_ssid)
{ {
u8 i; u8 i, j, index_to_add, ssid_found = false;
struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS];
memset(ssid_list, 0, sizeof(ssid_list));
if (n_ssids > MAX_PROBED_SSID_INDEX) if (n_ssids > MAX_PROBED_SSIDS ||
n_match_ssid > MAX_PROBED_SSIDS)
return -EINVAL; return -EINVAL;
for (i = 0; i < n_ssids; i++) { for (i = 0; i < n_ssids; i++) {
memcpy(ssid_list[i].ssid.ssid,
ssids[i].ssid,
ssids[i].ssid_len);
ssid_list[i].ssid.ssid_len = ssids[i].ssid_len;
if (ssids[i].ssid_len)
ssid_list[i].flag = SPECIFIC_SSID_FLAG;
else
ssid_list[i].flag = ANY_SSID_FLAG;
if (n_match_ssid == 0)
ssid_list[i].flag |= MATCH_SSID_FLAG;
}
index_to_add = i;
for (i = 0; i < n_match_ssid; i++) {
ssid_found = false;
for (j = 0; j < n_ssids; j++) {
if ((match_set[i].ssid.ssid_len ==
ssid_list[j].ssid.ssid_len) &&
(!memcmp(ssid_list[j].ssid.ssid,
match_set[i].ssid.ssid,
match_set[i].ssid.ssid_len))) {
ssid_list[j].flag |= MATCH_SSID_FLAG;
ssid_found = true;
break;
}
}
if (ssid_found)
continue;
if (index_to_add >= MAX_PROBED_SSIDS)
continue;
ssid_list[index_to_add].ssid.ssid_len =
match_set[i].ssid.ssid_len;
memcpy(ssid_list[index_to_add].ssid.ssid,
match_set[i].ssid.ssid,
match_set[i].ssid.ssid_len);
ssid_list[index_to_add].flag |= MATCH_SSID_FLAG;
index_to_add++;
}
for (i = 0; i < index_to_add; i++) {
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
ssids[i].ssid_len ? ssid_list[i].flag,
SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, ssid_list[i].ssid.ssid_len,
ssids[i].ssid_len, ssid_list[i].ssid.ssid);
ssids[i].ssid);
} }
/* Make sure no old entries are left behind */ /* Make sure no old entries are left behind */
for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) {
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
DISABLE_SSID_FLAG, 0, NULL); DISABLE_SSID_FLAG, 0, NULL);
} }
...@@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ...@@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
} }
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
request->n_ssids); request->n_ssids, NULL, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ...@@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
WMI_FRAME_PROBE_REQ, WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len); request->ie, request->ie_len);
if (ret) { if (ret) {
ath6kl_err("failed to set Probe Request appie for scan"); ath6kl_err("failed to set Probe Request appie for scan\n");
return ret; return ret;
} }
...@@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, ...@@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
} }
} }
/* need to clean up enhanced bmiss detection fw state */
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
set_iface_type: set_iface_type:
switch (type) { switch (type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
...@@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) ...@@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
return -EINVAL; return -EINVAL;
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, false); vif->fw_vif_idx, false);
if (ret) if (ret)
...@@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar) ...@@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
ar->state = ATH6KL_STATE_ON; ar->state = ATH6KL_STATE_ON;
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, true); vif->fw_vif_idx, true);
if (ret) if (ret)
...@@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar) ...@@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar)
static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
bool ht_enable) bool ht_enable)
{ {
struct ath6kl_htcap *htcap = &vif->htcap; struct ath6kl_htcap *htcap = &vif->htcap[band];
if (htcap->ht_enable == ht_enable) if (htcap->ht_enable == ht_enable)
return 0; return 0;
...@@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, ...@@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
return 0; return 0;
} }
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
{
int err;
if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
return;
if (vif->nw_type != INFRA_NETWORK)
return;
if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
vif->ar->fw_capabilities))
return;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
enable ? "enable" : "disable");
err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
vif->fw_vif_idx, enable);
if (err)
ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
enable ? "enable" : "disable", err);
}
static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
u8 *rsn_capab) u8 *rsn_capab)
{ {
...@@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
/* TODO: /* TODO:
* info->interval * info->interval
* info->dtim_period
*/ */
ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
info->dtim_period);
/* ignore error, just print a warning and continue normally */
if (ret)
ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret);
if (info->beacon.head == NULL) if (info->beacon.head == NULL)
return -EINVAL; return -EINVAL;
mgmt = (struct ieee80211_mgmt *) info->beacon.head; mgmt = (struct ieee80211_mgmt *) info->beacon.head;
...@@ -3131,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, ...@@ -3131,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
ath6kl_cfg80211_scan_complete_event(vif, true); ath6kl_cfg80211_scan_complete_event(vif, true);
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
request->n_ssids); request->n_ssids,
request->match_sets,
request->n_match_sets);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!request->n_match_sets) {
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
ALL_BSS_FILTER, 0);
if (ret < 0)
return ret;
} else {
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
MATCHED_SSID_FILTER, 0);
if (ret < 0)
return ret;
}
/* fw uses seconds, also make sure that it's >0 */ /* fw uses seconds, also make sure that it's >0 */
interval = max_t(u16, 1, request->interval / 1000); interval = max_t(u16, 1, request->interval / 1000);
...@@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, ...@@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
WMI_FRAME_PROBE_REQ, WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len); request->ie, request->ie_len);
if (ret) { if (ret) {
ath6kl_warn("Failed to set probe request IE for scheduled scan: %d", ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n",
ret); ret);
return ret; return ret;
} }
...@@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, ...@@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
return 0; return 0;
} }
static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
struct net_device *dev,
const u8 *addr,
const struct cfg80211_bitrate_mask *mask)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
mask);
}
static const struct ieee80211_txrx_stypes static const struct ieee80211_txrx_stypes
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = { [NL80211_IFTYPE_STATION] = {
...@@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { ...@@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.mgmt_frame_register = ath6kl_mgmt_frame_register, .mgmt_frame_register = ath6kl_mgmt_frame_register,
.sched_scan_start = ath6kl_cfg80211_sscan_start, .sched_scan_start = ath6kl_cfg80211_sscan_start,
.sched_scan_stop = ath6kl_cfg80211_sscan_stop, .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
}; };
void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
...@@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ...@@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
vif->bg_scan_period = 0; vif->bg_scan_period = 0;
vif->htcap.ht_enable = true; vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true;
vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0) if (fw_vif_idx != 0)
...@@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ...@@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
} }
/* max num of ssids that can be probed during scanning */ /* max num of ssids that can be probed during scanning */
wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
/* max num of ssids that can be matched after scan */
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
ar->fw_capabilities))
wiphy->max_match_sets = MAX_PROBED_SSIDS;
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
switch (ar->hw.cap) { switch (ar->hw.cap) {
case WMI_11AN_CAP: case WMI_11AN_CAP:
...@@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ...@@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.cap = 0; ath6kl_band_5ghz.ht_cap.cap = 0;
ath6kl_band_5ghz.ht_cap.ht_supported = false; ath6kl_band_5ghz.ht_cap.ht_supported = false;
} }
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
} else {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
}
if (band_2gig) if (band_2gig)
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
if (band_5gig) if (band_5gig)
...@@ -3497,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ...@@ -3497,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
wiphy->wowlan.pattern_min_len = 1; wiphy->wowlan.pattern_min_len = 1;
wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_HAVE_AP_SME |
......
...@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar); ...@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);
struct ath6kl *ath6kl_cfg80211_create(void); struct ath6kl *ath6kl_cfg80211_create(void);
void ath6kl_cfg80211_destroy(struct ath6kl *ar); void ath6kl_cfg80211_destroy(struct ath6kl *ar);
/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);
#endif /* ATH6KL_CFG80211_H */ #endif /* ATH6KL_CFG80211_H */
...@@ -100,6 +100,21 @@ enum ath6kl_fw_capability { ...@@ -100,6 +100,21 @@ enum ath6kl_fw_capability {
/* Firmware has support to override rsn cap of rsn ie */ /* Firmware has support to override rsn cap of rsn ie */
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
/*
* Multicast support in WOW and host awake mode.
* Allow all multicast in host awake mode.
* Apply multicast filter in WOW mode.
*/
ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
/* Firmware supports enhanced bmiss detection */
ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
/*
* FW supports matching of ssid in schedule scan
*/
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
/* this needs to be last */ /* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX, ATH6KL_FW_CAPABILITY_MAX,
}; };
...@@ -112,6 +127,10 @@ struct ath6kl_fw_ie { ...@@ -112,6 +127,10 @@ struct ath6kl_fw_ie {
u8 data[0]; u8 data[0];
}; };
enum ath6kl_hw_flags {
ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin" #define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin" #define ATH6KL_FW_API3_FILE "fw-3.bin"
...@@ -196,7 +215,7 @@ struct ath6kl_fw_ie { ...@@ -196,7 +215,7 @@ struct ath6kl_fw_ie {
#define AGGR_NUM_OF_FREE_NETBUFS 16 #define AGGR_NUM_OF_FREE_NETBUFS 16
#define AGGR_RX_TIMEOUT 400 /* in ms */ #define AGGR_RX_TIMEOUT 100 /* in ms */
#define WMI_TIMEOUT (2 * HZ) #define WMI_TIMEOUT (2 * HZ)
...@@ -245,7 +264,6 @@ struct skb_hold_q { ...@@ -245,7 +264,6 @@ struct skb_hold_q {
struct rxtid { struct rxtid {
bool aggr; bool aggr;
bool progress;
bool timer_mon; bool timer_mon;
u16 win_sz; u16 win_sz;
u16 seq_next; u16 seq_next;
...@@ -254,9 +272,15 @@ struct rxtid { ...@@ -254,9 +272,15 @@ struct rxtid {
struct sk_buff_head q; struct sk_buff_head q;
/* /*
* FIXME: No clue what this should protect. Apparently it should * lock mainly protects seq_next and hold_q. Movement of seq_next
* protect some of the fields above but they are also accessed * needs to be protected between aggr_timeout() and
* without taking the lock. * aggr_process_recv_frm(). hold_q will be holding the pending
* reorder frames and it's access should also be protected.
* Some of the other fields like hold_q_sz, win_sz and aggr are
* initialized/reset when receiving addba/delba req, also while
* deleting aggr state all the pending buffers are flushed before
* resetting these fields, so there should not be any race in accessing
* these fields.
*/ */
spinlock_t lock; spinlock_t lock;
}; };
...@@ -541,7 +565,7 @@ struct ath6kl_vif { ...@@ -541,7 +565,7 @@ struct ath6kl_vif {
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
struct aggr_info *aggr_cntxt; struct aggr_info *aggr_cntxt;
struct ath6kl_htcap htcap; struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS];
struct timer_list disconnect_timer; struct timer_list disconnect_timer;
struct timer_list sched_scan_timer; struct timer_list sched_scan_timer;
...@@ -684,6 +708,8 @@ struct ath6kl { ...@@ -684,6 +708,8 @@ struct ath6kl {
u32 testscript_addr; u32 testscript_addr;
enum wmi_phy_cap cap; enum wmi_phy_cap cap;
u32 flags;
struct ath6kl_hw_fw { struct ath6kl_hw_fw {
const char *dir; const char *dir;
const char *otp; const char *otp;
......
...@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target, ...@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target,
} }
ath6kl_dbg(ATH6KL_DBG_HTC, ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx 0x%p hdr x%x len %d mbox 0x%x\n", "htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n",
packet, packet->info.rx.exp_hdr, packet, packet->info.rx.exp_hdr,
padded_len, dev->ar->mbox_info.htc_addr); padded_len, dev->ar->mbox_info.htc_addr);
......
...@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
.reserved_ram_size = 6912, .reserved_ram_size = 6912,
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 8, .uarttx_pin = 8,
.flags = 0,
/* hw2.0 needs override address hardcoded */ /* hw2.0 needs override address hardcoded */
.app_start_override_addr = 0x944C00, .app_start_override_addr = 0x944C00,
...@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 8, .uarttx_pin = 8,
.testscript_addr = 0x57ef74, .testscript_addr = 0x57ef74,
.flags = 0,
.fw = { .fw = {
.dir = AR6003_HW_2_1_1_FW_DIR, .dir = AR6003_HW_2_1_1_FW_DIR,
...@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900, .board_addr = 0x433900,
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = { .fw = {
.dir = AR6004_HW_1_0_FW_DIR, .dir = AR6004_HW_1_0_FW_DIR,
...@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400, .board_addr = 0x43d400,
.refclk_hz = 40000000, .refclk_hz = 40000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = { .fw = {
.dir = AR6004_HW_1_1_FW_DIR, .dir = AR6004_HW_1_1_FW_DIR,
...@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00, .board_addr = 0x435c00,
.refclk_hz = 40000000, .refclk_hz = 40000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = { .fw = {
.dir = AR6004_HW_1_2_FW_DIR, .dir = AR6004_HW_1_2_FW_DIR,
...@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
} }
switch (ie_id) { switch (ie_id) {
case ATH6KL_FW_IE_FW_VERSION:
strlcpy(ar->wiphy->fw_version, data,
sizeof(ar->wiphy->fw_version));
ath6kl_dbg(ATH6KL_DBG_BOOT,
"found fw version %s\n",
ar->wiphy->fw_version);
break;
case ATH6KL_FW_IE_OTP_IMAGE: case ATH6KL_FW_IE_OTP_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
ie_len); ie_len);
...@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->hw.reserved_ram_size); ar->hw.reserved_ram_size);
break; break;
case ATH6KL_FW_IE_CAPABILITIES: case ATH6KL_FW_IE_CAPABILITIES:
if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8))
break;
ath6kl_dbg(ATH6KL_DBG_BOOT, ath6kl_dbg(ATH6KL_DBG_BOOT,
"found firmware capabilities ie (%zd B)\n", "found firmware capabilities ie (%zd B)\n",
ie_len); ie_len);
...@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
index = i / 8; index = i / 8;
bit = i % 8; bit = i % 8;
if (index == ie_len)
break;
if (data[index] & (1 << bit)) if (data[index] & (1 << bit))
__set_bit(i, ar->fw_capabilities); __set_bit(i, ar->fw_capabilities);
} }
...@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar) ...@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar)
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) { ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
ath6kl_err("temporary war to avoid sdio crc error\n"); ath6kl_err("temporary war to avoid sdio crc error\n");
param = 0x28;
address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS;
status = ath6kl_bmi_reg_write(ar, address, param);
if (status)
return status;
param = 0x20; param = 0x20;
address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
...@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) ...@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
cfg80211_scan_done(vif->scan_req, true); cfg80211_scan_done(vif->scan_req, true);
vif->scan_req = NULL; vif->scan_req = NULL;
} }
/* need to clean up enhanced bmiss detection fw state */
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
} }
void ath6kl_stop_txrx(struct ath6kl *ar) void ath6kl_stop_txrx(struct ath6kl *ar)
......
...@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, ...@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
struct ath6kl *ar = devt; struct ath6kl *ar = devt;
memcpy(ar->mac_addr, datap, ETH_ALEN); memcpy(ar->mac_addr, datap, ETH_ALEN);
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
__func__, ar->mac_addr); ath6kl_dbg(ATH6KL_DBG_BOOT,
"ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n",
ar->mac_addr, sw_ver, abi_ver, cap);
ar->version.wlan_ver = sw_ver; ar->version.wlan_ver = sw_ver;
ar->version.abi_ver = abi_ver; ar->version.abi_ver = abi_ver;
ar->hw.cap = cap; ar->hw.cap = cap;
snprintf(ar->wiphy->fw_version, if (strlen(ar->wiphy->fw_version) == 0) {
sizeof(ar->wiphy->fw_version), snprintf(ar->wiphy->fw_version,
"%u.%u.%u.%u", sizeof(ar->wiphy->fw_version),
(ar->version.wlan_ver & 0xf0000000) >> 28, "%u.%u.%u.%u",
(ar->version.wlan_ver & 0x0f000000) >> 24, (ar->version.wlan_ver & 0xf0000000) >> 28,
(ar->version.wlan_ver & 0x00ff0000) >> 16, (ar->version.wlan_ver & 0x0f000000) >> 24,
(ar->version.wlan_ver & 0x0000ffff)); (ar->version.wlan_ver & 0x00ff0000) >> 16,
(ar->version.wlan_ver & 0x0000ffff));
}
/* indicate to the waiting thread that the ready event was received */ /* indicate to the waiting thread that the ready event was received */
set_bit(WMI_READY, &ar->flag); set_bit(WMI_READY, &ar->flag);
...@@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) ...@@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
else else
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
vif->ar->fw_capabilities)) {
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
}
if (!(ndev->flags & IFF_MULTICAST)) { if (!(ndev->flags & IFF_MULTICAST)) {
mc_all_on = false; mc_all_on = false;
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#define LPO_CAL_ENABLE_S 20 #define LPO_CAL_ENABLE_S 20
#define LPO_CAL_ENABLE 0x00100000 #define LPO_CAL_ENABLE 0x00100000
#define GPIO_PIN9_ADDRESS 0x0000004c
#define GPIO_PIN10_ADDRESS 0x00000050 #define GPIO_PIN10_ADDRESS 0x00000050
#define GPIO_PIN11_ADDRESS 0x00000054 #define GPIO_PIN11_ADDRESS 0x00000054
#define GPIO_PIN12_ADDRESS 0x00000058 #define GPIO_PIN12_ADDRESS 0x00000058
......
...@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
rxtid = &agg_conn->rx_tid[tid]; rxtid = &agg_conn->rx_tid[tid];
stats = &agg_conn->stat[tid]; stats = &agg_conn->stat[tid];
spin_lock_bh(&rxtid->lock);
idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
/* /*
...@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
seq_end = seq_no ? seq_no : rxtid->seq_next; seq_end = seq_no ? seq_no : rxtid->seq_next;
idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
spin_lock_bh(&rxtid->lock);
do { do {
node = &rxtid->hold_q[idx]; node = &rxtid->hold_q[idx];
if ((order == 1) && (!node->skb)) if ((order == 1) && (!node->skb))
...@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
((end > extended_end) && (cur > extended_end) && ((end > extended_end) && (cur > extended_end) &&
(cur < end))) { (cur < end))) {
aggr_deque_frms(agg_conn, tid, 0, 0); aggr_deque_frms(agg_conn, tid, 0, 0);
spin_lock_bh(&rxtid->lock);
if (cur >= rxtid->hold_q_sz - 1) if (cur >= rxtid->hold_q_sz - 1)
rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
else else
rxtid->seq_next = ATH6KL_MAX_SEQ_NO - rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
(rxtid->hold_q_sz - 2 - cur); (rxtid->hold_q_sz - 2 - cur);
spin_unlock_bh(&rxtid->lock);
} else { } else {
/* /*
* Dequeue only those frames that are outside the * Dequeue only those frames that are outside the
...@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
aggr_deque_frms(agg_conn, tid, 0, 1); aggr_deque_frms(agg_conn, tid, 0, 1);
if (agg_conn->timer_scheduled) if (agg_conn->timer_scheduled)
rxtid->progress = true; return is_queued;
else
for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { spin_lock_bh(&rxtid->lock);
if (rxtid->hold_q[idx].skb) { for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
/* if (rxtid->hold_q[idx].skb) {
* There is a frame in the queue and no /*
* timer so start a timer to ensure that * There is a frame in the queue and no
* the frame doesn't remain stuck * timer so start a timer to ensure that
* forever. * the frame doesn't remain stuck
*/ * forever.
agg_conn->timer_scheduled = true; */
mod_timer(&agg_conn->timer, agg_conn->timer_scheduled = true;
(jiffies + mod_timer(&agg_conn->timer,
HZ * (AGGR_RX_TIMEOUT) / 1000)); (jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000));
rxtid->progress = false; rxtid->timer_mon = true;
rxtid->timer_mon = true; break;
break;
}
} }
}
spin_unlock_bh(&rxtid->lock);
return is_queued; return is_queued;
} }
...@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg) ...@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i]; rxtid = &aggr_conn->rx_tid[i];
stats = &aggr_conn->stat[i]; stats = &aggr_conn->stat[i];
if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) if (!rxtid->aggr || !rxtid->timer_mon)
continue; continue;
stats->num_timeouts++; stats->num_timeouts++;
...@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg) ...@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i]; rxtid = &aggr_conn->rx_tid[i];
if (rxtid->aggr && rxtid->hold_q) { if (rxtid->aggr && rxtid->hold_q) {
spin_lock_bh(&rxtid->lock);
for (j = 0; j < rxtid->hold_q_sz; j++) { for (j = 0; j < rxtid->hold_q_sz; j++) {
if (rxtid->hold_q[j].skb) { if (rxtid->hold_q[j].skb) {
aggr_conn->timer_scheduled = true; aggr_conn->timer_scheduled = true;
rxtid->timer_mon = true; rxtid->timer_mon = true;
rxtid->progress = false;
break; break;
} }
} }
spin_unlock_bh(&rxtid->lock);
if (j >= rxtid->hold_q_sz) if (j >= rxtid->hold_q_sz)
rxtid->timer_mon = false; rxtid->timer_mon = false;
...@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) ...@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
aggr_deque_frms(aggr_conn, tid, 0, 0); aggr_deque_frms(aggr_conn, tid, 0, 0);
rxtid->aggr = false; rxtid->aggr = false;
rxtid->progress = false;
rxtid->timer_mon = false; rxtid->timer_mon = false;
rxtid->win_sz = 0; rxtid->win_sz = 0;
rxtid->seq_next = 0; rxtid->seq_next = 0;
...@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, ...@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info,
for (i = 0; i < NUM_OF_TIDS; i++) { for (i = 0; i < NUM_OF_TIDS; i++) {
rxtid = &aggr_conn->rx_tid[i]; rxtid = &aggr_conn->rx_tid[i];
rxtid->aggr = false; rxtid->aggr = false;
rxtid->progress = false;
rxtid->timer_mon = false; rxtid->timer_mon = false;
skb_queue_head_init(&rxtid->q); skb_queue_head_init(&rxtid->q);
spin_lock_init(&rxtid->lock); spin_lock_init(&rxtid->lock);
......
...@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) ...@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
return -ENOMEM; return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data; cmd = (struct roam_ctrl_cmd *) skb->data;
memset(cmd, 0, sizeof(*cmd));
memcpy(cmd->info.bssid, bssid, ETH_ALEN); memcpy(cmd->info.bssid, bssid, ETH_ALEN);
cmd->roam_ctrl = WMI_FORCE_ROAM; cmd->roam_ctrl = WMI_FORCE_ROAM;
...@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) ...@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
NO_SYNC_WMIFLAG); NO_SYNC_WMIFLAG);
} }
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
{
struct sk_buff *skb;
struct set_dtim_cmd *cmd;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct set_dtim_cmd *) skb->data;
cmd->dtim_period = cpu_to_le32(dtim_period);
return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) ...@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
return -ENOMEM; return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data; cmd = (struct roam_ctrl_cmd *) skb->data;
memset(cmd, 0, sizeof(*cmd));
cmd->info.roam_mode = mode; cmd->info.roam_mode = mode;
cmd->roam_ctrl = WMI_SET_ROAM_MODE; cmd->roam_ctrl = WMI_SET_ROAM_MODE;
...@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag, ...@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
struct wmi_probed_ssid_cmd *cmd; struct wmi_probed_ssid_cmd *cmd;
int ret; int ret;
if (index > MAX_PROBED_SSID_INDEX) if (index >= MAX_PROBED_SSIDS)
return -EINVAL; return -EINVAL;
if (ssid_len > sizeof(cmd->ssid)) if (ssid_len > sizeof(cmd->ssid))
...@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi) ...@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
spin_unlock_bh(&wmi->lock); spin_unlock_bh(&wmi->lock);
} }
static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct sk_buff *skb;
int ret, mode, band;
u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
struct wmi_set_tx_select_rates64_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
ratemask[band] =
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[1];
mcsrate <<= 8;
mcsrate |= mask->control[band].mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 28;
}
ath6kl_dbg(ATH6KL_DBG_WMI,
"Ratemask 64 bit: 2.4:%llx 5:%llx\n",
ratemask[0], ratemask[1]);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
/* A mode operate in 5GHZ band */
if (mode == WMI_RATES_MODE_11A ||
mode == WMI_RATES_MODE_11A_HT20 ||
mode == WMI_RATES_MODE_11A_HT40)
band = IEEE80211_BAND_5GHZ;
else
band = IEEE80211_BAND_2GHZ;
cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
}
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_SET_TX_SELECT_RATES_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct sk_buff *skb;
int ret, mode, band;
u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
struct wmi_set_tx_select_rates32_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
ratemask[band] =
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 20;
}
ath6kl_dbg(ATH6KL_DBG_WMI,
"Ratemask 32 bit: 2.4:%x 5:%x\n",
ratemask[0], ratemask[1]);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
/* A mode operate in 5GHZ band */
if (mode == WMI_RATES_MODE_11A ||
mode == WMI_RATES_MODE_11A_HT20 ||
mode == WMI_RATES_MODE_11A_HT40)
band = IEEE80211_BAND_5GHZ;
else
band = IEEE80211_BAND_2GHZ;
cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
}
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_SET_TX_SELECT_RATES_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct ath6kl *ar = wmi->parent_dev;
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
}
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode) enum ath6kl_host_mode host_mode)
{ {
...@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
return ret; return ret;
} }
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
{
struct sk_buff *skb;
struct wmi_sta_bmiss_enhance_cmd *cmd;
int ret;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data;
cmd->enable = enhance ? 1 : 0;
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_STA_BMISS_ENHANCE_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
s32 ath6kl_wmi_get_rate(s8 rate_index) s32 ath6kl_wmi_get_rate(s8 rate_index)
{ {
if (rate_index == RATE_AUTO) if (rate_index == RATE_AUTO)
......
...@@ -624,6 +624,10 @@ enum wmi_cmd_id { ...@@ -624,6 +624,10 @@ enum wmi_cmd_id {
WMI_SEND_MGMT_CMDID, WMI_SEND_MGMT_CMDID,
WMI_BEGIN_SCAN_CMDID, WMI_BEGIN_SCAN_CMDID,
WMI_SET_BLACK_LIST,
WMI_SET_MCASTRATE,
WMI_STA_BMISS_ENHANCE_CMDID,
}; };
enum wmi_mgmt_frame_type { enum wmi_mgmt_frame_type {
...@@ -960,6 +964,9 @@ enum wmi_bss_filter { ...@@ -960,6 +964,9 @@ enum wmi_bss_filter {
/* beacons matching probed ssid */ /* beacons matching probed ssid */
PROBED_SSID_FILTER, PROBED_SSID_FILTER,
/* beacons matching matched ssid */
MATCHED_SSID_FILTER,
/* marker only */ /* marker only */
LAST_BSS_FILTER, LAST_BSS_FILTER,
}; };
...@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd { ...@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd {
} __packed; } __packed;
/* WMI_SET_PROBED_SSID_CMDID */ /* WMI_SET_PROBED_SSID_CMDID */
#define MAX_PROBED_SSID_INDEX 9 #define MAX_PROBED_SSIDS 16
enum wmi_ssid_flag { enum wmi_ssid_flag {
/* disables entry */ /* disables entry */
...@@ -989,10 +996,13 @@ enum wmi_ssid_flag { ...@@ -989,10 +996,13 @@ enum wmi_ssid_flag {
/* probes for any ssid */ /* probes for any ssid */
ANY_SSID_FLAG = 0x02, ANY_SSID_FLAG = 0x02,
/* match for ssid */
MATCH_SSID_FLAG = 0x08,
}; };
struct wmi_probed_ssid_cmd { struct wmi_probed_ssid_cmd {
/* 0 to MAX_PROBED_SSID_INDEX */ /* 0 to MAX_PROBED_SSIDS - 1 */
u8 entry_index; u8 entry_index;
/* see, enum wmi_ssid_flg */ /* see, enum wmi_ssid_flg */
...@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd { ...@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd {
__le16 num_beacons; __le16 num_beacons;
}; };
/* WMI_STA_ENHANCE_BMISS_CMDID */
struct wmi_sta_bmiss_enhance_cmd {
u8 enable;
} __packed;
/* WMI_SET_POWER_MODE_CMDID */ /* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode { enum wmi_power_mode {
REC_POWER = 0x01, REC_POWER = 0x01,
...@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd { ...@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd {
__le16 ps_fail_event_policy; __le16 ps_fail_event_policy;
} __packed; } __packed;
/*
* Ratemask for below modes should be passed
* to WMI_SET_TX_SELECT_RATES_CMDID.
* AR6003 has 32 bit mask for each modes.
* First 12 bits for legacy rates, 13 to 20
* bits for HT 20 rates and 21 to 28 bits for
* HT 40 rates
*/
enum wmi_mode_phy {
WMI_RATES_MODE_11A = 0,
WMI_RATES_MODE_11G,
WMI_RATES_MODE_11B,
WMI_RATES_MODE_11GONLY,
WMI_RATES_MODE_11A_HT20,
WMI_RATES_MODE_11G_HT20,
WMI_RATES_MODE_11A_HT40,
WMI_RATES_MODE_11G_HT40,
WMI_RATES_MODE_MAX
};
/* WMI_SET_TX_SELECT_RATES_CMDID */
struct wmi_set_tx_select_rates32_cmd {
__le32 ratemask[WMI_RATES_MODE_MAX];
} __packed;
/* WMI_SET_TX_SELECT_RATES_CMDID */
struct wmi_set_tx_select_rates64_cmd {
__le64 ratemask[WMI_RATES_MODE_MAX];
} __packed;
/* WMI_SET_DISC_TIMEOUT_CMDID */ /* WMI_SET_DISC_TIMEOUT_CMDID */
struct wmi_disc_timeout_cmd { struct wmi_disc_timeout_cmd {
/* seconds */ /* seconds */
...@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd { ...@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd {
u8 roam_ctrl; u8 roam_ctrl;
} __packed; } __packed;
struct set_dtim_cmd {
__le32 dtim_period;
} __packed;
/* BSS INFO HDR version 2.0 */ /* BSS INFO HDR version 2.0 */
struct wmi_bss_info_hdr2 { struct wmi_bss_info_hdr2 {
__le16 ch; /* frequency in MHz */ __le16 ch; /* frequency in MHz */
...@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1); __be32 ips0, __be32 ips1);
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode); enum ath6kl_host_mode host_mode);
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask);
int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_wow_mode wow_mode, enum ath6kl_wow_mode wow_mode,
u32 filter, u16 host_req_delay); u32 filter, u16 host_req_delay);
...@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u16 list_id, u16 filter_id); u16 list_id, u16 filter_id);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
u8 *filter, bool add_filter); u8 *filter, bool add_filter);
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
/* AP mode uAPSD */ /* AP mode uAPSD */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
......
...@@ -24,42 +24,34 @@ ...@@ -24,42 +24,34 @@
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
/* units are errors per second */ /* units are errors per second */
#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 #define ATH9K_ANI_OFDM_TRIG_HIGH 3500
#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 3500
#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
/* units are errors per second */ /* units are errors per second */
#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 #define ATH9K_ANI_OFDM_TRIG_LOW 400
#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
/* units are errors per second */ /* units are errors per second */
#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 #define ATH9K_ANI_CCK_TRIG_HIGH 600
#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
/* units are errors per second */ /* units are errors per second */
#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 #define ATH9K_ANI_CCK_TRIG_LOW 300
#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
#define ATH9K_ANI_NOISE_IMMUNE_LVL 4 #define ATH9K_ANI_NOISE_IMMUNE_LVL 4
#define ATH9K_ANI_USE_OFDM_WEAK_SIG true #define ATH9K_ANI_USE_OFDM_WEAK_SIG true
#define ATH9K_ANI_CCK_WEAK_SIG_THR false #define ATH9K_ANI_CCK_WEAK_SIG_THR false
#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7 #define ATH9K_ANI_SPUR_IMMUNE_LVL 3
#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
#define ATH9K_ANI_FIRSTEP_LVL_OLD 0 #define ATH9K_ANI_FIRSTEP_LVL 2
#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
#define ATH9K_ANI_RSSI_THR_HIGH 40 #define ATH9K_ANI_RSSI_THR_HIGH 40
#define ATH9K_ANI_RSSI_THR_LOW 7 #define ATH9K_ANI_RSSI_THR_LOW 7
#define ATH9K_ANI_PERIOD_OLD 100 #define ATH9K_ANI_PERIOD 300
#define ATH9K_ANI_PERIOD_NEW 300
/* in ms */ /* in ms */
#define ATH9K_ANI_POLLINTERVAL_OLD 100 #define ATH9K_ANI_POLLINTERVAL 1000
#define ATH9K_ANI_POLLINTERVAL_NEW 1000
#define HAL_NOISE_IMMUNE_MAX 4 #define HAL_NOISE_IMMUNE_MAX 4
#define HAL_SPUR_IMMUNE_MAX 7 #define HAL_SPUR_IMMUNE_MAX 7
...@@ -70,8 +62,6 @@ ...@@ -70,8 +62,6 @@
#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 #define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22 #define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
#define ATH9K_ANI_ENABLE_MRC_CCK true
/* values here are relative to the INI */ /* values here are relative to the INI */
enum ath9k_ani_cmd { enum ath9k_ani_cmd {
...@@ -119,16 +109,14 @@ struct ar5416AniState { ...@@ -119,16 +109,14 @@ struct ar5416AniState {
u8 ofdmNoiseImmunityLevel; u8 ofdmNoiseImmunityLevel;
u8 cckNoiseImmunityLevel; u8 cckNoiseImmunityLevel;
bool ofdmsTurn; bool ofdmsTurn;
u8 mrcCCKOff; u8 mrcCCK;
u8 spurImmunityLevel; u8 spurImmunityLevel;
u8 firstepLevel; u8 firstepLevel;
u8 ofdmWeakSigDetectOff; u8 ofdmWeakSigDetect;
u8 cckWeakSigThreshold; u8 cckWeakSigThreshold;
bool update_ani;
u32 listenTime; u32 listenTime;
int32_t rssiThrLow; int32_t rssiThrLow;
int32_t rssiThrHigh; int32_t rssiThrHigh;
u32 noiseFloor;
u32 ofdmPhyErrCount; u32 ofdmPhyErrCount;
u32 cckPhyErrCount; u32 cckPhyErrCount;
int16_t pktRssi[2]; int16_t pktRssi[2];
......
...@@ -995,141 +995,6 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, ...@@ -995,141 +995,6 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
return pll; return pll;
} }
static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
{
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
switch (cmd & ah->ani_function) {
case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
u32 level = param;
if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
level, ARRAY_SIZE(ah->totalSizeDesired));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
AR_PHY_DESIRED_SZ_TOT_DES,
ah->totalSizeDesired[level]);
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
AR_PHY_AGC_CTL1_COARSE_LOW,
ah->coarse_low[level]);
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
AR_PHY_AGC_CTL1_COARSE_HIGH,
ah->coarse_high[level]);
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRPWR,
ah->firpwr[level]);
if (level > aniState->noiseImmunityLevel)
ah->stats.ast_ani_niup++;
else if (level < aniState->noiseImmunityLevel)
ah->stats.ast_ani_nidown++;
aniState->noiseImmunityLevel = level;
break;
}
case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
u32 on = param ? 1 : 0;
if (on)
REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
else
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) {
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on;
}
break;
}
case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
static const int weakSigThrCck[] = { 8, 6 };
u32 high = param ? 1 : 0;
REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
weakSigThrCck[high]);
if (high != aniState->cckWeakSigThreshold) {
if (high)
ah->stats.ast_ani_cckhigh++;
else
ah->stats.ast_ani_ccklow++;
aniState->cckWeakSigThreshold = high;
}
break;
}
case ATH9K_ANI_FIRSTEP_LEVEL:{
static const int firstep[] = { 0, 4, 8 };
u32 level = param;
if (level >= ARRAY_SIZE(firstep)) {
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
level, ARRAY_SIZE(firstep));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRSTEP,
firstep[level]);
if (level > aniState->firstepLevel)
ah->stats.ast_ani_stepup++;
else if (level < aniState->firstepLevel)
ah->stats.ast_ani_stepdown++;
aniState->firstepLevel = level;
break;
}
case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
u32 level = param;
if (level >= ARRAY_SIZE(cycpwrThr1)) {
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
level, ARRAY_SIZE(cycpwrThr1));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
AR_PHY_TIMING5_CYCPWR_THR1,
cycpwrThr1[level]);
if (level > aniState->spurImmunityLevel)
ah->stats.ast_ani_spurup++;
else if (level < aniState->spurImmunityLevel)
ah->stats.ast_ani_spurdown++;
aniState->spurImmunityLevel = level;
break;
}
case ATH9K_ANI_PRESENT:
break;
default:
ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
return false;
}
ath_dbg(common, ANI, "ANI parameters:\n");
ath_dbg(common, ANI,
"noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
aniState->noiseImmunityLevel,
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff);
ath_dbg(common, ANI,
"cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
aniState->cckWeakSigThreshold,
aniState->firstepLevel,
aniState->listenTime);
ath_dbg(common, ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
}
static bool ar5008_hw_ani_control_new(struct ath_hw *ah, static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, enum ath9k_ani_cmd cmd,
int param) int param)
...@@ -1206,18 +1071,18 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1206,18 +1071,18 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) { if (on != aniState->ofdmWeakSigDetect) {
ath_dbg(common, ANI, ath_dbg(common, ANI,
"** ch %d: ofdm weak signal: %s=>%s\n", "** ch %d: ofdm weak signal: %s=>%s\n",
chan->channel, chan->channel,
!aniState->ofdmWeakSigDetectOff ? aniState->ofdmWeakSigDetect ?
"on" : "off", "on" : "off",
on ? "on" : "off"); on ? "on" : "off");
if (on) if (on)
ah->stats.ast_ani_ofdmon++; ah->stats.ast_ani_ofdmon++;
else else
ah->stats.ast_ani_ofdmoff++; ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on; aniState->ofdmWeakSigDetect = on;
} }
break; break;
} }
...@@ -1236,7 +1101,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1236,7 +1101,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value = firstep_table[level] - value = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstep; aniState->iniDef.firstep;
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value = ATH9K_SIG_FIRSTEP_SETTING_MIN; value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
...@@ -1251,7 +1116,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1251,7 +1116,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value2 = firstep_table[level] - value2 = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstepLow; aniState->iniDef.firstepLow;
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
...@@ -1267,7 +1132,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1267,7 +1132,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->firstepLevel, aniState->firstepLevel,
level, level,
ATH9K_ANI_FIRSTEP_LVL_NEW, ATH9K_ANI_FIRSTEP_LVL,
value, value,
aniState->iniDef.firstep); aniState->iniDef.firstep);
ath_dbg(common, ANI, ath_dbg(common, ANI,
...@@ -1275,7 +1140,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1275,7 +1140,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->firstepLevel, aniState->firstepLevel,
level, level,
ATH9K_ANI_FIRSTEP_LVL_NEW, ATH9K_ANI_FIRSTEP_LVL,
value2, value2,
aniState->iniDef.firstepLow); aniState->iniDef.firstepLow);
if (level > aniState->firstepLevel) if (level > aniState->firstepLevel)
...@@ -1300,7 +1165,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1300,7 +1165,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value = cycpwrThr1_table[level] - value = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1; aniState->iniDef.cycpwrThr1;
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
...@@ -1316,7 +1181,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1316,7 +1181,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value2 = cycpwrThr1_table[level] - value2 = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1Ext; aniState->iniDef.cycpwrThr1Ext;
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
...@@ -1331,7 +1196,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1331,7 +1196,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->spurImmunityLevel, aniState->spurImmunityLevel,
level, level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, ATH9K_ANI_SPUR_IMMUNE_LVL,
value, value,
aniState->iniDef.cycpwrThr1); aniState->iniDef.cycpwrThr1);
ath_dbg(common, ANI, ath_dbg(common, ANI,
...@@ -1339,7 +1204,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1339,7 +1204,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->spurImmunityLevel, aniState->spurImmunityLevel,
level, level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, ATH9K_ANI_SPUR_IMMUNE_LVL,
value2, value2,
aniState->iniDef.cycpwrThr1Ext); aniState->iniDef.cycpwrThr1Ext);
if (level > aniState->spurImmunityLevel) if (level > aniState->spurImmunityLevel)
...@@ -1367,9 +1232,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1367,9 +1232,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
ath_dbg(common, ANI, ath_dbg(common, ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel, aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off", aniState->ofdmWeakSigDetect ? "on" : "off",
aniState->firstepLevel, aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off", aniState->mrcCCK ? "on" : "off",
aniState->listenTime, aniState->listenTime,
aniState->ofdmPhyErrCount, aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount); aniState->cckPhyErrCount);
...@@ -1454,10 +1319,10 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) ...@@ -1454,10 +1319,10 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
AR_PHY_EXT_TIMING5_CYCPWR_THR1); AR_PHY_EXT_TIMING5_CYCPWR_THR1);
/* these levels just got reset to defaults by the INI */ /* these levels just got reset to defaults by the INI */
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = true; /* not available on pre AR9003 */ aniState->mrcCCK = false; /* not available on pre AR9003 */
} }
static void ar5008_hw_set_nf_limits(struct ath_hw *ah) static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
...@@ -1545,11 +1410,8 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) ...@@ -1545,11 +1410,8 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->do_getnf = ar5008_hw_do_getnf; priv_ops->do_getnf = ar5008_hw_do_getnf;
priv_ops->set_radar_params = ar5008_hw_set_radar_params; priv_ops->set_radar_params = ar5008_hw_set_radar_params;
if (modparam_force_new_ani) { priv_ops->ani_control = ar5008_hw_ani_control_new;
priv_ops->ani_control = ar5008_hw_ani_control_new; priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
} else
priv_ops->ani_control = ar5008_hw_ani_control_old;
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
......
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
#include "ar9002_initvals.h" #include "ar9002_initvals.h"
#include "ar9002_phy.h" #include "ar9002_phy.h"
int modparam_force_new_ani;
module_param_named(force_new_ani, modparam_force_new_ani, int, 0444);
MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002");
/* General hardware code for the A5008/AR9001/AR9002 hadware families */ /* General hardware code for the A5008/AR9001/AR9002 hadware families */
static void ar9002_hw_init_mode_regs(struct ath_hw *ah) static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
......
/* /*
* Copyright (c) 2010-2011 Atheros Communications Inc. * Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros Inc.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
......
...@@ -767,10 +767,6 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah) ...@@ -767,10 +767,6 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah)
{ {
/* disable all MCI messages */ /* disable all MCI messages */
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);
REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
/* wait pending HW messages to flush out */ /* wait pending HW messages to flush out */
...@@ -1019,9 +1015,14 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) ...@@ -1019,9 +1015,14 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
return; return;
if (mci->is_2g) { if (mci->is_2g) {
ar9003_mci_send_2g5g_status(ah, true); if (!force) {
ar9003_mci_send_2g5g_status(ah, true);
REG_SET_BIT(ah, AR_MCI_TX_CTRL, ar9003_mci_send_lna_transfer(ah, true);
udelay(5);
}
REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,
AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
...@@ -1029,6 +1030,11 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) ...@@ -1029,6 +1030,11 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
ar9003_mci_osla_setup(ah, true); ar9003_mci_osla_setup(ah, true);
} else { } else {
if (!force) {
ar9003_mci_send_lna_take(ah, true);
udelay(5);
}
REG_SET_BIT(ah, AR_MCI_TX_CTRL, REG_SET_BIT(ah, AR_MCI_TX_CTRL,
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
...@@ -1255,6 +1261,9 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) ...@@ -1255,6 +1261,9 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
ar9003_mci_send_lna_take(ah, true);
udelay(50);
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
mci->is_2g = false; mci->is_2g = false;
mci->update_2g5g = true; mci->update_2g5g = true;
......
...@@ -173,7 +173,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, ...@@ -173,7 +173,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
int cur_bb_spur, negative = 0, cck_spur_freq; int cur_bb_spur, negative = 0, cck_spur_freq;
int i; int i;
int range, max_spur_cnts, synth_freq; int range, max_spur_cnts, synth_freq;
u8 *spur_fbin_ptr = NULL; u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan));
/* /*
* Need to verify range +/- 10 MHz in control channel, otherwise spur * Need to verify range +/- 10 MHz in control channel, otherwise spur
...@@ -181,8 +181,6 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, ...@@ -181,8 +181,6 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
*/ */
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) { if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
IS_CHAN_2GHZ(chan));
if (spur_fbin_ptr[0] == 0) /* No spur */ if (spur_fbin_ptr[0] == 0) /* No spur */
return; return;
max_spur_cnts = 5; max_spur_cnts = 5;
...@@ -825,18 +823,18 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -825,18 +823,18 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) { if (on != aniState->ofdmWeakSigDetect) {
ath_dbg(common, ANI, ath_dbg(common, ANI,
"** ch %d: ofdm weak signal: %s=>%s\n", "** ch %d: ofdm weak signal: %s=>%s\n",
chan->channel, chan->channel,
!aniState->ofdmWeakSigDetectOff ? aniState->ofdmWeakSigDetect ?
"on" : "off", "on" : "off",
on ? "on" : "off"); on ? "on" : "off");
if (on) if (on)
ah->stats.ast_ani_ofdmon++; ah->stats.ast_ani_ofdmon++;
else else
ah->stats.ast_ani_ofdmoff++; ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on; aniState->ofdmWeakSigDetect = on;
} }
break; break;
} }
...@@ -855,7 +853,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -855,7 +853,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value = firstep_table[level] - value = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstep; aniState->iniDef.firstep;
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value = ATH9K_SIG_FIRSTEP_SETTING_MIN; value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
...@@ -870,7 +868,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -870,7 +868,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value2 = firstep_table[level] - value2 = firstep_table[level] -
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstepLow; aniState->iniDef.firstepLow;
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
...@@ -886,7 +884,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -886,7 +884,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->firstepLevel, aniState->firstepLevel,
level, level,
ATH9K_ANI_FIRSTEP_LVL_NEW, ATH9K_ANI_FIRSTEP_LVL,
value, value,
aniState->iniDef.firstep); aniState->iniDef.firstep);
ath_dbg(common, ANI, ath_dbg(common, ANI,
...@@ -894,7 +892,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -894,7 +892,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->firstepLevel, aniState->firstepLevel,
level, level,
ATH9K_ANI_FIRSTEP_LVL_NEW, ATH9K_ANI_FIRSTEP_LVL,
value2, value2,
aniState->iniDef.firstepLow); aniState->iniDef.firstepLow);
if (level > aniState->firstepLevel) if (level > aniState->firstepLevel)
...@@ -919,7 +917,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -919,7 +917,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value = cycpwrThr1_table[level] - value = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1; aniState->iniDef.cycpwrThr1;
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
...@@ -935,7 +933,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -935,7 +933,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value * from INI file & cap value
*/ */
value2 = cycpwrThr1_table[level] - value2 = cycpwrThr1_table[level] -
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1Ext; aniState->iniDef.cycpwrThr1Ext;
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
...@@ -950,7 +948,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -950,7 +948,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->spurImmunityLevel, aniState->spurImmunityLevel,
level, level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, ATH9K_ANI_SPUR_IMMUNE_LVL,
value, value,
aniState->iniDef.cycpwrThr1); aniState->iniDef.cycpwrThr1);
ath_dbg(common, ANI, ath_dbg(common, ANI,
...@@ -958,7 +956,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -958,7 +956,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->spurImmunityLevel, aniState->spurImmunityLevel,
level, level,
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, ATH9K_ANI_SPUR_IMMUNE_LVL,
value2, value2,
aniState->iniDef.cycpwrThr1Ext); aniState->iniDef.cycpwrThr1Ext);
if (level > aniState->spurImmunityLevel) if (level > aniState->spurImmunityLevel)
...@@ -979,16 +977,16 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -979,16 +977,16 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
AR_PHY_MRC_CCK_ENABLE, is_on); AR_PHY_MRC_CCK_ENABLE, is_on);
REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
AR_PHY_MRC_CCK_MUX_REG, is_on); AR_PHY_MRC_CCK_MUX_REG, is_on);
if (!is_on != aniState->mrcCCKOff) { if (is_on != aniState->mrcCCK) {
ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n", ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n",
chan->channel, chan->channel,
!aniState->mrcCCKOff ? "on" : "off", aniState->mrcCCK ? "on" : "off",
is_on ? "on" : "off"); is_on ? "on" : "off");
if (is_on) if (is_on)
ah->stats.ast_ani_ccklow++; ah->stats.ast_ani_ccklow++;
else else
ah->stats.ast_ani_cckhigh++; ah->stats.ast_ani_cckhigh++;
aniState->mrcCCKOff = !is_on; aniState->mrcCCK = is_on;
} }
break; break;
} }
...@@ -1002,9 +1000,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -1002,9 +1000,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
ath_dbg(common, ANI, ath_dbg(common, ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel, aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off", aniState->ofdmWeakSigDetect ? "on" : "off",
aniState->firstepLevel, aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off", aniState->mrcCCK ? "on" : "off",
aniState->listenTime, aniState->listenTime,
aniState->ofdmPhyErrCount, aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount); aniState->cckPhyErrCount);
...@@ -1111,10 +1109,10 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) ...@@ -1111,10 +1109,10 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
AR_PHY_EXT_CYCPWR_THR1); AR_PHY_EXT_CYCPWR_THR1);
/* these levels just got reset to defaults by the INI */ /* these levels just got reset to defaults by the INI */
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; aniState->mrcCCK = true;
} }
static void ar9003_hw_set_radar_params(struct ath_hw *ah, static void ar9003_hw_set_radar_params(struct ath_hw *ah,
......
...@@ -337,12 +337,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = { ...@@ -337,12 +337,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
}; };
static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = { #define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
/* Addr allmodes */
{0x0000a398, 0x00000000},
{0x0000a39c, 0x6f7f0301},
{0x0000a3a0, 0xca9228ee},
};
static const u32 ar9331_1p1_xtal_25M[][2] = { static const u32 ar9331_1p1_xtal_25M[][2] = {
/* Addr allmodes */ /* Addr allmodes */
...@@ -783,17 +778,7 @@ static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = { ...@@ -783,17 +778,7 @@ static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
}; };
static const u32 ar9331_1p1_mac_postamble[][5] = { #define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
};
static const u32 ar9331_1p1_soc_preamble[][2] = { static const u32 ar9331_1p1_soc_preamble[][2] = {
/* Addr allmodes */ /* Addr allmodes */
...@@ -1112,38 +1097,4 @@ static const u32 ar9331_common_tx_gain_offset1_1[][1] = { ...@@ -1112,38 +1097,4 @@ static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
{0x00000000}, {0x00000000},
}; };
static const u32 ar9331_1p1_chansel_xtal_25M[] = {
0x0101479e,
0x0101d027,
0x010258af,
0x0102e138,
0x010369c0,
0x0103f249,
0x01047ad1,
0x0105035a,
0x01058be2,
0x0106146b,
0x01069cf3,
0x0107257c,
0x0107ae04,
0x0108f5b2,
};
static const u32 ar9331_1p1_chansel_xtal_40M[] = {
0x00a0ccbe,
0x00a12213,
0x00a17769,
0x00a1ccbe,
0x00a22213,
0x00a27769,
0x00a2ccbe,
0x00a32213,
0x00a37769,
0x00a3ccbe,
0x00a42213,
0x00a47769,
0x00a4ccbe,
0x00a5998b,
};
#endif /* INITVALS_9330_1P1_H */ #endif /* INITVALS_9330_1P1_H */
/* /*
* Copyright (c) 2010 Atheros Communications Inc. * Copyright (c) 2010-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros Inc.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
...@@ -61,7 +62,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { ...@@ -61,7 +62,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, {0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
...@@ -1007,7 +1008,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { ...@@ -1007,7 +1008,7 @@ static const u32 ar9462_2p0_radio_core[][2] = {
static const u32 ar9462_2p0_soc_preamble[][2] = { static const u32 ar9462_2p0_soc_preamble[][2] = {
/* Addr allmodes */ /* Addr allmodes */
{0x000040a4 ,0x00a0c1c9}, {0x000040a4, 0x00a0c1c9},
{0x00007020, 0x00000000}, {0x00007020, 0x00000000},
{0x00007034, 0x00000002}, {0x00007034, 0x00000002},
{0x00007038, 0x000004c2}, {0x00007038, 0x000004c2},
......
...@@ -722,6 +722,7 @@ extern int ath9k_modparam_nohwcrypt; ...@@ -722,6 +722,7 @@ extern int ath9k_modparam_nohwcrypt;
extern int led_blink; extern int led_blink;
extern bool is_ath9k_unloaded; extern bool is_ath9k_unloaded;
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
irqreturn_t ath_isr(int irq, void *dev); irqreturn_t ath_isr(int irq, void *dev);
int ath9k_init_device(u16 devid, struct ath_softc *sc, int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops); const struct ath_bus_ops *bus_ops);
......
...@@ -348,8 +348,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) ...@@ -348,8 +348,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
sc->debug.stats.istats.txok++; sc->debug.stats.istats.txok++;
if (status & ATH9K_INT_TXURN) if (status & ATH9K_INT_TXURN)
sc->debug.stats.istats.txurn++; sc->debug.stats.istats.txurn++;
if (status & ATH9K_INT_MIB)
sc->debug.stats.istats.mib++;
if (status & ATH9K_INT_RXPHY) if (status & ATH9K_INT_RXPHY)
sc->debug.stats.istats.rxphyerr++; sc->debug.stats.istats.rxphyerr++;
if (status & ATH9K_INT_RXKCM) if (status & ATH9K_INT_RXKCM)
......
...@@ -416,7 +416,7 @@ int ath9k_init_btcoex(struct ath_softc *sc) ...@@ -416,7 +416,7 @@ int ath9k_init_btcoex(struct ath_softc *sc)
txq = sc->tx.txq_map[WME_AC_BE]; txq = sc->tx.txq_map[WME_AC_BE];
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
if (AR_SREV_9462(ah)) { if (ath9k_hw_mci_is_enabled(ah)) {
sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE; sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
INIT_LIST_HEAD(&sc->btcoex.mci.info); INIT_LIST_HEAD(&sc->btcoex.mci.info);
......
...@@ -453,7 +453,6 @@ struct ath9k_htc_priv { ...@@ -453,7 +453,6 @@ struct ath9k_htc_priv {
u8 num_sta_assoc_vif; u8 num_sta_assoc_vif;
u8 num_ap_vif; u8 num_ap_vif;
u16 op_flags;
u16 curtxpow; u16 curtxpow;
u16 txpowlimit; u16 txpowlimit;
u16 nvifs; u16 nvifs;
...@@ -461,6 +460,7 @@ struct ath9k_htc_priv { ...@@ -461,6 +460,7 @@ struct ath9k_htc_priv {
bool rearm_ani; bool rearm_ani;
bool reconfig_beacon; bool reconfig_beacon;
unsigned int rxfilter; unsigned int rxfilter;
unsigned long op_flags;
struct ath9k_hw_cal_data caldata; struct ath9k_hw_cal_data caldata;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
...@@ -572,8 +572,6 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, ...@@ -572,8 +572,6 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS
void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_init_leds(struct ath9k_htc_priv *priv);
......
...@@ -207,9 +207,9 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, ...@@ -207,9 +207,9 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
else else
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
if (priv->op_flags & OP_TSF_RESET) { if (test_bit(OP_TSF_RESET, &priv->op_flags)) {
ath9k_hw_reset_tsf(priv->ah); ath9k_hw_reset_tsf(priv->ah);
priv->op_flags &= ~OP_TSF_RESET; clear_bit(OP_TSF_RESET, &priv->op_flags);
} else { } else {
/* /*
* Pull nexttbtt forward to reflect the current TSF. * Pull nexttbtt forward to reflect the current TSF.
...@@ -221,7 +221,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, ...@@ -221,7 +221,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
} while (nexttbtt < tsftu); } while (nexttbtt < tsftu);
} }
if (priv->op_flags & OP_ENABLE_BEACON) if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
imask |= ATH9K_INT_SWBA; imask |= ATH9K_INT_SWBA;
ath_dbg(common, CONFIG, ath_dbg(common, CONFIG,
...@@ -269,7 +269,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, ...@@ -269,7 +269,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
else else
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
if (priv->op_flags & OP_ENABLE_BEACON) if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
imask |= ATH9K_INT_SWBA; imask |= ATH9K_INT_SWBA;
ath_dbg(common, CONFIG, ath_dbg(common, CONFIG,
...@@ -365,7 +365,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, ...@@ -365,7 +365,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
vif = priv->cur_beacon_conf.bslot[slot]; vif = priv->cur_beacon_conf.bslot[slot];
avp = (struct ath9k_htc_vif *)vif->drv_priv; avp = (struct ath9k_htc_vif *)vif->drv_priv;
if (unlikely(priv->op_flags & OP_SCANNING)) { if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) {
spin_unlock_bh(&priv->beacon_lock); spin_unlock_bh(&priv->beacon_lock);
return; return;
} }
......
...@@ -37,17 +37,18 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) ...@@ -37,17 +37,18 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
if (time_after(jiffies, btcoex->bt_priority_time + if (time_after(jiffies, btcoex->bt_priority_time +
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
clear_bit(OP_BT_SCAN, &priv->op_flags);
/* Detect if colocated bt started scanning */ /* Detect if colocated bt started scanning */
if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
ath_dbg(ath9k_hw_common(ah), BTCOEX, ath_dbg(ath9k_hw_common(ah), BTCOEX,
"BT scan detected\n"); "BT scan detected\n");
priv->op_flags |= (OP_BT_SCAN | set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
OP_BT_PRIORITY_DETECTED); set_bit(OP_BT_SCAN, &priv->op_flags);
} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
ath_dbg(ath9k_hw_common(ah), BTCOEX, ath_dbg(ath9k_hw_common(ah), BTCOEX,
"BT priority traffic detected\n"); "BT priority traffic detected\n");
priv->op_flags |= OP_BT_PRIORITY_DETECTED; set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
} }
btcoex->bt_priority_cnt = 0; btcoex->bt_priority_cnt = 0;
...@@ -67,26 +68,23 @@ static void ath_btcoex_period_work(struct work_struct *work) ...@@ -67,26 +68,23 @@ static void ath_btcoex_period_work(struct work_struct *work)
struct ath_btcoex *btcoex = &priv->btcoex; struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
u32 timer_period; u32 timer_period;
bool is_btscan;
int ret; int ret;
ath_detect_bt_priority(priv); ath_detect_bt_priority(priv);
is_btscan = !!(priv->op_flags & OP_BT_SCAN);
ret = ath9k_htc_update_cap_target(priv, ret = ath9k_htc_update_cap_target(priv,
!!(priv->op_flags & OP_BT_PRIORITY_DETECTED)); test_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags));
if (ret) { if (ret) {
ath_err(common, "Unable to set BTCOEX parameters\n"); ath_err(common, "Unable to set BTCOEX parameters\n");
return; return;
} }
ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : ath9k_hw_btcoex_bt_stomp(priv->ah, test_bit(OP_BT_SCAN, &priv->op_flags) ?
btcoex->bt_stomp_type); ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type);
ath9k_hw_btcoex_enable(priv->ah); ath9k_hw_btcoex_enable(priv->ah);
timer_period = is_btscan ? btcoex->btscan_no_stomp : timer_period = test_bit(OP_BT_SCAN, &priv->op_flags) ?
btcoex->btcoex_no_stomp; btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp;
ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
msecs_to_jiffies(timer_period)); msecs_to_jiffies(timer_period));
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
...@@ -104,14 +102,15 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work) ...@@ -104,14 +102,15 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
struct ath_hw *ah = priv->ah; struct ath_hw *ah = priv->ah;
struct ath_btcoex *btcoex = &priv->btcoex; struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
bool is_btscan = priv->op_flags & OP_BT_SCAN;
ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n"); ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n");
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
test_bit(OP_BT_SCAN, &priv->op_flags))
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
ath9k_hw_btcoex_enable(priv->ah); ath9k_hw_btcoex_enable(priv->ah);
} }
...@@ -141,7 +140,8 @@ static void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) ...@@ -141,7 +140,8 @@ static void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
btcoex->bt_priority_cnt = 0; btcoex->bt_priority_cnt = 0;
btcoex->bt_priority_time = jiffies; btcoex->bt_priority_time = jiffies;
priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
clear_bit(OP_BT_SCAN, &priv->op_flags);
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
} }
...@@ -310,95 +310,3 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) ...@@ -310,95 +310,3 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
wiphy_rfkill_start_polling(priv->hw->wiphy); wiphy_rfkill_start_polling(priv->hw->wiphy);
} }
void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
int ret;
u8 cmd_rsp;
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
/* Reset the HW */
ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (ret) {
ath_err(common,
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
ret, ah->curchan->channel);
}
ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
&priv->curtxpow);
/* Start RX */
WMI_CMD(WMI_START_RECV_CMDID);
ath9k_host_rx_init(priv);
/* Start TX */
htc_start(priv->htc);
spin_lock_bh(&priv->tx.tx_lock);
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
spin_unlock_bh(&priv->tx.tx_lock);
ieee80211_wake_queues(hw);
WMI_CMD(WMI_ENABLE_INTR_CMDID);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
}
void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
int ret;
u8 cmd_rsp;
ath9k_htc_ps_wakeup(priv);
/* Disable LED */
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
/* Stop TX */
ieee80211_stop_queues(hw);
ath9k_htc_tx_drain(priv);
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
/* Stop RX */
WMI_CMD(WMI_STOP_RECV_CMDID);
/* Clear the WMI event queue */
ath9k_wmi_event_drain(priv);
/*
* The MIB counters have to be disabled here,
* since the target doesn't do it.
*/
ath9k_hw_disable_mib_counters(ah);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
/* Reset the HW */
ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (ret) {
ath_err(common,
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
ret, ah->curchan->channel);
}
/* Disable the PHY */
ath9k_hw_phy_disable(ah);
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
}
...@@ -611,7 +611,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ...@@ -611,7 +611,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
struct ath_common *common; struct ath_common *common;
int i, ret = 0, csz = 0; int i, ret = 0, csz = 0;
priv->op_flags |= OP_INVALID; set_bit(OP_INVALID, &priv->op_flags);
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
if (!ah) if (!ah)
...@@ -718,7 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, ...@@ -718,7 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
hw->queues = 4; hw->queues = 4;
hw->channel_change_time = 5000; hw->channel_change_time = 5000;
hw->max_listen_interval = 10; hw->max_listen_interval = 1;
hw->vif_data_size = sizeof(struct ath9k_htc_vif); hw->vif_data_size = sizeof(struct ath9k_htc_vif);
hw->sta_data_size = sizeof(struct ath9k_htc_sta); hw->sta_data_size = sizeof(struct ath9k_htc_sta);
......
...@@ -75,14 +75,19 @@ void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv) ...@@ -75,14 +75,19 @@ void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv)
void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
{ {
bool reset;
mutex_lock(&priv->htc_pm_lock); mutex_lock(&priv->htc_pm_lock);
if (--priv->ps_usecount != 0) if (--priv->ps_usecount != 0)
goto unlock; goto unlock;
if (priv->ps_idle) if (priv->ps_idle) {
ath9k_hw_setrxabort(priv->ah, true);
ath9k_hw_stopdmarecv(priv->ah, &reset);
ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
else if (priv->ps_enabled) } else if (priv->ps_enabled) {
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
}
unlock: unlock:
mutex_unlock(&priv->htc_pm_lock); mutex_unlock(&priv->htc_pm_lock);
...@@ -250,7 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ...@@ -250,7 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
u8 cmd_rsp; u8 cmd_rsp;
int ret; int ret;
if (priv->op_flags & OP_INVALID) if (test_bit(OP_INVALID, &priv->op_flags))
return -EIO; return -EIO;
fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
...@@ -304,7 +309,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ...@@ -304,7 +309,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
htc_start(priv->htc); htc_start(priv->htc);
if (!(priv->op_flags & OP_SCANNING) && if (!test_bit(OP_SCANNING, &priv->op_flags) &&
!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
ath9k_htc_vif_reconfig(priv); ath9k_htc_vif_reconfig(priv);
...@@ -750,7 +755,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) ...@@ -750,7 +755,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
common->ani.shortcal_timer = timestamp; common->ani.shortcal_timer = timestamp;
common->ani.checkani_timer = timestamp; common->ani.checkani_timer = timestamp;
priv->op_flags |= OP_ANI_RUNNING; set_bit(OP_ANI_RUNNING, &priv->op_flags);
ieee80211_queue_delayed_work(common->hw, &priv->ani_work, ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
...@@ -759,7 +764,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) ...@@ -759,7 +764,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
{ {
cancel_delayed_work_sync(&priv->ani_work); cancel_delayed_work_sync(&priv->ani_work);
priv->op_flags &= ~OP_ANI_RUNNING; clear_bit(OP_ANI_RUNNING, &priv->op_flags);
} }
void ath9k_htc_ani_work(struct work_struct *work) void ath9k_htc_ani_work(struct work_struct *work)
...@@ -944,7 +949,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ...@@ -944,7 +949,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ath_dbg(common, CONFIG, ath_dbg(common, CONFIG,
"Failed to update capability in target\n"); "Failed to update capability in target\n");
priv->op_flags &= ~OP_INVALID; clear_bit(OP_INVALID, &priv->op_flags);
htc_start(priv->htc); htc_start(priv->htc);
spin_lock_bh(&priv->tx.tx_lock); spin_lock_bh(&priv->tx.tx_lock);
...@@ -973,7 +978,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) ...@@ -973,7 +978,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
if (priv->op_flags & OP_INVALID) { if (test_bit(OP_INVALID, &priv->op_flags)) {
ath_dbg(common, ANY, "Device not present\n"); ath_dbg(common, ANY, "Device not present\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return; return;
...@@ -1015,7 +1020,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) ...@@ -1015,7 +1020,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
ath9k_htc_ps_restore(priv); ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
priv->op_flags |= OP_INVALID; set_bit(OP_INVALID, &priv->op_flags);
ath_dbg(common, CONFIG, "Driver halt\n"); ath_dbg(common, CONFIG, "Driver halt\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
...@@ -1105,7 +1110,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, ...@@ -1105,7 +1110,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
ath9k_htc_set_opmode(priv); ath9k_htc_set_opmode(priv);
if ((priv->ah->opmode == NL80211_IFTYPE_AP) && if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
!(priv->op_flags & OP_ANI_RUNNING)) { !test_bit(OP_ANI_RUNNING, &priv->op_flags)) {
ath9k_hw_set_tsfadjust(priv->ah, 1); ath9k_hw_set_tsfadjust(priv->ah, 1);
ath9k_htc_start_ani(priv); ath9k_htc_start_ani(priv);
} }
...@@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
struct ieee80211_conf *conf = &hw->conf; struct ieee80211_conf *conf = &hw->conf;
bool chip_reset = false;
int ret = 0;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ath9k_htc_ps_wakeup(priv);
if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (changed & IEEE80211_CONF_CHANGE_IDLE) {
bool enable_radio = false;
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
mutex_lock(&priv->htc_pm_lock); mutex_lock(&priv->htc_pm_lock);
if (!idle && priv->ps_idle)
enable_radio = true;
priv->ps_idle = idle;
mutex_unlock(&priv->htc_pm_lock);
if (enable_radio) { priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
ath_dbg(common, CONFIG, "not-idle: enabling radio\n"); if (priv->ps_idle)
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); chip_reset = true;
ath9k_htc_radio_enable(hw);
} mutex_unlock(&priv->htc_pm_lock);
} }
/* /*
...@@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
ath9k_htc_remove_monitor_interface(priv); ath9k_htc_remove_monitor_interface(priv);
} }
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
struct ieee80211_channel *curchan = hw->conf.channel; struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value; int pos = curchan->hw_value;
...@@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n"); ath_err(common, "Unable to set channel\n");
mutex_unlock(&priv->mutex); ret = -EINVAL;
return -EINVAL; goto out;
} }
} }
...@@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
priv->txpowlimit, &priv->curtxpow); priv->txpowlimit, &priv->curtxpow);
} }
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
mutex_lock(&priv->htc_pm_lock);
if (!priv->ps_idle) {
mutex_unlock(&priv->htc_pm_lock);
goto out;
}
mutex_unlock(&priv->htc_pm_lock);
ath_dbg(common, CONFIG, "idle: disabling radio\n");
ath9k_htc_radio_disable(hw);
}
out: out:
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return 0; return ret;
} }
#define SUPPORTED_FILTERS \ #define SUPPORTED_FILTERS \
...@@ -1285,7 +1275,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, ...@@ -1285,7 +1275,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
changed_flags &= SUPPORTED_FILTERS; changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS;
if (priv->op_flags & OP_INVALID) { if (test_bit(OP_INVALID, &priv->op_flags)) {
ath_dbg(ath9k_hw_common(priv->ah), ANY, ath_dbg(ath9k_hw_common(priv->ah), ANY,
"Unable to configure filter on invalid state\n"); "Unable to configure filter on invalid state\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
...@@ -1516,7 +1506,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1516,7 +1506,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n", ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n",
bss_conf->bssid); bss_conf->bssid);
ath9k_htc_set_tsfadjust(priv, vif); ath9k_htc_set_tsfadjust(priv, vif);
priv->op_flags |= OP_ENABLE_BEACON; set_bit(OP_ENABLE_BEACON, &priv->op_flags);
ath9k_htc_beacon_config(priv, vif); ath9k_htc_beacon_config(priv, vif);
} }
...@@ -1529,7 +1519,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1529,7 +1519,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, ath_dbg(common, CONFIG,
"Beacon disabled for BSS: %pM\n", "Beacon disabled for BSS: %pM\n",
bss_conf->bssid); bss_conf->bssid);
priv->op_flags &= ~OP_ENABLE_BEACON; clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
ath9k_htc_beacon_config(priv, vif); ath9k_htc_beacon_config(priv, vif);
} }
} }
...@@ -1542,7 +1532,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1542,7 +1532,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
(priv->nvifs == 1) && (priv->nvifs == 1) &&
(priv->num_ap_vif == 1) && (priv->num_ap_vif == 1) &&
(vif->type == NL80211_IFTYPE_AP)) { (vif->type == NL80211_IFTYPE_AP)) {
priv->op_flags |= OP_TSF_RESET; set_bit(OP_TSF_RESET, &priv->op_flags);
} }
ath_dbg(common, CONFIG, ath_dbg(common, CONFIG,
"Beacon interval changed for BSS: %pM\n", "Beacon interval changed for BSS: %pM\n",
...@@ -1654,7 +1644,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) ...@@ -1654,7 +1644,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock); spin_lock_bh(&priv->beacon_lock);
priv->op_flags |= OP_SCANNING; set_bit(OP_SCANNING, &priv->op_flags);
spin_unlock_bh(&priv->beacon_lock); spin_unlock_bh(&priv->beacon_lock);
cancel_work_sync(&priv->ps_work); cancel_work_sync(&priv->ps_work);
ath9k_htc_stop_ani(priv); ath9k_htc_stop_ani(priv);
...@@ -1667,7 +1657,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) ...@@ -1667,7 +1657,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock); spin_lock_bh(&priv->beacon_lock);
priv->op_flags &= ~OP_SCANNING; clear_bit(OP_SCANNING, &priv->op_flags);
spin_unlock_bh(&priv->beacon_lock); spin_unlock_bh(&priv->beacon_lock);
ath9k_htc_ps_wakeup(priv); ath9k_htc_ps_wakeup(priv);
ath9k_htc_vif_reconfig(priv); ath9k_htc_vif_reconfig(priv);
......
...@@ -916,7 +916,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv) ...@@ -916,7 +916,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
{ {
ath9k_hw_rxena(priv->ah); ath9k_hw_rxena(priv->ah);
ath9k_htc_opmode_init(priv); ath9k_htc_opmode_init(priv);
ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING)); ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
} }
......
...@@ -1019,16 +1019,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah); ...@@ -1019,16 +1019,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah);
void ar9003_hw_attach_ops(struct ath_hw *ah); void ar9003_hw_attach_ops(struct ath_hw *ah);
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
/*
* ANI work can be shared between all families but a next
* generation implementation of ANI will be used only for AR9003 only
* for now as the other families still need to be tested with the same
* next generation ANI. Feel free to start testing it though for the
* older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
*/
extern int modparam_force_new_ani;
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
...@@ -1038,7 +1030,8 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) ...@@ -1038,7 +1030,8 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
} }
static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah)
{ {
return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI); return ah->common.btcoex_enabled &&
(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
} }
void ath9k_hw_btcoex_enable(struct ath_hw *ah); void ath9k_hw_btcoex_enable(struct ath_hw *ah);
......
...@@ -407,6 +407,7 @@ void ath_ani_calibrate(unsigned long data) ...@@ -407,6 +407,7 @@ void ath_ani_calibrate(unsigned long data)
longcal ? "long" : "", shortcal ? "short" : "", longcal ? "long" : "", shortcal ? "short" : "",
aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
ath9k_debug_samp_bb_mac(sc);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
set_timer: set_timer:
...@@ -415,7 +416,6 @@ void ath_ani_calibrate(unsigned long data) ...@@ -415,7 +416,6 @@ void ath_ani_calibrate(unsigned long data)
* The interval must be the shortest necessary to satisfy ANI, * The interval must be the shortest necessary to satisfy ANI,
* short calibration and long calibration. * short calibration and long calibration.
*/ */
ath9k_debug_samp_bb_mac(sc);
cal_interval = ATH_LONG_CALINTERVAL; cal_interval = ATH_LONG_CALINTERVAL;
if (sc->sc_ah->config.enable_ani) if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval, cal_interval = min(cal_interval,
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "ath9k.h" #include "ath9k.h"
#include "btcoex.h" #include "btcoex.h"
static u8 parse_mpdudensity(u8 mpdudensity) u8 ath9k_parse_mpdudensity(u8 mpdudensity)
{ {
/* /*
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
...@@ -150,8 +150,10 @@ static void __ath_cancel_work(struct ath_softc *sc) ...@@ -150,8 +150,10 @@ static void __ath_cancel_work(struct ath_softc *sc)
cancel_work_sync(&sc->hw_check_work); cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work); cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work); cancel_delayed_work_sync(&sc->hw_pll_work);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
cancel_work_sync(&sc->mci_work); if (ath9k_hw_mci_is_enabled(sc->sc_ah))
cancel_work_sync(&sc->mci_work);
#endif #endif
} }
...@@ -320,6 +322,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, ...@@ -320,6 +322,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct ath_node *an; struct ath_node *an;
u8 density;
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
#ifdef CONFIG_ATH9K_DEBUGFS #ifdef CONFIG_ATH9K_DEBUGFS
...@@ -334,7 +337,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, ...@@ -334,7 +337,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_tx_node_init(sc, an); ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor); sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
an->mpdudensity = density;
} }
} }
...@@ -516,24 +520,6 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -516,24 +520,6 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_hw_set_interrupts(ah); ath9k_hw_set_interrupts(ah);
} }
if (status & ATH9K_INT_MIB) {
/*
* Disable interrupts until we service the MIB
* interrupt; otherwise it will continue to
* fire.
*/
ath9k_hw_disable_interrupts(ah);
/*
* Let the hal handle the event. We assume
* it will clear whatever condition caused
* the interrupt.
*/
spin_lock(&common->cc_lock);
ath9k_hw_proc_mib_event(ah);
spin_unlock(&common->cc_lock);
ath9k_hw_enable_interrupts(ah);
}
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
if (status & ATH9K_INT_TIM_TIMER) { if (status & ATH9K_INT_TIM_TIMER) {
if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle)) if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
...@@ -959,14 +945,10 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, ...@@ -959,14 +945,10 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
/* /*
* Enable MIB interrupts when there are hardware phy counters. * Enable MIB interrupts when there are hardware phy counters.
*/ */
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) { if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
if (ah->config.enable_ani)
ah->imask |= ATH9K_INT_MIB;
ah->imask |= ATH9K_INT_TSFOOR; ah->imask |= ATH9K_INT_TSFOOR;
} else { else
ah->imask &= ~ATH9K_INT_MIB;
ah->imask &= ~ATH9K_INT_TSFOOR; ah->imask &= ~ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(ah); ath9k_hw_set_interrupts(ah);
......
...@@ -233,8 +233,21 @@ static void ath_mci_process_profile(struct ath_softc *sc, ...@@ -233,8 +233,21 @@ static void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *entry = NULL; struct ath_mci_profile_info *entry = NULL;
entry = ath_mci_find_profile(mci, info); entry = ath_mci_find_profile(mci, info);
if (entry) if (entry) {
/*
* Two MCI interrupts are generated while connecting to
* headset and A2DP profile, but only one MCI interrupt
* is generated with last added profile type while disconnecting
* both profiles.
* So while adding second profile type decrement
* the first one.
*/
if (entry->type != info->type) {
DEC_PROF(mci, entry);
INC_PROF(mci, info);
}
memcpy(entry, info, 10); memcpy(entry, info, 10);
}
if (info->start) { if (info->start) {
if (!entry && !ath_mci_add_profile(common, mci, info)) if (!entry && !ath_mci_add_profile(common, mci, info))
...@@ -335,7 +348,7 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) ...@@ -335,7 +348,7 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
seq_num = *((u32 *)(rx_payload + 12)); seq_num = *((u32 *)(rx_payload + 12));
ath_dbg(common, MCI, ath_dbg(common, MCI,
"BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%d\n", "BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%u\n",
profile_status.is_link, profile_status.conn_handle, profile_status.is_link, profile_status.conn_handle,
profile_status.is_critical, seq_num); profile_status.is_critical, seq_num);
......
...@@ -2162,10 +2162,6 @@ enum { ...@@ -2162,10 +2162,6 @@ enum {
#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000 #define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000
#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31 #define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31
#define AR_BTCOEX_WL_WEIGHTS0 0x18b0
#define AR_BTCOEX_WL_WEIGHTS1 0x18b4
#define AR_BTCOEX_WL_WEIGHTS2 0x18b8
#define AR_BTCOEX_WL_WEIGHTS3 0x18bc
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
#define AR_BTCOEX_WL_LNA 0x1940 #define AR_BTCOEX_WL_LNA 0x1940
#define AR_BTCOEX_RFGAIN_CTRL 0x1944 #define AR_BTCOEX_RFGAIN_CTRL 0x1944
......
...@@ -1165,6 +1165,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, ...@@ -1165,6 +1165,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
{ {
struct ath_atx_tid *txtid; struct ath_atx_tid *txtid;
struct ath_node *an; struct ath_node *an;
u8 density;
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid); txtid = ATH_AN_2_TID(an, tid);
...@@ -1172,6 +1173,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, ...@@ -1172,6 +1173,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
return -EAGAIN; return -EAGAIN;
/* update ampdu factor/density, they may have changed. This may happen
* in HT IBSS when a beacon with HT-info is received after the station
* has already been added.
*/
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
an->mpdudensity = density;
}
txtid->state |= AGGR_ADDBA_PROGRESS; txtid->state |= AGGR_ADDBA_PROGRESS;
txtid->paused = true; txtid->paused = true;
*ssn = txtid->seq_start = txtid->seq_next; *ssn = txtid->seq_start = txtid->seq_next;
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
#define SDIO_FUNC1_BLOCKSIZE 64 #define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512 #define SDIO_FUNC2_BLOCKSIZE 512
...@@ -52,6 +53,7 @@ ...@@ -52,6 +53,7 @@
static const struct sdio_device_id brcmf_sdmmc_ids[] = { static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
{ /* end: all zeroes */ }, { /* end: all zeroes */ },
}; };
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
......
...@@ -36,6 +36,13 @@ struct dngl_stats { ...@@ -36,6 +36,13 @@ struct dngl_stats {
unsigned long multicast; /* multicast packets received */ unsigned long multicast; /* multicast packets received */
}; };
struct brcmf_bus_dcmd {
char *name;
char *param;
int param_len;
struct list_head list;
};
/* interface structure between common and bus layer */ /* interface structure between common and bus layer */
struct brcmf_bus { struct brcmf_bus {
u8 type; /* bus type */ u8 type; /* bus type */
...@@ -50,6 +57,7 @@ struct brcmf_bus { ...@@ -50,6 +57,7 @@ struct brcmf_bus {
unsigned long tx_realloc; /* Tx packets realloced for headroom */ unsigned long tx_realloc; /* Tx packets realloced for headroom */
struct dngl_stats dstats; /* Stats for dongle-based data */ struct dngl_stats dstats; /* Stats for dongle-based data */
u8 align; /* bus alignment requirement */ u8 align; /* bus alignment requirement */
struct list_head dcmd_list;
/* interface functions pointers */ /* interface functions pointers */
/* Stop bus module: clear pending frames, disable data flow */ /* Stop bus module: clear pending frames, disable data flow */
......
...@@ -1020,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) ...@@ -1020,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address); INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list); INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
return ret; return ret;
fail: fail:
......
...@@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, ...@@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->c_inf[3].cib = 0x03004211; ci->c_inf[3].cib = 0x03004211;
ci->ramsize = 0x48000; ci->ramsize = 0x48000;
break; break;
case BCM4334_CHIP_ID:
ci->c_inf[0].wrapbase = 0x18100000;
ci->c_inf[0].cib = 0x29004211;
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = 0x18002000;
ci->c_inf[1].wrapbase = 0x18102000;
ci->c_inf[1].cib = 0x0d004211;
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
ci->c_inf[2].base = 0x18004000;
ci->c_inf[2].wrapbase = 0x18104000;
ci->c_inf[2].cib = 0x13080401;
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
ci->c_inf[3].base = 0x18003000;
ci->c_inf[3].wrapbase = 0x18103000;
ci->c_inf[3].cib = 0x07004211;
ci->ramsize = 0x80000;
break;
default: default:
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
return -ENODEV; return -ENODEV;
......
...@@ -1050,6 +1050,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) ...@@ -1050,6 +1050,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
goto fail; goto fail;
} }
brcms_c_regd_init(wl->wlc);
memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
if (WARN_ON(!is_valid_ether_addr(perm))) if (WARN_ON(!is_valid_ether_addr(perm)))
goto fail; goto fail;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册