aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2013-09-13 08:16:56 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2013-09-16 12:47:46 -0400
commited54388a38d817dce7fe22e7dc80fc13b1a6838e (patch)
tree8af974a287b4ed329f511725b87a62265d362763
parent12acbc43c1c302022984bf0af89ac5f0a24b133a (diff)
ath10k: improve beacon submission latency
The patch prevents beacon misses in some case of heavy load on a system. If a beacon can't be transmitted directly from an SWBA event it will be left in arvif->beacon and transmission will be retried once TX credits become available. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c74
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h3
4 files changed, 71 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index c953a3317d7b..14b7d3de6883 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -204,6 +204,7 @@ struct ath10k_vif {
204 enum wmi_vdev_subtype vdev_subtype; 204 enum wmi_vdev_subtype vdev_subtype;
205 u32 beacon_interval; 205 u32 beacon_interval;
206 u32 dtim_period; 206 u32 dtim_period;
207 struct sk_buff *beacon;
207 208
208 struct ath10k *ar; 209 struct ath10k *ar;
209 struct ieee80211_vif *vif; 210 struct ieee80211_vif *vif;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 8b9fb660519b..6c3e9d1f80d9 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2075,6 +2075,13 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
2075 2075
2076 mutex_lock(&ar->conf_mutex); 2076 mutex_lock(&ar->conf_mutex);
2077 2077
2078 spin_lock_bh(&ar->data_lock);
2079 if (arvif->beacon) {
2080 dev_kfree_skb_any(arvif->beacon);
2081 arvif->beacon = NULL;
2082 }
2083 spin_unlock_bh(&ar->data_lock);
2084
2078 ar->free_vdev_map |= 1 << (arvif->vdev_id); 2085 ar->free_vdev_map |= 1 << (arvif->vdev_id);
2079 2086
2080 if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { 2087 if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ff407c2f1d2b..9152daea9d96 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -120,8 +120,53 @@ err_pull:
120 return ret; 120 return ret;
121} 121}
122 122
123static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
124{
125 struct wmi_bcn_tx_arg arg = {0};
126 int ret;
127
128 lockdep_assert_held(&arvif->ar->data_lock);
129
130 if (arvif->beacon == NULL)
131 return;
132
133 arg.vdev_id = arvif->vdev_id;
134 arg.tx_rate = 0;
135 arg.tx_power = 0;
136 arg.bcn = arvif->beacon->data;
137 arg.bcn_len = arvif->beacon->len;
138
139 ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg);
140 if (ret)
141 return;
142
143 dev_kfree_skb_any(arvif->beacon);
144 arvif->beacon = NULL;
145}
146
147static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
148 struct ieee80211_vif *vif)
149{
150 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
151
152 ath10k_wmi_tx_beacon_nowait(arvif);
153}
154
155static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar)
156{
157 spin_lock_bh(&ar->data_lock);
158 ieee80211_iterate_active_interfaces_atomic(ar->hw,
159 IEEE80211_IFACE_ITER_NORMAL,
160 ath10k_wmi_tx_beacons_iter,
161 NULL);
162 spin_unlock_bh(&ar->data_lock);
163}
164
123static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) 165static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
124{ 166{
167 /* try to send pending beacons first. they take priority */
168 ath10k_wmi_tx_beacons_nowait(ar);
169
125 wake_up(&ar->wmi.tx_credits_wq); 170 wake_up(&ar->wmi.tx_credits_wq);
126} 171}
127 172
@@ -131,6 +176,9 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
131 int ret = -EINVAL; 176 int ret = -EINVAL;
132 177
133 wait_event_timeout(ar->wmi.tx_credits_wq, ({ 178 wait_event_timeout(ar->wmi.tx_credits_wq, ({
179 /* try to send pending beacons first. they take priority */
180 ath10k_wmi_tx_beacons_nowait(ar);
181
134 ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); 182 ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
135 (ret != -EAGAIN); 183 (ret != -EAGAIN);
136 }), 3*HZ); 184 }), 3*HZ);
@@ -760,10 +808,8 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
760 int i = -1; 808 int i = -1;
761 struct wmi_bcn_info *bcn_info; 809 struct wmi_bcn_info *bcn_info;
762 struct ath10k_vif *arvif; 810 struct ath10k_vif *arvif;
763 struct wmi_bcn_tx_arg arg;
764 struct sk_buff *bcn; 811 struct sk_buff *bcn;
765 int vdev_id = 0; 812 int vdev_id = 0;
766 int ret;
767 813
768 ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); 814 ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n");
769 815
@@ -820,17 +866,17 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
820 ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info); 866 ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info);
821 ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); 867 ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
822 868
823 arg.vdev_id = arvif->vdev_id; 869 spin_lock_bh(&ar->data_lock);
824 arg.tx_rate = 0; 870 if (arvif->beacon) {
825 arg.tx_power = 0; 871 ath10k_warn("SWBA overrun on vdev %d\n",
826 arg.bcn = bcn->data; 872 arvif->vdev_id);
827 arg.bcn_len = bcn->len; 873 dev_kfree_skb_any(arvif->beacon);
874 }
828 875
829 ret = ath10k_wmi_beacon_send(ar, &arg); 876 arvif->beacon = bcn;
830 if (ret)
831 ath10k_warn("could not send beacon (%d)\n", ret);
832 877
833 dev_kfree_skb_any(bcn); 878 ath10k_wmi_tx_beacon_nowait(arvif);
879 spin_unlock_bh(&ar->data_lock);
834 } 880 }
835} 881}
836 882
@@ -1181,6 +1227,7 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
1181 * thus can't be defered to a worker thread */ 1227 * thus can't be defered to a worker thread */
1182 switch (event_id) { 1228 switch (event_id) {
1183 case WMI_MGMT_RX_EVENTID: 1229 case WMI_MGMT_RX_EVENTID:
1230 case WMI_HOST_SWBA_EVENTID:
1184 ath10k_wmi_event_process(ar, skb); 1231 ath10k_wmi_event_process(ar, skb);
1185 return; 1232 return;
1186 default: 1233 default:
@@ -2138,7 +2185,8 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
2138 return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID); 2185 return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID);
2139} 2186}
2140 2187
2141int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg) 2188int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
2189 const struct wmi_bcn_tx_arg *arg)
2142{ 2190{
2143 struct wmi_bcn_tx_cmd *cmd; 2191 struct wmi_bcn_tx_cmd *cmd;
2144 struct sk_buff *skb; 2192 struct sk_buff *skb;
@@ -2154,7 +2202,7 @@ int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg)
2154 cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); 2202 cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len);
2155 memcpy(cmd->bcn, arg->bcn, arg->bcn_len); 2203 memcpy(cmd->bcn, arg->bcn, arg->bcn_len);
2156 2204
2157 return ath10k_wmi_cmd_send(ar, skb, WMI_BCN_TX_CMDID); 2205 return ath10k_wmi_cmd_send_nowait(ar, skb, WMI_BCN_TX_CMDID);
2158} 2206}
2159 2207
2160static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, 2208static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index ab46582d4eaa..b100431f2241 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3110,7 +3110,8 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
3110 enum wmi_ap_ps_peer_param param_id, u32 value); 3110 enum wmi_ap_ps_peer_param param_id, u32 value);
3111int ath10k_wmi_scan_chan_list(struct ath10k *ar, 3111int ath10k_wmi_scan_chan_list(struct ath10k *ar,
3112 const struct wmi_scan_chan_list_arg *arg); 3112 const struct wmi_scan_chan_list_arg *arg);
3113int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg); 3113int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
3114 const struct wmi_bcn_tx_arg *arg);
3114int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, 3115int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
3115 const struct wmi_pdev_set_wmm_params_arg *arg); 3116 const struct wmi_pdev_set_wmm_params_arg *arg);
3116int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); 3117int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);