Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
commit
531efffc3e
|
@ -2369,6 +2369,9 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
|
|||
int i;
|
||||
bool needreset = false;
|
||||
|
||||
if (!test_bit(ATH_STAT_STARTED, ah->status))
|
||||
return;
|
||||
|
||||
mutex_lock(&ah->lock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
|
||||
|
@ -2676,6 +2679,7 @@ done:
|
|||
mmiowb();
|
||||
mutex_unlock(&ah->lock);
|
||||
|
||||
set_bit(ATH_STAT_STARTED, ah->status);
|
||||
ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
|
||||
msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
|
||||
|
||||
|
@ -2737,6 +2741,7 @@ void ath5k_stop(struct ieee80211_hw *hw)
|
|||
|
||||
ath5k_stop_tasklets(ah);
|
||||
|
||||
clear_bit(ATH_STAT_STARTED, ah->status);
|
||||
cancel_delayed_work_sync(&ah->tx_complete_work);
|
||||
|
||||
if (!ath5k_modparam_no_hw_rfkill_switch)
|
||||
|
|
|
@ -233,9 +233,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
|
|||
{0x00009d10, 0x01834061},
|
||||
{0x00009d14, 0x00c00400},
|
||||
{0x00009d18, 0x00000000},
|
||||
{0x00009e08, 0x0078230c},
|
||||
{0x00009e24, 0x990bb515},
|
||||
{0x00009e28, 0x126f0000},
|
||||
{0x00009e08, 0x0038230c},
|
||||
{0x00009e24, 0x9907b515},
|
||||
{0x00009e28, 0x126f0600},
|
||||
{0x00009e30, 0x06336f77},
|
||||
{0x00009e34, 0x6af6532f},
|
||||
{0x00009e38, 0x0cc80c00},
|
||||
|
@ -337,7 +337,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
|
|||
|
||||
static const u32 ar9565_1p0_baseband_postamble[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800d},
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8009},
|
||||
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
|
||||
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
|
||||
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81},
|
||||
|
@ -345,9 +345,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
|
|||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
|
||||
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
|
||||
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
|
||||
{0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
|
||||
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
|
||||
{0x00009e04, 0x00802020, 0x00802020, 0x00142020, 0x00142020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
|
||||
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
|
@ -450,6 +450,8 @@ static const u32 ar9565_1p0_soc_postamble[][5] = {
|
|||
|
||||
static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004050, 0x00300300},
|
||||
{0x0000406c, 0x00100000},
|
||||
{0x0000a000, 0x00010000},
|
||||
{0x0000a004, 0x00030002},
|
||||
{0x0000a008, 0x00050004},
|
||||
|
@ -498,27 +500,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
|
|||
{0x0000a0b4, 0x00000000},
|
||||
{0x0000a0b8, 0x00000000},
|
||||
{0x0000a0bc, 0x00000000},
|
||||
{0x0000a0c0, 0x001f0000},
|
||||
{0x0000a0c4, 0x01000101},
|
||||
{0x0000a0c8, 0x011e011f},
|
||||
{0x0000a0cc, 0x011c011d},
|
||||
{0x0000a0d0, 0x02030204},
|
||||
{0x0000a0d4, 0x02010202},
|
||||
{0x0000a0d8, 0x021f0200},
|
||||
{0x0000a0dc, 0x0302021e},
|
||||
{0x0000a0e0, 0x03000301},
|
||||
{0x0000a0e4, 0x031e031f},
|
||||
{0x0000a0e8, 0x0402031d},
|
||||
{0x0000a0ec, 0x04000401},
|
||||
{0x0000a0f0, 0x041e041f},
|
||||
{0x0000a0f4, 0x0502041d},
|
||||
{0x0000a0f8, 0x05000501},
|
||||
{0x0000a0fc, 0x051e051f},
|
||||
{0x0000a100, 0x06010602},
|
||||
{0x0000a104, 0x061f0600},
|
||||
{0x0000a108, 0x061d061e},
|
||||
{0x0000a10c, 0x07020703},
|
||||
{0x0000a110, 0x07000701},
|
||||
{0x0000a0c0, 0x00bf00a0},
|
||||
{0x0000a0c4, 0x11a011a1},
|
||||
{0x0000a0c8, 0x11be11bf},
|
||||
{0x0000a0cc, 0x11bc11bd},
|
||||
{0x0000a0d0, 0x22632264},
|
||||
{0x0000a0d4, 0x22612262},
|
||||
{0x0000a0d8, 0x227f2260},
|
||||
{0x0000a0dc, 0x4322227e},
|
||||
{0x0000a0e0, 0x43204321},
|
||||
{0x0000a0e4, 0x433e433f},
|
||||
{0x0000a0e8, 0x4462433d},
|
||||
{0x0000a0ec, 0x44604461},
|
||||
{0x0000a0f0, 0x447e447f},
|
||||
{0x0000a0f4, 0x5582447d},
|
||||
{0x0000a0f8, 0x55805581},
|
||||
{0x0000a0fc, 0x559e559f},
|
||||
{0x0000a100, 0x66816682},
|
||||
{0x0000a104, 0x669f6680},
|
||||
{0x0000a108, 0x669d669e},
|
||||
{0x0000a10c, 0x77627763},
|
||||
{0x0000a110, 0x77607761},
|
||||
{0x0000a114, 0x00000000},
|
||||
{0x0000a118, 0x00000000},
|
||||
{0x0000a11c, 0x00000000},
|
||||
|
@ -530,27 +532,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
|
|||
{0x0000a134, 0x00000000},
|
||||
{0x0000a138, 0x00000000},
|
||||
{0x0000a13c, 0x00000000},
|
||||
{0x0000a140, 0x001f0000},
|
||||
{0x0000a144, 0x01000101},
|
||||
{0x0000a148, 0x011e011f},
|
||||
{0x0000a14c, 0x011c011d},
|
||||
{0x0000a150, 0x02030204},
|
||||
{0x0000a154, 0x02010202},
|
||||
{0x0000a158, 0x021f0200},
|
||||
{0x0000a15c, 0x0302021e},
|
||||
{0x0000a160, 0x03000301},
|
||||
{0x0000a164, 0x031e031f},
|
||||
{0x0000a168, 0x0402031d},
|
||||
{0x0000a16c, 0x04000401},
|
||||
{0x0000a170, 0x041e041f},
|
||||
{0x0000a174, 0x0502041d},
|
||||
{0x0000a178, 0x05000501},
|
||||
{0x0000a17c, 0x051e051f},
|
||||
{0x0000a180, 0x06010602},
|
||||
{0x0000a184, 0x061f0600},
|
||||
{0x0000a188, 0x061d061e},
|
||||
{0x0000a18c, 0x07020703},
|
||||
{0x0000a190, 0x07000701},
|
||||
{0x0000a140, 0x00bf00a0},
|
||||
{0x0000a144, 0x11a011a1},
|
||||
{0x0000a148, 0x11be11bf},
|
||||
{0x0000a14c, 0x11bc11bd},
|
||||
{0x0000a150, 0x22632264},
|
||||
{0x0000a154, 0x22612262},
|
||||
{0x0000a158, 0x227f2260},
|
||||
{0x0000a15c, 0x4322227e},
|
||||
{0x0000a160, 0x43204321},
|
||||
{0x0000a164, 0x433e433f},
|
||||
{0x0000a168, 0x4462433d},
|
||||
{0x0000a16c, 0x44604461},
|
||||
{0x0000a170, 0x447e447f},
|
||||
{0x0000a174, 0x5582447d},
|
||||
{0x0000a178, 0x55805581},
|
||||
{0x0000a17c, 0x559e559f},
|
||||
{0x0000a180, 0x66816682},
|
||||
{0x0000a184, 0x669f6680},
|
||||
{0x0000a188, 0x669d669e},
|
||||
{0x0000a18c, 0x77e677e7},
|
||||
{0x0000a190, 0x77e477e5},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
|
@ -770,7 +772,7 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
|
|||
|
||||
static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00018c00, 0x18213ede},
|
||||
{0x00018c00, 0x18212ede},
|
||||
{0x00018c04, 0x000801d8},
|
||||
{0x00018c08, 0x0003780c},
|
||||
};
|
||||
|
@ -889,8 +891,8 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = {
|
|||
{0x0000a180, 0x66816682},
|
||||
{0x0000a184, 0x669f6680},
|
||||
{0x0000a188, 0x669d669e},
|
||||
{0x0000a18c, 0x77627763},
|
||||
{0x0000a190, 0x77607761},
|
||||
{0x0000a18c, 0x77e677e7},
|
||||
{0x0000a190, 0x77e477e5},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
|
@ -1114,7 +1116,7 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
|
|||
{0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
|
||||
{0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
|
||||
{0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
|
||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
|
||||
|
@ -1140,13 +1142,13 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
|
|||
{0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5},
|
||||
{0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9},
|
||||
{0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb},
|
||||
{0x0000a564, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a568, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a56c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a570, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a574, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a578, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a57c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a564, 0x7804ff56, 0x7804ff56, 0x60001cf0, 0x60001cf0},
|
||||
{0x0000a568, 0x7804ff56, 0x7804ff56, 0x61001cf1, 0x61001cf1},
|
||||
{0x0000a56c, 0x7804ff56, 0x7804ff56, 0x62001cf2, 0x62001cf2},
|
||||
{0x0000a570, 0x7804ff56, 0x7804ff56, 0x63001cf3, 0x63001cf3},
|
||||
{0x0000a574, 0x7804ff56, 0x7804ff56, 0x64001cf4, 0x64001cf4},
|
||||
{0x0000a578, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
|
||||
{0x0000a57c, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
@ -1174,7 +1176,7 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
|
|||
{0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
|
||||
{0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
|
||||
{0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
|
||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
|
||||
|
@ -1200,13 +1202,13 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
|
|||
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a564, 0x7504ff56, 0x7504ff56, 0x59001cf0, 0x59001cf0},
|
||||
{0x0000a568, 0x7504ff56, 0x7504ff56, 0x5a001cf1, 0x5a001cf1},
|
||||
{0x0000a56c, 0x7504ff56, 0x7504ff56, 0x5b001cf2, 0x5b001cf2},
|
||||
{0x0000a570, 0x7504ff56, 0x7504ff56, 0x5c001cf3, 0x5c001cf3},
|
||||
{0x0000a574, 0x7504ff56, 0x7504ff56, 0x5d001cf4, 0x5d001cf4},
|
||||
{0x0000a578, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
|
||||
{0x0000a57c, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
|
|
@ -226,13 +226,13 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
|
|||
if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
|
||||
goto work;
|
||||
|
||||
ath9k_set_beacon(sc);
|
||||
|
||||
if (ah->opmode == NL80211_IFTYPE_STATION &&
|
||||
test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
|
||||
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||
} else {
|
||||
ath9k_set_beacon(sc);
|
||||
}
|
||||
work:
|
||||
ath_restart_work(sc);
|
||||
|
@ -1331,6 +1331,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
|
|||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_node *an = (struct ath_node *) sta->drv_priv;
|
||||
struct ieee80211_key_conf ps_key = { };
|
||||
int key;
|
||||
|
||||
ath_node_attach(sc, sta, vif);
|
||||
|
||||
|
@ -1338,7 +1339,9 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
|
|||
vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
return 0;
|
||||
|
||||
an->ps_key = ath_key_config(common, vif, sta, &ps_key);
|
||||
key = ath_key_config(common, vif, sta, &ps_key);
|
||||
if (key > 0)
|
||||
an->ps_key = key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1355,6 +1358,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc,
|
|||
return;
|
||||
|
||||
ath_key_delete(common, &ps_key);
|
||||
an->ps_key = 0;
|
||||
}
|
||||
|
||||
static int ath9k_sta_remove(struct ieee80211_hw *hw,
|
||||
|
|
|
@ -1728,6 +1728,25 @@ drop_recycle_buffer:
|
|||
sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
|
||||
}
|
||||
|
||||
void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
|
||||
{
|
||||
int current_slot, previous_slot;
|
||||
|
||||
B43_WARN_ON(ring->tx);
|
||||
|
||||
/* Device has filled all buffers, drop all packets and let TCP
|
||||
* decrease speed.
|
||||
* Decrement RX index by one will let the device to see all slots
|
||||
* as free again
|
||||
*/
|
||||
/*
|
||||
*TODO: How to increase rx_drop in mac80211?
|
||||
*/
|
||||
current_slot = ring->ops->get_current_rxslot(ring);
|
||||
previous_slot = prev_slot(ring, current_slot);
|
||||
ring->ops->set_current_rxslot(ring, previous_slot);
|
||||
}
|
||||
|
||||
void b43_dma_rx(struct b43_dmaring *ring)
|
||||
{
|
||||
const struct b43_dma_ops *ops = ring->ops;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/* DMA-Interrupt reasons. */
|
||||
#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
|
||||
| (1 << 14) | (1 << 15))
|
||||
#define B43_DMAIRQ_NONFATALMASK (1 << 13)
|
||||
#define B43_DMAIRQ_RDESC_UFLOW (1 << 13)
|
||||
#define B43_DMAIRQ_RX_DONE (1 << 16)
|
||||
|
||||
/*** 32-bit DMA Engine. ***/
|
||||
|
@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev,
|
|||
void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||
const struct b43_txstatus *status);
|
||||
|
||||
void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
|
||||
|
||||
void b43_dma_rx(struct b43_dmaring *ring);
|
||||
|
||||
void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
|
||||
|
|
|
@ -1902,30 +1902,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
|
||||
B43_DMAIRQ_NONFATALMASK))) {
|
||||
if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {
|
||||
b43err(dev->wl, "Fatal DMA error: "
|
||||
"0x%08X, 0x%08X, 0x%08X, "
|
||||
"0x%08X, 0x%08X, 0x%08X\n",
|
||||
dma_reason[0], dma_reason[1],
|
||||
dma_reason[2], dma_reason[3],
|
||||
dma_reason[4], dma_reason[5]);
|
||||
b43err(dev->wl, "This device does not support DMA "
|
||||
if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) {
|
||||
b43err(dev->wl,
|
||||
"Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
|
||||
dma_reason[0], dma_reason[1],
|
||||
dma_reason[2], dma_reason[3],
|
||||
dma_reason[4], dma_reason[5]);
|
||||
b43err(dev->wl, "This device does not support DMA "
|
||||
"on your system. It will now be switched to PIO.\n");
|
||||
/* Fall back to PIO transfers if we get fatal DMA errors! */
|
||||
dev->use_pio = true;
|
||||
b43_controller_restart(dev, "DMA error");
|
||||
return;
|
||||
}
|
||||
if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
|
||||
b43err(dev->wl, "DMA error: "
|
||||
"0x%08X, 0x%08X, 0x%08X, "
|
||||
"0x%08X, 0x%08X, 0x%08X\n",
|
||||
dma_reason[0], dma_reason[1],
|
||||
dma_reason[2], dma_reason[3],
|
||||
dma_reason[4], dma_reason[5]);
|
||||
}
|
||||
/* Fall back to PIO transfers if we get fatal DMA errors! */
|
||||
dev->use_pio = true;
|
||||
b43_controller_restart(dev, "DMA error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
|
||||
|
@ -1944,6 +1932,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
|
|||
handle_irq_noise(dev);
|
||||
|
||||
/* Check the DMA reason registers for received data. */
|
||||
if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
|
||||
if (B43_DEBUG)
|
||||
b43warn(dev->wl, "RX descriptor underrun\n");
|
||||
b43_dma_handle_rx_overflow(dev->dma.rx_ring);
|
||||
}
|
||||
if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
|
||||
if (b43_using_pio_transfers(dev))
|
||||
b43_pio_rx(dev->pio.rx_queue);
|
||||
|
@ -2001,7 +1994,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
|
|||
return IRQ_NONE;
|
||||
|
||||
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
|
||||
& 0x0001DC00;
|
||||
& 0x0001FC00;
|
||||
dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
|
||||
& 0x0000DC00;
|
||||
dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
|
||||
|
@ -3130,7 +3123,7 @@ static int b43_chip_init(struct b43_wldev *dev)
|
|||
b43_write32(dev, 0x018C, 0x02000000);
|
||||
}
|
||||
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
|
||||
b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
|
||||
b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00);
|
||||
b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
|
||||
b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
|
||||
b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
|
||||
|
|
|
@ -5741,8 +5741,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
|
|||
hw->flags =
|
||||
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
if (il->cfg->sku & IL_SKU_N)
|
||||
hw->flags |=
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||
|
|
|
@ -76,13 +76,16 @@
|
|||
#define IWL_INVALID_STATION 255
|
||||
|
||||
/* device operations */
|
||||
extern struct iwl_lib_ops iwl1000_lib;
|
||||
extern struct iwl_lib_ops iwl2000_lib;
|
||||
extern struct iwl_lib_ops iwl2030_lib;
|
||||
extern struct iwl_lib_ops iwl5000_lib;
|
||||
extern struct iwl_lib_ops iwl5150_lib;
|
||||
extern struct iwl_lib_ops iwl6000_lib;
|
||||
extern struct iwl_lib_ops iwl6030_lib;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_1000_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_2000_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_105_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_2030_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_5000_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_5150_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_6000_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_6005_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_6050_cfg;
|
||||
extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg;
|
||||
|
||||
|
||||
#define TIME_UNIT 1024
|
||||
|
@ -291,8 +294,8 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena);
|
|||
|
||||
static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
|
||||
{
|
||||
return priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist;
|
||||
return priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
|
|
@ -521,7 +521,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
|
|||
|
||||
iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);
|
||||
|
||||
if (priv->cfg->base_params->hd_v2) {
|
||||
if (priv->lib->hd_v2) {
|
||||
cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
|
||||
HD_INA_NON_SQUARE_DET_OFDM_DATA_V2;
|
||||
cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
|
||||
|
@ -895,7 +895,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
|
|||
continue;
|
||||
}
|
||||
|
||||
delta_g = (priv->cfg->base_params->chain_noise_scale *
|
||||
delta_g = (priv->lib->chain_noise_scale *
|
||||
((s32)average_noise[default_chain] -
|
||||
(s32)average_noise[i])) / 1500;
|
||||
|
||||
|
@ -1051,8 +1051,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
|||
return;
|
||||
|
||||
/* Analyze signal for disconnected antenna */
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
/* Disable disconnected antenna algorithm for advanced
|
||||
bt coex, assuming valid antennas are connected */
|
||||
data->active_chains = priv->nvm_data->valid_rx_ant;
|
||||
|
|
|
@ -838,10 +838,6 @@ struct iwl_qosparam_cmd {
|
|||
#define STA_MODIFY_DELBA_TID_MSK 0x10
|
||||
#define STA_MODIFY_SLEEP_TX_COUNT_MSK 0x20
|
||||
|
||||
/* Receiver address (actually, Rx station's index into station table),
|
||||
* combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
|
||||
#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid))
|
||||
|
||||
/* agn */
|
||||
struct iwl_keyinfo {
|
||||
__le16 key_flags;
|
||||
|
|
|
@ -568,16 +568,61 @@ struct iwl_hw_params {
|
|||
const struct iwl_sensitivity_ranges *sens;
|
||||
};
|
||||
|
||||
struct iwl_lib_ops {
|
||||
/* set hw dependent parameters */
|
||||
/**
|
||||
* struct iwl_dvm_bt_params - DVM specific BT (coex) parameters
|
||||
* @advanced_bt_coexist: support advanced bt coexist
|
||||
* @bt_init_traffic_load: specify initial bt traffic load
|
||||
* @bt_prio_boost: default bt priority boost value
|
||||
* @agg_time_limit: maximum number of uSec in aggregation
|
||||
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
|
||||
*/
|
||||
struct iwl_dvm_bt_params {
|
||||
bool advanced_bt_coexist;
|
||||
u8 bt_init_traffic_load;
|
||||
u32 bt_prio_boost;
|
||||
u16 agg_time_limit;
|
||||
bool bt_sco_disable;
|
||||
bool bt_session_2;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dvm_cfg - DVM firmware specific device configuration
|
||||
* @set_hw_params: set hardware parameters
|
||||
* @set_channel_switch: send channel switch command
|
||||
* @nic_config: apply device specific configuration
|
||||
* @temperature: read temperature
|
||||
* @adv_thermal_throttle: support advance thermal throttle
|
||||
* @support_ct_kill_exit: support ct kill exit condition
|
||||
* @plcp_delta_threshold: plcp error rate threshold used to trigger
|
||||
* radio tuning when there is a high receiving plcp error rate
|
||||
* @chain_noise_scale: default chain noise scale used for gain computation
|
||||
* @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
|
||||
* @no_idle_support: do not support idle mode
|
||||
* @bt_params: pointer to BT parameters
|
||||
* @need_temp_offset_calib: need to perform temperature offset calibration
|
||||
* @no_xtal_calib: some devices do not need crystal calibration data,
|
||||
* don't send it to those
|
||||
* @temp_offset_v2: support v2 of temperature offset calibration
|
||||
* @adv_pm: advanced power management
|
||||
*/
|
||||
struct iwl_dvm_cfg {
|
||||
void (*set_hw_params)(struct iwl_priv *priv);
|
||||
int (*set_channel_switch)(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
/* device specific configuration */
|
||||
void (*nic_config)(struct iwl_priv *priv);
|
||||
|
||||
/* temperature */
|
||||
void (*temperature)(struct iwl_priv *priv);
|
||||
|
||||
const struct iwl_dvm_bt_params *bt_params;
|
||||
s32 chain_noise_scale;
|
||||
u8 plcp_delta_threshold;
|
||||
bool adv_thermal_throttle;
|
||||
bool support_ct_kill_exit;
|
||||
bool hd_v2;
|
||||
bool no_idle_support;
|
||||
bool need_temp_offset_calib;
|
||||
bool no_xtal_calib;
|
||||
bool temp_offset_v2;
|
||||
bool adv_pm;
|
||||
};
|
||||
|
||||
struct iwl_wipan_noa_data {
|
||||
|
@ -610,7 +655,7 @@ struct iwl_priv {
|
|||
struct device *dev; /* for debug prints only */
|
||||
const struct iwl_cfg *cfg;
|
||||
const struct iwl_fw *fw;
|
||||
const struct iwl_lib_ops *lib;
|
||||
const struct iwl_dvm_cfg *lib;
|
||||
unsigned long status;
|
||||
|
||||
spinlock_t sta_lock;
|
||||
|
|
|
@ -174,10 +174,13 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
priv->hw_params.sens = &iwl1000_sensitivity;
|
||||
}
|
||||
|
||||
struct iwl_lib_ops iwl1000_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_1000_cfg = {
|
||||
.set_hw_params = iwl1000_hw_set_hw_params,
|
||||
.nic_config = iwl1000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
};
|
||||
|
||||
|
||||
|
@ -232,16 +235,56 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
priv->hw_params.sens = &iwl2000_sensitivity;
|
||||
}
|
||||
|
||||
struct iwl_lib_ops iwl2000_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_2000_cfg = {
|
||||
.set_hw_params = iwl2000_hw_set_hw_params,
|
||||
.nic_config = iwl2000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.hd_v2 = true,
|
||||
.need_temp_offset_calib = true,
|
||||
.temp_offset_v2 = true,
|
||||
};
|
||||
|
||||
struct iwl_lib_ops iwl2030_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_105_cfg = {
|
||||
.set_hw_params = iwl2000_hw_set_hw_params,
|
||||
.nic_config = iwl2000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.hd_v2 = true,
|
||||
.need_temp_offset_calib = true,
|
||||
.temp_offset_v2 = true,
|
||||
.adv_pm = true,
|
||||
};
|
||||
|
||||
static const struct iwl_dvm_bt_params iwl2030_bt_params = {
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.advanced_bt_coexist = true,
|
||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||
.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
|
||||
.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32,
|
||||
.bt_sco_disable = true,
|
||||
.bt_session_2 = true,
|
||||
};
|
||||
|
||||
const struct iwl_dvm_cfg iwl_dvm_2030_cfg = {
|
||||
.set_hw_params = iwl2000_hw_set_hw_params,
|
||||
.nic_config = iwl2000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.hd_v2 = true,
|
||||
.bt_params = &iwl2030_bt_params,
|
||||
.need_temp_offset_calib = true,
|
||||
.temp_offset_v2 = true,
|
||||
.adv_pm = true,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -420,16 +463,23 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
|||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
}
|
||||
|
||||
struct iwl_lib_ops iwl5000_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_5000_cfg = {
|
||||
.set_hw_params = iwl5000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.temperature = iwlagn_temperature,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.no_idle_support = true,
|
||||
};
|
||||
|
||||
struct iwl_lib_ops iwl5150_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_5150_cfg = {
|
||||
.set_hw_params = iwl5150_hw_set_hw_params,
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.temperature = iwl5150_temperature,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.no_idle_support = true,
|
||||
.no_xtal_calib = true,
|
||||
};
|
||||
|
||||
|
||||
|
@ -584,16 +634,59 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
return err;
|
||||
}
|
||||
|
||||
struct iwl_lib_ops iwl6000_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_6000_cfg = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
};
|
||||
|
||||
struct iwl_lib_ops iwl6030_lib = {
|
||||
const struct iwl_dvm_cfg iwl_dvm_6005_cfg = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.need_temp_offset_calib = true,
|
||||
};
|
||||
|
||||
const struct iwl_dvm_cfg iwl_dvm_6050_cfg = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1500,
|
||||
};
|
||||
|
||||
static const struct iwl_dvm_bt_params iwl6000_bt_params = {
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.advanced_bt_coexist = true,
|
||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||
.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
|
||||
.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
|
||||
.bt_sco_disable = true,
|
||||
};
|
||||
|
||||
const struct iwl_dvm_cfg iwl_dvm_6030_cfg = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.temperature = iwlagn_temperature,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.need_temp_offset_calib = true,
|
||||
.adv_pm = true,
|
||||
};
|
||||
|
|
|
@ -254,23 +254,23 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
|||
BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
|
||||
sizeof(basic.bt3_lookup_table));
|
||||
|
||||
if (priv->cfg->bt_params) {
|
||||
if (priv->lib->bt_params) {
|
||||
/*
|
||||
* newer generation of devices (2000 series and newer)
|
||||
* use the version 2 of the bt command
|
||||
* we need to make sure sending the host command
|
||||
* with correct data structure to avoid uCode assert
|
||||
*/
|
||||
if (priv->cfg->bt_params->bt_session_2) {
|
||||
if (priv->lib->bt_params->bt_session_2) {
|
||||
bt_cmd_v2.prio_boost = cpu_to_le32(
|
||||
priv->cfg->bt_params->bt_prio_boost);
|
||||
priv->lib->bt_params->bt_prio_boost);
|
||||
bt_cmd_v2.tx_prio_boost = 0;
|
||||
bt_cmd_v2.rx_prio_boost = 0;
|
||||
} else {
|
||||
/* older version only has 8 bits */
|
||||
WARN_ON(priv->cfg->bt_params->bt_prio_boost & ~0xFF);
|
||||
WARN_ON(priv->lib->bt_params->bt_prio_boost & ~0xFF);
|
||||
bt_cmd_v1.prio_boost =
|
||||
priv->cfg->bt_params->bt_prio_boost;
|
||||
priv->lib->bt_params->bt_prio_boost;
|
||||
bt_cmd_v1.tx_prio_boost = 0;
|
||||
bt_cmd_v1.rx_prio_boost = 0;
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
|||
priv->bt_full_concurrent ?
|
||||
"full concurrency" : "3-wire");
|
||||
|
||||
if (priv->cfg->bt_params->bt_session_2) {
|
||||
if (priv->lib->bt_params->bt_session_2) {
|
||||
memcpy(&bt_cmd_v2.basic, &basic,
|
||||
sizeof(basic));
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
|
||||
|
@ -758,8 +758,8 @@ static bool is_single_rx_stream(struct iwl_priv *priv)
|
|||
*/
|
||||
static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist &&
|
||||
(priv->bt_full_concurrent ||
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||
/*
|
||||
|
@ -830,8 +830,8 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||
else
|
||||
active_chains = priv->nvm_data->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist &&
|
||||
(priv->bt_full_concurrent ||
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||
/*
|
||||
|
|
|
@ -426,6 +426,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* let the ucode operate on its own */
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
iwl_trans_d3_suspend(priv->trans);
|
||||
|
||||
goto out;
|
||||
|
@ -509,6 +513,10 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* uCode is no longer operating by itself */
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
IWL_WARN(priv, "Invalid error table during resume!\n");
|
||||
|
@ -1276,8 +1284,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
|||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
if (rssi_event == RSSI_EVENT_LOW)
|
||||
priv->bt_enable_pspoll = true;
|
||||
else if (rssi_event == RSSI_EVENT_HIGH)
|
||||
|
@ -1387,7 +1395,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist &&
|
||||
vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
/*
|
||||
* pretend to have high BT traffic as long as we
|
||||
|
|
|
@ -615,7 +615,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||
|
||||
priv->thermal_throttle.ct_kill_toggle = false;
|
||||
|
||||
if (priv->cfg->base_params->support_ct_kill_exit) {
|
||||
if (priv->lib->support_ct_kill_exit) {
|
||||
adv_cmd.critical_temperature_enter =
|
||||
cpu_to_le32(priv->hw_params.ct_kill_threshold);
|
||||
adv_cmd.critical_temperature_exit =
|
||||
|
@ -732,10 +732,10 @@ int iwl_alive_start(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
/* download priority table before any calibration request */
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
/* Configure Bluetooth device coexistence support */
|
||||
if (priv->cfg->bt_params->bt_sco_disable)
|
||||
if (priv->lib->bt_params->bt_sco_disable)
|
||||
priv->bt_enable_pspoll = false;
|
||||
else
|
||||
priv->bt_enable_pspoll = true;
|
||||
|
@ -873,9 +873,9 @@ void iwl_down(struct iwl_priv *priv)
|
|||
priv->bt_status = 0;
|
||||
priv->cur_rssi_ctx = NULL;
|
||||
priv->bt_is_sco = 0;
|
||||
if (priv->cfg->bt_params)
|
||||
if (priv->lib->bt_params)
|
||||
priv->bt_traffic_load =
|
||||
priv->cfg->bt_params->bt_init_traffic_load;
|
||||
priv->lib->bt_params->bt_init_traffic_load;
|
||||
else
|
||||
priv->bt_traffic_load = 0;
|
||||
priv->bt_full_concurrent = false;
|
||||
|
@ -1058,7 +1058,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
|||
|
||||
iwl_setup_scan_deferred_work(priv);
|
||||
|
||||
if (priv->cfg->bt_params)
|
||||
if (priv->lib->bt_params)
|
||||
iwlagn_bt_setup_deferred_work(priv);
|
||||
|
||||
init_timer(&priv->statistics_periodic);
|
||||
|
@ -1072,7 +1072,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
|||
|
||||
void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->bt_params)
|
||||
if (priv->lib->bt_params)
|
||||
iwlagn_bt_cancel_deferred_work(priv);
|
||||
|
||||
cancel_work_sync(&priv->run_time_calib_work);
|
||||
|
@ -1098,8 +1098,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
|||
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
priv->plcp_delta_threshold =
|
||||
priv->cfg->base_params->plcp_delta_threshold;
|
||||
priv->plcp_delta_threshold = priv->lib->plcp_delta_threshold;
|
||||
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
|
||||
|
@ -1116,8 +1115,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
|||
iwl_init_scan_params(priv);
|
||||
|
||||
/* init bt coex */
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
|
||||
priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
|
||||
priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
|
||||
|
@ -1264,31 +1263,37 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
switch (priv->cfg->device_family) {
|
||||
case IWL_DEVICE_FAMILY_1000:
|
||||
case IWL_DEVICE_FAMILY_100:
|
||||
priv->lib = &iwl1000_lib;
|
||||
priv->lib = &iwl_dvm_1000_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_2000:
|
||||
priv->lib = &iwl_dvm_2000_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_105:
|
||||
priv->lib = &iwl2000_lib;
|
||||
priv->lib = &iwl_dvm_105_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_2030:
|
||||
case IWL_DEVICE_FAMILY_135:
|
||||
priv->lib = &iwl2030_lib;
|
||||
priv->lib = &iwl_dvm_2030_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_5000:
|
||||
priv->lib = &iwl5000_lib;
|
||||
priv->lib = &iwl_dvm_5000_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_5150:
|
||||
priv->lib = &iwl5150_lib;
|
||||
priv->lib = &iwl_dvm_5150_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6000:
|
||||
case IWL_DEVICE_FAMILY_6005:
|
||||
case IWL_DEVICE_FAMILY_6000i:
|
||||
priv->lib = &iwl_dvm_6000_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6005:
|
||||
priv->lib = &iwl_dvm_6005_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6050:
|
||||
case IWL_DEVICE_FAMILY_6150:
|
||||
priv->lib = &iwl6000_lib;
|
||||
priv->lib = &iwl_dvm_6050_cfg;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6030:
|
||||
priv->lib = &iwl6030_lib;
|
||||
priv->lib = &iwl_dvm_6030_cfg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -163,7 +163,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||
u8 skip;
|
||||
u32 slp_itrvl;
|
||||
|
||||
if (priv->cfg->adv_pm) {
|
||||
if (priv->lib->adv_pm) {
|
||||
table = apm_range_2;
|
||||
if (period <= IWL_DTIM_RANGE_1_MAX)
|
||||
table = apm_range_1;
|
||||
|
@ -217,7 +217,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
||||
|
||||
if (iwl_advanced_bt_coexist(priv)) {
|
||||
if (!priv->cfg->bt_params->bt_sco_disable)
|
||||
if (!priv->lib->bt_params->bt_sco_disable)
|
||||
cmd->flags |= IWL_POWER_BT_SCO_ENA;
|
||||
else
|
||||
cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
|
||||
|
@ -293,7 +293,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
|
|||
|
||||
if (priv->wowlan)
|
||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
|
||||
else if (!priv->cfg->base_params->no_idle_support &&
|
||||
else if (!priv->lib->no_idle_support &&
|
||||
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
||||
else if (iwl_tt_is_low_power_state(priv)) {
|
||||
|
|
|
@ -1088,7 +1088,7 @@ done:
|
|||
(priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
|
||||
rs_program_fix_rate(priv, lq_sta);
|
||||
#endif
|
||||
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
|
||||
if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist)
|
||||
rs_bt_update_lq(priv, ctx, lq_sta);
|
||||
}
|
||||
|
||||
|
@ -3064,11 +3064,11 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
|
|||
* overwrite if needed, pass aggregation time limit
|
||||
* to uCode in uSec
|
||||
*/
|
||||
if (priv && priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->agg_time_limit &&
|
||||
if (priv && priv->lib->bt_params &&
|
||||
priv->lib->bt_params->agg_time_limit &&
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
|
||||
lq_cmd->agg_params.agg_time_limit =
|
||||
cpu_to_le16(priv->cfg->bt_params->agg_time_limit);
|
||||
cpu_to_le16(priv->lib->bt_params->agg_time_limit);
|
||||
}
|
||||
|
||||
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
||||
|
|
|
@ -1102,7 +1102,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
|||
iwl_notification_wait_init(&priv->notif_wait);
|
||||
|
||||
/* Set up BT Rx handlers */
|
||||
if (priv->cfg->bt_params)
|
||||
if (priv->lib->bt_params)
|
||||
iwlagn_bt_rx_handler_setup(priv);
|
||||
}
|
||||
|
||||
|
|
|
@ -801,8 +801,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
* Internal scans are passive, so we can indiscriminately set
|
||||
* the BT ignore flag on 2.4 GHz since it applies to TX only.
|
||||
*/
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist)
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist)
|
||||
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
|
@ -844,8 +844,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
band = priv->scan_band;
|
||||
|
||||
if (band == IEEE80211_BAND_2GHZ &&
|
||||
priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
/* transmit 2.4 GHz probes only on first antenna */
|
||||
scan_tx_antennas = first_antenna(scan_tx_antennas);
|
||||
}
|
||||
|
@ -873,8 +873,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
rx_ant = first_antenna(active_chains);
|
||||
}
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist &&
|
||||
priv->bt_full_concurrent) {
|
||||
/* operated as 1x1 in full concurrency mode */
|
||||
rx_ant = first_antenna(rx_ant);
|
||||
|
|
|
@ -735,7 +735,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||
memcpy(&lq, priv->stations[i].lq,
|
||||
sizeof(struct iwl_link_quality_cmd));
|
||||
|
||||
if (!memcmp(&lq, &zero_lq, sizeof(lq)))
|
||||
if (memcmp(&lq, &zero_lq, sizeof(lq)))
|
||||
send_lq = true;
|
||||
}
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
|
|
@ -627,7 +627,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
|||
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
|
||||
INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
|
||||
|
||||
if (priv->cfg->base_params->adv_thermal_throttle) {
|
||||
if (priv->lib->adv_thermal_throttle) {
|
||||
IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
|
||||
tt->restriction = kcalloc(IWL_TI_STATE_MAX,
|
||||
sizeof(struct iwl_tt_restriction),
|
||||
|
|
|
@ -83,8 +83,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
|
|||
else if (ieee80211_is_back_req(fc))
|
||||
tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
|
||||
else if (info->band == IEEE80211_BAND_2GHZ &&
|
||||
priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist &&
|
||||
(ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
|
||||
ieee80211_is_reassoc_req(fc) ||
|
||||
skb->protocol == cpu_to_be16(ETH_P_PAE)))
|
||||
|
@ -202,8 +202,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||
rate_flags |= RATE_MCS_CCK_MSK;
|
||||
|
||||
/* Set up antennas */
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist &&
|
||||
priv->bt_full_concurrent) {
|
||||
/* operated as 1x1 in full concurrency mode */
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
|
@ -986,8 +986,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
|
|||
* notification again.
|
||||
*/
|
||||
if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
|
||||
priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -132,8 +132,8 @@ int iwl_init_alive_start(struct iwl_priv *priv)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
if (priv->lib->bt_params &&
|
||||
priv->lib->bt_params->advanced_bt_coexist) {
|
||||
/*
|
||||
* Tell uCode we are ready to perform calibration
|
||||
* need to perform this before any calibration
|
||||
|
@ -155,8 +155,8 @@ int iwl_init_alive_start(struct iwl_priv *priv)
|
|||
* temperature offset calibration is only needed for runtime ucode,
|
||||
* so prepare the value now.
|
||||
*/
|
||||
if (priv->cfg->need_temp_offset_calib) {
|
||||
if (priv->cfg->temp_offset_v2)
|
||||
if (priv->lib->need_temp_offset_calib) {
|
||||
if (priv->lib->temp_offset_v2)
|
||||
return iwl_set_temperature_offset_calib_v2(priv);
|
||||
else
|
||||
return iwl_set_temperature_offset_calib(priv);
|
||||
|
@ -277,7 +277,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!priv->cfg->no_xtal_calib) {
|
||||
if (!priv->lib->no_xtal_calib) {
|
||||
ret = iwl_set_Xtal_calib(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -60,9 +60,6 @@ static const struct iwl_base_params iwl1000_base_params = {
|
|||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.led_compensation = 51,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_WATCHDOG_DISABLED,
|
||||
.max_event_log_size = 128,
|
||||
};
|
||||
|
|
|
@ -72,14 +72,9 @@ static const struct iwl_base_params iwl2000_base_params = {
|
|||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
|
||||
.hd_v2 = true,
|
||||
};
|
||||
|
||||
|
||||
|
@ -90,14 +85,9 @@ static const struct iwl_base_params iwl2030_base_params = {
|
|||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
|
||||
.hd_v2 = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl2000_ht_params = {
|
||||
|
@ -106,16 +96,6 @@ static const struct iwl_ht_params iwl2000_ht_params = {
|
|||
.ht40_bands = BIT(IEEE80211_BAND_2GHZ),
|
||||
};
|
||||
|
||||
static const struct iwl_bt_params iwl2030_bt_params = {
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.advanced_bt_coexist = true,
|
||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||
.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
|
||||
.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32,
|
||||
.bt_sco_disable = true,
|
||||
.bt_session_2 = true,
|
||||
};
|
||||
|
||||
static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
|
@ -137,12 +117,10 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
|
|||
.device_family = IWL_DEVICE_FAMILY_2000, \
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
|
||||
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
|
||||
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
|
||||
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
|
||||
.base_params = &iwl2000_base_params, \
|
||||
.eeprom_params = &iwl20x0_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
const struct iwl_cfg iwl2000_2bgn_cfg = {
|
||||
|
@ -168,12 +146,8 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
|||
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
|
||||
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
|
||||
.base_params = &iwl2030_base_params, \
|
||||
.bt_params = &iwl2030_bt_params, \
|
||||
.eeprom_params = &iwl20x0_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
const struct iwl_cfg iwl2030_2bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
|
||||
|
@ -193,10 +167,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = {
|
|||
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
|
||||
.base_params = &iwl2000_base_params, \
|
||||
.eeprom_params = &iwl20x0_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true, \
|
||||
.rx_with_siso_diversity = true
|
||||
|
||||
const struct iwl_cfg iwl105_bgn_cfg = {
|
||||
|
@ -222,12 +193,8 @@ const struct iwl_cfg iwl105_bgn_d_cfg = {
|
|||
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
|
||||
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
|
||||
.base_params = &iwl2030_base_params, \
|
||||
.bt_params = &iwl2030_bt_params, \
|
||||
.eeprom_params = &iwl20x0_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true, \
|
||||
.rx_with_siso_diversity = true
|
||||
|
||||
const struct iwl_cfg iwl135_bgn_cfg = {
|
||||
|
|
|
@ -59,11 +59,8 @@ static const struct iwl_base_params iwl5000_base_params = {
|
|||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.led_compensation = 51,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_WATCHDOG_DISABLED,
|
||||
.max_event_log_size = 512,
|
||||
.no_idle_support = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl5000_ht_params = {
|
||||
|
@ -159,7 +156,6 @@ const struct iwl_cfg iwl5350_agn_cfg = {
|
|||
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
|
||||
.base_params = &iwl5000_base_params, \
|
||||
.eeprom_params = &iwl5000_eeprom_params, \
|
||||
.no_xtal_calib = true, \
|
||||
.led_mode = IWL_LED_BLINK, \
|
||||
.internal_wimax_coex = true
|
||||
|
||||
|
|
|
@ -82,10 +82,6 @@ static const struct iwl_base_params iwl6000_base_params = {
|
|||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
|
||||
|
@ -98,10 +94,6 @@ static const struct iwl_base_params iwl6050_base_params = {
|
|||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1500,
|
||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||
.max_event_log_size = 1024,
|
||||
.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
|
||||
|
@ -114,10 +106,6 @@ static const struct iwl_base_params iwl6000_g2_base_params = {
|
|||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
|
||||
|
@ -129,15 +117,6 @@ static const struct iwl_ht_params iwl6000_ht_params = {
|
|||
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
|
||||
};
|
||||
|
||||
static const struct iwl_bt_params iwl6000_bt_params = {
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.advanced_bt_coexist = true,
|
||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||
.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
|
||||
.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
|
||||
.bt_sco_disable = true,
|
||||
};
|
||||
|
||||
static const struct iwl_eeprom_params iwl6000_eeprom_params = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
|
@ -163,7 +142,6 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
|
|||
.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
|
||||
.base_params = &iwl6000_g2_base_params, \
|
||||
.eeprom_params = &iwl6000_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
const struct iwl_cfg iwl6005_2agn_cfg = {
|
||||
|
@ -217,11 +195,8 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
|
|||
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \
|
||||
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
|
||||
.base_params = &iwl6000_g2_base_params, \
|
||||
.bt_params = &iwl6000_bt_params, \
|
||||
.eeprom_params = &iwl6000_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true \
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
const struct iwl_cfg iwl6030_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
|
||||
|
@ -256,11 +231,8 @@ const struct iwl_cfg iwl6030_2bg_cfg = {
|
|||
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \
|
||||
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
|
||||
.base_params = &iwl6000_g2_base_params, \
|
||||
.bt_params = &iwl6000_bt_params, \
|
||||
.eeprom_params = &iwl6000_eeprom_params, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
const struct iwl_cfg iwl6035_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
|
||||
|
|
|
@ -96,13 +96,9 @@ static const struct iwl_base_params iwl7000_base_params = {
|
|||
.pll_cfg_val = 0,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl7000_ht_params = {
|
||||
|
@ -118,14 +114,11 @@ static const struct iwl_ht_params iwl7000_ht_params = {
|
|||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.base_params = &iwl7000_base_params, \
|
||||
/* TODO: .bt_params? */ \
|
||||
.need_temp_offset_calib = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true \
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
|
||||
const struct iwl_cfg iwl7260_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC7260",
|
||||
.name = "Intel(R) Dual Band Wireless AC 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
|
@ -133,8 +126,44 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
|
|||
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC3160",
|
||||
const struct iwl_cfg iwl7260_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7260_n_cfg = {
|
||||
.name = "Intel(R) Wireless N 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 3160",
|
||||
.fw_name_pre = IWL3160_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL3160_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 3160",
|
||||
.fw_name_pre = IWL3160_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL3160_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_n_cfg = {
|
||||
.name = "Intel(R) Wireless N 3160",
|
||||
.fw_name_pre = IWL3160_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
|
|
|
@ -136,17 +136,9 @@ enum iwl_led_mode {
|
|||
* @led_compensation: compensate on the led on/off time per HW according
|
||||
* to the deviation to achieve the desired led frequency.
|
||||
* The detail algorithm is described in iwl-led.c
|
||||
* @chain_noise_num_beacons: number of beacons used to compute chain noise
|
||||
* @adv_thermal_throttle: support advance thermal throttle
|
||||
* @support_ct_kill_exit: support ct kill exit condition
|
||||
* @plcp_delta_threshold: plcp error rate threshold used to trigger
|
||||
* radio tuning when there is a high receiving plcp error rate
|
||||
* @chain_noise_scale: default chain noise scale used for gain computation
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
||||
* @shadow_reg_enable: HW shadow register support
|
||||
* @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
|
||||
* @no_idle_support: do not support idle mode
|
||||
*/
|
||||
struct iwl_base_params {
|
||||
int eeprom_size;
|
||||
|
@ -157,31 +149,9 @@ struct iwl_base_params {
|
|||
const u16 max_ll_items;
|
||||
const bool shadow_ram_support;
|
||||
u16 led_compensation;
|
||||
bool adv_thermal_throttle;
|
||||
bool support_ct_kill_exit;
|
||||
u8 plcp_delta_threshold;
|
||||
s32 chain_noise_scale;
|
||||
unsigned int wd_timeout;
|
||||
u32 max_event_log_size;
|
||||
const bool shadow_reg_enable;
|
||||
const bool hd_v2;
|
||||
const bool no_idle_support;
|
||||
};
|
||||
|
||||
/*
|
||||
* @advanced_bt_coexist: support advanced bt coexist
|
||||
* @bt_init_traffic_load: specify initial bt traffic load
|
||||
* @bt_prio_boost: default bt priority boost value
|
||||
* @agg_time_limit: maximum number of uSec in aggregation
|
||||
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
|
||||
*/
|
||||
struct iwl_bt_params {
|
||||
bool advanced_bt_coexist;
|
||||
u8 bt_init_traffic_load;
|
||||
u32 bt_prio_boost;
|
||||
u16 agg_time_limit;
|
||||
bool bt_sco_disable;
|
||||
bool bt_session_2;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -231,16 +201,10 @@ struct iwl_eeprom_params {
|
|||
* @nvm_calib_ver: NVM calibration version
|
||||
* @lib: pointer to the lib ops
|
||||
* @base_params: pointer to basic parameters
|
||||
* @ht_params: point to ht patameters
|
||||
* @bt_params: pointer to bt parameters
|
||||
* @need_temp_offset_calib: need to perform temperature offset calibration
|
||||
* @no_xtal_calib: some devices do not need crystal calibration data,
|
||||
* don't send it to those
|
||||
* @ht_params: point to ht parameters
|
||||
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
|
||||
* @adv_pm: advance power management
|
||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||
* @internal_wimax_coex: internal wifi/wimax combo device
|
||||
* @temp_offset_v2: support v2 of temperature offset calibration
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt. hardware features.
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
|
@ -264,15 +228,10 @@ struct iwl_cfg {
|
|||
const struct iwl_base_params *base_params;
|
||||
/* params likely to change within a device family */
|
||||
const struct iwl_ht_params *ht_params;
|
||||
const struct iwl_bt_params *bt_params;
|
||||
const struct iwl_eeprom_params *eeprom_params;
|
||||
const bool need_temp_offset_calib; /* if used set to true */
|
||||
const bool no_xtal_calib;
|
||||
enum iwl_led_mode led_mode;
|
||||
const bool adv_pm;
|
||||
const bool rx_with_siso_diversity;
|
||||
const bool internal_wimax_coex;
|
||||
const bool temp_offset_v2;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -320,6 +279,10 @@ extern const struct iwl_cfg iwl105_bgn_cfg;
|
|||
extern const struct iwl_cfg iwl105_bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl135_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3160_ac_cfg;
|
||||
extern const struct iwl_cfg iwl7260_2n_cfg;
|
||||
extern const struct iwl_cfg iwl7260_n_cfg;
|
||||
extern const struct iwl_cfg iwl3160_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3160_2n_cfg;
|
||||
extern const struct iwl_cfg iwl3160_n_cfg;
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
|
|
@ -472,4 +472,23 @@
|
|||
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
|
||||
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
|
||||
|
||||
/*****************************************************************************
|
||||
* 7000/3000 series SHR DTS addresses *
|
||||
*****************************************************************************/
|
||||
|
||||
/* Diode Results Register Structure: */
|
||||
enum dtd_diode_reg {
|
||||
DTS_DIODE_REG_DIG_VAL = 0x000000FF, /* bits [7:0] */
|
||||
DTS_DIODE_REG_VREF_LOW = 0x0000FF00, /* bits [15:8] */
|
||||
DTS_DIODE_REG_VREF_HIGH = 0x00FF0000, /* bits [23:16] */
|
||||
DTS_DIODE_REG_VREF_ID = 0x03000000, /* bits [25:24] */
|
||||
DTS_DIODE_REG_PASS_ONCE = 0x80000000, /* bits [31:31] */
|
||||
DTS_DIODE_REG_FLAGS_MSK = 0xFF000000, /* bits [31:24] */
|
||||
/* Those are the masks INSIDE the flags bit-field: */
|
||||
DTS_DIODE_REG_FLAGS_VREFS_ID_POS = 0,
|
||||
DTS_DIODE_REG_FLAGS_VREFS_ID = 0x00000003, /* bits [1:0] */
|
||||
DTS_DIODE_REG_FLAGS_PASS_ONCE_POS = 7,
|
||||
DTS_DIODE_REG_FLAGS_PASS_ONCE = 0x00000080, /* bits [7:7] */
|
||||
};
|
||||
|
||||
#endif /* !__iwl_csr_h__ */
|
||||
|
|
|
@ -1234,6 +1234,9 @@ MODULE_PARM_DESC(wd_disable,
|
|||
"Disable stuck queue watchdog timer 0=system default, "
|
||||
"1=disable, 2=enable (default: 0)");
|
||||
|
||||
module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO);
|
||||
MODULE_PARM_DESC(nvm_file, "NVM file name");
|
||||
|
||||
/*
|
||||
* set bt_coex_active to true, uCode will do kill/defer
|
||||
* every time the priority line is asserted (BT is sending signals on the
|
||||
|
|
|
@ -732,17 +732,16 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
|||
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band)
|
||||
enum ieee80211_band band,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
int max_bit_rate = 0;
|
||||
u8 rx_chains;
|
||||
u8 tx_chains;
|
||||
|
||||
tx_chains = hweight8(data->valid_tx_ant);
|
||||
tx_chains = hweight8(tx_chains);
|
||||
if (cfg->rx_with_siso_diversity)
|
||||
rx_chains = 1;
|
||||
else
|
||||
rx_chains = hweight8(data->valid_rx_ant);
|
||||
rx_chains = hweight8(rx_chains);
|
||||
|
||||
if (!(data->sku_cap_11n_enable) || !cfg->ht_params) {
|
||||
ht_info->ht_supported = false;
|
||||
|
@ -806,7 +805,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
sband->n_bitrates = N_RATES_24;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ,
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_5GHZ];
|
||||
sband->band = IEEE80211_BAND_5GHZ;
|
||||
|
@ -814,7 +814,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
sband->n_bitrates = N_RATES_52;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ,
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n",
|
||||
|
|
|
@ -133,6 +133,7 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
|||
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band);
|
||||
enum ieee80211_band band,
|
||||
u8 tx_chains, u8 rx_chains);
|
||||
|
||||
#endif /* __iwl_eeprom_parse_h__ */
|
||||
|
|
|
@ -106,11 +106,14 @@ enum iwl_ucode_type {
|
|||
|
||||
/*
|
||||
* enumeration of ucode section.
|
||||
* This enumeration is used for legacy tlv style (before 16.0 uCode).
|
||||
* This enumeration is used directly for older firmware (before 16.0).
|
||||
* For new firmware, there can be up to 4 sections (see below) but the
|
||||
* first one packaged into the firmware file is the DATA section and
|
||||
* some debugging code accesses that.
|
||||
*/
|
||||
enum iwl_ucode_sec {
|
||||
IWL_UCODE_SECTION_INST,
|
||||
IWL_UCODE_SECTION_DATA,
|
||||
IWL_UCODE_SECTION_INST,
|
||||
};
|
||||
/*
|
||||
* For 16.0 uCode and above, there is no differentiation between sections,
|
||||
|
|
|
@ -119,6 +119,7 @@ struct iwl_mod_params {
|
|||
int ant_coupling;
|
||||
bool bt_ch_announce;
|
||||
bool auto_agg;
|
||||
char *nvm_file;
|
||||
};
|
||||
|
||||
#endif /* #__iwl_modparams_h__ */
|
||||
|
|
|
@ -89,6 +89,7 @@ enum nvm_sku_bits {
|
|||
NVM_SKU_CAP_BAND_24GHZ = BIT(0),
|
||||
NVM_SKU_CAP_BAND_52GHZ = BIT(1),
|
||||
NVM_SKU_CAP_11N_ENABLE = BIT(2),
|
||||
NVM_SKU_CAP_11AC_ENABLE = BIT(3),
|
||||
};
|
||||
|
||||
/* radio config bits (actual values from NVM definition) */
|
||||
|
@ -258,8 +259,6 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
|||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_vht_cap *vht_cap)
|
||||
{
|
||||
/* For now, assume new devices with NVM are VHT capable */
|
||||
|
||||
vht_cap->vht_supported = true;
|
||||
|
||||
vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
|
||||
|
@ -292,7 +291,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
|||
}
|
||||
|
||||
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data, const __le16 *nvm_sw)
|
||||
struct iwl_nvm_data *data, const __le16 *nvm_sw,
|
||||
bool enable_vht, u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
int n_channels = iwl_init_channel_map(dev, cfg, data,
|
||||
&nvm_sw[NVM_CHANNELS]);
|
||||
|
@ -305,7 +305,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
sband->n_bitrates = N_RATES_24;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ,
|
||||
tx_chains, rx_chains);
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_5GHZ];
|
||||
sband->band = IEEE80211_BAND_5GHZ;
|
||||
|
@ -313,8 +314,10 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
sband->n_bitrates = N_RATES_52;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
|
||||
iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ,
|
||||
tx_chains, rx_chains);
|
||||
if (enable_vht)
|
||||
iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
|
||||
|
@ -324,7 +327,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib)
|
||||
const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
u8 hw_addr[ETH_ALEN];
|
||||
|
@ -380,7 +383,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
|||
data->hw_addr[4] = hw_addr[5];
|
||||
data->hw_addr[5] = hw_addr[4];
|
||||
|
||||
iwl_init_sbands(dev, cfg, data, nvm_sw);
|
||||
iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE,
|
||||
tx_chains, rx_chains);
|
||||
|
||||
data->calib_version = 255; /* TODO:
|
||||
this value will prevent some checks from
|
||||
|
|
|
@ -75,6 +75,6 @@
|
|||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib);
|
||||
const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains);
|
||||
|
||||
#endif /* __iwl_nvm_parse_h__ */
|
||||
|
|
|
@ -100,6 +100,18 @@
|
|||
/* Device system time */
|
||||
#define DEVICE_SYSTEM_TIME_REG 0xA0206C
|
||||
|
||||
/*****************************************************************************
|
||||
* 7000/3000 series SHR DTS addresses *
|
||||
*****************************************************************************/
|
||||
|
||||
#define SHR_MISC_WFM_DTS_EN (0x00a10024)
|
||||
#define DTSC_CFG_MODE (0x00a10604)
|
||||
#define DTSC_VREF_AVG (0x00a10648)
|
||||
#define DTSC_VREF5_AVG (0x00a1064c)
|
||||
#define DTSC_CFG_MODE_PERIODIC (0x2)
|
||||
#define DTSC_PTAT_AVG (0x00a10650)
|
||||
|
||||
|
||||
/**
|
||||
* Tx Scheduler
|
||||
*
|
||||
|
|
|
@ -189,7 +189,8 @@ enum CMD_MODE {
|
|||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_ON_DEMAND = BIT(2),
|
||||
CMD_SEND_IN_RFKILL = BIT(2),
|
||||
CMD_ON_DEMAND = BIT(3),
|
||||
};
|
||||
|
||||
#define DEF_CMD_PAYLOAD_SIZE 320
|
||||
|
@ -455,7 +456,7 @@ struct iwl_trans_ops {
|
|||
int (*read_mem)(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
int (*write_mem)(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
const void *buf, int dwords);
|
||||
void (*configure)(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
void (*set_pmi)(struct iwl_trans *trans, bool state);
|
||||
|
@ -761,7 +762,7 @@ static inline u32 iwl_trans_read_mem32(struct iwl_trans *trans, u32 addr)
|
|||
}
|
||||
|
||||
static inline int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
const void *buf, int dwords)
|
||||
{
|
||||
return trans->ops->write_mem(trans, addr, buf, dwords);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
|
|||
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
|
||||
iwlmvm-y += scan.o time-event.o rs.o
|
||||
iwlmvm-y += power.o bt-coex.o
|
||||
iwlmvm-y += led.o
|
||||
iwlmvm-y += led.o tt.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
|
||||
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
||||
|
||||
|
|
|
@ -351,6 +351,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
enum ieee80211_band band;
|
||||
int ave_rssi;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
|
@ -365,7 +366,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
if (band != IEEE80211_BAND_2GHZ) {
|
||||
ieee80211_request_smps(vif, smps_mode);
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
|
||||
smps_mode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -380,7 +382,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
mvmvif->id, data->notif->bt_status,
|
||||
data->notif->bt_traffic_load, smps_mode);
|
||||
|
||||
ieee80211_request_smps(vif, smps_mode);
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
|
||||
|
||||
/* don't reduce the Tx power if in loose scheme */
|
||||
if (is_loose_coex())
|
||||
|
|
|
@ -1007,6 +1007,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = iwl_mvm_power_update_mode(mvm, vif);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* must be last -- this switches firmware state */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC,
|
||||
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
|
||||
|
@ -1214,6 +1218,26 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
|||
iwl_free_resp(&cmd);
|
||||
}
|
||||
|
||||
static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN];
|
||||
u32 len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||
|
||||
if (!mvm->store_d3_resume_sram)
|
||||
return;
|
||||
|
||||
if (!mvm->d3_resume_sram) {
|
||||
mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL);
|
||||
if (!mvm->d3_resume_sram)
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
int iwl_mvm_resume(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
@ -1245,6 +1269,9 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* query SRAM first in case we want event logging */
|
||||
iwl_mvm_read_d3_sram(mvm);
|
||||
|
||||
iwl_mvm_query_wakeup_reasons(mvm, vif);
|
||||
|
||||
out_unlock:
|
||||
|
|
|
@ -145,15 +145,18 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
|
|||
char *buf;
|
||||
u8 *ptr;
|
||||
|
||||
if (!mvm->ucode_loaded)
|
||||
return -EINVAL;
|
||||
|
||||
/* default is to dump the entire data segment */
|
||||
if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) {
|
||||
mvm->dbgfs_sram_offset = 0x800000;
|
||||
if (!mvm->ucode_loaded)
|
||||
return -EINVAL;
|
||||
img = &mvm->fw->img[mvm->cur_ucode];
|
||||
mvm->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||
len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
} else {
|
||||
ofs = mvm->dbgfs_sram_offset;
|
||||
len = mvm->dbgfs_sram_len;
|
||||
}
|
||||
len = mvm->dbgfs_sram_len;
|
||||
|
||||
bufsz = len * 4 + 256;
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
|
@ -167,12 +170,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
|
|||
}
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
|
||||
mvm->dbgfs_sram_offset);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", ofs);
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans,
|
||||
mvm->dbgfs_sram_offset,
|
||||
ptr, len);
|
||||
iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
|
||||
for (ofs = 0; ofs < len; ofs += 16) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs);
|
||||
hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
|
||||
|
@ -300,6 +300,146 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
|
|||
return count;
|
||||
}
|
||||
|
||||
static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
enum iwl_dbgfs_pm_mask param, int val)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
|
||||
|
||||
dbgfs_pm->mask |= param;
|
||||
|
||||
switch (param) {
|
||||
case MVM_DEBUGFS_PM_KEEP_ALIVE: {
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
int dtimper = hw->conf.ps_dtim_period ?: 1;
|
||||
int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
|
||||
IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
|
||||
if (val * MSEC_PER_SEC < 3 * dtimper_msec) {
|
||||
IWL_WARN(mvm,
|
||||
"debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
|
||||
val * MSEC_PER_SEC, 3 * dtimper_msec);
|
||||
}
|
||||
dbgfs_pm->keep_alive_seconds = val;
|
||||
break;
|
||||
}
|
||||
case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
|
||||
IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
|
||||
val ? "enabled" : "disabled");
|
||||
dbgfs_pm->skip_over_dtim = val;
|
||||
break;
|
||||
case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
|
||||
IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
|
||||
dbgfs_pm->skip_dtim_periods = val;
|
||||
break;
|
||||
case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
|
||||
IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
|
||||
dbgfs_pm->rx_data_timeout = val;
|
||||
break;
|
||||
case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
|
||||
IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
|
||||
dbgfs_pm->tx_data_timeout = val;
|
||||
break;
|
||||
case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
|
||||
IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
|
||||
dbgfs_pm->disable_power_off = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->dbgfs_data;
|
||||
enum iwl_dbgfs_pm_mask param;
|
||||
char buf[32] = {};
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(buf, user_buf, sizeof(buf)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!strncmp("keep_alive=", buf, 11)) {
|
||||
if (sscanf(buf + 11, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_PM_KEEP_ALIVE;
|
||||
} else if (!strncmp("skip_over_dtim=", buf, 15)) {
|
||||
if (sscanf(buf + 15, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
|
||||
} else if (!strncmp("skip_dtim_periods=", buf, 18)) {
|
||||
if (sscanf(buf + 18, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
|
||||
} else if (!strncmp("rx_data_timeout=", buf, 16)) {
|
||||
if (sscanf(buf + 16, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
|
||||
} else if (!strncmp("tx_data_timeout=", buf, 16)) {
|
||||
if (sscanf(buf + 16, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
|
||||
} else if (!strncmp("disable_power_off=", buf, 18)) {
|
||||
if (sscanf(buf + 18, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_dbgfs_update_pm(mvm, vif, param, val);
|
||||
ret = iwl_mvm_power_update_mode(mvm, vif);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->dbgfs_data;
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
char buf[256];
|
||||
int bufsz = sizeof(buf);
|
||||
int pos = 0;
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
|
||||
0 : 1);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
|
||||
le32_to_cpu(cmd.skip_dtim_periods));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
|
||||
iwlmvm_mod_params.power_scheme);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "flags = %d\n",
|
||||
le16_to_cpu(cmd.flags));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
|
||||
cmd.keep_alive_seconds);
|
||||
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
|
||||
1 : 0);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.rx_data_timeout));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.tx_data_timeout));
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -481,6 +621,255 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
|
|||
return count;
|
||||
}
|
||||
|
||||
static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
|
||||
enum iwl_dbgfs_bf_mask param, int value)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
|
||||
|
||||
dbgfs_bf->mask |= param;
|
||||
|
||||
switch (param) {
|
||||
case MVM_DEBUGFS_BF_ENERGY_DELTA:
|
||||
dbgfs_bf->bf_energy_delta = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
|
||||
dbgfs_bf->bf_roaming_energy_delta = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_ROAMING_STATE:
|
||||
dbgfs_bf->bf_roaming_state = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_TEMPERATURE_DELTA:
|
||||
dbgfs_bf->bf_temperature_delta = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
|
||||
dbgfs_bf->bf_enable_beacon_filter = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_DEBUG_FLAG:
|
||||
dbgfs_bf->bf_debug_flag = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_ESCAPE_TIMER:
|
||||
dbgfs_bf->bf_escape_timer = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
|
||||
dbgfs_bf->ba_enable_beacon_abort = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BA_ESCAPE_TIMER:
|
||||
dbgfs_bf->ba_escape_timer = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->dbgfs_data;
|
||||
enum iwl_dbgfs_bf_mask param;
|
||||
char buf[256];
|
||||
int buf_size;
|
||||
int value;
|
||||
int ret = 0;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buf_size = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
if (!strncmp("bf_energy_delta=", buf, 16)) {
|
||||
if (sscanf(buf+16, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_ENERGY_DELTA_MIN ||
|
||||
value > IWL_BF_ENERGY_DELTA_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_ENERGY_DELTA;
|
||||
} else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
|
||||
if (sscanf(buf+24, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
|
||||
value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
|
||||
} else if (!strncmp("bf_roaming_state=", buf, 17)) {
|
||||
if (sscanf(buf+17, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_ROAMING_STATE_MIN ||
|
||||
value > IWL_BF_ROAMING_STATE_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_ROAMING_STATE;
|
||||
} else if (!strncmp("bf_temperature_delta=", buf, 21)) {
|
||||
if (sscanf(buf+21, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_TEMPERATURE_DELTA_MIN ||
|
||||
value > IWL_BF_TEMPERATURE_DELTA_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA;
|
||||
} else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
|
||||
if (sscanf(buf+24, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < 0 || value > 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
|
||||
} else if (!strncmp("bf_debug_flag=", buf, 14)) {
|
||||
if (sscanf(buf+14, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < 0 || value > 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_DEBUG_FLAG;
|
||||
} else if (!strncmp("bf_escape_timer=", buf, 16)) {
|
||||
if (sscanf(buf+16, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_ESCAPE_TIMER_MIN ||
|
||||
value > IWL_BF_ESCAPE_TIMER_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
|
||||
} else if (!strncmp("ba_escape_timer=", buf, 16)) {
|
||||
if (sscanf(buf+16, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BA_ESCAPE_TIMER_MIN ||
|
||||
value > IWL_BA_ESCAPE_TIMER_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
|
||||
} else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
|
||||
if (sscanf(buf+23, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < 0 || value > 1)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_dbgfs_update_bf(vif, param, value);
|
||||
if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) {
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif);
|
||||
} else {
|
||||
if (mvmvif->bf_enabled)
|
||||
ret = iwl_mvm_enable_beacon_filter(mvm, vif);
|
||||
else
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif);
|
||||
}
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
char buf[256];
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
.bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT,
|
||||
.bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT,
|
||||
.bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT,
|
||||
.bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT,
|
||||
.bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT,
|
||||
.bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
|
||||
.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
|
||||
.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
|
||||
.ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
|
||||
};
|
||||
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
|
||||
if (mvmvif->bf_enabled)
|
||||
cmd.bf_enable_beacon_filter = 1;
|
||||
else
|
||||
cmd.bf_enable_beacon_filter = 0;
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
|
||||
cmd.bf_energy_delta);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
|
||||
cmd.bf_roaming_energy_delta);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
|
||||
cmd.bf_roaming_state);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n",
|
||||
cmd.bf_temperature_delta);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
|
||||
cmd.bf_enable_beacon_filter);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
|
||||
cmd.bf_debug_flag);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
|
||||
cmd.bf_escape_timer);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
|
||||
cmd.ba_escape_timer);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
|
||||
cmd.ba_enable_beacon_abort);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static ssize_t iwl_dbgfs_d3_sram_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
char buf[8] = {};
|
||||
int store;
|
||||
|
||||
if (copy_from_user(buf, user_buf, sizeof(buf)))
|
||||
return -EFAULT;
|
||||
|
||||
if (sscanf(buf, "%d", &store) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
mvm->store_d3_resume_sram = store;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
const struct fw_img *img;
|
||||
int ofs, len, pos = 0;
|
||||
size_t bufsz, ret;
|
||||
char *buf;
|
||||
u8 *ptr = mvm->d3_resume_sram;
|
||||
|
||||
img = &mvm->fw->img[IWL_UCODE_WOWLAN];
|
||||
len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
|
||||
bufsz = len * 4 + 256;
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
|
||||
mvm->store_d3_resume_sram ? "en" : "dis");
|
||||
|
||||
if (ptr) {
|
||||
for (ofs = 0; ofs < len; ofs += 16) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"0x%.4x ", ofs);
|
||||
hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
|
||||
bufsz - pos, false);
|
||||
pos += strlen(buf + pos);
|
||||
if (bufsz - pos > 0)
|
||||
buf[pos++] = '\n';
|
||||
}
|
||||
} else {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"(no data captured)\n");
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MVM_DEBUGFS_READ_FILE_OPS(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
|
@ -524,9 +913,14 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
|
|||
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram);
|
||||
#endif
|
||||
|
||||
/* Interface specific debugfs entries */
|
||||
MVM_DEBUGFS_READ_FILE_OPS(mac_params);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params);
|
||||
|
||||
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
{
|
||||
|
@ -542,6 +936,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
|||
MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a symlink with mac80211. It will be removed when mac80211
|
||||
|
@ -577,9 +974,19 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
return;
|
||||
}
|
||||
|
||||
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p)
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
|
||||
S_IRUSR);
|
||||
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
|
||||
S_IRUSR);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
mvmvif == mvm->bf_allowed_vif)
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
|
||||
S_IRUSR | S_IWUSR);
|
||||
|
||||
/*
|
||||
* Create symlink for convenience pointing to interface specific
|
||||
* debugfs entries for the driver. For example, under
|
||||
|
|
|
@ -75,13 +75,15 @@ enum iwl_d3_wakeup_flags {
|
|||
* struct iwl_d3_manager_config - D3 manager configuration command
|
||||
* @min_sleep_time: minimum sleep time (in usec)
|
||||
* @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags
|
||||
* @wakeup_host_timer: force wakeup after this many seconds
|
||||
*
|
||||
* The structure is used for the D3_CONFIG_CMD command.
|
||||
*/
|
||||
struct iwl_d3_manager_config {
|
||||
__le32 min_sleep_time;
|
||||
__le32 wakeup_flags;
|
||||
} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_3 */
|
||||
__le32 wakeup_host_timer;
|
||||
} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_4 */
|
||||
|
||||
|
||||
/* TODO: OFFLOADS_QUERY_API_S_VER_1 */
|
||||
|
|
|
@ -101,20 +101,107 @@ enum iwl_power_flags {
|
|||
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
|
||||
* PSM transition - legacy PM
|
||||
* @sleep_interval: not in use
|
||||
* @keep_alive_beacons: not in use
|
||||
* @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
|
||||
* is set. For example, if it is required to skip over
|
||||
* one DTIM, this value need to be set to 2 (DTIM periods).
|
||||
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
|
||||
* Default: 80dbm
|
||||
*/
|
||||
struct iwl_powertable_cmd {
|
||||
/* PM_POWER_TABLE_CMD_API_S_VER_5 */
|
||||
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
|
||||
__le16 flags;
|
||||
u8 keep_alive_seconds;
|
||||
u8 debug_flags;
|
||||
__le32 rx_data_timeout;
|
||||
__le32 tx_data_timeout;
|
||||
__le32 sleep_interval[IWL_POWER_VEC_SIZE];
|
||||
__le32 keep_alive_beacons;
|
||||
__le32 skip_dtim_periods;
|
||||
__le32 lprx_rssi_threshold;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_cmd
|
||||
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
|
||||
* @id_and_color: MAC contex identifier
|
||||
* @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
|
||||
* to driver if delta in Energy values calculated for this and last
|
||||
* passed beacon is greater than this threshold. Zero value means that
|
||||
* the Energy change is ignored for beacon filtering, and beacon will
|
||||
* not be forced to be sent to driver regardless of this delta. Typical
|
||||
* energy delta 5dB.
|
||||
* @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state.
|
||||
* Send beacon to driver if delta in Energy values calculated for this
|
||||
* and last passed beacon is greater than this threshold. Zero value
|
||||
* means that the Energy change is ignored for beacon filtering while in
|
||||
* Roaming state, typical energy delta 1dB.
|
||||
* @bf_roaming_state: Used for RSSI filtering. If absolute Energy values
|
||||
* calculated for current beacon is less than the threshold, use
|
||||
* Roaming Energy Delta Threshold, otherwise use normal Energy Delta
|
||||
* Threshold. Typical energy threshold is -72dBm.
|
||||
* @bf_temperature_delta: Send Beacon to driver if delta in temperature values
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature changeis ignored for
|
||||
* beacon filtering; beacons will not be forced to be sent to driver
|
||||
* regardless of whether its temerature has been changed.
|
||||
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
|
||||
* @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
|
||||
* for a specific period of time. Units: Beacons.
|
||||
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
|
||||
* for a longer period of time then this escape-timeout. Units: Beacons.
|
||||
* @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
|
||||
*/
|
||||
struct iwl_beacon_filter_cmd {
|
||||
u8 bf_energy_delta;
|
||||
u8 bf_roaming_energy_delta;
|
||||
u8 bf_roaming_state;
|
||||
u8 bf_temperature_delta;
|
||||
u8 bf_enable_beacon_filter;
|
||||
u8 bf_debug_flag;
|
||||
__le16 reserved1;
|
||||
__le32 bf_escape_timer;
|
||||
__le32 ba_escape_timer;
|
||||
u8 ba_enable_beacon_abort;
|
||||
u8 reserved2[3];
|
||||
} __packed;
|
||||
|
||||
/* Beacon filtering and beacon abort */
|
||||
#define IWL_BF_ENERGY_DELTA_DEFAULT 5
|
||||
#define IWL_BF_ENERGY_DELTA_MAX 255
|
||||
#define IWL_BF_ENERGY_DELTA_MIN 0
|
||||
|
||||
#define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1
|
||||
#define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255
|
||||
#define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0
|
||||
|
||||
#define IWL_BF_ROAMING_STATE_DEFAULT 72
|
||||
#define IWL_BF_ROAMING_STATE_MAX 255
|
||||
#define IWL_BF_ROAMING_STATE_MIN 0
|
||||
|
||||
#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5
|
||||
#define IWL_BF_TEMPERATURE_DELTA_MAX 255
|
||||
#define IWL_BF_TEMPERATURE_DELTA_MIN 0
|
||||
|
||||
#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
|
||||
|
||||
#define IWL_BF_DEBUG_FLAG_DEFAULT 0
|
||||
|
||||
#define IWL_BF_ESCAPE_TIMER_DEFAULT 50
|
||||
#define IWL_BF_ESCAPE_TIMER_MAX 1024
|
||||
#define IWL_BF_ESCAPE_TIMER_MIN 0
|
||||
|
||||
#define IWL_BA_ESCAPE_TIMER_DEFAULT 3
|
||||
#define IWL_BA_ESCAPE_TIMER_MAX 1024
|
||||
#define IWL_BA_ESCAPE_TIMER_MIN 0
|
||||
|
||||
#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
|
||||
|
||||
#define IWL_BF_CMD_CONFIG_DEFAULTS \
|
||||
.bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \
|
||||
.bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \
|
||||
.bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \
|
||||
.bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \
|
||||
.bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \
|
||||
.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \
|
||||
.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -134,6 +134,7 @@ enum iwl_tx_flags {
|
|||
#define TX_CMD_SEC_WEP 0x01
|
||||
#define TX_CMD_SEC_CCM 0x02
|
||||
#define TX_CMD_SEC_TKIP 0x03
|
||||
#define TX_CMD_SEC_MSK 0x07
|
||||
#define TX_CMD_SEC_WEP_KEY_IDX_POS 6
|
||||
#define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0
|
||||
#define TX_CMD_SEC_KEY128 0x08
|
||||
|
|
|
@ -139,6 +139,9 @@ enum {
|
|||
/* Power */
|
||||
POWER_TABLE_CMD = 0x77,
|
||||
|
||||
/* Thermal Throttling*/
|
||||
REPLY_THERMAL_MNG_BACKOFF = 0x7e,
|
||||
|
||||
/* Scanning */
|
||||
SCAN_REQUEST_CMD = 0x80,
|
||||
SCAN_ABORT_CMD = 0x81,
|
||||
|
@ -161,6 +164,8 @@ enum {
|
|||
CARD_STATE_CMD = 0xa0,
|
||||
CARD_STATE_NOTIFICATION = 0xa1,
|
||||
|
||||
MISSED_BEACONS_NOTIFICATION = 0xa2,
|
||||
|
||||
REPLY_RX_PHY_CMD = 0xc0,
|
||||
REPLY_RX_MPDU_CMD = 0xc1,
|
||||
BA_NOTIF = 0xc5,
|
||||
|
@ -170,9 +175,13 @@ enum {
|
|||
BT_COEX_PROT_ENV = 0xcd,
|
||||
BT_PROFILE_NOTIFICATION = 0xce,
|
||||
|
||||
REPLY_BEACON_FILTERING_CMD = 0xd2,
|
||||
|
||||
REPLY_DEBUG_CMD = 0xf0,
|
||||
DEBUG_LOG_MSG = 0xf7,
|
||||
|
||||
MCAST_FILTER_CMD = 0xd0,
|
||||
|
||||
/* D3 commands/notifications */
|
||||
D3_CONFIG_CMD = 0xd3,
|
||||
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
|
||||
|
@ -935,6 +944,24 @@ struct iwl_card_state_notif {
|
|||
__le32 flags;
|
||||
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_missed_beacons_notif - information on missed beacons
|
||||
* ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
|
||||
* @mac_id: interface ID
|
||||
* @consec_missed_beacons_since_last_rx: number of consecutive missed
|
||||
* beacons since last RX.
|
||||
* @consec_missed_beacons: number of consecutive missed beacons
|
||||
* @num_expected_beacons:
|
||||
* @num_recvd_beacons:
|
||||
*/
|
||||
struct iwl_missed_beacons_notif {
|
||||
__le32 mac_id;
|
||||
__le32 consec_missed_beacons_since_last_rx;
|
||||
__le32 consec_missed_beacons;
|
||||
__le32 num_expected_beacons;
|
||||
__le32 num_recvd_beacons;
|
||||
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_set_calib_default_cmd - set default value for calibration.
|
||||
* ( SET_CALIB_DEFAULT_CMD = 0x8e )
|
||||
|
@ -948,4 +975,237 @@ struct iwl_set_calib_default_cmd {
|
|||
u8 data[0];
|
||||
} __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */
|
||||
|
||||
#define MAX_PORT_ID_NUM 2
|
||||
|
||||
/**
|
||||
* struct iwl_mcast_filter_cmd - configure multicast filter.
|
||||
* @filter_own: Set 1 to filter out multicast packets sent by station itself
|
||||
* @port_id: Multicast MAC addresses array specifier. This is a strange way
|
||||
* to identify network interface adopted in host-device IF.
|
||||
* It is used by FW as index in array of addresses. This array has
|
||||
* MAX_PORT_ID_NUM members.
|
||||
* @count: Number of MAC addresses in the array
|
||||
* @pass_all: Set 1 to pass all multicast packets.
|
||||
* @bssid: current association BSSID.
|
||||
* @addr_list: Place holder for array of MAC addresses.
|
||||
* IMPORTANT: add padding if necessary to ensure DWORD alignment.
|
||||
*/
|
||||
struct iwl_mcast_filter_cmd {
|
||||
u8 filter_own;
|
||||
u8 port_id;
|
||||
u8 count;
|
||||
u8 pass_all;
|
||||
u8 bssid[6];
|
||||
u8 reserved[2];
|
||||
u8 addr_list[0];
|
||||
} __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_dbg {
|
||||
__le32 burst_check;
|
||||
__le32 burst_count;
|
||||
__le32 wait_for_silence_timeout_cnt;
|
||||
__le32 reserved[3];
|
||||
} __packed; /* STATISTICS_DEBUG_API_S_VER_2 */
|
||||
|
||||
struct mvm_statistics_div {
|
||||
__le32 tx_on_a;
|
||||
__le32 tx_on_b;
|
||||
__le32 exec_time;
|
||||
__le32 probe_time;
|
||||
__le32 rssi_ant;
|
||||
__le32 reserved2;
|
||||
} __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */
|
||||
|
||||
struct mvm_statistics_general_common {
|
||||
__le32 temperature; /* radio temperature */
|
||||
__le32 temperature_m; /* radio voltage */
|
||||
struct mvm_statistics_dbg dbg;
|
||||
__le32 sleep_time;
|
||||
__le32 slots_out;
|
||||
__le32 slots_idle;
|
||||
__le32 ttl_timestamp;
|
||||
struct mvm_statistics_div div;
|
||||
__le32 rx_enable_counter;
|
||||
/*
|
||||
* num_of_sos_states:
|
||||
* count the number of times we have to re-tune
|
||||
* in order to get out of bad PHY status
|
||||
*/
|
||||
__le32 num_of_sos_states;
|
||||
} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */
|
||||
|
||||
struct mvm_statistics_rx_non_phy {
|
||||
__le32 bogus_cts; /* CTS received when not expecting CTS */
|
||||
__le32 bogus_ack; /* ACK received when not expecting ACK */
|
||||
__le32 non_bssid_frames; /* number of frames with BSSID that
|
||||
* doesn't belong to the STA BSSID */
|
||||
__le32 filtered_frames; /* count frames that were dumped in the
|
||||
* filtering process */
|
||||
__le32 non_channel_beacons; /* beacons with our bss id but not on
|
||||
* our serving channel */
|
||||
__le32 channel_beacons; /* beacons with our bss id and in our
|
||||
* serving channel */
|
||||
__le32 num_missed_bcon; /* number of missed beacons */
|
||||
__le32 adc_rx_saturation_time; /* count in 0.8us units the time the
|
||||
* ADC was in saturation */
|
||||
__le32 ina_detection_search_time;/* total time (in 0.8us) searched
|
||||
* for INA */
|
||||
__le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */
|
||||
__le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */
|
||||
__le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */
|
||||
__le32 interference_data_flag; /* flag for interference data
|
||||
* availability. 1 when data is
|
||||
* available. */
|
||||
__le32 channel_load; /* counts RX Enable time in uSec */
|
||||
__le32 dsp_false_alarms; /* DSP false alarm (both OFDM
|
||||
* and CCK) counter */
|
||||
__le32 beacon_rssi_a;
|
||||
__le32 beacon_rssi_b;
|
||||
__le32 beacon_rssi_c;
|
||||
__le32 beacon_energy_a;
|
||||
__le32 beacon_energy_b;
|
||||
__le32 beacon_energy_c;
|
||||
__le32 num_bt_kills;
|
||||
__le32 mac_id;
|
||||
__le32 directed_data_mpdu;
|
||||
} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */
|
||||
|
||||
struct mvm_statistics_rx_phy {
|
||||
__le32 ina_cnt;
|
||||
__le32 fina_cnt;
|
||||
__le32 plcp_err;
|
||||
__le32 crc32_err;
|
||||
__le32 overrun_err;
|
||||
__le32 early_overrun_err;
|
||||
__le32 crc32_good;
|
||||
__le32 false_alarm_cnt;
|
||||
__le32 fina_sync_err_cnt;
|
||||
__le32 sfd_timeout;
|
||||
__le32 fina_timeout;
|
||||
__le32 unresponded_rts;
|
||||
__le32 rxe_frame_limit_overrun;
|
||||
__le32 sent_ack_cnt;
|
||||
__le32 sent_cts_cnt;
|
||||
__le32 sent_ba_rsp_cnt;
|
||||
__le32 dsp_self_kill;
|
||||
__le32 mh_format_err;
|
||||
__le32 re_acq_main_rssi_sum;
|
||||
__le32 reserved;
|
||||
} __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */
|
||||
|
||||
struct mvm_statistics_rx_ht_phy {
|
||||
__le32 plcp_err;
|
||||
__le32 overrun_err;
|
||||
__le32 early_overrun_err;
|
||||
__le32 crc32_good;
|
||||
__le32 crc32_err;
|
||||
__le32 mh_format_err;
|
||||
__le32 agg_crc32_good;
|
||||
__le32 agg_mpdu_cnt;
|
||||
__le32 agg_cnt;
|
||||
__le32 unsupport_mcs;
|
||||
} __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */
|
||||
|
||||
#define MAX_CHAINS 3
|
||||
|
||||
struct mvm_statistics_tx_non_phy_agg {
|
||||
__le32 ba_timeout;
|
||||
__le32 ba_reschedule_frames;
|
||||
__le32 scd_query_agg_frame_cnt;
|
||||
__le32 scd_query_no_agg;
|
||||
__le32 scd_query_agg;
|
||||
__le32 scd_query_mismatch;
|
||||
__le32 frame_not_ready;
|
||||
__le32 underrun;
|
||||
__le32 bt_prio_kill;
|
||||
__le32 rx_ba_rsp_cnt;
|
||||
__s8 txpower[MAX_CHAINS];
|
||||
__s8 reserved;
|
||||
__le32 reserved2;
|
||||
} __packed; /* STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_tx_channel_width {
|
||||
__le32 ext_cca_narrow_ch20[1];
|
||||
__le32 ext_cca_narrow_ch40[2];
|
||||
__le32 ext_cca_narrow_ch80[3];
|
||||
__le32 ext_cca_narrow_ch160[4];
|
||||
__le32 last_tx_ch_width_indx;
|
||||
__le32 rx_detected_per_ch_width[4];
|
||||
__le32 success_per_ch_width[4];
|
||||
__le32 fail_per_ch_width[4];
|
||||
}; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_tx {
|
||||
__le32 preamble_cnt;
|
||||
__le32 rx_detected_cnt;
|
||||
__le32 bt_prio_defer_cnt;
|
||||
__le32 bt_prio_kill_cnt;
|
||||
__le32 few_bytes_cnt;
|
||||
__le32 cts_timeout;
|
||||
__le32 ack_timeout;
|
||||
__le32 expected_ack_cnt;
|
||||
__le32 actual_ack_cnt;
|
||||
__le32 dump_msdu_cnt;
|
||||
__le32 burst_abort_next_frame_mismatch_cnt;
|
||||
__le32 burst_abort_missing_next_frame_cnt;
|
||||
__le32 cts_timeout_collision;
|
||||
__le32 ack_or_ba_timeout_collision;
|
||||
struct mvm_statistics_tx_non_phy_agg agg;
|
||||
struct mvm_statistics_tx_channel_width channel_width;
|
||||
} __packed; /* STATISTICS_TX_API_S_VER_4 */
|
||||
|
||||
|
||||
struct mvm_statistics_bt_activity {
|
||||
__le32 hi_priority_tx_req_cnt;
|
||||
__le32 hi_priority_tx_denied_cnt;
|
||||
__le32 lo_priority_tx_req_cnt;
|
||||
__le32 lo_priority_tx_denied_cnt;
|
||||
__le32 hi_priority_rx_req_cnt;
|
||||
__le32 hi_priority_rx_denied_cnt;
|
||||
__le32 lo_priority_rx_req_cnt;
|
||||
__le32 lo_priority_rx_denied_cnt;
|
||||
} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_general {
|
||||
struct mvm_statistics_general_common common;
|
||||
__le32 beacon_filtered;
|
||||
__le32 missed_beacons;
|
||||
__s8 beacon_filter_everage_energy;
|
||||
__s8 beacon_filter_reason;
|
||||
__s8 beacon_filter_current_energy;
|
||||
__s8 beacon_filter_reserved;
|
||||
__le32 beacon_filter_delta_time;
|
||||
struct mvm_statistics_bt_activity bt_activity;
|
||||
} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */
|
||||
|
||||
struct mvm_statistics_rx {
|
||||
struct mvm_statistics_rx_phy ofdm;
|
||||
struct mvm_statistics_rx_phy cck;
|
||||
struct mvm_statistics_rx_non_phy general;
|
||||
struct mvm_statistics_rx_ht_phy ofdm_ht;
|
||||
} __packed; /* STATISTICS_RX_API_S_VER_3 */
|
||||
|
||||
/*
|
||||
* STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
|
||||
*
|
||||
* By default, uCode issues this notification after receiving a beacon
|
||||
* while associated. To disable this behavior, set DISABLE_NOTIF flag in the
|
||||
* REPLY_STATISTICS_CMD 0x9c, above.
|
||||
*
|
||||
* Statistics counters continue to increment beacon after beacon, but are
|
||||
* cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
|
||||
* 0x9c with CLEAR_STATS bit set (see above).
|
||||
*
|
||||
* uCode also issues this notification during scans. uCode clears statistics
|
||||
* appropriately so that each notification contains statistics for only the
|
||||
* one channel that has just been scanned.
|
||||
*/
|
||||
|
||||
struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */
|
||||
__le32 flag;
|
||||
struct mvm_statistics_rx rx;
|
||||
struct mvm_statistics_tx tx;
|
||||
struct mvm_statistics_general general;
|
||||
} __packed;
|
||||
|
||||
#endif /* __fw_api_h__ */
|
||||
|
|
|
@ -326,6 +326,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
|
||||
WARN_ON(ret);
|
||||
|
||||
/*
|
||||
* abort after reading the nvm in case RF Kill is on, we will complete
|
||||
* the init seq later when RF kill will switch to off
|
||||
*/
|
||||
if (iwl_mvm_is_radio_killed(mvm)) {
|
||||
IWL_DEBUG_RF_KILL(mvm,
|
||||
"jump over all phy activities due to RF kill\n");
|
||||
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send TX valid antennas before triggering calibrations */
|
||||
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
|
||||
if (ret)
|
||||
|
@ -388,6 +399,8 @@ out:
|
|||
int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, i;
|
||||
struct ieee80211_channel *chan;
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -400,8 +413,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
ret = iwl_run_init_mvm_ucode(mvm, false);
|
||||
if (ret && !iwlmvm_mod_params.init_dbg) {
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
|
||||
/* this can't happen */
|
||||
if (WARN_ON(ret > 0))
|
||||
ret = -ERFKILL;
|
||||
goto error;
|
||||
}
|
||||
/* should stop & start HW since that INIT image just loaded */
|
||||
iwl_trans_stop_hw(mvm->trans, false);
|
||||
ret = iwl_trans_start_hw(mvm->trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
|
@ -443,8 +464,22 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
|
||||
/* Add all the PHY contexts */
|
||||
chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0];
|
||||
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
/*
|
||||
* The channel used here isn't relevant as it's
|
||||
* going to be overwritten in the other flows.
|
||||
* For now use the first channel we have.
|
||||
*/
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i],
|
||||
&chandef, 1, 1);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
|
||||
return 0;
|
||||
error:
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
|
|
|
@ -227,7 +227,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
|
|||
.found_vif = false,
|
||||
};
|
||||
u32 ac;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
/*
|
||||
* Allocate a MAC ID and a TSF for this MAC, along with the queues
|
||||
|
@ -335,6 +335,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
|
|||
mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT;
|
||||
mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
|
||||
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
|
||||
mvmvif->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_fail:
|
||||
|
@ -586,10 +589,12 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
|
|||
*/
|
||||
static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_data_sta *ctxt_sta)
|
||||
struct iwl_mac_data_sta *ctxt_sta,
|
||||
bool force_assoc_off)
|
||||
{
|
||||
/* We need the dtim_period to set the MAC as associated */
|
||||
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) {
|
||||
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
|
||||
!force_assoc_off) {
|
||||
u32 dtim_offs;
|
||||
|
||||
/*
|
||||
|
@ -659,7 +664,8 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
|
|||
cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
|
||||
/* Fill the data specific for station mode */
|
||||
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta);
|
||||
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta,
|
||||
action == FW_CTXT_ACTION_ADD);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
@ -677,7 +683,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
|
|||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
/* Fill the data specific for station mode */
|
||||
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta);
|
||||
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta,
|
||||
action == FW_CTXT_ACTION_ADD);
|
||||
|
||||
cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
|
||||
IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
|
||||
|
@ -1043,3 +1050,28 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
|||
rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u16 *id = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (mvmvif->id == *id)
|
||||
ieee80211_beacon_loss(vif);
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_missed_beacons_notif *missed_beacons = (void *)pkt->data;
|
||||
u16 id = (u16)le32_to_cpu(missed_beacons->mac_id);
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_beacon_loss_iterator,
|
||||
&id);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,17 @@ static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(mvm->phy_ctxts, 0, sizeof(mvm->phy_ctxts));
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
mvm->phy_ctxts[i].id = i;
|
||||
mvm->phy_ctxts[i].ref = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
|
@ -141,7 +152,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_TIMING_BEACON_ONLY;
|
||||
IEEE80211_HW_TIMING_BEACON_ONLY |
|
||||
IEEE80211_HW_CONNECTION_MONITOR;
|
||||
|
||||
hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
|
||||
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
|
||||
|
@ -158,7 +170,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
|
||||
hw->sta_data_size = sizeof(struct iwl_mvm_sta);
|
||||
hw->vif_data_size = sizeof(struct iwl_mvm_vif);
|
||||
hw->chanctx_data_size = sizeof(struct iwl_mvm_phy_ctxt);
|
||||
hw->chanctx_data_size = sizeof(u16);
|
||||
|
||||
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
|
@ -193,6 +205,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
hw->wiphy->n_addresses++;
|
||||
}
|
||||
|
||||
iwl_mvm_reset_phy_ctxts(mvm);
|
||||
|
||||
/* we create the 802.11 header and a max-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len =
|
||||
mvm->fw->ucode_capa.max_probe_length - 24 - 34;
|
||||
|
@ -252,8 +266,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
if (test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status)) {
|
||||
IWL_DEBUG_DROP(mvm, "Dropping - RF KILL\n");
|
||||
if (iwl_mvm_is_radio_killed(mvm)) {
|
||||
IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n");
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
@ -345,8 +359,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
|
|||
iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvmvif->phy_ctxt = NULL;
|
||||
mvmvif->phy_ctxt = NULL;
|
||||
}
|
||||
|
||||
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
||||
|
@ -363,6 +376,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
|||
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
iwl_mvm_cleanup_iterator, mvm);
|
||||
|
||||
mvm->p2p_device_vif = NULL;
|
||||
|
||||
iwl_mvm_reset_phy_ctxts(mvm);
|
||||
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
|
||||
memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
|
||||
|
||||
|
@ -456,6 +472,20 @@ static void iwl_mvm_power_update_iterator(void *data, u8 *mac,
|
|||
iwl_mvm_power_update_mode(mvm, vif);
|
||||
}
|
||||
|
||||
static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
|
||||
{
|
||||
u16 i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < NUM_PHY_CTX; i++)
|
||||
if (!mvm->phy_ctxts[i].ref)
|
||||
return &mvm->phy_ctxts[i];
|
||||
|
||||
IWL_ERR(mvm, "No available PHY context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -530,32 +560,34 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
*/
|
||||
iwl_mvm_power_update_mode(mvm, vif);
|
||||
|
||||
/* beacon filtering */
|
||||
if (!mvm->bf_allowed_vif &&
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p){
|
||||
mvm->bf_allowed_vif = mvmvif;
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif);
|
||||
if (ret)
|
||||
goto out_release;
|
||||
|
||||
/*
|
||||
* P2P_DEVICE interface does not have a channel context assigned to it,
|
||||
* so a dedicated PHY context is allocated to it and the corresponding
|
||||
* MAC context is bound to it at this stage.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
struct ieee80211_channel *chan;
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
mvmvif->phy_ctxt = &mvm->phy_ctxt_roc;
|
||||
|
||||
/*
|
||||
* The channel used here isn't relevant as it's
|
||||
* going to be overwritten as part of the ROC flow.
|
||||
* For now use the first channel we have.
|
||||
*/
|
||||
chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0];
|
||||
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt,
|
||||
&chandef, 1, 1);
|
||||
if (ret)
|
||||
mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!mvmvif->phy_ctxt) {
|
||||
ret = -ENOSPC;
|
||||
goto out_remove_mac;
|
||||
}
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
|
||||
ret = iwl_mvm_binding_add_vif(mvm, vif);
|
||||
if (ret)
|
||||
goto out_remove_phy;
|
||||
goto out_unref_phy;
|
||||
|
||||
ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
|
||||
if (ret)
|
||||
|
@ -571,8 +603,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
out_unbind:
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
out_remove_phy:
|
||||
iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt);
|
||||
out_unref_phy:
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
|
||||
out_remove_mac:
|
||||
mvmvif->phy_ctxt = NULL;
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
|
@ -646,6 +678,11 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (mvm->bf_allowed_vif == mvmvif) {
|
||||
mvm->bf_allowed_vif = NULL;
|
||||
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_clean(mvm, vif);
|
||||
|
||||
/*
|
||||
|
@ -661,7 +698,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
mvm->p2p_device_vif = NULL;
|
||||
iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt);
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
|
||||
mvmvif->phy_ctxt = NULL;
|
||||
}
|
||||
|
||||
|
@ -701,6 +738,20 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
|
|||
*total_flags = 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_configure_mcast_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mcast_filter_cmd mcast_filter_cmd = {
|
||||
.pass_all = 1,
|
||||
};
|
||||
|
||||
memcpy(mcast_filter_cmd.bssid, vif->bss_conf.bssid, ETH_ALEN);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC,
|
||||
sizeof(mcast_filter_cmd),
|
||||
&mcast_filter_cmd);
|
||||
}
|
||||
|
||||
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
|
@ -722,6 +773,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
return;
|
||||
}
|
||||
iwl_mvm_bt_coex_vif_assoc(mvm, vif);
|
||||
iwl_mvm_configure_mcast_filter(mvm, vif);
|
||||
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
|
||||
/* remove AP station now that the MAC is unassoc */
|
||||
ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
|
||||
|
@ -931,7 +983,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
|
|||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_SLEEP:
|
||||
if (atomic_read(&mvmsta->pending_frames) > 0)
|
||||
if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0)
|
||||
ieee80211_sta_block_awake(hw, sta, true);
|
||||
/*
|
||||
* The fw updates the STA to be asleep. Tx packets on the Tx
|
||||
|
@ -984,9 +1036,13 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
mvmvif->phy_ctxt->channel->band);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
/* enable beacon filtering */
|
||||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif));
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
/* disable beacon filtering */
|
||||
WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif));
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH) {
|
||||
|
@ -1152,29 +1208,107 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
|
|||
enum ieee80211_roc_type type)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct cfg80211_chan_def chandef;
|
||||
int ret;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
int ret, i;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
|
||||
duration, type);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
|
||||
IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
|
||||
duration, type);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, &mvm->phy_ctxt_roc,
|
||||
&chandef, 1, 1);
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
phy_ctxt = &mvm->phy_ctxts[i];
|
||||
if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
|
||||
continue;
|
||||
|
||||
if (phy_ctxt->ref && channel == phy_ctxt->channel) {
|
||||
/*
|
||||
* Unbind the P2P_DEVICE from the current PHY context,
|
||||
* and if the PHY context is not used remove it.
|
||||
*/
|
||||
ret = iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
|
||||
|
||||
/* Bind the P2P_DEVICE to the current PHY Context */
|
||||
mvmvif->phy_ctxt = phy_ctxt;
|
||||
|
||||
ret = iwl_mvm_binding_add_vif(mvm, vif);
|
||||
if (WARN(ret, "Failed binding P2P_DEVICE\n"))
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
|
||||
goto schedule_time_event;
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to update the PHY context only if the ROC channel changed */
|
||||
if (channel == mvmvif->phy_ctxt->channel)
|
||||
goto schedule_time_event;
|
||||
|
||||
cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
|
||||
|
||||
/*
|
||||
* Change the PHY context configuration as it is currently referenced
|
||||
* only by the P2P Device MAC
|
||||
*/
|
||||
if (mvmvif->phy_ctxt->ref == 1) {
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt,
|
||||
&chandef, 1, 1);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
/*
|
||||
* The PHY context is shared with other MACs. Need to remove the
|
||||
* P2P Device from the binding, allocate an new PHY context and
|
||||
* create a new binding
|
||||
*/
|
||||
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!phy_ctxt) {
|
||||
ret = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef,
|
||||
1, 1);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to change PHY context\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* Unbind the P2P_DEVICE from the current PHY context */
|
||||
ret = iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
|
||||
|
||||
/* Bind the P2P_DEVICE to the new allocated PHY context */
|
||||
mvmvif->phy_ctxt = phy_ctxt;
|
||||
|
||||
ret = iwl_mvm_binding_add_vif(mvm, vif);
|
||||
if (WARN(ret, "Failed binding P2P_DEVICE\n"))
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
|
||||
}
|
||||
|
||||
schedule_time_event:
|
||||
/* Schedule the time events */
|
||||
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
IWL_DEBUG_MAC80211(mvm, "leave\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1196,15 +1330,30 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
|
||||
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
IWL_DEBUG_MAC80211(mvm, "Add channel context\n");
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "Add PHY context\n");
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def,
|
||||
ctx->rx_chains_static,
|
||||
ctx->rx_chains_dynamic);
|
||||
mutex_lock(&mvm->mutex);
|
||||
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!phy_ctxt) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
|
||||
ctx->rx_chains_static,
|
||||
ctx->rx_chains_dynamic);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to add PHY context\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
|
||||
*phy_ctxt_id = phy_ctxt->id;
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1213,10 +1362,11 @@ static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
|
||||
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_phy_ctxt_remove(mvm, phy_ctxt);
|
||||
iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
|
@ -1225,7 +1375,16 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
|
|||
u32 changed)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
|
||||
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
||||
|
||||
if (WARN_ONCE((phy_ctxt->ref > 1) &&
|
||||
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
|
||||
IEEE80211_CHANCTX_CHANGE_RX_CHAINS |
|
||||
IEEE80211_CHANCTX_CHANGE_RADAR)),
|
||||
"Cannot change PHY. Ref=%d, changed=0x%X\n",
|
||||
phy_ctxt->ref, changed))
|
||||
return;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
|
||||
|
@ -1239,13 +1398,14 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_phy_ctxt *phyctx = (void *)ctx->drv_priv;
|
||||
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
mvmvif->phy_ctxt = phyctx;
|
||||
mvmvif->phy_ctxt = phy_ctxt;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
|
|
@ -109,6 +109,7 @@ extern struct iwl_mvm_mod_params iwlmvm_mod_params;
|
|||
struct iwl_mvm_phy_ctxt {
|
||||
u16 id;
|
||||
u16 color;
|
||||
u32 ref;
|
||||
|
||||
/*
|
||||
* TODO: This should probably be removed. Currently here only for rate
|
||||
|
@ -149,6 +150,60 @@ enum iwl_power_scheme {
|
|||
|
||||
#define IWL_CONN_MAX_LISTEN_INTERVAL 70
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
enum iwl_dbgfs_pm_mask {
|
||||
MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0),
|
||||
MVM_DEBUGFS_PM_SKIP_OVER_DTIM = BIT(1),
|
||||
MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS = BIT(2),
|
||||
MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3),
|
||||
MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4),
|
||||
MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
|
||||
};
|
||||
|
||||
struct iwl_dbgfs_pm {
|
||||
u8 keep_alive_seconds;
|
||||
u32 rx_data_timeout;
|
||||
u32 tx_data_timeout;
|
||||
bool skip_over_dtim;
|
||||
u8 skip_dtim_periods;
|
||||
bool disable_power_off;
|
||||
int mask;
|
||||
};
|
||||
|
||||
/* beacon filtering */
|
||||
|
||||
enum iwl_dbgfs_bf_mask {
|
||||
MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0),
|
||||
MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1),
|
||||
MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2),
|
||||
MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3),
|
||||
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4),
|
||||
MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5),
|
||||
MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6),
|
||||
MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7),
|
||||
MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8),
|
||||
};
|
||||
|
||||
struct iwl_dbgfs_bf {
|
||||
u8 bf_energy_delta;
|
||||
u8 bf_roaming_energy_delta;
|
||||
u8 bf_roaming_state;
|
||||
u8 bf_temperature_delta;
|
||||
u8 bf_enable_beacon_filter;
|
||||
u8 bf_debug_flag;
|
||||
u32 bf_escape_timer;
|
||||
u32 ba_escape_timer;
|
||||
u8 ba_enable_beacon_abort;
|
||||
int mask;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum iwl_mvm_smps_type_request {
|
||||
IWL_MVM_SMPS_REQ_BT_COEX,
|
||||
IWL_MVM_SMPS_REQ_TT,
|
||||
NUM_IWL_MVM_SMPS_REQ,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
|
||||
* @id: between 0 and 3
|
||||
|
@ -163,6 +218,8 @@ enum iwl_power_scheme {
|
|||
* @bcast_sta: station used for broadcast packets. Used by the following
|
||||
* vifs: P2P_DEVICE, GO and AP.
|
||||
* @beacon_skb: the skb used to hold the AP/GO beacon template
|
||||
* @smps_requests: the requests of of differents parts of the driver, regard
|
||||
the desired smps mode.
|
||||
*/
|
||||
struct iwl_mvm_vif {
|
||||
u16 id;
|
||||
|
@ -172,6 +229,8 @@ struct iwl_mvm_vif {
|
|||
bool uploaded;
|
||||
bool ap_active;
|
||||
bool monitor_active;
|
||||
/* indicate whether beacon filtering is enabled */
|
||||
bool bf_enabled;
|
||||
|
||||
u32 ap_beacon_time;
|
||||
|
||||
|
@ -214,7 +273,11 @@ struct iwl_mvm_vif {
|
|||
struct dentry *dbgfs_dir;
|
||||
struct dentry *dbgfs_slink;
|
||||
void *dbgfs_data;
|
||||
struct iwl_dbgfs_pm dbgfs_pm;
|
||||
struct iwl_dbgfs_bf dbgfs_bf;
|
||||
#endif
|
||||
|
||||
enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
|
||||
};
|
||||
|
||||
static inline struct iwl_mvm_vif *
|
||||
|
@ -223,12 +286,6 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
|
|||
return (void *)vif->drv_priv;
|
||||
}
|
||||
|
||||
enum iwl_mvm_status {
|
||||
IWL_MVM_STATUS_HW_RFKILL,
|
||||
IWL_MVM_STATUS_ROC_RUNNING,
|
||||
IWL_MVM_STATUS_IN_HW_RESTART,
|
||||
};
|
||||
|
||||
enum iwl_scan_status {
|
||||
IWL_MVM_SCAN_NONE,
|
||||
IWL_MVM_SCAN_OS,
|
||||
|
@ -246,6 +303,63 @@ struct iwl_nvm_section {
|
|||
const u8 *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Tx-backoff threshold
|
||||
* @temperature: The threshold in Celsius
|
||||
* @backoff: The tx-backoff in uSec
|
||||
*/
|
||||
struct iwl_tt_tx_backoff {
|
||||
s32 temperature;
|
||||
u32 backoff;
|
||||
};
|
||||
|
||||
#define TT_TX_BACKOFF_SIZE 6
|
||||
|
||||
/**
|
||||
* struct iwl_tt_params - thermal throttling parameters
|
||||
* @ct_kill_entry: CT Kill entry threshold
|
||||
* @ct_kill_exit: CT Kill exit threshold
|
||||
* @ct_kill_duration: The time intervals (in uSec) in which the driver needs
|
||||
* to checks whether to exit CT Kill.
|
||||
* @dynamic_smps_entry: Dynamic SMPS entry threshold
|
||||
* @dynamic_smps_exit: Dynamic SMPS exit threshold
|
||||
* @tx_protection_entry: TX protection entry threshold
|
||||
* @tx_protection_exit: TX protection exit threshold
|
||||
* @tx_backoff: Array of thresholds for tx-backoff , in ascending order.
|
||||
* @support_ct_kill: Support CT Kill?
|
||||
* @support_dynamic_smps: Support dynamic SMPS?
|
||||
* @support_tx_protection: Support tx protection?
|
||||
* @support_tx_backoff: Support tx-backoff?
|
||||
*/
|
||||
struct iwl_tt_params {
|
||||
s32 ct_kill_entry;
|
||||
s32 ct_kill_exit;
|
||||
u32 ct_kill_duration;
|
||||
s32 dynamic_smps_entry;
|
||||
s32 dynamic_smps_exit;
|
||||
s32 tx_protection_entry;
|
||||
s32 tx_protection_exit;
|
||||
struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE];
|
||||
bool support_ct_kill;
|
||||
bool support_dynamic_smps;
|
||||
bool support_tx_protection;
|
||||
bool support_tx_backoff;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tt_mgnt - Thermal Throttling Management structure
|
||||
* @ct_kill_exit: worker to exit thermal kill
|
||||
* @dynamic_smps: Is thermal throttling enabled dynamic_smps?
|
||||
* @tx_backoff: The current thremal throttling tx backoff in uSec.
|
||||
* @params: Parameters to configure the thermal throttling algorithm.
|
||||
*/
|
||||
struct iwl_mvm_tt_mgmt {
|
||||
struct delayed_work ct_kill_exit;
|
||||
bool dynamic_smps;
|
||||
u32 tx_backoff;
|
||||
const struct iwl_tt_params *params;
|
||||
};
|
||||
|
||||
struct iwl_mvm {
|
||||
/* for logger access */
|
||||
struct device *dev;
|
||||
|
@ -266,6 +380,12 @@ struct iwl_mvm {
|
|||
|
||||
unsigned long status;
|
||||
|
||||
/*
|
||||
* for beacon filtering -
|
||||
* currently only one interface can be supported
|
||||
*/
|
||||
struct iwl_mvm_vif *bf_allowed_vif;
|
||||
|
||||
enum iwl_ucode_type cur_ucode;
|
||||
bool ucode_loaded;
|
||||
bool init_ucode_run;
|
||||
|
@ -292,6 +412,7 @@ struct iwl_mvm {
|
|||
struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT];
|
||||
struct work_struct sta_drained_wk;
|
||||
unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
|
||||
atomic_t pending_frames[IWL_MVM_STATION_COUNT];
|
||||
|
||||
/* configured by mac80211 */
|
||||
u32 rts_threshold;
|
||||
|
@ -312,7 +433,7 @@ struct iwl_mvm {
|
|||
bool prevent_power_down_d3;
|
||||
#endif
|
||||
|
||||
struct iwl_mvm_phy_ctxt phy_ctxt_roc;
|
||||
struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX];
|
||||
|
||||
struct list_head time_event_list;
|
||||
spinlock_t time_event_lock;
|
||||
|
@ -337,11 +458,19 @@ struct iwl_mvm {
|
|||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
bool store_d3_resume_sram;
|
||||
void *d3_resume_sram;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* BT-Coex */
|
||||
u8 bt_kill_msk;
|
||||
struct iwl_bt_coex_profile_notif last_bt_notif;
|
||||
|
||||
/* Thermal Throttling and CTkill */
|
||||
struct iwl_mvm_tt_mgmt thermal_throttle;
|
||||
s32 temperature; /* Celsius */
|
||||
};
|
||||
|
||||
/* Extract MVM priv from op_mode and _hw */
|
||||
|
@ -351,6 +480,19 @@ struct iwl_mvm {
|
|||
#define IWL_MAC80211_GET_MVM(_hw) \
|
||||
IWL_OP_MODE_GET_MVM((struct iwl_op_mode *)((_hw)->priv))
|
||||
|
||||
enum iwl_mvm_status {
|
||||
IWL_MVM_STATUS_HW_RFKILL,
|
||||
IWL_MVM_STATUS_HW_CTKILL,
|
||||
IWL_MVM_STATUS_ROC_RUNNING,
|
||||
IWL_MVM_STATUS_IN_HW_RESTART,
|
||||
};
|
||||
|
||||
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
|
||||
{
|
||||
return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status) ||
|
||||
test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
|
||||
}
|
||||
|
||||
extern const u8 iwl_mvm_ac_to_tx_fifo[];
|
||||
|
||||
struct iwl_rate_info {
|
||||
|
@ -442,8 +584,10 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
u8 chains_static, u8 chains_dynamic);
|
||||
void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt);
|
||||
void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt);
|
||||
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt);
|
||||
|
||||
/* MAC (virtual interface) programming */
|
||||
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
@ -458,6 +602,9 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
|||
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
/* Bindings */
|
||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
@ -533,4 +680,36 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
enum ieee80211_rssi_event rssi_event);
|
||||
void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
||||
/* beacon filtering */
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
||||
struct iwl_beacon_filter_cmd *cmd);
|
||||
int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm);
|
||||
#else
|
||||
static inline void
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
{}
|
||||
static inline int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
/* SMPS */
|
||||
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
enum iwl_mvm_smps_type_request req_type,
|
||||
enum ieee80211_smps_mode smps_request);
|
||||
|
||||
/* Thermal management and CT-kill */
|
||||
void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
|
||||
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <linux/firmware.h>
|
||||
#include "iwl-trans.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
@ -75,31 +76,56 @@ static const int nvm_to_read[] = {
|
|||
};
|
||||
|
||||
/* Default NVM size to read */
|
||||
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
|
||||
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
|
||||
#define IWL_MAX_NVM_SECTION_SIZE 6000
|
||||
|
||||
static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
|
||||
u16 offset, u16 length, u16 section)
|
||||
#define NVM_WRITE_OPCODE 1
|
||||
#define NVM_READ_OPCODE 0
|
||||
|
||||
/*
|
||||
* prepare the NVM host command w/ the pointers to the nvm buffer
|
||||
* and send it to fw
|
||||
*/
|
||||
static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section,
|
||||
u16 offset, u16 length, const u8 *data)
|
||||
{
|
||||
cmd->offset = cpu_to_le16(offset);
|
||||
cmd->length = cpu_to_le16(length);
|
||||
cmd->type = cpu_to_le16(section);
|
||||
struct iwl_nvm_access_cmd nvm_access_cmd = {
|
||||
.offset = cpu_to_le16(offset),
|
||||
.length = cpu_to_le16(length),
|
||||
.type = cpu_to_le16(section),
|
||||
.op_code = NVM_WRITE_OPCODE,
|
||||
};
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = NVM_ACCESS_CMD,
|
||||
.len = { sizeof(struct iwl_nvm_access_cmd), length },
|
||||
.flags = CMD_SYNC | CMD_SEND_IN_RFKILL,
|
||||
.data = { &nvm_access_cmd, data },
|
||||
/* data may come from vmalloc, so use _DUP */
|
||||
.dataflags = { 0, IWL_HCMD_DFL_DUP },
|
||||
};
|
||||
|
||||
return iwl_mvm_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
||||
u16 offset, u16 length, u8 *data)
|
||||
{
|
||||
struct iwl_nvm_access_cmd nvm_access_cmd = {};
|
||||
struct iwl_nvm_access_cmd nvm_access_cmd = {
|
||||
.offset = cpu_to_le16(offset),
|
||||
.length = cpu_to_le16(length),
|
||||
.type = cpu_to_le16(section),
|
||||
.op_code = NVM_READ_OPCODE,
|
||||
};
|
||||
struct iwl_nvm_access_resp *nvm_resp;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = NVM_ACCESS_CMD,
|
||||
.flags = CMD_SYNC | CMD_WANT_SKB,
|
||||
.flags = CMD_SYNC | CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
|
||||
.data = { &nvm_access_cmd, },
|
||||
};
|
||||
int ret, bytes_read, offset_read;
|
||||
u8 *resp_data;
|
||||
|
||||
iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
|
||||
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
|
@ -144,6 +170,30 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section,
|
||||
const u8 *data, u16 length)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
/* copy data in chunks of 2k (and remainder if any) */
|
||||
|
||||
while (offset < length) {
|
||||
int chunk_size, ret;
|
||||
|
||||
chunk_size = min(IWL_NVM_DEFAULT_CHUNK_SIZE,
|
||||
length - offset);
|
||||
|
||||
ret = iwl_nvm_write_chunk(mvm, section, offset,
|
||||
chunk_size, data + offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
offset += chunk_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads an NVM section completely.
|
||||
* NICs prior to 7000 family doesn't have a real NVM, but just read
|
||||
|
@ -177,7 +227,8 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
|
|||
offset += ret;
|
||||
}
|
||||
|
||||
IWL_INFO(mvm, "NVM section %d read completed\n", section);
|
||||
IWL_DEBUG_EEPROM(mvm->trans->dev,
|
||||
"NVM section %d read completed\n", section);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -200,7 +251,130 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
|||
hw = (const __le16 *)sections[NVM_SECTION_TYPE_HW].data;
|
||||
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
|
||||
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
|
||||
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib);
|
||||
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
|
||||
iwl_fw_valid_tx_ant(mvm->fw),
|
||||
iwl_fw_valid_rx_ant(mvm->fw));
|
||||
}
|
||||
|
||||
#define MAX_NVM_FILE_LEN 16384
|
||||
|
||||
/*
|
||||
* HOW TO CREATE THE NVM FILE FORMAT:
|
||||
* ------------------------------
|
||||
* 1. create hex file, format:
|
||||
* 3800 -> header
|
||||
* 0000 -> header
|
||||
* 5a40 -> data
|
||||
*
|
||||
* rev - 6 bit (word1)
|
||||
* len - 10 bit (word1)
|
||||
* id - 4 bit (word2)
|
||||
* rsv - 12 bit (word2)
|
||||
*
|
||||
* 2. flip 8bits with 8 bits per line to get the right NVM file format
|
||||
*
|
||||
* 3. create binary file from the hex file
|
||||
*
|
||||
* 4. save as "iNVM_xxx.bin" under /lib/firmware
|
||||
*/
|
||||
static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, section_id, section_size;
|
||||
const struct firmware *fw_entry;
|
||||
const struct {
|
||||
__le16 word1;
|
||||
__le16 word2;
|
||||
u8 data[];
|
||||
} *file_sec;
|
||||
const u8 *eof;
|
||||
|
||||
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
|
||||
#define NVM_WORD2_ID(x) (x >> 12)
|
||||
|
||||
/*
|
||||
* Obtain NVM image via request_firmware. Since we already used
|
||||
* request_firmware_nowait() for the firmware binary load and only
|
||||
* get here after that we assume the NVM request can be satisfied
|
||||
* synchronously.
|
||||
*/
|
||||
ret = request_firmware(&fw_entry, iwlwifi_mod_params.nvm_file,
|
||||
mvm->trans->dev);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "ERROR: %s isn't available %d\n",
|
||||
iwlwifi_mod_params.nvm_file, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n",
|
||||
iwlwifi_mod_params.nvm_file, fw_entry->size);
|
||||
|
||||
if (fw_entry->size < sizeof(*file_sec)) {
|
||||
IWL_ERR(mvm, "NVM file too small\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fw_entry->size > MAX_NVM_FILE_LEN) {
|
||||
IWL_ERR(mvm, "NVM file too large\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
eof = fw_entry->data + fw_entry->size;
|
||||
|
||||
file_sec = (void *)fw_entry->data;
|
||||
|
||||
while (true) {
|
||||
if (file_sec->data > eof) {
|
||||
IWL_ERR(mvm,
|
||||
"ERROR - NVM file too short for section header\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for EOF marker */
|
||||
if (!file_sec->word1 && !file_sec->word2) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
|
||||
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
|
||||
|
||||
if (section_size > IWL_MAX_NVM_SECTION_SIZE) {
|
||||
IWL_ERR(mvm, "ERROR - section too large (%d)\n",
|
||||
section_size);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!section_size) {
|
||||
IWL_ERR(mvm, "ERROR - section empty\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (file_sec->data + section_size > eof) {
|
||||
IWL_ERR(mvm,
|
||||
"ERROR - NVM file too short for section (%d bytes)\n",
|
||||
section_size);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = iwl_nvm_write_section(mvm, section_id, file_sec->data,
|
||||
section_size);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
/* advance to the next section */
|
||||
file_sec = (void *)(file_sec->data + section_size);
|
||||
}
|
||||
out:
|
||||
release_firmware(fw_entry);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_nvm_init(struct iwl_mvm *mvm)
|
||||
|
@ -208,6 +382,17 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
|
|||
int ret, i, section;
|
||||
u8 *nvm_buffer, *temp;
|
||||
|
||||
/* load external NVM if configured */
|
||||
if (iwlwifi_mod_params.nvm_file) {
|
||||
/* move to External NVM flow */
|
||||
ret = iwl_mvm_load_external_nvm(mvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read From FW NVM */
|
||||
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
|
||||
|
||||
/* TODO: find correct NVM max size for a section */
|
||||
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
|
||||
GFP_KERNEL);
|
||||
|
@ -231,8 +416,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
|
||||
if (!mvm->nvm_data)
|
||||
return -ENODATA;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -222,10 +222,14 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
|
||||
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
|
||||
RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
|
||||
RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true),
|
||||
|
||||
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
|
||||
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
|
||||
|
||||
RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif,
|
||||
false),
|
||||
|
||||
RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
|
||||
};
|
||||
#undef RX_HANDLER
|
||||
|
@ -288,10 +292,14 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
|||
CMD(NET_DETECT_HOTSPOTS_CMD),
|
||||
CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
|
||||
CMD(CARD_STATE_NOTIFICATION),
|
||||
CMD(MISSED_BEACONS_NOTIFICATION),
|
||||
CMD(BT_COEX_PRIO_TABLE),
|
||||
CMD(BT_COEX_PROT_ENV),
|
||||
CMD(BT_PROFILE_NOTIFICATION),
|
||||
CMD(BT_CONFIG),
|
||||
CMD(MCAST_FILTER_CMD),
|
||||
CMD(REPLY_BEACON_FILTERING_CMD),
|
||||
CMD(REPLY_THERMAL_MNG_BACKOFF),
|
||||
};
|
||||
#undef CMD
|
||||
|
||||
|
@ -392,10 +400,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
iwl_mvm_tt_initialize(mvm);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
err = iwl_run_init_mvm_ucode(mvm, true);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
if (err && !iwlmvm_mod_params.init_dbg) {
|
||||
/* returns 0 if successful, 1 if success but in rfkill */
|
||||
if (err < 0 && !iwlmvm_mod_params.init_dbg) {
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -438,10 +449,16 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
|||
|
||||
iwl_mvm_leds_exit(mvm);
|
||||
|
||||
iwl_mvm_tt_exit(mvm);
|
||||
|
||||
ieee80211_unregister_hw(mvm->hw);
|
||||
|
||||
kfree(mvm->scan_cmd);
|
||||
|
||||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
|
||||
kfree(mvm->d3_resume_sram);
|
||||
#endif
|
||||
|
||||
iwl_trans_stop_hw(mvm->trans, true);
|
||||
|
||||
iwl_phy_db_free(mvm->phy_db);
|
||||
|
@ -588,6 +605,16 @@ static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|||
ieee80211_wake_queue(mvm->hw, mq);
|
||||
}
|
||||
|
||||
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
|
||||
{
|
||||
if (state)
|
||||
set_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
|
||||
else
|
||||
clear_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
|
||||
|
||||
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
@ -597,7 +624,7 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
|||
else
|
||||
clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
|
||||
|
||||
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state);
|
||||
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
|
||||
}
|
||||
|
||||
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
|
|
|
@ -195,21 +195,6 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct phy_ctx_used_data {
|
||||
unsigned long used[BITS_TO_LONGS(NUM_PHY_CTX)];
|
||||
};
|
||||
|
||||
static void iwl_mvm_phy_ctx_used_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
void *_data)
|
||||
{
|
||||
struct phy_ctx_used_data *data = _data;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
|
||||
|
||||
__set_bit(phy_ctxt->id, data->used);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to add a PHY context based on the current HW configuration.
|
||||
*/
|
||||
|
@ -217,34 +202,27 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
struct cfg80211_chan_def *chandef,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
struct phy_ctx_used_data data = {
|
||||
.used = { },
|
||||
};
|
||||
|
||||
/*
|
||||
* If this is a regular PHY context (not the ROC one)
|
||||
* skip the ROC PHY context's ID.
|
||||
*/
|
||||
if (ctxt != &mvm->phy_ctxt_roc)
|
||||
__set_bit(mvm->phy_ctxt_roc.id, data.used);
|
||||
int ret;
|
||||
|
||||
WARN_ON(ctxt->ref);
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
ctxt->color++;
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||
ieee80211_iter_chan_contexts_atomic(
|
||||
mvm->hw, iwl_mvm_phy_ctx_used_iter, &data);
|
||||
|
||||
ctxt->id = find_first_zero_bit(data.used, NUM_PHY_CTX);
|
||||
if (WARN_ONCE(ctxt->id == NUM_PHY_CTX,
|
||||
"Failed to init PHY context - no free ID!\n"))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ctxt->channel = chandef->chan;
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_ADD, 0);
|
||||
ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_ADD, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the number of references to the given PHY context. This is valid only
|
||||
* in case the PHY context was already created, i.e., its reference count > 0.
|
||||
*/
|
||||
void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
{
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
ctxt->ref++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -264,23 +242,12 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
FW_CTXT_ACTION_MODIFY, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to the FW to remove the given phy context.
|
||||
* Once the command is sent, regardless of success or failure, the context is
|
||||
* marked as invalid
|
||||
*/
|
||||
void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
{
|
||||
struct iwl_phy_context_cmd cmd;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, FW_CTXT_ACTION_REMOVE, 0);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC,
|
||||
sizeof(struct iwl_phy_context_cmd),
|
||||
&cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n",
|
||||
ctxt->id);
|
||||
if (WARN_ON_ONCE(!ctxt))
|
||||
return;
|
||||
|
||||
ctxt->ref--;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,54 @@
|
|||
|
||||
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
|
||||
|
||||
static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC,
|
||||
sizeof(struct iwl_beacon_filter_cmd), cmd);
|
||||
|
||||
if (!ret) {
|
||||
IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
|
||||
cmd->ba_enable_beacon_abort);
|
||||
IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
|
||||
cmd->ba_escape_timer);
|
||||
IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
|
||||
cmd->bf_debug_flag);
|
||||
IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
|
||||
cmd->bf_enable_beacon_filter);
|
||||
IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
|
||||
cmd->bf_energy_delta);
|
||||
IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
|
||||
cmd->bf_escape_timer);
|
||||
IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
|
||||
cmd->bf_roaming_energy_delta);
|
||||
IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
|
||||
cmd->bf_roaming_state);
|
||||
IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n",
|
||||
cmd->bf_temperature_delta);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
IWL_BF_CMD_CONFIG_DEFAULTS,
|
||||
.bf_enable_beacon_filter = 1,
|
||||
.ba_enable_beacon_abort = enable,
|
||||
};
|
||||
|
||||
if (!mvmvif->bf_enabled)
|
||||
return 0;
|
||||
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
|
||||
return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
||||
struct iwl_powertable_cmd *cmd)
|
||||
{
|
||||
|
@ -91,6 +139,9 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
|||
le32_to_cpu(cmd->tx_data_timeout));
|
||||
IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
|
||||
cmd->lprx_rssi_threshold);
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
|
||||
IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
|
||||
le32_to_cpu(cmd->skip_dtim_periods));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +154,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
int dtimper, dtimper_msec;
|
||||
int keep_alive;
|
||||
bool radar_detect = false;
|
||||
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
/*
|
||||
* Regardless of power management state the driver must set
|
||||
|
@ -116,6 +169,11 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
|
||||
mvmvif->dbgfs_pm.disable_power_off)
|
||||
cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
#endif
|
||||
if (!vif->bss_conf.ps)
|
||||
return;
|
||||
|
||||
|
@ -135,8 +193,11 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
/* Check skip over DTIM conditions */
|
||||
if (!radar_detect && (dtimper <= 10) &&
|
||||
(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP))
|
||||
(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
|
||||
mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
cmd->skip_dtim_periods = cpu_to_le32(3);
|
||||
}
|
||||
|
||||
/* Check that keep alive period is at least 3 * DTIM */
|
||||
dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
|
@ -145,12 +206,41 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
|
||||
cmd->keep_alive_seconds = keep_alive;
|
||||
|
||||
cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
|
||||
cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
} else {
|
||||
cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
|
||||
cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
|
||||
if (mvmvif->dbgfs_pm.skip_over_dtim)
|
||||
cmd->flags |=
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
else
|
||||
cmd->flags &=
|
||||
cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
}
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
|
||||
cmd->skip_dtim_periods =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
}
|
||||
|
||||
int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
int ret;
|
||||
bool ba_enable;
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
|
@ -159,13 +249,22 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ba_enable = !!(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
|
||||
|
||||
return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
|
||||
}
|
||||
|
||||
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
@ -173,8 +272,82 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
|
||||
cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
|
||||
mvmvif->dbgfs_pm.disable_power_off)
|
||||
cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
#endif
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
|
||||
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
|
||||
cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta;
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
|
||||
cmd->bf_roaming_energy_delta =
|
||||
dbgfs_bf->bf_roaming_energy_delta;
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
|
||||
cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state;
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA)
|
||||
cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta;
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
|
||||
cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag;
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
|
||||
cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
|
||||
cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
|
||||
cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort;
|
||||
}
|
||||
#endif
|
||||
|
||||
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
IWL_BF_CMD_CONFIG_DEFAULTS,
|
||||
.bf_enable_beacon_filter = 1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (mvmvif != mvm->bf_allowed_vif ||
|
||||
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
|
||||
if (!ret)
|
||||
mvmvif->bf_enabled = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_beacon_filter_cmd cmd = {};
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
|
||||
if (!ret)
|
||||
mvmvif->bf_enabled = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -3080,3 +3080,29 @@ void iwl_mvm_rate_control_unregister(void)
|
|||
{
|
||||
ieee80211_rate_control_unregister(&rs_mvm_ops);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
|
||||
* Tx protection, according to this rquest and previous requests,
|
||||
* and send the LQ command.
|
||||
* @lq: The LQ command
|
||||
* @mvmsta: The station
|
||||
* @enable: Enable Tx protection?
|
||||
*/
|
||||
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
|
||||
struct iwl_mvm_sta *mvmsta, bool enable)
|
||||
{
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (enable) {
|
||||
if (mvmsta->tx_protection == 0)
|
||||
lq->flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK;
|
||||
mvmsta->tx_protection++;
|
||||
} else {
|
||||
mvmsta->tx_protection--;
|
||||
if (mvmsta->tx_protection == 0)
|
||||
lq->flags &= ~LQ_FLAG_SET_STA_TLC_RTS_MSK;
|
||||
}
|
||||
|
||||
return iwl_mvm_send_lq_cmd(mvm, lq, CMD_ASYNC, false);
|
||||
}
|
||||
|
|
|
@ -390,4 +390,9 @@ extern int iwl_mvm_rate_control_register(void);
|
|||
*/
|
||||
extern void iwl_mvm_rate_control_unregister(void);
|
||||
|
||||
struct iwl_mvm_sta;
|
||||
|
||||
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
|
||||
struct iwl_mvm_sta *mvmsta, bool enable);
|
||||
|
||||
#endif /* __rs__ */
|
||||
|
|
|
@ -363,3 +363,25 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
|||
rxb, &rx_status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler
|
||||
*
|
||||
* TODO: This handler is implemented partially.
|
||||
* It only gets the NIC's temperature.
|
||||
*/
|
||||
int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_notif_statistics *stats = (void *)&pkt->data;
|
||||
struct mvm_statistics_general_common *common = &stats->general.common;
|
||||
|
||||
if (mvm->temperature != le32_to_cpu(common->temperature)) {
|
||||
mvm->temperature = le32_to_cpu(common->temperature);
|
||||
iwl_mvm_tt_handler(mvm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
|
||||
#include "mvm.h"
|
||||
#include "sta.h"
|
||||
#include "rs.h"
|
||||
|
||||
static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)
|
||||
{
|
||||
|
@ -217,9 +218,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
|||
mvmvif->color);
|
||||
mvm_sta->vif = vif;
|
||||
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
||||
mvm_sta->tx_protection = 0;
|
||||
mvm_sta->tt_tx_protection = false;
|
||||
|
||||
/* HW restart, don't assume the memory has been zeroed */
|
||||
atomic_set(&mvm_sta->pending_frames, 0);
|
||||
atomic_set(&mvm->pending_frames[sta_id], 0);
|
||||
mvm_sta->tid_disable_agg = 0;
|
||||
mvm_sta->tfd_queue_msk = 0;
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++)
|
||||
|
@ -406,15 +409,22 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
|||
mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the tx response code sees the station as -EBUSY and
|
||||
* calls the drain worker.
|
||||
*/
|
||||
spin_lock_bh(&mvm_sta->lock);
|
||||
/*
|
||||
* There are frames pending on the AC queues for this station.
|
||||
* We need to wait until all the frames are drained...
|
||||
*/
|
||||
if (atomic_read(&mvm_sta->pending_frames)) {
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
|
||||
if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) {
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
|
||||
ERR_PTR(-EBUSY));
|
||||
spin_unlock_bh(&mvm_sta->lock);
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
|
||||
} else {
|
||||
spin_unlock_bh(&mvm_sta->lock);
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
|
||||
}
|
||||
|
@ -791,21 +801,23 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
min(mvmsta->max_agg_bufsize, buf_size);
|
||||
mvmsta->lq_sta.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
|
||||
|
||||
IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
|
||||
sta->addr, tid);
|
||||
|
||||
if (mvm->cfg->ht_params->use_rts_for_aggregation) {
|
||||
/*
|
||||
* switch to RTS/CTS if it is the prefer protection
|
||||
* method for HT traffic
|
||||
* this function also sends the LQ command
|
||||
*/
|
||||
mvmsta->lq_sta.lq.flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK;
|
||||
return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
|
||||
mvmsta, true);
|
||||
/*
|
||||
* TODO: remove the TLC_RTS flag when we tear down the last
|
||||
* AGG session (agg_tids_count in DVM)
|
||||
*/
|
||||
}
|
||||
|
||||
IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
|
||||
sta->addr, tid);
|
||||
|
||||
return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -274,8 +274,9 @@ struct iwl_mvm_tid_data {
|
|||
* @bt_reduced_txpower: is reduced tx power enabled for this station
|
||||
* @lock: lock to protect the whole struct. Since %tid_data is access from Tx
|
||||
* and from Tx response flow, it needs a spinlock.
|
||||
* @pending_frames: number of frames for this STA on the shared Tx queues.
|
||||
* @tid_data: per tid data. Look at %iwl_mvm_tid_data.
|
||||
* @tx_protection: reference counter for controlling the Tx protection.
|
||||
* @tt_tx_protection: is thermal throttling enable Tx protection?
|
||||
*
|
||||
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
|
||||
* in the structure for use by driver. This structure is placed in that
|
||||
|
@ -290,7 +291,6 @@ struct iwl_mvm_sta {
|
|||
u8 max_agg_bufsize;
|
||||
bool bt_reduced_txpower;
|
||||
spinlock_t lock;
|
||||
atomic_t pending_frames;
|
||||
struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
|
||||
struct iwl_lq_sta lq_sta;
|
||||
struct ieee80211_vif *vif;
|
||||
|
@ -298,6 +298,10 @@ struct iwl_mvm_sta {
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
u16 last_seq_ctl;
|
||||
#endif
|
||||
|
||||
/* Temporary, until the new TLC will control the Tx protection */
|
||||
s8 tx_protection;
|
||||
bool tt_tx_protection;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,509 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "mvm.h"
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
#define OTP_DTS_DIODE_DEVIATION 96 /*in words*/
|
||||
/* VBG - Voltage Band Gap error data (temperature offset) */
|
||||
#define OTP_WP_DTS_VBG (OTP_DTS_DIODE_DEVIATION + 2)
|
||||
#define MEAS_VBG_MIN_VAL 2300
|
||||
#define MEAS_VBG_MAX_VAL 3000
|
||||
#define MEAS_VBG_DEFAULT_VAL 2700
|
||||
#define DTS_DIODE_VALID(flags) (flags & DTS_DIODE_REG_FLAGS_PASS_ONCE)
|
||||
#define MIN_TEMPERATURE 0
|
||||
#define MAX_TEMPERATURE 125
|
||||
#define TEMPERATURE_ERROR (MAX_TEMPERATURE + 1)
|
||||
#define PTAT_DIGITAL_VALUE_MIN_VALUE 0
|
||||
#define PTAT_DIGITAL_VALUE_MAX_VALUE 0xFF
|
||||
#define DTS_VREFS_NUM 5
|
||||
static inline u32 DTS_DIODE_GET_VREFS_ID(u32 flags)
|
||||
{
|
||||
return (flags & DTS_DIODE_REG_FLAGS_VREFS_ID) >>
|
||||
DTS_DIODE_REG_FLAGS_VREFS_ID_POS;
|
||||
}
|
||||
|
||||
#define CALC_VREFS_MIN_DIFF 43
|
||||
#define CALC_VREFS_MAX_DIFF 51
|
||||
#define CALC_LUT_SIZE (1 + CALC_VREFS_MAX_DIFF - CALC_VREFS_MIN_DIFF)
|
||||
#define CALC_LUT_INDEX_OFFSET CALC_VREFS_MIN_DIFF
|
||||
#define CALC_TEMPERATURE_RESULT_SHIFT_OFFSET 23
|
||||
|
||||
/*
|
||||
* @digital_value: The diode's digital-value sampled (temperature/voltage)
|
||||
* @vref_low: The lower voltage-reference (the vref just below the diode's
|
||||
* sampled digital-value)
|
||||
* @vref_high: The higher voltage-reference (the vref just above the diode's
|
||||
* sampled digital-value)
|
||||
* @flags: bits[1:0]: The ID of the Vrefs pair (lowVref,highVref)
|
||||
* bits[6:2]: Reserved.
|
||||
* bits[7:7]: Indicates completion of at least 1 successful sample
|
||||
* since last DTS reset.
|
||||
*/
|
||||
struct iwl_mvm_dts_diode_bits {
|
||||
u8 digital_value;
|
||||
u8 vref_low;
|
||||
u8 vref_high;
|
||||
u8 flags;
|
||||
} __packed;
|
||||
|
||||
union dts_diode_results {
|
||||
u32 reg_value;
|
||||
struct iwl_mvm_dts_diode_bits bits;
|
||||
} __packed;
|
||||
|
||||
static s16 iwl_mvm_dts_get_volt_band_gap(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_nvm_section calib_sec;
|
||||
const __le16 *calib;
|
||||
u16 vbg;
|
||||
|
||||
/* TODO: move parsing to NVM code */
|
||||
calib_sec = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION];
|
||||
calib = (__le16 *)calib_sec.data;
|
||||
|
||||
vbg = le16_to_cpu(calib[OTP_WP_DTS_VBG]);
|
||||
|
||||
if (vbg < MEAS_VBG_MIN_VAL || vbg > MEAS_VBG_MAX_VAL)
|
||||
vbg = MEAS_VBG_DEFAULT_VAL;
|
||||
|
||||
return vbg;
|
||||
}
|
||||
|
||||
static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
|
||||
{
|
||||
const u8 *calib;
|
||||
u8 ptat, pa1, pa2, median;
|
||||
|
||||
/* TODO: move parsing to NVM code */
|
||||
calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
|
||||
ptat = calib[OTP_DTS_DIODE_DEVIATION];
|
||||
pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1];
|
||||
pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2];
|
||||
|
||||
/* get the median: */
|
||||
if (ptat > pa1) {
|
||||
if (ptat > pa2)
|
||||
median = (pa1 > pa2) ? pa1 : pa2;
|
||||
else
|
||||
median = ptat;
|
||||
} else {
|
||||
if (pa1 > pa2)
|
||||
median = (ptat > pa2) ? ptat : pa2;
|
||||
else
|
||||
median = pa1;
|
||||
}
|
||||
|
||||
return ptat - median;
|
||||
}
|
||||
|
||||
static u8 iwl_mvm_dts_calibrate_ptat_deviation(struct iwl_mvm *mvm, u8 value)
|
||||
{
|
||||
/* Calibrate the PTAT digital value, based on PTAT deviation data: */
|
||||
s16 new_val = value - iwl_mvm_dts_get_ptat_deviation_offset(mvm);
|
||||
|
||||
if (new_val > PTAT_DIGITAL_VALUE_MAX_VALUE)
|
||||
new_val = PTAT_DIGITAL_VALUE_MAX_VALUE;
|
||||
else if (new_val < PTAT_DIGITAL_VALUE_MIN_VALUE)
|
||||
new_val = PTAT_DIGITAL_VALUE_MIN_VALUE;
|
||||
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static bool dts_get_adjacent_vrefs(struct iwl_mvm *mvm,
|
||||
union dts_diode_results *avg_ptat)
|
||||
{
|
||||
u8 vrefs_results[DTS_VREFS_NUM];
|
||||
u8 low_vref_index = 0, flags;
|
||||
u32 reg;
|
||||
|
||||
reg = iwl_read_prph(mvm->trans, DTSC_VREF_AVG);
|
||||
memcpy(vrefs_results, ®, sizeof(reg));
|
||||
reg = iwl_read_prph(mvm->trans, DTSC_VREF5_AVG);
|
||||
vrefs_results[4] = reg & 0xff;
|
||||
|
||||
if (avg_ptat->bits.digital_value < vrefs_results[0] ||
|
||||
avg_ptat->bits.digital_value > vrefs_results[4])
|
||||
return false;
|
||||
|
||||
if (avg_ptat->bits.digital_value > vrefs_results[3])
|
||||
low_vref_index = 3;
|
||||
else if (avg_ptat->bits.digital_value > vrefs_results[2])
|
||||
low_vref_index = 2;
|
||||
else if (avg_ptat->bits.digital_value > vrefs_results[1])
|
||||
low_vref_index = 1;
|
||||
|
||||
avg_ptat->bits.vref_low = vrefs_results[low_vref_index];
|
||||
avg_ptat->bits.vref_high = vrefs_results[low_vref_index + 1];
|
||||
flags = avg_ptat->bits.flags;
|
||||
avg_ptat->bits.flags =
|
||||
(flags & ~DTS_DIODE_REG_FLAGS_VREFS_ID) |
|
||||
(low_vref_index & DTS_DIODE_REG_FLAGS_VREFS_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* return true it the results are valid, and false otherwise.
|
||||
*/
|
||||
static bool dts_read_ptat_avg_results(struct iwl_mvm *mvm,
|
||||
union dts_diode_results *avg_ptat)
|
||||
{
|
||||
u32 reg;
|
||||
u8 tmp;
|
||||
|
||||
/* fill the diode value and pass_once with avg-reg results */
|
||||
reg = iwl_read_prph(mvm->trans, DTSC_PTAT_AVG);
|
||||
reg &= DTS_DIODE_REG_DIG_VAL | DTS_DIODE_REG_PASS_ONCE;
|
||||
avg_ptat->reg_value = reg;
|
||||
|
||||
/* calibrate the PTAT digital value */
|
||||
tmp = avg_ptat->bits.digital_value;
|
||||
tmp = iwl_mvm_dts_calibrate_ptat_deviation(mvm, tmp);
|
||||
avg_ptat->bits.digital_value = tmp;
|
||||
|
||||
/*
|
||||
* fill vrefs fields, based on the avgVrefs results
|
||||
* and the diode value
|
||||
*/
|
||||
return dts_get_adjacent_vrefs(mvm, avg_ptat) &&
|
||||
DTS_DIODE_VALID(avg_ptat->bits.flags);
|
||||
}
|
||||
|
||||
static s32 calculate_nic_temperature(union dts_diode_results avg_ptat,
|
||||
u16 volt_band_gap)
|
||||
{
|
||||
u32 tmp_result;
|
||||
u8 vrefs_diff;
|
||||
/*
|
||||
* For temperature calculation (at the end, shift right by 23)
|
||||
* LUT[(D2-D1)] = ROUND{ 2^23 / ((D2-D1)*9*10) }
|
||||
* (D2-D1) == 43 44 45 46 47 48 49 50 51
|
||||
*/
|
||||
static const u16 calc_lut[CALC_LUT_SIZE] = {
|
||||
2168, 2118, 2071, 2026, 1983, 1942, 1902, 1864, 1828,
|
||||
};
|
||||
|
||||
/*
|
||||
* The diff between the high and low voltage-references is assumed
|
||||
* to be strictly be in range of [60,68]
|
||||
*/
|
||||
vrefs_diff = avg_ptat.bits.vref_high - avg_ptat.bits.vref_low;
|
||||
|
||||
if (vrefs_diff < CALC_VREFS_MIN_DIFF ||
|
||||
vrefs_diff > CALC_VREFS_MAX_DIFF)
|
||||
return TEMPERATURE_ERROR;
|
||||
|
||||
/* calculate the result: */
|
||||
tmp_result =
|
||||
vrefs_diff * (DTS_DIODE_GET_VREFS_ID(avg_ptat.bits.flags) + 9);
|
||||
tmp_result += avg_ptat.bits.digital_value;
|
||||
tmp_result -= avg_ptat.bits.vref_high;
|
||||
|
||||
/* multiply by the LUT value (based on the diff) */
|
||||
tmp_result *= calc_lut[vrefs_diff - CALC_LUT_INDEX_OFFSET];
|
||||
|
||||
/*
|
||||
* Get the BandGap (the voltage refereces source) error data
|
||||
* (temperature offset)
|
||||
*/
|
||||
tmp_result *= volt_band_gap;
|
||||
|
||||
/*
|
||||
* here, tmp_result value can be up to 32-bits. We want to right-shift
|
||||
* it *without* sign-extend.
|
||||
*/
|
||||
tmp_result = tmp_result >> CALC_TEMPERATURE_RESULT_SHIFT_OFFSET;
|
||||
|
||||
/*
|
||||
* at this point, tmp_result should be in the range:
|
||||
* 200 <= tmp_result <= 365
|
||||
*/
|
||||
return (s16)tmp_result - 240;
|
||||
}
|
||||
|
||||
static s32 check_nic_temperature(struct iwl_mvm *mvm)
|
||||
{
|
||||
u16 volt_band_gap;
|
||||
union dts_diode_results avg_ptat;
|
||||
|
||||
volt_band_gap = iwl_mvm_dts_get_volt_band_gap(mvm);
|
||||
|
||||
/* disable DTS */
|
||||
iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0);
|
||||
|
||||
/* SV initialization */
|
||||
iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 1);
|
||||
iwl_write_prph(mvm->trans, DTSC_CFG_MODE,
|
||||
DTSC_CFG_MODE_PERIODIC);
|
||||
|
||||
/* wait for results */
|
||||
msleep(100);
|
||||
if (!dts_read_ptat_avg_results(mvm, &avg_ptat))
|
||||
return TEMPERATURE_ERROR;
|
||||
|
||||
/* disable DTS */
|
||||
iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0);
|
||||
|
||||
return calculate_nic_temperature(avg_ptat, volt_band_gap);
|
||||
}
|
||||
|
||||
static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
|
||||
{
|
||||
u32 duration = mvm->thermal_throttle.params->ct_kill_duration;
|
||||
|
||||
IWL_ERR(mvm, "Enter CT Kill\n");
|
||||
iwl_mvm_set_hw_ctkill_state(mvm, true);
|
||||
schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit,
|
||||
round_jiffies_relative(duration * HZ));
|
||||
}
|
||||
|
||||
static void iwl_mvm_exit_ctkill(struct iwl_mvm *mvm)
|
||||
{
|
||||
IWL_ERR(mvm, "Exit CT Kill\n");
|
||||
iwl_mvm_set_hw_ctkill_state(mvm, false);
|
||||
}
|
||||
|
||||
static void check_exit_ctkill(struct work_struct *work)
|
||||
{
|
||||
struct iwl_mvm_tt_mgmt *tt;
|
||||
struct iwl_mvm *mvm;
|
||||
u32 duration;
|
||||
s32 temp;
|
||||
|
||||
tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work);
|
||||
mvm = container_of(tt, struct iwl_mvm, thermal_throttle);
|
||||
|
||||
duration = tt->params->ct_kill_duration;
|
||||
|
||||
iwl_trans_start_hw(mvm->trans);
|
||||
temp = check_nic_temperature(mvm);
|
||||
iwl_trans_stop_hw(mvm->trans, false);
|
||||
|
||||
if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
|
||||
IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
|
||||
goto reschedule;
|
||||
}
|
||||
IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp);
|
||||
|
||||
if (temp <= tt->params->ct_kill_exit) {
|
||||
iwl_mvm_exit_ctkill(mvm);
|
||||
return;
|
||||
}
|
||||
|
||||
reschedule:
|
||||
schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit,
|
||||
round_jiffies(duration * HZ));
|
||||
}
|
||||
|
||||
static void iwl_mvm_tt_smps_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = _data;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (mvm->thermal_throttle.dynamic_smps)
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
else
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode);
|
||||
}
|
||||
|
||||
static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (IS_ERR_OR_NULL(sta))
|
||||
continue;
|
||||
mvmsta = (void *)sta->drv_priv;
|
||||
if (enable == mvmsta->tt_tx_protection)
|
||||
continue;
|
||||
err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
|
||||
mvmsta, enable);
|
||||
if (err) {
|
||||
IWL_ERR(mvm, "Failed to %s Tx protection\n",
|
||||
enable ? "enable" : "disable");
|
||||
} else {
|
||||
IWL_DEBUG_TEMP(mvm, "%s Tx protection\n",
|
||||
enable ? "Enable" : "Disable");
|
||||
mvmsta->tt_tx_protection = enable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_THERMAL_MNG_BACKOFF,
|
||||
.len = { sizeof(u32), },
|
||||
.data = { &backoff, },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
if (iwl_mvm_send_cmd(mvm, &cmd) == 0) {
|
||||
IWL_DEBUG_TEMP(mvm, "Set Thermal Tx backoff to: %u\n",
|
||||
backoff);
|
||||
mvm->thermal_throttle.tx_backoff = backoff;
|
||||
} else {
|
||||
IWL_ERR(mvm, "Failed to change Thermal Tx backoff\n");
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
|
||||
{
|
||||
const struct iwl_tt_params *params = mvm->thermal_throttle.params;
|
||||
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
|
||||
s32 temperature = mvm->temperature;
|
||||
int i;
|
||||
u32 tx_backoff;
|
||||
|
||||
IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", mvm->temperature);
|
||||
|
||||
if (params->support_ct_kill && temperature >= params->ct_kill_entry) {
|
||||
iwl_mvm_enter_ctkill(mvm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (params->support_dynamic_smps) {
|
||||
if (!tt->dynamic_smps &&
|
||||
temperature >= params->dynamic_smps_entry) {
|
||||
IWL_DEBUG_TEMP(mvm, "Enable dynamic SMPS\n");
|
||||
tt->dynamic_smps = true;
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_tt_smps_iterator, mvm);
|
||||
} else if (tt->dynamic_smps &&
|
||||
temperature <= params->dynamic_smps_exit) {
|
||||
IWL_DEBUG_TEMP(mvm, "Disable dynamic SMPS\n");
|
||||
tt->dynamic_smps = false;
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_tt_smps_iterator, mvm);
|
||||
}
|
||||
}
|
||||
|
||||
if (params->support_tx_protection) {
|
||||
if (temperature >= params->tx_protection_entry)
|
||||
iwl_mvm_tt_tx_protection(mvm, true);
|
||||
else if (temperature <= params->tx_protection_exit)
|
||||
iwl_mvm_tt_tx_protection(mvm, false);
|
||||
}
|
||||
|
||||
if (params->support_tx_backoff) {
|
||||
tx_backoff = 0;
|
||||
for (i = 0; i < TT_TX_BACKOFF_SIZE; i++) {
|
||||
if (temperature < params->tx_backoff[i].temperature)
|
||||
break;
|
||||
tx_backoff = params->tx_backoff[i].backoff;
|
||||
}
|
||||
if (tt->tx_backoff != tx_backoff)
|
||||
iwl_mvm_tt_tx_backoff(mvm, tx_backoff);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct iwl_tt_params iwl7000_tt_params = {
|
||||
.ct_kill_entry = 118,
|
||||
.ct_kill_exit = 96,
|
||||
.ct_kill_duration = 5,
|
||||
.dynamic_smps_entry = 114,
|
||||
.dynamic_smps_exit = 110,
|
||||
.tx_protection_entry = 114,
|
||||
.tx_protection_exit = 108,
|
||||
.tx_backoff = {
|
||||
{.temperature = 112, .backoff = 200},
|
||||
{.temperature = 113, .backoff = 600},
|
||||
{.temperature = 114, .backoff = 1200},
|
||||
{.temperature = 115, .backoff = 2000},
|
||||
{.temperature = 116, .backoff = 4000},
|
||||
{.temperature = 117, .backoff = 10000},
|
||||
},
|
||||
.support_ct_kill = true,
|
||||
.support_dynamic_smps = true,
|
||||
.support_tx_protection = true,
|
||||
.support_tx_backoff = true,
|
||||
};
|
||||
|
||||
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
|
||||
|
||||
IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
|
||||
tt->params = &iwl7000_tt_params;
|
||||
INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
|
||||
}
|
||||
|
||||
void iwl_mvm_tt_exit(struct iwl_mvm *mvm)
|
||||
{
|
||||
cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit);
|
||||
IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n");
|
||||
}
|
|
@ -416,9 +416,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
|
||||
spin_unlock(&mvmsta->lock);
|
||||
|
||||
if (mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
||||
txq_id < IWL_MVM_FIRST_AGG_QUEUE)
|
||||
atomic_inc(&mvmsta->pending_frames);
|
||||
if (txq_id < IWL_MVM_FIRST_AGG_QUEUE)
|
||||
atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -680,16 +679,41 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
|||
/*
|
||||
* If the txq is not an AMPDU queue, there is no chance we freed
|
||||
* several skbs. Check that out...
|
||||
* If there are no pending frames for this STA, notify mac80211 that
|
||||
* this station can go to sleep in its STA table.
|
||||
*/
|
||||
if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta &&
|
||||
!WARN_ON(skb_freed > 1) &&
|
||||
mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
||||
atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) {
|
||||
ieee80211_sta_block_awake(mvm->hw, sta, false);
|
||||
set_bit(sta_id, mvm->sta_drained);
|
||||
schedule_work(&mvm->sta_drained_wk);
|
||||
if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && !WARN_ON(skb_freed > 1) &&
|
||||
atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) {
|
||||
if (mvmsta) {
|
||||
/*
|
||||
* If there are no pending frames for this STA, notify
|
||||
* mac80211 that this station can go to sleep in its
|
||||
* STA table.
|
||||
*/
|
||||
if (mvmsta->vif->type == NL80211_IFTYPE_AP)
|
||||
ieee80211_sta_block_awake(mvm->hw, sta, false);
|
||||
/*
|
||||
* We might very well have taken mvmsta pointer while
|
||||
* the station was being removed. The remove flow might
|
||||
* have seen a pending_frame (because we didn't take
|
||||
* the lock) even if now the queues are drained. So make
|
||||
* really sure now that this the station is not being
|
||||
* removed. If it is, run the drain worker to remove it.
|
||||
*/
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||
if (IS_ERR_OR_NULL(sta)) {
|
||||
/*
|
||||
* Station disappeared in the meantime:
|
||||
* so we are draining.
|
||||
*/
|
||||
set_bit(sta_id, mvm->sta_drained);
|
||||
schedule_work(&mvm->sta_drained_wk);
|
||||
}
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
} else if (!mvmsta) {
|
||||
/* Tx response without STA, so we are draining */
|
||||
set_bit(sta_id, mvm->sta_drained);
|
||||
schedule_work(&mvm->sta_drained_wk);
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -471,3 +471,34 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
|
|||
|
||||
return iwl_mvm_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_mvm_update_smps - Get a requst to change the SMPS mode
|
||||
* @req_type: The part of the driver who call for a change.
|
||||
* @smps_requests: The request to change the SMPS mode.
|
||||
*
|
||||
* Get a requst to change the SMPS mode,
|
||||
* and change it according to all other requests in the driver.
|
||||
*/
|
||||
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
enum iwl_mvm_smps_type_request req_type,
|
||||
enum ieee80211_smps_mode smps_request)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
mvmvif->smps_requests[req_type] = smps_request;
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
|
||||
if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC) {
|
||||
smps_mode = IEEE80211_SMPS_STATIC;
|
||||
break;
|
||||
}
|
||||
if (mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC)
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
}
|
||||
|
||||
ieee80211_request_smps(vif, smps_mode);
|
||||
}
|
||||
|
|
|
@ -256,10 +256,54 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
|||
|
||||
/* 7000 Series */
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)},
|
||||
|
||||
/* 3160 Series */
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
|
||||
|
||||
{0}
|
||||
};
|
||||
|
|
|
@ -405,20 +405,27 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
|
|||
{
|
||||
u8 *v_addr;
|
||||
dma_addr_t p_addr;
|
||||
u32 offset;
|
||||
u32 offset, chunk_sz = section->len;
|
||||
int ret = 0;
|
||||
|
||||
IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n",
|
||||
section_num);
|
||||
|
||||
v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL);
|
||||
if (!v_addr)
|
||||
return -ENOMEM;
|
||||
v_addr = dma_alloc_coherent(trans->dev, chunk_sz, &p_addr,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!v_addr) {
|
||||
IWL_DEBUG_INFO(trans, "Falling back to small chunks of DMA\n");
|
||||
chunk_sz = PAGE_SIZE;
|
||||
v_addr = dma_alloc_coherent(trans->dev, chunk_sz,
|
||||
&p_addr, GFP_KERNEL);
|
||||
if (!v_addr)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < section->len; offset += PAGE_SIZE) {
|
||||
for (offset = 0; offset < section->len; offset += chunk_sz) {
|
||||
u32 copy_size;
|
||||
|
||||
copy_size = min_t(u32, PAGE_SIZE, section->len - offset);
|
||||
copy_size = min_t(u32, chunk_sz, section->len - offset);
|
||||
|
||||
memcpy(v_addr, (u8 *)section->data + offset, copy_size);
|
||||
ret = iwl_pcie_load_firmware_chunk(trans,
|
||||
|
@ -432,7 +439,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
|
|||
}
|
||||
}
|
||||
|
||||
dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr);
|
||||
dma_free_coherent(trans->dev, chunk_sz, v_addr, p_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -573,10 +580,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
|||
|
||||
static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
/* let the ucode operate on its own */
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
iwl_disable_interrupts(trans);
|
||||
iwl_pcie_disable_ict(trans);
|
||||
|
||||
|
@ -636,9 +639,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
return ret;
|
||||
}
|
||||
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
*status = IWL_D3_STATUS_ALIVE;
|
||||
return 0;
|
||||
}
|
||||
|
@ -917,11 +917,11 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
|
|||
}
|
||||
|
||||
static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
const void *buf, int dwords)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs, ret = 0;
|
||||
u32 *vals = buf;
|
||||
const u32 *vals = buf;
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
|
|
|
@ -1045,6 +1045,10 @@ static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans,
|
|||
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
|
||||
}
|
||||
|
||||
/* Receiver address (actually, Rx station's index into station table),
|
||||
* combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
|
||||
#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid))
|
||||
|
||||
void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
|
||||
int sta_id, int tid, int frame_limit, u16 ssn)
|
||||
{
|
||||
|
@ -1518,6 +1522,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
|||
if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
|
||||
IWL_ERR(trans, "FW error in SYNC CMD %s\n",
|
||||
get_cmd_string(trans_pcie, cmd->id));
|
||||
dump_stack();
|
||||
ret = -EIO;
|
||||
goto cancel;
|
||||
}
|
||||
|
@ -1564,7 +1569,8 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
|||
if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
|
||||
return -EIO;
|
||||
|
||||
if (test_bit(STATUS_RFKILL, &trans_pcie->status)) {
|
||||
if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
|
||||
test_bit(STATUS_RFKILL, &trans_pcie->status)) {
|
||||
IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
|
||||
cmd->id);
|
||||
return -ERFKILL;
|
||||
|
|
|
@ -2282,9 +2282,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
if (wdev->netdev->reg_state == NETREG_REGISTERED)
|
||||
unregister_netdevice(wdev->netdev);
|
||||
|
||||
if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
|
||||
free_netdev(wdev->netdev);
|
||||
|
||||
/* Clear the priv in adapter */
|
||||
priv->netdev = NULL;
|
||||
|
||||
|
|
|
@ -1192,6 +1192,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
|
|||
adapter->if_ops.wakeup(adapter);
|
||||
adapter->hs_activated = false;
|
||||
adapter->is_hs_configured = false;
|
||||
adapter->is_suspended = false;
|
||||
mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
|
||||
MWIFIEX_BSS_ROLE_ANY),
|
||||
false);
|
||||
|
|
|
@ -669,6 +669,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
|
|||
struct net_device *dev)
|
||||
{
|
||||
dev->netdev_ops = &mwifiex_netdev_ops;
|
||||
dev->destructor = free_netdev;
|
||||
/* Initialize private structure */
|
||||
priv->current_key_index = 0;
|
||||
priv->media_connected = false;
|
||||
|
|
|
@ -96,7 +96,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
|
|||
} else {
|
||||
/* Multicast */
|
||||
priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
|
||||
if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) {
|
||||
if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: Enabling All Multicast!\n");
|
||||
priv->curr_pkt_filter |=
|
||||
|
@ -108,20 +108,11 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
|
|||
dev_dbg(priv->adapter->dev,
|
||||
"info: Set multicast list=%d\n",
|
||||
mcast_list->num_multicast_addr);
|
||||
/* Set multicast addresses to firmware */
|
||||
if (old_pkt_filter == priv->curr_pkt_filter) {
|
||||
/* Send request to firmware */
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_MAC_MULTICAST_ADR,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
mcast_list);
|
||||
} else {
|
||||
/* Send request to firmware */
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_MAC_MULTICAST_ADR,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
mcast_list);
|
||||
}
|
||||
/* Send multicast addresses to firmware */
|
||||
ret = mwifiex_send_cmd_async(priv,
|
||||
HostCmd_CMD_MAC_MULTICAST_ADR,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
mcast_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue