Major changes:
mwifiex: * enhancements for AP mode: support verbose information in station dump command and also information about AP link. * enable power save by default brcmfmac: * fix module reload issue for PCIe * improving msgbuf protocol for PCIe devices * rework .get_station() cfg80211 callback operation * determine interface combinations upon device feature support ath9k: * ath9k_htc: add support of channel switch wil6210: * add modparam for bcast ring size * support hidden SSID * add per-MCS Rx stats -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAABAgAGBQJVglpWAAoJEG4XJFUm622bkT0H+QE/T3i44l6SEAxHEgW6Z2JP MsAVHFV8q2jPCGfg4oCozk3fo2WPdBKwhUy7xzAg/LfxuTn0CtIzl+KuEnhsBBsx +cNBFgBzIvHaMwfb/vxmuLK7zUROtDgOK7Kt4HF9p/Mn/JH8yTCrRy96hpnVKnuQ h6HFO8Qx0l0pd6lbosaSPvjM8qBPy3ZfvriEHV3BTV+AXgSPWwnFkY188G2CNK5J yYK0C2PkEX368m/qpmcbhlYrn3ZiJviiWhFmQZMW8eXe0k/pfBidXt6QGmKA7loT p09skJk+qQtZjK4p2Hzy/3KOLU7YGFVHzww5gXqrZSxhluyhEdbOVLvKfB5jR68= =3lke -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2015-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== Major changes: mwifiex: * enhancements for AP mode: support verbose information in station dump command and also information about AP link. * enable power save by default brcmfmac: * fix module reload issue for PCIe * improving msgbuf protocol for PCIe devices * rework .get_station() cfg80211 callback operation * determine interface combinations upon device feature support ath9k: * ath9k_htc: add support of channel switch wil6210: * add modparam for bcast ring size * support hidden SSID * add per-MCS Rx stats ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fa433354f0
|
@ -8169,8 +8169,6 @@ P: rt2x00 project
|
|||
M: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
M: Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: users@rt2x00.serialmonkey.com (moderated for non-subscribers)
|
||||
W: http://rt2x00.serialmonkey.com/
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/rt2x00/
|
||||
|
||||
|
|
|
@ -29,12 +29,6 @@ config BCMA_HOST_PCI
|
|||
select BCMA_DRIVER_PCI
|
||||
default y
|
||||
|
||||
config BCMA_DRIVER_PCI_HOSTMODE
|
||||
bool "Driver for PCI core working in hostmode"
|
||||
depends on BCMA && MIPS && BCMA_HOST_PCI
|
||||
help
|
||||
PCI core hostmode operation (external PCI bus).
|
||||
|
||||
config BCMA_HOST_SOC
|
||||
bool "Support for BCMA in a SoC"
|
||||
depends on BCMA
|
||||
|
@ -61,6 +55,12 @@ config BCMA_DRIVER_PCI
|
|||
This driver is also prerequisite for a hostmode PCIe core
|
||||
support.
|
||||
|
||||
config BCMA_DRIVER_PCI_HOSTMODE
|
||||
bool "Driver for PCI core working in hostmode"
|
||||
depends on BCMA && MIPS && BCMA_DRIVER_PCI
|
||||
help
|
||||
PCI core hostmode operation (external PCI bus).
|
||||
|
||||
config BCMA_DRIVER_MIPS
|
||||
bool "BCMA Broadcom MIPS core driver"
|
||||
depends on BCMA && MIPS
|
||||
|
|
|
@ -48,6 +48,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.name = "qca988x hw2.0",
|
||||
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.has_shifted_cc_wraparound = true,
|
||||
.fw = {
|
||||
.dir = QCA988X_HW_2_0_FW_DIR,
|
||||
.fw = QCA988X_HW_2_0_FW_FILE,
|
||||
|
@ -1084,6 +1085,22 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
|||
if (status)
|
||||
goto err;
|
||||
|
||||
/* Some of of qca988x solutions are having global reset issue
|
||||
* during target initialization. Bypassing PLL setting before
|
||||
* downloading firmware and letting the SoC run on REF_CLK is
|
||||
* fixing the problem. Corresponding firmware change is also needed
|
||||
* to set the clock source once the target is initialized.
|
||||
*/
|
||||
if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT,
|
||||
ar->fw_features)) {
|
||||
status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1);
|
||||
if (status) {
|
||||
ath10k_err(ar, "could not write to skip_clock_init: %d\n",
|
||||
status);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
status = ath10k_download_fw(ar, mode);
|
||||
if (status)
|
||||
goto err;
|
||||
|
|
|
@ -284,15 +284,6 @@ struct ath10k_sta {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct ath10k_chanctx {
|
||||
/* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally
|
||||
* mac80211 should allow some sort of explicit locking to guarantee
|
||||
* that the publicly available chanctx_conf can be accessed safely at
|
||||
* all times.
|
||||
*/
|
||||
struct ieee80211_chanctx_conf conf;
|
||||
};
|
||||
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
|
||||
|
||||
enum ath10k_beacon_state {
|
||||
|
@ -468,6 +459,9 @@ enum ath10k_fw_features {
|
|||
*/
|
||||
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
|
||||
|
||||
/* Firmware supports bypassing PLL setting on init. */
|
||||
ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
|
@ -577,6 +571,13 @@ struct ath10k {
|
|||
u32 patch_load_addr;
|
||||
int uart_pin;
|
||||
|
||||
/* This is true if given HW chip has a quirky Cycle Counter
|
||||
* wraparound which resets to 0x7fffffff instead of 0. All
|
||||
* other CC related counters (e.g. Rx Clear Count) are divided
|
||||
* by 2 so they never wraparound themselves.
|
||||
*/
|
||||
bool has_shifted_cc_wraparound;
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *fw;
|
||||
|
@ -694,6 +695,14 @@ struct ath10k {
|
|||
u32 survey_last_cycle_count;
|
||||
struct survey_info survey[ATH10K_NUM_CHANS];
|
||||
|
||||
/* Channel info events are expected to come in pairs without and with
|
||||
* COMPLETE flag set respectively for each channel visit during scan.
|
||||
*
|
||||
* However there are deviations from this rule. This flag is used to
|
||||
* avoid reporting garbage data.
|
||||
*/
|
||||
bool ch_info_can_report_survey;
|
||||
|
||||
struct dfs_pattern_detector *dfs_detector;
|
||||
|
||||
unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "core.h"
|
||||
#include "hw.h"
|
||||
|
||||
const struct ath10k_hw_regs qca988x_regs = {
|
||||
|
@ -56,3 +57,23 @@ const struct ath10k_hw_regs qca6174_regs = {
|
|||
.soc_chip_id_address = 0x000f0,
|
||||
.scratch_3_address = 0x0028,
|
||||
};
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
|
||||
{
|
||||
u32 cc_fix = 0;
|
||||
|
||||
survey->filled |= SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY;
|
||||
|
||||
if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) {
|
||||
cc_fix = 0x7fffffff;
|
||||
survey->filled &= ~SURVEY_INFO_TIME_BUSY;
|
||||
}
|
||||
|
||||
cc -= cc_prev - cc_fix;
|
||||
rcc -= rcc_prev;
|
||||
|
||||
survey->time = CCNT_TO_MSEC(cc);
|
||||
survey->time_busy = CCNT_TO_MSEC(rcc);
|
||||
}
|
||||
|
|
|
@ -169,6 +169,9 @@ struct ath10k_hw_regs {
|
|||
extern const struct ath10k_hw_regs qca988x_regs;
|
||||
extern const struct ath10k_hw_regs qca6174_regs;
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
|
||||
|
||||
#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
|
||||
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
|
||||
|
||||
|
@ -449,6 +452,9 @@ enum ath10k_hw_rate_cck {
|
|||
#define SCRATCH_3_ADDRESS ar->regs->scratch_3_address
|
||||
#define CPU_INTR_ADDRESS 0x0010
|
||||
|
||||
/* Cycle counters are running at 88MHz */
|
||||
#define CCNT_TO_MSEC(x) ((x) / 88000)
|
||||
|
||||
/* Firmware indications to the Host via SCRATCH_3 register. */
|
||||
#define FW_INDICATOR_ADDRESS (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS)
|
||||
#define FW_IND_EVENT_PENDING 1
|
||||
|
|
|
@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_mac_chan_reconfigure(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_vif *arvif;
|
||||
struct cfg80211_chan_def def;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n");
|
||||
|
||||
/* First stop monitor interface. Some FW versions crash if there's a
|
||||
* lone monitor interface. */
|
||||
if (ar->monitor_started)
|
||||
ath10k_monitor_stop(ar);
|
||||
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (!arvif->is_started)
|
||||
continue;
|
||||
|
||||
if (!arvif->is_up)
|
||||
continue;
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
||||
continue;
|
||||
|
||||
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to down vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* all vdevs are downed now - attempt to restart and re-up them */
|
||||
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (!arvif->is_started)
|
||||
continue;
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
||||
continue;
|
||||
|
||||
ret = ath10k_mac_setup_bcn_tmpl(arvif);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
|
||||
ret);
|
||||
|
||||
ret = ath10k_mac_setup_prb_tmpl(arvif);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
|
||||
ret);
|
||||
|
||||
if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
|
||||
continue;
|
||||
|
||||
ret = ath10k_vdev_restart(arvif, &def);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to restart vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!arvif->is_up)
|
||||
continue;
|
||||
|
||||
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
||||
arvif->bssid);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ath10k_monitor_recalc(ar);
|
||||
}
|
||||
|
||||
static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
|
||||
{
|
||||
int ret;
|
||||
|
@ -6144,7 +6067,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
static void
|
||||
ath10k_mac_update_rx_channel(struct ath10k *ar)
|
||||
ath10k_mac_update_rx_channel(struct ath10k *ar,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs)
|
||||
{
|
||||
struct cfg80211_chan_def *def = NULL;
|
||||
|
||||
|
@ -6154,6 +6080,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
|
|||
lockdep_assert_held(&ar->conf_mutex);
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
WARN_ON(ctx && vifs);
|
||||
WARN_ON(vifs && n_vifs != 1);
|
||||
|
||||
/* FIXME: Sort of an optimization and a workaround. Peers and vifs are
|
||||
* on a linked list now. Doing a lookup peer -> vif -> chanctx for each
|
||||
* ppdu on Rx may reduce performance on low-end systems. It should be
|
||||
|
@ -6165,36 +6094,28 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
|
|||
* affected much.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
if (ath10k_mac_num_chanctxs(ar) == 1) {
|
||||
if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) {
|
||||
ieee80211_iter_chan_contexts_atomic(ar->hw,
|
||||
ath10k_mac_get_any_chandef_iter,
|
||||
&def);
|
||||
|
||||
if (vifs)
|
||||
def = &vifs[0].new_ctx->def;
|
||||
|
||||
ar->rx_channel = def->chan;
|
||||
} else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
|
||||
ar->rx_channel = ctx->def.chan;
|
||||
} else {
|
||||
ar->rx_channel = NULL;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_mac_chan_ctx_init(struct ath10k *ar,
|
||||
struct ath10k_chanctx *arctx,
|
||||
struct ieee80211_chanctx_conf *conf)
|
||||
{
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
memset(arctx, 0, sizeof(*arctx));
|
||||
|
||||
arctx->conf = *conf;
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx add freq %hu width %d ptr %p\n",
|
||||
|
@ -6203,8 +6124,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ath10k_mac_chan_ctx_init(ar, arctx, ctx);
|
||||
ath10k_mac_update_rx_channel(ar);
|
||||
ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath10k_recalc_radar_detection(ar);
|
||||
|
@ -6228,7 +6148,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ath10k_mac_update_rx_channel(ar);
|
||||
ath10k_mac_update_rx_channel(ar, NULL, NULL, 0);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath10k_recalc_radar_detection(ar);
|
||||
|
@ -6243,16 +6163,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
|
|||
u32 changed)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n",
|
||||
arctx->conf.def.chan->center_freq,
|
||||
ctx->def.chan->center_freq,
|
||||
arctx->conf.def.width, ctx->def.width,
|
||||
ctx, changed);
|
||||
"mac chanctx change freq %hu width %d ptr %p changed %x\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
|
||||
|
||||
/* This shouldn't really happen because channel switching should use
|
||||
* switch_vif_chanctx().
|
||||
|
@ -6260,10 +6176,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
|
|||
if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
|
||||
goto unlock;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arctx->conf = *ctx;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath10k_recalc_radar_detection(ar);
|
||||
|
||||
/* FIXME: How to configure Rx chains properly? */
|
||||
|
@ -6283,7 +6195,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
int ret;
|
||||
|
||||
|
@ -6298,11 +6209,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = ath10k_vdev_start(arvif, &arctx->conf.def);
|
||||
ret = ath10k_vdev_start(arvif, &ctx->def);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n",
|
||||
arvif->vdev_id, vif->addr,
|
||||
arctx->conf.def.chan->center_freq, ret);
|
||||
ctx->def.chan->center_freq, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -6377,7 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_vif *arvif;
|
||||
struct ath10k_chanctx *arctx_new, *arctx_old;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
@ -6386,38 +6297,81 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
|||
"mac chanctx switch n_vifs %d mode %d\n",
|
||||
n_vifs, mode);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
/* First stop monitor interface. Some FW versions crash if there's a
|
||||
* lone monitor interface.
|
||||
*/
|
||||
if (ar->monitor_started)
|
||||
ath10k_monitor_stop(ar);
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
arvif = ath10k_vif_to_arvif(vifs[i].vif);
|
||||
arctx_new = (void *)vifs[i].new_ctx->drv_priv;
|
||||
arctx_old = (void *)vifs[i].old_ctx->drv_priv;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n",
|
||||
"mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
|
||||
arvif->vdev_id,
|
||||
vifs[i].old_ctx->def.chan->center_freq,
|
||||
vifs[i].new_ctx->def.chan->center_freq,
|
||||
vifs[i].old_ctx->def.width,
|
||||
vifs[i].new_ctx->def.width,
|
||||
arctx_old, arctx_new);
|
||||
vifs[i].new_ctx->def.width);
|
||||
|
||||
if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
|
||||
ath10k_mac_chan_ctx_init(ar, arctx_new,
|
||||
vifs[i].new_ctx);
|
||||
if (WARN_ON(!arvif->is_started))
|
||||
continue;
|
||||
|
||||
if (WARN_ON(!arvif->is_up))
|
||||
continue;
|
||||
|
||||
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to down vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
arctx_new->conf = *vifs[i].new_ctx;
|
||||
|
||||
/* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not
|
||||
* yet updated chanctx_conf pointer.
|
||||
*/
|
||||
arctx_old->conf = *vifs[i].new_ctx;
|
||||
}
|
||||
ath10k_mac_update_rx_channel(ar);
|
||||
|
||||
/* All relevant vdevs are downed and associated channel resources
|
||||
* should be available for the channel switch now.
|
||||
*/
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* FIXME: Reconfigure only affected vifs */
|
||||
ath10k_mac_chan_reconfigure(ar);
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
arvif = ath10k_vif_to_arvif(vifs[i].vif);
|
||||
|
||||
if (WARN_ON(!arvif->is_started))
|
||||
continue;
|
||||
|
||||
if (WARN_ON(!arvif->is_up))
|
||||
continue;
|
||||
|
||||
ret = ath10k_mac_setup_bcn_tmpl(arvif);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
|
||||
ret);
|
||||
|
||||
ret = ath10k_mac_setup_prb_tmpl(arvif);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
|
||||
ret);
|
||||
|
||||
ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to restart vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
||||
arvif->bssid);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ath10k_monitor_recalc(ar);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return 0;
|
||||
|
@ -6914,7 +6868,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
|
||||
ar->hw->vif_data_size = sizeof(struct ath10k_vif);
|
||||
ar->hw->sta_data_size = sizeof(struct ath10k_sta);
|
||||
ar->hw->chanctx_data_size = sizeof(struct ath10k_chanctx);
|
||||
|
||||
ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
|
||||
|
||||
|
|
|
@ -1424,7 +1424,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
|
|||
struct ath10k_ce_ring *ce_ring;
|
||||
struct ce_desc *ce_desc;
|
||||
struct sk_buff *skb;
|
||||
unsigned int id;
|
||||
int i;
|
||||
|
||||
ar = pci_pipe->hif_ce_state;
|
||||
|
@ -1448,8 +1447,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
|
|||
continue;
|
||||
|
||||
ce_ring->per_transfer_context[i] = NULL;
|
||||
id = MS(__le16_to_cpu(ce_desc[i].flags),
|
||||
CE_DESC_FLAGS_META_DATA);
|
||||
|
||||
ar_pci->msg_callbacks_current.tx_completion(ar, skb);
|
||||
}
|
||||
|
@ -2850,6 +2847,7 @@ err_free_pipes:
|
|||
ath10k_pci_free_pipes(ar);
|
||||
|
||||
err_sleep:
|
||||
ath10k_pci_sleep_sync(ar);
|
||||
ath10k_pci_release(ar);
|
||||
|
||||
err_core_destroy:
|
||||
|
@ -2927,8 +2925,10 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
|
|||
|
||||
/* QCA6174 2.1 firmware files */
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE);
|
||||
|
||||
/* QCA6174 3.1 firmware files */
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
|
||||
|
|
|
@ -402,7 +402,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
|
||||
|
||||
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
|
||||
|
||||
|
@ -521,6 +521,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "testmode.h"
|
||||
#include "wmi-ops.h"
|
||||
#include "p2p.h"
|
||||
#include "hw.h"
|
||||
|
||||
/* MAIN WMI cmd track */
|
||||
static struct wmi_cmd_map wmi_cmd_map = {
|
||||
|
@ -1450,6 +1451,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1636,20 +1638,22 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) {
|
||||
/* During scanning chan info is reported twice for each
|
||||
* visited channel. The reported cycle count is global
|
||||
* and per-channel cycle count must be calculated */
|
||||
if (ar->ch_info_can_report_survey) {
|
||||
survey = &ar->survey[idx];
|
||||
survey->noise = noise_floor;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
|
||||
cycle_count -= ar->survey_last_cycle_count;
|
||||
rx_clear_count -= ar->survey_last_rx_clear_count;
|
||||
ath10k_hw_fill_survey_time(ar,
|
||||
survey,
|
||||
cycle_count,
|
||||
rx_clear_count,
|
||||
ar->survey_last_cycle_count,
|
||||
ar->survey_last_rx_clear_count);
|
||||
}
|
||||
|
||||
survey = &ar->survey[idx];
|
||||
survey->time = WMI_CHAN_INFO_MSEC(cycle_count);
|
||||
survey->time_busy = WMI_CHAN_INFO_MSEC(rx_clear_count);
|
||||
survey->noise = noise_floor;
|
||||
survey->filled = SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_NOISE_DBM;
|
||||
ar->ch_info_can_report_survey = false;
|
||||
} else {
|
||||
ar->ch_info_can_report_survey = true;
|
||||
}
|
||||
|
||||
ar->survey_last_rx_clear_count = rx_clear_count;
|
||||
|
@ -3219,7 +3223,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
|
||||
|
||||
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
|
||||
|
||||
|
@ -3323,6 +3327,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
@ -3336,7 +3341,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
|
||||
|
||||
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
|
||||
|
||||
|
@ -3459,7 +3464,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
|
||||
|
||||
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
|
||||
|
||||
|
@ -3567,6 +3572,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
|
|
@ -4665,7 +4665,6 @@ struct wmi_peer_sta_kickout_event {
|
|||
} __packed;
|
||||
|
||||
#define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)
|
||||
#define WMI_CHAN_INFO_MSEC(x) ((x) / 88000)
|
||||
|
||||
/* Beacon filter wmi command info */
|
||||
#define BCN_FLT_MAX_SUPPORTED_IES 256
|
||||
|
|
|
@ -1527,8 +1527,8 @@ struct wmi_connect_event {
|
|||
__le32 nw_type;
|
||||
} sta;
|
||||
struct {
|
||||
u8 phymode;
|
||||
u8 aid;
|
||||
u8 phymode;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 auth;
|
||||
u8 keymgmt;
|
||||
|
|
|
@ -531,6 +531,7 @@ struct ath9k_htc_priv {
|
|||
struct ath9k_debug debug;
|
||||
#endif
|
||||
struct mutex mutex;
|
||||
struct ieee80211_vif *csa_vif;
|
||||
};
|
||||
|
||||
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
||||
|
@ -584,6 +585,7 @@ void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
|
|||
void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
|
||||
void ath9k_tx_failed_tasklet(unsigned long data);
|
||||
void ath9k_htc_tx_cleanup_timer(unsigned long data);
|
||||
bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv);
|
||||
|
||||
int ath9k_rx_init(struct ath9k_htc_priv *priv);
|
||||
void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
|
||||
|
|
|
@ -257,6 +257,8 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
|
|||
}
|
||||
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
|
||||
ath9k_htc_csa_is_finished(priv);
|
||||
}
|
||||
|
||||
static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
|
||||
|
@ -503,3 +505,20 @@ void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
vif = priv->csa_vif;
|
||||
if (!vif || !vif->csa_active)
|
||||
return false;
|
||||
|
||||
if (!ieee80211_csa_is_complete(vif))
|
||||
return false;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
|
||||
priv->csa_vif = NULL;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -744,7 +744,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
|||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
|
||||
|
||||
|
|
|
@ -1134,6 +1134,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
|
|||
priv->nvifs--;
|
||||
priv->vif_slot &= ~(1 << avp->index);
|
||||
|
||||
if (priv->csa_vif == vif)
|
||||
priv->csa_vif = NULL;
|
||||
|
||||
ath9k_htc_remove_station(priv, vif, NULL);
|
||||
|
||||
DEC_VIF(priv, vif->type);
|
||||
|
@ -1841,6 +1844,19 @@ static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_htc_channel_switch_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
/* mac80211 does not support CSA in multi-if cases (yet) */
|
||||
if (WARN_ON(priv->csa_vif))
|
||||
return;
|
||||
|
||||
priv->csa_vif = vif;
|
||||
}
|
||||
|
||||
struct ieee80211_ops ath9k_htc_ops = {
|
||||
.tx = ath9k_htc_tx,
|
||||
.start = ath9k_htc_start,
|
||||
|
@ -1867,6 +1883,7 @@ struct ieee80211_ops ath9k_htc_ops = {
|
|||
.set_bitrate_mask = ath9k_htc_set_bitrate_mask,
|
||||
.get_stats = ath9k_htc_get_stats,
|
||||
.get_antenna = ath9k_htc_get_antenna,
|
||||
.channel_switch_beacon = ath9k_htc_channel_switch_beacon,
|
||||
|
||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
||||
.get_et_sset_count = ath9k_htc_get_et_sset_count,
|
||||
|
|
|
@ -216,11 +216,13 @@ static bool ath_prepare_reset(struct ath_softc *sc)
|
|||
ath_stop_ani(sc);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
if (!ath_drain_all_txq(sc))
|
||||
ret = false;
|
||||
|
||||
if (!ath_stoprecv(sc))
|
||||
ret = false;
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ret &= ath_stoprecv(sc);
|
||||
ret &= ath_drain_all_txq(sc);
|
||||
} else {
|
||||
ret &= ath_drain_all_txq(sc);
|
||||
ret &= ath_stoprecv(sc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -289,6 +289,26 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
|
||||
wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
|
||||
|
||||
for (i = 0; i < request->n_ssids; i++) {
|
||||
wil_dbg_misc(wil, "SSID[%d]", i);
|
||||
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
|
||||
request->ssids[i].ssid,
|
||||
request->ssids[i].ssid_len);
|
||||
}
|
||||
|
||||
if (request->n_ssids)
|
||||
rc = wmi_set_ssid(wil, request->ssids[0].ssid_len,
|
||||
request->ssids[0].ssid);
|
||||
else
|
||||
rc = wmi_set_ssid(wil, 0, NULL);
|
||||
|
||||
if (rc) {
|
||||
wil_err(wil, "set SSID for scan request failed: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
wil->scan_request = request;
|
||||
mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
|
||||
|
||||
|
@ -778,6 +798,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
||||
const u8 *pr_ies = NULL;
|
||||
size_t pr_ies_len = 0;
|
||||
u8 hidden_ssid;
|
||||
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
|
@ -790,6 +811,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
channel->center_freq, info->privacy ? "secure" : "open");
|
||||
wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
|
||||
info->privacy, info->auth_type);
|
||||
wil_dbg_misc(wil, "Hidden SSID mode: %d\n",
|
||||
info->hidden_ssid);
|
||||
wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
|
||||
info->dtim_period);
|
||||
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
|
||||
|
@ -835,10 +858,28 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
|
||||
wil->privacy = info->privacy;
|
||||
|
||||
switch (info->hidden_ssid) {
|
||||
case NL80211_HIDDEN_SSID_NOT_IN_USE:
|
||||
hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
|
||||
break;
|
||||
|
||||
case NL80211_HIDDEN_SSID_ZERO_LEN:
|
||||
hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
|
||||
break;
|
||||
|
||||
case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
|
||||
hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
netif_carrier_on(ndev);
|
||||
|
||||
rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype,
|
||||
channel->hw_value);
|
||||
channel->hw_value, hidden_ssid);
|
||||
if (rc)
|
||||
goto err_pcp_start;
|
||||
|
||||
|
@ -1023,8 +1064,7 @@ static struct cfg80211_ops wil_cfg80211_ops = {
|
|||
|
||||
static void wil_wiphy_init(struct wiphy *wiphy)
|
||||
{
|
||||
/* TODO: set real value */
|
||||
wiphy->max_scan_ssids = 10;
|
||||
wiphy->max_scan_ssids = 1;
|
||||
wiphy->max_scan_ie_len = WMI_MAX_IE_LEN;
|
||||
wiphy->max_num_pmkids = 0 /* TODO: */;
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
|
|
|
@ -1360,7 +1360,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
|
|||
__acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int i, tid;
|
||||
int i, tid, mcs;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
struct wil_sta_info *p = &wil->sta[i];
|
||||
|
@ -1390,6 +1390,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
|||
}
|
||||
}
|
||||
spin_unlock_bh(&p->tid_rx_lock);
|
||||
seq_puts(s, "Rx/MCS:");
|
||||
for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
|
||||
mcs++)
|
||||
seq_printf(s, " %lld",
|
||||
p->stats.rx_per_mcs[mcs]);
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,8 @@ module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO);
|
|||
MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
|
||||
module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO);
|
||||
MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
|
||||
module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, S_IRUGO);
|
||||
MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
|
||||
|
||||
#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
|
||||
#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
|
||||
|
|
|
@ -132,7 +132,7 @@ static void wil_dev_setup(struct net_device *dev)
|
|||
dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
|
||||
}
|
||||
|
||||
void *wil_if_alloc(struct device *dev, void __iomem *csr)
|
||||
void *wil_if_alloc(struct device *dev)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
struct wireless_dev *wdev;
|
||||
|
@ -147,7 +147,6 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
|
|||
}
|
||||
|
||||
wil = wdev_to_wil(wdev);
|
||||
wil->csr = csr;
|
||||
wil->wdev = wdev;
|
||||
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
|
|
@ -163,7 +163,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
{
|
||||
struct wil6210_priv *wil;
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *csr;
|
||||
int rc;
|
||||
|
||||
/* check HW */
|
||||
|
@ -178,9 +177,28 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
wil = wil_if_alloc(dev);
|
||||
if (IS_ERR(wil)) {
|
||||
rc = (int)PTR_ERR(wil);
|
||||
dev_err(dev, "wil_if_alloc failed: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
wil->pdev = pdev;
|
||||
pci_set_drvdata(pdev, wil);
|
||||
/* rollback to if_free */
|
||||
|
||||
wil->platform_handle =
|
||||
wil_platform_init(&pdev->dev, &wil->platform_ops);
|
||||
if (!wil->platform_handle) {
|
||||
rc = -ENODEV;
|
||||
wil_err(wil, "wil_platform_init failed\n");
|
||||
goto if_free;
|
||||
}
|
||||
/* rollback to err_plat */
|
||||
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
wil_err(wil,
|
||||
"pci_enable_device failed, retry with MSI only\n");
|
||||
/* Work around for platforms that can't allocate IRQ:
|
||||
* retry with MSI only
|
||||
|
@ -188,47 +206,37 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
pdev->msi_enabled = 1;
|
||||
rc = pci_enable_device(pdev);
|
||||
}
|
||||
if (rc)
|
||||
return -ENODEV;
|
||||
if (rc) {
|
||||
wil_err(wil,
|
||||
"pci_enable_device failed, even with MSI only\n");
|
||||
goto err_plat;
|
||||
}
|
||||
/* rollback to err_disable_pdev */
|
||||
|
||||
rc = pci_request_region(pdev, 0, WIL_NAME);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "pci_request_region failed\n");
|
||||
wil_err(wil, "pci_request_region failed\n");
|
||||
goto err_disable_pdev;
|
||||
}
|
||||
/* rollback to err_release_reg */
|
||||
|
||||
csr = pci_ioremap_bar(pdev, 0);
|
||||
if (!csr) {
|
||||
dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
|
||||
wil->csr = pci_ioremap_bar(pdev, 0);
|
||||
if (!wil->csr) {
|
||||
wil_err(wil, "pci_ioremap_bar failed\n");
|
||||
rc = -ENODEV;
|
||||
goto err_release_reg;
|
||||
}
|
||||
/* rollback to err_iounmap */
|
||||
dev_info(&pdev->dev, "CSR at %pR -> 0x%p\n", &pdev->resource[0], csr);
|
||||
wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr);
|
||||
|
||||
wil = wil_if_alloc(dev, csr);
|
||||
if (IS_ERR(wil)) {
|
||||
rc = (int)PTR_ERR(wil);
|
||||
dev_err(dev, "wil_if_alloc failed: %d\n", rc);
|
||||
goto err_iounmap;
|
||||
}
|
||||
/* rollback to if_free */
|
||||
|
||||
pci_set_drvdata(pdev, wil);
|
||||
wil->pdev = pdev;
|
||||
wil_set_capabilities(wil);
|
||||
wil6210_clear_irq(wil);
|
||||
|
||||
wil->platform_handle =
|
||||
wil_platform_init(&pdev->dev, &wil->platform_ops);
|
||||
|
||||
/* FW should raise IRQ when ready */
|
||||
rc = wil_if_pcie_enable(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "Enable device failed\n");
|
||||
goto if_free;
|
||||
goto err_iounmap;
|
||||
}
|
||||
/* rollback to bus_disable */
|
||||
|
||||
|
@ -243,18 +251,19 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
|
||||
return 0;
|
||||
|
||||
bus_disable:
|
||||
bus_disable:
|
||||
wil_if_pcie_disable(wil);
|
||||
if_free:
|
||||
err_iounmap:
|
||||
pci_iounmap(pdev, wil->csr);
|
||||
err_release_reg:
|
||||
pci_release_region(pdev, 0);
|
||||
err_disable_pdev:
|
||||
pci_disable_device(pdev);
|
||||
err_plat:
|
||||
if (wil->platform_ops.uninit)
|
||||
wil->platform_ops.uninit(wil->platform_handle);
|
||||
if_free:
|
||||
wil_if_free(wil);
|
||||
err_iounmap:
|
||||
pci_iounmap(pdev, csr);
|
||||
err_release_reg:
|
||||
pci_release_region(pdev, 0);
|
||||
err_disable_pdev:
|
||||
pci_disable_device(pdev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -269,12 +278,12 @@ static void wil_pcie_remove(struct pci_dev *pdev)
|
|||
wil6210_debugfs_remove(wil);
|
||||
wil_if_remove(wil);
|
||||
wil_if_pcie_disable(wil);
|
||||
if (wil->platform_ops.uninit)
|
||||
wil->platform_ops.uninit(wil->platform_handle);
|
||||
wil_if_free(wil);
|
||||
pci_iounmap(pdev, csr);
|
||||
pci_release_region(pdev, 0);
|
||||
pci_disable_device(pdev);
|
||||
if (wil->platform_ops.uninit)
|
||||
wil->platform_ops.uninit(wil->platform_handle);
|
||||
wil_if_free(wil);
|
||||
}
|
||||
|
||||
static const struct pci_device_id wil6210_pcie_ids[] = {
|
||||
|
@ -291,7 +300,27 @@ static struct pci_driver wil6210_driver = {
|
|||
.name = WIL_NAME,
|
||||
};
|
||||
|
||||
module_pci_driver(wil6210_driver);
|
||||
static int __init wil6210_driver_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = wil_platform_modinit();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = pci_register_driver(&wil6210_driver);
|
||||
if (rc)
|
||||
wil_platform_modexit();
|
||||
return rc;
|
||||
}
|
||||
module_init(wil6210_driver_init);
|
||||
|
||||
static void __exit wil6210_driver_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&wil6210_driver);
|
||||
wil_platform_modexit();
|
||||
}
|
||||
module_exit(wil6210_driver_exit);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>");
|
||||
|
|
|
@ -427,6 +427,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
|||
cid = wil_rxdesc_cid(d);
|
||||
stats = &wil->sta[cid].stats;
|
||||
stats->last_mcs_rx = wil_rxdesc_mcs(d);
|
||||
if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs))
|
||||
stats->rx_per_mcs[stats->last_mcs_rx]++;
|
||||
|
||||
/* use radiotap header only if required */
|
||||
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
|
||||
|
|
|
@ -281,7 +281,7 @@ struct fw_map {
|
|||
};
|
||||
|
||||
/* array size should be in sync with actual definition in the wmi.c */
|
||||
extern const struct fw_map fw_mapping[7];
|
||||
extern const struct fw_map fw_mapping[8];
|
||||
|
||||
/**
|
||||
* mk_cidxtid - construct @cidxtid field
|
||||
|
@ -464,6 +464,7 @@ enum wil_sta_status {
|
|||
};
|
||||
|
||||
#define WIL_STA_TID_NUM (16)
|
||||
#define WIL_MCS_MAX (12) /* Maximum MCS supported */
|
||||
|
||||
struct wil_net_stats {
|
||||
unsigned long rx_packets;
|
||||
|
@ -473,6 +474,7 @@ struct wil_net_stats {
|
|||
unsigned long tx_errors;
|
||||
unsigned long rx_dropped;
|
||||
u16 last_mcs_rx;
|
||||
u64 rx_per_mcs[WIL_MCS_MAX + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -684,7 +686,7 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
|
|||
void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
|
||||
size_t count);
|
||||
|
||||
void *wil_if_alloc(struct device *dev, void __iomem *csr);
|
||||
void *wil_if_alloc(struct device *dev);
|
||||
void wil_if_free(struct wil6210_priv *wil);
|
||||
int wil_if_add(struct wil6210_priv *wil);
|
||||
void wil_if_remove(struct wil6210_priv *wil);
|
||||
|
@ -762,7 +764,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev);
|
|||
void wil_wdev_free(struct wil6210_priv *wil);
|
||||
|
||||
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
|
||||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
|
||||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
|
||||
u8 chan, u8 hidden_ssid);
|
||||
int wmi_pcp_stop(struct wil6210_priv *wil);
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
|
||||
u16 reason_code, bool from_event);
|
||||
|
|
|
@ -17,6 +17,15 @@
|
|||
#include "linux/device.h"
|
||||
#include "wil_platform.h"
|
||||
|
||||
int __init wil_platform_modinit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wil_platform_modexit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* wil_platform_init() - wil6210 platform module init
|
||||
*
|
||||
|
@ -26,10 +35,11 @@
|
|||
*/
|
||||
void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops)
|
||||
{
|
||||
void *handle = NULL;
|
||||
void *handle = ops; /* to return some non-NULL for 'void' impl. */
|
||||
|
||||
if (!ops) {
|
||||
dev_err(dev, "Invalid parameter. Cannot init platform module\n");
|
||||
dev_err(dev,
|
||||
"Invalid parameter. Cannot init platform module\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,4 +31,7 @@ struct wil_platform_ops {
|
|||
|
||||
void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops);
|
||||
|
||||
int __init wil_platform_modinit(void);
|
||||
void wil_platform_modexit(void);
|
||||
|
||||
#endif /* __WIL_PLATFORM_H__ */
|
||||
|
|
|
@ -85,6 +85,7 @@ const struct fw_map fw_mapping[] = {
|
|||
{0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */
|
||||
{0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf 512b */
|
||||
{0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */
|
||||
/*
|
||||
* 920000..930000 ucode code RAM
|
||||
|
@ -824,7 +825,8 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
|
|||
return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan)
|
||||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
|
||||
u8 chan, u8 hidden_ssid)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -834,6 +836,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan)
|
|||
.disable_sec_offload = 1,
|
||||
.channel = chan - 1,
|
||||
.pcp_max_assoc_sta = max_assoc_sta,
|
||||
.hidden_ssid = hidden_ssid,
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
|
|
|
@ -495,10 +495,18 @@ struct wmi_power_mgmt_cfg_cmd {
|
|||
/*
|
||||
* WMI_PCP_START_CMDID
|
||||
*/
|
||||
|
||||
enum wmi_hidden_ssid {
|
||||
WMI_HIDDEN_SSID_DISABLED = 0,
|
||||
WMI_HIDDEN_SSID_SEND_EMPTY = 1,
|
||||
WMI_HIDDEN_SSID_CLEAR = 2,
|
||||
};
|
||||
|
||||
struct wmi_pcp_start_cmd {
|
||||
__le16 bcon_interval;
|
||||
u8 pcp_max_assoc_sta;
|
||||
u8 reserved0[9];
|
||||
u8 hidden_ssid;
|
||||
u8 reserved0[8];
|
||||
u8 network_type;
|
||||
u8 channel;
|
||||
u8 disable_sec_offload;
|
||||
|
|
|
@ -5361,6 +5361,10 @@ static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy,
|
|||
*have_5ghz_phy = true;
|
||||
return;
|
||||
case 0x4321: /* BCM4306 */
|
||||
/* There are 14e4:4321 PCI devs with 2.4 GHz BCM4321 (N-PHY) */
|
||||
if (dev->phy.type != B43_PHYTYPE_G)
|
||||
break;
|
||||
/* fall through */
|
||||
case 0x4313: /* BCM4311 */
|
||||
case 0x431a: /* BCM4318 */
|
||||
case 0x432a: /* BCM4321 */
|
||||
|
|
|
@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
|
|||
|
||||
static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
sdiodev->state = BRCMF_SDIOD_DOWN;
|
||||
if (sdiodev->bus) {
|
||||
brcmf_sdio_remove(sdiodev->bus);
|
||||
sdiodev->bus = NULL;
|
||||
|
|
|
@ -52,8 +52,6 @@
|
|||
#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
|
||||
#define BRCMF_IFACE_MAX_CNT 3
|
||||
|
||||
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
|
||||
#define WPA_OUI_TYPE 1
|
||||
#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */
|
||||
|
@ -2398,27 +2396,80 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
|
|||
brcmf_err("set wsec error (%d)\n", err);
|
||||
}
|
||||
|
||||
static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
|
||||
{
|
||||
struct nl80211_sta_flag_update *sfu;
|
||||
|
||||
brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
|
||||
si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
|
||||
sfu = &si->sta_flags;
|
||||
sfu->mask = BIT(NL80211_STA_FLAG_WME) |
|
||||
BIT(NL80211_STA_FLAG_AUTHENTICATED) |
|
||||
BIT(NL80211_STA_FLAG_ASSOCIATED) |
|
||||
BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
if (fw_sta_flags & BRCMF_STA_WME)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_WME);
|
||||
if (fw_sta_flags & BRCMF_STA_AUTHE)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
|
||||
if (fw_sta_flags & BRCMF_STA_ASSOC)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
||||
if (fw_sta_flags & BRCMF_STA_AUTHO)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
}
|
||||
|
||||
static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
|
||||
{
|
||||
struct {
|
||||
__le32 len;
|
||||
struct brcmf_bss_info_le bss_le;
|
||||
} *buf;
|
||||
u16 capability;
|
||||
int err;
|
||||
|
||||
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
|
||||
WL_BSS_INFO_MAX);
|
||||
if (err) {
|
||||
brcmf_err("Failed to get bss info (%d)\n", err);
|
||||
return;
|
||||
}
|
||||
si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
|
||||
si->bss_param.dtim_period = buf->bss_le.dtim_period;
|
||||
capability = le16_to_cpu(buf->bss_le.capability);
|
||||
if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
|
||||
si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
|
||||
if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
|
||||
if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
struct brcmf_scb_val_le scb_val;
|
||||
int rssi;
|
||||
s32 rate;
|
||||
s32 err = 0;
|
||||
u8 *bssid = profile->bssid;
|
||||
struct brcmf_sta_info_le sta_info_le;
|
||||
u32 beacon_period;
|
||||
u32 dtim_period;
|
||||
u32 sta_flags;
|
||||
u32 is_tdls_peer;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
|
||||
if (!check_vif_up(ifp->vif))
|
||||
return -EIO;
|
||||
|
||||
if (brcmf_is_apmode(ifp->vif)) {
|
||||
memcpy(&sta_info_le, mac, ETH_ALEN);
|
||||
memset(&sta_info_le, 0, sizeof(sta_info_le));
|
||||
memcpy(&sta_info_le, mac, ETH_ALEN);
|
||||
err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
|
||||
&sta_info_le,
|
||||
sizeof(sta_info_le));
|
||||
is_tdls_peer = !err;
|
||||
if (err) {
|
||||
err = brcmf_fil_iovar_data_get(ifp, "sta_info",
|
||||
&sta_info_le,
|
||||
sizeof(sta_info_le));
|
||||
|
@ -2426,73 +2477,48 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|||
brcmf_err("GET STA INFO failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
}
|
||||
brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
|
||||
sinfo->inactive_time, sinfo->connected_time);
|
||||
} else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
|
||||
if (memcmp(mac, bssid, ETH_ALEN)) {
|
||||
brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
|
||||
mac, bssid);
|
||||
err = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
/* Report the current tx rate */
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
|
||||
if (err) {
|
||||
brcmf_err("Could not get rate (%d)\n", err);
|
||||
goto done;
|
||||
} else {
|
||||
}
|
||||
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
sta_flags = le32_to_cpu(sta_info_le.flags);
|
||||
brcmf_convert_sta_flags(sta_flags, sinfo);
|
||||
sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
if (is_tdls_peer)
|
||||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
else
|
||||
sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
if (sta_flags & BRCMF_STA_ASSOC) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
brcmf_fill_bss_param(ifp, sinfo);
|
||||
}
|
||||
if (sta_flags & BRCMF_STA_SCBSTATS) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
|
||||
sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
|
||||
sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
|
||||
sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
|
||||
sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
|
||||
if (sinfo->tx_packets) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
sinfo->txrate.legacy = rate * 5;
|
||||
brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
|
||||
sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
|
||||
sinfo->txrate.legacy /= 100;
|
||||
}
|
||||
|
||||
if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
|
||||
&ifp->vif->sme_state)) {
|
||||
memset(&scb_val, 0, sizeof(scb_val));
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
|
||||
&scb_val, sizeof(scb_val));
|
||||
if (err) {
|
||||
brcmf_err("Could not get rssi (%d)\n", err);
|
||||
goto done;
|
||||
} else {
|
||||
rssi = le32_to_cpu(scb_val.val);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = rssi;
|
||||
brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
|
||||
}
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
|
||||
&beacon_period);
|
||||
if (err) {
|
||||
brcmf_err("Could not get beacon period (%d)\n",
|
||||
err);
|
||||
goto done;
|
||||
} else {
|
||||
sinfo->bss_param.beacon_interval =
|
||||
beacon_period;
|
||||
brcmf_dbg(CONN, "Beacon peroid %d\n",
|
||||
beacon_period);
|
||||
}
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
|
||||
&dtim_period);
|
||||
if (err) {
|
||||
brcmf_err("Could not get DTIM period (%d)\n",
|
||||
err);
|
||||
goto done;
|
||||
} else {
|
||||
sinfo->bss_param.dtim_period = dtim_period;
|
||||
brcmf_dbg(CONN, "DTIM peroid %d\n",
|
||||
dtim_period);
|
||||
}
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
if (sinfo->rx_packets) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
|
||||
sinfo->rxrate.legacy /= 100;
|
||||
}
|
||||
} else
|
||||
err = -EPERM;
|
||||
if (le16_to_cpu(sta_info_le.ver) >= 4) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
|
||||
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
|
||||
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
|
||||
}
|
||||
}
|
||||
done:
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return err;
|
||||
|
@ -5640,53 +5666,6 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC)
|
||||
},
|
||||
{
|
||||
.max = 4,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
}
|
||||
};
|
||||
static struct ieee80211_iface_combination brcmf_iface_combos[] = {
|
||||
{
|
||||
.max_interfaces = BRCMF_IFACE_MAX_CNT,
|
||||
.num_different_channels = 1,
|
||||
.n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
|
||||
.limits = brcmf_iface_limits_sbss,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_txrx_stypes
|
||||
brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
||||
[NL80211_IFTYPE_STATION] = {
|
||||
|
@ -5716,6 +5695,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
|||
}
|
||||
};
|
||||
|
||||
static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct ieee80211_iface_combination *combo = NULL;
|
||||
struct ieee80211_iface_limit *limits = NULL;
|
||||
int i = 0, max_iface_cnt;
|
||||
|
||||
combo = kzalloc(sizeof(*combo), GFP_KERNEL);
|
||||
if (!combo)
|
||||
goto err;
|
||||
|
||||
limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
|
||||
if (!limits)
|
||||
goto err;
|
||||
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
combo->num_different_channels = 2;
|
||||
else
|
||||
combo->num_different_channels = 1;
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
limits[i].max = 1;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_STATION);
|
||||
limits[i].max = 4;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_AP);
|
||||
max_iface_cnt = 5;
|
||||
} else {
|
||||
limits[i].max = 2;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
max_iface_cnt = 2;
|
||||
}
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
|
||||
wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
limits[i].max = 1;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
limits[i].max = 1;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
max_iface_cnt += 2;
|
||||
}
|
||||
combo->max_interfaces = max_iface_cnt;
|
||||
combo->limits = limits;
|
||||
combo->n_limits = i;
|
||||
|
||||
wiphy->iface_combinations = combo;
|
||||
wiphy->n_iface_combinations = 1;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(limits);
|
||||
kfree(combo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
|
||||
{
|
||||
/* scheduled scan settings */
|
||||
|
@ -5746,7 +5786,6 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy)
|
|||
static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ieee80211_iface_combination ifc_combo;
|
||||
__le32 bandlist[3];
|
||||
u32 n_bands;
|
||||
int err, i;
|
||||
|
@ -5754,24 +5793,11 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
|||
wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
|
||||
wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
|
||||
wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
/* need VSDB firmware feature for concurrent channels */
|
||||
ifc_combo = brcmf_iface_combos[0];
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
ifc_combo.num_different_channels = 2;
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
|
||||
ifc_combo.limits = brcmf_iface_limits_mbss;
|
||||
}
|
||||
wiphy->iface_combinations = kmemdup(&ifc_combo,
|
||||
sizeof(ifc_combo),
|
||||
GFP_KERNEL);
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
|
||||
|
||||
err = brcmf_setup_ifmodes(wiphy, ifp);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
wiphy->cipher_suites = __wl_cipher_suites;
|
||||
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
|
||||
|
@ -6036,6 +6062,8 @@ static void brcmf_free_wiphy(struct wiphy *wiphy)
|
|||
if (!wiphy)
|
||||
return;
|
||||
|
||||
if (wiphy->iface_combinations)
|
||||
kfree(wiphy->iface_combinations->limits);
|
||||
kfree(wiphy->iface_combinations);
|
||||
if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
|
||||
kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
|
||||
|
@ -6071,6 +6099,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
|||
brcmf_err("Could not allocate wiphy device\n");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
|
||||
set_wiphy_dev(wiphy, busdev);
|
||||
|
||||
cfg = wiphy_priv(wiphy);
|
||||
|
@ -6178,10 +6207,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
|||
if (!cfg)
|
||||
return;
|
||||
|
||||
WARN_ON(!list_empty(&cfg->vif_list));
|
||||
wiphy_unregister(cfg->wiphy);
|
||||
brcmf_btcoex_detach(cfg);
|
||||
brcmf_p2p_detach(&cfg->p2p);
|
||||
wiphy_unregister(cfg->wiphy);
|
||||
wl_deinit_priv(cfg);
|
||||
brcmf_free_wiphy(cfg->wiphy);
|
||||
}
|
||||
|
|
|
@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
|
|||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items)
|
||||
{
|
||||
void *ret_addr;
|
||||
|
||||
if (commonring->cr_update_wptr)
|
||||
commonring->cr_update_wptr(commonring->cr_ctx);
|
||||
|
||||
|
@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
|||
if (*n_items == 0)
|
||||
return NULL;
|
||||
|
||||
ret_addr = commonring->buf_addr +
|
||||
(commonring->r_ptr * commonring->item_len);
|
||||
|
||||
commonring->r_ptr += *n_items;
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
return ret_addr;
|
||||
return commonring->buf_addr +
|
||||
(commonring->r_ptr * commonring->item_len);
|
||||
}
|
||||
|
||||
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
|
||||
u16 n_items)
|
||||
{
|
||||
commonring->r_ptr += n_items;
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
if (commonring->cr_write_rptr)
|
||||
return commonring->cr_write_rptr(commonring->cr_ctx);
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
|
|||
u16 n_items);
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items);
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
|
||||
u16 n_items);
|
||||
|
||||
#define brcmf_commonring_n_items(commonring) (commonring->depth)
|
||||
#define brcmf_commonring_len_item(commonring) (commonring->item_len)
|
||||
|
|
|
@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
|||
}
|
||||
/* unregister will take care of freeing it */
|
||||
unregister_netdev(ifp->ndev);
|
||||
} else {
|
||||
kfree(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1100,6 +1098,8 @@ void brcmf_detach(struct device *dev)
|
|||
|
||||
/* stop firmware event handling */
|
||||
brcmf_fweh_detach(drvr);
|
||||
if (drvr->config)
|
||||
brcmf_p2p_detach(&drvr->config->p2p);
|
||||
|
||||
brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
|
||||
|
||||
|
|
|
@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void)
|
|||
root_folder = NULL;
|
||||
}
|
||||
|
||||
static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
|
||||
{
|
||||
struct brcmf_bus *bus = dev_get_drvdata(seq->private);
|
||||
|
||||
seq_printf(seq, "chip: %x(%u) rev %u\n",
|
||||
bus->chip, bus->chip, bus->chiprev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct device *dev = drvr->bus_if->dev;
|
||||
|
@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
|||
return -ENODEV;
|
||||
|
||||
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
|
||||
brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
|
||||
|
||||
return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
|
||||
}
|
||||
|
@ -74,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
|
|||
return drvr->dbgfs_dir;
|
||||
}
|
||||
|
||||
struct brcmf_debugfs_entry {
|
||||
int (*read)(struct seq_file *seq, void *data);
|
||||
struct brcmf_pub *drvr;
|
||||
};
|
||||
|
||||
static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
struct brcmf_debugfs_entry *entry = inode->i_private;
|
||||
|
||||
return single_open(f, entry->read, entry->drvr->bus_if->dev);
|
||||
}
|
||||
|
||||
static const struct file_operations brcmf_debugfs_def_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = brcmf_debugfs_entry_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek
|
||||
};
|
||||
|
||||
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
|
||||
int (*read_fn)(struct seq_file *seq, void *data))
|
||||
{
|
||||
struct dentry *dentry = drvr->dbgfs_dir;
|
||||
struct brcmf_debugfs_entry *entry;
|
||||
struct dentry *e;
|
||||
|
||||
if (IS_ERR_OR_NULL(dentry))
|
||||
return -ENOENT;
|
||||
|
||||
entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->read = read_fn;
|
||||
entry->drvr = drvr;
|
||||
|
||||
dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
|
||||
&brcmf_debugfs_def_ops);
|
||||
|
||||
return PTR_ERR_OR_ZERO(dentry);
|
||||
e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
|
||||
drvr->dbgfs_dir, read_fn);
|
||||
return PTR_ERR_OR_ZERO(e);
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
|
||||
if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
|
||||
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
|
||||
|
||||
/* set chip related quirks */
|
||||
switch (drvr->bus_if->chip) {
|
||||
|
|
|
@ -23,12 +23,14 @@
|
|||
* MCHAN: multi-channel for concurrent P2P.
|
||||
* PNO: preferred network offload.
|
||||
* WOWL: Wake-On-WLAN.
|
||||
* P2P: peer-to-peer
|
||||
*/
|
||||
#define BRCMF_FEAT_LIST \
|
||||
BRCMF_FEAT_DEF(MBSS) \
|
||||
BRCMF_FEAT_DEF(MCHAN) \
|
||||
BRCMF_FEAT_DEF(PNO) \
|
||||
BRCMF_FEAT_DEF(WOWL)
|
||||
BRCMF_FEAT_DEF(WOWL) \
|
||||
BRCMF_FEAT_DEF(P2P)
|
||||
/*
|
||||
* Quirks:
|
||||
*
|
||||
|
|
|
@ -43,7 +43,7 @@ enum nvram_parser_state {
|
|||
* struct nvram_parser - internal info for parser.
|
||||
*
|
||||
* @state: current parser state.
|
||||
* @fwnv: input buffer being parsed.
|
||||
* @data: input buffer being parsed.
|
||||
* @nvram: output buffer with parse result.
|
||||
* @nvram_len: lenght of parse result.
|
||||
* @line: current line.
|
||||
|
@ -55,7 +55,7 @@ enum nvram_parser_state {
|
|||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
const struct firmware *fwnv;
|
||||
const u8 *data;
|
||||
u8 *nvram;
|
||||
u32 nvram_len;
|
||||
u32 line;
|
||||
|
@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
|
|||
{
|
||||
char c;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
c = nvp->data[nvp->pos];
|
||||
if (c == '\n')
|
||||
return COMMENT;
|
||||
if (is_whitespace(c))
|
||||
|
@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
|
|||
enum nvram_parser_state st = nvp->state;
|
||||
char c;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
c = nvp->data[nvp->pos];
|
||||
if (c == '=') {
|
||||
/* ignore RAW1 by treating as comment */
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0)
|
||||
if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
|
||||
st = COMMENT;
|
||||
else
|
||||
st = VALUE;
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0)
|
||||
if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
|
||||
nvp->multi_dev_v1 = true;
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
|
||||
if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
|
||||
nvp->multi_dev_v2 = true;
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
|
@ -145,11 +145,11 @@ brcmf_nvram_handle_value(struct nvram_parser *nvp)
|
|||
char *ekv;
|
||||
u32 cplen;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
c = nvp->data[nvp->pos];
|
||||
if (!is_nvram_char(c)) {
|
||||
/* key,value pair complete */
|
||||
ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
|
||||
skv = (u8 *)&nvp->fwnv->data[nvp->entry];
|
||||
ekv = (u8 *)&nvp->data[nvp->pos];
|
||||
skv = (u8 *)&nvp->data[nvp->entry];
|
||||
cplen = ekv - skv;
|
||||
if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
|
||||
return END;
|
||||
|
@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_parser *nvp)
|
|||
{
|
||||
char *eoc, *sol;
|
||||
|
||||
sol = (char *)&nvp->fwnv->data[nvp->pos];
|
||||
sol = (char *)&nvp->data[nvp->pos];
|
||||
eoc = strchr(sol, '\n');
|
||||
if (!eoc) {
|
||||
eoc = strchr(sol, '\0');
|
||||
|
@ -201,17 +201,17 @@ static enum nvram_parser_state
|
|||
};
|
||||
|
||||
static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
|
||||
const struct firmware *nv)
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
memset(nvp, 0, sizeof(*nvp));
|
||||
nvp->fwnv = nv;
|
||||
nvp->data = data;
|
||||
/* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
|
||||
if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE)
|
||||
if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
|
||||
size = BRCMF_FW_MAX_NVRAM_SIZE;
|
||||
else
|
||||
size = nv->size;
|
||||
size = data_len;
|
||||
/* Alloc for extra 0 byte + roundup by 4 + length field */
|
||||
size += 1 + 3 + sizeof(u32);
|
||||
nvp->nvram = kzalloc(size, GFP_KERNEL);
|
||||
|
@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
|||
u16 bus_nr)
|
||||
{
|
||||
/* Device path with a leading '=' key-value separator */
|
||||
char pci_path[] = "=pci/?/?";
|
||||
size_t pci_len;
|
||||
char pcie_path[] = "=pcie/?/?";
|
||||
size_t pcie_len;
|
||||
|
||||
|
@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
|||
/* First search for the devpathX and see if it is the configuration
|
||||
* for domain_nr/bus_nr. Search complete nvp
|
||||
*/
|
||||
snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
|
||||
bus_nr);
|
||||
pci_len = strlen(pci_path);
|
||||
snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
|
||||
bus_nr);
|
||||
pcie_len = strlen(pcie_path);
|
||||
|
@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
|||
/* Format: devpathX=pcie/Y/Z/
|
||||
* Y = domain_nr, Z = bus_nr, X = virtual ID
|
||||
*/
|
||||
if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
|
||||
(strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
|
||||
if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
|
||||
(!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
|
||||
!strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
|
||||
id = nvp->nvram[i + 7] - '0';
|
||||
found = true;
|
||||
break;
|
||||
|
@ -356,18 +362,18 @@ fail:
|
|||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
* End of buffer is completed with token identifying length of buffer.
|
||||
*/
|
||||
static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length,
|
||||
u16 domain_nr, u16 bus_nr)
|
||||
static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
|
||||
u32 *new_length, u16 domain_nr, u16 bus_nr)
|
||||
{
|
||||
struct nvram_parser nvp;
|
||||
u32 pad;
|
||||
u32 token;
|
||||
__le32 token_le;
|
||||
|
||||
if (brcmf_init_nvram_parser(&nvp, nv) < 0)
|
||||
if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
|
||||
return NULL;
|
||||
|
||||
while (nvp.pos < nv->size) {
|
||||
while (nvp.pos < data_len) {
|
||||
nvp.state = nv_parser_states[nvp.state](&nvp);
|
||||
if (nvp.state == END)
|
||||
break;
|
||||
|
@ -426,7 +432,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
|||
goto fail;
|
||||
|
||||
if (fw) {
|
||||
nvram = brcmf_fw_nvram_strip(fw, &nvram_length,
|
||||
nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
|
||||
fwctx->domain_nr, fwctx->bus_nr);
|
||||
release_firmware(fw);
|
||||
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
|
|
|
@ -32,7 +32,11 @@
|
|||
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
|
||||
#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
|
||||
|
||||
#define BRCMF_STA_ASSOC 0x10 /* Associated */
|
||||
#define BRCMF_STA_WME 0x00000002 /* WMM association */
|
||||
#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
|
||||
#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
|
||||
#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
|
||||
#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
|
||||
|
||||
/* size of brcmf_scan_params not including variable length array */
|
||||
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
||||
|
@ -113,6 +117,7 @@
|
|||
#define BRCMF_WOWL_MAXPATTERNSIZE 128
|
||||
|
||||
#define BRCMF_COUNTRY_BUF_SZ 4
|
||||
#define BRCMF_ANT_MAX 4
|
||||
|
||||
/* join preference types for join_pref iovar */
|
||||
enum brcmf_join_pref_types {
|
||||
|
@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
|
|||
};
|
||||
|
||||
struct brcmf_sta_info_le {
|
||||
__le16 ver; /* version of this struct */
|
||||
__le16 len; /* length in bytes of this structure */
|
||||
__le16 cap; /* sta's advertised capabilities */
|
||||
__le32 flags; /* flags defined below */
|
||||
__le32 idle; /* time since data pkt rx'd from sta */
|
||||
u8 ea[ETH_ALEN]; /* Station address */
|
||||
__le32 count; /* # rates in this set */
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
__le16 ver; /* version of this struct */
|
||||
__le16 len; /* length in bytes of this structure */
|
||||
__le16 cap; /* sta's advertised capabilities */
|
||||
__le32 flags; /* flags defined below */
|
||||
__le32 idle; /* time since data pkt rx'd from sta */
|
||||
u8 ea[ETH_ALEN]; /* Station address */
|
||||
__le32 count; /* # rates in this set */
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
/* w/hi bit set if basic */
|
||||
__le32 in; /* seconds elapsed since associated */
|
||||
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
__le32 tx_pkts; /* # of packets transmitted */
|
||||
__le32 tx_failures; /* # of packets failed */
|
||||
__le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
__le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
__le32 tx_rate; /* Rate of last successful tx frame */
|
||||
__le32 rx_rate; /* Rate of last successful rx frame */
|
||||
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
__le32 in; /* seconds elapsed since associated */
|
||||
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
__le32 tx_pkts; /* # of packets transmitted */
|
||||
__le32 tx_failures; /* # of packets failed */
|
||||
__le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
__le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
__le32 tx_rate; /* Rate of last successful tx frame */
|
||||
__le32 rx_rate; /* Rate of last successful rx frame */
|
||||
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
__le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
|
||||
__le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
|
||||
__le32 tx_mcast_pkts; /* # of mcast pkts txed */
|
||||
__le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
|
||||
__le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
|
||||
__le64 tx_ucast_bytes; /* data bytes txed (ucast) */
|
||||
__le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
|
||||
__le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
|
||||
__le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
|
||||
s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */
|
||||
s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */
|
||||
__le16 aid; /* association ID */
|
||||
__le16 ht_capabilities; /* advertised ht caps */
|
||||
__le16 vht_flags; /* converted vht flags */
|
||||
__le32 tx_pkts_retry_cnt; /* # of frames where a retry was
|
||||
* exhausted.
|
||||
*/
|
||||
__le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
|
||||
* was exhausted
|
||||
*/
|
||||
s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
|
||||
* received data frame.
|
||||
*/
|
||||
/* TX WLAN retry/failure statistics:
|
||||
* Separated for host requested frames and locally generated frames.
|
||||
* Include unicast frame only where the retries/failures can be counted.
|
||||
*/
|
||||
__le32 tx_pkts_total; /* # user frames sent successfully */
|
||||
__le32 tx_pkts_retries; /* # user frames retries */
|
||||
__le32 tx_pkts_fw_total; /* # FW generated sent successfully */
|
||||
__le32 tx_pkts_fw_retries; /* # retries for FW generated frames */
|
||||
__le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry
|
||||
* was exhausted
|
||||
*/
|
||||
__le32 rx_pkts_retried; /* # rx with retry bit set */
|
||||
__le32 tx_rate_fallback; /* lowest fallback TX rate */
|
||||
};
|
||||
|
||||
struct brcmf_chanspec_list {
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
|
||||
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
|
||||
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
|
||||
#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48
|
||||
|
||||
|
||||
struct msgbuf_common_hdr {
|
||||
u8 msgtype;
|
||||
|
@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
|
|||
{
|
||||
void *buf;
|
||||
u16 count;
|
||||
u16 processed;
|
||||
|
||||
again:
|
||||
buf = brcmf_commonring_get_read_ptr(commonring, &count);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
processed = 0;
|
||||
while (count) {
|
||||
brcmf_msgbuf_process_msgtype(msgbuf,
|
||||
buf + msgbuf->rx_dataoffset);
|
||||
buf += brcmf_commonring_len_item(commonring);
|
||||
processed++;
|
||||
if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
|
||||
brcmf_commonring_read_complete(commonring, processed);
|
||||
processed = 0;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
brcmf_commonring_read_complete(commonring);
|
||||
if (processed)
|
||||
brcmf_commonring_read_complete(commonring, processed);
|
||||
|
||||
if (commonring->r_ptr == 0)
|
||||
goto again;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <brcmu_wifi.h>
|
||||
|
@ -1907,105 +1908,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* brcmf_p2p_attach() - attach for P2P.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
*/
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_if *pri_ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
struct brcmf_cfg80211_vif *p2p_vif;
|
||||
struct brcmf_p2p_info *p2p;
|
||||
struct brcmf_pub *drvr;
|
||||
s32 bssidx;
|
||||
s32 err = 0;
|
||||
|
||||
p2p = &cfg->p2p;
|
||||
p2p->cfg = cfg;
|
||||
|
||||
drvr = cfg->pub;
|
||||
|
||||
pri_ifp = drvr->iflist[0];
|
||||
p2p_ifp = drvr->iflist[1];
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
|
||||
|
||||
if (p2p_ifp) {
|
||||
p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
|
||||
false);
|
||||
if (IS_ERR(p2p_vif)) {
|
||||
brcmf_err("could not create discovery vif\n");
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
p2p_vif->ifp = p2p_ifp;
|
||||
p2p_ifp->vif = p2p_vif;
|
||||
p2p_vif->wdev.netdev = p2p_ifp->ndev;
|
||||
p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
|
||||
SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
||||
|
||||
brcmf_p2p_generate_bss_mac(p2p, NULL);
|
||||
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
||||
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||
|
||||
/* Initialize P2P Discovery in the firmware */
|
||||
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||
if (err < 0) {
|
||||
brcmf_err("set p2p_disc error\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* obtain bsscfg index for P2P discovery */
|
||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||
if (err < 0) {
|
||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* Verify that firmware uses same bssidx as driver !! */
|
||||
if (p2p_ifp->bssidx != bssidx) {
|
||||
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
||||
bssidx, p2p_ifp->bssidx);
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
init_completion(&p2p->send_af_done);
|
||||
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
|
||||
init_completion(&p2p->afx_hdl.act_frm_scan);
|
||||
init_completion(&p2p->wait_next_af);
|
||||
}
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* brcmf_p2p_detach() - detach P2P.
|
||||
*
|
||||
* @p2p: P2P specific data.
|
||||
*/
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
||||
if (vif != NULL) {
|
||||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
/* remove discovery interface */
|
||||
brcmf_free_vif(vif);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
}
|
||||
/* just set it all to zero */
|
||||
memset(p2p, 0, sizeof(*p2p));
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_get_current_chanspec() - Get current operation channel.
|
||||
*
|
||||
|
@ -2238,6 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
|
|||
{
|
||||
cfg80211_unregister_wdev(&vif->wdev);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
|
||||
brcmf_free_vif(vif);
|
||||
}
|
||||
|
||||
|
@ -2364,6 +2267,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
break;
|
||||
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
brcmf_p2p_delete_p2pdev(p2p, vif);
|
||||
return 0;
|
||||
default:
|
||||
|
@ -2425,3 +2330,103 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
|
||||
mutex_unlock(&cfg->usr_sync);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_attach() - attach for P2P.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
*/
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_if *pri_ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
struct brcmf_cfg80211_vif *p2p_vif;
|
||||
struct brcmf_p2p_info *p2p;
|
||||
struct brcmf_pub *drvr;
|
||||
s32 bssidx;
|
||||
s32 err = 0;
|
||||
|
||||
p2p = &cfg->p2p;
|
||||
p2p->cfg = cfg;
|
||||
|
||||
drvr = cfg->pub;
|
||||
|
||||
pri_ifp = drvr->iflist[0];
|
||||
p2p_ifp = drvr->iflist[1];
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
|
||||
|
||||
if (p2p_ifp) {
|
||||
p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
|
||||
false);
|
||||
if (IS_ERR(p2p_vif)) {
|
||||
brcmf_err("could not create discovery vif\n");
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
p2p_vif->ifp = p2p_ifp;
|
||||
p2p_ifp->vif = p2p_vif;
|
||||
p2p_vif->wdev.netdev = p2p_ifp->ndev;
|
||||
p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
|
||||
SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
||||
|
||||
brcmf_p2p_generate_bss_mac(p2p, NULL);
|
||||
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
||||
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||
|
||||
/* Initialize P2P Discovery in the firmware */
|
||||
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||
if (err < 0) {
|
||||
brcmf_err("set p2p_disc error\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* obtain bsscfg index for P2P discovery */
|
||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||
if (err < 0) {
|
||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* Verify that firmware uses same bssidx as driver !! */
|
||||
if (p2p_ifp->bssidx != bssidx) {
|
||||
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
||||
bssidx, p2p_ifp->bssidx);
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
init_completion(&p2p->send_af_done);
|
||||
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
|
||||
init_completion(&p2p->afx_hdl.act_frm_scan);
|
||||
init_completion(&p2p->wait_next_af);
|
||||
}
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_detach() - detach P2P.
|
||||
*
|
||||
* @p2p: P2P specific data.
|
||||
*/
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
||||
if (vif != NULL) {
|
||||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
/* remove discovery interface */
|
||||
rtnl_lock();
|
||||
brcmf_p2p_delete_p2pdev(p2p, vif);
|
||||
rtnl_unlock();
|
||||
}
|
||||
/* just set it all to zero */
|
||||
memset(p2p, 0, sizeof(*p2p));
|
||||
}
|
||||
|
||||
|
|
|
@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
|
|||
|
||||
static int brcmf_pcie_buscoreprep(void *ctx)
|
||||
{
|
||||
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
|
||||
int err;
|
||||
|
||||
err = brcmf_pcie_get_resource(devinfo);
|
||||
if (err == 0) {
|
||||
/* Set CC watchdog to reset all the cores on the chip to bring
|
||||
* back dongle to a sane state.
|
||||
*/
|
||||
brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
|
||||
watchdog), 4);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
return err;
|
||||
return brcmf_pcie_get_resource(ctx);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
|||
brcmf_pcie_intr_disable(devinfo);
|
||||
|
||||
brcmf_detach(&pdev->dev);
|
||||
brcmf_pcie_reset_device(devinfo);
|
||||
|
||||
kfree(bus->bus_priv.pcie);
|
||||
kfree(bus->msgbuf->flowrings);
|
||||
|
|
|
@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
|
|||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
|
||||
if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
return -EIO;
|
||||
|
||||
/* Add space for the header */
|
||||
skb_push(pkt, bus->tx_hdrlen);
|
||||
|
@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
return -EIO;
|
||||
|
||||
/* Send from dpc */
|
||||
bus->ctrl_frame_buf = msg;
|
||||
|
@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
return -EIO;
|
||||
|
||||
/* Wait until control frame is available */
|
||||
timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
|
||||
|
|
|
@ -34,56 +34,32 @@ static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len)
|
|||
|
||||
static struct sk_buff *
|
||||
mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
|
||||
u8 *data, u32 seg_len)
|
||||
void *data, u32 seg_len, u32 truesize, struct page *p)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u32 true_len;
|
||||
u32 true_len, hdr_len = 0, copy, frag;
|
||||
|
||||
if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD))
|
||||
seg_len -= 2;
|
||||
|
||||
skb = alloc_skb(seg_len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
|
||||
int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
|
||||
|
||||
memcpy(skb_put(skb, hdr_len), data, hdr_len);
|
||||
data += hdr_len + 2;
|
||||
seg_len -= hdr_len;
|
||||
}
|
||||
|
||||
memcpy(skb_put(skb, seg_len), data, seg_len);
|
||||
|
||||
true_len = mt76_mac_process_rx(dev, skb, skb->data, rxwi);
|
||||
skb_trim(skb, true_len);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
|
||||
struct mt7601u_rxwi *rxwi, void *data,
|
||||
u32 seg_len, u32 truesize, struct page *p)
|
||||
{
|
||||
unsigned int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
|
||||
unsigned int true_len, copy, frag;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(128, GFP_ATOMIC);
|
||||
skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
|
||||
if (!true_len || true_len > seg_len)
|
||||
goto bad_frame;
|
||||
|
||||
hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len);
|
||||
if (!hdr_len)
|
||||
goto bad_frame;
|
||||
|
||||
if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
|
||||
memcpy(skb_put(skb, hdr_len), data, hdr_len);
|
||||
|
||||
data += hdr_len + 2;
|
||||
true_len -= hdr_len;
|
||||
hdr_len = 0;
|
||||
}
|
||||
|
||||
/* If not doing paged RX allocated skb will always have enough space */
|
||||
copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8;
|
||||
frag = true_len - copy;
|
||||
|
||||
|
@ -97,10 +73,16 @@ mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
|
|||
}
|
||||
|
||||
return skb;
|
||||
|
||||
bad_frame:
|
||||
dev_err_ratelimited(dev->dev, "Error: incorrect frame len:%u hdr:%u\n",
|
||||
true_len, hdr_len);
|
||||
dev_kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
|
||||
u32 seg_len, struct page *p, bool paged)
|
||||
u32 seg_len, struct page *p)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct mt7601u_rxwi *rxwi;
|
||||
|
@ -126,11 +108,7 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
|
|||
|
||||
trace_mt_rx(dev, rxwi, fce_info);
|
||||
|
||||
if (paged)
|
||||
skb = mt7601u_rx_skb_from_seg_paged(dev, rxwi, data, seg_len,
|
||||
truesize, p);
|
||||
else
|
||||
skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len);
|
||||
skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len, truesize, p);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
|
@ -158,23 +136,17 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
|
|||
u32 seg_len, data_len = e->urb->actual_length;
|
||||
u8 *data = page_address(e->p);
|
||||
struct page *new_p = NULL;
|
||||
bool paged = true;
|
||||
int cnt = 0;
|
||||
|
||||
if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state))
|
||||
return;
|
||||
|
||||
/* Copy if there is very little data in the buffer. */
|
||||
if (data_len < 512) {
|
||||
paged = false;
|
||||
} else {
|
||||
if (data_len > 512)
|
||||
new_p = dev_alloc_pages(MT_RX_ORDER);
|
||||
if (!new_p)
|
||||
paged = false;
|
||||
}
|
||||
|
||||
while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) {
|
||||
mt7601u_rx_process_seg(dev, data, seg_len, e->p, paged);
|
||||
mt7601u_rx_process_seg(dev, data, seg_len, new_p ? e->p : NULL);
|
||||
|
||||
data_len -= seg_len;
|
||||
data += seg_len;
|
||||
|
@ -182,9 +154,9 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
|
|||
}
|
||||
|
||||
if (cnt > 1)
|
||||
trace_mt_rx_dma_aggr(dev, cnt, paged);
|
||||
trace_mt_rx_dma_aggr(dev, cnt, !!new_p);
|
||||
|
||||
if (paged) {
|
||||
if (new_p) {
|
||||
/* we have one extra ref from the allocator */
|
||||
__free_pages(e->p, MT_RX_ORDER);
|
||||
|
||||
|
|
|
@ -277,6 +277,10 @@ mt7601u_extra_power_over_mac(struct mt7601u_dev *dev)
|
|||
static void
|
||||
mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value)
|
||||
{
|
||||
/* Invalid? Note: vendor driver does not handle this */
|
||||
if (value == 0xff)
|
||||
return;
|
||||
|
||||
rate->raw = s6_validate(value);
|
||||
rate->bw20 = s6_to_int(value);
|
||||
/* Note: vendor driver does cap the value to s6 right away */
|
||||
|
|
|
@ -427,6 +427,9 @@ err:
|
|||
|
||||
void mt7601u_cleanup(struct mt7601u_dev *dev)
|
||||
{
|
||||
if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state))
|
||||
return;
|
||||
|
||||
mt7601u_stop_hardware(dev);
|
||||
mt7601u_dma_cleanup(dev);
|
||||
mt7601u_mcu_cmd_deinit(dev);
|
||||
|
|
|
@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
|
|||
{
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct mt7601u_rxwi *rxwi = rxi;
|
||||
u32 ctl = le32_to_cpu(rxwi->ctl);
|
||||
u32 len, ctl = le32_to_cpu(rxwi->ctl);
|
||||
u16 rate = le16_to_cpu(rxwi->rate);
|
||||
int rssi;
|
||||
|
||||
len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
|
||||
if (len < 10)
|
||||
return 0;
|
||||
|
||||
if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
|
||||
status->flag |= RX_FLAG_DECRYPTED;
|
||||
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
|
||||
|
@ -474,7 +478,7 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
|
|||
dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
|
||||
spin_unlock_bh(&dev->con_mon_lock);
|
||||
|
||||
return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
|
||||
return len;
|
||||
}
|
||||
|
||||
static enum mt76_cipher_type
|
||||
|
|
|
@ -119,6 +119,7 @@ mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
|
|||
|
||||
dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
|
||||
|
||||
MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC);
|
||||
MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
|
||||
MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
|
||||
MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
|
||||
|
|
|
@ -338,8 +338,15 @@ static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
|
|||
static int mt7601u_resume(struct usb_interface *usb_intf)
|
||||
{
|
||||
struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
|
||||
int ret;
|
||||
|
||||
return mt7601u_init_hardware(dev);
|
||||
ret = mt7601u_init_hardware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
|
||||
|
|
|
@ -161,19 +161,38 @@ int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
|
|||
cr_req->chan_desc.chan_width = radar_params->chandef->width;
|
||||
cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
|
||||
|
||||
mwifiex_dbg(priv->adapter, MSG,
|
||||
"11h: issuing DFS Radar check for channel=%d\n",
|
||||
radar_params->chandef->chan->hw_value);
|
||||
if (radar_params->cac_time_ms)
|
||||
mwifiex_dbg(priv->adapter, MSG,
|
||||
"11h: issuing DFS Radar check for channel=%d\n",
|
||||
radar_params->chandef->chan->hw_value);
|
||||
else
|
||||
mwifiex_dbg(priv->adapter, MSG, "cancelling CAC\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct mwifiex_radar_params radar_params;
|
||||
|
||||
memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
|
||||
radar_params.chandef = chandef;
|
||||
radar_params.cac_time_ms = 0;
|
||||
|
||||
return mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
|
||||
HostCmd_ACT_GEN_SET, 0, &radar_params, true);
|
||||
}
|
||||
|
||||
/* This function is to abort ongoing CAC upon stopping AP operations
|
||||
* or during unload.
|
||||
*/
|
||||
void mwifiex_abort_cac(struct mwifiex_private *priv)
|
||||
{
|
||||
if (priv->wdev.cac_started) {
|
||||
if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"failed to stop CAC in FW\n");
|
||||
mwifiex_dbg(priv->adapter, MSG,
|
||||
"Aborting delayed work for CAC.\n");
|
||||
cancel_delayed_work_sync(&priv->dfs_cac_work);
|
||||
|
@ -245,6 +264,9 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
|
|||
if (le32_to_cpu(rdr_event->passed)) {
|
||||
mwifiex_dbg(priv->adapter, MSG,
|
||||
"radar detected; indicating kernel\n");
|
||||
if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to stop CAC in FW\n");
|
||||
cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
|
||||
GFP_KERNEL);
|
||||
mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
|
||||
|
@ -252,7 +274,7 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
|
|||
mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n",
|
||||
rdr_event->det_type);
|
||||
} else {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
mwifiex_dbg(priv->adapter, MSG,
|
||||
"false radar detection event!\n");
|
||||
}
|
||||
|
||||
|
@ -283,7 +305,7 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef);
|
||||
mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef);
|
||||
|
||||
if (mwifiex_config_start_uap(priv, bss_cfg)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
|
|
|
@ -156,7 +156,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
|
|||
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp)
|
||||
{
|
||||
int tid;
|
||||
int tid, tid_down;
|
||||
struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
|
||||
struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
|
@ -167,7 +167,9 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
|
|||
|
||||
tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
|
||||
>> BLOCKACKPARAM_TID_POS;
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, tid, add_ba_rsp->
|
||||
|
||||
tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp->
|
||||
peer_mac_addr);
|
||||
if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
|
||||
if (ra_list) {
|
||||
|
@ -530,13 +532,16 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
|
|||
struct mwifiex_tx_ba_stream_tbl *new_node;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
unsigned long flags;
|
||||
int tid_down;
|
||||
|
||||
if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
|
||||
new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl),
|
||||
GFP_ATOMIC);
|
||||
if (!new_node)
|
||||
return;
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra);
|
||||
|
||||
tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra);
|
||||
if (ra_list) {
|
||||
ra_list->ba_status = ba_status;
|
||||
ra_list->amsdu_in_ampdu = false;
|
||||
|
@ -642,6 +647,30 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sends delba to specific tid
|
||||
*/
|
||||
void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
|
||||
|
||||
if (list_empty(&priv->rx_reorder_tbl_ptr)) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
|
||||
if (rx_reor_tbl_ptr->tid == tid) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"Send delba to tid=%d, %pM\n",
|
||||
tid, rx_reor_tbl_ptr->ta);
|
||||
mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the command response of a delete BA request.
|
||||
*/
|
||||
|
@ -814,3 +843,72 @@ u8 mwifiex_get_sec_chan_offset(int chan)
|
|||
|
||||
return sec_offset;
|
||||
}
|
||||
|
||||
/* This function will send DELBA to entries in the priv's
|
||||
* Tx BA stream table
|
||||
*/
|
||||
static void
|
||||
mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr;
|
||||
|
||||
if (list_empty(&priv->tx_ba_stream_tbl_ptr))
|
||||
return;
|
||||
|
||||
list_for_each_entry(tx_ba_stream_tbl_ptr,
|
||||
&priv->tx_ba_stream_tbl_ptr, list) {
|
||||
if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) {
|
||||
if (tid == tx_ba_stream_tbl_ptr->tid) {
|
||||
dev_dbg(adapter->dev,
|
||||
"Tx:Send delba to tid=%d, %pM\n", tid,
|
||||
tx_ba_stream_tbl_ptr->ra);
|
||||
mwifiex_send_delba(priv,
|
||||
tx_ba_stream_tbl_ptr->tid,
|
||||
tx_ba_stream_tbl_ptr->ra, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function updates all the tx_win_size
|
||||
*/
|
||||
void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
u8 i;
|
||||
u32 tx_win_size;
|
||||
struct mwifiex_private *priv;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
if (!adapter->priv[i])
|
||||
continue;
|
||||
priv = adapter->priv[i];
|
||||
tx_win_size = priv->add_ba_param.tx_win_size;
|
||||
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
|
||||
priv->add_ba_param.tx_win_size =
|
||||
MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
|
||||
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
|
||||
priv->add_ba_param.tx_win_size =
|
||||
MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
|
||||
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
|
||||
priv->add_ba_param.tx_win_size =
|
||||
MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
|
||||
|
||||
if (adapter->coex_win_size) {
|
||||
if (adapter->coex_tx_win_size)
|
||||
priv->add_ba_param.tx_win_size =
|
||||
adapter->coex_tx_win_size;
|
||||
}
|
||||
|
||||
if (tx_win_size != priv->add_ba_param.tx_win_size) {
|
||||
if (!priv->media_connected)
|
||||
continue;
|
||||
for (i = 0; i < MAX_NUM_TID; i++)
|
||||
mwifiex_send_delba_txbastream_tbl(priv, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -663,6 +663,7 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
|||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
u8 cleanup_rx_reorder_tbl;
|
||||
unsigned long flags;
|
||||
int tid_down;
|
||||
|
||||
if (type == TYPE_DELBA_RECEIVE)
|
||||
cleanup_rx_reorder_tbl = (initiator) ? true : false;
|
||||
|
@ -688,7 +689,9 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
|||
"event: TID, RA not found in table\n");
|
||||
return;
|
||||
}
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, tid, peer_mac);
|
||||
|
||||
tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac);
|
||||
if (ra_list) {
|
||||
ra_list->amsdu_in_ampdu = false;
|
||||
ra_list->ba_status = BA_SETUP_NONE;
|
||||
|
@ -825,3 +828,83 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function update all the rx_win_size based on coex flag
|
||||
*/
|
||||
static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter,
|
||||
bool coex_flag)
|
||||
{
|
||||
u8 i;
|
||||
u32 rx_win_size;
|
||||
struct mwifiex_private *priv;
|
||||
|
||||
dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag);
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
if (!adapter->priv[i])
|
||||
continue;
|
||||
priv = adapter->priv[i];
|
||||
rx_win_size = priv->add_ba_param.rx_win_size;
|
||||
if (coex_flag) {
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE;
|
||||
} else {
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
|
||||
}
|
||||
|
||||
if (adapter->coex_win_size && adapter->coex_rx_win_size)
|
||||
priv->add_ba_param.rx_win_size =
|
||||
adapter->coex_rx_win_size;
|
||||
|
||||
if (rx_win_size != priv->add_ba_param.rx_win_size) {
|
||||
if (!priv->media_connected)
|
||||
continue;
|
||||
for (i = 0; i < MAX_NUM_TID; i++)
|
||||
mwifiex_11n_delba(priv, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function check coex for RX BA
|
||||
*/
|
||||
void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
u8 i;
|
||||
struct mwifiex_private *priv;
|
||||
u8 count = 0;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
if (adapter->priv[i]) {
|
||||
priv = adapter->priv[i];
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
|
||||
if (priv->media_connected)
|
||||
count++;
|
||||
}
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
|
||||
if (priv->bss_started)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count >= MWIFIEX_BSS_COEX_COUNT)
|
||||
break;
|
||||
}
|
||||
if (count >= MWIFIEX_BSS_COEX_COUNT)
|
||||
mwifiex_update_ampdu_rxwinsize(adapter, true);
|
||||
else
|
||||
mwifiex_update_ampdu_rxwinsize(adapter, false);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,22 @@ u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
|
|||
}
|
||||
}
|
||||
|
||||
/* This function maps IEEE HT secondary channel type to NL80211 channel type
|
||||
*/
|
||||
u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset)
|
||||
{
|
||||
switch (second_chan_offset) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_NONE:
|
||||
return NL80211_CHAN_HT20;
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
return NL80211_CHAN_HT40PLUS;
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
|
||||
return NL80211_CHAN_HT40MINUS;
|
||||
default:
|
||||
return NL80211_CHAN_HT20;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks whether WEP is set.
|
||||
*/
|
||||
|
@ -1213,6 +1229,7 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
|
|||
*/
|
||||
static int
|
||||
mwifiex_dump_station_info(struct mwifiex_private *priv,
|
||||
struct mwifiex_sta_node *node,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
u32 rate;
|
||||
|
@ -1222,6 +1239,30 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
|
|||
BIT(NL80211_STA_INFO_TX_BITRATE) |
|
||||
BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
|
||||
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
|
||||
if (!node)
|
||||
return -ENOENT;
|
||||
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
|
||||
BIT(NL80211_STA_INFO_TX_FAILED);
|
||||
sinfo->inactive_time =
|
||||
jiffies_to_msecs(jiffies - node->stats.last_rx);
|
||||
|
||||
sinfo->signal = node->stats.rssi;
|
||||
sinfo->signal_avg = node->stats.rssi;
|
||||
sinfo->rx_bytes = node->stats.rx_bytes;
|
||||
sinfo->tx_bytes = node->stats.tx_bytes;
|
||||
sinfo->rx_packets = node->stats.rx_packets;
|
||||
sinfo->tx_packets = node->stats.tx_packets;
|
||||
sinfo->tx_failed = node->stats.tx_failed;
|
||||
|
||||
mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo,
|
||||
&sinfo->txrate);
|
||||
sinfo->txrate.legacy = node->stats.last_tx_rate * 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get signal information from the firmware */
|
||||
if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
|
||||
HostCmd_ACT_GEN_GET, 0, NULL, true)) {
|
||||
|
@ -1288,7 +1329,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
|
||||
return -ENOENT;
|
||||
|
||||
return mwifiex_dump_station_info(priv, sinfo);
|
||||
return mwifiex_dump_station_info(priv, NULL, sinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1299,13 +1340,29 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
static struct mwifiex_sta_node *node;
|
||||
|
||||
if (!priv->media_connected || idx)
|
||||
return -ENOENT;
|
||||
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
|
||||
priv->media_connected && idx == 0) {
|
||||
ether_addr_copy(mac, priv->cfg_bssid);
|
||||
return mwifiex_dump_station_info(priv, NULL, sinfo);
|
||||
} else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
|
||||
mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
|
||||
HostCmd_ACT_GEN_GET, 0, NULL, true);
|
||||
|
||||
memcpy(mac, priv->cfg_bssid, ETH_ALEN);
|
||||
if (node && (&node->list == &priv->sta_list)) {
|
||||
node = NULL;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return mwifiex_dump_station_info(priv, sinfo);
|
||||
node = list_prepare_entry(node, &priv->sta_list, list);
|
||||
list_for_each_entry_continue(node, &priv->sta_list, list) {
|
||||
ether_addr_copy(mac, node->mac_addr);
|
||||
return mwifiex_dump_station_info(priv, node, sinfo);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1725,6 +1782,13 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL, true)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to reset BSS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1778,7 +1842,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mwifiex_uap_set_channel(bss_cfg, params->chandef);
|
||||
mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);
|
||||
mwifiex_set_uap_rates(bss_cfg, params);
|
||||
|
||||
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
|
||||
|
@ -1803,6 +1867,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
|
||||
mwifiex_set_wmm_params(priv, bss_cfg, params);
|
||||
|
||||
if (mwifiex_is_11h_active(priv))
|
||||
mwifiex_set_tpc_params(priv, bss_cfg, params);
|
||||
|
||||
if (mwifiex_is_11h_active(priv) &&
|
||||
!cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef,
|
||||
priv->bss_mode)) {
|
||||
|
@ -1813,7 +1880,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
"Failed to disable 11h extensions!!");
|
||||
return -1;
|
||||
}
|
||||
priv->state_11h.is_11h_active = true;
|
||||
priv->state_11h.is_11h_active = false;
|
||||
}
|
||||
|
||||
if (mwifiex_config_start_uap(priv, bss_cfg)) {
|
||||
|
@ -2518,7 +2585,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
|
||||
priv->bss_priority = 0;
|
||||
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
|
||||
priv->bss_num = 0;
|
||||
priv->bss_num = adapter->curr_iface_comb.sta_intf;
|
||||
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
@ -2544,7 +2611,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
priv->bss_priority = 0;
|
||||
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
|
||||
priv->bss_started = 0;
|
||||
priv->bss_num = 0;
|
||||
priv->bss_num = adapter->curr_iface_comb.uap_intf;
|
||||
priv->bss_mode = type;
|
||||
|
||||
break;
|
||||
|
@ -2580,7 +2647,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
|
||||
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
|
||||
priv->bss_started = 0;
|
||||
priv->bss_num = 0;
|
||||
priv->bss_num = adapter->curr_iface_comb.p2p_intf;
|
||||
|
||||
if (mwifiex_cfg80211_init_p2p_client(priv)) {
|
||||
memset(&priv->wdev, 0, sizeof(priv->wdev));
|
||||
|
@ -3366,6 +3433,45 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
|
||||
struct mwifiex_bssdescriptor *curr_bss;
|
||||
struct ieee80211_channel *chan;
|
||||
u8 second_chan_offset;
|
||||
enum nl80211_channel_type chan_type;
|
||||
enum ieee80211_band band;
|
||||
int freq;
|
||||
int ret = -ENODATA;
|
||||
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
|
||||
cfg80211_chandef_valid(&priv->bss_chandef)) {
|
||||
*chandef = priv->bss_chandef;
|
||||
ret = 0;
|
||||
} else if (priv->media_connected) {
|
||||
curr_bss = &priv->curr_bss_params.bss_descriptor;
|
||||
band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
|
||||
freq = ieee80211_channel_to_frequency(curr_bss->channel, band);
|
||||
chan = ieee80211_get_channel(wiphy, freq);
|
||||
|
||||
if (curr_bss->bcn_ht_oper) {
|
||||
second_chan_offset = curr_bss->bcn_ht_oper->ht_param &
|
||||
IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
|
||||
chan_type = mwifiex_sec_chan_offset_to_chan_type
|
||||
(second_chan_offset);
|
||||
cfg80211_chandef_create(chandef, chan, chan_type);
|
||||
} else {
|
||||
cfg80211_chandef_create(chandef, chan,
|
||||
NL80211_CHAN_NO_HT);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
|
@ -3471,6 +3577,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
|
|||
.tdls_oper = mwifiex_cfg80211_tdls_oper,
|
||||
.add_station = mwifiex_cfg80211_add_station,
|
||||
.change_station = mwifiex_cfg80211_change_station,
|
||||
.get_channel = mwifiex_cfg80211_get_channel,
|
||||
.start_radar_detection = mwifiex_cfg80211_start_radar_detection,
|
||||
.channel_switch = mwifiex_cfg80211_channel_switch,
|
||||
};
|
||||
|
@ -3578,7 +3685,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
|||
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
|
||||
WIPHY_FLAG_AP_UAPSD |
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
WIPHY_FLAG_HAS_CHANNEL_SWITCH |
|
||||
WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
|
||||
wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
|
||||
|
|
|
@ -469,10 +469,11 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
|
|||
memset(rx_info, 0, sizeof(*rx_info));
|
||||
rx_info->bss_num = priv->bss_num;
|
||||
rx_info->bss_type = priv->bss_type;
|
||||
mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:",
|
||||
skb->data, skb->len);
|
||||
}
|
||||
|
||||
mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause);
|
||||
mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", skb->data, skb->len);
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
ret = mwifiex_process_uap_event(priv);
|
||||
|
@ -574,6 +575,8 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
|
|||
case HostCmd_CMD_UAP_BSS_START:
|
||||
case HostCmd_CMD_UAP_BSS_STOP:
|
||||
case HostCmd_CMD_UAP_STA_DEAUTH:
|
||||
case HOST_CMD_APCMD_SYS_RESET:
|
||||
case HOST_CMD_APCMD_STA_LIST:
|
||||
ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
|
||||
cmd_oid, data_buf,
|
||||
cmd_ptr);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <uapi/linux/if_arp.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
|
||||
#define MWIFIEX_BSS_COEX_COUNT 2
|
||||
#define MWIFIEX_MAX_BSS_NUM (3)
|
||||
|
||||
#define MWIFIEX_DMA_ALIGN_SZ 64
|
||||
|
@ -49,7 +49,12 @@
|
|||
|
||||
#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 64
|
||||
#define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 64
|
||||
#define MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE 16
|
||||
|
||||
#define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32
|
||||
|
||||
#define MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE 16
|
||||
|
||||
#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16
|
||||
#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 64
|
||||
#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 64
|
||||
|
|
|
@ -128,6 +128,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
|
||||
#define TLV_TYPE_UAP_SSID 0x0000
|
||||
#define TLV_TYPE_UAP_RATES 0x0001
|
||||
#define TLV_TYPE_PWR_CONSTRAINT 0x0020
|
||||
|
||||
#define PROPRIETARY_TLV_BASE_ID 0x0100
|
||||
#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
|
||||
|
@ -174,6 +175,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197)
|
||||
#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
|
||||
#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198)
|
||||
#define TLV_BTCOEX_WL_AGGR_WINSIZE (PROPRIETARY_TLV_BASE_ID + 202)
|
||||
#define TLV_BTCOEX_WL_SCANTIME (PROPRIETARY_TLV_BASE_ID + 203)
|
||||
|
||||
#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048
|
||||
|
||||
|
@ -330,9 +333,11 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
#define HostCmd_CMD_RSSI_INFO 0x00a4
|
||||
#define HostCmd_CMD_FUNC_INIT 0x00a9
|
||||
#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
|
||||
#define HOST_CMD_APCMD_SYS_RESET 0x00af
|
||||
#define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0
|
||||
#define HostCmd_CMD_UAP_BSS_START 0x00b1
|
||||
#define HostCmd_CMD_UAP_BSS_STOP 0x00b2
|
||||
#define HOST_CMD_APCMD_STA_LIST 0x00b3
|
||||
#define HostCmd_CMD_UAP_STA_DEAUTH 0x00b5
|
||||
#define HostCmd_CMD_11N_CFG 0x00cd
|
||||
#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce
|
||||
|
@ -419,8 +424,12 @@ enum P2P_MODES {
|
|||
#define HS_CFG_COND_MAC_EVENT 0x00000004
|
||||
#define HS_CFG_COND_MULTICAST_DATA 0x00000008
|
||||
|
||||
#define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc
|
||||
#define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2
|
||||
#define CONNECT_ERR_AUTH_ERR_STA_FAILURE 0xFFFB
|
||||
#define CONNECT_ERR_ASSOC_ERR_TIMEOUT 0xFFFC
|
||||
#define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED 0xFFFD
|
||||
#define CONNECT_ERR_AUTH_MSG_UNHANDLED 0xFFFE
|
||||
#define CONNECT_ERR_STA_FAILURE 0xFFFF
|
||||
|
||||
|
||||
#define CMD_F_HOSTCMD (1 << 0)
|
||||
#define CMD_F_CANCELED (1 << 1)
|
||||
|
@ -503,6 +512,7 @@ enum P2P_MODES {
|
|||
#define EVENT_EXT_SCAN_REPORT 0x00000058
|
||||
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
|
||||
#define EVENT_TX_STATUS_REPORT 0x00000074
|
||||
#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
|
||||
|
||||
#define EVENT_ID_MASK 0xffff
|
||||
#define BSS_NUM_MASK 0xf
|
||||
|
@ -627,7 +637,12 @@ struct uap_rxpd {
|
|||
__le16 rx_pkt_type;
|
||||
__le16 seq_num;
|
||||
u8 priority;
|
||||
u8 reserved1;
|
||||
u8 rx_rate;
|
||||
s8 snr;
|
||||
s8 nf;
|
||||
u8 ht_info;
|
||||
u8 reserved[3];
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
struct mwifiex_fw_chan_stats {
|
||||
|
@ -1151,6 +1166,13 @@ enum SNMP_MIB_INDEX {
|
|||
DOT11H_I = 10,
|
||||
};
|
||||
|
||||
enum mwifiex_assocmd_failurepoint {
|
||||
MWIFIEX_ASSOC_CMD_SUCCESS = 0,
|
||||
MWIFIEX_ASSOC_CMD_FAILURE_ASSOC,
|
||||
MWIFIEX_ASSOC_CMD_FAILURE_AUTH,
|
||||
MWIFIEX_ASSOC_CMD_FAILURE_JOIN
|
||||
};
|
||||
|
||||
#define MAX_SNMP_BUF_SIZE 128
|
||||
|
||||
struct host_cmd_ds_802_11_snmp_mib {
|
||||
|
@ -1448,6 +1470,18 @@ struct host_cmd_ds_sta_deauth {
|
|||
__le16 reason;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_ie_types_sta_info {
|
||||
struct mwifiex_ie_types_header header;
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 power_mfg_status;
|
||||
s8 rssi;
|
||||
};
|
||||
|
||||
struct host_cmd_ds_sta_list {
|
||||
u16 sta_count;
|
||||
u8 tlv[0];
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_ie_types_pwr_capability {
|
||||
struct mwifiex_ie_types_header header;
|
||||
s8 min_pwr;
|
||||
|
@ -1750,6 +1784,27 @@ struct host_cmd_tlv_ageout_timer {
|
|||
__le32 sta_ao_timer;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_power_constraint {
|
||||
struct mwifiex_ie_types_header header;
|
||||
u8 constraint;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_ie_types_btcoex_scan_time {
|
||||
struct mwifiex_ie_types_header header;
|
||||
u8 coex_scan;
|
||||
u8 reserved;
|
||||
u16 min_scan_time;
|
||||
u16 max_scan_time;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_ie_types_btcoex_aggr_win_size {
|
||||
struct mwifiex_ie_types_header header;
|
||||
u8 coex_win_size;
|
||||
u8 tx_win_size;
|
||||
u8 rx_win_size;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_version_ext {
|
||||
u8 version_str_sel;
|
||||
char version_str[128];
|
||||
|
@ -1977,6 +2032,7 @@ struct host_cmd_ds_command {
|
|||
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
|
||||
struct host_cmd_ds_sys_config uap_sys_config;
|
||||
struct host_cmd_ds_sta_deauth sta_deauth;
|
||||
struct host_cmd_ds_sta_list sta_list;
|
||||
struct host_cmd_11ac_vht_cfg vht_cfg;
|
||||
struct host_cmd_ds_coalesce_cfg coalesce_cfg;
|
||||
struct host_cmd_ds_tdls_oper tdls_oper;
|
||||
|
|
|
@ -320,63 +320,81 @@ done:
|
|||
/* This function parses head and tail IEs, from cfg80211_beacon_data and sets
|
||||
* these IE to FW.
|
||||
*/
|
||||
static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
|
||||
struct cfg80211_beacon_data *info)
|
||||
static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
||||
struct cfg80211_beacon_data *info)
|
||||
{
|
||||
struct mwifiex_ie *gen_ie;
|
||||
struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
|
||||
struct ieee_types_header *chsw_ie = NULL;
|
||||
struct ieee_types_header *hdr;
|
||||
struct ieee80211_vendor_ie *vendorhdr;
|
||||
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
|
||||
const u8 *vendor_ie;
|
||||
int left_len, parsed_len = 0;
|
||||
|
||||
if (!info->tail || !info->tail_len)
|
||||
return 0;
|
||||
|
||||
gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
|
||||
if (!gen_ie)
|
||||
return -ENOMEM;
|
||||
|
||||
left_len = info->tail_len;
|
||||
|
||||
/* Many IEs are generated in FW by parsing bss configuration.
|
||||
* Let's not add them here; else we may end up duplicating these IEs
|
||||
*/
|
||||
while (left_len > sizeof(struct ieee_types_header)) {
|
||||
hdr = (void *)(info->tail + parsed_len);
|
||||
switch (hdr->element_id) {
|
||||
case WLAN_EID_SSID:
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
case WLAN_EID_COUNTRY:
|
||||
case WLAN_EID_PWR_CONSTRAINT:
|
||||
case WLAN_EID_EXT_SUPP_RATES:
|
||||
case WLAN_EID_HT_CAPABILITY:
|
||||
case WLAN_EID_HT_OPERATION:
|
||||
case WLAN_EID_VHT_CAPABILITY:
|
||||
case WLAN_EID_VHT_OPERATION:
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
break;
|
||||
default:
|
||||
memcpy(gen_ie->ie_buffer + ie_len, hdr,
|
||||
hdr->len + sizeof(struct ieee_types_header));
|
||||
ie_len += hdr->len + sizeof(struct ieee_types_header);
|
||||
break;
|
||||
}
|
||||
left_len -= hdr->len + sizeof(struct ieee_types_header);
|
||||
parsed_len += hdr->len + sizeof(struct ieee_types_header);
|
||||
}
|
||||
|
||||
/* parse only WPA vendor IE from tail, WMM IE is configured by
|
||||
* bss_config command
|
||||
*/
|
||||
vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
|
||||
WLAN_OUI_TYPE_MICROSOFT_WPA,
|
||||
info->tail, info->tail_len);
|
||||
if (vendorhdr) {
|
||||
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
|
||||
vendorhdr->len + sizeof(struct ieee_types_header));
|
||||
ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
|
||||
}
|
||||
|
||||
if (!ie_len) {
|
||||
kfree(gen_ie);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gen_ie->ie_index = cpu_to_le16(gen_idx);
|
||||
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
|
||||
MGMT_MASK_PROBE_RESP |
|
||||
MGMT_MASK_ASSOC_RESP);
|
||||
gen_ie->ie_length = cpu_to_le16(ie_len);
|
||||
|
||||
if (info->tail && info->tail_len) {
|
||||
rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
|
||||
info->tail, info->tail_len);
|
||||
if (rsn_ie) {
|
||||
memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2);
|
||||
ie_len = rsn_ie->len + 2;
|
||||
gen_ie->ie_length = cpu_to_le16(ie_len);
|
||||
}
|
||||
|
||||
vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
|
||||
WLAN_OUI_TYPE_MICROSOFT_WPA,
|
||||
info->tail,
|
||||
info->tail_len);
|
||||
if (vendor_ie) {
|
||||
wpa_ie = (struct ieee_types_header *)vendor_ie;
|
||||
memcpy(gen_ie->ie_buffer + ie_len,
|
||||
wpa_ie, wpa_ie->len + 2);
|
||||
ie_len += wpa_ie->len + 2;
|
||||
gen_ie->ie_length = cpu_to_le16(ie_len);
|
||||
}
|
||||
|
||||
chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
|
||||
info->tail, info->tail_len);
|
||||
if (chsw_ie) {
|
||||
memcpy(gen_ie->ie_buffer + ie_len,
|
||||
chsw_ie, chsw_ie->len + 2);
|
||||
ie_len += chsw_ie->len + 2;
|
||||
gen_ie->ie_length = cpu_to_le16(ie_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (rsn_ie || wpa_ie || chsw_ie) {
|
||||
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL,
|
||||
NULL, NULL, NULL)) {
|
||||
kfree(gen_ie);
|
||||
return -1;
|
||||
}
|
||||
priv->gen_idx = gen_idx;
|
||||
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
|
||||
NULL, NULL)) {
|
||||
kfree(gen_ie);
|
||||
return -1;
|
||||
}
|
||||
|
||||
priv->gen_idx = gen_idx;
|
||||
kfree(gen_ie);
|
||||
return 0;
|
||||
}
|
||||
|
@ -390,7 +408,7 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = mwifiex_uap_set_head_tail_ies(priv, info);
|
||||
ret = mwifiex_uap_parse_tail_ies(priv, info);
|
||||
return ret;
|
||||
|
||||
return mwifiex_set_mgmt_beacon_data_ies(priv, info);
|
||||
|
|
|
@ -113,6 +113,7 @@ struct mwifiex_uap_bss_param {
|
|||
u32 sta_ao_timer;
|
||||
u32 ps_sta_ao_timer;
|
||||
u8 qos_info;
|
||||
u8 power_constraint;
|
||||
struct mwifiex_types_wmm_info wmm_info;
|
||||
};
|
||||
|
||||
|
|
|
@ -556,6 +556,23 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *assoc_failure_reason_to_str(u16 cap_info)
|
||||
{
|
||||
switch (cap_info) {
|
||||
case CONNECT_ERR_AUTH_ERR_STA_FAILURE:
|
||||
return "CONNECT_ERR_AUTH_ERR_STA_FAILURE";
|
||||
case CONNECT_ERR_AUTH_MSG_UNHANDLED:
|
||||
return "CONNECT_ERR_AUTH_MSG_UNHANDLED";
|
||||
case CONNECT_ERR_ASSOC_ERR_TIMEOUT:
|
||||
return "CONNECT_ERR_ASSOC_ERR_TIMEOUT";
|
||||
case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED:
|
||||
return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED";
|
||||
case CONNECT_ERR_STA_FAILURE:
|
||||
return "CONNECT_ERR_STA_FAILURE";
|
||||
}
|
||||
|
||||
return "Unknown connect failure";
|
||||
}
|
||||
/*
|
||||
* Association firmware command response handler
|
||||
*
|
||||
|
@ -656,11 +673,18 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
|
|||
status_code, cap_info,
|
||||
le16_to_cpu(assoc_rsp->a_id));
|
||||
|
||||
if (cap_info == MWIFIEX_TIMEOUT_FOR_AP_RESP) {
|
||||
if (status_code == MWIFIEX_STATUS_CODE_AUTH_TIMEOUT)
|
||||
mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n",
|
||||
assoc_failure_reason_to_str(cap_info));
|
||||
if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) {
|
||||
if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) {
|
||||
ret = WLAN_STATUS_AUTH_TIMEOUT;
|
||||
else
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"ASSOC_RESP: AUTH timeout\n");
|
||||
} else {
|
||||
ret = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"ASSOC_RESP: UNSPECIFIED failure\n");
|
||||
}
|
||||
} else {
|
||||
ret = status_code;
|
||||
}
|
||||
|
|
|
@ -642,6 +642,7 @@ struct mwifiex_private {
|
|||
u8 del_list_idx;
|
||||
bool hs2_enabled;
|
||||
struct mwifiex_uap_bss_param bss_cfg;
|
||||
struct cfg80211_chan_def bss_chandef;
|
||||
struct station_parameters *sta_params;
|
||||
struct sk_buff_head tdls_txq;
|
||||
u8 check_tdls_tx;
|
||||
|
@ -740,6 +741,18 @@ struct mwifiex_tdls_capab {
|
|||
struct ieee80211_vht_operation vhtoper;
|
||||
};
|
||||
|
||||
struct mwifiex_station_stats {
|
||||
u64 last_rx;
|
||||
s8 rssi;
|
||||
u64 rx_bytes;
|
||||
u64 tx_bytes;
|
||||
u32 rx_packets;
|
||||
u32 tx_packets;
|
||||
u32 tx_failed;
|
||||
u8 last_tx_rate;
|
||||
u8 last_tx_htinfo;
|
||||
};
|
||||
|
||||
/* This is AP/TDLS specific structure which stores information
|
||||
* about associated/peer STA
|
||||
*/
|
||||
|
@ -754,6 +767,7 @@ struct mwifiex_sta_node {
|
|||
u16 max_amsdu;
|
||||
u8 tdls_status;
|
||||
struct mwifiex_tdls_capab tdls_cap;
|
||||
struct mwifiex_station_stats stats;
|
||||
};
|
||||
|
||||
struct mwifiex_auto_tdls_peer {
|
||||
|
@ -959,6 +973,12 @@ struct mwifiex_adapter {
|
|||
u32 num_in_chan_stats;
|
||||
int survey_idx;
|
||||
bool auto_tdls;
|
||||
u8 coex_scan;
|
||||
u8 coex_min_scan_time;
|
||||
u8 coex_max_scan_time;
|
||||
u8 coex_win_size;
|
||||
u8 coex_tx_win_size;
|
||||
u8 coex_rx_win_size;
|
||||
};
|
||||
|
||||
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
|
||||
|
@ -1135,6 +1155,9 @@ void mwifiex_set_ht_params(struct mwifiex_private *priv,
|
|||
void mwifiex_set_vht_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_tpc_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_vht_width(struct mwifiex_private *priv,
|
||||
|
@ -1145,6 +1168,11 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
|||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_ba_params(struct mwifiex_private *priv);
|
||||
|
||||
void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *pmadapter);
|
||||
void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
|
||||
struct sk_buff *event_skb);
|
||||
|
||||
void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
|
||||
int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd,
|
||||
|
@ -1382,6 +1410,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
|
|||
struct mwifiex_bssdescriptor *bss_desc);
|
||||
|
||||
u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type);
|
||||
u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset);
|
||||
|
||||
struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
||||
const char *name,
|
||||
|
@ -1399,7 +1428,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
|
|||
struct cfg80211_beacon_data *data);
|
||||
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
|
||||
u8 *mwifiex_11d_code_2_region(u8 code);
|
||||
void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
|
||||
void mwifiex_uap_set_channel(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_chan_def chandef);
|
||||
int mwifiex_config_start_uap(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg);
|
||||
|
@ -1473,6 +1503,8 @@ mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
|
|||
void mwifiex_dfs_cac_work_queue(struct work_struct *work);
|
||||
void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work);
|
||||
void mwifiex_abort_cac(struct mwifiex_private *priv);
|
||||
int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb);
|
||||
|
||||
|
@ -1488,7 +1520,8 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
|
|||
void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
|
||||
void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
|
||||
void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
|
||||
|
||||
void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter);
|
||||
void mwifiex_11n_delba(struct mwifiex_private *priv, int tid);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void mwifiex_debugfs_init(void);
|
||||
void mwifiex_debugfs_remove(void);
|
||||
|
|
|
@ -958,6 +958,27 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp)
|
||||
{
|
||||
struct host_cmd_ds_sta_list *sta_list =
|
||||
&resp->params.sta_list;
|
||||
struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv;
|
||||
int i;
|
||||
struct mwifiex_sta_node *sta_node;
|
||||
|
||||
for (i = 0; i < sta_list->sta_count; i++) {
|
||||
sta_node = mwifiex_get_sta_entry(priv, sta_info->mac);
|
||||
if (unlikely(!sta_node))
|
||||
continue;
|
||||
|
||||
sta_node->stats.rssi = sta_info->rssi;
|
||||
sta_info++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function handles the command response of set_cfg_data */
|
||||
static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp)
|
||||
|
@ -1148,6 +1169,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
|
|||
break;
|
||||
case HostCmd_CMD_UAP_SYS_CONFIG:
|
||||
break;
|
||||
case HOST_CMD_APCMD_STA_LIST:
|
||||
ret = mwifiex_ret_uap_sta_list(priv, resp);
|
||||
break;
|
||||
case HostCmd_CMD_UAP_BSS_START:
|
||||
adapter->tx_lock_flag = false;
|
||||
adapter->pps_uapsd_mode = false;
|
||||
|
@ -1159,6 +1183,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
|
|||
break;
|
||||
case HostCmd_CMD_UAP_STA_DEAUTH:
|
||||
break;
|
||||
case HOST_CMD_APCMD_SYS_RESET:
|
||||
break;
|
||||
case HostCmd_CMD_MEF_CFG:
|
||||
break;
|
||||
case HostCmd_CMD_COALESCE_CFG:
|
||||
|
|
|
@ -182,6 +182,63 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles coex events generated by firmware
|
||||
*/
|
||||
void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
|
||||
struct sk_buff *event_skb)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_ie_types_header *tlv;
|
||||
struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv;
|
||||
struct mwifiex_ie_types_btcoex_scan_time *scantlv;
|
||||
s32 len = event_skb->len - sizeof(u32);
|
||||
u8 *cur_ptr = event_skb->data + sizeof(u32);
|
||||
u16 tlv_type, tlv_len;
|
||||
|
||||
while (len >= sizeof(struct mwifiex_ie_types_header)) {
|
||||
tlv = (struct mwifiex_ie_types_header *)cur_ptr;
|
||||
tlv_len = le16_to_cpu(tlv->len);
|
||||
tlv_type = le16_to_cpu(tlv->type);
|
||||
|
||||
if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len)
|
||||
break;
|
||||
switch (tlv_type) {
|
||||
case TLV_BTCOEX_WL_AGGR_WINSIZE:
|
||||
winsizetlv =
|
||||
(struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv;
|
||||
adapter->coex_win_size = winsizetlv->coex_win_size;
|
||||
adapter->coex_tx_win_size =
|
||||
winsizetlv->tx_win_size;
|
||||
adapter->coex_rx_win_size =
|
||||
winsizetlv->rx_win_size;
|
||||
mwifiex_coex_ampdu_rxwinsize(adapter);
|
||||
mwifiex_update_ampdu_txwinsize(adapter);
|
||||
break;
|
||||
|
||||
case TLV_BTCOEX_WL_SCANTIME:
|
||||
scantlv =
|
||||
(struct mwifiex_ie_types_btcoex_scan_time *)tlv;
|
||||
adapter->coex_scan = scantlv->coex_scan;
|
||||
adapter->coex_min_scan_time = scantlv->min_scan_time;
|
||||
adapter->coex_max_scan_time = scantlv->max_scan_time;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
len -= tlv_len + sizeof(struct mwifiex_ie_types_header);
|
||||
cur_ptr += tlv_len +
|
||||
sizeof(struct mwifiex_ie_types_header);
|
||||
}
|
||||
|
||||
dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
|
||||
adapter->coex_scan, adapter->coex_min_scan_time,
|
||||
adapter->coex_win_size, adapter->coex_tx_win_size,
|
||||
adapter->coex_rx_win_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles events generated by firmware.
|
||||
*
|
||||
|
@ -531,6 +588,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
|||
ret = mwifiex_11h_handle_radar_detected(priv,
|
||||
adapter->event_skb);
|
||||
break;
|
||||
case EVENT_BT_COEX_WLAN_PARA_CHANGE:
|
||||
dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n");
|
||||
mwifiex_bt_coex_wlan_param_update_event(priv,
|
||||
adapter->event_skb);
|
||||
break;
|
||||
default:
|
||||
mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
|
||||
eventcause);
|
||||
|
|
|
@ -88,13 +88,22 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
|
|||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
u8 *head_ptr;
|
||||
struct txpd *local_tx_pd = NULL;
|
||||
struct mwifiex_sta_node *dest_node;
|
||||
struct ethhdr *hdr = (void *)skb->data;
|
||||
|
||||
hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
|
||||
dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
|
||||
if (dest_node) {
|
||||
dest_node->stats.tx_bytes += skb->len;
|
||||
dest_node->stats.tx_packets++;
|
||||
}
|
||||
|
||||
head_ptr = mwifiex_process_uap_txpd(priv, skb);
|
||||
else
|
||||
} else {
|
||||
head_ptr = mwifiex_process_sta_txpd(priv, skb);
|
||||
}
|
||||
|
||||
if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
|
||||
skb_queue_tail(&adapter->tx_data_q, skb);
|
||||
|
@ -310,11 +319,11 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
|
|||
priv->stats.tx_errors++;
|
||||
}
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) {
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
|
||||
atomic_dec_return(&adapter->pending_bridged_pkts);
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
|
||||
goto done;
|
||||
|
||||
if (aggr)
|
||||
/* For skb_aggr, do not wake up tx queue */
|
||||
|
|
|
@ -222,6 +222,23 @@ void mwifiex_set_vht_params(struct mwifiex_private *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
/* This function updates 11ac related parameters from IE
|
||||
* and sets them into bss_config structure.
|
||||
*/
|
||||
void mwifiex_set_tpc_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
const u8 *tpc_ie;
|
||||
|
||||
tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
|
||||
params->beacon.tail_len);
|
||||
if (tpc_ie)
|
||||
bss_cfg->power_constraint = *(tpc_ie + 2);
|
||||
else
|
||||
bss_cfg->power_constraint = 0;
|
||||
}
|
||||
|
||||
/* Enable VHT only when cfg80211_ap_settings has VHT IE.
|
||||
* Otherwise disable VHT.
|
||||
*/
|
||||
|
@ -466,6 +483,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
|||
struct host_cmd_tlv_auth_type *auth_type;
|
||||
struct host_cmd_tlv_rates *tlv_rates;
|
||||
struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
|
||||
struct host_cmd_tlv_power_constraint *pwr_ct;
|
||||
struct mwifiex_ie_types_htcap *htcap;
|
||||
struct mwifiex_ie_types_wmmcap *wmm_cap;
|
||||
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
|
||||
|
@ -644,6 +662,15 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
|||
tlv += sizeof(*ao_timer);
|
||||
}
|
||||
|
||||
if (bss_cfg->power_constraint) {
|
||||
pwr_ct = (void *)tlv;
|
||||
pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
|
||||
pwr_ct->header.len = cpu_to_le16(sizeof(u8));
|
||||
pwr_ct->constraint = bss_cfg->power_constraint;
|
||||
cmd_size += sizeof(*pwr_ct);
|
||||
tlv += sizeof(*pwr_ct);
|
||||
}
|
||||
|
||||
if (bss_cfg->ps_sta_ao_timer) {
|
||||
ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
|
||||
ps_ao_timer->header.type =
|
||||
|
@ -754,6 +781,8 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
|
|||
break;
|
||||
case HostCmd_CMD_UAP_BSS_START:
|
||||
case HostCmd_CMD_UAP_BSS_STOP:
|
||||
case HOST_CMD_APCMD_SYS_RESET:
|
||||
case HOST_CMD_APCMD_STA_LIST:
|
||||
cmd->command = cpu_to_le16(cmd_no);
|
||||
cmd->size = cpu_to_le16(S_DS_GEN);
|
||||
break;
|
||||
|
@ -775,11 +804,14 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
|
||||
void mwifiex_uap_set_channel(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_chan_def chandef)
|
||||
{
|
||||
u8 config_bands = 0;
|
||||
|
||||
priv->bss_chandef = chandef;
|
||||
|
||||
bss_cfg->channel = ieee80211_frequency_to_channel(
|
||||
chandef.chan->center_freq);
|
||||
|
||||
|
@ -800,19 +832,28 @@ void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
|
|||
if (chandef.width > NL80211_CHAN_WIDTH_40)
|
||||
config_bands |= BAND_AAC;
|
||||
}
|
||||
|
||||
priv->adapter->config_bands = config_bands;
|
||||
}
|
||||
|
||||
int mwifiex_config_start_uap(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg)
|
||||
{
|
||||
enum state_11d_t state_11d;
|
||||
|
||||
if (mwifiex_del_mgmt_ies(priv))
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to delete mgmt IEs!\n");
|
||||
|
||||
if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL, true)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to stop the BSS\n");
|
||||
mwifiex_dbg(priv->adapter, ERROR, "Failed to stop the BSS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL, true)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR, "Failed to reset BSS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -824,6 +865,16 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Send cmd to FW to enable 11D function */
|
||||
state_11d = ENABLE_11D;
|
||||
if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
|
||||
HostCmd_ACT_GEN_SET, DOT11D_I,
|
||||
&state_11d, true)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"11D: failed to enable 11D\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL, false)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
|
|
|
@ -21,8 +21,70 @@
|
|||
#include "main.h"
|
||||
#include "11n.h"
|
||||
|
||||
#define MWIFIEX_BSS_START_EVT_FIX_SIZE 12
|
||||
|
||||
static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv,
|
||||
struct sk_buff *event)
|
||||
{
|
||||
int evt_len;
|
||||
u8 *curr;
|
||||
u16 tlv_len;
|
||||
struct mwifiex_ie_types_data *tlv_hdr;
|
||||
struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
|
||||
int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
|
||||
|
||||
priv->wmm_enabled = false;
|
||||
skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
|
||||
evt_len = event->len;
|
||||
curr = event->data;
|
||||
|
||||
mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:",
|
||||
event->data, event->len);
|
||||
|
||||
while ((evt_len >= sizeof(tlv_hdr->header))) {
|
||||
tlv_hdr = (struct mwifiex_ie_types_data *)curr;
|
||||
tlv_len = le16_to_cpu(tlv_hdr->header.len);
|
||||
|
||||
if (evt_len < tlv_len + sizeof(tlv_hdr->header))
|
||||
break;
|
||||
|
||||
switch (le16_to_cpu(tlv_hdr->header.type)) {
|
||||
case WLAN_EID_HT_CAPABILITY:
|
||||
priv->ap_11n_enabled = true;
|
||||
break;
|
||||
|
||||
case WLAN_EID_VHT_CAPABILITY:
|
||||
priv->ap_11ac_enabled = true;
|
||||
break;
|
||||
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
/* Point the regular IEEE IE 2 bytes into the Marvell IE
|
||||
* and setup the IEEE IE type and length byte fields
|
||||
*/
|
||||
wmm_param_ie = (void *)(curr + 2);
|
||||
wmm_param_ie->vend_hdr.len = (u8)tlv_len;
|
||||
wmm_param_ie->vend_hdr.element_id =
|
||||
WLAN_EID_VENDOR_SPECIFIC;
|
||||
mwifiex_dbg(priv->adapter, EVENT,
|
||||
"info: check uap capabilities:\t"
|
||||
"wmm parameter set count: %d\n",
|
||||
wmm_param_ie->qos_info_bitmap & mask);
|
||||
|
||||
mwifiex_wmm_setup_ac_downgrade(priv);
|
||||
priv->wmm_enabled = true;
|
||||
mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
curr += (tlv_len + sizeof(tlv_hdr->header));
|
||||
evt_len -= (tlv_len + sizeof(tlv_hdr->header));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles AP interface specific events generated by firmware.
|
||||
|
@ -134,6 +196,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
|
|||
ETH_ALEN);
|
||||
if (priv->hist_data)
|
||||
mwifiex_hist_data_reset(priv);
|
||||
mwifiex_check_uap_capabilties(priv, adapter->event_skb);
|
||||
break;
|
||||
case EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
/* For future development */
|
||||
|
@ -229,6 +292,11 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
|
|||
mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
|
||||
mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
|
||||
break;
|
||||
case EVENT_BT_COEX_WLAN_PARA_CHANGE:
|
||||
dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
|
||||
mwifiex_bt_coex_wlan_param_update_event(priv,
|
||||
adapter->event_skb);
|
||||
break;
|
||||
default:
|
||||
mwifiex_dbg(adapter, EVENT,
|
||||
"event: unknown event id: %#x\n", eventcause);
|
||||
|
|
|
@ -97,6 +97,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
|
|||
struct mwifiex_txinfo *tx_info;
|
||||
int hdr_chop;
|
||||
struct ethhdr *p_ethhdr;
|
||||
struct mwifiex_sta_node *src_node;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
@ -180,6 +181,15 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
|
|||
tx_info->bss_type = priv->bss_type;
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
|
||||
|
||||
src_node = mwifiex_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source);
|
||||
if (src_node) {
|
||||
src_node->stats.last_rx = jiffies;
|
||||
src_node->stats.rx_bytes += skb->len;
|
||||
src_node->stats.rx_packets++;
|
||||
src_node->stats.last_tx_rate = uap_rx_pd->rx_rate;
|
||||
src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info;
|
||||
}
|
||||
|
||||
if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
|
||||
/* Update bridge packet statistics as the
|
||||
* packet is not going to kernel/upper layer.
|
||||
|
@ -275,6 +285,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
|
||||
|
||||
if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
|
||||
le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
|
@ -282,6 +294,11 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||
skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
|
||||
le16_to_cpu(uap_rx_pd->rx_pkt_length));
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
if (node)
|
||||
node->stats.tx_failed++;
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
return 0;
|
||||
}
|
||||
|
@ -295,7 +312,6 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
||||
|
||||
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
|
|
|
@ -329,7 +329,7 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
|
|||
struct rxpd *rx_pd)
|
||||
{
|
||||
u16 stype;
|
||||
u8 category, action_code;
|
||||
u8 category, action_code, *addr2;
|
||||
struct ieee80211_hdr *ieee_hdr = (void *)payload;
|
||||
|
||||
stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
|
||||
|
@ -337,21 +337,35 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
|
|||
switch (stype) {
|
||||
case IEEE80211_STYPE_ACTION:
|
||||
category = *(payload + sizeof(struct ieee80211_hdr));
|
||||
action_code = *(payload + sizeof(struct ieee80211_hdr) + 1);
|
||||
if (category == WLAN_CATEGORY_PUBLIC &&
|
||||
action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
|
||||
switch (category) {
|
||||
case WLAN_CATEGORY_PUBLIC:
|
||||
action_code = *(payload + sizeof(struct ieee80211_hdr)
|
||||
+ 1);
|
||||
if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
|
||||
addr2 = ieee_hdr->addr2;
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"TDLS discovery response %pM nf=%d, snr=%d\n",
|
||||
addr2, rx_pd->nf, rx_pd->snr);
|
||||
mwifiex_auto_tdls_update_peer_signal(priv,
|
||||
addr2,
|
||||
rx_pd->snr,
|
||||
rx_pd->nf);
|
||||
}
|
||||
break;
|
||||
case WLAN_CATEGORY_BACK:
|
||||
/*we dont indicate BACK action frames to cfg80211*/
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"TDLS discovery response %pM nf=%d, snr=%d\n",
|
||||
ieee_hdr->addr2, rx_pd->nf, rx_pd->snr);
|
||||
mwifiex_auto_tdls_update_peer_signal(priv,
|
||||
ieee_hdr->addr2,
|
||||
rx_pd->snr,
|
||||
rx_pd->nf);
|
||||
"drop BACK action frames");
|
||||
return -1;
|
||||
default:
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"unknown public action frame category %d\n",
|
||||
category);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"unknown mgmt frame subtype %#x\n", stype);
|
||||
"unknown mgmt frame subtype %#x\n", stype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -387,8 +401,9 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
|
|||
|
||||
ieee_hdr = (void *)skb->data;
|
||||
if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
|
||||
mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
|
||||
pkt_len, rx_pd);
|
||||
if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
|
||||
pkt_len, rx_pd))
|
||||
return -1;
|
||||
}
|
||||
/* Remove address4 */
|
||||
memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
|
||||
|
@ -416,12 +431,25 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
|
|||
*/
|
||||
int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_sta_node *src_node;
|
||||
struct ethhdr *p_ethhdr;
|
||||
|
||||
if (!skb)
|
||||
return -1;
|
||||
|
||||
priv->stats.rx_bytes += skb->len;
|
||||
priv->stats.rx_packets++;
|
||||
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
|
||||
p_ethhdr = (void *)skb->data;
|
||||
src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
|
||||
if (src_node) {
|
||||
src_node->stats.last_rx = jiffies;
|
||||
src_node->stats.rx_bytes += skb->len;
|
||||
src_node->stats.rx_packets++;
|
||||
}
|
||||
}
|
||||
|
||||
skb->dev = priv->netdev;
|
||||
skb->protocol = eth_type_trans(skb, priv->netdev);
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
|
|
@ -2960,6 +2960,15 @@ enum rt2800_eeprom_word {
|
|||
*/
|
||||
#define BCN_TBTT_OFFSET 64
|
||||
|
||||
/*
|
||||
* Hardware has 255 WCID table entries. First 32 entries are reserved for
|
||||
* shared keys. Since parts of the pairwise key table might be shared with
|
||||
* the beacon frame buffers 6 & 7 we could only use the first 222 entries.
|
||||
*/
|
||||
#define WCID_START 33
|
||||
#define WCID_END 222
|
||||
#define STA_IDS_SIZE (WCID_END - WCID_START + 2)
|
||||
|
||||
/*
|
||||
* RT2800 driver data structure
|
||||
*/
|
||||
|
@ -2971,6 +2980,7 @@ struct rt2800_drv_data {
|
|||
u8 txmixer_gain_24g;
|
||||
u8 txmixer_gain_5g;
|
||||
unsigned int tbtt_tick;
|
||||
DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
|
||||
};
|
||||
|
||||
#endif /* RT2800_H */
|
||||
|
|
|
@ -1381,38 +1381,6 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
|
||||
|
||||
static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct mac_wcid_entry wcid_entry;
|
||||
int idx;
|
||||
u32 offset;
|
||||
|
||||
/*
|
||||
* Search for the first free WCID entry and return the corresponding
|
||||
* index.
|
||||
*
|
||||
* Make sure the WCID starts _after_ the last possible shared key
|
||||
* entry (>32).
|
||||
*
|
||||
* Since parts of the pairwise key table might be shared with
|
||||
* the beacon frame buffers 6 & 7 we should only write into the
|
||||
* first 222 entries.
|
||||
*/
|
||||
for (idx = 33; idx <= 222; idx++) {
|
||||
offset = MAC_WCID_ENTRY(idx);
|
||||
rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
|
||||
sizeof(wcid_entry));
|
||||
if (is_broadcast_ether_addr(wcid_entry.mac))
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use -1 to indicate that we don't have any more space in the WCID
|
||||
* table.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
struct rt2x00lib_crypto *crypto,
|
||||
struct ieee80211_key_conf *key)
|
||||
|
@ -1425,7 +1393,7 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
|||
* Allow key configuration only for STAs that are
|
||||
* known by the hw.
|
||||
*/
|
||||
if (crypto->wcid < 0)
|
||||
if (crypto->wcid > WCID_END)
|
||||
return -ENOSPC;
|
||||
key->hw_key_idx = crypto->wcid;
|
||||
|
||||
|
@ -1455,11 +1423,13 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
|
|||
{
|
||||
int wcid;
|
||||
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
|
||||
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
|
||||
|
||||
/*
|
||||
* Find next free WCID.
|
||||
* Search for the first free WCID entry and return the corresponding
|
||||
* index.
|
||||
*/
|
||||
wcid = rt2800_find_wcid(rt2x00dev);
|
||||
wcid = find_first_zero_bit(drv_data->sta_ids, STA_IDS_SIZE) + WCID_START;
|
||||
|
||||
/*
|
||||
* Store selected wcid even if it is invalid so that we can
|
||||
|
@ -1471,9 +1441,11 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
|
|||
* No space left in the device, however, we can still communicate
|
||||
* with the STA -> No error.
|
||||
*/
|
||||
if (wcid < 0)
|
||||
if (wcid > WCID_END)
|
||||
return 0;
|
||||
|
||||
__set_bit(wcid - WCID_START, drv_data->sta_ids);
|
||||
|
||||
/*
|
||||
* Clean up WCID attributes and write STA address to the device.
|
||||
*/
|
||||
|
@ -1487,11 +1459,16 @@ EXPORT_SYMBOL_GPL(rt2800_sta_add);
|
|||
|
||||
int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
|
||||
{
|
||||
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
|
||||
|
||||
if (wcid > WCID_END)
|
||||
return 0;
|
||||
/*
|
||||
* Remove WCID entry, no need to clean the attributes as they will
|
||||
* get renewed when the WCID is reused.
|
||||
*/
|
||||
rt2800_config_wcid(rt2x00dev, NULL, wcid);
|
||||
__clear_bit(wcid - WCID_START, drv_data->sta_ids);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7968,11 +7945,11 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
/*
|
||||
* Don't allow aggregation for stations the hardware isn't aware
|
||||
* of because tx status reports for frames to an unknown station
|
||||
* always contain wcid=255 and thus we can't distinguish between
|
||||
* multiple stations which leads to unwanted situations when the
|
||||
* hw reorders frames due to aggregation.
|
||||
* always contain wcid=WCID_END+1 and thus we can't distinguish
|
||||
* between multiple stations which leads to unwanted situations
|
||||
* when the hw reorders frames due to aggregation.
|
||||
*/
|
||||
if (sta_priv->wcid < 0)
|
||||
if (sta_priv->wcid > WCID_END)
|
||||
return 1;
|
||||
|
||||
switch (action) {
|
||||
|
|
|
@ -535,16 +535,8 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
|
||||
|
||||
/*
|
||||
* If there's no space left in the device table store
|
||||
* -1 as wcid but tell mac80211 everything went ok.
|
||||
*/
|
||||
if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
|
||||
sta_priv->wcid = -1;
|
||||
|
||||
return 0;
|
||||
return rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
|
||||
|
||||
|
@ -554,12 +546,6 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
|
||||
|
||||
/*
|
||||
* If we never sent the STA to the device no need to clean it up.
|
||||
*/
|
||||
if (sta_priv->wcid < 0)
|
||||
return 0;
|
||||
|
||||
return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
|
||||
|
|
|
@ -1123,23 +1123,22 @@ static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw)
|
|||
void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
static u8 tm_trigger;
|
||||
|
||||
if (!rtlpriv->dm.txpower_tracking)
|
||||
return;
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16),
|
||||
0x03);
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Trigger 88E Thermal Meter!!\n");
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
return;
|
||||
} else {
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Schedule TxPowerTracking !!\n");
|
||||
dm_txpower_track_cb_therm(hw);
|
||||
tm_trigger = 0;
|
||||
rtlpriv->dm.tm_trigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1169,23 +1169,22 @@ static void rtl92c_dm_check_txpower_tracking_thermal_meter(
|
|||
struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
static u8 tm_trigger;
|
||||
|
||||
if (!rtlpriv->dm.txpower_tracking)
|
||||
return;
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
|
||||
0x60);
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Trigger 92S Thermal Meter!!\n");
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
return;
|
||||
} else {
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Schedule TxPowerTracking direct call!!\n");
|
||||
rtl92c_dm_txpower_tracking_directcall(hw);
|
||||
tm_trigger = 0;
|
||||
rtlpriv->dm.tm_trigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -233,13 +233,14 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
|
|||
pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
|
||||
pfwdata = (u8 *)rtlhal->pfirmware;
|
||||
fwsize = rtlhal->fwsize;
|
||||
|
||||
if (IS_FW_HEADER_EXIST(pfwheader)) {
|
||||
RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
|
||||
"Firmware Version(%d), Signature(%#x),Size(%d)\n",
|
||||
pfwheader->version, pfwheader->signature,
|
||||
(int)sizeof(struct rtl92c_firmware_header));
|
||||
|
||||
rtlhal->fw_version = pfwheader->version;
|
||||
rtlhal->fw_subversion = pfwheader->subversion;
|
||||
pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
|
||||
fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
|
||||
}
|
||||
|
|
|
@ -840,6 +840,26 @@ static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw)
|
|||
rtl92c_set_data_filter(hw, value16);
|
||||
}
|
||||
|
||||
static void _rtl92cu_init_beacon_parameters(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
|
||||
rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010);
|
||||
|
||||
/* TODO: Remove these magic number */
|
||||
rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);
|
||||
rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
|
||||
rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
|
||||
/* Change beacon AIFS to the largest number
|
||||
* beacause test chip does not contension before sending beacon.
|
||||
*/
|
||||
if (IS_NORMAL_CHIP(rtlhal->version))
|
||||
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
|
||||
else
|
||||
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
|
||||
}
|
||||
|
||||
static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
@ -887,7 +907,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
|
|||
_rtl92cu_init_usb_aggregation(hw);
|
||||
rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20);
|
||||
rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version));
|
||||
rtl92c_init_beacon_parameters(hw, rtlhal->version);
|
||||
_rtl92cu_init_beacon_parameters(hw);
|
||||
rtl92c_init_ampdu_aggregation(hw);
|
||||
rtl92c_init_beacon_max_error(hw);
|
||||
return err;
|
||||
|
@ -987,7 +1007,6 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
|
|||
struct rtl_phy *rtlphy = &(rtlpriv->phy);
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
int err = 0;
|
||||
static bool iqk_initialized;
|
||||
unsigned long flags;
|
||||
|
||||
/* As this function can take a very long time (up to 350 ms)
|
||||
|
@ -1038,11 +1057,11 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
|
|||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
|
||||
if (ppsc->rfpwr_state == ERFON) {
|
||||
rtl92c_phy_set_rfpath_switch(hw, 1);
|
||||
if (iqk_initialized) {
|
||||
if (rtlphy->iqk_initialized) {
|
||||
rtl92c_phy_iq_calibrate(hw, true);
|
||||
} else {
|
||||
rtl92c_phy_iq_calibrate(hw, false);
|
||||
iqk_initialized = true;
|
||||
rtlphy->iqk_initialized = true;
|
||||
}
|
||||
rtl92c_dm_check_txpower_tracking(hw);
|
||||
rtl92c_phy_lc_calibrate(hw);
|
||||
|
@ -1391,6 +1410,9 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
|
|||
_CardDisableHWSM(hw);
|
||||
else
|
||||
_CardDisableWithoutHWSM(hw);
|
||||
|
||||
/* after power off we should do iqk again */
|
||||
rtlpriv->phy.iqk_initialized = false;
|
||||
}
|
||||
|
||||
void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
|
||||
|
@ -1451,25 +1473,6 @@ int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void _InitBeaconParameters(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
|
||||
rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010);
|
||||
|
||||
/* TODO: Remove these magic number */
|
||||
rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);
|
||||
rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
|
||||
rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
|
||||
/* Change beacon AIFS to the largest number
|
||||
* beacause test chip does not contension before sending beacon. */
|
||||
if (IS_NORMAL_CHIP(rtlhal->version))
|
||||
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
|
||||
else
|
||||
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
|
||||
}
|
||||
|
||||
static void _beacon_function_enable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
@ -1490,7 +1493,7 @@ void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw)
|
|||
atim_window = 2; /*FIX MERGE */
|
||||
rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
|
||||
rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
|
||||
_InitBeaconParameters(hw);
|
||||
_rtl92cu_init_beacon_parameters(hw);
|
||||
rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
|
||||
/*
|
||||
* Force beacon frame transmission even after receiving beacon frame
|
||||
|
|
|
@ -641,21 +641,6 @@ void rtl92c_init_retry_function(struct ieee80211_hw *hw)
|
|||
rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
|
||||
}
|
||||
|
||||
void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
|
||||
enum version_8192c version)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
|
||||
rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
|
||||
rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
|
||||
rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
|
||||
if (IS_NORMAL_CHIP(rtlhal->version))
|
||||
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
|
||||
else
|
||||
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
|
||||
}
|
||||
|
||||
void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
|
|
@ -70,9 +70,6 @@ void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw);
|
|||
void rtl92c_init_rdg_setting(struct ieee80211_hw *hw);
|
||||
void rtl92c_init_retry_function(struct ieee80211_hw *hw);
|
||||
|
||||
void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
|
||||
enum version_8192c version);
|
||||
|
||||
void rtl92c_disable_fast_edca(struct ieee80211_hw *hw);
|
||||
void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T);
|
||||
|
||||
|
|
|
@ -108,13 +108,8 @@ void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|||
bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
|
||||
{
|
||||
bool rtstatus;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
bool is92c = IS_92C_SERIAL(rtlhal->version);
|
||||
|
||||
rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
|
||||
if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal))
|
||||
rtl_write_byte(rtlpriv, 0x14, 0x71);
|
||||
return rtstatus;
|
||||
}
|
||||
|
||||
|
@ -122,7 +117,6 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
|
|||
{
|
||||
bool rtstatus = true;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
u16 regval;
|
||||
u32 regval32;
|
||||
u8 b_reg_hwparafile = 1;
|
||||
|
@ -134,17 +128,11 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
|
|||
rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
|
||||
rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
|
||||
rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
|
||||
if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
|
||||
FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB);
|
||||
} else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
|
||||
FEN_BB_GLB_RSTn | FEN_BBRSTB);
|
||||
}
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
|
||||
FEN_BB_GLB_RSTn | FEN_BBRSTB);
|
||||
regval32 = rtl_read_dword(rtlpriv, 0x87c);
|
||||
rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31)));
|
||||
if (IS_HARDWARE_TYPE_8192CU(rtlhal))
|
||||
rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
|
||||
rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
|
||||
rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
|
||||
if (b_reg_hwparafile == 1)
|
||||
rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
|
||||
|
@ -162,7 +150,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
|
|||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
|
||||
arraylength = rtlphy->hwparam_tables[MAC_REG].length ;
|
||||
ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n");
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n");
|
||||
for (i = 0; i < arraylength; i = i + 2)
|
||||
rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
|
||||
return true;
|
||||
|
@ -259,18 +247,18 @@ bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
|
|||
radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
|
||||
radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Radio_A:RTL8192CERADIOA_2TARRAY\n");
|
||||
"Radio_A:RTL8192CURADIOA_2TARRAY\n");
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Radio_B:RTL8192CE_RADIOB_2TARRAY\n");
|
||||
"Radio_B:RTL8192CU_RADIOB_2TARRAY\n");
|
||||
} else {
|
||||
radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
|
||||
radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
|
||||
radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
|
||||
radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Radio_A:RTL8192CE_RADIOA_1TARRAY\n");
|
||||
"Radio_A:RTL8192CU_RADIOA_1TARRAY\n");
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Radio_B:RTL8192CE_RADIOB_1TARRAY\n");
|
||||
"Radio_B:RTL8192CU_RADIOB_1TARRAY\n");
|
||||
}
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath);
|
||||
switch (rfpath) {
|
||||
|
|
|
@ -66,7 +66,6 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_phy *rtlphy = &(rtlpriv->phy);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
|
||||
u32 tx_agc[2] = { 0, 0 }, tmpval = 0;
|
||||
|
@ -74,14 +73,8 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
|
|||
u8 idx1, idx2;
|
||||
u8 *ptr;
|
||||
|
||||
if (rtlhal->interface == INTF_PCI) {
|
||||
if (rtlefuse->eeprom_regulatory != 0)
|
||||
turbo_scanoff = true;
|
||||
} else {
|
||||
if ((rtlefuse->eeprom_regulatory != 0) ||
|
||||
(rtlefuse->external_pa))
|
||||
turbo_scanoff = true;
|
||||
}
|
||||
if ((rtlefuse->eeprom_regulatory != 0) || (rtlefuse->external_pa))
|
||||
turbo_scanoff = true;
|
||||
if (mac->act_scanning) {
|
||||
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
|
||||
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
|
||||
|
@ -90,11 +83,8 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
|
|||
(ppowerlevel[idx1] << 8) |
|
||||
(ppowerlevel[idx1] << 16) |
|
||||
(ppowerlevel[idx1] << 24);
|
||||
if (rtlhal->interface == INTF_USB) {
|
||||
if (tx_agc[idx1] > 0x20 &&
|
||||
rtlefuse->external_pa)
|
||||
tx_agc[idx1] = 0x20;
|
||||
}
|
||||
if (tx_agc[idx1] > 0x20 && rtlefuse->external_pa)
|
||||
tx_agc[idx1] = 0x20;
|
||||
}
|
||||
} else {
|
||||
if (rtlpriv->dm.dynamic_txhighpower_lvl ==
|
||||
|
@ -452,9 +442,6 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
|
|||
udelay(1);
|
||||
switch (rfpath) {
|
||||
case RF90_PATH_A:
|
||||
rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
|
||||
(enum radio_path) rfpath);
|
||||
break;
|
||||
case RF90_PATH_B:
|
||||
rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
|
||||
(enum radio_path) rfpath);
|
||||
|
@ -483,7 +470,6 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
|
|||
}
|
||||
}
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
|
||||
return rtstatus;
|
||||
phy_rf_cfg_fail:
|
||||
return rtstatus;
|
||||
}
|
||||
|
|
|
@ -321,7 +321,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
|
|||
stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc);
|
||||
stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
|
||||
stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
|
||||
stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
|
||||
stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1)
|
||||
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
|
||||
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
|
||||
stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
|
||||
|
|
|
@ -1240,23 +1240,22 @@ static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
|
|||
void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
static u8 tm_trigger;
|
||||
|
||||
if (!rtlpriv->dm.txpower_tracking)
|
||||
return;
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) |
|
||||
BIT(16), 0x03);
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Trigger 92S Thermal Meter!!\n");
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
return;
|
||||
} else {
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Schedule TxPowerTracking direct call!!\n");
|
||||
rtl92d_dm_txpower_tracking_callback_thermalmeter(hw);
|
||||
tm_trigger = 0;
|
||||
rtlpriv->dm.tm_trigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -200,7 +200,6 @@ static void _rtl92s_dm_check_txpowertracking_thermalmeter(
|
|||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_phy *rtlphy = &(rtlpriv->phy);
|
||||
static u8 tm_trigger;
|
||||
u8 tx_power_checkcnt = 5;
|
||||
|
||||
/* 2T2R TP issue */
|
||||
|
@ -215,13 +214,13 @@ static void _rtl92s_dm_check_txpowertracking_thermalmeter(
|
|||
return;
|
||||
}
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER,
|
||||
RFREG_OFFSET_MASK, 0x60);
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
} else {
|
||||
_rtl92s_dm_txpowertracking_callback_thermalmeter(hw);
|
||||
tm_trigger = 0;
|
||||
rtlpriv->dm.tm_trigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -909,23 +909,22 @@ static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
|
|||
void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
static u8 tm_trigger;
|
||||
|
||||
if (!rtlpriv->dm.txpower_tracking)
|
||||
return;
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
|
||||
0x03);
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Trigger 8723be Thermal Meter!!\n");
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
return;
|
||||
} else {
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Schedule TxPowerTracking !!\n");
|
||||
rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
|
||||
tm_trigger = 0;
|
||||
rtlpriv->dm.tm_trigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1068,20 +1068,18 @@ static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
|
|||
struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
static u8 tm_trigger;
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
|
||||
BIT(17) | BIT(16), 0x03);
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Trigger 8812 Thermal Meter!!\n");
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
return;
|
||||
}
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Schedule TxPowerTracking direct call!!\n");
|
||||
rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
|
||||
tm_trigger = 0;
|
||||
}
|
||||
|
||||
static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
|
||||
|
@ -2519,21 +2517,19 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
|
|||
void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
static u8 tm_trigger;
|
||||
|
||||
if (!tm_trigger) {
|
||||
if (!rtlpriv->dm.tm_trigger) {
|
||||
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
|
||||
0x03);
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Trigger 8821ae Thermal Meter!!\n");
|
||||
tm_trigger = 1;
|
||||
rtlpriv->dm.tm_trigger = 1;
|
||||
return;
|
||||
} else {
|
||||
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
|
||||
"Schedule TxPowerTracking !!\n");
|
||||
|
||||
rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
|
||||
tm_trigger = 0;
|
||||
rtlpriv->dm.tm_trigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1665,6 +1665,7 @@ struct rtl_dm {
|
|||
u8 last_dtp_lvl;
|
||||
u8 thermalvalue_avg[AVG_THERMAL_NUM];
|
||||
u8 thermalvalue_avg_index;
|
||||
u8 tm_trigger;
|
||||
bool done_txpower;
|
||||
u8 dynamic_txhighpower_lvl; /*Tx high power level */
|
||||
u8 dm_flag; /*Indicate each dynamic mechanism's status. */
|
||||
|
|
|
@ -53,10 +53,7 @@ int wl1251_acx_station_id(struct wl1251 *wl)
|
|||
mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
|
||||
|
||||
ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
kfree(mac);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -246,7 +246,18 @@ static inline void bcma_core_pci_power_save(struct bcma_bus *bus, bool up)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
|
||||
extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
|
||||
#else
|
||||
static inline int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
static inline int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
|
||||
|
|
Loading…
Reference in a new issue