Commit 61cc776f authored by David S. Miller's avatar David S. Miller

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

John W. Linville says:

====================
Please pull this batch of wireless updates intended for the 3.15
stream!

For the mac80211 bits, Johannes says:

"We have some cleanups and minor fixes as well as userspace API
improvements from a lot of people, extended VHT support for radiotap
from Emmanuel, CSA improvements from Andrei, Luca and Michal. I've also
included my work on hwsim to make dynamic registration of radios
possible."

Along with that, we get the usual round of updates to ath9k,
brcmfmac, mwifiex, wcn36xx, and the ti drivers -- nothing particularly
noteworthy, mostly just random updates and refactoring.

Also included is a pull of the wireless tree, intended to resolve
some potential merge issues.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 010d3c39 88daf80d
......@@ -161,6 +161,8 @@ struct ath_common {
bool btcoex_enabled;
bool disable_ani;
bool bt_ant_diversity;
int last_rssi;
};
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
......
......@@ -204,7 +204,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
break;
/* 80MHZ */
case 2:
status->flag |= RX_FLAG_80MHZ;
status->vht_flag |= RX_VHT_FLAG_80MHZ;
}
status->flag |= RX_FLAG_VHT;
......@@ -266,7 +266,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
status->flag & RX_FLAG_HT ? "ht" : "",
status->flag & RX_FLAG_VHT ? "vht" : "",
status->flag & RX_FLAG_40MHZ ? "40" : "",
status->flag & RX_FLAG_80MHZ ? "80" : "",
status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
status->rate_idx,
status->vht_nss,
......
......@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
if (nw_type & ADHOC_NETWORK) {
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
nw_type & ADHOC_CREATOR ? "creator" : "joiner");
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
cfg80211_put_bss(ar->wiphy, bss);
return;
}
......@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
}
if (vif->nw_type & ADHOC_NETWORK) {
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
"%s: ath6k not in ibss mode\n", __func__);
return;
}
memset(bssid, 0, ETH_ALEN);
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
return;
}
......@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
struct ath6kl_vif *vif = netdev_priv(dev);
u16 interval;
int ret, rssi_thold;
int n_match_sets = request->n_match_sets;
/*
* If there's a matchset w/o an SSID, then assume it's just for
* the RSSI (nothing else is currently supported) and ignore it.
* The device only supports a global RSSI filter that we set below.
*/
if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
n_match_sets = 0;
if (ar->state != ATH6KL_STATE_ON)
return -EIO;
......@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
request->n_ssids,
request->match_sets,
request->n_match_sets);
n_match_sets);
if (ret < 0)
return ret;
if (!request->n_match_sets) {
if (!n_match_sets) {
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
ALL_BSS_FILTER, 0);
if (ret < 0)
......@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
ar->fw_capabilities)) {
if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
rssi_thold = 0;
else if (request->rssi_thold < -127)
else if (request->min_rssi_thold < -127)
rssi_thold = -127;
else
rssi_thold = request->rssi_thold;
rssi_thold = request->min_rssi_thold;
ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
rssi_thold);
......
......@@ -120,18 +120,6 @@ config ATH9K_WOW
This option enables Wake on Wireless LAN support for certain cards.
Currently, AR9462 is supported.
config ATH9K_LEGACY_RATE_CONTROL
bool "Atheros ath9k rate control"
depends on ATH9K
default n
---help---
Say Y, if you want to use the ath9k specific rate control
module instead of minstrel_ht. Be warned that there are various
issues with the ath9k RC and minstrel is a more robust algorithm.
Note that even if this option is selected, "ath9k_rate_control"
has to be passed to mac80211 using the module parameter,
ieee80211_default_rc_algo.
config ATH9K_RFKILL
bool "Atheros ath9k rfkill support" if EXPERT
depends on ATH9K
......
......@@ -8,7 +8,6 @@ ath9k-y += beacon.o \
antenna.o
ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
......
......@@ -30,7 +30,6 @@
#include "spectral.h"
struct ath_node;
struct ath_rate_table;
extern struct ieee80211_ops ath9k_ops;
extern int ath9k_modparam_nohwcrypt;
......@@ -150,6 +149,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
#define IS_OFDM_RATE(rate) ((rate >= 0x8) && (rate <= 0xf))
enum {
WLAN_RC_PHY_OFDM,
WLAN_RC_PHY_CCK,
};
struct ath_txq {
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
u32 axq_qnum; /* ath9k hardware queue number */
......@@ -442,7 +446,8 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_beacon(struct ath_softc *sc);
bool ath9k_csa_is_finished(struct ath_softc *sc);
bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_csa_update(struct ath_softc *sc);
/*******************/
/* Link Monitoring */
......@@ -757,7 +762,6 @@ struct ath_softc {
#endif
struct ath9k_hw_cal_data caldata;
int last_rssi;
#ifdef CONFIG_ATH9K_DEBUGFS
struct ath9k_debug debug;
......@@ -774,7 +778,6 @@ struct ath_softc {
#endif
struct ath_descdma txsdma;
struct ieee80211_vif *csa_vif;
struct ath_ant_comb ant_comb;
u8 ant_tx, ant_rx;
......
......@@ -292,11 +292,8 @@ static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
(unsigned long long)tsfadjust, avp->av_bslot);
}
bool ath9k_csa_is_finished(struct ath_softc *sc)
bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ieee80211_vif *vif;
vif = sc->csa_vif;
if (!vif || !vif->csa_active)
return false;
......@@ -304,11 +301,23 @@ bool ath9k_csa_is_finished(struct ath_softc *sc)
return false;
ieee80211_csa_finish(vif);
sc->csa_vif = NULL;
return true;
}
static void ath9k_csa_update_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath_softc *sc = data;
ath9k_csa_is_finished(sc, vif);
}
void ath9k_csa_update(struct ath_softc *sc)
{
ieee80211_iterate_active_interfaces(sc->hw,
IEEE80211_IFACE_ITER_NORMAL,
ath9k_csa_update_vif,
sc);
}
void ath9k_beacon_tasklet(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
......@@ -362,13 +371,13 @@ void ath9k_beacon_tasklet(unsigned long data)
return;
}
/* EDMA devices check that in the tx completion function. */
if (!edma && ath9k_csa_is_finished(sc))
return;
slot = ath9k_beacon_choose_slot(sc);
vif = sc->beacon.bslot[slot];
/* EDMA devices check that in the tx completion function. */
if (!edma && ath9k_csa_is_finished(sc, vif))
return;
if (!vif || !vif->bss_conf.enable_beacon)
return;
......
......@@ -27,6 +27,250 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
/* Assumes you've already done the endian to CPU conversion */
bool ath9k_cmn_rx_accept(struct ath_common *common,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rxs,
struct ath_rx_status *rx_stats,
bool *decrypt_error,
unsigned int rxfilter)
{
struct ath_hw *ah = common->ah;
bool is_mc, is_valid_tkip, strip_mic, mic_error;
__le16 fc;
fc = hdr->frame_control;
is_mc = !!is_multicast_ether_addr(hdr->addr1);
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
ieee80211_has_protected(fc) &&
!(rx_stats->rs_status &
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS));
/*
* Key miss events are only relevant for pairwise keys where the
* descriptor does contain a valid key index. This has been observed
* mostly with CCMP encryption.
*/
if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
!ieee80211_has_morefrags(fc) &&
!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
(rx_stats->rs_status & ATH9K_RXERR_MIC);
/*
* The rx_stats->rs_status will not be set until the end of the
* chained descriptors so it can be ignored if rs_more is set. The
* rs_more will be false at the last element of the chained
* descriptors.
*/
if (rx_stats->rs_status != 0) {
u8 status_mask;
if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
mic_error = false;
}
if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
*decrypt_error = true;
mic_error = false;
}
/*
* Reject error frames with the exception of
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS;
if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
status_mask |= ATH9K_RXERR_CRC;
if (rx_stats->rs_status & ~status_mask)
return false;
}
/*
* For unicast frames the MIC error bit can have false positives,
* so all MIC error reports need to be validated in software.
* False negatives are not common, so skip software verification
* if the hardware considers the MIC valid.
*/
if (strip_mic)
rxs->flag |= RX_FLAG_MMIC_STRIPPED;
else if (is_mc && mic_error)
rxs->flag |= RX_FLAG_MMIC_ERROR;
return true;
}
EXPORT_SYMBOL(ath9k_cmn_rx_accept);
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
struct sk_buff *skb,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs,
bool decrypt_error)
{
struct ath_hw *ah = common->ah;
struct ieee80211_hdr *hdr;
int hdrlen, padpos, padsize;
u8 keyix;
__le16 fc;
/* see if any padding is done by the hw and remove it */
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
padpos = ieee80211_hdrlen(fc);
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
* padsize would take into account odd header lengths:
* padsize = (4 - padpos % 4) % 4; However, since only
* even-length headers are used, padding can only be 0 or 2
* bytes and we can optimize this a bit. In addition, we must
* not try to remove padding from short control frames that do
* not have payload. */
padsize = padpos & 3;
if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
}
keyix = rx_stats->rs_keyix;
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
ieee80211_has_protected(fc)) {
rxs->flag |= RX_FLAG_DECRYPTED;
} else if (ieee80211_has_protected(fc)
&& !decrypt_error && skb->len >= hdrlen + 4) {
keyix = skb->data[hdrlen + 3] >> 6;
if (test_bit(keyix, common->keymap))
rxs->flag |= RX_FLAG_DECRYPTED;
}
if (ah->sw_mgmt_crypto &&
(rxs->flag & RX_FLAG_DECRYPTED) &&
ieee80211_is_mgmt(fc))
/* Use software decrypt for management frames. */
rxs->flag &= ~RX_FLAG_DECRYPTED;
}
EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
int ath9k_cmn_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs)
{
struct ieee80211_supported_band *sband;
enum ieee80211_band band;
unsigned int i = 0;
struct ath_hw *ah = common->ah;
band = ah->curchan->chan->band;
sband = hw->wiphy->bands[band];
if (IS_CHAN_QUARTER_RATE(ah->curchan))
rxs->flag |= RX_FLAG_5MHZ;
else if (IS_CHAN_HALF_RATE(ah->curchan))
rxs->flag |= RX_FLAG_10MHZ;
if (rx_stats->rs_rate & 0x80) {
/* HT rate */
rxs->flag |= RX_FLAG_HT;
rxs->flag |= rx_stats->flag;
rxs->rate_idx = rx_stats->rs_rate & 0x7f;
return 0;
}
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
rxs->rate_idx = i;
return 0;
}
if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
rxs->flag |= RX_FLAG_SHORTPRE;
rxs->rate_idx = i;
return 0;
}
}
return -EINVAL;
}
EXPORT_SYMBOL(ath9k_cmn_process_rate);
void ath9k_cmn_process_rssi(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs)
{
struct ath_hw *ah = common->ah;
int last_rssi;
int rssi = rx_stats->rs_rssi;
int i, j;
/*
* RSSI is not available for subframes in an A-MPDU.
*/
if (rx_stats->rs_moreaggr) {
rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
return;
}
/*
* Check if the RSSI for the last subframe in an A-MPDU
* or an unaggregated frame is valid.
*/
if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
return;
}
for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
s8 rssi;
if (!(ah->rxchainmask & BIT(i)))
continue;
rssi = rx_stats->rs_rssi_ctl[i];
if (rssi != ATH9K_RSSI_BAD) {
rxs->chains |= BIT(j);
rxs->chain_signal[j] = ah->noise + rssi;
}
j++;
}
/*
* Update Beacon RSSI, this is used by ANI.
*/
if (rx_stats->is_mybeacon &&
((ah->opmode == NL80211_IFTYPE_STATION) ||
(ah->opmode == NL80211_IFTYPE_ADHOC))) {
ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
last_rssi = common->last_rssi;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
if (rssi < 0)
rssi = 0;
ah->stats.avgbrssi = rssi;
}
rxs->signal = ah->noise + rx_stats->rs_rssi;
}
EXPORT_SYMBOL(ath9k_cmn_process_rssi);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
......
......@@ -42,6 +42,25 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))
bool ath9k_cmn_rx_accept(struct ath_common *common,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rxs,
struct ath_rx_status *rx_stats,
bool *decrypt_error,
unsigned int rxfilter);
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
struct sk_buff *skb,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs,
bool decrypt_error);
int ath9k_cmn_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs);
void ath9k_cmn_process_rssi(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
struct ath_hw *ah,
......
......@@ -18,7 +18,6 @@
#define DEBUG_H
#include "hw.h"
#include "rc.h"
#include "dfs_debug.h"
struct ath_txq;
......
......@@ -21,6 +21,8 @@
#include "hw.h"
struct ath_softc;
/**
* struct ath_dfs_stats - DFS Statistics per wiphy
* @pulses_total: pulses reported by HW
......
......@@ -54,6 +54,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
.driver_info = AR9280_USB }, /* SMC Networks */
{ USB_DEVICE(0x0411, 0x017f),
.driver_info = AR9280_USB }, /* Sony UWA-BR100 */
{ USB_DEVICE(0x0411, 0x0197),
.driver_info = AR9280_USB }, /* Buffalo WLI-UV-AG300P */
{ USB_DEVICE(0x04da, 0x3904),
.driver_info = AR9280_USB },
......
......@@ -277,7 +277,6 @@ struct ath9k_htc_rxbuf {
};
struct ath9k_htc_rx {
int last_rssi; /* FIXME: per-STA */
struct list_head rxbuf;
spinlock_t rxbuflock;
};
......
......@@ -611,6 +611,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
priv->ah->opmode = NL80211_IFTYPE_STATION;
}
......
......@@ -1474,6 +1474,7 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) {
common->curaid = bss_conf->aid;
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
}
}
......
......@@ -927,43 +927,39 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
ath9k_hw_rxena(priv->ah);
ath9k_htc_opmode_init(priv);
ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
}
static void ath9k_process_rate(struct ieee80211_hw *hw,
struct ieee80211_rx_status *rxs,
u8 rx_rate, u8 rs_flags)
static inline void convert_htc_flag(struct ath_rx_status *rx_stats,
struct ath_htc_rx_status *rxstatus)
{
struct ieee80211_supported_band *sband;
enum ieee80211_band band;
unsigned int i = 0;
if (rx_rate & 0x80) {
/* HT rate */
rxs->flag |= RX_FLAG_HT;
if (rs_flags & ATH9K_RX_2040)
rxs->flag |= RX_FLAG_40MHZ;
if (rs_flags & ATH9K_RX_GI)
rxs->flag |= RX_FLAG_SHORT_GI;
rxs->rate_idx = rx_rate & 0x7f;
return;
}
band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].hw_value == rx_rate) {
rxs->rate_idx = i;
return;
}
if (sband->bitrates[i].hw_value_short == rx_rate) {
rxs->rate_idx = i;
rxs->flag |= RX_FLAG_SHORTPRE;
return;
}
}
rx_stats->flag = 0;
if (rxstatus->rs_flags & ATH9K_RX_2040)
rx_stats->flag |= RX_FLAG_40MHZ;
if (rxstatus->rs_flags & ATH9K_RX_GI)
rx_stats->flag |= RX_FLAG_SHORT_GI;
}
static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats,
struct ath_htc_rx_status *rxstatus)
{
rx_stats->rs_datalen = rxstatus->rs_datalen;
rx_stats->rs_status = rxstatus->rs_status;
rx_stats->rs_phyerr = rxstatus->rs_phyerr;
rx_stats->rs_rssi = rxstatus->rs_rssi;
rx_stats->rs_keyix = rxstatus->rs_keyix;
rx_stats->rs_rate = rxstatus->rs_rate;
rx_stats->rs_antenna = rxstatus->rs_antenna;
rx_stats->rs_more = rxstatus->rs_more;
memcpy(rx_stats->rs_rssi_ctl, rxstatus->rs_rssi_ctl,
sizeof(rx_stats->rs_rssi_ctl));
memcpy(rx_stats->rs_rssi_ext, rxstatus->rs_rssi_ext,
sizeof(rx_stats->rs_rssi_ext));
rx_stats->rs_isaggr = rxstatus->rs_isaggr;
rx_stats->rs_moreaggr = rxstatus->rs_moreaggr;
rx_stats->rs_num_delims = rxstatus->rs_num_delims;
convert_htc_flag(rx_stats, rxstatus);
}
static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
......@@ -975,10 +971,10 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw = priv->hw;
struct sk_buff *skb = rxbuf->skb;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath_hw *ah = common->ah;
struct ath_htc_rx_status *rxstatus;
int hdrlen, padsize;
int last_rssi = ATH_RSSI_DUMMY_MARKER;
__le16 fc;
struct ath_rx_status rx_stats;
bool decrypt_error;
if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
......@@ -999,103 +995,39 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
ath9k_htc_err_stat_rx(priv, rxstatus);
/* Get the RX status information */
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
padsize = hdrlen & 3;
if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
memmove(skb->data + padsize, skb->data, hdrlen);
skb_pull(skb, padsize);
}
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
if (rxbuf->rxstatus.rs_status != 0) {
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY)
goto rx_next;
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) {
/* FIXME */
} else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) {
if (ieee80211_is_ctl(fc))
/*
* Sometimes, we get invalid
* MIC failures on valid control frames.
* Remove these mic errors.
*/
rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC;
else
rx_status->flag |= RX_FLAG_MMIC_ERROR;
}
/*
* Reject error frames with the exception of
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) {
if (rxbuf->rxstatus.rs_status &
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_CRC))
goto rx_next;
} else {
if (rxbuf->rxstatus.rs_status &
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
goto rx_next;
}
}
}
if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) {
u8 keyix;
keyix = rxbuf->rxstatus.rs_keyix;
if (keyix != ATH9K_RXKEYIX_INVALID) {
rx_status->flag |= RX_FLAG_DECRYPTED;
} else if (ieee80211_has_protected(fc) &&
skb->len >= hdrlen + 4) {
keyix = skb->data[hdrlen + 3] >> 6;
if (test_bit(keyix, common->keymap))
rx_status->flag |= RX_FLAG_DECRYPTED;
}
}
ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
rxbuf->rxstatus.rs_flags);
if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
!rxbuf->rxstatus.rs_moreaggr)
ATH_RSSI_LPF(priv->rx.last_rssi,
rxbuf->rxstatus.rs_rssi);
last_rssi = priv->rx.last_rssi;
/* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).
* After this, we can drop this part of skb. */
rx_status_htc_to_ath(&rx_stats, rxstatus);
rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
if (ath_is_mybeacon(common, hdr)) {
s8 rssi = rxbuf->rxstatus.rs_rssi;
/*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
hdr = (struct ieee80211_hdr *)skb->data;
if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats,
&decrypt_error, priv->rxfilter))
goto rx_next;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
ath9k_cmn_rx_skb_postprocess(common, skb, &rx_stats,
rx_status, decrypt_error);
if (rssi < 0)
rssi = 0;
if (ath9k_cmn_process_rate(common, hw, &rx_stats, rx_status))
goto rx_next;
priv->ah->stats.avgbrssi = rssi;
}
rx_stats.is_mybeacon = ath_is_mybeacon(common, hdr);
ath9k_cmn_process_rssi(common, hw, &rx_stats, rx_status);
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
rx_status->band = hw->conf.chandef.chan->band;
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
rx_status->band = ah->curchan->chan->band;
rx_status->freq = ah->curchan->chan->center_freq;
rx_status->antenna = rx_stats.rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
return true;
rx_next:
return false;
}
......
......@@ -358,6 +358,36 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
kfree_skb(skb);
}
static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
struct sk_buff *skb)
{
uint32_t *pattern = (uint32_t *)skb->data;
switch (*pattern) {
case 0x33221199:
{
struct htc_panic_bad_vaddr *htc_panic;
htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
dev_err(htc_handle->dev, "ath: firmware panic! "
"exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
htc_panic->exccause, htc_panic->pc,
htc_panic->badvaddr);
break;
}
case 0x33221299:
{
struct htc_panic_bad_epid *htc_panic;
htc_panic = (struct htc_panic_bad_epid *) skb->data;
dev_err(htc_handle->dev, "ath: firmware panic! "
"bad epid: 0x%08x\n", htc_panic->epid);
break;
}
default:
dev_err(htc_handle->dev, "ath: uknown panic pattern!\n");
break;
}
}
/*
* HTC Messages are handled directly here and the obtained SKB
* is freed.
......@@ -379,6 +409,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
htc_hdr = (struct htc_frame_hdr *) skb->data;
epid = htc_hdr->endpoint_id;
if (epid == 0x99) {
ath9k_htc_fw_panic_report(htc_handle, skb);
kfree_skb(skb);
return;
}
if (epid >= ENDPOINT_MAX) {
if (pipe_id != USB_REG_IN_PIPE)
dev_kfree_skb_any(skb);
......
......@@ -77,6 +77,18 @@ struct htc_config_pipe_msg {
u8 credits;
} __packed;
struct htc_panic_bad_vaddr {
__be32 pattern;
__be32 exccause;
__be32 pc;
__be32 badvaddr;
} __packed;
struct htc_panic_bad_epid {
__be32 pattern;
__be32 epid;
} __packed;
struct htc_ep_callbacks {
void *priv;
void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
......
......@@ -23,7 +23,6 @@
#include "hw.h"
#include "hw-ops.h"
#include "rc.h"
#include "ar9003_mac.h"
#include "ar9003_mci.h"
#include "ar9003_phy.h"
......
......@@ -538,7 +538,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->config.txpowlimit = ATH_TXPOWER_MAX;
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
sc->beacon.slottime = ATH9K_SLOT_TIME_9;
......@@ -1106,19 +1106,11 @@ static int __init ath9k_init(void)
{
int error;
/* Register rate control algorithm */
error = ath_rate_control_register();
if (error != 0) {
pr_err("Unable to register rate control algorithm: %d\n",
error);
goto err_out;
}
error = ath_pci_init();
if (error < 0) {
pr_err("No PCI devices found, driver not installed\n");
error = -ENODEV;
goto err_rate_unregister;
goto err_out;
}
error = ath_ahb_init();
......@@ -1131,9 +1123,6 @@ static int __init ath9k_init(void)
err_pci_exit:
ath_pci_exit();
err_rate_unregister:
ath_rate_control_unregister();
err_out:
return error;
}
......@@ -1144,7 +1133,6 @@ static void __exit ath9k_exit(void)
is_ath9k_unloaded = true;
ath_ahb_exit();
ath_pci_exit();
ath_rate_control_unregister();
pr_info("%s: Driver unloaded\n", dev_info);
}
module_exit(ath9k_exit);
......@@ -155,12 +155,8 @@ struct ath_htc_rx_status {
u8 rs_status;
u8 rs_phyerr;
int8_t rs_rssi;
int8_t rs_rssi_ctl0;
int8_t rs_rssi_ctl1;
int8_t rs_rssi_ctl2;
int8_t rs_rssi_ext0;
int8_t rs_rssi_ext1;
int8_t rs_rssi_ext2;
int8_t rs_rssi_ctl[3];
int8_t rs_rssi_ext[3];
u8 rs_keyix;
u8 rs_rate;
u8 rs_antenna;
......@@ -170,6 +166,7 @@ struct ath_htc_rx_status {
u8 rs_num_delims;
u8 rs_flags;
u8 rs_dummy;
/* FIXME: evm* never used? */
__be32 evm0;
__be32 evm1;
__be32 evm2;
......
......@@ -1178,9 +1178,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_remove_slot(sc, vif);
if (sc->csa_vif == vif)
sc->csa_vif = NULL;
ath9k_ps_wakeup(sc);
ath9k_calculate_summary_state(hw, NULL);
ath9k_ps_restore(sc);
......@@ -1609,7 +1606,7 @@ static void ath9k_set_assoc_state(struct ath_softc *sc,
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
......@@ -1866,7 +1863,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
static bool ath9k_has_tx_pending(struct ath_softc *sc)
{
int i, npend;
int i, npend = 0;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (!ATH_TXQ_SETUP(sc, i))
......@@ -2086,13 +2083,8 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_chan_def *chandef)
{
struct ath_softc *sc = hw->priv;
/* mac80211 does not support CSA in multi-if cases (yet) */
if (WARN_ON(sc->csa_vif))
return;
sc->csa_vif = vif;
/* depend on vif->csa_active only */
return;
}
struct ieee80211_ops ath9k_ops = {
......
This diff is collapsed.
/*
* Copyright (c) 2004 Sam Leffler, Errno Consulting
* Copyright (c) 2004 Video54 Technologies, Inc.
* Copyright (c) 2008-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef RC_H
#define RC_H
#include "hw.h"
struct ath_softc;
#define ATH_RATE_MAX 30
#define RATE_TABLE_SIZE 72
#define RC_INVALID 0x0000
#define RC_LEGACY 0x0001
#define RC_SS 0x0002
#define RC_DS 0x0004
#define RC_TS 0x0008
#define RC_HT_20 0x0010
#define RC_HT_40 0x0020
#define RC_STREAM_MASK 0xe
#define RC_DS_OR_LATER(f) ((((f) & RC_STREAM_MASK) == RC_DS) || \
(((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
#define RC_TS_ONLY(f) (((f) & RC_STREAM_MASK) == RC_TS)
#define RC_SS_OR_LEGACY(f) ((f) & (RC_SS | RC_LEGACY))
#define RC_HT_2040 (RC_HT_20 | RC_HT_40)
#define RC_ALL_STREAM (RC_SS | RC_DS | RC_TS)
#define RC_L_SD (RC_LEGACY | RC_SS | RC_DS)
#define RC_L_SDT (RC_LEGACY | RC_SS | RC_DS | RC_TS)
#define RC_HT_S_20 (RC_HT_20 | RC_SS)
#define RC_HT_D_20 (RC_HT_20 | RC_DS)
#define RC_HT_T_20 (RC_HT_20 | RC_TS)
#define RC_HT_S_40 (RC_HT_40 | RC_SS)
#define RC_HT_D_40 (RC_HT_40 | RC_DS)
#define RC_HT_T_40 (RC_HT_40 | RC_TS)
#define RC_HT_SD_20 (RC_HT_20 | RC_SS | RC_DS)
#define RC_HT_DT_20 (RC_HT_20 | RC_DS | RC_TS)
#define RC_HT_SD_40 (RC_HT_40 | RC_SS | RC_DS)
#define RC_HT_DT_40 (RC_HT_40 | RC_DS | RC_TS)
#define RC_HT_SD_2040 (RC_HT_2040 | RC_SS | RC_DS)
#define RC_HT_SDT_2040 (RC_HT_2040 | RC_SS | RC_DS | RC_TS)
#define RC_HT_SDT_20 (RC_HT_20 | RC_SS | RC_DS | RC_TS)
#define RC_HT_SDT_40 (RC_HT_40 | RC_SS | RC_DS | RC_TS)
#define RC_ALL (RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)
enum {
WLAN_RC_PHY_OFDM,
WLAN_RC_PHY_CCK,
WLAN_RC_PHY_HT_20_SS,
WLAN_RC_PHY_HT_20_DS,
WLAN_RC_PHY_HT_20_TS,
WLAN_RC_PHY_HT_40_SS,
WLAN_RC_PHY_HT_40_DS,
WLAN_RC_PHY_HT_40_TS,
WLAN_RC_PHY_HT_20_SS_HGI,
WLAN_RC_PHY_HT_20_DS_HGI,
WLAN_RC_PHY_HT_20_TS_HGI,
WLAN_RC_PHY_HT_40_SS_HGI,
WLAN_RC_PHY_HT_40_DS_HGI,
WLAN_RC_PHY_HT_40_TS_HGI,
WLAN_RC_PHY_MAX
};
#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
#define WLAN_RC_PHY_TS(_phy) ((_phy == WLAN_RC_PHY_HT_20_TS) \
|| (_phy == WLAN_RC_PHY_HT_40_TS) \
|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \
|| (_phy == WLAN_RC_PHY_HT_20_DS) \
|| (_phy == WLAN_RC_PHY_HT_20_TS) \
|| (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
|| (_phy == WLAN_RC_PHY_HT_40_TS) \
|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))
#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ? \
(RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))
/* Return TRUE if flag supports HT20 && client supports HT20 or
* return TRUE if flag supports HT40 && client supports HT40.
* This is used becos some rates overlap between HT20/HT40.
*/
#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
(((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))
#define WLAN_RC_DS_FLAG (0x01)
#define WLAN_RC_TS_FLAG (0x02)
#define WLAN_RC_40_FLAG (0x04)
#define WLAN_RC_SGI_FLAG (0x08)
#define WLAN_RC_HT_FLAG (0x10)
/**
* struct ath_rate_table - Rate Control table
* @rate_cnt: total number of rates for the given wireless mode
* @mcs_start: MCS rate index offset
* @rate_flags: Rate Control flags
* @phy: CCK/OFDM/HT20/HT40
* @ratekbps: rate in Kbits per second
* @user_ratekbps: user rate in Kbits per second
* @ratecode: rate that goes into HW descriptors
* @dot11rate: value that goes into supported
* rates info element of MLME
* @ctrl_rate: Index of next lower basic rate, used for duration computation
* @cw40index: Index of rates having 40MHz channel width
* @sgi_index: Index of rates having Short Guard Interval
* @ht_index: high throughput rates having 40MHz channel width and
* Short Guard Interval
* @probe_interval: interval for rate control to probe for other rates
* @initial_ratemax: initial ratemax value
*/
struct ath_rate_table {
int rate_cnt;
int mcs_start;
struct {
u16 rate_flags;
u8 phy;
u32 ratekbps;
u32 user_ratekbps;
u8 ratecode;
u8 dot11rate;
} info[RATE_TABLE_SIZE];
u32 probe_interval;
u8 initial_ratemax;
};
struct ath_rateset {
u8 rs_nrates;
u8 rs_rates[ATH_RATE_MAX];
};
struct ath_rc_stats {
u32 success;
u32 retries;
u32 xretries;
u8 per;
};
/**
* struct ath_rate_priv - Rate Control priv data
* @state: RC state
* @probe_rate: rate we are probing at
* @probe_time: msec timestamp for last probe
* @hw_maxretry_pktcnt: num of packets since we got HW max retry error
* @max_valid_rate: maximum number of valid rate
* @per_down_time: msec timestamp for last PER down step
* @valid_phy_ratecnt: valid rate count
* @rate_max_phy: phy index for the max rate
* @per: PER for every valid rate in %
* @probe_interval: interval for ratectrl to probe for other rates
* @ht_cap: HT capabilities
* @neg_rates: Negotatied rates
* @neg_ht_rates: Negotiated HT rates
*/
struct ath_rate_priv {
u8 rate_table_size;
u8 probe_rate;
u8 hw_maxretry_pktcnt;
u8 max_valid_rate;
u8 valid_rate_index[RATE_TABLE_SIZE];
u8 ht_cap;
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
u8 rate_max_phy;
u8 per[RATE_TABLE_SIZE];
u32 probe_time;
u32 per_down_time;
u32 probe_interval;
struct ath_rateset neg_rates;
struct ath_rateset neg_ht_rates;
const struct ath_rate_table *rate_table;
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
struct dentry *debugfs_rcstats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
#endif
};
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate);
void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
int xretries, int retries, u8 per);
#else
static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
{
}
static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
int xretries, int retries, u8 per)
{
}
#endif
#ifdef CONFIG_ATH9K_LEGACY_RATE_CONTROL
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
#else
static inline int ath_rate_control_register(void)
{
return 0;
}
static inline void ath_rate_control_unregister(void)
{
}
#endif
#endif /* RC_H */
......@@ -755,204 +755,6 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
return bf;
}
/* Assumes you've already done the endian to CPU conversion */
static bool ath9k_rx_accept(struct ath_common *common,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rxs,
struct ath_rx_status *rx_stats,
bool *decrypt_error)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
bool is_mc, is_valid_tkip, strip_mic, mic_error;
struct ath_hw *ah = common->ah;
__le16 fc;
fc = hdr->frame_control;
is_mc = !!is_multicast_ether_addr(hdr->addr1);
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
ieee80211_has_protected(fc) &&
!(rx_stats->rs_status &
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS));
/*
* Key miss events are only relevant for pairwise keys where the
* descriptor does contain a valid key index. This has been observed
* mostly with CCMP encryption.
*/
if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
!ieee80211_has_morefrags(fc) &&
!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
(rx_stats->rs_status & ATH9K_RXERR_MIC);
/*
* The rx_stats->rs_status will not be set until the end of the
* chained descriptors so it can be ignored if rs_more is set. The
* rs_more will be false at the last element of the chained
* descriptors.
*/
if (rx_stats->rs_status != 0) {
u8 status_mask;
if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
mic_error = false;
}
if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
*decrypt_error = true;
mic_error = false;
}
/*
* Reject error frames with the exception of
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS;
if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
status_mask |= ATH9K_RXERR_CRC;
if (rx_stats->rs_status & ~status_mask)
return false;
}
/*
* For unicast frames the MIC error bit can have false positives,
* so all MIC error reports need to be validated in software.
* False negatives are not common, so skip software verification
* if the hardware considers the MIC valid.
*/
if (strip_mic)
rxs->flag |= RX_FLAG_MMIC_STRIPPED;
else if (is_mc && mic_error)
rxs->flag |= RX_FLAG_MMIC_ERROR;
return true;
}
static int ath9k_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs)
{
struct ieee80211_supported_band *sband;
enum ieee80211_band band;
unsigned int i = 0;
struct ath_softc __maybe_unused *sc = common->priv;
struct ath_hw *ah = sc->sc_ah;
band = ah->curchan->chan->band;
sband = hw->wiphy->bands[band];
if (IS_CHAN_QUARTER_RATE(ah->curchan))
rxs->flag |= RX_FLAG_5MHZ;
else if (IS_CHAN_HALF_RATE(ah->curchan))
rxs->flag |= RX_FLAG_10MHZ;
if (rx_stats->rs_rate & 0x80) {
/* HT rate */
rxs->flag |= RX_FLAG_HT;
rxs->flag |= rx_stats->flag;
rxs->rate_idx = rx_stats->rs_rate & 0x7f;
return 0;
}
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
rxs->rate_idx = i;
return 0;
}
if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
rxs->flag |= RX_FLAG_SHORTPRE;
rxs->rate_idx = i;
return 0;
}
}
/*
* No valid hardware bitrate found -- we should not get here
* because hardware has already validated this frame as OK.
*/
ath_dbg(common, ANY,
"unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate);
RX_STAT_INC(rx_rate_err);
return -EINVAL;
}
static void ath9k_process_rssi(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = common->ah;
int last_rssi;
int rssi = rx_stats->rs_rssi;
int i, j;
/*
* RSSI is not available for subframes in an A-MPDU.
*/
if (rx_stats->rs_moreaggr) {
rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
return;
}
/*
* Check if the RSSI for the last subframe in an A-MPDU
* or an unaggregated frame is valid.
*/
if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
return;
}
for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
s8 rssi;
if (!(ah->rxchainmask & BIT(i)))
continue;
rssi = rx_stats->rs_rssi_ctl[i];
if (rssi != ATH9K_RSSI_BAD) {
rxs->chains |= BIT(j);
rxs->chain_signal[j] = ah->noise + rssi;
}
j++;
}
/*
* Update Beacon RSSI, this is used by ANI.
*/
if (rx_stats->is_mybeacon &&
((ah->opmode == NL80211_IFTYPE_STATION) ||
(ah->opmode == NL80211_IFTYPE_ADHOC))) {
ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
last_rssi = sc->last_rssi;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
if (rssi < 0)
rssi = 0;
ah->stats.avgbrssi = rssi;
}
rxs->signal = ah->noise + rx_stats->rs_rssi;
}
static void ath9k_process_tsf(struct ath_rx_status *rs,
struct ieee80211_rx_status *rxs,
u64 tsf)
......@@ -1051,7 +853,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error, sc->rx.rxfilter)) {
ret = -EINVAL;
goto exit;
}
......@@ -1069,12 +871,19 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
goto exit;
}
if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status)) {
/*
* No valid hardware bitrate found -- we should not get here
* because hardware has already validated this frame as OK.
*/
ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate);
RX_STAT_INC(rx_rate_err);
ret =-EINVAL;
goto exit;
}
ath9k_process_rssi(common, hw, rx_stats, rx_status);
ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
rx_status->band = ah->curchan->chan->band;
rx_status->freq = ah->curchan->chan->center_freq;
......@@ -1092,57 +901,6 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
return ret;
}
static void ath9k_rx_skb_postprocess(struct ath_common *common,
struct sk_buff *skb,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rxs,
bool decrypt_error)
{
struct ath_hw *ah = common->ah;
struct ieee80211_hdr *hdr;
int hdrlen, padpos, padsize;
u8 keyix;
__le16 fc;
/* see if any padding is done by the hw and remove it */
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
padpos = ieee80211_hdrlen(fc);
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
* padsize would take into account odd header lengths:
* padsize = (4 - padpos % 4) % 4; However, since only
* even-length headers are used, padding can only be 0 or 2
* bytes and we can optimize this a bit. In addition, we must
* not try to remove padding from short control frames that do
* not have payload. */
padsize = padpos & 3;
if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
}
keyix = rx_stats->rs_keyix;
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
ieee80211_has_protected(fc)) {
rxs->flag |= RX_FLAG_DECRYPTED;
} else if (ieee80211_has_protected(fc)
&& !decrypt_error && skb->len >= hdrlen + 4) {
keyix = skb->data[hdrlen + 3] >> 6;
if (test_bit(keyix, common->keymap))
rxs->flag |= RX_FLAG_DECRYPTED;
}
if (ah->sw_mgmt_crypto &&
(rxs->flag & RX_FLAG_DECRYPTED) &&
ieee80211_is_mgmt(fc))
/* Use software decrypt for management frames. */
rxs->flag &= ~RX_FLAG_DECRYPTED;
}
/*
* Run the LNA combining algorithm only in these cases:
*
......@@ -1292,8 +1050,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
skb_pull(skb, ah->caps.rx_status_len);
if (!rs.rs_more)
ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
rxs, decrypt_error);
ath9k_cmn_rx_skb_postprocess(common, hdr_skb, &rs,
rxs, decrypt_error);
if (rs.rs_more) {
RX_STAT_INC(rx_frags);
......
......@@ -2566,7 +2566,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
sc->beacon.tx_processed = true;
sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
ath9k_csa_is_finished(sc);
ath9k_csa_update(sc);
continue;
}
......
......@@ -44,6 +44,14 @@ static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
writel(data, wcn->mmio + addr);
}
#define wcn36xx_dxe_write_register_x(wcn, reg, reg_data) \
do { \
if (wcn->chip_version == WCN36XX_CHIP_3680) \
wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
else \
wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
} while (0) \
static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
{
*data = readl(wcn->mmio + addr);
......@@ -680,7 +688,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/* Setting interrupt path */
reg_data = WCN36XX_DXE_CCU_INT;
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
/***************************************/
/* Init descriptors for TX LOW channel */
......
......@@ -28,11 +28,11 @@ H2H_TEST_RX_TX = DMA2
*/
/* DXE registers */
#define WCN36XX_DXE_MEM_BASE 0x03000000
#define WCN36XX_DXE_MEM_REG 0x202000
#define WCN36XX_DXE_CCU_INT 0xA0011
#define WCN36XX_DXE_REG_CCU_INT 0x200b10
#define WCN36XX_DXE_REG_CCU_INT_3660 0x200b10
#define WCN36XX_DXE_REG_CCU_INT_3680 0x2050dc
/* TODO This must calculated properly but not hardcoded */
#define WCN36XX_DXE_CTRL_TX_L 0x328a44
......
......@@ -4384,11 +4384,13 @@ enum place_holder_in_cap_bitmap {
MAX_FEATURE_SUPPORTED = 128,
};
#define WCN36XX_HAL_CAPS_SIZE 4
struct wcn36xx_hal_feat_caps_msg {
struct wcn36xx_hal_msg_header header;
u32 feat_caps[4];
u32 feat_caps[WCN36XX_HAL_CAPS_SIZE];
} __packed;
/* status codes to help debug rekey failures */
......
......@@ -17,6 +17,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
#include "wcn36xx.h"
......@@ -177,6 +178,60 @@ static inline u8 get_sta_index(struct ieee80211_vif *vif,
sta_priv->sta_index;
}
static const char * const wcn36xx_caps_names[] = {
"MCC", /* 0 */
"P2P", /* 1 */
"DOT11AC", /* 2 */
"SLM_SESSIONIZATION", /* 3 */
"DOT11AC_OPMODE", /* 4 */
"SAP32STA", /* 5 */
"TDLS", /* 6 */
"P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
"WLANACTIVE_OFFLOAD", /* 8 */
"BEACON_OFFLOAD", /* 9 */
"SCAN_OFFLOAD", /* 10 */
"ROAM_OFFLOAD", /* 11 */
"BCN_MISS_OFFLOAD", /* 12 */
"STA_POWERSAVE", /* 13 */
"STA_ADVANCED_PWRSAVE", /* 14 */
"AP_UAPSD", /* 15 */
"AP_DFS", /* 16 */
"BLOCKACK", /* 17 */
"PHY_ERR", /* 18 */
"BCN_FILTER", /* 19 */
"RTT", /* 20 */
"RATECTRL", /* 21 */
"WOW" /* 22 */
};
static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
{
if (x >= ARRAY_SIZE(wcn36xx_caps_names))
return "UNKNOWN";
return wcn36xx_caps_names[x];
}
static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
{
int i;
for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
if (get_feat_caps(wcn->fw_feat_caps, i))
wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i));
}
}
static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
{
if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
wcn36xx_info("Chip is 3680\n");
wcn->chip_version = WCN36XX_CHIP_3680;
} else {
wcn36xx_info("Chip is 3660\n");
wcn->chip_version = WCN36XX_CHIP_3660;
}
}
static int wcn36xx_start(struct ieee80211_hw *hw)
{
struct wcn36xx *wcn = hw->priv;
......@@ -223,6 +278,16 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
goto out_free_smd_buf;
}
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
ret = wcn36xx_smd_feature_caps_exchange(wcn);
if (ret)
wcn36xx_warn("Exchange feature caps failed\n");
else
wcn36xx_feat_caps_info(wcn);
}
wcn36xx_detect_chip_version(wcn);
/* DMA channel initialization */
ret = wcn36xx_dxe_init(wcn);
if (ret) {
......@@ -232,11 +297,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
wcn36xx_debugfs_init(wcn);
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
ret = wcn36xx_smd_feature_caps_exchange(wcn);
if (ret)
wcn36xx_warn("Exchange feature caps failed\n");
}
INIT_LIST_HEAD(&wcn->vif_list);
return 0;
......@@ -648,6 +708,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->enable_beacon);
if (bss_conf->enable_beacon) {
vif_priv->dtim_period = bss_conf->dtim_period;
vif_priv->bss_index = 0xff;
wcn36xx_smd_config_bss(wcn, vif, NULL,
vif->addr, false);
......@@ -992,6 +1053,7 @@ static int wcn36xx_remove(struct platform_device *pdev)
struct wcn36xx *wcn = hw->priv;
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
release_firmware(wcn->nv);
mutex_destroy(&wcn->hal_mutex);
ieee80211_unregister_hw(hw);
......
......@@ -195,9 +195,11 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
{
int ret = 0;
unsigned long start;
wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
init_completion(&wcn->hal_rsp_compl);
start = jiffies;
ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
if (ret) {
wcn36xx_err("HAL TX failed\n");
......@@ -205,10 +207,13 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
}
if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
wcn36xx_err("Timeout while waiting SMD response\n");
wcn36xx_err("Timeout! No SMD response in %dms\n",
HAL_MSG_TIMEOUT);
ret = -ETIME;
goto out;
}
wcn36xx_dbg(WCN36XX_DBG_SMD, "SMD command completed in %dms",
jiffies_to_msecs(jiffies - start));
out:
return ret;
}
......@@ -246,21 +251,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
{
const struct firmware *nv;
struct nv_data *nv_d;
struct wcn36xx_hal_nv_img_download_req_msg msg_body;
int fw_bytes_left;
int ret;
u16 fm_offset = 0;
ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev);
if (ret) {
wcn36xx_err("Failed to load nv file %s: %d\n",
WLAN_NV_FILE, ret);
goto out_free_nv;
if (!wcn->nv) {
ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
if (ret) {
wcn36xx_err("Failed to load nv file %s: %d\n",
WLAN_NV_FILE, ret);
goto out;
}
}
nv_d = (struct nv_data *)nv->data;
nv_d = (struct nv_data *)wcn->nv->data;
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
......@@ -270,7 +276,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
mutex_lock(&wcn->hal_mutex);
do {
fw_bytes_left = nv->size - fm_offset - 4;
fw_bytes_left = wcn->nv->size - fm_offset - 4;
if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
msg_body.last_fragment = 0;
msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
......@@ -308,10 +314,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
out_unlock:
mutex_unlock(&wcn->hal_mutex);
out_free_nv:
release_firmware(nv);
return ret;
out: return ret;
}
static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
......@@ -899,11 +902,12 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
sta_priv->sta_index = params->sta_index;
sta_priv->dpu_desc_index = params->dpu_index;
sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
wcn36xx_dbg(WCN36XX_DBG_HAL,
"hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n",
"hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
params->status, params->sta_index, params->bssid_index,
params->p2p);
params->uc_ucast_sig, params->p2p);
return 0;
}
......@@ -1118,7 +1122,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
}
priv_vif->ucast_dpu_signature = params->ucast_dpu_signature;
priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature;
return 0;
}
......@@ -1637,12 +1641,12 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
if (ret) {
wcn36xx_err("Sending hal_exit_bmps failed\n");
wcn36xx_err("Sending hal_keep_alive failed\n");
goto out;
}
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
goto out;
}
out:
......@@ -1682,8 +1686,7 @@ int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
return ret;
}
static inline void set_feat_caps(u32 *bitmap,
enum place_holder_in_cap_bitmap cap)
void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
{
int arr_idx, bit_idx;
......@@ -1697,8 +1700,7 @@ static inline void set_feat_caps(u32 *bitmap,
bitmap[arr_idx] |= (1 << bit_idx);
}
static inline int get_feat_caps(u32 *bitmap,
enum place_holder_in_cap_bitmap cap)
int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
{
int arr_idx, bit_idx;
int ret = 0;
......@@ -1714,8 +1716,7 @@ static inline int get_feat_caps(u32 *bitmap,
return ret;
}
static inline void clear_feat_caps(u32 *bitmap,
enum place_holder_in_cap_bitmap cap)
void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
{
int arr_idx, bit_idx;
......@@ -1731,8 +1732,8 @@ static inline void clear_feat_caps(u32 *bitmap,
int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
{
struct wcn36xx_hal_feat_caps_msg msg_body;
int ret = 0;
struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
int ret = 0, i;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
......@@ -1746,12 +1747,15 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
goto out;
}
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n",
ret);
if (wcn->hal_rsp_len != sizeof(*rsp)) {
wcn36xx_err("Invalid hal_feature_caps_exchange response");
goto out;
}
rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
wcn->fw_feat_caps[i] = rsp->feat_caps[i];
out:
mutex_unlock(&wcn->hal_mutex);
return ret;
......
......@@ -24,7 +24,7 @@
#define WCN36XX_HAL_BUF_SIZE 4096
#define HAL_MSG_TIMEOUT 200
#define HAL_MSG_TIMEOUT 500
#define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400
#define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200
/* The PNO version info be contained in the rsp msg */
......@@ -112,6 +112,9 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
u32 arg3, u32 arg4, u32 arg5);
int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn);
void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap);
int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap);
void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap);
int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
struct ieee80211_sta *sta,
......
......@@ -57,8 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
RX_FLAG_MMIC_STRIPPED |
RX_FLAG_DECRYPTED;
wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n",
status.flag, status.vendor_radiotap_len);
wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
......@@ -132,6 +131,7 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
struct ieee80211_vif,
drv_priv);
bd->dpu_sign = sta_priv->ucast_dpu_sign;
if (vif->type == NL80211_IFTYPE_STATION) {
bd->sta_index = sta_priv->bss_sta_index;
bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index;
......@@ -145,10 +145,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
__vif_priv = get_vif_by_addr(wcn, hdr->addr2);
bd->sta_index = __vif_priv->self_sta_index;
bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
}
bd->dpu_sign = __vif_priv->ucast_dpu_signature;
if (ieee80211_is_nullfunc(hdr->frame_control) ||
(sta_priv && !sta_priv->is_data_encrypted))
bd->dpu_ne = 1;
......
......@@ -125,10 +125,10 @@ struct wcn36xx_vif {
enum wcn36xx_power_state pw_state;
u8 bss_index;
u8 ucast_dpu_signature;
/* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */
u8 self_sta_index;
u8 self_dpu_desc_index;
u8 self_ucast_dpu_sign;
};
/**
......@@ -159,6 +159,7 @@ struct wcn36xx_sta {
u16 tid;
u8 sta_index;
u8 dpu_desc_index;
u8 ucast_dpu_sign;
u8 bss_sta_index;
u8 bss_dpu_desc_index;
bool is_data_encrypted;
......@@ -171,10 +172,14 @@ struct wcn36xx {
struct device *dev;
struct list_head vif_list;
const struct firmware *nv;
u8 fw_revision;
u8 fw_version;
u8 fw_minor;
u8 fw_major;
u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
u32 chip_version;
/* extra byte for the NULL termination */
u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
......@@ -222,6 +227,9 @@ struct wcn36xx {
};
#define WCN36XX_CHIP_3660 0
#define WCN36XX_CHIP_3680 1
static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
u8 major,
u8 minor,
......
......@@ -58,41 +58,6 @@ enum b43_verbosity {
#endif
};
/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
static inline u8 b43_freq_to_channel_5ghz(int freq)
{
return ((freq - 5000) / 5);
}
static inline u8 b43_freq_to_channel_2ghz(int freq)
{
u8 channel;
if (freq == 2484)
channel = 14;
else
channel = (freq - 2407) / 5;
return channel;
}
/* Lightweight function to convert a channel number to a frequency (in Mhz). */
static inline int b43_channel_to_freq_5ghz(u8 channel)
{
return (5000 + (5 * channel));
}
static inline int b43_channel_to_freq_2ghz(u8 channel)
{
int freq;
if (channel == 14)
freq = 2484;
else
freq = 2407 + (5 * channel);
return freq;
}
static inline int b43_is_cck_rate(int rate)
{
return (rate == B43_CCK_RATE_1MB ||
......
......@@ -806,7 +806,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
B43_WARN_ON(1);
/* FIXME: We don't really know which value the "chanid" contains.
* So the following assignment might be wrong. */
status.freq = b43_channel_to_freq_5ghz(chanid);
status.freq =
ieee80211_channel_to_frequency(chanid, status.band);
break;
case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ;
......@@ -819,13 +820,12 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
case B43_PHYTYPE_HT:
/* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */
if (chanstat & B43_RX_CHAN_5GHZ) {
if (chanstat & B43_RX_CHAN_5GHZ)
status.band = IEEE80211_BAND_5GHZ;
status.freq = b43_channel_to_freq_5ghz(chanid);
} else {
else
status.band = IEEE80211_BAND_2GHZ;
status.freq = b43_channel_to_freq_2ghz(chanid);
}
status.freq =
ieee80211_channel_to_frequency(chanid, status.band);
break;
default:
B43_WARN_ON(1);
......
......@@ -24,6 +24,7 @@ ccflags-y += -D__CHECK_ENDIAN__
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += \
wl_cfg80211.o \
chip.o \
fwil.o \
fweh.o \
fwsignal.o \
......@@ -36,8 +37,7 @@ brcmfmac-objs += \
btcoex.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
bcmsdh.o \
sdio_chip.o
bcmsdh.o
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
usb.o
brcmfmac-$(CONFIG_BRCMDBG) += \
......
......@@ -43,7 +43,6 @@
#include "dhd_bus.h"
#include "dhd_dbg.h"
#include "sdio_host.h"
#include "sdio_chip.h"
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
......@@ -827,7 +826,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
}
if (!write)
memcpy(data, pkt->data, dsize);
skb_trim(pkt, dsize);
skb_trim(pkt, 0);
/* Adjust for next transfer (if any) */
size -= dsize;
......@@ -1115,11 +1114,12 @@ static struct sdio_driver brcmf_sdmmc_driver = {
.remove = brcmf_ops_sdio_remove,
.name = BRCMFMAC_SDIO_PDATA_NAME,
.id_table = brcmf_sdmmc_ids,
#ifdef CONFIG_PM_SLEEP
.drv = {
.owner = THIS_MODULE,
#ifdef CONFIG_PM_SLEEP
.pm = &brcmf_sdio_pm_ops,
},
#endif /* CONFIG_PM_SLEEP */
},
};
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
......
This diff is collapsed.
/*
* Copyright (c) 2014 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef BRCMF_CHIP_H
#define BRCMF_CHIP_H
#include <linux/types.h>
#define CORE_CC_REG(base, field) \
(base + offsetof(struct chipcregs, field))
/**
* struct brcmf_chip - chip level information.
*
* @chip: chip identifier.
* @chiprev: chip revision.
* @cc_caps: chipcommon core capabilities.
* @pmucaps: PMU capabilities.
* @pmurev: PMU revision.
* @rambase: RAM base address (only applicable for ARM CR4 chips).
* @ramsize: amount of RAM on chip.
* @name: string representation of the chip identifier.
*/
struct brcmf_chip {
u32 chip;
u32 chiprev;
u32 cc_caps;
u32 pmucaps;
u32 pmurev;
u32 rambase;
u32 ramsize;
char name[8];
};
/**
* struct brcmf_core - core related information.
*
* @id: core identifier.
* @rev: core revision.
* @base: base address of core register space.
*/
struct brcmf_core {
u16 id;
u16 rev;
u32 base;
};
/**
* struct brcmf_buscore_ops - buscore specific callbacks.
*
* @read32: read 32-bit value over bus.
* @write32: write 32-bit value over bus.
* @prepare: prepare bus for core configuration.
* @setup: bus-specific core setup.
* @exit_dl: exit download state.
* The callback should use the provided @rstvec when non-zero.
*/
struct brcmf_buscore_ops {
u32 (*read32)(void *ctx, u32 addr);
void (*write32)(void *ctx, u32 addr, u32 value);
int (*prepare)(void *ctx);
int (*setup)(void *ctx, struct brcmf_chip *chip);
void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
};
struct brcmf_chip *brcmf_chip_attach(void *ctx,
const struct brcmf_buscore_ops *ops);
void brcmf_chip_detach(struct brcmf_chip *chip);
struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
bool brcmf_chip_iscoreup(struct brcmf_core *core);
void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
u32 postreset);
void brcmf_chip_enter_download(struct brcmf_chip *ci);
bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec);
bool brcmf_chip_sr_capable(struct brcmf_chip *pub);
#endif /* BRCMF_AXIDMP_H */
......@@ -124,7 +124,8 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
}
static u32
brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
brcmf_create_iovar(char *name, const char *data, u32 datalen,
char *buf, u32 buflen)
{
u32 len;
......@@ -144,7 +145,7 @@ brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
s32
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
u32 len)
{
struct brcmf_pub *drvr = ifp->drvr;
......
......@@ -83,7 +83,7 @@ s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
u32 len);
s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
u32 len);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment