diff options
Diffstat (limited to 'drivers/net/wireless')
83 files changed, 1723 insertions, 894 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index bcccae19325d..59496a90ad5e 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -48,6 +48,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
48 | .name = "qca988x hw2.0", | 48 | .name = "qca988x hw2.0", |
49 | .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, | 49 | .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, |
50 | .uart_pin = 7, | 50 | .uart_pin = 7, |
51 | .has_shifted_cc_wraparound = true, | ||
51 | .fw = { | 52 | .fw = { |
52 | .dir = QCA988X_HW_2_0_FW_DIR, | 53 | .dir = QCA988X_HW_2_0_FW_DIR, |
53 | .fw = QCA988X_HW_2_0_FW_FILE, | 54 | .fw = QCA988X_HW_2_0_FW_FILE, |
@@ -1084,6 +1085,22 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
1084 | if (status) | 1085 | if (status) |
1085 | goto err; | 1086 | goto err; |
1086 | 1087 | ||
1088 | /* Some of of qca988x solutions are having global reset issue | ||
1089 | * during target initialization. Bypassing PLL setting before | ||
1090 | * downloading firmware and letting the SoC run on REF_CLK is | ||
1091 | * fixing the problem. Corresponding firmware change is also needed | ||
1092 | * to set the clock source once the target is initialized. | ||
1093 | */ | ||
1094 | if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT, | ||
1095 | ar->fw_features)) { | ||
1096 | status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1); | ||
1097 | if (status) { | ||
1098 | ath10k_err(ar, "could not write to skip_clock_init: %d\n", | ||
1099 | status); | ||
1100 | goto err; | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1087 | status = ath10k_download_fw(ar, mode); | 1104 | status = ath10k_download_fw(ar, mode); |
1088 | if (status) | 1105 | if (status) |
1089 | goto err; | 1106 | goto err; |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 70fcdc9c2758..78094f23c9dd 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -284,15 +284,6 @@ struct ath10k_sta { | |||
284 | #endif | 284 | #endif |
285 | }; | 285 | }; |
286 | 286 | ||
287 | struct ath10k_chanctx { | ||
288 | /* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally | ||
289 | * mac80211 should allow some sort of explicit locking to guarantee | ||
290 | * that the publicly available chanctx_conf can be accessed safely at | ||
291 | * all times. | ||
292 | */ | ||
293 | struct ieee80211_chanctx_conf conf; | ||
294 | }; | ||
295 | |||
296 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) | 287 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) |
297 | 288 | ||
298 | enum ath10k_beacon_state { | 289 | enum ath10k_beacon_state { |
@@ -468,6 +459,9 @@ enum ath10k_fw_features { | |||
468 | */ | 459 | */ |
469 | ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING, | 460 | ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING, |
470 | 461 | ||
462 | /* Firmware supports bypassing PLL setting on init. */ | ||
463 | ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9, | ||
464 | |||
471 | /* keep last */ | 465 | /* keep last */ |
472 | ATH10K_FW_FEATURE_COUNT, | 466 | ATH10K_FW_FEATURE_COUNT, |
473 | }; | 467 | }; |
@@ -577,6 +571,13 @@ struct ath10k { | |||
577 | u32 patch_load_addr; | 571 | u32 patch_load_addr; |
578 | int uart_pin; | 572 | int uart_pin; |
579 | 573 | ||
574 | /* This is true if given HW chip has a quirky Cycle Counter | ||
575 | * wraparound which resets to 0x7fffffff instead of 0. All | ||
576 | * other CC related counters (e.g. Rx Clear Count) are divided | ||
577 | * by 2 so they never wraparound themselves. | ||
578 | */ | ||
579 | bool has_shifted_cc_wraparound; | ||
580 | |||
580 | struct ath10k_hw_params_fw { | 581 | struct ath10k_hw_params_fw { |
581 | const char *dir; | 582 | const char *dir; |
582 | const char *fw; | 583 | const char *fw; |
@@ -694,6 +695,14 @@ struct ath10k { | |||
694 | u32 survey_last_cycle_count; | 695 | u32 survey_last_cycle_count; |
695 | struct survey_info survey[ATH10K_NUM_CHANS]; | 696 | struct survey_info survey[ATH10K_NUM_CHANS]; |
696 | 697 | ||
698 | /* Channel info events are expected to come in pairs without and with | ||
699 | * COMPLETE flag set respectively for each channel visit during scan. | ||
700 | * | ||
701 | * However there are deviations from this rule. This flag is used to | ||
702 | * avoid reporting garbage data. | ||
703 | */ | ||
704 | bool ch_info_can_report_survey; | ||
705 | |||
697 | struct dfs_pattern_detector *dfs_detector; | 706 | struct dfs_pattern_detector *dfs_detector; |
698 | 707 | ||
699 | unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */ | 708 | unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */ |
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 839a8791fb9e..5997f00afe3b 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include "core.h" | ||
18 | #include "hw.h" | 19 | #include "hw.h" |
19 | 20 | ||
20 | const struct ath10k_hw_regs qca988x_regs = { | 21 | const struct ath10k_hw_regs qca988x_regs = { |
@@ -56,3 +57,23 @@ const struct ath10k_hw_regs qca6174_regs = { | |||
56 | .soc_chip_id_address = 0x000f0, | 57 | .soc_chip_id_address = 0x000f0, |
57 | .scratch_3_address = 0x0028, | 58 | .scratch_3_address = 0x0028, |
58 | }; | 59 | }; |
60 | |||
61 | void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, | ||
62 | u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) | ||
63 | { | ||
64 | u32 cc_fix = 0; | ||
65 | |||
66 | survey->filled |= SURVEY_INFO_TIME | | ||
67 | SURVEY_INFO_TIME_BUSY; | ||
68 | |||
69 | if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) { | ||
70 | cc_fix = 0x7fffffff; | ||
71 | survey->filled &= ~SURVEY_INFO_TIME_BUSY; | ||
72 | } | ||
73 | |||
74 | cc -= cc_prev - cc_fix; | ||
75 | rcc -= rcc_prev; | ||
76 | |||
77 | survey->time = CCNT_TO_MSEC(cc); | ||
78 | survey->time_busy = CCNT_TO_MSEC(rcc); | ||
79 | } | ||
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 89e09cbeac19..85cca29375fe 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
@@ -169,6 +169,9 @@ struct ath10k_hw_regs { | |||
169 | extern const struct ath10k_hw_regs qca988x_regs; | 169 | extern const struct ath10k_hw_regs qca988x_regs; |
170 | extern const struct ath10k_hw_regs qca6174_regs; | 170 | extern const struct ath10k_hw_regs qca6174_regs; |
171 | 171 | ||
172 | void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, | ||
173 | u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); | ||
174 | |||
172 | #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) | 175 | #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) |
173 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) | 176 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) |
174 | 177 | ||
@@ -449,6 +452,9 @@ enum ath10k_hw_rate_cck { | |||
449 | #define SCRATCH_3_ADDRESS ar->regs->scratch_3_address | 452 | #define SCRATCH_3_ADDRESS ar->regs->scratch_3_address |
450 | #define CPU_INTR_ADDRESS 0x0010 | 453 | #define CPU_INTR_ADDRESS 0x0010 |
451 | 454 | ||
455 | /* Cycle counters are running at 88MHz */ | ||
456 | #define CCNT_TO_MSEC(x) ((x) / 88000) | ||
457 | |||
452 | /* Firmware indications to the Host via SCRATCH_3 register. */ | 458 | /* Firmware indications to the Host via SCRATCH_3 register. */ |
453 | #define FW_INDICATOR_ADDRESS (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS) | 459 | #define FW_INDICATOR_ADDRESS (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS) |
454 | #define FW_IND_EVENT_PENDING 1 | 460 | #define FW_IND_EVENT_PENDING 1 |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 609ca8619ebd..218b6af63447 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar) | |||
3949 | return ret; | 3949 | return ret; |
3950 | } | 3950 | } |
3951 | 3951 | ||
3952 | static void ath10k_mac_chan_reconfigure(struct ath10k *ar) | ||
3953 | { | ||
3954 | struct ath10k_vif *arvif; | ||
3955 | struct cfg80211_chan_def def; | ||
3956 | int ret; | ||
3957 | |||
3958 | lockdep_assert_held(&ar->conf_mutex); | ||
3959 | |||
3960 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n"); | ||
3961 | |||
3962 | /* First stop monitor interface. Some FW versions crash if there's a | ||
3963 | * lone monitor interface. */ | ||
3964 | if (ar->monitor_started) | ||
3965 | ath10k_monitor_stop(ar); | ||
3966 | |||
3967 | list_for_each_entry(arvif, &ar->arvifs, list) { | ||
3968 | if (!arvif->is_started) | ||
3969 | continue; | ||
3970 | |||
3971 | if (!arvif->is_up) | ||
3972 | continue; | ||
3973 | |||
3974 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) | ||
3975 | continue; | ||
3976 | |||
3977 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); | ||
3978 | if (ret) { | ||
3979 | ath10k_warn(ar, "failed to down vdev %d: %d\n", | ||
3980 | arvif->vdev_id, ret); | ||
3981 | continue; | ||
3982 | } | ||
3983 | } | ||
3984 | |||
3985 | /* all vdevs are downed now - attempt to restart and re-up them */ | ||
3986 | |||
3987 | list_for_each_entry(arvif, &ar->arvifs, list) { | ||
3988 | if (!arvif->is_started) | ||
3989 | continue; | ||
3990 | |||
3991 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) | ||
3992 | continue; | ||
3993 | |||
3994 | ret = ath10k_mac_setup_bcn_tmpl(arvif); | ||
3995 | if (ret) | ||
3996 | ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", | ||
3997 | ret); | ||
3998 | |||
3999 | ret = ath10k_mac_setup_prb_tmpl(arvif); | ||
4000 | if (ret) | ||
4001 | ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", | ||
4002 | ret); | ||
4003 | |||
4004 | if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) | ||
4005 | continue; | ||
4006 | |||
4007 | ret = ath10k_vdev_restart(arvif, &def); | ||
4008 | if (ret) { | ||
4009 | ath10k_warn(ar, "failed to restart vdev %d: %d\n", | ||
4010 | arvif->vdev_id, ret); | ||
4011 | continue; | ||
4012 | } | ||
4013 | |||
4014 | if (!arvif->is_up) | ||
4015 | continue; | ||
4016 | |||
4017 | ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, | ||
4018 | arvif->bssid); | ||
4019 | if (ret) { | ||
4020 | ath10k_warn(ar, "failed to bring vdev up %d: %d\n", | ||
4021 | arvif->vdev_id, ret); | ||
4022 | continue; | ||
4023 | } | ||
4024 | } | ||
4025 | |||
4026 | ath10k_monitor_recalc(ar); | ||
4027 | } | ||
4028 | |||
4029 | static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) | 3952 | static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) |
4030 | { | 3953 | { |
4031 | int ret; | 3954 | int ret; |
@@ -6144,7 +6067,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, | |||
6144 | } | 6067 | } |
6145 | 6068 | ||
6146 | static void | 6069 | static void |
6147 | ath10k_mac_update_rx_channel(struct ath10k *ar) | 6070 | ath10k_mac_update_rx_channel(struct ath10k *ar, |
6071 | struct ieee80211_chanctx_conf *ctx, | ||
6072 | struct ieee80211_vif_chanctx_switch *vifs, | ||
6073 | int n_vifs) | ||
6148 | { | 6074 | { |
6149 | struct cfg80211_chan_def *def = NULL; | 6075 | struct cfg80211_chan_def *def = NULL; |
6150 | 6076 | ||
@@ -6154,6 +6080,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar) | |||
6154 | lockdep_assert_held(&ar->conf_mutex); | 6080 | lockdep_assert_held(&ar->conf_mutex); |
6155 | lockdep_assert_held(&ar->data_lock); | 6081 | lockdep_assert_held(&ar->data_lock); |
6156 | 6082 | ||
6083 | WARN_ON(ctx && vifs); | ||
6084 | WARN_ON(vifs && n_vifs != 1); | ||
6085 | |||
6157 | /* FIXME: Sort of an optimization and a workaround. Peers and vifs are | 6086 | /* FIXME: Sort of an optimization and a workaround. Peers and vifs are |
6158 | * on a linked list now. Doing a lookup peer -> vif -> chanctx for each | 6087 | * on a linked list now. Doing a lookup peer -> vif -> chanctx for each |
6159 | * ppdu on Rx may reduce performance on low-end systems. It should be | 6088 | * 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) | |||
6165 | * affected much. | 6094 | * affected much. |
6166 | */ | 6095 | */ |
6167 | rcu_read_lock(); | 6096 | rcu_read_lock(); |
6168 | if (ath10k_mac_num_chanctxs(ar) == 1) { | 6097 | if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) { |
6169 | ieee80211_iter_chan_contexts_atomic(ar->hw, | 6098 | ieee80211_iter_chan_contexts_atomic(ar->hw, |
6170 | ath10k_mac_get_any_chandef_iter, | 6099 | ath10k_mac_get_any_chandef_iter, |
6171 | &def); | 6100 | &def); |
6101 | |||
6102 | if (vifs) | ||
6103 | def = &vifs[0].new_ctx->def; | ||
6104 | |||
6172 | ar->rx_channel = def->chan; | 6105 | ar->rx_channel = def->chan; |
6106 | } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) { | ||
6107 | ar->rx_channel = ctx->def.chan; | ||
6173 | } else { | 6108 | } else { |
6174 | ar->rx_channel = NULL; | 6109 | ar->rx_channel = NULL; |
6175 | } | 6110 | } |
6176 | rcu_read_unlock(); | 6111 | rcu_read_unlock(); |
6177 | } | 6112 | } |
6178 | 6113 | ||
6179 | static void | ||
6180 | ath10k_mac_chan_ctx_init(struct ath10k *ar, | ||
6181 | struct ath10k_chanctx *arctx, | ||
6182 | struct ieee80211_chanctx_conf *conf) | ||
6183 | { | ||
6184 | lockdep_assert_held(&ar->conf_mutex); | ||
6185 | lockdep_assert_held(&ar->data_lock); | ||
6186 | |||
6187 | memset(arctx, 0, sizeof(*arctx)); | ||
6188 | |||
6189 | arctx->conf = *conf; | ||
6190 | } | ||
6191 | |||
6192 | static int | 6114 | static int |
6193 | ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, | 6115 | ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, |
6194 | struct ieee80211_chanctx_conf *ctx) | 6116 | struct ieee80211_chanctx_conf *ctx) |
6195 | { | 6117 | { |
6196 | struct ath10k *ar = hw->priv; | 6118 | struct ath10k *ar = hw->priv; |
6197 | struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; | ||
6198 | 6119 | ||
6199 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 6120 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
6200 | "mac chanctx add freq %hu width %d ptr %p\n", | 6121 | "mac chanctx add freq %hu width %d ptr %p\n", |
@@ -6203,8 +6124,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, | |||
6203 | mutex_lock(&ar->conf_mutex); | 6124 | mutex_lock(&ar->conf_mutex); |
6204 | 6125 | ||
6205 | spin_lock_bh(&ar->data_lock); | 6126 | spin_lock_bh(&ar->data_lock); |
6206 | ath10k_mac_chan_ctx_init(ar, arctx, ctx); | 6127 | ath10k_mac_update_rx_channel(ar, ctx, NULL, 0); |
6207 | ath10k_mac_update_rx_channel(ar); | ||
6208 | spin_unlock_bh(&ar->data_lock); | 6128 | spin_unlock_bh(&ar->data_lock); |
6209 | 6129 | ||
6210 | ath10k_recalc_radar_detection(ar); | 6130 | ath10k_recalc_radar_detection(ar); |
@@ -6228,7 +6148,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw, | |||
6228 | mutex_lock(&ar->conf_mutex); | 6148 | mutex_lock(&ar->conf_mutex); |
6229 | 6149 | ||
6230 | spin_lock_bh(&ar->data_lock); | 6150 | spin_lock_bh(&ar->data_lock); |
6231 | ath10k_mac_update_rx_channel(ar); | 6151 | ath10k_mac_update_rx_channel(ar, NULL, NULL, 0); |
6232 | spin_unlock_bh(&ar->data_lock); | 6152 | spin_unlock_bh(&ar->data_lock); |
6233 | 6153 | ||
6234 | ath10k_recalc_radar_detection(ar); | 6154 | ath10k_recalc_radar_detection(ar); |
@@ -6243,16 +6163,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, | |||
6243 | u32 changed) | 6163 | u32 changed) |
6244 | { | 6164 | { |
6245 | struct ath10k *ar = hw->priv; | 6165 | struct ath10k *ar = hw->priv; |
6246 | struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; | ||
6247 | 6166 | ||
6248 | mutex_lock(&ar->conf_mutex); | 6167 | mutex_lock(&ar->conf_mutex); |
6249 | 6168 | ||
6250 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 6169 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
6251 | "mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n", | 6170 | "mac chanctx change freq %hu width %d ptr %p changed %x\n", |
6252 | arctx->conf.def.chan->center_freq, | 6171 | ctx->def.chan->center_freq, ctx->def.width, ctx, changed); |
6253 | ctx->def.chan->center_freq, | ||
6254 | arctx->conf.def.width, ctx->def.width, | ||
6255 | ctx, changed); | ||
6256 | 6172 | ||
6257 | /* This shouldn't really happen because channel switching should use | 6173 | /* This shouldn't really happen because channel switching should use |
6258 | * switch_vif_chanctx(). | 6174 | * switch_vif_chanctx(). |
@@ -6260,10 +6176,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, | |||
6260 | if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) | 6176 | if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) |
6261 | goto unlock; | 6177 | goto unlock; |
6262 | 6178 | ||
6263 | spin_lock_bh(&ar->data_lock); | ||
6264 | arctx->conf = *ctx; | ||
6265 | spin_unlock_bh(&ar->data_lock); | ||
6266 | |||
6267 | ath10k_recalc_radar_detection(ar); | 6179 | ath10k_recalc_radar_detection(ar); |
6268 | 6180 | ||
6269 | /* FIXME: How to configure Rx chains properly? */ | 6181 | /* FIXME: How to configure Rx chains properly? */ |
@@ -6283,7 +6195,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
6283 | struct ieee80211_chanctx_conf *ctx) | 6195 | struct ieee80211_chanctx_conf *ctx) |
6284 | { | 6196 | { |
6285 | struct ath10k *ar = hw->priv; | 6197 | struct ath10k *ar = hw->priv; |
6286 | struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; | ||
6287 | struct ath10k_vif *arvif = (void *)vif->drv_priv; | 6198 | struct ath10k_vif *arvif = (void *)vif->drv_priv; |
6288 | int ret; | 6199 | int ret; |
6289 | 6200 | ||
@@ -6298,11 +6209,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
6298 | return -EBUSY; | 6209 | return -EBUSY; |
6299 | } | 6210 | } |
6300 | 6211 | ||
6301 | ret = ath10k_vdev_start(arvif, &arctx->conf.def); | 6212 | ret = ath10k_vdev_start(arvif, &ctx->def); |
6302 | if (ret) { | 6213 | if (ret) { |
6303 | ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n", | 6214 | ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n", |
6304 | arvif->vdev_id, vif->addr, | 6215 | arvif->vdev_id, vif->addr, |
6305 | arctx->conf.def.chan->center_freq, ret); | 6216 | ctx->def.chan->center_freq, ret); |
6306 | goto err; | 6217 | goto err; |
6307 | } | 6218 | } |
6308 | 6219 | ||
@@ -6377,7 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, | |||
6377 | { | 6288 | { |
6378 | struct ath10k *ar = hw->priv; | 6289 | struct ath10k *ar = hw->priv; |
6379 | struct ath10k_vif *arvif; | 6290 | struct ath10k_vif *arvif; |
6380 | struct ath10k_chanctx *arctx_new, *arctx_old; | 6291 | int ret; |
6381 | int i; | 6292 | int i; |
6382 | 6293 | ||
6383 | mutex_lock(&ar->conf_mutex); | 6294 | mutex_lock(&ar->conf_mutex); |
@@ -6386,38 +6297,81 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, | |||
6386 | "mac chanctx switch n_vifs %d mode %d\n", | 6297 | "mac chanctx switch n_vifs %d mode %d\n", |
6387 | n_vifs, mode); | 6298 | n_vifs, mode); |
6388 | 6299 | ||
6389 | spin_lock_bh(&ar->data_lock); | 6300 | /* First stop monitor interface. Some FW versions crash if there's a |
6301 | * lone monitor interface. | ||
6302 | */ | ||
6303 | if (ar->monitor_started) | ||
6304 | ath10k_monitor_stop(ar); | ||
6305 | |||
6390 | for (i = 0; i < n_vifs; i++) { | 6306 | for (i = 0; i < n_vifs; i++) { |
6391 | arvif = ath10k_vif_to_arvif(vifs[i].vif); | 6307 | arvif = ath10k_vif_to_arvif(vifs[i].vif); |
6392 | arctx_new = (void *)vifs[i].new_ctx->drv_priv; | ||
6393 | arctx_old = (void *)vifs[i].old_ctx->drv_priv; | ||
6394 | 6308 | ||
6395 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 6309 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
6396 | "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n", | 6310 | "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", |
6397 | arvif->vdev_id, | 6311 | arvif->vdev_id, |
6398 | vifs[i].old_ctx->def.chan->center_freq, | 6312 | vifs[i].old_ctx->def.chan->center_freq, |
6399 | vifs[i].new_ctx->def.chan->center_freq, | 6313 | vifs[i].new_ctx->def.chan->center_freq, |
6400 | vifs[i].old_ctx->def.width, | 6314 | vifs[i].old_ctx->def.width, |
6401 | vifs[i].new_ctx->def.width, | 6315 | vifs[i].new_ctx->def.width); |
6402 | arctx_old, arctx_new); | ||
6403 | 6316 | ||
6404 | if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { | 6317 | if (WARN_ON(!arvif->is_started)) |
6405 | ath10k_mac_chan_ctx_init(ar, arctx_new, | 6318 | continue; |
6406 | vifs[i].new_ctx); | ||
6407 | } | ||
6408 | 6319 | ||
6409 | arctx_new->conf = *vifs[i].new_ctx; | 6320 | if (WARN_ON(!arvif->is_up)) |
6321 | continue; | ||
6410 | 6322 | ||
6411 | /* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not | 6323 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); |
6412 | * yet updated chanctx_conf pointer. | 6324 | if (ret) { |
6413 | */ | 6325 | ath10k_warn(ar, "failed to down vdev %d: %d\n", |
6414 | arctx_old->conf = *vifs[i].new_ctx; | 6326 | arvif->vdev_id, ret); |
6327 | continue; | ||
6328 | } | ||
6415 | } | 6329 | } |
6416 | ath10k_mac_update_rx_channel(ar); | 6330 | |
6331 | /* All relevant vdevs are downed and associated channel resources | ||
6332 | * should be available for the channel switch now. | ||
6333 | */ | ||
6334 | |||
6335 | spin_lock_bh(&ar->data_lock); | ||
6336 | ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); | ||
6417 | spin_unlock_bh(&ar->data_lock); | 6337 | spin_unlock_bh(&ar->data_lock); |
6418 | 6338 | ||
6419 | /* FIXME: Reconfigure only affected vifs */ | 6339 | for (i = 0; i < n_vifs; i++) { |
6420 | ath10k_mac_chan_reconfigure(ar); | 6340 | arvif = ath10k_vif_to_arvif(vifs[i].vif); |
6341 | |||
6342 | if (WARN_ON(!arvif->is_started)) | ||
6343 | continue; | ||
6344 | |||
6345 | if (WARN_ON(!arvif->is_up)) | ||
6346 | continue; | ||
6347 | |||
6348 | ret = ath10k_mac_setup_bcn_tmpl(arvif); | ||
6349 | if (ret) | ||
6350 | ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", | ||
6351 | ret); | ||
6352 | |||
6353 | ret = ath10k_mac_setup_prb_tmpl(arvif); | ||
6354 | if (ret) | ||
6355 | ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", | ||
6356 | ret); | ||
6357 | |||
6358 | ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); | ||
6359 | if (ret) { | ||
6360 | ath10k_warn(ar, "failed to restart vdev %d: %d\n", | ||
6361 | arvif->vdev_id, ret); | ||
6362 | continue; | ||
6363 | } | ||
6364 | |||
6365 | ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, | ||
6366 | arvif->bssid); | ||
6367 | if (ret) { | ||
6368 | ath10k_warn(ar, "failed to bring vdev up %d: %d\n", | ||
6369 | arvif->vdev_id, ret); | ||
6370 | continue; | ||
6371 | } | ||
6372 | } | ||
6373 | |||
6374 | ath10k_monitor_recalc(ar); | ||
6421 | 6375 | ||
6422 | mutex_unlock(&ar->conf_mutex); | 6376 | mutex_unlock(&ar->conf_mutex); |
6423 | return 0; | 6377 | return 0; |
@@ -6914,7 +6868,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
6914 | 6868 | ||
6915 | ar->hw->vif_data_size = sizeof(struct ath10k_vif); | 6869 | ar->hw->vif_data_size = sizeof(struct ath10k_vif); |
6916 | ar->hw->sta_data_size = sizeof(struct ath10k_sta); | 6870 | ar->hw->sta_data_size = sizeof(struct ath10k_sta); |
6917 | ar->hw->chanctx_data_size = sizeof(struct ath10k_chanctx); | ||
6918 | 6871 | ||
6919 | ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; | 6872 | ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; |
6920 | 6873 | ||
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 17a060e8efa2..ea656e011a96 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -1424,7 +1424,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) | |||
1424 | struct ath10k_ce_ring *ce_ring; | 1424 | struct ath10k_ce_ring *ce_ring; |
1425 | struct ce_desc *ce_desc; | 1425 | struct ce_desc *ce_desc; |
1426 | struct sk_buff *skb; | 1426 | struct sk_buff *skb; |
1427 | unsigned int id; | ||
1428 | int i; | 1427 | int i; |
1429 | 1428 | ||
1430 | ar = pci_pipe->hif_ce_state; | 1429 | ar = pci_pipe->hif_ce_state; |
@@ -1448,8 +1447,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) | |||
1448 | continue; | 1447 | continue; |
1449 | 1448 | ||
1450 | ce_ring->per_transfer_context[i] = NULL; | 1449 | ce_ring->per_transfer_context[i] = NULL; |
1451 | id = MS(__le16_to_cpu(ce_desc[i].flags), | ||
1452 | CE_DESC_FLAGS_META_DATA); | ||
1453 | 1450 | ||
1454 | ar_pci->msg_callbacks_current.tx_completion(ar, skb); | 1451 | ar_pci->msg_callbacks_current.tx_completion(ar, skb); |
1455 | } | 1452 | } |
@@ -2850,6 +2847,7 @@ err_free_pipes: | |||
2850 | ath10k_pci_free_pipes(ar); | 2847 | ath10k_pci_free_pipes(ar); |
2851 | 2848 | ||
2852 | err_sleep: | 2849 | err_sleep: |
2850 | ath10k_pci_sleep_sync(ar); | ||
2853 | ath10k_pci_release(ar); | 2851 | ath10k_pci_release(ar); |
2854 | 2852 | ||
2855 | err_core_destroy: | 2853 | err_core_destroy: |
@@ -2927,8 +2925,10 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); | |||
2927 | 2925 | ||
2928 | /* QCA6174 2.1 firmware files */ | 2926 | /* QCA6174 2.1 firmware files */ |
2929 | MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE); | 2927 | MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE); |
2928 | MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE); | ||
2930 | MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE); | 2929 | MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE); |
2931 | 2930 | ||
2932 | /* QCA6174 3.1 firmware files */ | 2931 | /* QCA6174 3.1 firmware files */ |
2933 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); | 2932 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); |
2933 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); | ||
2934 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); | 2934 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 563fde73623c..8fdba3865c96 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
@@ -402,7 +402,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
402 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 402 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
403 | 403 | ||
404 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 404 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
405 | return; | 405 | goto out; |
406 | 406 | ||
407 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 407 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
408 | 408 | ||
@@ -521,6 +521,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
521 | break; | 521 | break; |
522 | } | 522 | } |
523 | 523 | ||
524 | out: | ||
524 | dev_kfree_skb(skb); | 525 | dev_kfree_skb(skb); |
525 | } | 526 | } |
526 | 527 | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 0fabe689179c..6c046c244705 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "testmode.h" | 27 | #include "testmode.h" |
28 | #include "wmi-ops.h" | 28 | #include "wmi-ops.h" |
29 | #include "p2p.h" | 29 | #include "p2p.h" |
30 | #include "hw.h" | ||
30 | 31 | ||
31 | /* MAIN WMI cmd track */ | 32 | /* MAIN WMI cmd track */ |
32 | static struct wmi_cmd_map wmi_cmd_map = { | 33 | 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) | |||
1450 | ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg); | 1451 | ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg); |
1451 | if (ret) { | 1452 | if (ret) { |
1452 | ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret); | 1453 | ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret); |
1454 | dev_kfree_skb(skb); | ||
1453 | return ret; | 1455 | return ret; |
1454 | } | 1456 | } |
1455 | 1457 | ||
@@ -1636,20 +1638,22 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) | |||
1636 | } | 1638 | } |
1637 | 1639 | ||
1638 | if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { | 1640 | if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { |
1639 | /* During scanning chan info is reported twice for each | 1641 | if (ar->ch_info_can_report_survey) { |
1640 | * visited channel. The reported cycle count is global | 1642 | survey = &ar->survey[idx]; |
1641 | * and per-channel cycle count must be calculated */ | 1643 | survey->noise = noise_floor; |
1642 | 1644 | survey->filled = SURVEY_INFO_NOISE_DBM; | |
1643 | cycle_count -= ar->survey_last_cycle_count; | 1645 | |
1644 | rx_clear_count -= ar->survey_last_rx_clear_count; | 1646 | ath10k_hw_fill_survey_time(ar, |
1645 | 1647 | survey, | |
1646 | survey = &ar->survey[idx]; | 1648 | cycle_count, |
1647 | survey->time = WMI_CHAN_INFO_MSEC(cycle_count); | 1649 | rx_clear_count, |
1648 | survey->time_busy = WMI_CHAN_INFO_MSEC(rx_clear_count); | 1650 | ar->survey_last_cycle_count, |
1649 | survey->noise = noise_floor; | 1651 | ar->survey_last_rx_clear_count); |
1650 | survey->filled = SURVEY_INFO_TIME | | 1652 | } |
1651 | SURVEY_INFO_TIME_BUSY | | 1653 | |
1652 | SURVEY_INFO_NOISE_DBM; | 1654 | ar->ch_info_can_report_survey = false; |
1655 | } else { | ||
1656 | ar->ch_info_can_report_survey = true; | ||
1653 | } | 1657 | } |
1654 | 1658 | ||
1655 | ar->survey_last_rx_clear_count = rx_clear_count; | 1659 | 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) | |||
3219 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 3223 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
3220 | 3224 | ||
3221 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 3225 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
3222 | return; | 3226 | goto out; |
3223 | 3227 | ||
3224 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 3228 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
3225 | 3229 | ||
@@ -3323,6 +3327,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3323 | break; | 3327 | break; |
3324 | } | 3328 | } |
3325 | 3329 | ||
3330 | out: | ||
3326 | dev_kfree_skb(skb); | 3331 | dev_kfree_skb(skb); |
3327 | } | 3332 | } |
3328 | 3333 | ||
@@ -3336,7 +3341,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3336 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 3341 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
3337 | 3342 | ||
3338 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 3343 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
3339 | return; | 3344 | goto out; |
3340 | 3345 | ||
3341 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 3346 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
3342 | 3347 | ||
@@ -3459,7 +3464,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3459 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 3464 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
3460 | 3465 | ||
3461 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 3466 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
3462 | return; | 3467 | goto out; |
3463 | 3468 | ||
3464 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 3469 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
3465 | 3470 | ||
@@ -3567,6 +3572,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3567 | break; | 3572 | break; |
3568 | } | 3573 | } |
3569 | 3574 | ||
3575 | out: | ||
3570 | dev_kfree_skb(skb); | 3576 | dev_kfree_skb(skb); |
3571 | } | 3577 | } |
3572 | 3578 | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index cad72ae76253..cf44a3d080a3 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -4665,7 +4665,6 @@ struct wmi_peer_sta_kickout_event { | |||
4665 | } __packed; | 4665 | } __packed; |
4666 | 4666 | ||
4667 | #define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0) | 4667 | #define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0) |
4668 | #define WMI_CHAN_INFO_MSEC(x) ((x) / 88000) | ||
4669 | 4668 | ||
4670 | /* Beacon filter wmi command info */ | 4669 | /* Beacon filter wmi command info */ |
4671 | #define BCN_FLT_MAX_SUPPORTED_IES 256 | 4670 | #define BCN_FLT_MAX_SUPPORTED_IES 256 |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 19f88b4a24fb..05d25a94c781 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -1527,8 +1527,8 @@ struct wmi_connect_event { | |||
1527 | __le32 nw_type; | 1527 | __le32 nw_type; |
1528 | } sta; | 1528 | } sta; |
1529 | struct { | 1529 | struct { |
1530 | u8 phymode; | ||
1531 | u8 aid; | 1530 | u8 aid; |
1531 | u8 phymode; | ||
1532 | u8 mac_addr[ETH_ALEN]; | 1532 | u8 mac_addr[ETH_ALEN]; |
1533 | u8 auth; | 1533 | u8 auth; |
1534 | u8 keymgmt; | 1534 | u8 keymgmt; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 5dbc617ecf8a..16dff4b89a86 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -531,6 +531,7 @@ struct ath9k_htc_priv { | |||
531 | struct ath9k_debug debug; | 531 | struct ath9k_debug debug; |
532 | #endif | 532 | #endif |
533 | struct mutex mutex; | 533 | struct mutex mutex; |
534 | struct ieee80211_vif *csa_vif; | ||
534 | }; | 535 | }; |
535 | 536 | ||
536 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) | 537 | 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); | |||
584 | void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); | 585 | void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); |
585 | void ath9k_tx_failed_tasklet(unsigned long data); | 586 | void ath9k_tx_failed_tasklet(unsigned long data); |
586 | void ath9k_htc_tx_cleanup_timer(unsigned long data); | 587 | void ath9k_htc_tx_cleanup_timer(unsigned long data); |
588 | bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv); | ||
587 | 589 | ||
588 | int ath9k_rx_init(struct ath9k_htc_priv *priv); | 590 | int ath9k_rx_init(struct ath9k_htc_priv *priv); |
589 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); | 591 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index e8b6ec3c1dbb..e6bcb4c90fa0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -257,6 +257,8 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | |||
257 | } | 257 | } |
258 | 258 | ||
259 | spin_unlock_bh(&priv->beacon_lock); | 259 | spin_unlock_bh(&priv->beacon_lock); |
260 | |||
261 | ath9k_htc_csa_is_finished(priv); | ||
260 | } | 262 | } |
261 | 263 | ||
262 | static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, | 264 | 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) | |||
503 | return; | 505 | return; |
504 | } | 506 | } |
505 | } | 507 | } |
508 | |||
509 | bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv) | ||
510 | { | ||
511 | struct ieee80211_vif *vif; | ||
512 | |||
513 | vif = priv->csa_vif; | ||
514 | if (!vif || !vif->csa_active) | ||
515 | return false; | ||
516 | |||
517 | if (!ieee80211_csa_is_complete(vif)) | ||
518 | return false; | ||
519 | |||
520 | ieee80211_csa_finish(vif); | ||
521 | |||
522 | priv->csa_vif = NULL; | ||
523 | return true; | ||
524 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 36218ee2bdbe..39eaf9b6e9b4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -744,7 +744,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
744 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 744 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
745 | 745 | ||
746 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | | 746 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | |
747 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 747 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
748 | WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
748 | 749 | ||
749 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; | 750 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; |
750 | 751 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index b71f3072fd9a..dab1323dfec7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1134,6 +1134,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1134 | priv->nvifs--; | 1134 | priv->nvifs--; |
1135 | priv->vif_slot &= ~(1 << avp->index); | 1135 | priv->vif_slot &= ~(1 << avp->index); |
1136 | 1136 | ||
1137 | if (priv->csa_vif == vif) | ||
1138 | priv->csa_vif = NULL; | ||
1139 | |||
1137 | ath9k_htc_remove_station(priv, vif, NULL); | 1140 | ath9k_htc_remove_station(priv, vif, NULL); |
1138 | 1141 | ||
1139 | DEC_VIF(priv, vif->type); | 1142 | DEC_VIF(priv, vif->type); |
@@ -1841,6 +1844,19 @@ static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, | |||
1841 | return 0; | 1844 | return 0; |
1842 | } | 1845 | } |
1843 | 1846 | ||
1847 | static void ath9k_htc_channel_switch_beacon(struct ieee80211_hw *hw, | ||
1848 | struct ieee80211_vif *vif, | ||
1849 | struct cfg80211_chan_def *chandef) | ||
1850 | { | ||
1851 | struct ath9k_htc_priv *priv = hw->priv; | ||
1852 | |||
1853 | /* mac80211 does not support CSA in multi-if cases (yet) */ | ||
1854 | if (WARN_ON(priv->csa_vif)) | ||
1855 | return; | ||
1856 | |||
1857 | priv->csa_vif = vif; | ||
1858 | } | ||
1859 | |||
1844 | struct ieee80211_ops ath9k_htc_ops = { | 1860 | struct ieee80211_ops ath9k_htc_ops = { |
1845 | .tx = ath9k_htc_tx, | 1861 | .tx = ath9k_htc_tx, |
1846 | .start = ath9k_htc_start, | 1862 | .start = ath9k_htc_start, |
@@ -1867,6 +1883,7 @@ struct ieee80211_ops ath9k_htc_ops = { | |||
1867 | .set_bitrate_mask = ath9k_htc_set_bitrate_mask, | 1883 | .set_bitrate_mask = ath9k_htc_set_bitrate_mask, |
1868 | .get_stats = ath9k_htc_get_stats, | 1884 | .get_stats = ath9k_htc_get_stats, |
1869 | .get_antenna = ath9k_htc_get_antenna, | 1885 | .get_antenna = ath9k_htc_get_antenna, |
1886 | .channel_switch_beacon = ath9k_htc_channel_switch_beacon, | ||
1870 | 1887 | ||
1871 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 1888 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
1872 | .get_et_sset_count = ath9k_htc_get_et_sset_count, | 1889 | .get_et_sset_count = ath9k_htc_get_et_sset_count, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d285e3a89853..cfd45cb8ccfc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -216,11 +216,13 @@ static bool ath_prepare_reset(struct ath_softc *sc) | |||
216 | ath_stop_ani(sc); | 216 | ath_stop_ani(sc); |
217 | ath9k_hw_disable_interrupts(ah); | 217 | ath9k_hw_disable_interrupts(ah); |
218 | 218 | ||
219 | if (!ath_drain_all_txq(sc)) | 219 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
220 | ret = false; | 220 | ret &= ath_stoprecv(sc); |
221 | 221 | ret &= ath_drain_all_txq(sc); | |
222 | if (!ath_stoprecv(sc)) | 222 | } else { |
223 | ret = false; | 223 | ret &= ath_drain_all_txq(sc); |
224 | ret &= ath_stoprecv(sc); | ||
225 | } | ||
224 | 226 | ||
225 | return ret; | 227 | return ret; |
226 | } | 228 | } |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index dbfcdd16628a..c79cfe02ec80 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -289,6 +289,26 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
289 | } | 289 | } |
290 | 290 | ||
291 | wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); | 291 | wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); |
292 | wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); | ||
293 | |||
294 | for (i = 0; i < request->n_ssids; i++) { | ||
295 | wil_dbg_misc(wil, "SSID[%d]", i); | ||
296 | print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, | ||
297 | request->ssids[i].ssid, | ||
298 | request->ssids[i].ssid_len); | ||
299 | } | ||
300 | |||
301 | if (request->n_ssids) | ||
302 | rc = wmi_set_ssid(wil, request->ssids[0].ssid_len, | ||
303 | request->ssids[0].ssid); | ||
304 | else | ||
305 | rc = wmi_set_ssid(wil, 0, NULL); | ||
306 | |||
307 | if (rc) { | ||
308 | wil_err(wil, "set SSID for scan request failed: %d\n", rc); | ||
309 | return rc; | ||
310 | } | ||
311 | |||
292 | wil->scan_request = request; | 312 | wil->scan_request = request; |
293 | mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO); | 313 | mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO); |
294 | 314 | ||
@@ -778,6 +798,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
778 | size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | 798 | size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); |
779 | const u8 *pr_ies = NULL; | 799 | const u8 *pr_ies = NULL; |
780 | size_t pr_ies_len = 0; | 800 | size_t pr_ies_len = 0; |
801 | u8 hidden_ssid; | ||
781 | 802 | ||
782 | wil_dbg_misc(wil, "%s()\n", __func__); | 803 | wil_dbg_misc(wil, "%s()\n", __func__); |
783 | 804 | ||
@@ -790,6 +811,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
790 | channel->center_freq, info->privacy ? "secure" : "open"); | 811 | channel->center_freq, info->privacy ? "secure" : "open"); |
791 | wil_dbg_misc(wil, "Privacy: %d auth_type %d\n", | 812 | wil_dbg_misc(wil, "Privacy: %d auth_type %d\n", |
792 | info->privacy, info->auth_type); | 813 | info->privacy, info->auth_type); |
814 | wil_dbg_misc(wil, "Hidden SSID mode: %d\n", | ||
815 | info->hidden_ssid); | ||
793 | wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval, | 816 | wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval, |
794 | info->dtim_period); | 817 | info->dtim_period); |
795 | print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, | 818 | print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, |
@@ -835,10 +858,28 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
835 | 858 | ||
836 | wil->privacy = info->privacy; | 859 | wil->privacy = info->privacy; |
837 | 860 | ||
861 | switch (info->hidden_ssid) { | ||
862 | case NL80211_HIDDEN_SSID_NOT_IN_USE: | ||
863 | hidden_ssid = WMI_HIDDEN_SSID_DISABLED; | ||
864 | break; | ||
865 | |||
866 | case NL80211_HIDDEN_SSID_ZERO_LEN: | ||
867 | hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY; | ||
868 | break; | ||
869 | |||
870 | case NL80211_HIDDEN_SSID_ZERO_CONTENTS: | ||
871 | hidden_ssid = WMI_HIDDEN_SSID_CLEAR; | ||
872 | break; | ||
873 | |||
874 | default: | ||
875 | rc = -EOPNOTSUPP; | ||
876 | goto out; | ||
877 | } | ||
878 | |||
838 | netif_carrier_on(ndev); | 879 | netif_carrier_on(ndev); |
839 | 880 | ||
840 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, | 881 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
841 | channel->hw_value); | 882 | channel->hw_value, hidden_ssid); |
842 | if (rc) | 883 | if (rc) |
843 | goto err_pcp_start; | 884 | goto err_pcp_start; |
844 | 885 | ||
@@ -1023,8 +1064,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { | |||
1023 | 1064 | ||
1024 | static void wil_wiphy_init(struct wiphy *wiphy) | 1065 | static void wil_wiphy_init(struct wiphy *wiphy) |
1025 | { | 1066 | { |
1026 | /* TODO: set real value */ | 1067 | wiphy->max_scan_ssids = 1; |
1027 | wiphy->max_scan_ssids = 10; | ||
1028 | wiphy->max_scan_ie_len = WMI_MAX_IE_LEN; | 1068 | wiphy->max_scan_ie_len = WMI_MAX_IE_LEN; |
1029 | wiphy->max_num_pmkids = 0 /* TODO: */; | 1069 | wiphy->max_num_pmkids = 0 /* TODO: */; |
1030 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1070 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 8f9c0722a801..75219a1b8805 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -1360,7 +1360,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) | |||
1360 | __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | 1360 | __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) |
1361 | { | 1361 | { |
1362 | struct wil6210_priv *wil = s->private; | 1362 | struct wil6210_priv *wil = s->private; |
1363 | int i, tid; | 1363 | int i, tid, mcs; |
1364 | 1364 | ||
1365 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1365 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
1366 | struct wil_sta_info *p = &wil->sta[i]; | 1366 | struct wil_sta_info *p = &wil->sta[i]; |
@@ -1390,6 +1390,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | |||
1390 | } | 1390 | } |
1391 | } | 1391 | } |
1392 | spin_unlock_bh(&p->tid_rx_lock); | 1392 | spin_unlock_bh(&p->tid_rx_lock); |
1393 | seq_puts(s, "Rx/MCS:"); | ||
1394 | for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); | ||
1395 | mcs++) | ||
1396 | seq_printf(s, " %lld", | ||
1397 | p->stats.rx_per_mcs[mcs]); | ||
1398 | seq_puts(s, "\n"); | ||
1393 | } | 1399 | } |
1394 | } | 1400 | } |
1395 | 1401 | ||
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 6d704aee3afd..b9febab89167 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -100,6 +100,8 @@ module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO); | |||
100 | MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order"); | 100 | MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order"); |
101 | module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO); | 101 | module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO); |
102 | MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order"); | 102 | MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order"); |
103 | module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, S_IRUGO); | ||
104 | MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order"); | ||
103 | 105 | ||
104 | #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ | 106 | #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ |
105 | #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ | 107 | #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 6042f61b016c..8ef18ace110f 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -132,7 +132,7 @@ static void wil_dev_setup(struct net_device *dev) | |||
132 | dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; | 132 | dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; |
133 | } | 133 | } |
134 | 134 | ||
135 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | 135 | void *wil_if_alloc(struct device *dev) |
136 | { | 136 | { |
137 | struct net_device *ndev; | 137 | struct net_device *ndev; |
138 | struct wireless_dev *wdev; | 138 | struct wireless_dev *wdev; |
@@ -147,7 +147,6 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
147 | } | 147 | } |
148 | 148 | ||
149 | wil = wdev_to_wil(wdev); | 149 | wil = wdev_to_wil(wdev); |
150 | wil->csr = csr; | ||
151 | wil->wdev = wdev; | 150 | wil->wdev = wdev; |
152 | 151 | ||
153 | wil_dbg_misc(wil, "%s()\n", __func__); | 152 | wil_dbg_misc(wil, "%s()\n", __func__); |
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 58c79166a6d1..aa3ecc607ca3 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -163,7 +163,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
163 | { | 163 | { |
164 | struct wil6210_priv *wil; | 164 | struct wil6210_priv *wil; |
165 | struct device *dev = &pdev->dev; | 165 | struct device *dev = &pdev->dev; |
166 | void __iomem *csr; | ||
167 | int rc; | 166 | int rc; |
168 | 167 | ||
169 | /* check HW */ | 168 | /* check HW */ |
@@ -178,9 +177,28 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
178 | return -ENODEV; | 177 | return -ENODEV; |
179 | } | 178 | } |
180 | 179 | ||
180 | wil = wil_if_alloc(dev); | ||
181 | if (IS_ERR(wil)) { | ||
182 | rc = (int)PTR_ERR(wil); | ||
183 | dev_err(dev, "wil_if_alloc failed: %d\n", rc); | ||
184 | return rc; | ||
185 | } | ||
186 | wil->pdev = pdev; | ||
187 | pci_set_drvdata(pdev, wil); | ||
188 | /* rollback to if_free */ | ||
189 | |||
190 | wil->platform_handle = | ||
191 | wil_platform_init(&pdev->dev, &wil->platform_ops); | ||
192 | if (!wil->platform_handle) { | ||
193 | rc = -ENODEV; | ||
194 | wil_err(wil, "wil_platform_init failed\n"); | ||
195 | goto if_free; | ||
196 | } | ||
197 | /* rollback to err_plat */ | ||
198 | |||
181 | rc = pci_enable_device(pdev); | 199 | rc = pci_enable_device(pdev); |
182 | if (rc) { | 200 | if (rc) { |
183 | dev_err(&pdev->dev, | 201 | wil_err(wil, |
184 | "pci_enable_device failed, retry with MSI only\n"); | 202 | "pci_enable_device failed, retry with MSI only\n"); |
185 | /* Work around for platforms that can't allocate IRQ: | 203 | /* Work around for platforms that can't allocate IRQ: |
186 | * retry with MSI only | 204 | * retry with MSI only |
@@ -188,47 +206,37 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
188 | pdev->msi_enabled = 1; | 206 | pdev->msi_enabled = 1; |
189 | rc = pci_enable_device(pdev); | 207 | rc = pci_enable_device(pdev); |
190 | } | 208 | } |
191 | if (rc) | 209 | if (rc) { |
192 | return -ENODEV; | 210 | wil_err(wil, |
211 | "pci_enable_device failed, even with MSI only\n"); | ||
212 | goto err_plat; | ||
213 | } | ||
193 | /* rollback to err_disable_pdev */ | 214 | /* rollback to err_disable_pdev */ |
194 | 215 | ||
195 | rc = pci_request_region(pdev, 0, WIL_NAME); | 216 | rc = pci_request_region(pdev, 0, WIL_NAME); |
196 | if (rc) { | 217 | if (rc) { |
197 | dev_err(&pdev->dev, "pci_request_region failed\n"); | 218 | wil_err(wil, "pci_request_region failed\n"); |
198 | goto err_disable_pdev; | 219 | goto err_disable_pdev; |
199 | } | 220 | } |
200 | /* rollback to err_release_reg */ | 221 | /* rollback to err_release_reg */ |
201 | 222 | ||
202 | csr = pci_ioremap_bar(pdev, 0); | 223 | wil->csr = pci_ioremap_bar(pdev, 0); |
203 | if (!csr) { | 224 | if (!wil->csr) { |
204 | dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); | 225 | wil_err(wil, "pci_ioremap_bar failed\n"); |
205 | rc = -ENODEV; | 226 | rc = -ENODEV; |
206 | goto err_release_reg; | 227 | goto err_release_reg; |
207 | } | 228 | } |
208 | /* rollback to err_iounmap */ | 229 | /* rollback to err_iounmap */ |
209 | dev_info(&pdev->dev, "CSR at %pR -> 0x%p\n", &pdev->resource[0], csr); | 230 | wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr); |
210 | 231 | ||
211 | wil = wil_if_alloc(dev, csr); | ||
212 | if (IS_ERR(wil)) { | ||
213 | rc = (int)PTR_ERR(wil); | ||
214 | dev_err(dev, "wil_if_alloc failed: %d\n", rc); | ||
215 | goto err_iounmap; | ||
216 | } | ||
217 | /* rollback to if_free */ | ||
218 | |||
219 | pci_set_drvdata(pdev, wil); | ||
220 | wil->pdev = pdev; | ||
221 | wil_set_capabilities(wil); | 232 | wil_set_capabilities(wil); |
222 | wil6210_clear_irq(wil); | 233 | wil6210_clear_irq(wil); |
223 | 234 | ||
224 | wil->platform_handle = | ||
225 | wil_platform_init(&pdev->dev, &wil->platform_ops); | ||
226 | |||
227 | /* FW should raise IRQ when ready */ | 235 | /* FW should raise IRQ when ready */ |
228 | rc = wil_if_pcie_enable(wil); | 236 | rc = wil_if_pcie_enable(wil); |
229 | if (rc) { | 237 | if (rc) { |
230 | wil_err(wil, "Enable device failed\n"); | 238 | wil_err(wil, "Enable device failed\n"); |
231 | goto if_free; | 239 | goto err_iounmap; |
232 | } | 240 | } |
233 | /* rollback to bus_disable */ | 241 | /* rollback to bus_disable */ |
234 | 242 | ||
@@ -243,18 +251,19 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
243 | 251 | ||
244 | return 0; | 252 | return 0; |
245 | 253 | ||
246 | bus_disable: | 254 | bus_disable: |
247 | wil_if_pcie_disable(wil); | 255 | wil_if_pcie_disable(wil); |
248 | if_free: | 256 | err_iounmap: |
257 | pci_iounmap(pdev, wil->csr); | ||
258 | err_release_reg: | ||
259 | pci_release_region(pdev, 0); | ||
260 | err_disable_pdev: | ||
261 | pci_disable_device(pdev); | ||
262 | err_plat: | ||
249 | if (wil->platform_ops.uninit) | 263 | if (wil->platform_ops.uninit) |
250 | wil->platform_ops.uninit(wil->platform_handle); | 264 | wil->platform_ops.uninit(wil->platform_handle); |
265 | if_free: | ||
251 | wil_if_free(wil); | 266 | wil_if_free(wil); |
252 | err_iounmap: | ||
253 | pci_iounmap(pdev, csr); | ||
254 | err_release_reg: | ||
255 | pci_release_region(pdev, 0); | ||
256 | err_disable_pdev: | ||
257 | pci_disable_device(pdev); | ||
258 | 267 | ||
259 | return rc; | 268 | return rc; |
260 | } | 269 | } |
@@ -269,12 +278,12 @@ static void wil_pcie_remove(struct pci_dev *pdev) | |||
269 | wil6210_debugfs_remove(wil); | 278 | wil6210_debugfs_remove(wil); |
270 | wil_if_remove(wil); | 279 | wil_if_remove(wil); |
271 | wil_if_pcie_disable(wil); | 280 | wil_if_pcie_disable(wil); |
272 | if (wil->platform_ops.uninit) | ||
273 | wil->platform_ops.uninit(wil->platform_handle); | ||
274 | wil_if_free(wil); | ||
275 | pci_iounmap(pdev, csr); | 281 | pci_iounmap(pdev, csr); |
276 | pci_release_region(pdev, 0); | 282 | pci_release_region(pdev, 0); |
277 | pci_disable_device(pdev); | 283 | pci_disable_device(pdev); |
284 | if (wil->platform_ops.uninit) | ||
285 | wil->platform_ops.uninit(wil->platform_handle); | ||
286 | wil_if_free(wil); | ||
278 | } | 287 | } |
279 | 288 | ||
280 | static const struct pci_device_id wil6210_pcie_ids[] = { | 289 | static const struct pci_device_id wil6210_pcie_ids[] = { |
@@ -291,7 +300,27 @@ static struct pci_driver wil6210_driver = { | |||
291 | .name = WIL_NAME, | 300 | .name = WIL_NAME, |
292 | }; | 301 | }; |
293 | 302 | ||
294 | module_pci_driver(wil6210_driver); | 303 | static int __init wil6210_driver_init(void) |
304 | { | ||
305 | int rc; | ||
306 | |||
307 | rc = wil_platform_modinit(); | ||
308 | if (rc) | ||
309 | return rc; | ||
310 | |||
311 | rc = pci_register_driver(&wil6210_driver); | ||
312 | if (rc) | ||
313 | wil_platform_modexit(); | ||
314 | return rc; | ||
315 | } | ||
316 | module_init(wil6210_driver_init); | ||
317 | |||
318 | static void __exit wil6210_driver_exit(void) | ||
319 | { | ||
320 | pci_unregister_driver(&wil6210_driver); | ||
321 | wil_platform_modexit(); | ||
322 | } | ||
323 | module_exit(wil6210_driver_exit); | ||
295 | 324 | ||
296 | MODULE_LICENSE("Dual BSD/GPL"); | 325 | MODULE_LICENSE("Dual BSD/GPL"); |
297 | MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); | 326 | MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 0113dac3a9a9..aa20af86e1d6 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -427,6 +427,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
427 | cid = wil_rxdesc_cid(d); | 427 | cid = wil_rxdesc_cid(d); |
428 | stats = &wil->sta[cid].stats; | 428 | stats = &wil->sta[cid].stats; |
429 | stats->last_mcs_rx = wil_rxdesc_mcs(d); | 429 | stats->last_mcs_rx = wil_rxdesc_mcs(d); |
430 | if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) | ||
431 | stats->rx_per_mcs[stats->last_mcs_rx]++; | ||
430 | 432 | ||
431 | /* use radiotap header only if required */ | 433 | /* use radiotap header only if required */ |
432 | if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) | 434 | if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f3513a1fa424..275355d46a36 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -281,7 +281,7 @@ struct fw_map { | |||
281 | }; | 281 | }; |
282 | 282 | ||
283 | /* array size should be in sync with actual definition in the wmi.c */ | 283 | /* array size should be in sync with actual definition in the wmi.c */ |
284 | extern const struct fw_map fw_mapping[7]; | 284 | extern const struct fw_map fw_mapping[8]; |
285 | 285 | ||
286 | /** | 286 | /** |
287 | * mk_cidxtid - construct @cidxtid field | 287 | * mk_cidxtid - construct @cidxtid field |
@@ -464,6 +464,7 @@ enum wil_sta_status { | |||
464 | }; | 464 | }; |
465 | 465 | ||
466 | #define WIL_STA_TID_NUM (16) | 466 | #define WIL_STA_TID_NUM (16) |
467 | #define WIL_MCS_MAX (12) /* Maximum MCS supported */ | ||
467 | 468 | ||
468 | struct wil_net_stats { | 469 | struct wil_net_stats { |
469 | unsigned long rx_packets; | 470 | unsigned long rx_packets; |
@@ -473,6 +474,7 @@ struct wil_net_stats { | |||
473 | unsigned long tx_errors; | 474 | unsigned long tx_errors; |
474 | unsigned long rx_dropped; | 475 | unsigned long rx_dropped; |
475 | u16 last_mcs_rx; | 476 | u16 last_mcs_rx; |
477 | u64 rx_per_mcs[WIL_MCS_MAX + 1]; | ||
476 | }; | 478 | }; |
477 | 479 | ||
478 | /** | 480 | /** |
@@ -684,7 +686,7 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | |||
684 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | 686 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, |
685 | size_t count); | 687 | size_t count); |
686 | 688 | ||
687 | void *wil_if_alloc(struct device *dev, void __iomem *csr); | 689 | void *wil_if_alloc(struct device *dev); |
688 | void wil_if_free(struct wil6210_priv *wil); | 690 | void wil_if_free(struct wil6210_priv *wil); |
689 | int wil_if_add(struct wil6210_priv *wil); | 691 | int wil_if_add(struct wil6210_priv *wil); |
690 | void wil_if_remove(struct wil6210_priv *wil); | 692 | void wil_if_remove(struct wil6210_priv *wil); |
@@ -762,7 +764,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev); | |||
762 | void wil_wdev_free(struct wil6210_priv *wil); | 764 | void wil_wdev_free(struct wil6210_priv *wil); |
763 | 765 | ||
764 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | 766 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); |
765 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); | 767 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, |
768 | u8 chan, u8 hidden_ssid); | ||
766 | int wmi_pcp_stop(struct wil6210_priv *wil); | 769 | int wmi_pcp_stop(struct wil6210_priv *wil); |
767 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 770 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
768 | u16 reason_code, bool from_event); | 771 | u16 reason_code, bool from_event); |
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.c b/drivers/net/wireless/ath/wil6210/wil_platform.c index 976a071ba74e..de15f1422fe9 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.c +++ b/drivers/net/wireless/ath/wil6210/wil_platform.c | |||
@@ -17,6 +17,15 @@ | |||
17 | #include "linux/device.h" | 17 | #include "linux/device.h" |
18 | #include "wil_platform.h" | 18 | #include "wil_platform.h" |
19 | 19 | ||
20 | int __init wil_platform_modinit(void) | ||
21 | { | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | void wil_platform_modexit(void) | ||
26 | { | ||
27 | } | ||
28 | |||
20 | /** | 29 | /** |
21 | * wil_platform_init() - wil6210 platform module init | 30 | * wil_platform_init() - wil6210 platform module init |
22 | * | 31 | * |
@@ -26,10 +35,11 @@ | |||
26 | */ | 35 | */ |
27 | void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops) | 36 | void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops) |
28 | { | 37 | { |
29 | void *handle = NULL; | 38 | void *handle = ops; /* to return some non-NULL for 'void' impl. */ |
30 | 39 | ||
31 | if (!ops) { | 40 | if (!ops) { |
32 | dev_err(dev, "Invalid parameter. Cannot init platform module\n"); | 41 | dev_err(dev, |
42 | "Invalid parameter. Cannot init platform module\n"); | ||
33 | return NULL; | 43 | return NULL; |
34 | } | 44 | } |
35 | 45 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h index 158c73b049a9..d7fa19b7886d 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.h +++ b/drivers/net/wireless/ath/wil6210/wil_platform.h | |||
@@ -31,4 +31,7 @@ struct wil_platform_ops { | |||
31 | 31 | ||
32 | void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops); | 32 | void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops); |
33 | 33 | ||
34 | int __init wil_platform_modinit(void); | ||
35 | void wil_platform_modexit(void); | ||
36 | |||
34 | #endif /* __WIL_PLATFORM_H__ */ | 37 | #endif /* __WIL_PLATFORM_H__ */ |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 3dc8daf69bd2..c759759afbb2 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -85,6 +85,7 @@ const struct fw_map fw_mapping[] = { | |||
85 | {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */ | 85 | {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */ |
86 | {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */ | 86 | {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */ |
87 | {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */ | 87 | {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */ |
88 | {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf 512b */ | ||
88 | {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */ | 89 | {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */ |
89 | /* | 90 | /* |
90 | * 920000..930000 ucode code RAM | 91 | * 920000..930000 ucode code RAM |
@@ -824,7 +825,8 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | |||
824 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | 825 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); |
825 | } | 826 | } |
826 | 827 | ||
827 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) | 828 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, |
829 | u8 chan, u8 hidden_ssid) | ||
828 | { | 830 | { |
829 | int rc; | 831 | int rc; |
830 | 832 | ||
@@ -834,6 +836,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) | |||
834 | .disable_sec_offload = 1, | 836 | .disable_sec_offload = 1, |
835 | .channel = chan - 1, | 837 | .channel = chan - 1, |
836 | .pcp_max_assoc_sta = max_assoc_sta, | 838 | .pcp_max_assoc_sta = max_assoc_sta, |
839 | .hidden_ssid = hidden_ssid, | ||
837 | }; | 840 | }; |
838 | struct { | 841 | struct { |
839 | struct wil6210_mbox_hdr_wmi wmi; | 842 | struct wil6210_mbox_hdr_wmi wmi; |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index cc04ab73b398..6e90e78f1554 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -495,10 +495,18 @@ struct wmi_power_mgmt_cfg_cmd { | |||
495 | /* | 495 | /* |
496 | * WMI_PCP_START_CMDID | 496 | * WMI_PCP_START_CMDID |
497 | */ | 497 | */ |
498 | |||
499 | enum wmi_hidden_ssid { | ||
500 | WMI_HIDDEN_SSID_DISABLED = 0, | ||
501 | WMI_HIDDEN_SSID_SEND_EMPTY = 1, | ||
502 | WMI_HIDDEN_SSID_CLEAR = 2, | ||
503 | }; | ||
504 | |||
498 | struct wmi_pcp_start_cmd { | 505 | struct wmi_pcp_start_cmd { |
499 | __le16 bcon_interval; | 506 | __le16 bcon_interval; |
500 | u8 pcp_max_assoc_sta; | 507 | u8 pcp_max_assoc_sta; |
501 | u8 reserved0[9]; | 508 | u8 hidden_ssid; |
509 | u8 reserved0[8]; | ||
502 | u8 network_type; | 510 | u8 network_type; |
503 | u8 channel; | 511 | u8 channel; |
504 | u8 disable_sec_offload; | 512 | u8 disable_sec_offload; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 575b9f4b5589..28490702124a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -5361,6 +5361,10 @@ static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy, | |||
5361 | *have_5ghz_phy = true; | 5361 | *have_5ghz_phy = true; |
5362 | return; | 5362 | return; |
5363 | case 0x4321: /* BCM4306 */ | 5363 | case 0x4321: /* BCM4306 */ |
5364 | /* There are 14e4:4321 PCI devs with 2.4 GHz BCM4321 (N-PHY) */ | ||
5365 | if (dev->phy.type != B43_PHYTYPE_G) | ||
5366 | break; | ||
5367 | /* fall through */ | ||
5364 | case 0x4313: /* BCM4311 */ | 5368 | case 0x4313: /* BCM4311 */ |
5365 | case 0x431a: /* BCM4318 */ | 5369 | case 0x431a: /* BCM4318 */ |
5366 | case 0x432a: /* BCM4321 */ | 5370 | case 0x432a: /* BCM4321 */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 71779b9e4bbe..410a6645d316 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev) | |||
988 | 988 | ||
989 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | 989 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) |
990 | { | 990 | { |
991 | sdiodev->state = BRCMF_SDIOD_DOWN; | ||
991 | if (sdiodev->bus) { | 992 | if (sdiodev->bus) { |
992 | brcmf_sdio_remove(sdiodev->bus); | 993 | brcmf_sdio_remove(sdiodev->bus); |
993 | sdiodev->bus = NULL; | 994 | sdiodev->bus = NULL; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index e10fa67010c0..d86d1f1f1c91 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | |||
@@ -52,8 +52,6 @@ | |||
52 | #define BRCMF_PNO_SCAN_COMPLETE 1 | 52 | #define BRCMF_PNO_SCAN_COMPLETE 1 |
53 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 | 53 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 |
54 | 54 | ||
55 | #define BRCMF_IFACE_MAX_CNT 3 | ||
56 | |||
57 | #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ | 55 | #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ |
58 | #define WPA_OUI_TYPE 1 | 56 | #define WPA_OUI_TYPE 1 |
59 | #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ | 57 | #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ |
@@ -2398,27 +2396,80 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp) | |||
2398 | brcmf_err("set wsec error (%d)\n", err); | 2396 | brcmf_err("set wsec error (%d)\n", err); |
2399 | } | 2397 | } |
2400 | 2398 | ||
2399 | static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) | ||
2400 | { | ||
2401 | struct nl80211_sta_flag_update *sfu; | ||
2402 | |||
2403 | brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags); | ||
2404 | si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS); | ||
2405 | sfu = &si->sta_flags; | ||
2406 | sfu->mask = BIT(NL80211_STA_FLAG_WME) | | ||
2407 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
2408 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
2409 | BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
2410 | if (fw_sta_flags & BRCMF_STA_WME) | ||
2411 | sfu->set |= BIT(NL80211_STA_FLAG_WME); | ||
2412 | if (fw_sta_flags & BRCMF_STA_AUTHE) | ||
2413 | sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
2414 | if (fw_sta_flags & BRCMF_STA_ASSOC) | ||
2415 | sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
2416 | if (fw_sta_flags & BRCMF_STA_AUTHO) | ||
2417 | sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
2418 | } | ||
2419 | |||
2420 | static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) | ||
2421 | { | ||
2422 | struct { | ||
2423 | __le32 len; | ||
2424 | struct brcmf_bss_info_le bss_le; | ||
2425 | } *buf; | ||
2426 | u16 capability; | ||
2427 | int err; | ||
2428 | |||
2429 | buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); | ||
2430 | if (!buf) | ||
2431 | return; | ||
2432 | |||
2433 | buf->len = cpu_to_le32(WL_BSS_INFO_MAX); | ||
2434 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf, | ||
2435 | WL_BSS_INFO_MAX); | ||
2436 | if (err) { | ||
2437 | brcmf_err("Failed to get bss info (%d)\n", err); | ||
2438 | return; | ||
2439 | } | ||
2440 | si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); | ||
2441 | si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); | ||
2442 | si->bss_param.dtim_period = buf->bss_le.dtim_period; | ||
2443 | capability = le16_to_cpu(buf->bss_le.capability); | ||
2444 | if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT) | ||
2445 | si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; | ||
2446 | if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
2447 | si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; | ||
2448 | if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2449 | si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | ||
2450 | } | ||
2451 | |||
2401 | static s32 | 2452 | static s32 |
2402 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | 2453 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, |
2403 | const u8 *mac, struct station_info *sinfo) | 2454 | const u8 *mac, struct station_info *sinfo) |
2404 | { | 2455 | { |
2405 | struct brcmf_if *ifp = netdev_priv(ndev); | 2456 | struct brcmf_if *ifp = netdev_priv(ndev); |
2406 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
2407 | struct brcmf_scb_val_le scb_val; | ||
2408 | int rssi; | ||
2409 | s32 rate; | ||
2410 | s32 err = 0; | 2457 | s32 err = 0; |
2411 | u8 *bssid = profile->bssid; | ||
2412 | struct brcmf_sta_info_le sta_info_le; | 2458 | struct brcmf_sta_info_le sta_info_le; |
2413 | u32 beacon_period; | 2459 | u32 sta_flags; |
2414 | u32 dtim_period; | 2460 | u32 is_tdls_peer; |
2415 | 2461 | ||
2416 | brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); | 2462 | brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); |
2417 | if (!check_vif_up(ifp->vif)) | 2463 | if (!check_vif_up(ifp->vif)) |
2418 | return -EIO; | 2464 | return -EIO; |
2419 | 2465 | ||
2420 | if (brcmf_is_apmode(ifp->vif)) { | 2466 | memset(&sta_info_le, 0, sizeof(sta_info_le)); |
2421 | memcpy(&sta_info_le, mac, ETH_ALEN); | 2467 | memcpy(&sta_info_le, mac, ETH_ALEN); |
2468 | err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info", | ||
2469 | &sta_info_le, | ||
2470 | sizeof(sta_info_le)); | ||
2471 | is_tdls_peer = !err; | ||
2472 | if (err) { | ||
2422 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", | 2473 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", |
2423 | &sta_info_le, | 2474 | &sta_info_le, |
2424 | sizeof(sta_info_le)); | 2475 | sizeof(sta_info_le)); |
@@ -2426,73 +2477,48 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2426 | brcmf_err("GET STA INFO failed, %d\n", err); | 2477 | brcmf_err("GET STA INFO failed, %d\n", err); |
2427 | goto done; | 2478 | goto done; |
2428 | } | 2479 | } |
2429 | sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); | 2480 | } |
2430 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; | 2481 | brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver)); |
2431 | if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { | 2482 | sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); |
2432 | sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); | 2483 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; |
2433 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); | 2484 | sta_flags = le32_to_cpu(sta_info_le.flags); |
2434 | } | 2485 | brcmf_convert_sta_flags(sta_flags, sinfo); |
2435 | brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", | 2486 | sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
2436 | sinfo->inactive_time, sinfo->connected_time); | 2487 | if (is_tdls_peer) |
2437 | } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) { | 2488 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
2438 | if (memcmp(mac, bssid, ETH_ALEN)) { | 2489 | else |
2439 | brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", | 2490 | sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); |
2440 | mac, bssid); | 2491 | if (sta_flags & BRCMF_STA_ASSOC) { |
2441 | err = -ENOENT; | 2492 | sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); |
2442 | goto done; | 2493 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); |
2443 | } | 2494 | brcmf_fill_bss_param(ifp, sinfo); |
2444 | /* Report the current tx rate */ | 2495 | } |
2445 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); | 2496 | if (sta_flags & BRCMF_STA_SCBSTATS) { |
2446 | if (err) { | 2497 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); |
2447 | brcmf_err("Could not get rate (%d)\n", err); | 2498 | sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures); |
2448 | goto done; | 2499 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); |
2449 | } else { | 2500 | sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts); |
2501 | sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts); | ||
2502 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); | ||
2503 | sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts); | ||
2504 | sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts); | ||
2505 | if (sinfo->tx_packets) { | ||
2450 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); | 2506 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
2451 | sinfo->txrate.legacy = rate * 5; | 2507 | sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate); |
2452 | brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2); | 2508 | sinfo->txrate.legacy /= 100; |
2453 | } | 2509 | } |
2454 | 2510 | if (sinfo->rx_packets) { | |
2455 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, | 2511 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); |
2456 | &ifp->vif->sme_state)) { | 2512 | sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate); |
2457 | memset(&scb_val, 0, sizeof(scb_val)); | 2513 | sinfo->rxrate.legacy /= 100; |
2458 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, | ||
2459 | &scb_val, sizeof(scb_val)); | ||
2460 | if (err) { | ||
2461 | brcmf_err("Could not get rssi (%d)\n", err); | ||
2462 | goto done; | ||
2463 | } else { | ||
2464 | rssi = le32_to_cpu(scb_val.val); | ||
2465 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | ||
2466 | sinfo->signal = rssi; | ||
2467 | brcmf_dbg(CONN, "RSSI %d dBm\n", rssi); | ||
2468 | } | ||
2469 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD, | ||
2470 | &beacon_period); | ||
2471 | if (err) { | ||
2472 | brcmf_err("Could not get beacon period (%d)\n", | ||
2473 | err); | ||
2474 | goto done; | ||
2475 | } else { | ||
2476 | sinfo->bss_param.beacon_interval = | ||
2477 | beacon_period; | ||
2478 | brcmf_dbg(CONN, "Beacon peroid %d\n", | ||
2479 | beacon_period); | ||
2480 | } | ||
2481 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD, | ||
2482 | &dtim_period); | ||
2483 | if (err) { | ||
2484 | brcmf_err("Could not get DTIM period (%d)\n", | ||
2485 | err); | ||
2486 | goto done; | ||
2487 | } else { | ||
2488 | sinfo->bss_param.dtim_period = dtim_period; | ||
2489 | brcmf_dbg(CONN, "DTIM peroid %d\n", | ||
2490 | dtim_period); | ||
2491 | } | ||
2492 | sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); | ||
2493 | } | 2514 | } |
2494 | } else | 2515 | if (le16_to_cpu(sta_info_le.ver) >= 4) { |
2495 | err = -EPERM; | 2516 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); |
2517 | sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes); | ||
2518 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); | ||
2519 | sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes); | ||
2520 | } | ||
2521 | } | ||
2496 | done: | 2522 | done: |
2497 | brcmf_dbg(TRACE, "Exit\n"); | 2523 | brcmf_dbg(TRACE, "Exit\n"); |
2498 | return err; | 2524 | return err; |
@@ -5640,53 +5666,6 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy) | |||
5640 | return 0; | 5666 | return 0; |
5641 | } | 5667 | } |
5642 | 5668 | ||
5643 | static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = { | ||
5644 | { | ||
5645 | .max = 1, | ||
5646 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
5647 | BIT(NL80211_IFTYPE_ADHOC) | ||
5648 | }, | ||
5649 | { | ||
5650 | .max = 4, | ||
5651 | .types = BIT(NL80211_IFTYPE_AP) | ||
5652 | }, | ||
5653 | { | ||
5654 | .max = 1, | ||
5655 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5656 | BIT(NL80211_IFTYPE_P2P_GO) | ||
5657 | }, | ||
5658 | { | ||
5659 | .max = 1, | ||
5660 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
5661 | } | ||
5662 | }; | ||
5663 | |||
5664 | static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = { | ||
5665 | { | ||
5666 | .max = 2, | ||
5667 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
5668 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5669 | BIT(NL80211_IFTYPE_AP) | ||
5670 | }, | ||
5671 | { | ||
5672 | .max = 1, | ||
5673 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5674 | BIT(NL80211_IFTYPE_P2P_GO) | ||
5675 | }, | ||
5676 | { | ||
5677 | .max = 1, | ||
5678 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
5679 | } | ||
5680 | }; | ||
5681 | static struct ieee80211_iface_combination brcmf_iface_combos[] = { | ||
5682 | { | ||
5683 | .max_interfaces = BRCMF_IFACE_MAX_CNT, | ||
5684 | .num_different_channels = 1, | ||
5685 | .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss), | ||
5686 | .limits = brcmf_iface_limits_sbss, | ||
5687 | } | ||
5688 | }; | ||
5689 | |||
5690 | static const struct ieee80211_txrx_stypes | 5669 | static const struct ieee80211_txrx_stypes |
5691 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | 5670 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { |
5692 | [NL80211_IFTYPE_STATION] = { | 5671 | [NL80211_IFTYPE_STATION] = { |
@@ -5716,6 +5695,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | |||
5716 | } | 5695 | } |
5717 | }; | 5696 | }; |
5718 | 5697 | ||
5698 | static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) | ||
5699 | { | ||
5700 | struct ieee80211_iface_combination *combo = NULL; | ||
5701 | struct ieee80211_iface_limit *limits = NULL; | ||
5702 | int i = 0, max_iface_cnt; | ||
5703 | |||
5704 | combo = kzalloc(sizeof(*combo), GFP_KERNEL); | ||
5705 | if (!combo) | ||
5706 | goto err; | ||
5707 | |||
5708 | limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL); | ||
5709 | if (!limits) | ||
5710 | goto err; | ||
5711 | |||
5712 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
5713 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5714 | BIT(NL80211_IFTYPE_AP); | ||
5715 | |||
5716 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) | ||
5717 | combo->num_different_channels = 2; | ||
5718 | else | ||
5719 | combo->num_different_channels = 1; | ||
5720 | |||
5721 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { | ||
5722 | limits[i].max = 1; | ||
5723 | limits[i++].types = BIT(NL80211_IFTYPE_STATION); | ||
5724 | limits[i].max = 4; | ||
5725 | limits[i++].types = BIT(NL80211_IFTYPE_AP); | ||
5726 | max_iface_cnt = 5; | ||
5727 | } else { | ||
5728 | limits[i].max = 2; | ||
5729 | limits[i++].types = BIT(NL80211_IFTYPE_STATION) | | ||
5730 | BIT(NL80211_IFTYPE_AP); | ||
5731 | max_iface_cnt = 2; | ||
5732 | } | ||
5733 | |||
5734 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) { | ||
5735 | wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5736 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
5737 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5738 | limits[i].max = 1; | ||
5739 | limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5740 | BIT(NL80211_IFTYPE_P2P_GO); | ||
5741 | limits[i].max = 1; | ||
5742 | limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5743 | max_iface_cnt += 2; | ||
5744 | } | ||
5745 | combo->max_interfaces = max_iface_cnt; | ||
5746 | combo->limits = limits; | ||
5747 | combo->n_limits = i; | ||
5748 | |||
5749 | wiphy->iface_combinations = combo; | ||
5750 | wiphy->n_iface_combinations = 1; | ||
5751 | return 0; | ||
5752 | |||
5753 | err: | ||
5754 | kfree(limits); | ||
5755 | kfree(combo); | ||
5756 | return -ENOMEM; | ||
5757 | } | ||
5758 | |||
5719 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | 5759 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) |
5720 | { | 5760 | { |
5721 | /* scheduled scan settings */ | 5761 | /* scheduled scan settings */ |
@@ -5746,7 +5786,6 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy) | |||
5746 | static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | 5786 | static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) |
5747 | { | 5787 | { |
5748 | struct ieee80211_supported_band *band; | 5788 | struct ieee80211_supported_band *band; |
5749 | struct ieee80211_iface_combination ifc_combo; | ||
5750 | __le32 bandlist[3]; | 5789 | __le32 bandlist[3]; |
5751 | u32 n_bands; | 5790 | u32 n_bands; |
5752 | int err, i; | 5791 | int err, i; |
@@ -5754,24 +5793,11 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | |||
5754 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | 5793 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; |
5755 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | 5794 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; |
5756 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | 5795 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; |
5757 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 5796 | |
5758 | BIT(NL80211_IFTYPE_ADHOC) | | 5797 | err = brcmf_setup_ifmodes(wiphy, ifp); |
5759 | BIT(NL80211_IFTYPE_AP) | | 5798 | if (err) |
5760 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 5799 | return err; |
5761 | BIT(NL80211_IFTYPE_P2P_GO) | | 5800 | |
5762 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5763 | /* need VSDB firmware feature for concurrent channels */ | ||
5764 | ifc_combo = brcmf_iface_combos[0]; | ||
5765 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) | ||
5766 | ifc_combo.num_different_channels = 2; | ||
5767 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { | ||
5768 | ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss), | ||
5769 | ifc_combo.limits = brcmf_iface_limits_mbss; | ||
5770 | } | ||
5771 | wiphy->iface_combinations = kmemdup(&ifc_combo, | ||
5772 | sizeof(ifc_combo), | ||
5773 | GFP_KERNEL); | ||
5774 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | ||
5775 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 5801 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
5776 | wiphy->cipher_suites = __wl_cipher_suites; | 5802 | wiphy->cipher_suites = __wl_cipher_suites; |
5777 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 5803 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); |
@@ -6036,6 +6062,8 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) | |||
6036 | if (!wiphy) | 6062 | if (!wiphy) |
6037 | return; | 6063 | return; |
6038 | 6064 | ||
6065 | if (wiphy->iface_combinations) | ||
6066 | kfree(wiphy->iface_combinations->limits); | ||
6039 | kfree(wiphy->iface_combinations); | 6067 | kfree(wiphy->iface_combinations); |
6040 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { | 6068 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { |
6041 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); | 6069 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); |
@@ -6071,6 +6099,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
6071 | brcmf_err("Could not allocate wiphy device\n"); | 6099 | brcmf_err("Could not allocate wiphy device\n"); |
6072 | return NULL; | 6100 | return NULL; |
6073 | } | 6101 | } |
6102 | memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN); | ||
6074 | set_wiphy_dev(wiphy, busdev); | 6103 | set_wiphy_dev(wiphy, busdev); |
6075 | 6104 | ||
6076 | cfg = wiphy_priv(wiphy); | 6105 | cfg = wiphy_priv(wiphy); |
@@ -6178,10 +6207,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | |||
6178 | if (!cfg) | 6207 | if (!cfg) |
6179 | return; | 6208 | return; |
6180 | 6209 | ||
6181 | WARN_ON(!list_empty(&cfg->vif_list)); | ||
6182 | wiphy_unregister(cfg->wiphy); | ||
6183 | brcmf_btcoex_detach(cfg); | 6210 | brcmf_btcoex_detach(cfg); |
6184 | brcmf_p2p_detach(&cfg->p2p); | 6211 | wiphy_unregister(cfg->wiphy); |
6185 | wl_deinit_priv(cfg); | 6212 | wl_deinit_priv(cfg); |
6186 | brcmf_free_wiphy(cfg->wiphy); | 6213 | brcmf_free_wiphy(cfg->wiphy); |
6187 | } | 6214 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c index 26c65872dae3..7b0e52195a85 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c | |||
@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring, | |||
223 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, | 223 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, |
224 | u16 *n_items) | 224 | u16 *n_items) |
225 | { | 225 | { |
226 | void *ret_addr; | ||
227 | |||
228 | if (commonring->cr_update_wptr) | 226 | if (commonring->cr_update_wptr) |
229 | commonring->cr_update_wptr(commonring->cr_ctx); | 227 | commonring->cr_update_wptr(commonring->cr_ctx); |
230 | 228 | ||
@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, | |||
235 | if (*n_items == 0) | 233 | if (*n_items == 0) |
236 | return NULL; | 234 | return NULL; |
237 | 235 | ||
238 | ret_addr = commonring->buf_addr + | 236 | return commonring->buf_addr + |
239 | (commonring->r_ptr * commonring->item_len); | 237 | (commonring->r_ptr * commonring->item_len); |
240 | |||
241 | commonring->r_ptr += *n_items; | ||
242 | if (commonring->r_ptr == commonring->depth) | ||
243 | commonring->r_ptr = 0; | ||
244 | |||
245 | return ret_addr; | ||
246 | } | 238 | } |
247 | 239 | ||
248 | 240 | ||
249 | int brcmf_commonring_read_complete(struct brcmf_commonring *commonring) | 241 | int brcmf_commonring_read_complete(struct brcmf_commonring *commonring, |
242 | u16 n_items) | ||
250 | { | 243 | { |
244 | commonring->r_ptr += n_items; | ||
245 | if (commonring->r_ptr == commonring->depth) | ||
246 | commonring->r_ptr = 0; | ||
247 | |||
251 | if (commonring->cr_write_rptr) | 248 | if (commonring->cr_write_rptr) |
252 | return commonring->cr_write_rptr(commonring->cr_ctx); | 249 | return commonring->cr_write_rptr(commonring->cr_ctx); |
253 | 250 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h index 3d404016a92e..b85033611c8d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h | |||
@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring, | |||
62 | u16 n_items); | 62 | u16 n_items); |
63 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, | 63 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, |
64 | u16 *n_items); | 64 | u16 *n_items); |
65 | int brcmf_commonring_read_complete(struct brcmf_commonring *commonring); | 65 | int brcmf_commonring_read_complete(struct brcmf_commonring *commonring, |
66 | u16 n_items); | ||
66 | 67 | ||
67 | #define brcmf_commonring_n_items(commonring) (commonring->depth) | 68 | #define brcmf_commonring_n_items(commonring) (commonring->depth) |
68 | #define brcmf_commonring_len_item(commonring) (commonring->item_len) | 69 | #define brcmf_commonring_len_item(commonring) (commonring->item_len) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index f8f47dcfa886..fe9d3fbf5fe2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c | |||
@@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
867 | } | 867 | } |
868 | /* unregister will take care of freeing it */ | 868 | /* unregister will take care of freeing it */ |
869 | unregister_netdev(ifp->ndev); | 869 | unregister_netdev(ifp->ndev); |
870 | } else { | ||
871 | kfree(ifp); | ||
872 | } | 870 | } |
873 | } | 871 | } |
874 | 872 | ||
@@ -1100,6 +1098,8 @@ void brcmf_detach(struct device *dev) | |||
1100 | 1098 | ||
1101 | /* stop firmware event handling */ | 1099 | /* stop firmware event handling */ |
1102 | brcmf_fweh_detach(drvr); | 1100 | brcmf_fweh_detach(drvr); |
1101 | if (drvr->config) | ||
1102 | brcmf_p2p_detach(&drvr->config->p2p); | ||
1103 | 1103 | ||
1104 | brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); | 1104 | brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); |
1105 | 1105 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c index 9b473d50b005..2d6d00553858 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c | |||
@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void) | |||
41 | root_folder = NULL; | 41 | root_folder = NULL; |
42 | } | 42 | } |
43 | 43 | ||
44 | static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data) | ||
45 | { | ||
46 | struct brcmf_bus *bus = dev_get_drvdata(seq->private); | ||
47 | |||
48 | seq_printf(seq, "chip: %x(%u) rev %u\n", | ||
49 | bus->chip, bus->chip, bus->chiprev); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int brcmf_debugfs_attach(struct brcmf_pub *drvr) | 44 | int brcmf_debugfs_attach(struct brcmf_pub *drvr) |
54 | { | 45 | { |
55 | struct device *dev = drvr->bus_if->dev; | 46 | struct device *dev = drvr->bus_if->dev; |
@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
58 | return -ENODEV; | 49 | return -ENODEV; |
59 | 50 | ||
60 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); | 51 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); |
61 | brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read); | ||
62 | 52 | ||
63 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); | 53 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); |
64 | } | 54 | } |
@@ -74,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) | |||
74 | return drvr->dbgfs_dir; | 64 | return drvr->dbgfs_dir; |
75 | } | 65 | } |
76 | 66 | ||
77 | struct brcmf_debugfs_entry { | ||
78 | int (*read)(struct seq_file *seq, void *data); | ||
79 | struct brcmf_pub *drvr; | ||
80 | }; | ||
81 | |||
82 | static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f) | ||
83 | { | ||
84 | struct brcmf_debugfs_entry *entry = inode->i_private; | ||
85 | |||
86 | return single_open(f, entry->read, entry->drvr->bus_if->dev); | ||
87 | } | ||
88 | |||
89 | static const struct file_operations brcmf_debugfs_def_ops = { | ||
90 | .owner = THIS_MODULE, | ||
91 | .open = brcmf_debugfs_entry_open, | ||
92 | .release = single_release, | ||
93 | .read = seq_read, | ||
94 | .llseek = seq_lseek | ||
95 | }; | ||
96 | |||
97 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, | 67 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
98 | int (*read_fn)(struct seq_file *seq, void *data)) | 68 | int (*read_fn)(struct seq_file *seq, void *data)) |
99 | { | 69 | { |
100 | struct dentry *dentry = drvr->dbgfs_dir; | 70 | struct dentry *e; |
101 | struct brcmf_debugfs_entry *entry; | ||
102 | |||
103 | if (IS_ERR_OR_NULL(dentry)) | ||
104 | return -ENOENT; | ||
105 | |||
106 | entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL); | ||
107 | if (!entry) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | entry->read = read_fn; | ||
111 | entry->drvr = drvr; | ||
112 | |||
113 | dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry, | ||
114 | &brcmf_debugfs_def_ops); | ||
115 | 71 | ||
116 | return PTR_ERR_OR_ZERO(dentry); | 72 | e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn, |
73 | drvr->dbgfs_dir, read_fn); | ||
74 | return PTR_ERR_OR_ZERO(e); | ||
117 | } | 75 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c index 2c5fad3a3aa2..1e94e94e01dc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c | |||
@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) | |||
129 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); | 129 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); |
130 | if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) | 130 | if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) |
131 | brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); | 131 | brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); |
132 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p"); | ||
132 | 133 | ||
133 | /* set chip related quirks */ | 134 | /* set chip related quirks */ |
134 | switch (drvr->bus_if->chip) { | 135 | switch (drvr->bus_if->chip) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h index 546962525cd2..6b381f799f22 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h | |||
@@ -23,12 +23,14 @@ | |||
23 | * MCHAN: multi-channel for concurrent P2P. | 23 | * MCHAN: multi-channel for concurrent P2P. |
24 | * PNO: preferred network offload. | 24 | * PNO: preferred network offload. |
25 | * WOWL: Wake-On-WLAN. | 25 | * WOWL: Wake-On-WLAN. |
26 | * P2P: peer-to-peer | ||
26 | */ | 27 | */ |
27 | #define BRCMF_FEAT_LIST \ | 28 | #define BRCMF_FEAT_LIST \ |
28 | BRCMF_FEAT_DEF(MBSS) \ | 29 | BRCMF_FEAT_DEF(MBSS) \ |
29 | BRCMF_FEAT_DEF(MCHAN) \ | 30 | BRCMF_FEAT_DEF(MCHAN) \ |
30 | BRCMF_FEAT_DEF(PNO) \ | 31 | BRCMF_FEAT_DEF(PNO) \ |
31 | BRCMF_FEAT_DEF(WOWL) | 32 | BRCMF_FEAT_DEF(WOWL) \ |
33 | BRCMF_FEAT_DEF(P2P) | ||
32 | /* | 34 | /* |
33 | * Quirks: | 35 | * Quirks: |
34 | * | 36 | * |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 7ae6461df932..743f16b6a072 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c | |||
@@ -43,7 +43,7 @@ enum nvram_parser_state { | |||
43 | * struct nvram_parser - internal info for parser. | 43 | * struct nvram_parser - internal info for parser. |
44 | * | 44 | * |
45 | * @state: current parser state. | 45 | * @state: current parser state. |
46 | * @fwnv: input buffer being parsed. | 46 | * @data: input buffer being parsed. |
47 | * @nvram: output buffer with parse result. | 47 | * @nvram: output buffer with parse result. |
48 | * @nvram_len: lenght of parse result. | 48 | * @nvram_len: lenght of parse result. |
49 | * @line: current line. | 49 | * @line: current line. |
@@ -55,7 +55,7 @@ enum nvram_parser_state { | |||
55 | */ | 55 | */ |
56 | struct nvram_parser { | 56 | struct nvram_parser { |
57 | enum nvram_parser_state state; | 57 | enum nvram_parser_state state; |
58 | const struct firmware *fwnv; | 58 | const u8 *data; |
59 | u8 *nvram; | 59 | u8 *nvram; |
60 | u32 nvram_len; | 60 | u32 nvram_len; |
61 | u32 line; | 61 | u32 line; |
@@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp) | |||
91 | { | 91 | { |
92 | char c; | 92 | char c; |
93 | 93 | ||
94 | c = nvp->fwnv->data[nvp->pos]; | 94 | c = nvp->data[nvp->pos]; |
95 | if (c == '\n') | 95 | if (c == '\n') |
96 | return COMMENT; | 96 | return COMMENT; |
97 | if (is_whitespace(c)) | 97 | if (is_whitespace(c)) |
@@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) | |||
115 | enum nvram_parser_state st = nvp->state; | 115 | enum nvram_parser_state st = nvp->state; |
116 | char c; | 116 | char c; |
117 | 117 | ||
118 | c = nvp->fwnv->data[nvp->pos]; | 118 | c = nvp->data[nvp->pos]; |
119 | if (c == '=') { | 119 | if (c == '=') { |
120 | /* ignore RAW1 by treating as comment */ | 120 | /* ignore RAW1 by treating as comment */ |
121 | if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0) | 121 | if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0) |
122 | st = COMMENT; | 122 | st = COMMENT; |
123 | else | 123 | else |
124 | st = VALUE; | 124 | st = VALUE; |
125 | if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0) | 125 | if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0) |
126 | nvp->multi_dev_v1 = true; | 126 | nvp->multi_dev_v1 = true; |
127 | if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0) | 127 | if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0) |
128 | nvp->multi_dev_v2 = true; | 128 | nvp->multi_dev_v2 = true; |
129 | } else if (!is_nvram_char(c) || c == ' ') { | 129 | } else if (!is_nvram_char(c) || c == ' ') { |
130 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", | 130 | 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) | |||
145 | char *ekv; | 145 | char *ekv; |
146 | u32 cplen; | 146 | u32 cplen; |
147 | 147 | ||
148 | c = nvp->fwnv->data[nvp->pos]; | 148 | c = nvp->data[nvp->pos]; |
149 | if (!is_nvram_char(c)) { | 149 | if (!is_nvram_char(c)) { |
150 | /* key,value pair complete */ | 150 | /* key,value pair complete */ |
151 | ekv = (u8 *)&nvp->fwnv->data[nvp->pos]; | 151 | ekv = (u8 *)&nvp->data[nvp->pos]; |
152 | skv = (u8 *)&nvp->fwnv->data[nvp->entry]; | 152 | skv = (u8 *)&nvp->data[nvp->entry]; |
153 | cplen = ekv - skv; | 153 | cplen = ekv - skv; |
154 | if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE) | 154 | if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE) |
155 | return END; | 155 | return END; |
@@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_parser *nvp) | |||
170 | { | 170 | { |
171 | char *eoc, *sol; | 171 | char *eoc, *sol; |
172 | 172 | ||
173 | sol = (char *)&nvp->fwnv->data[nvp->pos]; | 173 | sol = (char *)&nvp->data[nvp->pos]; |
174 | eoc = strchr(sol, '\n'); | 174 | eoc = strchr(sol, '\n'); |
175 | if (!eoc) { | 175 | if (!eoc) { |
176 | eoc = strchr(sol, '\0'); | 176 | eoc = strchr(sol, '\0'); |
@@ -201,17 +201,17 @@ static enum nvram_parser_state | |||
201 | }; | 201 | }; |
202 | 202 | ||
203 | static int brcmf_init_nvram_parser(struct nvram_parser *nvp, | 203 | static int brcmf_init_nvram_parser(struct nvram_parser *nvp, |
204 | const struct firmware *nv) | 204 | const u8 *data, size_t data_len) |
205 | { | 205 | { |
206 | size_t size; | 206 | size_t size; |
207 | 207 | ||
208 | memset(nvp, 0, sizeof(*nvp)); | 208 | memset(nvp, 0, sizeof(*nvp)); |
209 | nvp->fwnv = nv; | 209 | nvp->data = data; |
210 | /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */ | 210 | /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */ |
211 | if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE) | 211 | if (data_len > BRCMF_FW_MAX_NVRAM_SIZE) |
212 | size = BRCMF_FW_MAX_NVRAM_SIZE; | 212 | size = BRCMF_FW_MAX_NVRAM_SIZE; |
213 | else | 213 | else |
214 | size = nv->size; | 214 | size = data_len; |
215 | /* Alloc for extra 0 byte + roundup by 4 + length field */ | 215 | /* Alloc for extra 0 byte + roundup by 4 + length field */ |
216 | size += 1 + 3 + sizeof(u32); | 216 | size += 1 + 3 + sizeof(u32); |
217 | nvp->nvram = kzalloc(size, GFP_KERNEL); | 217 | nvp->nvram = kzalloc(size, GFP_KERNEL); |
@@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, | |||
232 | u16 bus_nr) | 232 | u16 bus_nr) |
233 | { | 233 | { |
234 | /* Device path with a leading '=' key-value separator */ | 234 | /* Device path with a leading '=' key-value separator */ |
235 | char pci_path[] = "=pci/?/?"; | ||
236 | size_t pci_len; | ||
235 | char pcie_path[] = "=pcie/?/?"; | 237 | char pcie_path[] = "=pcie/?/?"; |
236 | size_t pcie_len; | 238 | size_t pcie_len; |
237 | 239 | ||
@@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, | |||
251 | /* First search for the devpathX and see if it is the configuration | 253 | /* First search for the devpathX and see if it is the configuration |
252 | * for domain_nr/bus_nr. Search complete nvp | 254 | * for domain_nr/bus_nr. Search complete nvp |
253 | */ | 255 | */ |
256 | snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr, | ||
257 | bus_nr); | ||
258 | pci_len = strlen(pci_path); | ||
254 | snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr, | 259 | snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr, |
255 | bus_nr); | 260 | bus_nr); |
256 | pcie_len = strlen(pcie_path); | 261 | pcie_len = strlen(pcie_path); |
@@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, | |||
260 | /* Format: devpathX=pcie/Y/Z/ | 265 | /* Format: devpathX=pcie/Y/Z/ |
261 | * Y = domain_nr, Z = bus_nr, X = virtual ID | 266 | * Y = domain_nr, Z = bus_nr, X = virtual ID |
262 | */ | 267 | */ |
263 | if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) && | 268 | if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 && |
264 | (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) { | 269 | (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) || |
270 | !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) { | ||
265 | id = nvp->nvram[i + 7] - '0'; | 271 | id = nvp->nvram[i + 7] - '0'; |
266 | found = true; | 272 | found = true; |
267 | break; | 273 | break; |
@@ -356,18 +362,18 @@ fail: | |||
356 | * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. | 362 | * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. |
357 | * End of buffer is completed with token identifying length of buffer. | 363 | * End of buffer is completed with token identifying length of buffer. |
358 | */ | 364 | */ |
359 | static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length, | 365 | static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, |
360 | u16 domain_nr, u16 bus_nr) | 366 | u32 *new_length, u16 domain_nr, u16 bus_nr) |
361 | { | 367 | { |
362 | struct nvram_parser nvp; | 368 | struct nvram_parser nvp; |
363 | u32 pad; | 369 | u32 pad; |
364 | u32 token; | 370 | u32 token; |
365 | __le32 token_le; | 371 | __le32 token_le; |
366 | 372 | ||
367 | if (brcmf_init_nvram_parser(&nvp, nv) < 0) | 373 | if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0) |
368 | return NULL; | 374 | return NULL; |
369 | 375 | ||
370 | while (nvp.pos < nv->size) { | 376 | while (nvp.pos < data_len) { |
371 | nvp.state = nv_parser_states[nvp.state](&nvp); | 377 | nvp.state = nv_parser_states[nvp.state](&nvp); |
372 | if (nvp.state == END) | 378 | if (nvp.state == END) |
373 | break; | 379 | break; |
@@ -426,7 +432,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) | |||
426 | goto fail; | 432 | goto fail; |
427 | 433 | ||
428 | if (fw) { | 434 | if (fw) { |
429 | nvram = brcmf_fw_nvram_strip(fw, &nvram_length, | 435 | nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length, |
430 | fwctx->domain_nr, fwctx->bus_nr); | 436 | fwctx->domain_nr, fwctx->bus_nr); |
431 | release_firmware(fw); | 437 | release_firmware(fw); |
432 | if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) | 438 | if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 374920965108..297911f38fa0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -32,7 +32,11 @@ | |||
32 | #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ | 32 | #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ |
33 | #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 | 33 | #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 |
34 | 34 | ||
35 | #define BRCMF_STA_ASSOC 0x10 /* Associated */ | 35 | #define BRCMF_STA_WME 0x00000002 /* WMM association */ |
36 | #define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */ | ||
37 | #define BRCMF_STA_ASSOC 0x00000010 /* Associated */ | ||
38 | #define BRCMF_STA_AUTHO 0x00000020 /* Authorized */ | ||
39 | #define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */ | ||
36 | 40 | ||
37 | /* size of brcmf_scan_params not including variable length array */ | 41 | /* size of brcmf_scan_params not including variable length array */ |
38 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 | 42 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 |
@@ -113,6 +117,7 @@ | |||
113 | #define BRCMF_WOWL_MAXPATTERNSIZE 128 | 117 | #define BRCMF_WOWL_MAXPATTERNSIZE 128 |
114 | 118 | ||
115 | #define BRCMF_COUNTRY_BUF_SZ 4 | 119 | #define BRCMF_COUNTRY_BUF_SZ 4 |
120 | #define BRCMF_ANT_MAX 4 | ||
116 | 121 | ||
117 | /* join preference types for join_pref iovar */ | 122 | /* join preference types for join_pref iovar */ |
118 | enum brcmf_join_pref_types { | 123 | enum brcmf_join_pref_types { |
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le { | |||
456 | }; | 461 | }; |
457 | 462 | ||
458 | struct brcmf_sta_info_le { | 463 | struct brcmf_sta_info_le { |
459 | __le16 ver; /* version of this struct */ | 464 | __le16 ver; /* version of this struct */ |
460 | __le16 len; /* length in bytes of this structure */ | 465 | __le16 len; /* length in bytes of this structure */ |
461 | __le16 cap; /* sta's advertised capabilities */ | 466 | __le16 cap; /* sta's advertised capabilities */ |
462 | __le32 flags; /* flags defined below */ | 467 | __le32 flags; /* flags defined below */ |
463 | __le32 idle; /* time since data pkt rx'd from sta */ | 468 | __le32 idle; /* time since data pkt rx'd from sta */ |
464 | u8 ea[ETH_ALEN]; /* Station address */ | 469 | u8 ea[ETH_ALEN]; /* Station address */ |
465 | __le32 count; /* # rates in this set */ | 470 | __le32 count; /* # rates in this set */ |
466 | u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ | 471 | u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ |
467 | /* w/hi bit set if basic */ | 472 | /* w/hi bit set if basic */ |
468 | __le32 in; /* seconds elapsed since associated */ | 473 | __le32 in; /* seconds elapsed since associated */ |
469 | __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ | 474 | __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ |
470 | __le32 tx_pkts; /* # of packets transmitted */ | 475 | __le32 tx_pkts; /* # of packets transmitted */ |
471 | __le32 tx_failures; /* # of packets failed */ | 476 | __le32 tx_failures; /* # of packets failed */ |
472 | __le32 rx_ucast_pkts; /* # of unicast packets received */ | 477 | __le32 rx_ucast_pkts; /* # of unicast packets received */ |
473 | __le32 rx_mcast_pkts; /* # of multicast packets received */ | 478 | __le32 rx_mcast_pkts; /* # of multicast packets received */ |
474 | __le32 tx_rate; /* Rate of last successful tx frame */ | 479 | __le32 tx_rate; /* Rate of last successful tx frame */ |
475 | __le32 rx_rate; /* Rate of last successful rx frame */ | 480 | __le32 rx_rate; /* Rate of last successful rx frame */ |
476 | __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ | 481 | __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ |
477 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ | 482 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ |
483 | __le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */ | ||
484 | __le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */ | ||
485 | __le32 tx_mcast_pkts; /* # of mcast pkts txed */ | ||
486 | __le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */ | ||
487 | __le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */ | ||
488 | __le64 tx_ucast_bytes; /* data bytes txed (ucast) */ | ||
489 | __le64 tx_mcast_bytes; /* # data bytes txed (mcast) */ | ||
490 | __le64 rx_ucast_bytes; /* data bytes recvd (ucast) */ | ||
491 | __le64 rx_mcast_bytes; /* data bytes recvd (mcast) */ | ||
492 | s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */ | ||
493 | s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */ | ||
494 | __le16 aid; /* association ID */ | ||
495 | __le16 ht_capabilities; /* advertised ht caps */ | ||
496 | __le16 vht_flags; /* converted vht flags */ | ||
497 | __le32 tx_pkts_retry_cnt; /* # of frames where a retry was | ||
498 | * exhausted. | ||
499 | */ | ||
500 | __le32 tx_pkts_retry_exhausted; /* # of user frames where a retry | ||
501 | * was exhausted | ||
502 | */ | ||
503 | s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last | ||
504 | * received data frame. | ||
505 | */ | ||
506 | /* TX WLAN retry/failure statistics: | ||
507 | * Separated for host requested frames and locally generated frames. | ||
508 | * Include unicast frame only where the retries/failures can be counted. | ||
509 | */ | ||
510 | __le32 tx_pkts_total; /* # user frames sent successfully */ | ||
511 | __le32 tx_pkts_retries; /* # user frames retries */ | ||
512 | __le32 tx_pkts_fw_total; /* # FW generated sent successfully */ | ||
513 | __le32 tx_pkts_fw_retries; /* # retries for FW generated frames */ | ||
514 | __le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry | ||
515 | * was exhausted | ||
516 | */ | ||
517 | __le32 rx_pkts_retried; /* # rx with retry bit set */ | ||
518 | __le32 tx_rate_fallback; /* lowest fallback TX rate */ | ||
478 | }; | 519 | }; |
479 | 520 | ||
480 | struct brcmf_chanspec_list { | 521 | struct brcmf_chanspec_list { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 1b47de067d25..898c3801e658 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | |||
@@ -75,6 +75,8 @@ | |||
75 | 75 | ||
76 | #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96 | 76 | #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96 |
77 | #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 | 77 | #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 |
78 | #define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48 | ||
79 | |||
78 | 80 | ||
79 | struct msgbuf_common_hdr { | 81 | struct msgbuf_common_hdr { |
80 | u8 msgtype; | 82 | u8 msgtype; |
@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf, | |||
1257 | { | 1259 | { |
1258 | void *buf; | 1260 | void *buf; |
1259 | u16 count; | 1261 | u16 count; |
1262 | u16 processed; | ||
1260 | 1263 | ||
1261 | again: | 1264 | again: |
1262 | buf = brcmf_commonring_get_read_ptr(commonring, &count); | 1265 | buf = brcmf_commonring_get_read_ptr(commonring, &count); |
1263 | if (buf == NULL) | 1266 | if (buf == NULL) |
1264 | return; | 1267 | return; |
1265 | 1268 | ||
1269 | processed = 0; | ||
1266 | while (count) { | 1270 | while (count) { |
1267 | brcmf_msgbuf_process_msgtype(msgbuf, | 1271 | brcmf_msgbuf_process_msgtype(msgbuf, |
1268 | buf + msgbuf->rx_dataoffset); | 1272 | buf + msgbuf->rx_dataoffset); |
1269 | buf += brcmf_commonring_len_item(commonring); | 1273 | buf += brcmf_commonring_len_item(commonring); |
1274 | processed++; | ||
1275 | if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) { | ||
1276 | brcmf_commonring_read_complete(commonring, processed); | ||
1277 | processed = 0; | ||
1278 | } | ||
1270 | count--; | 1279 | count--; |
1271 | } | 1280 | } |
1272 | brcmf_commonring_read_complete(commonring); | 1281 | if (processed) |
1282 | brcmf_commonring_read_complete(commonring, processed); | ||
1273 | 1283 | ||
1274 | if (commonring->r_ptr == 0) | 1284 | if (commonring->r_ptr == 0) |
1275 | goto again; | 1285 | goto again; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 710fbe570eb2..a9ba775a24c1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/rtnetlink.h> | ||
19 | #include <net/cfg80211.h> | 20 | #include <net/cfg80211.h> |
20 | 21 | ||
21 | #include <brcmu_wifi.h> | 22 | #include <brcmu_wifi.h> |
@@ -1908,105 +1909,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1908 | 1909 | ||
1909 | 1910 | ||
1910 | /** | 1911 | /** |
1911 | * brcmf_p2p_attach() - attach for P2P. | ||
1912 | * | ||
1913 | * @cfg: driver private data for cfg80211 interface. | ||
1914 | */ | ||
1915 | s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | ||
1916 | { | ||
1917 | struct brcmf_if *pri_ifp; | ||
1918 | struct brcmf_if *p2p_ifp; | ||
1919 | struct brcmf_cfg80211_vif *p2p_vif; | ||
1920 | struct brcmf_p2p_info *p2p; | ||
1921 | struct brcmf_pub *drvr; | ||
1922 | s32 bssidx; | ||
1923 | s32 err = 0; | ||
1924 | |||
1925 | p2p = &cfg->p2p; | ||
1926 | p2p->cfg = cfg; | ||
1927 | |||
1928 | drvr = cfg->pub; | ||
1929 | |||
1930 | pri_ifp = drvr->iflist[0]; | ||
1931 | p2p_ifp = drvr->iflist[1]; | ||
1932 | |||
1933 | p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; | ||
1934 | |||
1935 | if (p2p_ifp) { | ||
1936 | p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, | ||
1937 | false); | ||
1938 | if (IS_ERR(p2p_vif)) { | ||
1939 | brcmf_err("could not create discovery vif\n"); | ||
1940 | err = -ENOMEM; | ||
1941 | goto exit; | ||
1942 | } | ||
1943 | |||
1944 | p2p_vif->ifp = p2p_ifp; | ||
1945 | p2p_ifp->vif = p2p_vif; | ||
1946 | p2p_vif->wdev.netdev = p2p_ifp->ndev; | ||
1947 | p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; | ||
1948 | SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); | ||
1949 | |||
1950 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
1951 | |||
1952 | brcmf_p2p_generate_bss_mac(p2p, NULL); | ||
1953 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
1954 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | ||
1955 | |||
1956 | /* Initialize P2P Discovery in the firmware */ | ||
1957 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | ||
1958 | if (err < 0) { | ||
1959 | brcmf_err("set p2p_disc error\n"); | ||
1960 | brcmf_free_vif(p2p_vif); | ||
1961 | goto exit; | ||
1962 | } | ||
1963 | /* obtain bsscfg index for P2P discovery */ | ||
1964 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | ||
1965 | if (err < 0) { | ||
1966 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
1967 | brcmf_free_vif(p2p_vif); | ||
1968 | goto exit; | ||
1969 | } | ||
1970 | /* Verify that firmware uses same bssidx as driver !! */ | ||
1971 | if (p2p_ifp->bssidx != bssidx) { | ||
1972 | brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", | ||
1973 | bssidx, p2p_ifp->bssidx); | ||
1974 | brcmf_free_vif(p2p_vif); | ||
1975 | goto exit; | ||
1976 | } | ||
1977 | |||
1978 | init_completion(&p2p->send_af_done); | ||
1979 | INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); | ||
1980 | init_completion(&p2p->afx_hdl.act_frm_scan); | ||
1981 | init_completion(&p2p->wait_next_af); | ||
1982 | } | ||
1983 | exit: | ||
1984 | return err; | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | /** | ||
1989 | * brcmf_p2p_detach() - detach P2P. | ||
1990 | * | ||
1991 | * @p2p: P2P specific data. | ||
1992 | */ | ||
1993 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) | ||
1994 | { | ||
1995 | struct brcmf_cfg80211_vif *vif; | ||
1996 | |||
1997 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | ||
1998 | if (vif != NULL) { | ||
1999 | brcmf_p2p_cancel_remain_on_channel(vif->ifp); | ||
2000 | brcmf_p2p_deinit_discovery(p2p); | ||
2001 | /* remove discovery interface */ | ||
2002 | brcmf_free_vif(vif); | ||
2003 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | ||
2004 | } | ||
2005 | /* just set it all to zero */ | ||
2006 | memset(p2p, 0, sizeof(*p2p)); | ||
2007 | } | ||
2008 | |||
2009 | /** | ||
2010 | * brcmf_p2p_get_current_chanspec() - Get current operation channel. | 1912 | * brcmf_p2p_get_current_chanspec() - Get current operation channel. |
2011 | * | 1913 | * |
2012 | * @p2p: P2P specific data. | 1914 | * @p2p: P2P specific data. |
@@ -2238,6 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p, | |||
2238 | { | 2140 | { |
2239 | cfg80211_unregister_wdev(&vif->wdev); | 2141 | cfg80211_unregister_wdev(&vif->wdev); |
2240 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | 2142 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; |
2143 | brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx); | ||
2241 | brcmf_free_vif(vif); | 2144 | brcmf_free_vif(vif); |
2242 | } | 2145 | } |
2243 | 2146 | ||
@@ -2364,6 +2267,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2364 | break; | 2267 | break; |
2365 | 2268 | ||
2366 | case NL80211_IFTYPE_P2P_DEVICE: | 2269 | case NL80211_IFTYPE_P2P_DEVICE: |
2270 | brcmf_p2p_cancel_remain_on_channel(vif->ifp); | ||
2271 | brcmf_p2p_deinit_discovery(p2p); | ||
2367 | brcmf_p2p_delete_p2pdev(p2p, vif); | 2272 | brcmf_p2p_delete_p2pdev(p2p, vif); |
2368 | return 0; | 2273 | return 0; |
2369 | default: | 2274 | default: |
@@ -2425,3 +2330,103 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2425 | clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | 2330 | clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); |
2426 | mutex_unlock(&cfg->usr_sync); | 2331 | mutex_unlock(&cfg->usr_sync); |
2427 | } | 2332 | } |
2333 | |||
2334 | /** | ||
2335 | * brcmf_p2p_attach() - attach for P2P. | ||
2336 | * | ||
2337 | * @cfg: driver private data for cfg80211 interface. | ||
2338 | */ | ||
2339 | s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | ||
2340 | { | ||
2341 | struct brcmf_if *pri_ifp; | ||
2342 | struct brcmf_if *p2p_ifp; | ||
2343 | struct brcmf_cfg80211_vif *p2p_vif; | ||
2344 | struct brcmf_p2p_info *p2p; | ||
2345 | struct brcmf_pub *drvr; | ||
2346 | s32 bssidx; | ||
2347 | s32 err = 0; | ||
2348 | |||
2349 | p2p = &cfg->p2p; | ||
2350 | p2p->cfg = cfg; | ||
2351 | |||
2352 | drvr = cfg->pub; | ||
2353 | |||
2354 | pri_ifp = drvr->iflist[0]; | ||
2355 | p2p_ifp = drvr->iflist[1]; | ||
2356 | |||
2357 | p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; | ||
2358 | |||
2359 | if (p2p_ifp) { | ||
2360 | p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, | ||
2361 | false); | ||
2362 | if (IS_ERR(p2p_vif)) { | ||
2363 | brcmf_err("could not create discovery vif\n"); | ||
2364 | err = -ENOMEM; | ||
2365 | goto exit; | ||
2366 | } | ||
2367 | |||
2368 | p2p_vif->ifp = p2p_ifp; | ||
2369 | p2p_ifp->vif = p2p_vif; | ||
2370 | p2p_vif->wdev.netdev = p2p_ifp->ndev; | ||
2371 | p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; | ||
2372 | SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); | ||
2373 | |||
2374 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
2375 | |||
2376 | brcmf_p2p_generate_bss_mac(p2p, NULL); | ||
2377 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
2378 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | ||
2379 | |||
2380 | /* Initialize P2P Discovery in the firmware */ | ||
2381 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | ||
2382 | if (err < 0) { | ||
2383 | brcmf_err("set p2p_disc error\n"); | ||
2384 | brcmf_free_vif(p2p_vif); | ||
2385 | goto exit; | ||
2386 | } | ||
2387 | /* obtain bsscfg index for P2P discovery */ | ||
2388 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | ||
2389 | if (err < 0) { | ||
2390 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
2391 | brcmf_free_vif(p2p_vif); | ||
2392 | goto exit; | ||
2393 | } | ||
2394 | /* Verify that firmware uses same bssidx as driver !! */ | ||
2395 | if (p2p_ifp->bssidx != bssidx) { | ||
2396 | brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", | ||
2397 | bssidx, p2p_ifp->bssidx); | ||
2398 | brcmf_free_vif(p2p_vif); | ||
2399 | goto exit; | ||
2400 | } | ||
2401 | |||
2402 | init_completion(&p2p->send_af_done); | ||
2403 | INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); | ||
2404 | init_completion(&p2p->afx_hdl.act_frm_scan); | ||
2405 | init_completion(&p2p->wait_next_af); | ||
2406 | } | ||
2407 | exit: | ||
2408 | return err; | ||
2409 | } | ||
2410 | |||
2411 | /** | ||
2412 | * brcmf_p2p_detach() - detach P2P. | ||
2413 | * | ||
2414 | * @p2p: P2P specific data. | ||
2415 | */ | ||
2416 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) | ||
2417 | { | ||
2418 | struct brcmf_cfg80211_vif *vif; | ||
2419 | |||
2420 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | ||
2421 | if (vif != NULL) { | ||
2422 | brcmf_p2p_cancel_remain_on_channel(vif->ifp); | ||
2423 | brcmf_p2p_deinit_discovery(p2p); | ||
2424 | /* remove discovery interface */ | ||
2425 | rtnl_lock(); | ||
2426 | brcmf_p2p_delete_p2pdev(p2p, vif); | ||
2427 | rtnl_unlock(); | ||
2428 | } | ||
2429 | /* just set it all to zero */ | ||
2430 | memset(p2p, 0, sizeof(*p2p)); | ||
2431 | } | ||
2432 | |||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 37a2624d7bba..3a98c4306d1d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c | |||
@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value) | |||
1629 | 1629 | ||
1630 | static int brcmf_pcie_buscoreprep(void *ctx) | 1630 | static int brcmf_pcie_buscoreprep(void *ctx) |
1631 | { | 1631 | { |
1632 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; | 1632 | return brcmf_pcie_get_resource(ctx); |
1633 | int err; | ||
1634 | |||
1635 | err = brcmf_pcie_get_resource(devinfo); | ||
1636 | if (err == 0) { | ||
1637 | /* Set CC watchdog to reset all the cores on the chip to bring | ||
1638 | * back dongle to a sane state. | ||
1639 | */ | ||
1640 | brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE, | ||
1641 | watchdog), 4); | ||
1642 | msleep(100); | ||
1643 | } | ||
1644 | |||
1645 | return err; | ||
1646 | } | 1633 | } |
1647 | 1634 | ||
1648 | 1635 | ||
@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev) | |||
1824 | brcmf_pcie_intr_disable(devinfo); | 1811 | brcmf_pcie_intr_disable(devinfo); |
1825 | 1812 | ||
1826 | brcmf_detach(&pdev->dev); | 1813 | brcmf_detach(&pdev->dev); |
1814 | brcmf_pcie_reset_device(devinfo); | ||
1827 | 1815 | ||
1828 | kfree(bus->bus_priv.pcie); | 1816 | kfree(bus->bus_priv.pcie); |
1829 | kfree(bus->msgbuf->flowrings); | 1817 | kfree(bus->msgbuf->flowrings); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index bf7a8b1ad914..d36f5f3d931b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c | |||
@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2820 | struct brcmf_sdio *bus = sdiodev->bus; | 2820 | struct brcmf_sdio *bus = sdiodev->bus; |
2821 | 2821 | ||
2822 | brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len); | 2822 | brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len); |
2823 | if (sdiodev->state != BRCMF_SDIOD_DATA) | ||
2824 | return -EIO; | ||
2823 | 2825 | ||
2824 | /* Add space for the header */ | 2826 | /* Add space for the header */ |
2825 | skb_push(pkt, bus->tx_hdrlen); | 2827 | skb_push(pkt, bus->tx_hdrlen); |
@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2948 | int ret; | 2950 | int ret; |
2949 | 2951 | ||
2950 | brcmf_dbg(TRACE, "Enter\n"); | 2952 | brcmf_dbg(TRACE, "Enter\n"); |
2953 | if (sdiodev->state != BRCMF_SDIOD_DATA) | ||
2954 | return -EIO; | ||
2951 | 2955 | ||
2952 | /* Send from dpc */ | 2956 | /* Send from dpc */ |
2953 | bus->ctrl_frame_buf = msg; | 2957 | bus->ctrl_frame_buf = msg; |
@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3238 | struct brcmf_sdio *bus = sdiodev->bus; | 3242 | struct brcmf_sdio *bus = sdiodev->bus; |
3239 | 3243 | ||
3240 | brcmf_dbg(TRACE, "Enter\n"); | 3244 | brcmf_dbg(TRACE, "Enter\n"); |
3245 | if (sdiodev->state != BRCMF_SDIOD_DATA) | ||
3246 | return -EIO; | ||
3241 | 3247 | ||
3242 | /* Wait until control frame is available */ | 3248 | /* Wait until control frame is available */ |
3243 | timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending); | 3249 | timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending); |
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c index 9c9e1288644b..7217da4f1543 100644 --- a/drivers/net/wireless/mediatek/mt7601u/dma.c +++ b/drivers/net/wireless/mediatek/mt7601u/dma.c | |||
@@ -34,56 +34,32 @@ static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len) | |||
34 | 34 | ||
35 | static struct sk_buff * | 35 | static struct sk_buff * |
36 | mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi, | 36 | mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi, |
37 | u8 *data, u32 seg_len) | 37 | void *data, u32 seg_len, u32 truesize, struct page *p) |
38 | { | 38 | { |
39 | struct sk_buff *skb; | 39 | struct sk_buff *skb; |
40 | u32 true_len; | 40 | u32 true_len, hdr_len = 0, copy, frag; |
41 | 41 | ||
42 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) | 42 | skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC); |
43 | seg_len -= 2; | ||
44 | |||
45 | skb = alloc_skb(seg_len, GFP_ATOMIC); | ||
46 | if (!skb) | ||
47 | return NULL; | ||
48 | |||
49 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) { | ||
50 | int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len); | ||
51 | |||
52 | memcpy(skb_put(skb, hdr_len), data, hdr_len); | ||
53 | data += hdr_len + 2; | ||
54 | seg_len -= hdr_len; | ||
55 | } | ||
56 | |||
57 | memcpy(skb_put(skb, seg_len), data, seg_len); | ||
58 | |||
59 | true_len = mt76_mac_process_rx(dev, skb, skb->data, rxwi); | ||
60 | skb_trim(skb, true_len); | ||
61 | |||
62 | return skb; | ||
63 | } | ||
64 | |||
65 | static struct sk_buff * | ||
66 | mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev, | ||
67 | struct mt7601u_rxwi *rxwi, void *data, | ||
68 | u32 seg_len, u32 truesize, struct page *p) | ||
69 | { | ||
70 | unsigned int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len); | ||
71 | unsigned int true_len, copy, frag; | ||
72 | struct sk_buff *skb; | ||
73 | |||
74 | skb = alloc_skb(128, GFP_ATOMIC); | ||
75 | if (!skb) | 43 | if (!skb) |
76 | return NULL; | 44 | return NULL; |
77 | 45 | ||
78 | true_len = mt76_mac_process_rx(dev, skb, data, rxwi); | 46 | true_len = mt76_mac_process_rx(dev, skb, data, rxwi); |
47 | if (!true_len || true_len > seg_len) | ||
48 | goto bad_frame; | ||
49 | |||
50 | hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len); | ||
51 | if (!hdr_len) | ||
52 | goto bad_frame; | ||
79 | 53 | ||
80 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) { | 54 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) { |
81 | memcpy(skb_put(skb, hdr_len), data, hdr_len); | 55 | memcpy(skb_put(skb, hdr_len), data, hdr_len); |
56 | |||
82 | data += hdr_len + 2; | 57 | data += hdr_len + 2; |
83 | true_len -= hdr_len; | 58 | true_len -= hdr_len; |
84 | hdr_len = 0; | 59 | hdr_len = 0; |
85 | } | 60 | } |
86 | 61 | ||
62 | /* If not doing paged RX allocated skb will always have enough space */ | ||
87 | copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8; | 63 | copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8; |
88 | frag = true_len - copy; | 64 | frag = true_len - copy; |
89 | 65 | ||
@@ -97,10 +73,16 @@ mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev, | |||
97 | } | 73 | } |
98 | 74 | ||
99 | return skb; | 75 | return skb; |
76 | |||
77 | bad_frame: | ||
78 | dev_err_ratelimited(dev->dev, "Error: incorrect frame len:%u hdr:%u\n", | ||
79 | true_len, hdr_len); | ||
80 | dev_kfree_skb(skb); | ||
81 | return NULL; | ||
100 | } | 82 | } |
101 | 83 | ||
102 | static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data, | 84 | static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data, |
103 | u32 seg_len, struct page *p, bool paged) | 85 | u32 seg_len, struct page *p) |
104 | { | 86 | { |
105 | struct sk_buff *skb; | 87 | struct sk_buff *skb; |
106 | struct mt7601u_rxwi *rxwi; | 88 | struct mt7601u_rxwi *rxwi; |
@@ -126,11 +108,7 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data, | |||
126 | 108 | ||
127 | trace_mt_rx(dev, rxwi, fce_info); | 109 | trace_mt_rx(dev, rxwi, fce_info); |
128 | 110 | ||
129 | if (paged) | 111 | skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len, truesize, p); |
130 | skb = mt7601u_rx_skb_from_seg_paged(dev, rxwi, data, seg_len, | ||
131 | truesize, p); | ||
132 | else | ||
133 | skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len); | ||
134 | if (!skb) | 112 | if (!skb) |
135 | return; | 113 | return; |
136 | 114 | ||
@@ -158,23 +136,17 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e) | |||
158 | u32 seg_len, data_len = e->urb->actual_length; | 136 | u32 seg_len, data_len = e->urb->actual_length; |
159 | u8 *data = page_address(e->p); | 137 | u8 *data = page_address(e->p); |
160 | struct page *new_p = NULL; | 138 | struct page *new_p = NULL; |
161 | bool paged = true; | ||
162 | int cnt = 0; | 139 | int cnt = 0; |
163 | 140 | ||
164 | if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state)) | 141 | if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state)) |
165 | return; | 142 | return; |
166 | 143 | ||
167 | /* Copy if there is very little data in the buffer. */ | 144 | /* Copy if there is very little data in the buffer. */ |
168 | if (data_len < 512) { | 145 | if (data_len > 512) |
169 | paged = false; | ||
170 | } else { | ||
171 | new_p = dev_alloc_pages(MT_RX_ORDER); | 146 | new_p = dev_alloc_pages(MT_RX_ORDER); |
172 | if (!new_p) | ||
173 | paged = false; | ||
174 | } | ||
175 | 147 | ||
176 | while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) { | 148 | while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) { |
177 | mt7601u_rx_process_seg(dev, data, seg_len, e->p, paged); | 149 | mt7601u_rx_process_seg(dev, data, seg_len, new_p ? e->p : NULL); |
178 | 150 | ||
179 | data_len -= seg_len; | 151 | data_len -= seg_len; |
180 | data += seg_len; | 152 | data += seg_len; |
@@ -182,9 +154,9 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e) | |||
182 | } | 154 | } |
183 | 155 | ||
184 | if (cnt > 1) | 156 | if (cnt > 1) |
185 | trace_mt_rx_dma_aggr(dev, cnt, paged); | 157 | trace_mt_rx_dma_aggr(dev, cnt, !!new_p); |
186 | 158 | ||
187 | if (paged) { | 159 | if (new_p) { |
188 | /* we have one extra ref from the allocator */ | 160 | /* we have one extra ref from the allocator */ |
189 | __free_pages(e->p, MT_RX_ORDER); | 161 | __free_pages(e->p, MT_RX_ORDER); |
190 | 162 | ||
diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.c b/drivers/net/wireless/mediatek/mt7601u/eeprom.c index ce3837f270f0..8d8ee0344f7b 100644 --- a/drivers/net/wireless/mediatek/mt7601u/eeprom.c +++ b/drivers/net/wireless/mediatek/mt7601u/eeprom.c | |||
@@ -277,6 +277,10 @@ mt7601u_extra_power_over_mac(struct mt7601u_dev *dev) | |||
277 | static void | 277 | static void |
278 | mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value) | 278 | mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value) |
279 | { | 279 | { |
280 | /* Invalid? Note: vendor driver does not handle this */ | ||
281 | if (value == 0xff) | ||
282 | return; | ||
283 | |||
280 | rate->raw = s6_validate(value); | 284 | rate->raw = s6_validate(value); |
281 | rate->bw20 = s6_to_int(value); | 285 | rate->bw20 = s6_to_int(value); |
282 | /* Note: vendor driver does cap the value to s6 right away */ | 286 | /* Note: vendor driver does cap the value to s6 right away */ |
diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c index ca1ea2e55ff4..df3dd56199a7 100644 --- a/drivers/net/wireless/mediatek/mt7601u/init.c +++ b/drivers/net/wireless/mediatek/mt7601u/init.c | |||
@@ -427,6 +427,9 @@ err: | |||
427 | 427 | ||
428 | void mt7601u_cleanup(struct mt7601u_dev *dev) | 428 | void mt7601u_cleanup(struct mt7601u_dev *dev) |
429 | { | 429 | { |
430 | if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state)) | ||
431 | return; | ||
432 | |||
430 | mt7601u_stop_hardware(dev); | 433 | mt7601u_stop_hardware(dev); |
431 | mt7601u_dma_cleanup(dev); | 434 | mt7601u_dma_cleanup(dev); |
432 | mt7601u_mcu_cmd_deinit(dev); | 435 | mt7601u_mcu_cmd_deinit(dev); |
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c index c161bcc6a7fa..7514bce1ac91 100644 --- a/drivers/net/wireless/mediatek/mt7601u/mac.c +++ b/drivers/net/wireless/mediatek/mt7601u/mac.c | |||
@@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb, | |||
450 | { | 450 | { |
451 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 451 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
452 | struct mt7601u_rxwi *rxwi = rxi; | 452 | struct mt7601u_rxwi *rxwi = rxi; |
453 | u32 ctl = le32_to_cpu(rxwi->ctl); | 453 | u32 len, ctl = le32_to_cpu(rxwi->ctl); |
454 | u16 rate = le16_to_cpu(rxwi->rate); | 454 | u16 rate = le16_to_cpu(rxwi->rate); |
455 | int rssi; | 455 | int rssi; |
456 | 456 | ||
457 | len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl); | ||
458 | if (len < 10) | ||
459 | return 0; | ||
460 | |||
457 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) { | 461 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) { |
458 | status->flag |= RX_FLAG_DECRYPTED; | 462 | status->flag |= RX_FLAG_DECRYPTED; |
459 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | 463 | 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, | |||
474 | dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8); | 478 | dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8); |
475 | spin_unlock_bh(&dev->con_mon_lock); | 479 | spin_unlock_bh(&dev->con_mon_lock); |
476 | 480 | ||
477 | return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl); | 481 | return len; |
478 | } | 482 | } |
479 | 483 | ||
480 | static enum mt76_cipher_type | 484 | static enum mt76_cipher_type |
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index ced82abb414f..169384b48b27 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c | |||
@@ -119,6 +119,7 @@ mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | |||
119 | 119 | ||
120 | dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS; | 120 | dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS; |
121 | 121 | ||
122 | MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC); | ||
122 | MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR); | 123 | MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR); |
123 | MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR); | 124 | MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR); |
124 | MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK | | 125 | MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK | |
diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c index 99e2b3997bfa..54dba4001865 100644 --- a/drivers/net/wireless/mediatek/mt7601u/usb.c +++ b/drivers/net/wireless/mediatek/mt7601u/usb.c | |||
@@ -338,8 +338,15 @@ static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state) | |||
338 | static int mt7601u_resume(struct usb_interface *usb_intf) | 338 | static int mt7601u_resume(struct usb_interface *usb_intf) |
339 | { | 339 | { |
340 | struct mt7601u_dev *dev = usb_get_intfdata(usb_intf); | 340 | struct mt7601u_dev *dev = usb_get_intfdata(usb_intf); |
341 | int ret; | ||
342 | |||
343 | ret = mt7601u_init_hardware(dev); | ||
344 | if (ret) | ||
345 | return ret; | ||
346 | |||
347 | set_bit(MT7601U_STATE_INITIALIZED, &dev->state); | ||
341 | 348 | ||
342 | return mt7601u_init_hardware(dev); | 349 | return 0; |
343 | } | 350 | } |
344 | 351 | ||
345 | MODULE_DEVICE_TABLE(usb, mt7601u_device_table); | 352 | MODULE_DEVICE_TABLE(usb, mt7601u_device_table); |
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c index 65cd461c88db..71a1b580796f 100644 --- a/drivers/net/wireless/mwifiex/11h.c +++ b/drivers/net/wireless/mwifiex/11h.c | |||
@@ -161,19 +161,38 @@ int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, | |||
161 | cr_req->chan_desc.chan_width = radar_params->chandef->width; | 161 | cr_req->chan_desc.chan_width = radar_params->chandef->width; |
162 | cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms); | 162 | cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms); |
163 | 163 | ||
164 | mwifiex_dbg(priv->adapter, MSG, | 164 | if (radar_params->cac_time_ms) |
165 | "11h: issuing DFS Radar check for channel=%d\n", | 165 | mwifiex_dbg(priv->adapter, MSG, |
166 | radar_params->chandef->chan->hw_value); | 166 | "11h: issuing DFS Radar check for channel=%d\n", |
167 | radar_params->chandef->chan->hw_value); | ||
168 | else | ||
169 | mwifiex_dbg(priv->adapter, MSG, "cancelling CAC\n"); | ||
167 | 170 | ||
168 | return 0; | 171 | return 0; |
169 | } | 172 | } |
170 | 173 | ||
174 | int mwifiex_stop_radar_detection(struct mwifiex_private *priv, | ||
175 | struct cfg80211_chan_def *chandef) | ||
176 | { | ||
177 | struct mwifiex_radar_params radar_params; | ||
178 | |||
179 | memset(&radar_params, 0, sizeof(struct mwifiex_radar_params)); | ||
180 | radar_params.chandef = chandef; | ||
181 | radar_params.cac_time_ms = 0; | ||
182 | |||
183 | return mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST, | ||
184 | HostCmd_ACT_GEN_SET, 0, &radar_params, true); | ||
185 | } | ||
186 | |||
171 | /* This function is to abort ongoing CAC upon stopping AP operations | 187 | /* This function is to abort ongoing CAC upon stopping AP operations |
172 | * or during unload. | 188 | * or during unload. |
173 | */ | 189 | */ |
174 | void mwifiex_abort_cac(struct mwifiex_private *priv) | 190 | void mwifiex_abort_cac(struct mwifiex_private *priv) |
175 | { | 191 | { |
176 | if (priv->wdev.cac_started) { | 192 | if (priv->wdev.cac_started) { |
193 | if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef)) | ||
194 | mwifiex_dbg(priv->adapter, ERROR, | ||
195 | "failed to stop CAC in FW\n"); | ||
177 | mwifiex_dbg(priv->adapter, MSG, | 196 | mwifiex_dbg(priv->adapter, MSG, |
178 | "Aborting delayed work for CAC.\n"); | 197 | "Aborting delayed work for CAC.\n"); |
179 | cancel_delayed_work_sync(&priv->dfs_cac_work); | 198 | cancel_delayed_work_sync(&priv->dfs_cac_work); |
@@ -245,6 +264,9 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | |||
245 | if (le32_to_cpu(rdr_event->passed)) { | 264 | if (le32_to_cpu(rdr_event->passed)) { |
246 | mwifiex_dbg(priv->adapter, MSG, | 265 | mwifiex_dbg(priv->adapter, MSG, |
247 | "radar detected; indicating kernel\n"); | 266 | "radar detected; indicating kernel\n"); |
267 | if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef)) | ||
268 | mwifiex_dbg(priv->adapter, ERROR, | ||
269 | "Failed to stop CAC in FW\n"); | ||
248 | cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef, | 270 | cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef, |
249 | GFP_KERNEL); | 271 | GFP_KERNEL); |
250 | mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n", | 272 | mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n", |
@@ -252,7 +274,7 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | |||
252 | mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n", | 274 | mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n", |
253 | rdr_event->det_type); | 275 | rdr_event->det_type); |
254 | } else { | 276 | } else { |
255 | mwifiex_dbg(priv->adapter, ERROR, | 277 | mwifiex_dbg(priv->adapter, MSG, |
256 | "false radar detection event!\n"); | 278 | "false radar detection event!\n"); |
257 | } | 279 | } |
258 | 280 | ||
@@ -283,7 +305,7 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) | |||
283 | return; | 305 | return; |
284 | } | 306 | } |
285 | 307 | ||
286 | mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef); | 308 | mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef); |
287 | 309 | ||
288 | if (mwifiex_config_start_uap(priv, bss_cfg)) { | 310 | if (mwifiex_config_start_uap(priv, bss_cfg)) { |
289 | mwifiex_dbg(priv->adapter, ERROR, | 311 | mwifiex_dbg(priv->adapter, ERROR, |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 8422986cd7a9..c174e79e6df2 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -156,7 +156,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv, | |||
156 | int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | 156 | int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, |
157 | struct host_cmd_ds_command *resp) | 157 | struct host_cmd_ds_command *resp) |
158 | { | 158 | { |
159 | int tid; | 159 | int tid, tid_down; |
160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; | 160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; |
161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; | 161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; |
162 | struct mwifiex_ra_list_tbl *ra_list; | 162 | struct mwifiex_ra_list_tbl *ra_list; |
@@ -167,7 +167,9 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
167 | 167 | ||
168 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) | 168 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) |
169 | >> BLOCKACKPARAM_TID_POS; | 169 | >> BLOCKACKPARAM_TID_POS; |
170 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, add_ba_rsp-> | 170 | |
171 | tid_down = mwifiex_wmm_downgrade_tid(priv, tid); | ||
172 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp-> | ||
171 | peer_mac_addr); | 173 | peer_mac_addr); |
172 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { | 174 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
173 | if (ra_list) { | 175 | if (ra_list) { |
@@ -530,13 +532,16 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
530 | struct mwifiex_tx_ba_stream_tbl *new_node; | 532 | struct mwifiex_tx_ba_stream_tbl *new_node; |
531 | struct mwifiex_ra_list_tbl *ra_list; | 533 | struct mwifiex_ra_list_tbl *ra_list; |
532 | unsigned long flags; | 534 | unsigned long flags; |
535 | int tid_down; | ||
533 | 536 | ||
534 | if (!mwifiex_get_ba_tbl(priv, tid, ra)) { | 537 | if (!mwifiex_get_ba_tbl(priv, tid, ra)) { |
535 | new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl), | 538 | new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl), |
536 | GFP_ATOMIC); | 539 | GFP_ATOMIC); |
537 | if (!new_node) | 540 | if (!new_node) |
538 | return; | 541 | return; |
539 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra); | 542 | |
543 | tid_down = mwifiex_wmm_downgrade_tid(priv, tid); | ||
544 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra); | ||
540 | if (ra_list) { | 545 | if (ra_list) { |
541 | ra_list->ba_status = ba_status; | 546 | ra_list->ba_status = ba_status; |
542 | ra_list->amsdu_in_ampdu = false; | 547 | ra_list->amsdu_in_ampdu = false; |
@@ -643,6 +648,30 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
643 | } | 648 | } |
644 | 649 | ||
645 | /* | 650 | /* |
651 | * This function sends delba to specific tid | ||
652 | */ | ||
653 | void mwifiex_11n_delba(struct mwifiex_private *priv, int tid) | ||
654 | { | ||
655 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; | ||
656 | |||
657 | if (list_empty(&priv->rx_reorder_tbl_ptr)) { | ||
658 | dev_dbg(priv->adapter->dev, | ||
659 | "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n"); | ||
660 | return; | ||
661 | } | ||
662 | |||
663 | list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) { | ||
664 | if (rx_reor_tbl_ptr->tid == tid) { | ||
665 | dev_dbg(priv->adapter->dev, | ||
666 | "Send delba to tid=%d, %pM\n", | ||
667 | tid, rx_reor_tbl_ptr->ta); | ||
668 | mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0); | ||
669 | return; | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | |||
674 | /* | ||
646 | * This function handles the command response of a delete BA request. | 675 | * This function handles the command response of a delete BA request. |
647 | */ | 676 | */ |
648 | void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba) | 677 | void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba) |
@@ -814,3 +843,72 @@ u8 mwifiex_get_sec_chan_offset(int chan) | |||
814 | 843 | ||
815 | return sec_offset; | 844 | return sec_offset; |
816 | } | 845 | } |
846 | |||
847 | /* This function will send DELBA to entries in the priv's | ||
848 | * Tx BA stream table | ||
849 | */ | ||
850 | static void | ||
851 | mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid) | ||
852 | { | ||
853 | struct mwifiex_adapter *adapter = priv->adapter; | ||
854 | struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr; | ||
855 | |||
856 | if (list_empty(&priv->tx_ba_stream_tbl_ptr)) | ||
857 | return; | ||
858 | |||
859 | list_for_each_entry(tx_ba_stream_tbl_ptr, | ||
860 | &priv->tx_ba_stream_tbl_ptr, list) { | ||
861 | if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) { | ||
862 | if (tid == tx_ba_stream_tbl_ptr->tid) { | ||
863 | dev_dbg(adapter->dev, | ||
864 | "Tx:Send delba to tid=%d, %pM\n", tid, | ||
865 | tx_ba_stream_tbl_ptr->ra); | ||
866 | mwifiex_send_delba(priv, | ||
867 | tx_ba_stream_tbl_ptr->tid, | ||
868 | tx_ba_stream_tbl_ptr->ra, 1); | ||
869 | return; | ||
870 | } | ||
871 | } | ||
872 | } | ||
873 | } | ||
874 | |||
875 | /* This function updates all the tx_win_size | ||
876 | */ | ||
877 | void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter) | ||
878 | { | ||
879 | u8 i; | ||
880 | u32 tx_win_size; | ||
881 | struct mwifiex_private *priv; | ||
882 | |||
883 | for (i = 0; i < adapter->priv_num; i++) { | ||
884 | if (!adapter->priv[i]) | ||
885 | continue; | ||
886 | priv = adapter->priv[i]; | ||
887 | tx_win_size = priv->add_ba_param.tx_win_size; | ||
888 | |||
889 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) | ||
890 | priv->add_ba_param.tx_win_size = | ||
891 | MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; | ||
892 | |||
893 | if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) | ||
894 | priv->add_ba_param.tx_win_size = | ||
895 | MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; | ||
896 | |||
897 | if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) | ||
898 | priv->add_ba_param.tx_win_size = | ||
899 | MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE; | ||
900 | |||
901 | if (adapter->coex_win_size) { | ||
902 | if (adapter->coex_tx_win_size) | ||
903 | priv->add_ba_param.tx_win_size = | ||
904 | adapter->coex_tx_win_size; | ||
905 | } | ||
906 | |||
907 | if (tx_win_size != priv->add_ba_param.tx_win_size) { | ||
908 | if (!priv->media_connected) | ||
909 | continue; | ||
910 | for (i = 0; i < MAX_NUM_TID; i++) | ||
911 | mwifiex_send_delba_txbastream_tbl(priv, i); | ||
912 | } | ||
913 | } | ||
914 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 39d7a957674c..2906cd543532 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -663,6 +663,7 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
663 | struct mwifiex_ra_list_tbl *ra_list; | 663 | struct mwifiex_ra_list_tbl *ra_list; |
664 | u8 cleanup_rx_reorder_tbl; | 664 | u8 cleanup_rx_reorder_tbl; |
665 | unsigned long flags; | 665 | unsigned long flags; |
666 | int tid_down; | ||
666 | 667 | ||
667 | if (type == TYPE_DELBA_RECEIVE) | 668 | if (type == TYPE_DELBA_RECEIVE) |
668 | cleanup_rx_reorder_tbl = (initiator) ? true : false; | 669 | cleanup_rx_reorder_tbl = (initiator) ? true : false; |
@@ -688,7 +689,9 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
688 | "event: TID, RA not found in table\n"); | 689 | "event: TID, RA not found in table\n"); |
689 | return; | 690 | return; |
690 | } | 691 | } |
691 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, peer_mac); | 692 | |
693 | tid_down = mwifiex_wmm_downgrade_tid(priv, tid); | ||
694 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac); | ||
692 | if (ra_list) { | 695 | if (ra_list) { |
693 | ra_list->amsdu_in_ampdu = false; | 696 | ra_list->amsdu_in_ampdu = false; |
694 | ra_list->ba_status = BA_SETUP_NONE; | 697 | ra_list->ba_status = BA_SETUP_NONE; |
@@ -825,3 +828,83 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags) | |||
825 | 828 | ||
826 | return; | 829 | return; |
827 | } | 830 | } |
831 | |||
832 | /* This function update all the rx_win_size based on coex flag | ||
833 | */ | ||
834 | static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter, | ||
835 | bool coex_flag) | ||
836 | { | ||
837 | u8 i; | ||
838 | u32 rx_win_size; | ||
839 | struct mwifiex_private *priv; | ||
840 | |||
841 | dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag); | ||
842 | |||
843 | for (i = 0; i < adapter->priv_num; i++) { | ||
844 | if (!adapter->priv[i]) | ||
845 | continue; | ||
846 | priv = adapter->priv[i]; | ||
847 | rx_win_size = priv->add_ba_param.rx_win_size; | ||
848 | if (coex_flag) { | ||
849 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) | ||
850 | priv->add_ba_param.rx_win_size = | ||
851 | MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE; | ||
852 | if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) | ||
853 | priv->add_ba_param.rx_win_size = | ||
854 | MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE; | ||
855 | if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) | ||
856 | priv->add_ba_param.rx_win_size = | ||
857 | MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE; | ||
858 | } else { | ||
859 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) | ||
860 | priv->add_ba_param.rx_win_size = | ||
861 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; | ||
862 | if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) | ||
863 | priv->add_ba_param.rx_win_size = | ||
864 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; | ||
865 | if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) | ||
866 | priv->add_ba_param.rx_win_size = | ||
867 | MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE; | ||
868 | } | ||
869 | |||
870 | if (adapter->coex_win_size && adapter->coex_rx_win_size) | ||
871 | priv->add_ba_param.rx_win_size = | ||
872 | adapter->coex_rx_win_size; | ||
873 | |||
874 | if (rx_win_size != priv->add_ba_param.rx_win_size) { | ||
875 | if (!priv->media_connected) | ||
876 | continue; | ||
877 | for (i = 0; i < MAX_NUM_TID; i++) | ||
878 | mwifiex_11n_delba(priv, i); | ||
879 | } | ||
880 | } | ||
881 | } | ||
882 | |||
883 | /* This function check coex for RX BA | ||
884 | */ | ||
885 | void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter) | ||
886 | { | ||
887 | u8 i; | ||
888 | struct mwifiex_private *priv; | ||
889 | u8 count = 0; | ||
890 | |||
891 | for (i = 0; i < adapter->priv_num; i++) { | ||
892 | if (adapter->priv[i]) { | ||
893 | priv = adapter->priv[i]; | ||
894 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { | ||
895 | if (priv->media_connected) | ||
896 | count++; | ||
897 | } | ||
898 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
899 | if (priv->bss_started) | ||
900 | count++; | ||
901 | } | ||
902 | } | ||
903 | if (count >= MWIFIEX_BSS_COEX_COUNT) | ||
904 | break; | ||
905 | } | ||
906 | if (count >= MWIFIEX_BSS_COEX_COUNT) | ||
907 | mwifiex_update_ampdu_rxwinsize(adapter, true); | ||
908 | else | ||
909 | mwifiex_update_ampdu_rxwinsize(adapter, false); | ||
910 | } | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 4eecedadefbf..b15e4c7acbec 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -67,6 +67,22 @@ u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) | |||
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | /* This function maps IEEE HT secondary channel type to NL80211 channel type | ||
71 | */ | ||
72 | u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset) | ||
73 | { | ||
74 | switch (second_chan_offset) { | ||
75 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | ||
76 | return NL80211_CHAN_HT20; | ||
77 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
78 | return NL80211_CHAN_HT40PLUS; | ||
79 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
80 | return NL80211_CHAN_HT40MINUS; | ||
81 | default: | ||
82 | return NL80211_CHAN_HT20; | ||
83 | } | ||
84 | } | ||
85 | |||
70 | /* | 86 | /* |
71 | * This function checks whether WEP is set. | 87 | * This function checks whether WEP is set. |
72 | */ | 88 | */ |
@@ -1213,6 +1229,7 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, | |||
1213 | */ | 1229 | */ |
1214 | static int | 1230 | static int |
1215 | mwifiex_dump_station_info(struct mwifiex_private *priv, | 1231 | mwifiex_dump_station_info(struct mwifiex_private *priv, |
1232 | struct mwifiex_sta_node *node, | ||
1216 | struct station_info *sinfo) | 1233 | struct station_info *sinfo) |
1217 | { | 1234 | { |
1218 | u32 rate; | 1235 | u32 rate; |
@@ -1222,6 +1239,30 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
1222 | BIT(NL80211_STA_INFO_TX_BITRATE) | | 1239 | BIT(NL80211_STA_INFO_TX_BITRATE) | |
1223 | BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG); | 1240 | BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG); |
1224 | 1241 | ||
1242 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
1243 | if (!node) | ||
1244 | return -ENOENT; | ||
1245 | |||
1246 | sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) | | ||
1247 | BIT(NL80211_STA_INFO_TX_FAILED); | ||
1248 | sinfo->inactive_time = | ||
1249 | jiffies_to_msecs(jiffies - node->stats.last_rx); | ||
1250 | |||
1251 | sinfo->signal = node->stats.rssi; | ||
1252 | sinfo->signal_avg = node->stats.rssi; | ||
1253 | sinfo->rx_bytes = node->stats.rx_bytes; | ||
1254 | sinfo->tx_bytes = node->stats.tx_bytes; | ||
1255 | sinfo->rx_packets = node->stats.rx_packets; | ||
1256 | sinfo->tx_packets = node->stats.tx_packets; | ||
1257 | sinfo->tx_failed = node->stats.tx_failed; | ||
1258 | |||
1259 | mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo, | ||
1260 | &sinfo->txrate); | ||
1261 | sinfo->txrate.legacy = node->stats.last_tx_rate * 5; | ||
1262 | |||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1225 | /* Get signal information from the firmware */ | 1266 | /* Get signal information from the firmware */ |
1226 | if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, | 1267 | if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, |
1227 | HostCmd_ACT_GEN_GET, 0, NULL, true)) { | 1268 | HostCmd_ACT_GEN_GET, 0, NULL, true)) { |
@@ -1288,7 +1329,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
1288 | if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) | 1329 | if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) |
1289 | return -ENOENT; | 1330 | return -ENOENT; |
1290 | 1331 | ||
1291 | return mwifiex_dump_station_info(priv, sinfo); | 1332 | return mwifiex_dump_station_info(priv, NULL, sinfo); |
1292 | } | 1333 | } |
1293 | 1334 | ||
1294 | /* | 1335 | /* |
@@ -1299,13 +1340,29 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
1299 | int idx, u8 *mac, struct station_info *sinfo) | 1340 | int idx, u8 *mac, struct station_info *sinfo) |
1300 | { | 1341 | { |
1301 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1342 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1343 | static struct mwifiex_sta_node *node; | ||
1302 | 1344 | ||
1303 | if (!priv->media_connected || idx) | 1345 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && |
1304 | return -ENOENT; | 1346 | priv->media_connected && idx == 0) { |
1347 | ether_addr_copy(mac, priv->cfg_bssid); | ||
1348 | return mwifiex_dump_station_info(priv, NULL, sinfo); | ||
1349 | } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
1350 | mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST, | ||
1351 | HostCmd_ACT_GEN_GET, 0, NULL, true); | ||
1352 | |||
1353 | if (node && (&node->list == &priv->sta_list)) { | ||
1354 | node = NULL; | ||
1355 | return -ENOENT; | ||
1356 | } | ||
1305 | 1357 | ||
1306 | memcpy(mac, priv->cfg_bssid, ETH_ALEN); | 1358 | node = list_prepare_entry(node, &priv->sta_list, list); |
1359 | list_for_each_entry_continue(node, &priv->sta_list, list) { | ||
1360 | ether_addr_copy(mac, node->mac_addr); | ||
1361 | return mwifiex_dump_station_info(priv, node, sinfo); | ||
1362 | } | ||
1363 | } | ||
1307 | 1364 | ||
1308 | return mwifiex_dump_station_info(priv, sinfo); | 1365 | return -ENOENT; |
1309 | } | 1366 | } |
1310 | 1367 | ||
1311 | static int | 1368 | static int |
@@ -1725,6 +1782,13 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1725 | return -1; | 1782 | return -1; |
1726 | } | 1783 | } |
1727 | 1784 | ||
1785 | if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, | ||
1786 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | ||
1787 | mwifiex_dbg(priv->adapter, ERROR, | ||
1788 | "Failed to reset BSS\n"); | ||
1789 | return -1; | ||
1790 | } | ||
1791 | |||
1728 | return 0; | 1792 | return 0; |
1729 | } | 1793 | } |
1730 | 1794 | ||
@@ -1778,7 +1842,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1778 | return -EINVAL; | 1842 | return -EINVAL; |
1779 | } | 1843 | } |
1780 | 1844 | ||
1781 | mwifiex_uap_set_channel(bss_cfg, params->chandef); | 1845 | mwifiex_uap_set_channel(priv, bss_cfg, params->chandef); |
1782 | mwifiex_set_uap_rates(bss_cfg, params); | 1846 | mwifiex_set_uap_rates(bss_cfg, params); |
1783 | 1847 | ||
1784 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | 1848 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { |
@@ -1803,6 +1867,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1803 | 1867 | ||
1804 | mwifiex_set_wmm_params(priv, bss_cfg, params); | 1868 | mwifiex_set_wmm_params(priv, bss_cfg, params); |
1805 | 1869 | ||
1870 | if (mwifiex_is_11h_active(priv)) | ||
1871 | mwifiex_set_tpc_params(priv, bss_cfg, params); | ||
1872 | |||
1806 | if (mwifiex_is_11h_active(priv) && | 1873 | if (mwifiex_is_11h_active(priv) && |
1807 | !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, | 1874 | !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, |
1808 | priv->bss_mode)) { | 1875 | priv->bss_mode)) { |
@@ -1813,7 +1880,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1813 | "Failed to disable 11h extensions!!"); | 1880 | "Failed to disable 11h extensions!!"); |
1814 | return -1; | 1881 | return -1; |
1815 | } | 1882 | } |
1816 | priv->state_11h.is_11h_active = true; | 1883 | priv->state_11h.is_11h_active = false; |
1817 | } | 1884 | } |
1818 | 1885 | ||
1819 | if (mwifiex_config_start_uap(priv, bss_cfg)) { | 1886 | if (mwifiex_config_start_uap(priv, bss_cfg)) { |
@@ -2518,7 +2585,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2518 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | 2585 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; |
2519 | priv->bss_priority = 0; | 2586 | priv->bss_priority = 0; |
2520 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | 2587 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; |
2521 | priv->bss_num = 0; | 2588 | priv->bss_num = adapter->curr_iface_comb.sta_intf; |
2522 | 2589 | ||
2523 | break; | 2590 | break; |
2524 | case NL80211_IFTYPE_AP: | 2591 | case NL80211_IFTYPE_AP: |
@@ -2544,7 +2611,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2544 | priv->bss_priority = 0; | 2611 | priv->bss_priority = 0; |
2545 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; | 2612 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; |
2546 | priv->bss_started = 0; | 2613 | priv->bss_started = 0; |
2547 | priv->bss_num = 0; | 2614 | priv->bss_num = adapter->curr_iface_comb.uap_intf; |
2548 | priv->bss_mode = type; | 2615 | priv->bss_mode = type; |
2549 | 2616 | ||
2550 | break; | 2617 | break; |
@@ -2580,7 +2647,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2580 | priv->bss_priority = MWIFIEX_BSS_ROLE_STA; | 2647 | priv->bss_priority = MWIFIEX_BSS_ROLE_STA; |
2581 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | 2648 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; |
2582 | priv->bss_started = 0; | 2649 | priv->bss_started = 0; |
2583 | priv->bss_num = 0; | 2650 | priv->bss_num = adapter->curr_iface_comb.p2p_intf; |
2584 | 2651 | ||
2585 | if (mwifiex_cfg80211_init_p2p_client(priv)) { | 2652 | if (mwifiex_cfg80211_init_p2p_client(priv)) { |
2586 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | 2653 | memset(&priv->wdev, 0, sizeof(priv->wdev)); |
@@ -3366,6 +3433,45 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3366 | return 0; | 3433 | return 0; |
3367 | } | 3434 | } |
3368 | 3435 | ||
3436 | static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, | ||
3437 | struct wireless_dev *wdev, | ||
3438 | struct cfg80211_chan_def *chandef) | ||
3439 | { | ||
3440 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); | ||
3441 | struct mwifiex_bssdescriptor *curr_bss; | ||
3442 | struct ieee80211_channel *chan; | ||
3443 | u8 second_chan_offset; | ||
3444 | enum nl80211_channel_type chan_type; | ||
3445 | enum ieee80211_band band; | ||
3446 | int freq; | ||
3447 | int ret = -ENODATA; | ||
3448 | |||
3449 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP && | ||
3450 | cfg80211_chandef_valid(&priv->bss_chandef)) { | ||
3451 | *chandef = priv->bss_chandef; | ||
3452 | ret = 0; | ||
3453 | } else if (priv->media_connected) { | ||
3454 | curr_bss = &priv->curr_bss_params.bss_descriptor; | ||
3455 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | ||
3456 | freq = ieee80211_channel_to_frequency(curr_bss->channel, band); | ||
3457 | chan = ieee80211_get_channel(wiphy, freq); | ||
3458 | |||
3459 | if (curr_bss->bcn_ht_oper) { | ||
3460 | second_chan_offset = curr_bss->bcn_ht_oper->ht_param & | ||
3461 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
3462 | chan_type = mwifiex_sec_chan_offset_to_chan_type | ||
3463 | (second_chan_offset); | ||
3464 | cfg80211_chandef_create(chandef, chan, chan_type); | ||
3465 | } else { | ||
3466 | cfg80211_chandef_create(chandef, chan, | ||
3467 | NL80211_CHAN_NO_HT); | ||
3468 | } | ||
3469 | ret = 0; | ||
3470 | } | ||
3471 | |||
3472 | return ret; | ||
3473 | } | ||
3474 | |||
3369 | static int | 3475 | static int |
3370 | mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, | 3476 | mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, |
3371 | struct net_device *dev, | 3477 | struct net_device *dev, |
@@ -3471,6 +3577,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
3471 | .tdls_oper = mwifiex_cfg80211_tdls_oper, | 3577 | .tdls_oper = mwifiex_cfg80211_tdls_oper, |
3472 | .add_station = mwifiex_cfg80211_add_station, | 3578 | .add_station = mwifiex_cfg80211_add_station, |
3473 | .change_station = mwifiex_cfg80211_change_station, | 3579 | .change_station = mwifiex_cfg80211_change_station, |
3580 | .get_channel = mwifiex_cfg80211_get_channel, | ||
3474 | .start_radar_detection = mwifiex_cfg80211_start_radar_detection, | 3581 | .start_radar_detection = mwifiex_cfg80211_start_radar_detection, |
3475 | .channel_switch = mwifiex_cfg80211_channel_switch, | 3582 | .channel_switch = mwifiex_cfg80211_channel_switch, |
3476 | }; | 3583 | }; |
@@ -3578,7 +3685,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
3578 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 3685 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
3579 | WIPHY_FLAG_AP_UAPSD | | 3686 | WIPHY_FLAG_AP_UAPSD | |
3580 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | 3687 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
3581 | WIPHY_FLAG_HAS_CHANNEL_SWITCH; | 3688 | WIPHY_FLAG_HAS_CHANNEL_SWITCH | |
3689 | WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
3582 | 3690 | ||
3583 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) | 3691 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) |
3584 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | 3692 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index a1de83fd1dbe..207da40500f4 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -469,10 +469,11 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
469 | memset(rx_info, 0, sizeof(*rx_info)); | 469 | memset(rx_info, 0, sizeof(*rx_info)); |
470 | rx_info->bss_num = priv->bss_num; | 470 | rx_info->bss_num = priv->bss_num; |
471 | rx_info->bss_type = priv->bss_type; | 471 | rx_info->bss_type = priv->bss_type; |
472 | mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", | ||
473 | skb->data, skb->len); | ||
472 | } | 474 | } |
473 | 475 | ||
474 | mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause); | 476 | mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause); |
475 | mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", skb->data, skb->len); | ||
476 | 477 | ||
477 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 478 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
478 | ret = mwifiex_process_uap_event(priv); | 479 | ret = mwifiex_process_uap_event(priv); |
@@ -574,6 +575,8 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
574 | case HostCmd_CMD_UAP_BSS_START: | 575 | case HostCmd_CMD_UAP_BSS_START: |
575 | case HostCmd_CMD_UAP_BSS_STOP: | 576 | case HostCmd_CMD_UAP_BSS_STOP: |
576 | case HostCmd_CMD_UAP_STA_DEAUTH: | 577 | case HostCmd_CMD_UAP_STA_DEAUTH: |
578 | case HOST_CMD_APCMD_SYS_RESET: | ||
579 | case HOST_CMD_APCMD_STA_LIST: | ||
577 | ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, | 580 | ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, |
578 | cmd_oid, data_buf, | 581 | cmd_oid, data_buf, |
579 | cmd_ptr); | 582 | cmd_ptr); |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 38f24e0427d2..51e344789ba2 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <uapi/linux/if_arp.h> | 29 | #include <uapi/linux/if_arp.h> |
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | 31 | ||
32 | 32 | #define MWIFIEX_BSS_COEX_COUNT 2 | |
33 | #define MWIFIEX_MAX_BSS_NUM (3) | 33 | #define MWIFIEX_MAX_BSS_NUM (3) |
34 | 34 | ||
35 | #define MWIFIEX_DMA_ALIGN_SZ 64 | 35 | #define MWIFIEX_DMA_ALIGN_SZ 64 |
@@ -49,7 +49,12 @@ | |||
49 | 49 | ||
50 | #define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 64 | 50 | #define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 64 |
51 | #define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 64 | 51 | #define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 64 |
52 | #define MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE 16 | ||
53 | |||
52 | #define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32 | 54 | #define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32 |
55 | |||
56 | #define MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE 16 | ||
57 | |||
53 | #define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16 | 58 | #define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16 |
54 | #define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 64 | 59 | #define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 64 |
55 | #define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 64 | 60 | #define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 64 |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index c404390cb0fa..cd09051710e6 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -128,6 +128,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
128 | 128 | ||
129 | #define TLV_TYPE_UAP_SSID 0x0000 | 129 | #define TLV_TYPE_UAP_SSID 0x0000 |
130 | #define TLV_TYPE_UAP_RATES 0x0001 | 130 | #define TLV_TYPE_UAP_RATES 0x0001 |
131 | #define TLV_TYPE_PWR_CONSTRAINT 0x0020 | ||
131 | 132 | ||
132 | #define PROPRIETARY_TLV_BASE_ID 0x0100 | 133 | #define PROPRIETARY_TLV_BASE_ID 0x0100 |
133 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) | 134 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) |
@@ -174,6 +175,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
174 | #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) | 175 | #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) |
175 | #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) | 176 | #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) |
176 | #define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198) | 177 | #define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198) |
178 | #define TLV_BTCOEX_WL_AGGR_WINSIZE (PROPRIETARY_TLV_BASE_ID + 202) | ||
179 | #define TLV_BTCOEX_WL_SCANTIME (PROPRIETARY_TLV_BASE_ID + 203) | ||
177 | 180 | ||
178 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 | 181 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 |
179 | 182 | ||
@@ -330,9 +333,11 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
330 | #define HostCmd_CMD_RSSI_INFO 0x00a4 | 333 | #define HostCmd_CMD_RSSI_INFO 0x00a4 |
331 | #define HostCmd_CMD_FUNC_INIT 0x00a9 | 334 | #define HostCmd_CMD_FUNC_INIT 0x00a9 |
332 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa | 335 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa |
336 | #define HOST_CMD_APCMD_SYS_RESET 0x00af | ||
333 | #define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0 | 337 | #define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0 |
334 | #define HostCmd_CMD_UAP_BSS_START 0x00b1 | 338 | #define HostCmd_CMD_UAP_BSS_START 0x00b1 |
335 | #define HostCmd_CMD_UAP_BSS_STOP 0x00b2 | 339 | #define HostCmd_CMD_UAP_BSS_STOP 0x00b2 |
340 | #define HOST_CMD_APCMD_STA_LIST 0x00b3 | ||
336 | #define HostCmd_CMD_UAP_STA_DEAUTH 0x00b5 | 341 | #define HostCmd_CMD_UAP_STA_DEAUTH 0x00b5 |
337 | #define HostCmd_CMD_11N_CFG 0x00cd | 342 | #define HostCmd_CMD_11N_CFG 0x00cd |
338 | #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce | 343 | #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce |
@@ -419,8 +424,12 @@ enum P2P_MODES { | |||
419 | #define HS_CFG_COND_MAC_EVENT 0x00000004 | 424 | #define HS_CFG_COND_MAC_EVENT 0x00000004 |
420 | #define HS_CFG_COND_MULTICAST_DATA 0x00000008 | 425 | #define HS_CFG_COND_MULTICAST_DATA 0x00000008 |
421 | 426 | ||
422 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc | 427 | #define CONNECT_ERR_AUTH_ERR_STA_FAILURE 0xFFFB |
423 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 | 428 | #define CONNECT_ERR_ASSOC_ERR_TIMEOUT 0xFFFC |
429 | #define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED 0xFFFD | ||
430 | #define CONNECT_ERR_AUTH_MSG_UNHANDLED 0xFFFE | ||
431 | #define CONNECT_ERR_STA_FAILURE 0xFFFF | ||
432 | |||
424 | 433 | ||
425 | #define CMD_F_HOSTCMD (1 << 0) | 434 | #define CMD_F_HOSTCMD (1 << 0) |
426 | #define CMD_F_CANCELED (1 << 1) | 435 | #define CMD_F_CANCELED (1 << 1) |
@@ -503,6 +512,7 @@ enum P2P_MODES { | |||
503 | #define EVENT_EXT_SCAN_REPORT 0x00000058 | 512 | #define EVENT_EXT_SCAN_REPORT 0x00000058 |
504 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f | 513 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f |
505 | #define EVENT_TX_STATUS_REPORT 0x00000074 | 514 | #define EVENT_TX_STATUS_REPORT 0x00000074 |
515 | #define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076 | ||
506 | 516 | ||
507 | #define EVENT_ID_MASK 0xffff | 517 | #define EVENT_ID_MASK 0xffff |
508 | #define BSS_NUM_MASK 0xf | 518 | #define BSS_NUM_MASK 0xf |
@@ -627,7 +637,12 @@ struct uap_rxpd { | |||
627 | __le16 rx_pkt_type; | 637 | __le16 rx_pkt_type; |
628 | __le16 seq_num; | 638 | __le16 seq_num; |
629 | u8 priority; | 639 | u8 priority; |
630 | u8 reserved1; | 640 | u8 rx_rate; |
641 | s8 snr; | ||
642 | s8 nf; | ||
643 | u8 ht_info; | ||
644 | u8 reserved[3]; | ||
645 | u8 flags; | ||
631 | }; | 646 | }; |
632 | 647 | ||
633 | struct mwifiex_fw_chan_stats { | 648 | struct mwifiex_fw_chan_stats { |
@@ -1151,6 +1166,13 @@ enum SNMP_MIB_INDEX { | |||
1151 | DOT11H_I = 10, | 1166 | DOT11H_I = 10, |
1152 | }; | 1167 | }; |
1153 | 1168 | ||
1169 | enum mwifiex_assocmd_failurepoint { | ||
1170 | MWIFIEX_ASSOC_CMD_SUCCESS = 0, | ||
1171 | MWIFIEX_ASSOC_CMD_FAILURE_ASSOC, | ||
1172 | MWIFIEX_ASSOC_CMD_FAILURE_AUTH, | ||
1173 | MWIFIEX_ASSOC_CMD_FAILURE_JOIN | ||
1174 | }; | ||
1175 | |||
1154 | #define MAX_SNMP_BUF_SIZE 128 | 1176 | #define MAX_SNMP_BUF_SIZE 128 |
1155 | 1177 | ||
1156 | struct host_cmd_ds_802_11_snmp_mib { | 1178 | struct host_cmd_ds_802_11_snmp_mib { |
@@ -1448,6 +1470,18 @@ struct host_cmd_ds_sta_deauth { | |||
1448 | __le16 reason; | 1470 | __le16 reason; |
1449 | } __packed; | 1471 | } __packed; |
1450 | 1472 | ||
1473 | struct mwifiex_ie_types_sta_info { | ||
1474 | struct mwifiex_ie_types_header header; | ||
1475 | u8 mac[ETH_ALEN]; | ||
1476 | u8 power_mfg_status; | ||
1477 | s8 rssi; | ||
1478 | }; | ||
1479 | |||
1480 | struct host_cmd_ds_sta_list { | ||
1481 | u16 sta_count; | ||
1482 | u8 tlv[0]; | ||
1483 | } __packed; | ||
1484 | |||
1451 | struct mwifiex_ie_types_pwr_capability { | 1485 | struct mwifiex_ie_types_pwr_capability { |
1452 | struct mwifiex_ie_types_header header; | 1486 | struct mwifiex_ie_types_header header; |
1453 | s8 min_pwr; | 1487 | s8 min_pwr; |
@@ -1750,6 +1784,27 @@ struct host_cmd_tlv_ageout_timer { | |||
1750 | __le32 sta_ao_timer; | 1784 | __le32 sta_ao_timer; |
1751 | } __packed; | 1785 | } __packed; |
1752 | 1786 | ||
1787 | struct host_cmd_tlv_power_constraint { | ||
1788 | struct mwifiex_ie_types_header header; | ||
1789 | u8 constraint; | ||
1790 | } __packed; | ||
1791 | |||
1792 | struct mwifiex_ie_types_btcoex_scan_time { | ||
1793 | struct mwifiex_ie_types_header header; | ||
1794 | u8 coex_scan; | ||
1795 | u8 reserved; | ||
1796 | u16 min_scan_time; | ||
1797 | u16 max_scan_time; | ||
1798 | } __packed; | ||
1799 | |||
1800 | struct mwifiex_ie_types_btcoex_aggr_win_size { | ||
1801 | struct mwifiex_ie_types_header header; | ||
1802 | u8 coex_win_size; | ||
1803 | u8 tx_win_size; | ||
1804 | u8 rx_win_size; | ||
1805 | u8 reserved; | ||
1806 | } __packed; | ||
1807 | |||
1753 | struct host_cmd_ds_version_ext { | 1808 | struct host_cmd_ds_version_ext { |
1754 | u8 version_str_sel; | 1809 | u8 version_str_sel; |
1755 | char version_str[128]; | 1810 | char version_str[128]; |
@@ -1977,6 +2032,7 @@ struct host_cmd_ds_command { | |||
1977 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; | 2032 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; |
1978 | struct host_cmd_ds_sys_config uap_sys_config; | 2033 | struct host_cmd_ds_sys_config uap_sys_config; |
1979 | struct host_cmd_ds_sta_deauth sta_deauth; | 2034 | struct host_cmd_ds_sta_deauth sta_deauth; |
2035 | struct host_cmd_ds_sta_list sta_list; | ||
1980 | struct host_cmd_11ac_vht_cfg vht_cfg; | 2036 | struct host_cmd_11ac_vht_cfg vht_cfg; |
1981 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 2037 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
1982 | struct host_cmd_ds_tdls_oper tdls_oper; | 2038 | struct host_cmd_ds_tdls_oper tdls_oper; |
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index f3b6ed249403..0ba894509413 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -320,63 +320,81 @@ done: | |||
320 | /* This function parses head and tail IEs, from cfg80211_beacon_data and sets | 320 | /* This function parses head and tail IEs, from cfg80211_beacon_data and sets |
321 | * these IE to FW. | 321 | * these IE to FW. |
322 | */ | 322 | */ |
323 | static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv, | 323 | static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, |
324 | struct cfg80211_beacon_data *info) | 324 | struct cfg80211_beacon_data *info) |
325 | { | 325 | { |
326 | struct mwifiex_ie *gen_ie; | 326 | struct mwifiex_ie *gen_ie; |
327 | struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL; | 327 | struct ieee_types_header *hdr; |
328 | struct ieee_types_header *chsw_ie = NULL; | 328 | struct ieee80211_vendor_ie *vendorhdr; |
329 | u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; | 329 | u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; |
330 | const u8 *vendor_ie; | 330 | int left_len, parsed_len = 0; |
331 | |||
332 | if (!info->tail || !info->tail_len) | ||
333 | return 0; | ||
331 | 334 | ||
332 | gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL); | 335 | gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL); |
333 | if (!gen_ie) | 336 | if (!gen_ie) |
334 | return -ENOMEM; | 337 | return -ENOMEM; |
335 | gen_ie->ie_index = cpu_to_le16(gen_idx); | ||
336 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | | ||
337 | MGMT_MASK_PROBE_RESP | | ||
338 | MGMT_MASK_ASSOC_RESP); | ||
339 | 338 | ||
340 | if (info->tail && info->tail_len) { | 339 | left_len = info->tail_len; |
341 | rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, | 340 | |
342 | info->tail, info->tail_len); | 341 | /* Many IEs are generated in FW by parsing bss configuration. |
343 | if (rsn_ie) { | 342 | * Let's not add them here; else we may end up duplicating these IEs |
344 | memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2); | 343 | */ |
345 | ie_len = rsn_ie->len + 2; | 344 | while (left_len > sizeof(struct ieee_types_header)) { |
346 | gen_ie->ie_length = cpu_to_le16(ie_len); | 345 | hdr = (void *)(info->tail + parsed_len); |
346 | switch (hdr->element_id) { | ||
347 | case WLAN_EID_SSID: | ||
348 | case WLAN_EID_SUPP_RATES: | ||
349 | case WLAN_EID_COUNTRY: | ||
350 | case WLAN_EID_PWR_CONSTRAINT: | ||
351 | case WLAN_EID_EXT_SUPP_RATES: | ||
352 | case WLAN_EID_HT_CAPABILITY: | ||
353 | case WLAN_EID_HT_OPERATION: | ||
354 | case WLAN_EID_VHT_CAPABILITY: | ||
355 | case WLAN_EID_VHT_OPERATION: | ||
356 | case WLAN_EID_VENDOR_SPECIFIC: | ||
357 | break; | ||
358 | default: | ||
359 | memcpy(gen_ie->ie_buffer + ie_len, hdr, | ||
360 | hdr->len + sizeof(struct ieee_types_header)); | ||
361 | ie_len += hdr->len + sizeof(struct ieee_types_header); | ||
362 | break; | ||
347 | } | 363 | } |
364 | left_len -= hdr->len + sizeof(struct ieee_types_header); | ||
365 | parsed_len += hdr->len + sizeof(struct ieee_types_header); | ||
366 | } | ||
348 | 367 | ||
349 | vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, | 368 | /* parse only WPA vendor IE from tail, WMM IE is configured by |
369 | * bss_config command | ||
370 | */ | ||
371 | vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, | ||
350 | WLAN_OUI_TYPE_MICROSOFT_WPA, | 372 | WLAN_OUI_TYPE_MICROSOFT_WPA, |
351 | info->tail, | 373 | info->tail, info->tail_len); |
352 | info->tail_len); | 374 | if (vendorhdr) { |
353 | if (vendor_ie) { | 375 | memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, |
354 | wpa_ie = (struct ieee_types_header *)vendor_ie; | 376 | vendorhdr->len + sizeof(struct ieee_types_header)); |
355 | memcpy(gen_ie->ie_buffer + ie_len, | 377 | ie_len += vendorhdr->len + sizeof(struct ieee_types_header); |
356 | wpa_ie, wpa_ie->len + 2); | 378 | } |
357 | ie_len += wpa_ie->len + 2; | ||
358 | gen_ie->ie_length = cpu_to_le16(ie_len); | ||
359 | } | ||
360 | 379 | ||
361 | chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH, | 380 | if (!ie_len) { |
362 | info->tail, info->tail_len); | 381 | kfree(gen_ie); |
363 | if (chsw_ie) { | 382 | return 0; |
364 | memcpy(gen_ie->ie_buffer + ie_len, | ||
365 | chsw_ie, chsw_ie->len + 2); | ||
366 | ie_len += chsw_ie->len + 2; | ||
367 | gen_ie->ie_length = cpu_to_le16(ie_len); | ||
368 | } | ||
369 | } | 383 | } |
370 | 384 | ||
371 | if (rsn_ie || wpa_ie || chsw_ie) { | 385 | gen_ie->ie_index = cpu_to_le16(gen_idx); |
372 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, | 386 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | |
373 | NULL, NULL, NULL)) { | 387 | MGMT_MASK_PROBE_RESP | |
374 | kfree(gen_ie); | 388 | MGMT_MASK_ASSOC_RESP); |
375 | return -1; | 389 | gen_ie->ie_length = cpu_to_le16(ie_len); |
376 | } | 390 | |
377 | priv->gen_idx = gen_idx; | 391 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL, |
392 | NULL, NULL)) { | ||
393 | kfree(gen_ie); | ||
394 | return -1; | ||
378 | } | 395 | } |
379 | 396 | ||
397 | priv->gen_idx = gen_idx; | ||
380 | kfree(gen_ie); | 398 | kfree(gen_ie); |
381 | return 0; | 399 | return 0; |
382 | } | 400 | } |
@@ -390,7 +408,7 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
390 | { | 408 | { |
391 | int ret; | 409 | int ret; |
392 | 410 | ||
393 | ret = mwifiex_uap_set_head_tail_ies(priv, info); | 411 | ret = mwifiex_uap_parse_tail_ies(priv, info); |
394 | return ret; | 412 | return ret; |
395 | 413 | ||
396 | return mwifiex_set_mgmt_beacon_data_ies(priv, info); | 414 | return mwifiex_set_mgmt_beacon_data_ies(priv, info); |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 6f11a25a6b49..4f0174c64946 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -113,6 +113,7 @@ struct mwifiex_uap_bss_param { | |||
113 | u32 sta_ao_timer; | 113 | u32 sta_ao_timer; |
114 | u32 ps_sta_ao_timer; | 114 | u32 ps_sta_ao_timer; |
115 | u8 qos_info; | 115 | u8 qos_info; |
116 | u8 power_constraint; | ||
116 | struct mwifiex_types_wmm_info wmm_info; | 117 | struct mwifiex_types_wmm_info wmm_info; |
117 | }; | 118 | }; |
118 | 119 | ||
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index cce8e39aa45e..56b024a6aaa5 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -556,6 +556,23 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, | |||
556 | return 0; | 556 | return 0; |
557 | } | 557 | } |
558 | 558 | ||
559 | static const char *assoc_failure_reason_to_str(u16 cap_info) | ||
560 | { | ||
561 | switch (cap_info) { | ||
562 | case CONNECT_ERR_AUTH_ERR_STA_FAILURE: | ||
563 | return "CONNECT_ERR_AUTH_ERR_STA_FAILURE"; | ||
564 | case CONNECT_ERR_AUTH_MSG_UNHANDLED: | ||
565 | return "CONNECT_ERR_AUTH_MSG_UNHANDLED"; | ||
566 | case CONNECT_ERR_ASSOC_ERR_TIMEOUT: | ||
567 | return "CONNECT_ERR_ASSOC_ERR_TIMEOUT"; | ||
568 | case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED: | ||
569 | return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED"; | ||
570 | case CONNECT_ERR_STA_FAILURE: | ||
571 | return "CONNECT_ERR_STA_FAILURE"; | ||
572 | } | ||
573 | |||
574 | return "Unknown connect failure"; | ||
575 | } | ||
559 | /* | 576 | /* |
560 | * Association firmware command response handler | 577 | * Association firmware command response handler |
561 | * | 578 | * |
@@ -656,11 +673,18 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, | |||
656 | status_code, cap_info, | 673 | status_code, cap_info, |
657 | le16_to_cpu(assoc_rsp->a_id)); | 674 | le16_to_cpu(assoc_rsp->a_id)); |
658 | 675 | ||
659 | if (cap_info == MWIFIEX_TIMEOUT_FOR_AP_RESP) { | 676 | mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n", |
660 | if (status_code == MWIFIEX_STATUS_CODE_AUTH_TIMEOUT) | 677 | assoc_failure_reason_to_str(cap_info)); |
678 | if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) { | ||
679 | if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) { | ||
661 | ret = WLAN_STATUS_AUTH_TIMEOUT; | 680 | ret = WLAN_STATUS_AUTH_TIMEOUT; |
662 | else | 681 | mwifiex_dbg(priv->adapter, ERROR, |
682 | "ASSOC_RESP: AUTH timeout\n"); | ||
683 | } else { | ||
663 | ret = WLAN_STATUS_UNSPECIFIED_FAILURE; | 684 | ret = WLAN_STATUS_UNSPECIFIED_FAILURE; |
685 | mwifiex_dbg(priv->adapter, ERROR, | ||
686 | "ASSOC_RESP: UNSPECIFIED failure\n"); | ||
687 | } | ||
664 | } else { | 688 | } else { |
665 | ret = status_code; | 689 | ret = status_code; |
666 | } | 690 | } |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 5a6c1c76b33b..ae98b5b83b1f 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -642,6 +642,7 @@ struct mwifiex_private { | |||
642 | u8 del_list_idx; | 642 | u8 del_list_idx; |
643 | bool hs2_enabled; | 643 | bool hs2_enabled; |
644 | struct mwifiex_uap_bss_param bss_cfg; | 644 | struct mwifiex_uap_bss_param bss_cfg; |
645 | struct cfg80211_chan_def bss_chandef; | ||
645 | struct station_parameters *sta_params; | 646 | struct station_parameters *sta_params; |
646 | struct sk_buff_head tdls_txq; | 647 | struct sk_buff_head tdls_txq; |
647 | u8 check_tdls_tx; | 648 | u8 check_tdls_tx; |
@@ -740,6 +741,18 @@ struct mwifiex_tdls_capab { | |||
740 | struct ieee80211_vht_operation vhtoper; | 741 | struct ieee80211_vht_operation vhtoper; |
741 | }; | 742 | }; |
742 | 743 | ||
744 | struct mwifiex_station_stats { | ||
745 | u64 last_rx; | ||
746 | s8 rssi; | ||
747 | u64 rx_bytes; | ||
748 | u64 tx_bytes; | ||
749 | u32 rx_packets; | ||
750 | u32 tx_packets; | ||
751 | u32 tx_failed; | ||
752 | u8 last_tx_rate; | ||
753 | u8 last_tx_htinfo; | ||
754 | }; | ||
755 | |||
743 | /* This is AP/TDLS specific structure which stores information | 756 | /* This is AP/TDLS specific structure which stores information |
744 | * about associated/peer STA | 757 | * about associated/peer STA |
745 | */ | 758 | */ |
@@ -754,6 +767,7 @@ struct mwifiex_sta_node { | |||
754 | u16 max_amsdu; | 767 | u16 max_amsdu; |
755 | u8 tdls_status; | 768 | u8 tdls_status; |
756 | struct mwifiex_tdls_capab tdls_cap; | 769 | struct mwifiex_tdls_capab tdls_cap; |
770 | struct mwifiex_station_stats stats; | ||
757 | }; | 771 | }; |
758 | 772 | ||
759 | struct mwifiex_auto_tdls_peer { | 773 | struct mwifiex_auto_tdls_peer { |
@@ -959,6 +973,12 @@ struct mwifiex_adapter { | |||
959 | u32 num_in_chan_stats; | 973 | u32 num_in_chan_stats; |
960 | int survey_idx; | 974 | int survey_idx; |
961 | bool auto_tdls; | 975 | bool auto_tdls; |
976 | u8 coex_scan; | ||
977 | u8 coex_min_scan_time; | ||
978 | u8 coex_max_scan_time; | ||
979 | u8 coex_win_size; | ||
980 | u8 coex_tx_win_size; | ||
981 | u8 coex_rx_win_size; | ||
962 | }; | 982 | }; |
963 | 983 | ||
964 | void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); | 984 | void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); |
@@ -1135,6 +1155,9 @@ void mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
1135 | void mwifiex_set_vht_params(struct mwifiex_private *priv, | 1155 | void mwifiex_set_vht_params(struct mwifiex_private *priv, |
1136 | struct mwifiex_uap_bss_param *bss_cfg, | 1156 | struct mwifiex_uap_bss_param *bss_cfg, |
1137 | struct cfg80211_ap_settings *params); | 1157 | struct cfg80211_ap_settings *params); |
1158 | void mwifiex_set_tpc_params(struct mwifiex_private *priv, | ||
1159 | struct mwifiex_uap_bss_param *bss_cfg, | ||
1160 | struct cfg80211_ap_settings *params); | ||
1138 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, | 1161 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, |
1139 | struct cfg80211_ap_settings *params); | 1162 | struct cfg80211_ap_settings *params); |
1140 | void mwifiex_set_vht_width(struct mwifiex_private *priv, | 1163 | void mwifiex_set_vht_width(struct mwifiex_private *priv, |
@@ -1145,6 +1168,11 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv, | |||
1145 | struct mwifiex_uap_bss_param *bss_cfg, | 1168 | struct mwifiex_uap_bss_param *bss_cfg, |
1146 | struct cfg80211_ap_settings *params); | 1169 | struct cfg80211_ap_settings *params); |
1147 | void mwifiex_set_ba_params(struct mwifiex_private *priv); | 1170 | void mwifiex_set_ba_params(struct mwifiex_private *priv); |
1171 | |||
1172 | void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *pmadapter); | ||
1173 | void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv, | ||
1174 | struct sk_buff *event_skb); | ||
1175 | |||
1148 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | 1176 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); |
1149 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | 1177 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, |
1150 | struct host_cmd_ds_command *cmd, | 1178 | struct host_cmd_ds_command *cmd, |
@@ -1382,6 +1410,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, | |||
1382 | struct mwifiex_bssdescriptor *bss_desc); | 1410 | struct mwifiex_bssdescriptor *bss_desc); |
1383 | 1411 | ||
1384 | u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type); | 1412 | u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type); |
1413 | u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset); | ||
1385 | 1414 | ||
1386 | struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | 1415 | struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, |
1387 | const char *name, | 1416 | const char *name, |
@@ -1399,7 +1428,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
1399 | struct cfg80211_beacon_data *data); | 1428 | struct cfg80211_beacon_data *data); |
1400 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1429 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
1401 | u8 *mwifiex_11d_code_2_region(u8 code); | 1430 | u8 *mwifiex_11d_code_2_region(u8 code); |
1402 | void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | 1431 | void mwifiex_uap_set_channel(struct mwifiex_private *priv, |
1432 | struct mwifiex_uap_bss_param *bss_cfg, | ||
1403 | struct cfg80211_chan_def chandef); | 1433 | struct cfg80211_chan_def chandef); |
1404 | int mwifiex_config_start_uap(struct mwifiex_private *priv, | 1434 | int mwifiex_config_start_uap(struct mwifiex_private *priv, |
1405 | struct mwifiex_uap_bss_param *bss_cfg); | 1435 | struct mwifiex_uap_bss_param *bss_cfg); |
@@ -1473,6 +1503,8 @@ mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, | |||
1473 | void mwifiex_dfs_cac_work_queue(struct work_struct *work); | 1503 | void mwifiex_dfs_cac_work_queue(struct work_struct *work); |
1474 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work); | 1504 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work); |
1475 | void mwifiex_abort_cac(struct mwifiex_private *priv); | 1505 | void mwifiex_abort_cac(struct mwifiex_private *priv); |
1506 | int mwifiex_stop_radar_detection(struct mwifiex_private *priv, | ||
1507 | struct cfg80211_chan_def *chandef); | ||
1476 | int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | 1508 | int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, |
1477 | struct sk_buff *skb); | 1509 | struct sk_buff *skb); |
1478 | 1510 | ||
@@ -1488,7 +1520,8 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter); | |||
1488 | void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter); | 1520 | void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter); |
1489 | void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); | 1521 | void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); |
1490 | void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); | 1522 | void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); |
1491 | 1523 | void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter); | |
1524 | void mwifiex_11n_delba(struct mwifiex_private *priv, int tid); | ||
1492 | #ifdef CONFIG_DEBUG_FS | 1525 | #ifdef CONFIG_DEBUG_FS |
1493 | void mwifiex_debugfs_init(void); | 1526 | void mwifiex_debugfs_init(void); |
1494 | void mwifiex_debugfs_remove(void); | 1527 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index aa5b9a310340..b645884b3b97 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -958,6 +958,27 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, | |||
958 | return 0; | 958 | return 0; |
959 | } | 959 | } |
960 | 960 | ||
961 | static int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv, | ||
962 | struct host_cmd_ds_command *resp) | ||
963 | { | ||
964 | struct host_cmd_ds_sta_list *sta_list = | ||
965 | &resp->params.sta_list; | ||
966 | struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv; | ||
967 | int i; | ||
968 | struct mwifiex_sta_node *sta_node; | ||
969 | |||
970 | for (i = 0; i < sta_list->sta_count; i++) { | ||
971 | sta_node = mwifiex_get_sta_entry(priv, sta_info->mac); | ||
972 | if (unlikely(!sta_node)) | ||
973 | continue; | ||
974 | |||
975 | sta_node->stats.rssi = sta_info->rssi; | ||
976 | sta_info++; | ||
977 | } | ||
978 | |||
979 | return 0; | ||
980 | } | ||
981 | |||
961 | /* This function handles the command response of set_cfg_data */ | 982 | /* This function handles the command response of set_cfg_data */ |
962 | static int mwifiex_ret_cfg_data(struct mwifiex_private *priv, | 983 | static int mwifiex_ret_cfg_data(struct mwifiex_private *priv, |
963 | struct host_cmd_ds_command *resp) | 984 | struct host_cmd_ds_command *resp) |
@@ -1148,6 +1169,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
1148 | break; | 1169 | break; |
1149 | case HostCmd_CMD_UAP_SYS_CONFIG: | 1170 | case HostCmd_CMD_UAP_SYS_CONFIG: |
1150 | break; | 1171 | break; |
1172 | case HOST_CMD_APCMD_STA_LIST: | ||
1173 | ret = mwifiex_ret_uap_sta_list(priv, resp); | ||
1174 | break; | ||
1151 | case HostCmd_CMD_UAP_BSS_START: | 1175 | case HostCmd_CMD_UAP_BSS_START: |
1152 | adapter->tx_lock_flag = false; | 1176 | adapter->tx_lock_flag = false; |
1153 | adapter->pps_uapsd_mode = false; | 1177 | adapter->pps_uapsd_mode = false; |
@@ -1159,6 +1183,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
1159 | break; | 1183 | break; |
1160 | case HostCmd_CMD_UAP_STA_DEAUTH: | 1184 | case HostCmd_CMD_UAP_STA_DEAUTH: |
1161 | break; | 1185 | break; |
1186 | case HOST_CMD_APCMD_SYS_RESET: | ||
1187 | break; | ||
1162 | case HostCmd_CMD_MEF_CFG: | 1188 | case HostCmd_CMD_MEF_CFG: |
1163 | break; | 1189 | break; |
1164 | case HostCmd_CMD_COALESCE_CFG: | 1190 | case HostCmd_CMD_COALESCE_CFG: |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 95203780010a..848de2621958 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -183,6 +183,63 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv, | |||
183 | } | 183 | } |
184 | 184 | ||
185 | /* | 185 | /* |
186 | * This function handles coex events generated by firmware | ||
187 | */ | ||
188 | void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv, | ||
189 | struct sk_buff *event_skb) | ||
190 | { | ||
191 | struct mwifiex_adapter *adapter = priv->adapter; | ||
192 | struct mwifiex_ie_types_header *tlv; | ||
193 | struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv; | ||
194 | struct mwifiex_ie_types_btcoex_scan_time *scantlv; | ||
195 | s32 len = event_skb->len - sizeof(u32); | ||
196 | u8 *cur_ptr = event_skb->data + sizeof(u32); | ||
197 | u16 tlv_type, tlv_len; | ||
198 | |||
199 | while (len >= sizeof(struct mwifiex_ie_types_header)) { | ||
200 | tlv = (struct mwifiex_ie_types_header *)cur_ptr; | ||
201 | tlv_len = le16_to_cpu(tlv->len); | ||
202 | tlv_type = le16_to_cpu(tlv->type); | ||
203 | |||
204 | if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len) | ||
205 | break; | ||
206 | switch (tlv_type) { | ||
207 | case TLV_BTCOEX_WL_AGGR_WINSIZE: | ||
208 | winsizetlv = | ||
209 | (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv; | ||
210 | adapter->coex_win_size = winsizetlv->coex_win_size; | ||
211 | adapter->coex_tx_win_size = | ||
212 | winsizetlv->tx_win_size; | ||
213 | adapter->coex_rx_win_size = | ||
214 | winsizetlv->rx_win_size; | ||
215 | mwifiex_coex_ampdu_rxwinsize(adapter); | ||
216 | mwifiex_update_ampdu_txwinsize(adapter); | ||
217 | break; | ||
218 | |||
219 | case TLV_BTCOEX_WL_SCANTIME: | ||
220 | scantlv = | ||
221 | (struct mwifiex_ie_types_btcoex_scan_time *)tlv; | ||
222 | adapter->coex_scan = scantlv->coex_scan; | ||
223 | adapter->coex_min_scan_time = scantlv->min_scan_time; | ||
224 | adapter->coex_max_scan_time = scantlv->max_scan_time; | ||
225 | break; | ||
226 | |||
227 | default: | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | len -= tlv_len + sizeof(struct mwifiex_ie_types_header); | ||
232 | cur_ptr += tlv_len + | ||
233 | sizeof(struct mwifiex_ie_types_header); | ||
234 | } | ||
235 | |||
236 | dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n", | ||
237 | adapter->coex_scan, adapter->coex_min_scan_time, | ||
238 | adapter->coex_win_size, adapter->coex_tx_win_size, | ||
239 | adapter->coex_rx_win_size); | ||
240 | } | ||
241 | |||
242 | /* | ||
186 | * This function handles events generated by firmware. | 243 | * This function handles events generated by firmware. |
187 | * | 244 | * |
188 | * This is a generic function and handles all events. | 245 | * This is a generic function and handles all events. |
@@ -531,6 +588,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
531 | ret = mwifiex_11h_handle_radar_detected(priv, | 588 | ret = mwifiex_11h_handle_radar_detected(priv, |
532 | adapter->event_skb); | 589 | adapter->event_skb); |
533 | break; | 590 | break; |
591 | case EVENT_BT_COEX_WLAN_PARA_CHANGE: | ||
592 | dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n"); | ||
593 | mwifiex_bt_coex_wlan_param_update_event(priv, | ||
594 | adapter->event_skb); | ||
595 | break; | ||
534 | default: | 596 | default: |
535 | mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n", | 597 | mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n", |
536 | eventcause); | 598 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 28dcc84a34d2..5ed9b794053e 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -88,13 +88,22 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
88 | struct mwifiex_adapter *adapter = priv->adapter; | 88 | struct mwifiex_adapter *adapter = priv->adapter; |
89 | u8 *head_ptr; | 89 | u8 *head_ptr; |
90 | struct txpd *local_tx_pd = NULL; | 90 | struct txpd *local_tx_pd = NULL; |
91 | struct mwifiex_sta_node *dest_node; | ||
92 | struct ethhdr *hdr = (void *)skb->data; | ||
91 | 93 | ||
92 | hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; | 94 | hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; |
93 | 95 | ||
94 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 96 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { |
97 | dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest); | ||
98 | if (dest_node) { | ||
99 | dest_node->stats.tx_bytes += skb->len; | ||
100 | dest_node->stats.tx_packets++; | ||
101 | } | ||
102 | |||
95 | head_ptr = mwifiex_process_uap_txpd(priv, skb); | 103 | head_ptr = mwifiex_process_uap_txpd(priv, skb); |
96 | else | 104 | } else { |
97 | head_ptr = mwifiex_process_sta_txpd(priv, skb); | 105 | head_ptr = mwifiex_process_sta_txpd(priv, skb); |
106 | } | ||
98 | 107 | ||
99 | if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { | 108 | if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { |
100 | skb_queue_tail(&adapter->tx_data_q, skb); | 109 | skb_queue_tail(&adapter->tx_data_q, skb); |
@@ -310,11 +319,11 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
310 | priv->stats.tx_errors++; | 319 | priv->stats.tx_errors++; |
311 | } | 320 | } |
312 | 321 | ||
313 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) { | 322 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) |
314 | atomic_dec_return(&adapter->pending_bridged_pkts); | 323 | atomic_dec_return(&adapter->pending_bridged_pkts); |
315 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | 324 | |
316 | goto done; | 325 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) |
317 | } | 326 | goto done; |
318 | 327 | ||
319 | if (aggr) | 328 | if (aggr) |
320 | /* For skb_aggr, do not wake up tx queue */ | 329 | /* For skb_aggr, do not wake up tx queue */ |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index a4ae28353b6d..b74930054b8c 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -222,6 +222,23 @@ void mwifiex_set_vht_params(struct mwifiex_private *priv, | |||
222 | return; | 222 | return; |
223 | } | 223 | } |
224 | 224 | ||
225 | /* This function updates 11ac related parameters from IE | ||
226 | * and sets them into bss_config structure. | ||
227 | */ | ||
228 | void mwifiex_set_tpc_params(struct mwifiex_private *priv, | ||
229 | struct mwifiex_uap_bss_param *bss_cfg, | ||
230 | struct cfg80211_ap_settings *params) | ||
231 | { | ||
232 | const u8 *tpc_ie; | ||
233 | |||
234 | tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail, | ||
235 | params->beacon.tail_len); | ||
236 | if (tpc_ie) | ||
237 | bss_cfg->power_constraint = *(tpc_ie + 2); | ||
238 | else | ||
239 | bss_cfg->power_constraint = 0; | ||
240 | } | ||
241 | |||
225 | /* Enable VHT only when cfg80211_ap_settings has VHT IE. | 242 | /* Enable VHT only when cfg80211_ap_settings has VHT IE. |
226 | * Otherwise disable VHT. | 243 | * Otherwise disable VHT. |
227 | */ | 244 | */ |
@@ -466,6 +483,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
466 | struct host_cmd_tlv_auth_type *auth_type; | 483 | struct host_cmd_tlv_auth_type *auth_type; |
467 | struct host_cmd_tlv_rates *tlv_rates; | 484 | struct host_cmd_tlv_rates *tlv_rates; |
468 | struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; | 485 | struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; |
486 | struct host_cmd_tlv_power_constraint *pwr_ct; | ||
469 | struct mwifiex_ie_types_htcap *htcap; | 487 | struct mwifiex_ie_types_htcap *htcap; |
470 | struct mwifiex_ie_types_wmmcap *wmm_cap; | 488 | struct mwifiex_ie_types_wmmcap *wmm_cap; |
471 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | 489 | 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) | |||
644 | tlv += sizeof(*ao_timer); | 662 | tlv += sizeof(*ao_timer); |
645 | } | 663 | } |
646 | 664 | ||
665 | if (bss_cfg->power_constraint) { | ||
666 | pwr_ct = (void *)tlv; | ||
667 | pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT); | ||
668 | pwr_ct->header.len = cpu_to_le16(sizeof(u8)); | ||
669 | pwr_ct->constraint = bss_cfg->power_constraint; | ||
670 | cmd_size += sizeof(*pwr_ct); | ||
671 | tlv += sizeof(*pwr_ct); | ||
672 | } | ||
673 | |||
647 | if (bss_cfg->ps_sta_ao_timer) { | 674 | if (bss_cfg->ps_sta_ao_timer) { |
648 | ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; | 675 | ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; |
649 | ps_ao_timer->header.type = | 676 | ps_ao_timer->header.type = |
@@ -754,6 +781,8 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
754 | break; | 781 | break; |
755 | case HostCmd_CMD_UAP_BSS_START: | 782 | case HostCmd_CMD_UAP_BSS_START: |
756 | case HostCmd_CMD_UAP_BSS_STOP: | 783 | case HostCmd_CMD_UAP_BSS_STOP: |
784 | case HOST_CMD_APCMD_SYS_RESET: | ||
785 | case HOST_CMD_APCMD_STA_LIST: | ||
757 | cmd->command = cpu_to_le16(cmd_no); | 786 | cmd->command = cpu_to_le16(cmd_no); |
758 | cmd->size = cpu_to_le16(S_DS_GEN); | 787 | cmd->size = cpu_to_le16(S_DS_GEN); |
759 | break; | 788 | break; |
@@ -775,11 +804,14 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
775 | return 0; | 804 | return 0; |
776 | } | 805 | } |
777 | 806 | ||
778 | void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | 807 | void mwifiex_uap_set_channel(struct mwifiex_private *priv, |
808 | struct mwifiex_uap_bss_param *bss_cfg, | ||
779 | struct cfg80211_chan_def chandef) | 809 | struct cfg80211_chan_def chandef) |
780 | { | 810 | { |
781 | u8 config_bands = 0; | 811 | u8 config_bands = 0; |
782 | 812 | ||
813 | priv->bss_chandef = chandef; | ||
814 | |||
783 | bss_cfg->channel = ieee80211_frequency_to_channel( | 815 | bss_cfg->channel = ieee80211_frequency_to_channel( |
784 | chandef.chan->center_freq); | 816 | chandef.chan->center_freq); |
785 | 817 | ||
@@ -800,19 +832,28 @@ void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | |||
800 | if (chandef.width > NL80211_CHAN_WIDTH_40) | 832 | if (chandef.width > NL80211_CHAN_WIDTH_40) |
801 | config_bands |= BAND_AAC; | 833 | config_bands |= BAND_AAC; |
802 | } | 834 | } |
835 | |||
836 | priv->adapter->config_bands = config_bands; | ||
803 | } | 837 | } |
804 | 838 | ||
805 | int mwifiex_config_start_uap(struct mwifiex_private *priv, | 839 | int mwifiex_config_start_uap(struct mwifiex_private *priv, |
806 | struct mwifiex_uap_bss_param *bss_cfg) | 840 | struct mwifiex_uap_bss_param *bss_cfg) |
807 | { | 841 | { |
842 | enum state_11d_t state_11d; | ||
843 | |||
808 | if (mwifiex_del_mgmt_ies(priv)) | 844 | if (mwifiex_del_mgmt_ies(priv)) |
809 | mwifiex_dbg(priv->adapter, ERROR, | 845 | mwifiex_dbg(priv->adapter, ERROR, |
810 | "Failed to delete mgmt IEs!\n"); | 846 | "Failed to delete mgmt IEs!\n"); |
811 | 847 | ||
812 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | 848 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
813 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | 849 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { |
814 | mwifiex_dbg(priv->adapter, ERROR, | 850 | mwifiex_dbg(priv->adapter, ERROR, "Failed to stop the BSS\n"); |
815 | "Failed to stop the BSS\n"); | 851 | return -1; |
852 | } | ||
853 | |||
854 | if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, | ||
855 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | ||
856 | mwifiex_dbg(priv->adapter, ERROR, "Failed to reset BSS\n"); | ||
816 | return -1; | 857 | return -1; |
817 | } | 858 | } |
818 | 859 | ||
@@ -824,6 +865,16 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv, | |||
824 | return -1; | 865 | return -1; |
825 | } | 866 | } |
826 | 867 | ||
868 | /* Send cmd to FW to enable 11D function */ | ||
869 | state_11d = ENABLE_11D; | ||
870 | if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
871 | HostCmd_ACT_GEN_SET, DOT11D_I, | ||
872 | &state_11d, true)) { | ||
873 | mwifiex_dbg(priv->adapter, ERROR, | ||
874 | "11D: failed to enable 11D\n"); | ||
875 | return -1; | ||
876 | } | ||
877 | |||
827 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | 878 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, |
828 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { | 879 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { |
829 | mwifiex_dbg(priv->adapter, ERROR, | 880 | mwifiex_dbg(priv->adapter, ERROR, |
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 06ce3fe660f1..7bc1f850e3b7 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c | |||
@@ -21,8 +21,70 @@ | |||
21 | #include "main.h" | 21 | #include "main.h" |
22 | #include "11n.h" | 22 | #include "11n.h" |
23 | 23 | ||
24 | #define MWIFIEX_BSS_START_EVT_FIX_SIZE 12 | ||
24 | 25 | ||
26 | static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv, | ||
27 | struct sk_buff *event) | ||
28 | { | ||
29 | int evt_len; | ||
30 | u8 *curr; | ||
31 | u16 tlv_len; | ||
32 | struct mwifiex_ie_types_data *tlv_hdr; | ||
33 | struct ieee_types_wmm_parameter *wmm_param_ie = NULL; | ||
34 | int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK; | ||
35 | |||
36 | priv->wmm_enabled = false; | ||
37 | skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE); | ||
38 | evt_len = event->len; | ||
39 | curr = event->data; | ||
40 | |||
41 | mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:", | ||
42 | event->data, event->len); | ||
25 | 43 | ||
44 | while ((evt_len >= sizeof(tlv_hdr->header))) { | ||
45 | tlv_hdr = (struct mwifiex_ie_types_data *)curr; | ||
46 | tlv_len = le16_to_cpu(tlv_hdr->header.len); | ||
47 | |||
48 | if (evt_len < tlv_len + sizeof(tlv_hdr->header)) | ||
49 | break; | ||
50 | |||
51 | switch (le16_to_cpu(tlv_hdr->header.type)) { | ||
52 | case WLAN_EID_HT_CAPABILITY: | ||
53 | priv->ap_11n_enabled = true; | ||
54 | break; | ||
55 | |||
56 | case WLAN_EID_VHT_CAPABILITY: | ||
57 | priv->ap_11ac_enabled = true; | ||
58 | break; | ||
59 | |||
60 | case WLAN_EID_VENDOR_SPECIFIC: | ||
61 | /* Point the regular IEEE IE 2 bytes into the Marvell IE | ||
62 | * and setup the IEEE IE type and length byte fields | ||
63 | */ | ||
64 | wmm_param_ie = (void *)(curr + 2); | ||
65 | wmm_param_ie->vend_hdr.len = (u8)tlv_len; | ||
66 | wmm_param_ie->vend_hdr.element_id = | ||
67 | WLAN_EID_VENDOR_SPECIFIC; | ||
68 | mwifiex_dbg(priv->adapter, EVENT, | ||
69 | "info: check uap capabilities:\t" | ||
70 | "wmm parameter set count: %d\n", | ||
71 | wmm_param_ie->qos_info_bitmap & mask); | ||
72 | |||
73 | mwifiex_wmm_setup_ac_downgrade(priv); | ||
74 | priv->wmm_enabled = true; | ||
75 | mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); | ||
76 | break; | ||
77 | |||
78 | default: | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | curr += (tlv_len + sizeof(tlv_hdr->header)); | ||
83 | evt_len -= (tlv_len + sizeof(tlv_hdr->header)); | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
26 | 88 | ||
27 | /* | 89 | /* |
28 | * This function handles AP interface specific events generated by firmware. | 90 | * This function handles AP interface specific events generated by firmware. |
@@ -134,6 +196,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
134 | ETH_ALEN); | 196 | ETH_ALEN); |
135 | if (priv->hist_data) | 197 | if (priv->hist_data) |
136 | mwifiex_hist_data_reset(priv); | 198 | mwifiex_hist_data_reset(priv); |
199 | mwifiex_check_uap_capabilties(priv, adapter->event_skb); | ||
137 | break; | 200 | break; |
138 | case EVENT_UAP_MIC_COUNTERMEASURES: | 201 | case EVENT_UAP_MIC_COUNTERMEASURES: |
139 | /* For future development */ | 202 | /* For future development */ |
@@ -229,6 +292,11 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
229 | mwifiex_dbg(adapter, EVENT, "event: Radar detected\n"); | 292 | mwifiex_dbg(adapter, EVENT, "event: Radar detected\n"); |
230 | mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); | 293 | mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); |
231 | break; | 294 | break; |
295 | case EVENT_BT_COEX_WLAN_PARA_CHANGE: | ||
296 | dev_err(adapter->dev, "EVENT: BT coex wlan param update\n"); | ||
297 | mwifiex_bt_coex_wlan_param_update_event(priv, | ||
298 | adapter->event_skb); | ||
299 | break; | ||
232 | default: | 300 | default: |
233 | mwifiex_dbg(adapter, EVENT, | 301 | mwifiex_dbg(adapter, EVENT, |
234 | "event: unknown event id: %#x\n", eventcause); | 302 | "event: unknown event id: %#x\n", eventcause); |
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 61c52fdf945d..87667418af5f 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c | |||
@@ -97,6 +97,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, | |||
97 | struct mwifiex_txinfo *tx_info; | 97 | struct mwifiex_txinfo *tx_info; |
98 | int hdr_chop; | 98 | int hdr_chop; |
99 | struct ethhdr *p_ethhdr; | 99 | struct ethhdr *p_ethhdr; |
100 | struct mwifiex_sta_node *src_node; | ||
100 | 101 | ||
101 | uap_rx_pd = (struct uap_rxpd *)(skb->data); | 102 | uap_rx_pd = (struct uap_rxpd *)(skb->data); |
102 | rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); | 103 | 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, | |||
180 | tx_info->bss_type = priv->bss_type; | 181 | tx_info->bss_type = priv->bss_type; |
181 | tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; | 182 | tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; |
182 | 183 | ||
184 | src_node = mwifiex_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source); | ||
185 | if (src_node) { | ||
186 | src_node->stats.last_rx = jiffies; | ||
187 | src_node->stats.rx_bytes += skb->len; | ||
188 | src_node->stats.rx_packets++; | ||
189 | src_node->stats.last_tx_rate = uap_rx_pd->rx_rate; | ||
190 | src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info; | ||
191 | } | ||
192 | |||
183 | if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) { | 193 | if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) { |
184 | /* Update bridge packet statistics as the | 194 | /* Update bridge packet statistics as the |
185 | * packet is not going to kernel/upper layer. | 195 | * packet is not going to kernel/upper layer. |
@@ -275,6 +285,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |||
275 | rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); | 285 | rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); |
276 | rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); | 286 | rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); |
277 | 287 | ||
288 | ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source); | ||
289 | |||
278 | if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + | 290 | if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + |
279 | le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) { | 291 | le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) { |
280 | mwifiex_dbg(adapter, ERROR, | 292 | mwifiex_dbg(adapter, ERROR, |
@@ -282,6 +294,11 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |||
282 | skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset), | 294 | skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset), |
283 | le16_to_cpu(uap_rx_pd->rx_pkt_length)); | 295 | le16_to_cpu(uap_rx_pd->rx_pkt_length)); |
284 | priv->stats.rx_dropped++; | 296 | priv->stats.rx_dropped++; |
297 | |||
298 | node = mwifiex_get_sta_entry(priv, ta); | ||
299 | if (node) | ||
300 | node->stats.tx_failed++; | ||
301 | |||
285 | dev_kfree_skb_any(skb); | 302 | dev_kfree_skb_any(skb); |
286 | return 0; | 303 | return 0; |
287 | } | 304 | } |
@@ -295,7 +312,6 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |||
295 | return ret; | 312 | return ret; |
296 | } | 313 | } |
297 | 314 | ||
298 | memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); | ||
299 | 315 | ||
300 | if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) { | 316 | if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) { |
301 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | 317 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 370323a47ecb..790e61953abf 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -329,7 +329,7 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len, | |||
329 | struct rxpd *rx_pd) | 329 | struct rxpd *rx_pd) |
330 | { | 330 | { |
331 | u16 stype; | 331 | u16 stype; |
332 | u8 category, action_code; | 332 | u8 category, action_code, *addr2; |
333 | struct ieee80211_hdr *ieee_hdr = (void *)payload; | 333 | struct ieee80211_hdr *ieee_hdr = (void *)payload; |
334 | 334 | ||
335 | stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE); | 335 | 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, | |||
337 | switch (stype) { | 337 | switch (stype) { |
338 | case IEEE80211_STYPE_ACTION: | 338 | case IEEE80211_STYPE_ACTION: |
339 | category = *(payload + sizeof(struct ieee80211_hdr)); | 339 | category = *(payload + sizeof(struct ieee80211_hdr)); |
340 | action_code = *(payload + sizeof(struct ieee80211_hdr) + 1); | 340 | switch (category) { |
341 | if (category == WLAN_CATEGORY_PUBLIC && | 341 | case WLAN_CATEGORY_PUBLIC: |
342 | action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { | 342 | action_code = *(payload + sizeof(struct ieee80211_hdr) |
343 | + 1); | ||
344 | if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { | ||
345 | addr2 = ieee_hdr->addr2; | ||
346 | mwifiex_dbg(priv->adapter, INFO, | ||
347 | "TDLS discovery response %pM nf=%d, snr=%d\n", | ||
348 | addr2, rx_pd->nf, rx_pd->snr); | ||
349 | mwifiex_auto_tdls_update_peer_signal(priv, | ||
350 | addr2, | ||
351 | rx_pd->snr, | ||
352 | rx_pd->nf); | ||
353 | } | ||
354 | break; | ||
355 | case WLAN_CATEGORY_BACK: | ||
356 | /*we dont indicate BACK action frames to cfg80211*/ | ||
357 | mwifiex_dbg(priv->adapter, INFO, | ||
358 | "drop BACK action frames"); | ||
359 | return -1; | ||
360 | default: | ||
343 | mwifiex_dbg(priv->adapter, INFO, | 361 | mwifiex_dbg(priv->adapter, INFO, |
344 | "TDLS discovery response %pM nf=%d, snr=%d\n", | 362 | "unknown public action frame category %d\n", |
345 | ieee_hdr->addr2, rx_pd->nf, rx_pd->snr); | 363 | category); |
346 | mwifiex_auto_tdls_update_peer_signal(priv, | ||
347 | ieee_hdr->addr2, | ||
348 | rx_pd->snr, | ||
349 | rx_pd->nf); | ||
350 | } | 364 | } |
351 | break; | ||
352 | default: | 365 | default: |
353 | mwifiex_dbg(priv->adapter, INFO, | 366 | mwifiex_dbg(priv->adapter, INFO, |
354 | "unknown mgmt frame subtype %#x\n", stype); | 367 | "unknown mgmt frame subtype %#x\n", stype); |
368 | return 0; | ||
355 | } | 369 | } |
356 | 370 | ||
357 | return 0; | 371 | return 0; |
@@ -387,8 +401,9 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |||
387 | 401 | ||
388 | ieee_hdr = (void *)skb->data; | 402 | ieee_hdr = (void *)skb->data; |
389 | if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { | 403 | if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { |
390 | mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr, | 404 | if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr, |
391 | pkt_len, rx_pd); | 405 | pkt_len, rx_pd)) |
406 | return -1; | ||
392 | } | 407 | } |
393 | /* Remove address4 */ | 408 | /* Remove address4 */ |
394 | memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), | 409 | memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), |
@@ -416,12 +431,25 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |||
416 | */ | 431 | */ |
417 | int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | 432 | int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) |
418 | { | 433 | { |
434 | struct mwifiex_sta_node *src_node; | ||
435 | struct ethhdr *p_ethhdr; | ||
436 | |||
419 | if (!skb) | 437 | if (!skb) |
420 | return -1; | 438 | return -1; |
421 | 439 | ||
422 | priv->stats.rx_bytes += skb->len; | 440 | priv->stats.rx_bytes += skb->len; |
423 | priv->stats.rx_packets++; | 441 | priv->stats.rx_packets++; |
424 | 442 | ||
443 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
444 | p_ethhdr = (void *)skb->data; | ||
445 | src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source); | ||
446 | if (src_node) { | ||
447 | src_node->stats.last_rx = jiffies; | ||
448 | src_node->stats.rx_bytes += skb->len; | ||
449 | src_node->stats.rx_packets++; | ||
450 | } | ||
451 | } | ||
452 | |||
425 | skb->dev = priv->netdev; | 453 | skb->dev = priv->netdev; |
426 | skb->protocol = eth_type_trans(skb, priv->netdev); | 454 | skb->protocol = eth_type_trans(skb, priv->netdev); |
427 | skb->ip_summed = CHECKSUM_NONE; | 455 | skb->ip_summed = CHECKSUM_NONE; |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ebd5625d13f1..95c1d7c0a2f3 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -2961,6 +2961,15 @@ enum rt2800_eeprom_word { | |||
2961 | #define BCN_TBTT_OFFSET 64 | 2961 | #define BCN_TBTT_OFFSET 64 |
2962 | 2962 | ||
2963 | /* | 2963 | /* |
2964 | * Hardware has 255 WCID table entries. First 32 entries are reserved for | ||
2965 | * shared keys. Since parts of the pairwise key table might be shared with | ||
2966 | * the beacon frame buffers 6 & 7 we could only use the first 222 entries. | ||
2967 | */ | ||
2968 | #define WCID_START 33 | ||
2969 | #define WCID_END 222 | ||
2970 | #define STA_IDS_SIZE (WCID_END - WCID_START + 2) | ||
2971 | |||
2972 | /* | ||
2964 | * RT2800 driver data structure | 2973 | * RT2800 driver data structure |
2965 | */ | 2974 | */ |
2966 | struct rt2800_drv_data { | 2975 | struct rt2800_drv_data { |
@@ -2971,6 +2980,7 @@ struct rt2800_drv_data { | |||
2971 | u8 txmixer_gain_24g; | 2980 | u8 txmixer_gain_24g; |
2972 | u8 txmixer_gain_5g; | 2981 | u8 txmixer_gain_5g; |
2973 | unsigned int tbtt_tick; | 2982 | unsigned int tbtt_tick; |
2983 | DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); | ||
2974 | }; | 2984 | }; |
2975 | 2985 | ||
2976 | #endif /* RT2800_H */ | 2986 | #endif /* RT2800_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 0bc5ac56f283..9524564f873b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1381,38 +1381,6 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
1381 | } | 1381 | } |
1382 | EXPORT_SYMBOL_GPL(rt2800_config_shared_key); | 1382 | EXPORT_SYMBOL_GPL(rt2800_config_shared_key); |
1383 | 1383 | ||
1384 | static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev) | ||
1385 | { | ||
1386 | struct mac_wcid_entry wcid_entry; | ||
1387 | int idx; | ||
1388 | u32 offset; | ||
1389 | |||
1390 | /* | ||
1391 | * Search for the first free WCID entry and return the corresponding | ||
1392 | * index. | ||
1393 | * | ||
1394 | * Make sure the WCID starts _after_ the last possible shared key | ||
1395 | * entry (>32). | ||
1396 | * | ||
1397 | * Since parts of the pairwise key table might be shared with | ||
1398 | * the beacon frame buffers 6 & 7 we should only write into the | ||
1399 | * first 222 entries. | ||
1400 | */ | ||
1401 | for (idx = 33; idx <= 222; idx++) { | ||
1402 | offset = MAC_WCID_ENTRY(idx); | ||
1403 | rt2800_register_multiread(rt2x00dev, offset, &wcid_entry, | ||
1404 | sizeof(wcid_entry)); | ||
1405 | if (is_broadcast_ether_addr(wcid_entry.mac)) | ||
1406 | return idx; | ||
1407 | } | ||
1408 | |||
1409 | /* | ||
1410 | * Use -1 to indicate that we don't have any more space in the WCID | ||
1411 | * table. | ||
1412 | */ | ||
1413 | return -1; | ||
1414 | } | ||
1415 | |||
1416 | int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | 1384 | int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, |
1417 | struct rt2x00lib_crypto *crypto, | 1385 | struct rt2x00lib_crypto *crypto, |
1418 | struct ieee80211_key_conf *key) | 1386 | struct ieee80211_key_conf *key) |
@@ -1425,7 +1393,7 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
1425 | * Allow key configuration only for STAs that are | 1393 | * Allow key configuration only for STAs that are |
1426 | * known by the hw. | 1394 | * known by the hw. |
1427 | */ | 1395 | */ |
1428 | if (crypto->wcid < 0) | 1396 | if (crypto->wcid > WCID_END) |
1429 | return -ENOSPC; | 1397 | return -ENOSPC; |
1430 | key->hw_key_idx = crypto->wcid; | 1398 | key->hw_key_idx = crypto->wcid; |
1431 | 1399 | ||
@@ -1455,11 +1423,13 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, | |||
1455 | { | 1423 | { |
1456 | int wcid; | 1424 | int wcid; |
1457 | struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); | 1425 | struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); |
1426 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
1458 | 1427 | ||
1459 | /* | 1428 | /* |
1460 | * Find next free WCID. | 1429 | * Search for the first free WCID entry and return the corresponding |
1430 | * index. | ||
1461 | */ | 1431 | */ |
1462 | wcid = rt2800_find_wcid(rt2x00dev); | 1432 | wcid = find_first_zero_bit(drv_data->sta_ids, STA_IDS_SIZE) + WCID_START; |
1463 | 1433 | ||
1464 | /* | 1434 | /* |
1465 | * Store selected wcid even if it is invalid so that we can | 1435 | * 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, | |||
1471 | * No space left in the device, however, we can still communicate | 1441 | * No space left in the device, however, we can still communicate |
1472 | * with the STA -> No error. | 1442 | * with the STA -> No error. |
1473 | */ | 1443 | */ |
1474 | if (wcid < 0) | 1444 | if (wcid > WCID_END) |
1475 | return 0; | 1445 | return 0; |
1476 | 1446 | ||
1447 | __set_bit(wcid - WCID_START, drv_data->sta_ids); | ||
1448 | |||
1477 | /* | 1449 | /* |
1478 | * Clean up WCID attributes and write STA address to the device. | 1450 | * Clean up WCID attributes and write STA address to the device. |
1479 | */ | 1451 | */ |
@@ -1487,11 +1459,16 @@ EXPORT_SYMBOL_GPL(rt2800_sta_add); | |||
1487 | 1459 | ||
1488 | int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) | 1460 | int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) |
1489 | { | 1461 | { |
1462 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
1463 | |||
1464 | if (wcid > WCID_END) | ||
1465 | return 0; | ||
1490 | /* | 1466 | /* |
1491 | * Remove WCID entry, no need to clean the attributes as they will | 1467 | * Remove WCID entry, no need to clean the attributes as they will |
1492 | * get renewed when the WCID is reused. | 1468 | * get renewed when the WCID is reused. |
1493 | */ | 1469 | */ |
1494 | rt2800_config_wcid(rt2x00dev, NULL, wcid); | 1470 | rt2800_config_wcid(rt2x00dev, NULL, wcid); |
1471 | __clear_bit(wcid - WCID_START, drv_data->sta_ids); | ||
1495 | 1472 | ||
1496 | return 0; | 1473 | return 0; |
1497 | } | 1474 | } |
@@ -7968,11 +7945,11 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
7968 | /* | 7945 | /* |
7969 | * Don't allow aggregation for stations the hardware isn't aware | 7946 | * Don't allow aggregation for stations the hardware isn't aware |
7970 | * of because tx status reports for frames to an unknown station | 7947 | * of because tx status reports for frames to an unknown station |
7971 | * always contain wcid=255 and thus we can't distinguish between | 7948 | * always contain wcid=WCID_END+1 and thus we can't distinguish |
7972 | * multiple stations which leads to unwanted situations when the | 7949 | * between multiple stations which leads to unwanted situations |
7973 | * hw reorders frames due to aggregation. | 7950 | * when the hw reorders frames due to aggregation. |
7974 | */ | 7951 | */ |
7975 | if (sta_priv->wcid < 0) | 7952 | if (sta_priv->wcid > WCID_END) |
7976 | return 1; | 7953 | return 1; |
7977 | 7954 | ||
7978 | switch (action) { | 7955 | switch (action) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 1b8a459a412b..3c26ee65a415 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -535,16 +535,8 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
535 | struct ieee80211_sta *sta) | 535 | struct ieee80211_sta *sta) |
536 | { | 536 | { |
537 | struct rt2x00_dev *rt2x00dev = hw->priv; | 537 | struct rt2x00_dev *rt2x00dev = hw->priv; |
538 | struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); | ||
539 | 538 | ||
540 | /* | 539 | return rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta); |
541 | * If there's no space left in the device table store | ||
542 | * -1 as wcid but tell mac80211 everything went ok. | ||
543 | */ | ||
544 | if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta)) | ||
545 | sta_priv->wcid = -1; | ||
546 | |||
547 | return 0; | ||
548 | } | 540 | } |
549 | EXPORT_SYMBOL_GPL(rt2x00mac_sta_add); | 541 | EXPORT_SYMBOL_GPL(rt2x00mac_sta_add); |
550 | 542 | ||
@@ -554,12 +546,6 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
554 | struct rt2x00_dev *rt2x00dev = hw->priv; | 546 | struct rt2x00_dev *rt2x00dev = hw->priv; |
555 | struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); | 547 | struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); |
556 | 548 | ||
557 | /* | ||
558 | * If we never sent the STA to the device no need to clean it up. | ||
559 | */ | ||
560 | if (sta_priv->wcid < 0) | ||
561 | return 0; | ||
562 | |||
563 | return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid); | 549 | return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid); |
564 | } | 550 | } |
565 | EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); | 551 | EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c index d930c1f78721..ce4da9d79fbd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c | |||
@@ -1123,23 +1123,22 @@ static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw) | |||
1123 | void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) | 1123 | void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) |
1124 | { | 1124 | { |
1125 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1125 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1126 | static u8 tm_trigger; | ||
1127 | 1126 | ||
1128 | if (!rtlpriv->dm.txpower_tracking) | 1127 | if (!rtlpriv->dm.txpower_tracking) |
1129 | return; | 1128 | return; |
1130 | 1129 | ||
1131 | if (!tm_trigger) { | 1130 | if (!rtlpriv->dm.tm_trigger) { |
1132 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16), | 1131 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16), |
1133 | 0x03); | 1132 | 0x03); |
1134 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1133 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1135 | "Trigger 88E Thermal Meter!!\n"); | 1134 | "Trigger 88E Thermal Meter!!\n"); |
1136 | tm_trigger = 1; | 1135 | rtlpriv->dm.tm_trigger = 1; |
1137 | return; | 1136 | return; |
1138 | } else { | 1137 | } else { |
1139 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1138 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1140 | "Schedule TxPowerTracking !!\n"); | 1139 | "Schedule TxPowerTracking !!\n"); |
1141 | dm_txpower_track_cb_therm(hw); | 1140 | dm_txpower_track_cb_therm(hw); |
1142 | tm_trigger = 0; | 1141 | rtlpriv->dm.tm_trigger = 0; |
1143 | } | 1142 | } |
1144 | } | 1143 | } |
1145 | 1144 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index f5ee67cda73a..0aca6f47487c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | |||
@@ -1169,23 +1169,22 @@ static void rtl92c_dm_check_txpower_tracking_thermal_meter( | |||
1169 | struct ieee80211_hw *hw) | 1169 | struct ieee80211_hw *hw) |
1170 | { | 1170 | { |
1171 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1171 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1172 | static u8 tm_trigger; | ||
1173 | 1172 | ||
1174 | if (!rtlpriv->dm.txpower_tracking) | 1173 | if (!rtlpriv->dm.txpower_tracking) |
1175 | return; | 1174 | return; |
1176 | 1175 | ||
1177 | if (!tm_trigger) { | 1176 | if (!rtlpriv->dm.tm_trigger) { |
1178 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK, | 1177 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK, |
1179 | 0x60); | 1178 | 0x60); |
1180 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1179 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1181 | "Trigger 92S Thermal Meter!!\n"); | 1180 | "Trigger 92S Thermal Meter!!\n"); |
1182 | tm_trigger = 1; | 1181 | rtlpriv->dm.tm_trigger = 1; |
1183 | return; | 1182 | return; |
1184 | } else { | 1183 | } else { |
1185 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1184 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1186 | "Schedule TxPowerTracking direct call!!\n"); | 1185 | "Schedule TxPowerTracking direct call!!\n"); |
1187 | rtl92c_dm_txpower_tracking_directcall(hw); | 1186 | rtl92c_dm_txpower_tracking_directcall(hw); |
1188 | tm_trigger = 0; | 1187 | rtlpriv->dm.tm_trigger = 0; |
1189 | } | 1188 | } |
1190 | } | 1189 | } |
1191 | 1190 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 29983bc96a89..14b819ea8b71 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |||
@@ -233,13 +233,14 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) | |||
233 | pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; | 233 | pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; |
234 | pfwdata = (u8 *)rtlhal->pfirmware; | 234 | pfwdata = (u8 *)rtlhal->pfirmware; |
235 | fwsize = rtlhal->fwsize; | 235 | fwsize = rtlhal->fwsize; |
236 | |||
237 | if (IS_FW_HEADER_EXIST(pfwheader)) { | 236 | if (IS_FW_HEADER_EXIST(pfwheader)) { |
238 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | 237 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, |
239 | "Firmware Version(%d), Signature(%#x),Size(%d)\n", | 238 | "Firmware Version(%d), Signature(%#x),Size(%d)\n", |
240 | pfwheader->version, pfwheader->signature, | 239 | pfwheader->version, pfwheader->signature, |
241 | (int)sizeof(struct rtl92c_firmware_header)); | 240 | (int)sizeof(struct rtl92c_firmware_header)); |
242 | 241 | ||
242 | rtlhal->fw_version = pfwheader->version; | ||
243 | rtlhal->fw_subversion = pfwheader->subversion; | ||
243 | pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); | 244 | pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); |
244 | fwsize = fwsize - sizeof(struct rtl92c_firmware_header); | 245 | fwsize = fwsize - sizeof(struct rtl92c_firmware_header); |
245 | } | 246 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 189859617db8..767358a553fb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -840,6 +840,26 @@ static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) | |||
840 | rtl92c_set_data_filter(hw, value16); | 840 | rtl92c_set_data_filter(hw, value16); |
841 | } | 841 | } |
842 | 842 | ||
843 | static void _rtl92cu_init_beacon_parameters(struct ieee80211_hw *hw) | ||
844 | { | ||
845 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
846 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
847 | |||
848 | rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010); | ||
849 | |||
850 | /* TODO: Remove these magic number */ | ||
851 | rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404); | ||
852 | rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME); | ||
853 | rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); | ||
854 | /* Change beacon AIFS to the largest number | ||
855 | * beacause test chip does not contension before sending beacon. | ||
856 | */ | ||
857 | if (IS_NORMAL_CHIP(rtlhal->version)) | ||
858 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F); | ||
859 | else | ||
860 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); | ||
861 | } | ||
862 | |||
843 | static int _rtl92cu_init_mac(struct ieee80211_hw *hw) | 863 | static int _rtl92cu_init_mac(struct ieee80211_hw *hw) |
844 | { | 864 | { |
845 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 865 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -887,7 +907,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw) | |||
887 | _rtl92cu_init_usb_aggregation(hw); | 907 | _rtl92cu_init_usb_aggregation(hw); |
888 | rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20); | 908 | rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20); |
889 | rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version)); | 909 | rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version)); |
890 | rtl92c_init_beacon_parameters(hw, rtlhal->version); | 910 | _rtl92cu_init_beacon_parameters(hw); |
891 | rtl92c_init_ampdu_aggregation(hw); | 911 | rtl92c_init_ampdu_aggregation(hw); |
892 | rtl92c_init_beacon_max_error(hw); | 912 | rtl92c_init_beacon_max_error(hw); |
893 | return err; | 913 | return err; |
@@ -987,7 +1007,6 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
987 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 1007 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
988 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 1008 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
989 | int err = 0; | 1009 | int err = 0; |
990 | static bool iqk_initialized; | ||
991 | unsigned long flags; | 1010 | unsigned long flags; |
992 | 1011 | ||
993 | /* As this function can take a very long time (up to 350 ms) | 1012 | /* 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) | |||
1038 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); | 1057 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); |
1039 | if (ppsc->rfpwr_state == ERFON) { | 1058 | if (ppsc->rfpwr_state == ERFON) { |
1040 | rtl92c_phy_set_rfpath_switch(hw, 1); | 1059 | rtl92c_phy_set_rfpath_switch(hw, 1); |
1041 | if (iqk_initialized) { | 1060 | if (rtlphy->iqk_initialized) { |
1042 | rtl92c_phy_iq_calibrate(hw, true); | 1061 | rtl92c_phy_iq_calibrate(hw, true); |
1043 | } else { | 1062 | } else { |
1044 | rtl92c_phy_iq_calibrate(hw, false); | 1063 | rtl92c_phy_iq_calibrate(hw, false); |
1045 | iqk_initialized = true; | 1064 | rtlphy->iqk_initialized = true; |
1046 | } | 1065 | } |
1047 | rtl92c_dm_check_txpower_tracking(hw); | 1066 | rtl92c_dm_check_txpower_tracking(hw); |
1048 | rtl92c_phy_lc_calibrate(hw); | 1067 | rtl92c_phy_lc_calibrate(hw); |
@@ -1391,6 +1410,9 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw) | |||
1391 | _CardDisableHWSM(hw); | 1410 | _CardDisableHWSM(hw); |
1392 | else | 1411 | else |
1393 | _CardDisableWithoutHWSM(hw); | 1412 | _CardDisableWithoutHWSM(hw); |
1413 | |||
1414 | /* after power off we should do iqk again */ | ||
1415 | rtlpriv->phy.iqk_initialized = false; | ||
1394 | } | 1416 | } |
1395 | 1417 | ||
1396 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | 1418 | 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) | |||
1451 | return 0; | 1473 | return 0; |
1452 | } | 1474 | } |
1453 | 1475 | ||
1454 | static void _InitBeaconParameters(struct ieee80211_hw *hw) | ||
1455 | { | ||
1456 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1457 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
1458 | |||
1459 | rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010); | ||
1460 | |||
1461 | /* TODO: Remove these magic number */ | ||
1462 | rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404); | ||
1463 | rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME); | ||
1464 | rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); | ||
1465 | /* Change beacon AIFS to the largest number | ||
1466 | * beacause test chip does not contension before sending beacon. */ | ||
1467 | if (IS_NORMAL_CHIP(rtlhal->version)) | ||
1468 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F); | ||
1469 | else | ||
1470 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); | ||
1471 | } | ||
1472 | |||
1473 | static void _beacon_function_enable(struct ieee80211_hw *hw) | 1476 | static void _beacon_function_enable(struct ieee80211_hw *hw) |
1474 | { | 1477 | { |
1475 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1478 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1490,7 +1493,7 @@ void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) | |||
1490 | atim_window = 2; /*FIX MERGE */ | 1493 | atim_window = 2; /*FIX MERGE */ |
1491 | rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); | 1494 | rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); |
1492 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | 1495 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); |
1493 | _InitBeaconParameters(hw); | 1496 | _rtl92cu_init_beacon_parameters(hw); |
1494 | rtl_write_byte(rtlpriv, REG_SLOT, 0x09); | 1497 | rtl_write_byte(rtlpriv, REG_SLOT, 0x09); |
1495 | /* | 1498 | /* |
1496 | * Force beacon frame transmission even after receiving beacon frame | 1499 | * Force beacon frame transmission even after receiving beacon frame |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index f3db6bc8596a..490a7cf7c702 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | |||
@@ -641,21 +641,6 @@ void rtl92c_init_retry_function(struct ieee80211_hw *hw) | |||
641 | rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); | 641 | rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); |
642 | } | 642 | } |
643 | 643 | ||
644 | void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw, | ||
645 | enum version_8192c version) | ||
646 | { | ||
647 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
648 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
649 | |||
650 | rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */ | ||
651 | rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/ | ||
652 | rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); | ||
653 | if (IS_NORMAL_CHIP(rtlhal->version)) | ||
654 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F); | ||
655 | else | ||
656 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); | ||
657 | } | ||
658 | |||
659 | void rtl92c_disable_fast_edca(struct ieee80211_hw *hw) | 644 | void rtl92c_disable_fast_edca(struct ieee80211_hw *hw) |
660 | { | 645 | { |
661 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 646 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h index 58548e8f2c41..e34f0f14ccd7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h | |||
@@ -70,9 +70,6 @@ void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw); | |||
70 | void rtl92c_init_rdg_setting(struct ieee80211_hw *hw); | 70 | void rtl92c_init_rdg_setting(struct ieee80211_hw *hw); |
71 | void rtl92c_init_retry_function(struct ieee80211_hw *hw); | 71 | void rtl92c_init_retry_function(struct ieee80211_hw *hw); |
72 | 72 | ||
73 | void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw, | ||
74 | enum version_8192c version); | ||
75 | |||
76 | void rtl92c_disable_fast_edca(struct ieee80211_hw *hw); | 73 | void rtl92c_disable_fast_edca(struct ieee80211_hw *hw); |
77 | void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T); | 74 | void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T); |
78 | 75 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 12f6d474b492..c972fa50926d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | |||
@@ -108,13 +108,8 @@ void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, | |||
108 | bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw) | 108 | bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw) |
109 | { | 109 | { |
110 | bool rtstatus; | 110 | bool rtstatus; |
111 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
112 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
113 | bool is92c = IS_92C_SERIAL(rtlhal->version); | ||
114 | 111 | ||
115 | rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw); | 112 | rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw); |
116 | if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal)) | ||
117 | rtl_write_byte(rtlpriv, 0x14, 0x71); | ||
118 | return rtstatus; | 113 | return rtstatus; |
119 | } | 114 | } |
120 | 115 | ||
@@ -122,7 +117,6 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) | |||
122 | { | 117 | { |
123 | bool rtstatus = true; | 118 | bool rtstatus = true; |
124 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 119 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
125 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
126 | u16 regval; | 120 | u16 regval; |
127 | u32 regval32; | 121 | u32 regval32; |
128 | u8 b_reg_hwparafile = 1; | 122 | u8 b_reg_hwparafile = 1; |
@@ -134,17 +128,11 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) | |||
134 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); | 128 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); |
135 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); | 129 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); |
136 | rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); | 130 | rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); |
137 | if (IS_HARDWARE_TYPE_8192CE(rtlhal)) { | 131 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | |
138 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | | 132 | FEN_BB_GLB_RSTn | FEN_BBRSTB); |
139 | FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB); | ||
140 | } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) { | ||
141 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | | ||
142 | FEN_BB_GLB_RSTn | FEN_BBRSTB); | ||
143 | } | ||
144 | regval32 = rtl_read_dword(rtlpriv, 0x87c); | 133 | regval32 = rtl_read_dword(rtlpriv, 0x87c); |
145 | rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); | 134 | rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); |
146 | if (IS_HARDWARE_TYPE_8192CU(rtlhal)) | 135 | rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); |
147 | rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); | ||
148 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); | 136 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); |
149 | if (b_reg_hwparafile == 1) | 137 | if (b_reg_hwparafile == 1) |
150 | rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); | 138 | rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); |
@@ -162,7 +150,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) | |||
162 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); | 150 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); |
163 | arraylength = rtlphy->hwparam_tables[MAC_REG].length ; | 151 | arraylength = rtlphy->hwparam_tables[MAC_REG].length ; |
164 | ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata; | 152 | ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata; |
165 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n"); | 153 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n"); |
166 | for (i = 0; i < arraylength; i = i + 2) | 154 | for (i = 0; i < arraylength; i = i + 2) |
167 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); | 155 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); |
168 | return true; | 156 | return true; |
@@ -259,18 +247,18 @@ bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | |||
259 | radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length; | 247 | radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length; |
260 | radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata; | 248 | radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata; |
261 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | 249 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
262 | "Radio_A:RTL8192CERADIOA_2TARRAY\n"); | 250 | "Radio_A:RTL8192CURADIOA_2TARRAY\n"); |
263 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | 251 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
264 | "Radio_B:RTL8192CE_RADIOB_2TARRAY\n"); | 252 | "Radio_B:RTL8192CU_RADIOB_2TARRAY\n"); |
265 | } else { | 253 | } else { |
266 | radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length; | 254 | radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length; |
267 | radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata; | 255 | radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata; |
268 | radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length; | 256 | radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length; |
269 | radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata; | 257 | radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata; |
270 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | 258 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
271 | "Radio_A:RTL8192CE_RADIOA_1TARRAY\n"); | 259 | "Radio_A:RTL8192CU_RADIOA_1TARRAY\n"); |
272 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | 260 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
273 | "Radio_B:RTL8192CE_RADIOB_1TARRAY\n"); | 261 | "Radio_B:RTL8192CU_RADIOB_1TARRAY\n"); |
274 | } | 262 | } |
275 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); | 263 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); |
276 | switch (rfpath) { | 264 | switch (rfpath) { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index b878d56d2f4d..5624ade92cc0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | |||
@@ -66,7 +66,6 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | |||
66 | { | 66 | { |
67 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 67 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
68 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 68 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
69 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
70 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 69 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
71 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 70 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
72 | u32 tx_agc[2] = { 0, 0 }, tmpval = 0; | 71 | u32 tx_agc[2] = { 0, 0 }, tmpval = 0; |
@@ -74,14 +73,8 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | |||
74 | u8 idx1, idx2; | 73 | u8 idx1, idx2; |
75 | u8 *ptr; | 74 | u8 *ptr; |
76 | 75 | ||
77 | if (rtlhal->interface == INTF_PCI) { | 76 | if ((rtlefuse->eeprom_regulatory != 0) || (rtlefuse->external_pa)) |
78 | if (rtlefuse->eeprom_regulatory != 0) | 77 | turbo_scanoff = true; |
79 | turbo_scanoff = true; | ||
80 | } else { | ||
81 | if ((rtlefuse->eeprom_regulatory != 0) || | ||
82 | (rtlefuse->external_pa)) | ||
83 | turbo_scanoff = true; | ||
84 | } | ||
85 | if (mac->act_scanning) { | 78 | if (mac->act_scanning) { |
86 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; | 79 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; |
87 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; | 80 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; |
@@ -90,11 +83,8 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | |||
90 | (ppowerlevel[idx1] << 8) | | 83 | (ppowerlevel[idx1] << 8) | |
91 | (ppowerlevel[idx1] << 16) | | 84 | (ppowerlevel[idx1] << 16) | |
92 | (ppowerlevel[idx1] << 24); | 85 | (ppowerlevel[idx1] << 24); |
93 | if (rtlhal->interface == INTF_USB) { | 86 | if (tx_agc[idx1] > 0x20 && rtlefuse->external_pa) |
94 | if (tx_agc[idx1] > 0x20 && | 87 | tx_agc[idx1] = 0x20; |
95 | rtlefuse->external_pa) | ||
96 | tx_agc[idx1] = 0x20; | ||
97 | } | ||
98 | } | 88 | } |
99 | } else { | 89 | } else { |
100 | if (rtlpriv->dm.dynamic_txhighpower_lvl == | 90 | if (rtlpriv->dm.dynamic_txhighpower_lvl == |
@@ -452,9 +442,6 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) | |||
452 | udelay(1); | 442 | udelay(1); |
453 | switch (rfpath) { | 443 | switch (rfpath) { |
454 | case RF90_PATH_A: | 444 | case RF90_PATH_A: |
455 | rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw, | ||
456 | (enum radio_path) rfpath); | ||
457 | break; | ||
458 | case RF90_PATH_B: | 445 | case RF90_PATH_B: |
459 | rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw, | 446 | rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw, |
460 | (enum radio_path) rfpath); | 447 | (enum radio_path) rfpath); |
@@ -483,7 +470,6 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) | |||
483 | } | 470 | } |
484 | } | 471 | } |
485 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); | 472 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); |
486 | return rtstatus; | ||
487 | phy_rf_cfg_fail: | 473 | phy_rf_cfg_fail: |
488 | return rtstatus; | 474 | return rtstatus; |
489 | } | 475 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index cbead007171f..95880fe4106e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | |||
@@ -321,7 +321,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, | |||
321 | stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc); | 321 | stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc); |
322 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); | 322 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); |
323 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); | 323 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); |
324 | stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) | 324 | stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) |
325 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); | 325 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); |
326 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); | 326 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); |
327 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); | 327 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index a1be5a68edfb..587b8c505a76 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c | |||
@@ -1240,23 +1240,22 @@ static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) | |||
1240 | void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw) | 1240 | void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw) |
1241 | { | 1241 | { |
1242 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1242 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1243 | static u8 tm_trigger; | ||
1244 | 1243 | ||
1245 | if (!rtlpriv->dm.txpower_tracking) | 1244 | if (!rtlpriv->dm.txpower_tracking) |
1246 | return; | 1245 | return; |
1247 | 1246 | ||
1248 | if (!tm_trigger) { | 1247 | if (!rtlpriv->dm.tm_trigger) { |
1249 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | | 1248 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | |
1250 | BIT(16), 0x03); | 1249 | BIT(16), 0x03); |
1251 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1250 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1252 | "Trigger 92S Thermal Meter!!\n"); | 1251 | "Trigger 92S Thermal Meter!!\n"); |
1253 | tm_trigger = 1; | 1252 | rtlpriv->dm.tm_trigger = 1; |
1254 | return; | 1253 | return; |
1255 | } else { | 1254 | } else { |
1256 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1255 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1257 | "Schedule TxPowerTracking direct call!!\n"); | 1256 | "Schedule TxPowerTracking direct call!!\n"); |
1258 | rtl92d_dm_txpower_tracking_callback_thermalmeter(hw); | 1257 | rtl92d_dm_txpower_tracking_callback_thermalmeter(hw); |
1259 | tm_trigger = 0; | 1258 | rtlpriv->dm.tm_trigger = 0; |
1260 | } | 1259 | } |
1261 | } | 1260 | } |
1262 | 1261 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c index 575980b88658..9bae5a92e30f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c | |||
@@ -200,7 +200,6 @@ static void _rtl92s_dm_check_txpowertracking_thermalmeter( | |||
200 | { | 200 | { |
201 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 201 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
202 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 202 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
203 | static u8 tm_trigger; | ||
204 | u8 tx_power_checkcnt = 5; | 203 | u8 tx_power_checkcnt = 5; |
205 | 204 | ||
206 | /* 2T2R TP issue */ | 205 | /* 2T2R TP issue */ |
@@ -215,13 +214,13 @@ static void _rtl92s_dm_check_txpowertracking_thermalmeter( | |||
215 | return; | 214 | return; |
216 | } | 215 | } |
217 | 216 | ||
218 | if (!tm_trigger) { | 217 | if (!rtlpriv->dm.tm_trigger) { |
219 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, | 218 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, |
220 | RFREG_OFFSET_MASK, 0x60); | 219 | RFREG_OFFSET_MASK, 0x60); |
221 | tm_trigger = 1; | 220 | rtlpriv->dm.tm_trigger = 1; |
222 | } else { | 221 | } else { |
223 | _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); | 222 | _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); |
224 | tm_trigger = 0; | 223 | rtlpriv->dm.tm_trigger = 0; |
225 | } | 224 | } |
226 | } | 225 | } |
227 | 226 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/rtlwifi/rtl8723be/dm.c index e77c3a46c94a..3a81cdba8ca3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/dm.c | |||
@@ -909,23 +909,22 @@ static void rtl8723be_dm_txpower_tracking_callback_thermalmeter( | |||
909 | void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw) | 909 | void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw) |
910 | { | 910 | { |
911 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 911 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
912 | static u8 tm_trigger; | ||
913 | 912 | ||
914 | if (!rtlpriv->dm.txpower_tracking) | 913 | if (!rtlpriv->dm.txpower_tracking) |
915 | return; | 914 | return; |
916 | 915 | ||
917 | if (!tm_trigger) { | 916 | if (!rtlpriv->dm.tm_trigger) { |
918 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16), | 917 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16), |
919 | 0x03); | 918 | 0x03); |
920 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 919 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
921 | "Trigger 8723be Thermal Meter!!\n"); | 920 | "Trigger 8723be Thermal Meter!!\n"); |
922 | tm_trigger = 1; | 921 | rtlpriv->dm.tm_trigger = 1; |
923 | return; | 922 | return; |
924 | } else { | 923 | } else { |
925 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 924 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
926 | "Schedule TxPowerTracking !!\n"); | 925 | "Schedule TxPowerTracking !!\n"); |
927 | rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw); | 926 | rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw); |
928 | tm_trigger = 0; | 927 | rtlpriv->dm.tm_trigger = 0; |
929 | } | 928 | } |
930 | } | 929 | } |
931 | 930 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c index 342678d2ed42..b57cfd965196 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c | |||
@@ -1068,20 +1068,18 @@ static void rtl8812ae_dm_check_txpower_tracking_thermalmeter( | |||
1068 | struct ieee80211_hw *hw) | 1068 | struct ieee80211_hw *hw) |
1069 | { | 1069 | { |
1070 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1070 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1071 | static u8 tm_trigger; | ||
1072 | 1071 | ||
1073 | if (!tm_trigger) { | 1072 | if (!rtlpriv->dm.tm_trigger) { |
1074 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, | 1073 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, |
1075 | BIT(17) | BIT(16), 0x03); | 1074 | BIT(17) | BIT(16), 0x03); |
1076 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1075 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1077 | "Trigger 8812 Thermal Meter!!\n"); | 1076 | "Trigger 8812 Thermal Meter!!\n"); |
1078 | tm_trigger = 1; | 1077 | rtlpriv->dm.tm_trigger = 1; |
1079 | return; | 1078 | return; |
1080 | } | 1079 | } |
1081 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 1080 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
1082 | "Schedule TxPowerTracking direct call!!\n"); | 1081 | "Schedule TxPowerTracking direct call!!\n"); |
1083 | rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw); | 1082 | rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw); |
1084 | tm_trigger = 0; | ||
1085 | } | 1083 | } |
1086 | 1084 | ||
1087 | static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw) | 1085 | static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw) |
@@ -2519,21 +2517,19 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( | |||
2519 | void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw) | 2517 | void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw) |
2520 | { | 2518 | { |
2521 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 2519 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2522 | static u8 tm_trigger; | 2520 | if (!rtlpriv->dm.tm_trigger) { |
2523 | |||
2524 | if (!tm_trigger) { | ||
2525 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16), | 2521 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16), |
2526 | 0x03); | 2522 | 0x03); |
2527 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 2523 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
2528 | "Trigger 8821ae Thermal Meter!!\n"); | 2524 | "Trigger 8821ae Thermal Meter!!\n"); |
2529 | tm_trigger = 1; | 2525 | rtlpriv->dm.tm_trigger = 1; |
2530 | return; | 2526 | return; |
2531 | } else { | 2527 | } else { |
2532 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | 2528 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, |
2533 | "Schedule TxPowerTracking !!\n"); | 2529 | "Schedule TxPowerTracking !!\n"); |
2534 | 2530 | ||
2535 | rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw); | 2531 | rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw); |
2536 | tm_trigger = 0; | 2532 | rtlpriv->dm.tm_trigger = 0; |
2537 | } | 2533 | } |
2538 | } | 2534 | } |
2539 | 2535 | ||
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 51572912c53d..2b770b5e2620 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -1665,6 +1665,7 @@ struct rtl_dm { | |||
1665 | u8 last_dtp_lvl; | 1665 | u8 last_dtp_lvl; |
1666 | u8 thermalvalue_avg[AVG_THERMAL_NUM]; | 1666 | u8 thermalvalue_avg[AVG_THERMAL_NUM]; |
1667 | u8 thermalvalue_avg_index; | 1667 | u8 thermalvalue_avg_index; |
1668 | u8 tm_trigger; | ||
1668 | bool done_txpower; | 1669 | bool done_txpower; |
1669 | u8 dynamic_txhighpower_lvl; /*Tx high power level */ | 1670 | u8 dynamic_txhighpower_lvl; /*Tx high power level */ |
1670 | u8 dm_flag; /*Indicate each dynamic mechanism's status. */ | 1671 | u8 dm_flag; /*Indicate each dynamic mechanism's status. */ |
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c index 5695628757ee..d6fbdda2cba3 100644 --- a/drivers/net/wireless/ti/wl1251/acx.c +++ b/drivers/net/wireless/ti/wl1251/acx.c | |||
@@ -53,10 +53,7 @@ int wl1251_acx_station_id(struct wl1251 *wl) | |||
53 | mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; | 53 | mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; |
54 | 54 | ||
55 | ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac)); | 55 | ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac)); |
56 | if (ret < 0) | ||
57 | goto out; | ||
58 | 56 | ||
59 | out: | ||
60 | kfree(mac); | 57 | kfree(mac); |
61 | return ret; | 58 | return ret; |
62 | } | 59 | } |