ath9k: Add concurrent WLAN and BT tx support for MCI based chips
This feature enables both WLAN and BT can transmit simultaneously by setting WLAN and BT to equal priorities. Whenever both are transmitting, it might violate regulatory power limits. To avoid regulatory violation, WLAN tx power will be adjusted according to BT power index based on avaliability of BT scheduling message. If the combined power exceeds threshold, BT transmission will be held off. Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:

committed by
John W. Linville

parent
50072ebca3
commit
db60428b1a
@@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common,
|
||||
struct ath_mci_profile_info *info)
|
||||
{
|
||||
struct ath_mci_profile_info *entry;
|
||||
u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 };
|
||||
|
||||
if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
|
||||
(info->type == MCI_GPM_COEX_PROFILE_VOICE))
|
||||
@@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common,
|
||||
memcpy(entry, info, 10);
|
||||
INC_PROF(mci, info);
|
||||
list_add_tail(&entry->list, &mci->info);
|
||||
if (info->type == MCI_GPM_COEX_PROFILE_VOICE) {
|
||||
if (info->voice_type < sizeof(voice_priority))
|
||||
mci->voice_priority = voice_priority[info->voice_type];
|
||||
else
|
||||
mci->voice_priority = 110;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -250,6 +257,57 @@ static void ath9k_mci_work(struct work_struct *work)
|
||||
ath_mci_update_scheme(sc);
|
||||
}
|
||||
|
||||
static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio)
|
||||
{
|
||||
if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE])
|
||||
stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio;
|
||||
|
||||
if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL])
|
||||
stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio;
|
||||
|
||||
if ((cur_txprio > ATH_MCI_HI_PRIO) &&
|
||||
(cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW]))
|
||||
stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio;
|
||||
}
|
||||
|
||||
static void ath_mci_set_concur_txprio(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
struct ath_mci_profile *mci = &btcoex->mci;
|
||||
u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */
|
||||
|
||||
if (mci->num_mgmt) {
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO;
|
||||
if (!mci->num_pan && !mci->num_other_acl)
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_NONE] =
|
||||
ATH_MCI_INQUIRY_PRIO;
|
||||
} else {
|
||||
u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */
|
||||
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_LOW] =
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff;
|
||||
|
||||
if (mci->num_sco)
|
||||
ath_mci_update_stomp_txprio(mci->voice_priority,
|
||||
stomp_txprio);
|
||||
if (mci->num_other_acl)
|
||||
ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio);
|
||||
if (mci->num_a2dp)
|
||||
ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio);
|
||||
if (mci->num_hid)
|
||||
ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio);
|
||||
if (mci->num_pan)
|
||||
ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio);
|
||||
|
||||
if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff)
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0;
|
||||
|
||||
if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff)
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0;
|
||||
}
|
||||
ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio);
|
||||
}
|
||||
|
||||
static u8 ath_mci_process_profile(struct ath_softc *sc,
|
||||
struct ath_mci_profile_info *info)
|
||||
{
|
||||
@@ -281,6 +339,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc,
|
||||
} else
|
||||
ath_mci_del_profile(common, mci, entry);
|
||||
|
||||
ath_mci_set_concur_txprio(sc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -314,6 +373,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc,
|
||||
mci->num_mgmt++;
|
||||
} while (++i < ATH_MCI_MAX_PROFILE);
|
||||
|
||||
ath_mci_set_concur_txprio(sc);
|
||||
if (old_num_mgmt != mci->num_mgmt)
|
||||
return 1;
|
||||
|
||||
|
Reference in New Issue
Block a user