18 #include <linux/slab.h>
23 static const u8 ath_mci_duty_cycle[] = { 55, 50, 60, 70, 80, 85, 90, 95, 98 };
31 if (list_empty(&mci->
info))
66 static void ath_mci_del_profile(
struct ath_common *common,
85 if (list_empty(&mci->
info))
95 static void ath_mci_adjust_aggr_limit(
struct ath_btcoex *btcoex)
107 if ((wlan_airtime <= 4) &&
112 static void ath_mci_update_scheme(
struct ath_softc *
sc)
125 btcoex->
duty_cycle = ath_mci_duty_cycle[num_profile];
133 if (num_profile == 1) {
140 else if (info->
T == 6) {
146 "Single SCO, aggregation limit %d 1/4 ms\n",
156 "Single PAN/FTP bt period %d ms dutycycle %d\n",
162 "Multiple attempt/timeout single HID "
163 "aggregation limit 1.5 ms dutycycle 30%%\n");
165 }
else if (num_profile == 2) {
170 "Two BT profiles aggr limit 1.5 ms dutycycle %d%%\n",
172 }
else if (num_profile >= 3) {
175 "Three or more profiles aggregation limit 1 ms\n");
181 ath_mci_adjust_aggr_limit(btcoex);
186 ath9k_btcoex_timer_pause(sc);
200 ath9k_btcoex_timer_resume(sc);
203 static void ath_mci_wait_btcal_done(
struct ath_softc *sc)
223 struct ath_common *common = ath9k_hw_common(ah);
231 ath_mci_wait_btcal_done(sc);
241 ath_dbg(common, MCI,
"Unknown GPM CAL message\n");
250 ath_mci_update_scheme(sc);
253 static u8 ath_mci_process_profile(
struct ath_softc *sc,
261 entry = ath_mci_find_profile(mci, info);
279 if (!entry && !ath_mci_add_profile(common, mci, info))
282 ath_mci_del_profile(common, mci, entry);
287 static u8 ath_mci_process_status(
struct ath_softc *sc,
300 if (ath_mci_find_profile(mci, &info))
323 static void ath_mci_msg(
struct ath_softc *sc,
u8 opcode,
u8 *rx_payload)
334 ath_dbg(common, MCI,
"(MCI) Need to flush BT profiles\n");
358 "Illegal profile type = %d, state = %d\n",
364 update_scheme += ath_mci_process_profile(sc, &profile_info);
367 profile_status.is_link = *(rx_payload +
369 profile_status.conn_handle = *(rx_payload +
371 profile_status.is_critical = *(rx_payload +
374 seq_num = *((
u32 *)(rx_payload + 12));
376 "BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%u\n",
377 profile_status.is_link, profile_status.conn_handle,
378 profile_status.is_critical, seq_num);
380 update_scheme += ath_mci_process_status(sc, &profile_status);
383 ath_dbg(common, MCI,
"Unknown GPM COEX message = 0x%02x\n", opcode);
402 ath_dbg(common, FATAL,
"MCI buffer alloc failed\n");
419 ath_err(common,
"Failed to initialize MCI\n");
423 INIT_WORK(&sc->mci_work, ath9k_mci_work);
424 ath_dbg(common, MCI,
"MCI Initialized\n");
443 ath_dbg(common, MCI,
"MCI De-Initialized\n");
450 struct ath_common *common = ath9k_hw_common(ah);
452 u32 mci_int, mci_int_rxmsg;
456 bool skip_gpm =
false;
466 u32 payload[4] = { 0xffffffff, 0xffffffff,
467 0xffffffff, 0xffffff00};
475 payload, 16,
true,
false);
477 NULL, 0,
true,
false);
479 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE;
489 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING;
498 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING;
513 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
518 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM;
529 pgpm += (offset >> 2);
542 ath_mci_cal_msg(sc, subtype, (
u8 *)pgpm);
546 ath_mci_msg(sc, opcode, (
u8 *)pgpm);
559 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL;
562 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO;
568 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO;
571 "MCI CONT_INFO: (%s) pri = %d pwr = %d dBm\n",
579 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_NACK;
582 mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_RST;
585 if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) ||
586 (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
587 mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR |