diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mci.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/btcoex.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/btcoex.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mci.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mci.h | 3 |
5 files changed, 110 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 2a2d0188961..29282348eb4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -196,7 +196,6 @@ enum mci_state_type { | |||
196 | MCI_STATE_SEND_WLAN_COEX_VERSION, | 196 | MCI_STATE_SEND_WLAN_COEX_VERSION, |
197 | MCI_STATE_SEND_VERSION_QUERY, | 197 | MCI_STATE_SEND_VERSION_QUERY, |
198 | MCI_STATE_SEND_STATUS_QUERY, | 198 | MCI_STATE_SEND_STATUS_QUERY, |
199 | MCI_STATE_SET_CONCUR_TX_PRI, | ||
200 | MCI_STATE_RECOVER_RX, | 199 | MCI_STATE_RECOVER_RX, |
201 | MCI_STATE_NEED_FTP_STOMP, | 200 | MCI_STATE_NEED_FTP_STOMP, |
202 | MCI_STATE_DEBUG, | 201 | MCI_STATE_DEBUG, |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 419e9a3f2fe..05d9be5be52 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -218,27 +218,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | |||
218 | enum ath_stomp_type stomp_type) | 218 | enum ath_stomp_type stomp_type) |
219 | { | 219 | { |
220 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 220 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
221 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
222 | u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */ | ||
223 | bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]); | ||
224 | const u32 *weight = ar9003_wlan_weights[stomp_type]; | ||
225 | int i; | ||
221 | 226 | ||
222 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 227 | if (!AR_SREV_9300_20_OR_LATER(ah)) { |
223 | const u32 *weight = ar9003_wlan_weights[stomp_type]; | ||
224 | int i; | ||
225 | |||
226 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
227 | if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | ||
228 | btcoex_hw->mci.stomp_ftp) | ||
229 | stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; | ||
230 | weight = mci_wlan_weights[stomp_type]; | ||
231 | } | ||
232 | |||
233 | for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | ||
234 | btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; | ||
235 | btcoex_hw->wlan_weight[i] = weight[i]; | ||
236 | } | ||
237 | } else { | ||
238 | btcoex_hw->bt_coex_weights = | 228 | btcoex_hw->bt_coex_weights = |
239 | SM(bt_weight, AR_BTCOEX_BT_WGHT) | | 229 | SM(bt_weight, AR_BTCOEX_BT_WGHT) | |
240 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); | 230 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); |
231 | return; | ||
232 | } | ||
233 | |||
234 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
235 | enum ath_stomp_type stype = | ||
236 | ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | ||
237 | btcoex_hw->mci.stomp_ftp) ? | ||
238 | ATH_BTCOEX_STOMP_LOW_FTP : stomp_type; | ||
239 | weight = mci_wlan_weights[stype]; | ||
241 | } | 240 | } |
241 | |||
242 | for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | ||
243 | btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; | ||
244 | btcoex_hw->wlan_weight[i] = weight[i]; | ||
245 | if (concur_tx && i) { | ||
246 | btcoex_hw->wlan_weight[i] &= | ||
247 | ~(0xff << txprio_shift[i-1]); | ||
248 | btcoex_hw->wlan_weight[i] |= | ||
249 | (btcoex_hw->tx_prio[stomp_type] << | ||
250 | txprio_shift[i-1]); | ||
251 | } | ||
252 | } | ||
253 | /* Last WLAN weight has to be adjusted wrt tx priority */ | ||
254 | if (concur_tx) { | ||
255 | btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]); | ||
256 | btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type] | ||
257 | << txprio_shift[i-1]); | ||
258 | } | ||
259 | |||
242 | } | 260 | } |
243 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); | 261 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); |
244 | 262 | ||
@@ -385,3 +403,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, | |||
385 | } | 403 | } |
386 | } | 404 | } |
387 | EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); | 405 | EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); |
406 | |||
407 | void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio) | ||
408 | { | ||
409 | struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; | ||
410 | int i; | ||
411 | |||
412 | for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) | ||
413 | btcoex->tx_prio[i] = stomp_txprio[i]; | ||
414 | } | ||
415 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio); | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 385197ad79b..a260fcb99d1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -84,6 +84,7 @@ struct ath9k_hw_mci { | |||
84 | u8 bt_ver_minor; | 84 | u8 bt_ver_minor; |
85 | u8 bt_state; | 85 | u8 bt_state; |
86 | u8 stomp_ftp; | 86 | u8 stomp_ftp; |
87 | bool concur_tx; | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | struct ath_btcoex_hw { | 90 | struct ath_btcoex_hw { |
@@ -98,6 +99,7 @@ struct ath_btcoex_hw { | |||
98 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ | 99 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ |
99 | u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; | 100 | u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; |
100 | u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; | 101 | u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; |
102 | u8 tx_prio[ATH_BTCOEX_STOMP_MAX]; | ||
101 | }; | 103 | }; |
102 | 104 | ||
103 | void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); | 105 | void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); |
@@ -112,5 +114,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | |||
112 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); | 114 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); |
113 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, | 115 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, |
114 | enum ath_stomp_type stomp_type); | 116 | enum ath_stomp_type stomp_type); |
117 | void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio); | ||
115 | 118 | ||
116 | #endif | 119 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 1733a5ac327..b37c8af6e02 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common, | |||
43 | struct ath_mci_profile_info *info) | 43 | struct ath_mci_profile_info *info) |
44 | { | 44 | { |
45 | struct ath_mci_profile_info *entry; | 45 | struct ath_mci_profile_info *entry; |
46 | u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 }; | ||
46 | 47 | ||
47 | if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) && | 48 | if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) && |
48 | (info->type == MCI_GPM_COEX_PROFILE_VOICE)) | 49 | (info->type == MCI_GPM_COEX_PROFILE_VOICE)) |
@@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common, | |||
59 | memcpy(entry, info, 10); | 60 | memcpy(entry, info, 10); |
60 | INC_PROF(mci, info); | 61 | INC_PROF(mci, info); |
61 | list_add_tail(&entry->list, &mci->info); | 62 | list_add_tail(&entry->list, &mci->info); |
63 | if (info->type == MCI_GPM_COEX_PROFILE_VOICE) { | ||
64 | if (info->voice_type < sizeof(voice_priority)) | ||
65 | mci->voice_priority = voice_priority[info->voice_type]; | ||
66 | else | ||
67 | mci->voice_priority = 110; | ||
68 | } | ||
62 | 69 | ||
63 | return true; | 70 | return true; |
64 | } | 71 | } |
@@ -250,6 +257,57 @@ static void ath9k_mci_work(struct work_struct *work) | |||
250 | ath_mci_update_scheme(sc); | 257 | ath_mci_update_scheme(sc); |
251 | } | 258 | } |
252 | 259 | ||
260 | static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio) | ||
261 | { | ||
262 | if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE]) | ||
263 | stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio; | ||
264 | |||
265 | if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL]) | ||
266 | stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio; | ||
267 | |||
268 | if ((cur_txprio > ATH_MCI_HI_PRIO) && | ||
269 | (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW])) | ||
270 | stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio; | ||
271 | } | ||
272 | |||
273 | static void ath_mci_set_concur_txprio(struct ath_softc *sc) | ||
274 | { | ||
275 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
276 | struct ath_mci_profile *mci = &btcoex->mci; | ||
277 | u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */ | ||
278 | |||
279 | if (mci->num_mgmt) { | ||
280 | stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO; | ||
281 | if (!mci->num_pan && !mci->num_other_acl) | ||
282 | stomp_txprio[ATH_BTCOEX_STOMP_NONE] = | ||
283 | ATH_MCI_INQUIRY_PRIO; | ||
284 | } else { | ||
285 | u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */ | ||
286 | |||
287 | stomp_txprio[ATH_BTCOEX_STOMP_LOW] = | ||
288 | stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff; | ||
289 | |||
290 | if (mci->num_sco) | ||
291 | ath_mci_update_stomp_txprio(mci->voice_priority, | ||
292 | stomp_txprio); | ||
293 | if (mci->num_other_acl) | ||
294 | ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio); | ||
295 | if (mci->num_a2dp) | ||
296 | ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio); | ||
297 | if (mci->num_hid) | ||
298 | ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio); | ||
299 | if (mci->num_pan) | ||
300 | ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio); | ||
301 | |||
302 | if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff) | ||
303 | stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0; | ||
304 | |||
305 | if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff) | ||
306 | stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0; | ||
307 | } | ||
308 | ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio); | ||
309 | } | ||
310 | |||
253 | static u8 ath_mci_process_profile(struct ath_softc *sc, | 311 | static u8 ath_mci_process_profile(struct ath_softc *sc, |
254 | struct ath_mci_profile_info *info) | 312 | struct ath_mci_profile_info *info) |
255 | { | 313 | { |
@@ -281,6 +339,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc, | |||
281 | } else | 339 | } else |
282 | ath_mci_del_profile(common, mci, entry); | 340 | ath_mci_del_profile(common, mci, entry); |
283 | 341 | ||
342 | ath_mci_set_concur_txprio(sc); | ||
284 | return 1; | 343 | return 1; |
285 | } | 344 | } |
286 | 345 | ||
@@ -314,6 +373,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc, | |||
314 | mci->num_mgmt++; | 373 | mci->num_mgmt++; |
315 | } while (++i < ATH_MCI_MAX_PROFILE); | 374 | } while (++i < ATH_MCI_MAX_PROFILE); |
316 | 375 | ||
376 | ath_mci_set_concur_txprio(sc); | ||
317 | if (old_num_mgmt != mci->num_mgmt) | 377 | if (old_num_mgmt != mci->num_mgmt) |
318 | return 1; | 378 | return 1; |
319 | 379 | ||
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h index a3df314c1e7..e85a0e9506f 100644 --- a/drivers/net/wireless/ath/ath9k/mci.h +++ b/drivers/net/wireless/ath/ath9k/mci.h | |||
@@ -32,6 +32,8 @@ | |||
32 | #define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\ | 32 | #define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\ |
33 | ATH_MCI_MAX_SCO_PROFILE) | 33 | ATH_MCI_MAX_SCO_PROFILE) |
34 | 34 | ||
35 | #define ATH_MCI_INQUIRY_PRIO 62 | ||
36 | #define ATH_MCI_HI_PRIO 60 | ||
35 | #define ATH_MCI_NUM_BT_CHANNELS 79 | 37 | #define ATH_MCI_NUM_BT_CHANNELS 79 |
36 | 38 | ||
37 | #define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \ | 39 | #define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \ |
@@ -131,6 +133,7 @@ struct ath_mci_profile { | |||
131 | u8 num_pan; | 133 | u8 num_pan; |
132 | u8 num_other_acl; | 134 | u8 num_other_acl; |
133 | u8 num_bdr; | 135 | u8 num_bdr; |
136 | u8 voice_priority; | ||
134 | }; | 137 | }; |
135 | 138 | ||
136 | struct ath_mci_buf { | 139 | struct ath_mci_buf { |