diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-05-29 14:50:45 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-05-29 14:50:45 -0400 |
commit | 531efffc3e3ff52d732c8fa6f32e084e9c447612 (patch) | |
tree | 79c301b2c8b5400a39c95e034764cf7a208a16a2 /drivers | |
parent | bbf71a8f35cf52e97ba129401f82ccefd249c757 (diff) | |
parent | b571a69745dc90aec3d0505a7ceac2702a93861b (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers')
70 files changed, 2907 insertions, 546 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 9b20d9ee2719..7f702fe3ecc2 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -2369,6 +2369,9 @@ ath5k_tx_complete_poll_work(struct work_struct *work) | |||
2369 | int i; | 2369 | int i; |
2370 | bool needreset = false; | 2370 | bool needreset = false; |
2371 | 2371 | ||
2372 | if (!test_bit(ATH_STAT_STARTED, ah->status)) | ||
2373 | return; | ||
2374 | |||
2372 | mutex_lock(&ah->lock); | 2375 | mutex_lock(&ah->lock); |
2373 | 2376 | ||
2374 | for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { | 2377 | for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { |
@@ -2676,6 +2679,7 @@ done: | |||
2676 | mmiowb(); | 2679 | mmiowb(); |
2677 | mutex_unlock(&ah->lock); | 2680 | mutex_unlock(&ah->lock); |
2678 | 2681 | ||
2682 | set_bit(ATH_STAT_STARTED, ah->status); | ||
2679 | ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work, | 2683 | ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work, |
2680 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); | 2684 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); |
2681 | 2685 | ||
@@ -2737,6 +2741,7 @@ void ath5k_stop(struct ieee80211_hw *hw) | |||
2737 | 2741 | ||
2738 | ath5k_stop_tasklets(ah); | 2742 | ath5k_stop_tasklets(ah); |
2739 | 2743 | ||
2744 | clear_bit(ATH_STAT_STARTED, ah->status); | ||
2740 | cancel_delayed_work_sync(&ah->tx_complete_work); | 2745 | cancel_delayed_work_sync(&ah->tx_complete_work); |
2741 | 2746 | ||
2742 | if (!ath5k_modparam_no_hw_rfkill_switch) | 2747 | if (!ath5k_modparam_no_hw_rfkill_switch) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index 0c2ac0c6dc89..e85a8b076c22 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h | |||
@@ -233,9 +233,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
233 | {0x00009d10, 0x01834061}, | 233 | {0x00009d10, 0x01834061}, |
234 | {0x00009d14, 0x00c00400}, | 234 | {0x00009d14, 0x00c00400}, |
235 | {0x00009d18, 0x00000000}, | 235 | {0x00009d18, 0x00000000}, |
236 | {0x00009e08, 0x0078230c}, | 236 | {0x00009e08, 0x0038230c}, |
237 | {0x00009e24, 0x990bb515}, | 237 | {0x00009e24, 0x9907b515}, |
238 | {0x00009e28, 0x126f0000}, | 238 | {0x00009e28, 0x126f0600}, |
239 | {0x00009e30, 0x06336f77}, | 239 | {0x00009e30, 0x06336f77}, |
240 | {0x00009e34, 0x6af6532f}, | 240 | {0x00009e34, 0x6af6532f}, |
241 | {0x00009e38, 0x0cc80c00}, | 241 | {0x00009e38, 0x0cc80c00}, |
@@ -337,7 +337,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
337 | 337 | ||
338 | static const u32 ar9565_1p0_baseband_postamble[][5] = { | 338 | static const u32 ar9565_1p0_baseband_postamble[][5] = { |
339 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 339 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
340 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800d}, | 340 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8009}, |
341 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, | 341 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, |
342 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, | 342 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, |
343 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81}, | 343 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81}, |
@@ -345,9 +345,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { | |||
345 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, | 345 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, |
346 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 346 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
347 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | 347 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, |
348 | {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, | 348 | {0x00009e04, 0x00802020, 0x00802020, 0x00142020, 0x00142020}, |
349 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, | 349 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, |
350 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, | 350 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, |
351 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, | 351 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, |
352 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 352 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
@@ -450,6 +450,8 @@ static const u32 ar9565_1p0_soc_postamble[][5] = { | |||
450 | 450 | ||
451 | static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | 451 | static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { |
452 | /* Addr allmodes */ | 452 | /* Addr allmodes */ |
453 | {0x00004050, 0x00300300}, | ||
454 | {0x0000406c, 0x00100000}, | ||
453 | {0x0000a000, 0x00010000}, | 455 | {0x0000a000, 0x00010000}, |
454 | {0x0000a004, 0x00030002}, | 456 | {0x0000a004, 0x00030002}, |
455 | {0x0000a008, 0x00050004}, | 457 | {0x0000a008, 0x00050004}, |
@@ -498,27 +500,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | |||
498 | {0x0000a0b4, 0x00000000}, | 500 | {0x0000a0b4, 0x00000000}, |
499 | {0x0000a0b8, 0x00000000}, | 501 | {0x0000a0b8, 0x00000000}, |
500 | {0x0000a0bc, 0x00000000}, | 502 | {0x0000a0bc, 0x00000000}, |
501 | {0x0000a0c0, 0x001f0000}, | 503 | {0x0000a0c0, 0x00bf00a0}, |
502 | {0x0000a0c4, 0x01000101}, | 504 | {0x0000a0c4, 0x11a011a1}, |
503 | {0x0000a0c8, 0x011e011f}, | 505 | {0x0000a0c8, 0x11be11bf}, |
504 | {0x0000a0cc, 0x011c011d}, | 506 | {0x0000a0cc, 0x11bc11bd}, |
505 | {0x0000a0d0, 0x02030204}, | 507 | {0x0000a0d0, 0x22632264}, |
506 | {0x0000a0d4, 0x02010202}, | 508 | {0x0000a0d4, 0x22612262}, |
507 | {0x0000a0d8, 0x021f0200}, | 509 | {0x0000a0d8, 0x227f2260}, |
508 | {0x0000a0dc, 0x0302021e}, | 510 | {0x0000a0dc, 0x4322227e}, |
509 | {0x0000a0e0, 0x03000301}, | 511 | {0x0000a0e0, 0x43204321}, |
510 | {0x0000a0e4, 0x031e031f}, | 512 | {0x0000a0e4, 0x433e433f}, |
511 | {0x0000a0e8, 0x0402031d}, | 513 | {0x0000a0e8, 0x4462433d}, |
512 | {0x0000a0ec, 0x04000401}, | 514 | {0x0000a0ec, 0x44604461}, |
513 | {0x0000a0f0, 0x041e041f}, | 515 | {0x0000a0f0, 0x447e447f}, |
514 | {0x0000a0f4, 0x0502041d}, | 516 | {0x0000a0f4, 0x5582447d}, |
515 | {0x0000a0f8, 0x05000501}, | 517 | {0x0000a0f8, 0x55805581}, |
516 | {0x0000a0fc, 0x051e051f}, | 518 | {0x0000a0fc, 0x559e559f}, |
517 | {0x0000a100, 0x06010602}, | 519 | {0x0000a100, 0x66816682}, |
518 | {0x0000a104, 0x061f0600}, | 520 | {0x0000a104, 0x669f6680}, |
519 | {0x0000a108, 0x061d061e}, | 521 | {0x0000a108, 0x669d669e}, |
520 | {0x0000a10c, 0x07020703}, | 522 | {0x0000a10c, 0x77627763}, |
521 | {0x0000a110, 0x07000701}, | 523 | {0x0000a110, 0x77607761}, |
522 | {0x0000a114, 0x00000000}, | 524 | {0x0000a114, 0x00000000}, |
523 | {0x0000a118, 0x00000000}, | 525 | {0x0000a118, 0x00000000}, |
524 | {0x0000a11c, 0x00000000}, | 526 | {0x0000a11c, 0x00000000}, |
@@ -530,27 +532,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | |||
530 | {0x0000a134, 0x00000000}, | 532 | {0x0000a134, 0x00000000}, |
531 | {0x0000a138, 0x00000000}, | 533 | {0x0000a138, 0x00000000}, |
532 | {0x0000a13c, 0x00000000}, | 534 | {0x0000a13c, 0x00000000}, |
533 | {0x0000a140, 0x001f0000}, | 535 | {0x0000a140, 0x00bf00a0}, |
534 | {0x0000a144, 0x01000101}, | 536 | {0x0000a144, 0x11a011a1}, |
535 | {0x0000a148, 0x011e011f}, | 537 | {0x0000a148, 0x11be11bf}, |
536 | {0x0000a14c, 0x011c011d}, | 538 | {0x0000a14c, 0x11bc11bd}, |
537 | {0x0000a150, 0x02030204}, | 539 | {0x0000a150, 0x22632264}, |
538 | {0x0000a154, 0x02010202}, | 540 | {0x0000a154, 0x22612262}, |
539 | {0x0000a158, 0x021f0200}, | 541 | {0x0000a158, 0x227f2260}, |
540 | {0x0000a15c, 0x0302021e}, | 542 | {0x0000a15c, 0x4322227e}, |
541 | {0x0000a160, 0x03000301}, | 543 | {0x0000a160, 0x43204321}, |
542 | {0x0000a164, 0x031e031f}, | 544 | {0x0000a164, 0x433e433f}, |
543 | {0x0000a168, 0x0402031d}, | 545 | {0x0000a168, 0x4462433d}, |
544 | {0x0000a16c, 0x04000401}, | 546 | {0x0000a16c, 0x44604461}, |
545 | {0x0000a170, 0x041e041f}, | 547 | {0x0000a170, 0x447e447f}, |
546 | {0x0000a174, 0x0502041d}, | 548 | {0x0000a174, 0x5582447d}, |
547 | {0x0000a178, 0x05000501}, | 549 | {0x0000a178, 0x55805581}, |
548 | {0x0000a17c, 0x051e051f}, | 550 | {0x0000a17c, 0x559e559f}, |
549 | {0x0000a180, 0x06010602}, | 551 | {0x0000a180, 0x66816682}, |
550 | {0x0000a184, 0x061f0600}, | 552 | {0x0000a184, 0x669f6680}, |
551 | {0x0000a188, 0x061d061e}, | 553 | {0x0000a188, 0x669d669e}, |
552 | {0x0000a18c, 0x07020703}, | 554 | {0x0000a18c, 0x77e677e7}, |
553 | {0x0000a190, 0x07000701}, | 555 | {0x0000a190, 0x77e477e5}, |
554 | {0x0000a194, 0x00000000}, | 556 | {0x0000a194, 0x00000000}, |
555 | {0x0000a198, 0x00000000}, | 557 | {0x0000a198, 0x00000000}, |
556 | {0x0000a19c, 0x00000000}, | 558 | {0x0000a19c, 0x00000000}, |
@@ -770,7 +772,7 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = { | |||
770 | 772 | ||
771 | static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { | 773 | static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { |
772 | /* Addr allmodes */ | 774 | /* Addr allmodes */ |
773 | {0x00018c00, 0x18213ede}, | 775 | {0x00018c00, 0x18212ede}, |
774 | {0x00018c04, 0x000801d8}, | 776 | {0x00018c04, 0x000801d8}, |
775 | {0x00018c08, 0x0003780c}, | 777 | {0x00018c08, 0x0003780c}, |
776 | }; | 778 | }; |
@@ -889,8 +891,8 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = { | |||
889 | {0x0000a180, 0x66816682}, | 891 | {0x0000a180, 0x66816682}, |
890 | {0x0000a184, 0x669f6680}, | 892 | {0x0000a184, 0x669f6680}, |
891 | {0x0000a188, 0x669d669e}, | 893 | {0x0000a188, 0x669d669e}, |
892 | {0x0000a18c, 0x77627763}, | 894 | {0x0000a18c, 0x77e677e7}, |
893 | {0x0000a190, 0x77607761}, | 895 | {0x0000a190, 0x77e477e5}, |
894 | {0x0000a194, 0x00000000}, | 896 | {0x0000a194, 0x00000000}, |
895 | {0x0000a198, 0x00000000}, | 897 | {0x0000a198, 0x00000000}, |
896 | {0x0000a19c, 0x00000000}, | 898 | {0x0000a19c, 0x00000000}, |
@@ -1114,7 +1116,7 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = { | |||
1114 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, | 1116 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, |
1115 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, | 1117 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, |
1116 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, | 1118 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, |
1117 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 1119 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df}, |
1118 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 1120 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
1119 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 1121 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, |
1120 | {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, | 1122 | {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, |
@@ -1140,13 +1142,13 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = { | |||
1140 | {0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5}, | 1142 | {0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5}, |
1141 | {0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9}, | 1143 | {0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9}, |
1142 | {0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb}, | 1144 | {0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb}, |
1143 | {0x0000a564, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1145 | {0x0000a564, 0x7804ff56, 0x7804ff56, 0x60001cf0, 0x60001cf0}, |
1144 | {0x0000a568, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1146 | {0x0000a568, 0x7804ff56, 0x7804ff56, 0x61001cf1, 0x61001cf1}, |
1145 | {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1147 | {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x62001cf2, 0x62001cf2}, |
1146 | {0x0000a570, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1148 | {0x0000a570, 0x7804ff56, 0x7804ff56, 0x63001cf3, 0x63001cf3}, |
1147 | {0x0000a574, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1149 | {0x0000a574, 0x7804ff56, 0x7804ff56, 0x64001cf4, 0x64001cf4}, |
1148 | {0x0000a578, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1150 | {0x0000a578, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6}, |
1149 | {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1151 | {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6}, |
1150 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1152 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1151 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1153 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1152 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1154 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
@@ -1174,7 +1176,7 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = { | |||
1174 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, | 1176 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, |
1175 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, | 1177 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, |
1176 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, | 1178 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, |
1177 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 1179 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df}, |
1178 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 1180 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
1179 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 1181 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, |
1180 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 1182 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, |
@@ -1200,13 +1202,13 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = { | |||
1200 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 1202 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, |
1201 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 1203 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, |
1202 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 1204 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, |
1203 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1205 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x59001cf0, 0x59001cf0}, |
1204 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1206 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x5a001cf1, 0x5a001cf1}, |
1205 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1207 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x5b001cf2, 0x5b001cf2}, |
1206 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1208 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x5c001cf3, 0x5c001cf3}, |
1207 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1209 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x5d001cf4, 0x5d001cf4}, |
1208 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1210 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6}, |
1209 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1211 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6}, |
1210 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1212 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1211 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1213 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1212 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1214 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e6a30958e944..a1630d1ee3c9 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -226,13 +226,13 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
226 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | 226 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) |
227 | goto work; | 227 | goto work; |
228 | 228 | ||
229 | ath9k_set_beacon(sc); | ||
230 | |||
231 | if (ah->opmode == NL80211_IFTYPE_STATION && | 229 | if (ah->opmode == NL80211_IFTYPE_STATION && |
232 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | 230 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { |
233 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 231 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
234 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | 232 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
235 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 233 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
234 | } else { | ||
235 | ath9k_set_beacon(sc); | ||
236 | } | 236 | } |
237 | work: | 237 | work: |
238 | ath_restart_work(sc); | 238 | ath_restart_work(sc); |
@@ -1331,6 +1331,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
1331 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1331 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1332 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | 1332 | struct ath_node *an = (struct ath_node *) sta->drv_priv; |
1333 | struct ieee80211_key_conf ps_key = { }; | 1333 | struct ieee80211_key_conf ps_key = { }; |
1334 | int key; | ||
1334 | 1335 | ||
1335 | ath_node_attach(sc, sta, vif); | 1336 | ath_node_attach(sc, sta, vif); |
1336 | 1337 | ||
@@ -1338,7 +1339,9 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
1338 | vif->type != NL80211_IFTYPE_AP_VLAN) | 1339 | vif->type != NL80211_IFTYPE_AP_VLAN) |
1339 | return 0; | 1340 | return 0; |
1340 | 1341 | ||
1341 | an->ps_key = ath_key_config(common, vif, sta, &ps_key); | 1342 | key = ath_key_config(common, vif, sta, &ps_key); |
1343 | if (key > 0) | ||
1344 | an->ps_key = key; | ||
1342 | 1345 | ||
1343 | return 0; | 1346 | return 0; |
1344 | } | 1347 | } |
@@ -1355,6 +1358,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc, | |||
1355 | return; | 1358 | return; |
1356 | 1359 | ||
1357 | ath_key_delete(common, &ps_key); | 1360 | ath_key_delete(common, &ps_key); |
1361 | an->ps_key = 0; | ||
1358 | } | 1362 | } |
1359 | 1363 | ||
1360 | static int ath9k_sta_remove(struct ieee80211_hw *hw, | 1364 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 523355b87659..f7c70b3a6ea9 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1728,6 +1728,25 @@ drop_recycle_buffer: | |||
1728 | sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); | 1728 | sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); |
1729 | } | 1729 | } |
1730 | 1730 | ||
1731 | void b43_dma_handle_rx_overflow(struct b43_dmaring *ring) | ||
1732 | { | ||
1733 | int current_slot, previous_slot; | ||
1734 | |||
1735 | B43_WARN_ON(ring->tx); | ||
1736 | |||
1737 | /* Device has filled all buffers, drop all packets and let TCP | ||
1738 | * decrease speed. | ||
1739 | * Decrement RX index by one will let the device to see all slots | ||
1740 | * as free again | ||
1741 | */ | ||
1742 | /* | ||
1743 | *TODO: How to increase rx_drop in mac80211? | ||
1744 | */ | ||
1745 | current_slot = ring->ops->get_current_rxslot(ring); | ||
1746 | previous_slot = prev_slot(ring, current_slot); | ||
1747 | ring->ops->set_current_rxslot(ring, previous_slot); | ||
1748 | } | ||
1749 | |||
1731 | void b43_dma_rx(struct b43_dmaring *ring) | 1750 | void b43_dma_rx(struct b43_dmaring *ring) |
1732 | { | 1751 | { |
1733 | const struct b43_dma_ops *ops = ring->ops; | 1752 | const struct b43_dma_ops *ops = ring->ops; |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 9fdd1983079c..df8c8cdcbdb5 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -9,7 +9,7 @@ | |||
9 | /* DMA-Interrupt reasons. */ | 9 | /* DMA-Interrupt reasons. */ |
10 | #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ | 10 | #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ |
11 | | (1 << 14) | (1 << 15)) | 11 | | (1 << 14) | (1 << 15)) |
12 | #define B43_DMAIRQ_NONFATALMASK (1 << 13) | 12 | #define B43_DMAIRQ_RDESC_UFLOW (1 << 13) |
13 | #define B43_DMAIRQ_RX_DONE (1 << 16) | 13 | #define B43_DMAIRQ_RX_DONE (1 << 16) |
14 | 14 | ||
15 | /*** 32-bit DMA Engine. ***/ | 15 | /*** 32-bit DMA Engine. ***/ |
@@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
295 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 295 | void b43_dma_handle_txstatus(struct b43_wldev *dev, |
296 | const struct b43_txstatus *status); | 296 | const struct b43_txstatus *status); |
297 | 297 | ||
298 | void b43_dma_handle_rx_overflow(struct b43_dmaring *ring); | ||
299 | |||
298 | void b43_dma_rx(struct b43_dmaring *ring); | 300 | void b43_dma_rx(struct b43_dmaring *ring); |
299 | 301 | ||
300 | void b43_dma_direct_fifo_rx(struct b43_wldev *dev, | 302 | void b43_dma_direct_fifo_rx(struct b43_wldev *dev, |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d377f77d30b5..6dd07e2ec595 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1902,30 +1902,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1902 | } | 1902 | } |
1903 | } | 1903 | } |
1904 | 1904 | ||
1905 | if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | | 1905 | if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) { |
1906 | B43_DMAIRQ_NONFATALMASK))) { | 1906 | b43err(dev->wl, |
1907 | if (merged_dma_reason & B43_DMAIRQ_FATALMASK) { | 1907 | "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n", |
1908 | b43err(dev->wl, "Fatal DMA error: " | 1908 | dma_reason[0], dma_reason[1], |
1909 | "0x%08X, 0x%08X, 0x%08X, " | 1909 | dma_reason[2], dma_reason[3], |
1910 | "0x%08X, 0x%08X, 0x%08X\n", | 1910 | dma_reason[4], dma_reason[5]); |
1911 | dma_reason[0], dma_reason[1], | 1911 | b43err(dev->wl, "This device does not support DMA " |
1912 | dma_reason[2], dma_reason[3], | ||
1913 | dma_reason[4], dma_reason[5]); | ||
1914 | b43err(dev->wl, "This device does not support DMA " | ||
1915 | "on your system. It will now be switched to PIO.\n"); | 1912 | "on your system. It will now be switched to PIO.\n"); |
1916 | /* Fall back to PIO transfers if we get fatal DMA errors! */ | 1913 | /* Fall back to PIO transfers if we get fatal DMA errors! */ |
1917 | dev->use_pio = true; | 1914 | dev->use_pio = true; |
1918 | b43_controller_restart(dev, "DMA error"); | 1915 | b43_controller_restart(dev, "DMA error"); |
1919 | return; | 1916 | return; |
1920 | } | ||
1921 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { | ||
1922 | b43err(dev->wl, "DMA error: " | ||
1923 | "0x%08X, 0x%08X, 0x%08X, " | ||
1924 | "0x%08X, 0x%08X, 0x%08X\n", | ||
1925 | dma_reason[0], dma_reason[1], | ||
1926 | dma_reason[2], dma_reason[3], | ||
1927 | dma_reason[4], dma_reason[5]); | ||
1928 | } | ||
1929 | } | 1917 | } |
1930 | 1918 | ||
1931 | if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) | 1919 | if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) |
@@ -1944,6 +1932,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1944 | handle_irq_noise(dev); | 1932 | handle_irq_noise(dev); |
1945 | 1933 | ||
1946 | /* Check the DMA reason registers for received data. */ | 1934 | /* Check the DMA reason registers for received data. */ |
1935 | if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) { | ||
1936 | if (B43_DEBUG) | ||
1937 | b43warn(dev->wl, "RX descriptor underrun\n"); | ||
1938 | b43_dma_handle_rx_overflow(dev->dma.rx_ring); | ||
1939 | } | ||
1947 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { | 1940 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { |
1948 | if (b43_using_pio_transfers(dev)) | 1941 | if (b43_using_pio_transfers(dev)) |
1949 | b43_pio_rx(dev->pio.rx_queue); | 1942 | b43_pio_rx(dev->pio.rx_queue); |
@@ -2001,7 +1994,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev) | |||
2001 | return IRQ_NONE; | 1994 | return IRQ_NONE; |
2002 | 1995 | ||
2003 | dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) | 1996 | dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) |
2004 | & 0x0001DC00; | 1997 | & 0x0001FC00; |
2005 | dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) | 1998 | dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) |
2006 | & 0x0000DC00; | 1999 | & 0x0000DC00; |
2007 | dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) | 2000 | dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) |
@@ -3130,7 +3123,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
3130 | b43_write32(dev, 0x018C, 0x02000000); | 3123 | b43_write32(dev, 0x018C, 0x02000000); |
3131 | } | 3124 | } |
3132 | b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); | 3125 | b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); |
3133 | b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); | 3126 | b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00); |
3134 | b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); | 3127 | b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); |
3135 | b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); | 3128 | b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); |
3136 | b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); | 3129 | b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index b8f82e688c72..9a95045c97b6 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -5741,8 +5741,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) | |||
5741 | hw->flags = | 5741 | hw->flags = |
5742 | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | | 5742 | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | |
5743 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | | 5743 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | |
5744 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | | 5744 | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
5745 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
5746 | if (il->cfg->sku & IL_SKU_N) | 5745 | if (il->cfg->sku & IL_SKU_N) |
5747 | hw->flags |= | 5746 | hw->flags |= |
5748 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 5747 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 48545ab00311..de2c9514bef6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -76,13 +76,16 @@ | |||
76 | #define IWL_INVALID_STATION 255 | 76 | #define IWL_INVALID_STATION 255 |
77 | 77 | ||
78 | /* device operations */ | 78 | /* device operations */ |
79 | extern struct iwl_lib_ops iwl1000_lib; | 79 | extern const struct iwl_dvm_cfg iwl_dvm_1000_cfg; |
80 | extern struct iwl_lib_ops iwl2000_lib; | 80 | extern const struct iwl_dvm_cfg iwl_dvm_2000_cfg; |
81 | extern struct iwl_lib_ops iwl2030_lib; | 81 | extern const struct iwl_dvm_cfg iwl_dvm_105_cfg; |
82 | extern struct iwl_lib_ops iwl5000_lib; | 82 | extern const struct iwl_dvm_cfg iwl_dvm_2030_cfg; |
83 | extern struct iwl_lib_ops iwl5150_lib; | 83 | extern const struct iwl_dvm_cfg iwl_dvm_5000_cfg; |
84 | extern struct iwl_lib_ops iwl6000_lib; | 84 | extern const struct iwl_dvm_cfg iwl_dvm_5150_cfg; |
85 | extern struct iwl_lib_ops iwl6030_lib; | 85 | extern const struct iwl_dvm_cfg iwl_dvm_6000_cfg; |
86 | extern const struct iwl_dvm_cfg iwl_dvm_6005_cfg; | ||
87 | extern const struct iwl_dvm_cfg iwl_dvm_6050_cfg; | ||
88 | extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg; | ||
86 | 89 | ||
87 | 90 | ||
88 | #define TIME_UNIT 1024 | 91 | #define TIME_UNIT 1024 |
@@ -291,8 +294,8 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena); | |||
291 | 294 | ||
292 | static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) | 295 | static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) |
293 | { | 296 | { |
294 | return priv->cfg->bt_params && | 297 | return priv->lib->bt_params && |
295 | priv->cfg->bt_params->advanced_bt_coexist; | 298 | priv->lib->bt_params->advanced_bt_coexist; |
296 | } | 299 | } |
297 | 300 | ||
298 | #ifdef CONFIG_IWLWIFI_DEBUG | 301 | #ifdef CONFIG_IWLWIFI_DEBUG |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index d6c4cf2ad7c5..1b0f0d502568 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
@@ -521,7 +521,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) | |||
521 | 521 | ||
522 | iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]); | 522 | iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]); |
523 | 523 | ||
524 | if (priv->cfg->base_params->hd_v2) { | 524 | if (priv->lib->hd_v2) { |
525 | cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] = | 525 | cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] = |
526 | HD_INA_NON_SQUARE_DET_OFDM_DATA_V2; | 526 | HD_INA_NON_SQUARE_DET_OFDM_DATA_V2; |
527 | cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] = | 527 | cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] = |
@@ -895,7 +895,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, | |||
895 | continue; | 895 | continue; |
896 | } | 896 | } |
897 | 897 | ||
898 | delta_g = (priv->cfg->base_params->chain_noise_scale * | 898 | delta_g = (priv->lib->chain_noise_scale * |
899 | ((s32)average_noise[default_chain] - | 899 | ((s32)average_noise[default_chain] - |
900 | (s32)average_noise[i])) / 1500; | 900 | (s32)average_noise[i])) / 1500; |
901 | 901 | ||
@@ -1051,8 +1051,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1051 | return; | 1051 | return; |
1052 | 1052 | ||
1053 | /* Analyze signal for disconnected antenna */ | 1053 | /* Analyze signal for disconnected antenna */ |
1054 | if (priv->cfg->bt_params && | 1054 | if (priv->lib->bt_params && |
1055 | priv->cfg->bt_params->advanced_bt_coexist) { | 1055 | priv->lib->bt_params->advanced_bt_coexist) { |
1056 | /* Disable disconnected antenna algorithm for advanced | 1056 | /* Disable disconnected antenna algorithm for advanced |
1057 | bt coex, assuming valid antennas are connected */ | 1057 | bt coex, assuming valid antennas are connected */ |
1058 | data->active_chains = priv->nvm_data->valid_rx_ant; | 1058 | data->active_chains = priv->nvm_data->valid_rx_ant; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 95ca026ecc9d..19f3ce7646ab 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -838,10 +838,6 @@ struct iwl_qosparam_cmd { | |||
838 | #define STA_MODIFY_DELBA_TID_MSK 0x10 | 838 | #define STA_MODIFY_DELBA_TID_MSK 0x10 |
839 | #define STA_MODIFY_SLEEP_TX_COUNT_MSK 0x20 | 839 | #define STA_MODIFY_SLEEP_TX_COUNT_MSK 0x20 |
840 | 840 | ||
841 | /* Receiver address (actually, Rx station's index into station table), | ||
842 | * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ | ||
843 | #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) | ||
844 | |||
845 | /* agn */ | 841 | /* agn */ |
846 | struct iwl_keyinfo { | 842 | struct iwl_keyinfo { |
847 | __le16 key_flags; | 843 | __le16 key_flags; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 71ea77576d22..f1b8df16dbba 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
@@ -568,16 +568,61 @@ struct iwl_hw_params { | |||
568 | const struct iwl_sensitivity_ranges *sens; | 568 | const struct iwl_sensitivity_ranges *sens; |
569 | }; | 569 | }; |
570 | 570 | ||
571 | struct iwl_lib_ops { | 571 | /** |
572 | /* set hw dependent parameters */ | 572 | * struct iwl_dvm_bt_params - DVM specific BT (coex) parameters |
573 | * @advanced_bt_coexist: support advanced bt coexist | ||
574 | * @bt_init_traffic_load: specify initial bt traffic load | ||
575 | * @bt_prio_boost: default bt priority boost value | ||
576 | * @agg_time_limit: maximum number of uSec in aggregation | ||
577 | * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode | ||
578 | */ | ||
579 | struct iwl_dvm_bt_params { | ||
580 | bool advanced_bt_coexist; | ||
581 | u8 bt_init_traffic_load; | ||
582 | u32 bt_prio_boost; | ||
583 | u16 agg_time_limit; | ||
584 | bool bt_sco_disable; | ||
585 | bool bt_session_2; | ||
586 | }; | ||
587 | |||
588 | /** | ||
589 | * struct iwl_dvm_cfg - DVM firmware specific device configuration | ||
590 | * @set_hw_params: set hardware parameters | ||
591 | * @set_channel_switch: send channel switch command | ||
592 | * @nic_config: apply device specific configuration | ||
593 | * @temperature: read temperature | ||
594 | * @adv_thermal_throttle: support advance thermal throttle | ||
595 | * @support_ct_kill_exit: support ct kill exit condition | ||
596 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | ||
597 | * radio tuning when there is a high receiving plcp error rate | ||
598 | * @chain_noise_scale: default chain noise scale used for gain computation | ||
599 | * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up | ||
600 | * @no_idle_support: do not support idle mode | ||
601 | * @bt_params: pointer to BT parameters | ||
602 | * @need_temp_offset_calib: need to perform temperature offset calibration | ||
603 | * @no_xtal_calib: some devices do not need crystal calibration data, | ||
604 | * don't send it to those | ||
605 | * @temp_offset_v2: support v2 of temperature offset calibration | ||
606 | * @adv_pm: advanced power management | ||
607 | */ | ||
608 | struct iwl_dvm_cfg { | ||
573 | void (*set_hw_params)(struct iwl_priv *priv); | 609 | void (*set_hw_params)(struct iwl_priv *priv); |
574 | int (*set_channel_switch)(struct iwl_priv *priv, | 610 | int (*set_channel_switch)(struct iwl_priv *priv, |
575 | struct ieee80211_channel_switch *ch_switch); | 611 | struct ieee80211_channel_switch *ch_switch); |
576 | /* device specific configuration */ | ||
577 | void (*nic_config)(struct iwl_priv *priv); | 612 | void (*nic_config)(struct iwl_priv *priv); |
578 | |||
579 | /* temperature */ | ||
580 | void (*temperature)(struct iwl_priv *priv); | 613 | void (*temperature)(struct iwl_priv *priv); |
614 | |||
615 | const struct iwl_dvm_bt_params *bt_params; | ||
616 | s32 chain_noise_scale; | ||
617 | u8 plcp_delta_threshold; | ||
618 | bool adv_thermal_throttle; | ||
619 | bool support_ct_kill_exit; | ||
620 | bool hd_v2; | ||
621 | bool no_idle_support; | ||
622 | bool need_temp_offset_calib; | ||
623 | bool no_xtal_calib; | ||
624 | bool temp_offset_v2; | ||
625 | bool adv_pm; | ||
581 | }; | 626 | }; |
582 | 627 | ||
583 | struct iwl_wipan_noa_data { | 628 | struct iwl_wipan_noa_data { |
@@ -610,7 +655,7 @@ struct iwl_priv { | |||
610 | struct device *dev; /* for debug prints only */ | 655 | struct device *dev; /* for debug prints only */ |
611 | const struct iwl_cfg *cfg; | 656 | const struct iwl_cfg *cfg; |
612 | const struct iwl_fw *fw; | 657 | const struct iwl_fw *fw; |
613 | const struct iwl_lib_ops *lib; | 658 | const struct iwl_dvm_cfg *lib; |
614 | unsigned long status; | 659 | unsigned long status; |
615 | 660 | ||
616 | spinlock_t sta_lock; | 661 | spinlock_t sta_lock; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index c48907c8ab43..352c6cb7b4f1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
@@ -174,10 +174,13 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
174 | priv->hw_params.sens = &iwl1000_sensitivity; | 174 | priv->hw_params.sens = &iwl1000_sensitivity; |
175 | } | 175 | } |
176 | 176 | ||
177 | struct iwl_lib_ops iwl1000_lib = { | 177 | const struct iwl_dvm_cfg iwl_dvm_1000_cfg = { |
178 | .set_hw_params = iwl1000_hw_set_hw_params, | 178 | .set_hw_params = iwl1000_hw_set_hw_params, |
179 | .nic_config = iwl1000_nic_config, | 179 | .nic_config = iwl1000_nic_config, |
180 | .temperature = iwlagn_temperature, | 180 | .temperature = iwlagn_temperature, |
181 | .support_ct_kill_exit = true, | ||
182 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||
183 | .chain_noise_scale = 1000, | ||
181 | }; | 184 | }; |
182 | 185 | ||
183 | 186 | ||
@@ -232,16 +235,56 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
232 | priv->hw_params.sens = &iwl2000_sensitivity; | 235 | priv->hw_params.sens = &iwl2000_sensitivity; |
233 | } | 236 | } |
234 | 237 | ||
235 | struct iwl_lib_ops iwl2000_lib = { | 238 | const struct iwl_dvm_cfg iwl_dvm_2000_cfg = { |
236 | .set_hw_params = iwl2000_hw_set_hw_params, | 239 | .set_hw_params = iwl2000_hw_set_hw_params, |
237 | .nic_config = iwl2000_nic_config, | 240 | .nic_config = iwl2000_nic_config, |
238 | .temperature = iwlagn_temperature, | 241 | .temperature = iwlagn_temperature, |
242 | .adv_thermal_throttle = true, | ||
243 | .support_ct_kill_exit = true, | ||
244 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
245 | .chain_noise_scale = 1000, | ||
246 | .hd_v2 = true, | ||
247 | .need_temp_offset_calib = true, | ||
248 | .temp_offset_v2 = true, | ||
239 | }; | 249 | }; |
240 | 250 | ||
241 | struct iwl_lib_ops iwl2030_lib = { | 251 | const struct iwl_dvm_cfg iwl_dvm_105_cfg = { |
242 | .set_hw_params = iwl2000_hw_set_hw_params, | 252 | .set_hw_params = iwl2000_hw_set_hw_params, |
243 | .nic_config = iwl2000_nic_config, | 253 | .nic_config = iwl2000_nic_config, |
244 | .temperature = iwlagn_temperature, | 254 | .temperature = iwlagn_temperature, |
255 | .adv_thermal_throttle = true, | ||
256 | .support_ct_kill_exit = true, | ||
257 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
258 | .chain_noise_scale = 1000, | ||
259 | .hd_v2 = true, | ||
260 | .need_temp_offset_calib = true, | ||
261 | .temp_offset_v2 = true, | ||
262 | .adv_pm = true, | ||
263 | }; | ||
264 | |||
265 | static const struct iwl_dvm_bt_params iwl2030_bt_params = { | ||
266 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
267 | .advanced_bt_coexist = true, | ||
268 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | ||
269 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
270 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32, | ||
271 | .bt_sco_disable = true, | ||
272 | .bt_session_2 = true, | ||
273 | }; | ||
274 | |||
275 | const struct iwl_dvm_cfg iwl_dvm_2030_cfg = { | ||
276 | .set_hw_params = iwl2000_hw_set_hw_params, | ||
277 | .nic_config = iwl2000_nic_config, | ||
278 | .temperature = iwlagn_temperature, | ||
279 | .adv_thermal_throttle = true, | ||
280 | .support_ct_kill_exit = true, | ||
281 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
282 | .chain_noise_scale = 1000, | ||
283 | .hd_v2 = true, | ||
284 | .bt_params = &iwl2030_bt_params, | ||
285 | .need_temp_offset_calib = true, | ||
286 | .temp_offset_v2 = true, | ||
287 | .adv_pm = true, | ||
245 | }; | 288 | }; |
246 | 289 | ||
247 | /* | 290 | /* |
@@ -420,16 +463,23 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
420 | return iwl_dvm_send_cmd(priv, &hcmd); | 463 | return iwl_dvm_send_cmd(priv, &hcmd); |
421 | } | 464 | } |
422 | 465 | ||
423 | struct iwl_lib_ops iwl5000_lib = { | 466 | const struct iwl_dvm_cfg iwl_dvm_5000_cfg = { |
424 | .set_hw_params = iwl5000_hw_set_hw_params, | 467 | .set_hw_params = iwl5000_hw_set_hw_params, |
425 | .set_channel_switch = iwl5000_hw_channel_switch, | 468 | .set_channel_switch = iwl5000_hw_channel_switch, |
426 | .temperature = iwlagn_temperature, | 469 | .temperature = iwlagn_temperature, |
470 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
471 | .chain_noise_scale = 1000, | ||
472 | .no_idle_support = true, | ||
427 | }; | 473 | }; |
428 | 474 | ||
429 | struct iwl_lib_ops iwl5150_lib = { | 475 | const struct iwl_dvm_cfg iwl_dvm_5150_cfg = { |
430 | .set_hw_params = iwl5150_hw_set_hw_params, | 476 | .set_hw_params = iwl5150_hw_set_hw_params, |
431 | .set_channel_switch = iwl5000_hw_channel_switch, | 477 | .set_channel_switch = iwl5000_hw_channel_switch, |
432 | .temperature = iwl5150_temperature, | 478 | .temperature = iwl5150_temperature, |
479 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
480 | .chain_noise_scale = 1000, | ||
481 | .no_idle_support = true, | ||
482 | .no_xtal_calib = true, | ||
433 | }; | 483 | }; |
434 | 484 | ||
435 | 485 | ||
@@ -584,16 +634,59 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
584 | return err; | 634 | return err; |
585 | } | 635 | } |
586 | 636 | ||
587 | struct iwl_lib_ops iwl6000_lib = { | 637 | const struct iwl_dvm_cfg iwl_dvm_6000_cfg = { |
588 | .set_hw_params = iwl6000_hw_set_hw_params, | 638 | .set_hw_params = iwl6000_hw_set_hw_params, |
589 | .set_channel_switch = iwl6000_hw_channel_switch, | 639 | .set_channel_switch = iwl6000_hw_channel_switch, |
590 | .nic_config = iwl6000_nic_config, | 640 | .nic_config = iwl6000_nic_config, |
591 | .temperature = iwlagn_temperature, | 641 | .temperature = iwlagn_temperature, |
642 | .adv_thermal_throttle = true, | ||
643 | .support_ct_kill_exit = true, | ||
644 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
645 | .chain_noise_scale = 1000, | ||
646 | }; | ||
647 | |||
648 | const struct iwl_dvm_cfg iwl_dvm_6005_cfg = { | ||
649 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
650 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
651 | .nic_config = iwl6000_nic_config, | ||
652 | .temperature = iwlagn_temperature, | ||
653 | .adv_thermal_throttle = true, | ||
654 | .support_ct_kill_exit = true, | ||
655 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
656 | .chain_noise_scale = 1000, | ||
657 | .need_temp_offset_calib = true, | ||
658 | }; | ||
659 | |||
660 | const struct iwl_dvm_cfg iwl_dvm_6050_cfg = { | ||
661 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
662 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
663 | .nic_config = iwl6000_nic_config, | ||
664 | .temperature = iwlagn_temperature, | ||
665 | .adv_thermal_throttle = true, | ||
666 | .support_ct_kill_exit = true, | ||
667 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
668 | .chain_noise_scale = 1500, | ||
669 | }; | ||
670 | |||
671 | static const struct iwl_dvm_bt_params iwl6000_bt_params = { | ||
672 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
673 | .advanced_bt_coexist = true, | ||
674 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | ||
675 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
676 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
677 | .bt_sco_disable = true, | ||
592 | }; | 678 | }; |
593 | 679 | ||
594 | struct iwl_lib_ops iwl6030_lib = { | 680 | const struct iwl_dvm_cfg iwl_dvm_6030_cfg = { |
595 | .set_hw_params = iwl6000_hw_set_hw_params, | 681 | .set_hw_params = iwl6000_hw_set_hw_params, |
596 | .set_channel_switch = iwl6000_hw_channel_switch, | 682 | .set_channel_switch = iwl6000_hw_channel_switch, |
597 | .nic_config = iwl6000_nic_config, | 683 | .nic_config = iwl6000_nic_config, |
598 | .temperature = iwlagn_temperature, | 684 | .temperature = iwlagn_temperature, |
685 | .adv_thermal_throttle = true, | ||
686 | .support_ct_kill_exit = true, | ||
687 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
688 | .chain_noise_scale = 1000, | ||
689 | .bt_params = &iwl6000_bt_params, | ||
690 | .need_temp_offset_calib = true, | ||
691 | .adv_pm = true, | ||
599 | }; | 692 | }; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 54f553380aa8..9879550a0fea 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -254,23 +254,23 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
254 | BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != | 254 | BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != |
255 | sizeof(basic.bt3_lookup_table)); | 255 | sizeof(basic.bt3_lookup_table)); |
256 | 256 | ||
257 | if (priv->cfg->bt_params) { | 257 | if (priv->lib->bt_params) { |
258 | /* | 258 | /* |
259 | * newer generation of devices (2000 series and newer) | 259 | * newer generation of devices (2000 series and newer) |
260 | * use the version 2 of the bt command | 260 | * use the version 2 of the bt command |
261 | * we need to make sure sending the host command | 261 | * we need to make sure sending the host command |
262 | * with correct data structure to avoid uCode assert | 262 | * with correct data structure to avoid uCode assert |
263 | */ | 263 | */ |
264 | if (priv->cfg->bt_params->bt_session_2) { | 264 | if (priv->lib->bt_params->bt_session_2) { |
265 | bt_cmd_v2.prio_boost = cpu_to_le32( | 265 | bt_cmd_v2.prio_boost = cpu_to_le32( |
266 | priv->cfg->bt_params->bt_prio_boost); | 266 | priv->lib->bt_params->bt_prio_boost); |
267 | bt_cmd_v2.tx_prio_boost = 0; | 267 | bt_cmd_v2.tx_prio_boost = 0; |
268 | bt_cmd_v2.rx_prio_boost = 0; | 268 | bt_cmd_v2.rx_prio_boost = 0; |
269 | } else { | 269 | } else { |
270 | /* older version only has 8 bits */ | 270 | /* older version only has 8 bits */ |
271 | WARN_ON(priv->cfg->bt_params->bt_prio_boost & ~0xFF); | 271 | WARN_ON(priv->lib->bt_params->bt_prio_boost & ~0xFF); |
272 | bt_cmd_v1.prio_boost = | 272 | bt_cmd_v1.prio_boost = |
273 | priv->cfg->bt_params->bt_prio_boost; | 273 | priv->lib->bt_params->bt_prio_boost; |
274 | bt_cmd_v1.tx_prio_boost = 0; | 274 | bt_cmd_v1.tx_prio_boost = 0; |
275 | bt_cmd_v1.rx_prio_boost = 0; | 275 | bt_cmd_v1.rx_prio_boost = 0; |
276 | } | 276 | } |
@@ -330,7 +330,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
330 | priv->bt_full_concurrent ? | 330 | priv->bt_full_concurrent ? |
331 | "full concurrency" : "3-wire"); | 331 | "full concurrency" : "3-wire"); |
332 | 332 | ||
333 | if (priv->cfg->bt_params->bt_session_2) { | 333 | if (priv->lib->bt_params->bt_session_2) { |
334 | memcpy(&bt_cmd_v2.basic, &basic, | 334 | memcpy(&bt_cmd_v2.basic, &basic, |
335 | sizeof(basic)); | 335 | sizeof(basic)); |
336 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 336 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
@@ -758,8 +758,8 @@ static bool is_single_rx_stream(struct iwl_priv *priv) | |||
758 | */ | 758 | */ |
759 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | 759 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) |
760 | { | 760 | { |
761 | if (priv->cfg->bt_params && | 761 | if (priv->lib->bt_params && |
762 | priv->cfg->bt_params->advanced_bt_coexist && | 762 | priv->lib->bt_params->advanced_bt_coexist && |
763 | (priv->bt_full_concurrent || | 763 | (priv->bt_full_concurrent || |
764 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | 764 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { |
765 | /* | 765 | /* |
@@ -830,8 +830,8 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
830 | else | 830 | else |
831 | active_chains = priv->nvm_data->valid_rx_ant; | 831 | active_chains = priv->nvm_data->valid_rx_ant; |
832 | 832 | ||
833 | if (priv->cfg->bt_params && | 833 | if (priv->lib->bt_params && |
834 | priv->cfg->bt_params->advanced_bt_coexist && | 834 | priv->lib->bt_params->advanced_bt_coexist && |
835 | (priv->bt_full_concurrent || | 835 | (priv->bt_full_concurrent || |
836 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | 836 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { |
837 | /* | 837 | /* |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cab23af0be9e..ac7ed3f809a0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -426,6 +426,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | |||
426 | if (ret) | 426 | if (ret) |
427 | goto error; | 427 | goto error; |
428 | 428 | ||
429 | /* let the ucode operate on its own */ | ||
430 | iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, | ||
431 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
432 | |||
429 | iwl_trans_d3_suspend(priv->trans); | 433 | iwl_trans_d3_suspend(priv->trans); |
430 | 434 | ||
431 | goto out; | 435 | goto out; |
@@ -509,6 +513,10 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
509 | goto out_unlock; | 513 | goto out_unlock; |
510 | } | 514 | } |
511 | 515 | ||
516 | /* uCode is no longer operating by itself */ | ||
517 | iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, | ||
518 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
519 | |||
512 | base = priv->device_pointers.error_event_table; | 520 | base = priv->device_pointers.error_event_table; |
513 | if (!iwlagn_hw_valid_rtc_data_addr(base)) { | 521 | if (!iwlagn_hw_valid_rtc_data_addr(base)) { |
514 | IWL_WARN(priv, "Invalid error table during resume!\n"); | 522 | IWL_WARN(priv, "Invalid error table during resume!\n"); |
@@ -1276,8 +1284,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | |||
1276 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1284 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
1277 | mutex_lock(&priv->mutex); | 1285 | mutex_lock(&priv->mutex); |
1278 | 1286 | ||
1279 | if (priv->cfg->bt_params && | 1287 | if (priv->lib->bt_params && |
1280 | priv->cfg->bt_params->advanced_bt_coexist) { | 1288 | priv->lib->bt_params->advanced_bt_coexist) { |
1281 | if (rssi_event == RSSI_EVENT_LOW) | 1289 | if (rssi_event == RSSI_EVENT_LOW) |
1282 | priv->bt_enable_pspoll = true; | 1290 | priv->bt_enable_pspoll = true; |
1283 | else if (rssi_event == RSSI_EVENT_HIGH) | 1291 | else if (rssi_event == RSSI_EVENT_HIGH) |
@@ -1387,7 +1395,7 @@ static int iwl_setup_interface(struct iwl_priv *priv, | |||
1387 | return err; | 1395 | return err; |
1388 | } | 1396 | } |
1389 | 1397 | ||
1390 | if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && | 1398 | if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist && |
1391 | vif->type == NL80211_IFTYPE_ADHOC) { | 1399 | vif->type == NL80211_IFTYPE_ADHOC) { |
1392 | /* | 1400 | /* |
1393 | * pretend to have high BT traffic as long as we | 1401 | * pretend to have high BT traffic as long as we |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 74d7572e7091..68f754659570 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -615,7 +615,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
615 | 615 | ||
616 | priv->thermal_throttle.ct_kill_toggle = false; | 616 | priv->thermal_throttle.ct_kill_toggle = false; |
617 | 617 | ||
618 | if (priv->cfg->base_params->support_ct_kill_exit) { | 618 | if (priv->lib->support_ct_kill_exit) { |
619 | adv_cmd.critical_temperature_enter = | 619 | adv_cmd.critical_temperature_enter = |
620 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | 620 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
621 | adv_cmd.critical_temperature_exit = | 621 | adv_cmd.critical_temperature_exit = |
@@ -732,10 +732,10 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
732 | } | 732 | } |
733 | 733 | ||
734 | /* download priority table before any calibration request */ | 734 | /* download priority table before any calibration request */ |
735 | if (priv->cfg->bt_params && | 735 | if (priv->lib->bt_params && |
736 | priv->cfg->bt_params->advanced_bt_coexist) { | 736 | priv->lib->bt_params->advanced_bt_coexist) { |
737 | /* Configure Bluetooth device coexistence support */ | 737 | /* Configure Bluetooth device coexistence support */ |
738 | if (priv->cfg->bt_params->bt_sco_disable) | 738 | if (priv->lib->bt_params->bt_sco_disable) |
739 | priv->bt_enable_pspoll = false; | 739 | priv->bt_enable_pspoll = false; |
740 | else | 740 | else |
741 | priv->bt_enable_pspoll = true; | 741 | priv->bt_enable_pspoll = true; |
@@ -873,9 +873,9 @@ void iwl_down(struct iwl_priv *priv) | |||
873 | priv->bt_status = 0; | 873 | priv->bt_status = 0; |
874 | priv->cur_rssi_ctx = NULL; | 874 | priv->cur_rssi_ctx = NULL; |
875 | priv->bt_is_sco = 0; | 875 | priv->bt_is_sco = 0; |
876 | if (priv->cfg->bt_params) | 876 | if (priv->lib->bt_params) |
877 | priv->bt_traffic_load = | 877 | priv->bt_traffic_load = |
878 | priv->cfg->bt_params->bt_init_traffic_load; | 878 | priv->lib->bt_params->bt_init_traffic_load; |
879 | else | 879 | else |
880 | priv->bt_traffic_load = 0; | 880 | priv->bt_traffic_load = 0; |
881 | priv->bt_full_concurrent = false; | 881 | priv->bt_full_concurrent = false; |
@@ -1058,7 +1058,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
1058 | 1058 | ||
1059 | iwl_setup_scan_deferred_work(priv); | 1059 | iwl_setup_scan_deferred_work(priv); |
1060 | 1060 | ||
1061 | if (priv->cfg->bt_params) | 1061 | if (priv->lib->bt_params) |
1062 | iwlagn_bt_setup_deferred_work(priv); | 1062 | iwlagn_bt_setup_deferred_work(priv); |
1063 | 1063 | ||
1064 | init_timer(&priv->statistics_periodic); | 1064 | init_timer(&priv->statistics_periodic); |
@@ -1072,7 +1072,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
1072 | 1072 | ||
1073 | void iwl_cancel_deferred_work(struct iwl_priv *priv) | 1073 | void iwl_cancel_deferred_work(struct iwl_priv *priv) |
1074 | { | 1074 | { |
1075 | if (priv->cfg->bt_params) | 1075 | if (priv->lib->bt_params) |
1076 | iwlagn_bt_cancel_deferred_work(priv); | 1076 | iwlagn_bt_cancel_deferred_work(priv); |
1077 | 1077 | ||
1078 | cancel_work_sync(&priv->run_time_calib_work); | 1078 | cancel_work_sync(&priv->run_time_calib_work); |
@@ -1098,8 +1098,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
1098 | 1098 | ||
1099 | priv->band = IEEE80211_BAND_2GHZ; | 1099 | priv->band = IEEE80211_BAND_2GHZ; |
1100 | 1100 | ||
1101 | priv->plcp_delta_threshold = | 1101 | priv->plcp_delta_threshold = priv->lib->plcp_delta_threshold; |
1102 | priv->cfg->base_params->plcp_delta_threshold; | ||
1103 | 1102 | ||
1104 | priv->iw_mode = NL80211_IFTYPE_STATION; | 1103 | priv->iw_mode = NL80211_IFTYPE_STATION; |
1105 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | 1104 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; |
@@ -1116,8 +1115,8 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
1116 | iwl_init_scan_params(priv); | 1115 | iwl_init_scan_params(priv); |
1117 | 1116 | ||
1118 | /* init bt coex */ | 1117 | /* init bt coex */ |
1119 | if (priv->cfg->bt_params && | 1118 | if (priv->lib->bt_params && |
1120 | priv->cfg->bt_params->advanced_bt_coexist) { | 1119 | priv->lib->bt_params->advanced_bt_coexist) { |
1121 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | 1120 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; |
1122 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | 1121 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; |
1123 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | 1122 | 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, | |||
1264 | switch (priv->cfg->device_family) { | 1263 | switch (priv->cfg->device_family) { |
1265 | case IWL_DEVICE_FAMILY_1000: | 1264 | case IWL_DEVICE_FAMILY_1000: |
1266 | case IWL_DEVICE_FAMILY_100: | 1265 | case IWL_DEVICE_FAMILY_100: |
1267 | priv->lib = &iwl1000_lib; | 1266 | priv->lib = &iwl_dvm_1000_cfg; |
1268 | break; | 1267 | break; |
1269 | case IWL_DEVICE_FAMILY_2000: | 1268 | case IWL_DEVICE_FAMILY_2000: |
1269 | priv->lib = &iwl_dvm_2000_cfg; | ||
1270 | break; | ||
1270 | case IWL_DEVICE_FAMILY_105: | 1271 | case IWL_DEVICE_FAMILY_105: |
1271 | priv->lib = &iwl2000_lib; | 1272 | priv->lib = &iwl_dvm_105_cfg; |
1272 | break; | 1273 | break; |
1273 | case IWL_DEVICE_FAMILY_2030: | 1274 | case IWL_DEVICE_FAMILY_2030: |
1274 | case IWL_DEVICE_FAMILY_135: | 1275 | case IWL_DEVICE_FAMILY_135: |
1275 | priv->lib = &iwl2030_lib; | 1276 | priv->lib = &iwl_dvm_2030_cfg; |
1276 | break; | 1277 | break; |
1277 | case IWL_DEVICE_FAMILY_5000: | 1278 | case IWL_DEVICE_FAMILY_5000: |
1278 | priv->lib = &iwl5000_lib; | 1279 | priv->lib = &iwl_dvm_5000_cfg; |
1279 | break; | 1280 | break; |
1280 | case IWL_DEVICE_FAMILY_5150: | 1281 | case IWL_DEVICE_FAMILY_5150: |
1281 | priv->lib = &iwl5150_lib; | 1282 | priv->lib = &iwl_dvm_5150_cfg; |
1282 | break; | 1283 | break; |
1283 | case IWL_DEVICE_FAMILY_6000: | 1284 | case IWL_DEVICE_FAMILY_6000: |
1284 | case IWL_DEVICE_FAMILY_6005: | ||
1285 | case IWL_DEVICE_FAMILY_6000i: | 1285 | case IWL_DEVICE_FAMILY_6000i: |
1286 | priv->lib = &iwl_dvm_6000_cfg; | ||
1287 | break; | ||
1288 | case IWL_DEVICE_FAMILY_6005: | ||
1289 | priv->lib = &iwl_dvm_6005_cfg; | ||
1290 | break; | ||
1286 | case IWL_DEVICE_FAMILY_6050: | 1291 | case IWL_DEVICE_FAMILY_6050: |
1287 | case IWL_DEVICE_FAMILY_6150: | 1292 | case IWL_DEVICE_FAMILY_6150: |
1288 | priv->lib = &iwl6000_lib; | 1293 | priv->lib = &iwl_dvm_6050_cfg; |
1289 | break; | 1294 | break; |
1290 | case IWL_DEVICE_FAMILY_6030: | 1295 | case IWL_DEVICE_FAMILY_6030: |
1291 | priv->lib = &iwl6030_lib; | 1296 | priv->lib = &iwl_dvm_6030_cfg; |
1292 | break; | 1297 | break; |
1293 | default: | 1298 | default: |
1294 | break; | 1299 | break; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index bd69018d07a9..77cb59712235 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
@@ -163,7 +163,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
163 | u8 skip; | 163 | u8 skip; |
164 | u32 slp_itrvl; | 164 | u32 slp_itrvl; |
165 | 165 | ||
166 | if (priv->cfg->adv_pm) { | 166 | if (priv->lib->adv_pm) { |
167 | table = apm_range_2; | 167 | table = apm_range_2; |
168 | if (period <= IWL_DTIM_RANGE_1_MAX) | 168 | if (period <= IWL_DTIM_RANGE_1_MAX) |
169 | table = apm_range_1; | 169 | table = apm_range_1; |
@@ -217,7 +217,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
217 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; | 217 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; |
218 | 218 | ||
219 | if (iwl_advanced_bt_coexist(priv)) { | 219 | if (iwl_advanced_bt_coexist(priv)) { |
220 | if (!priv->cfg->bt_params->bt_sco_disable) | 220 | if (!priv->lib->bt_params->bt_sco_disable) |
221 | cmd->flags |= IWL_POWER_BT_SCO_ENA; | 221 | cmd->flags |= IWL_POWER_BT_SCO_ENA; |
222 | else | 222 | else |
223 | cmd->flags &= ~IWL_POWER_BT_SCO_ENA; | 223 | cmd->flags &= ~IWL_POWER_BT_SCO_ENA; |
@@ -293,7 +293,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
293 | 293 | ||
294 | if (priv->wowlan) | 294 | if (priv->wowlan) |
295 | iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); | 295 | iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); |
296 | else if (!priv->cfg->base_params->no_idle_support && | 296 | else if (!priv->lib->no_idle_support && |
297 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | 297 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) |
298 | iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); | 298 | iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); |
299 | else if (iwl_tt_is_low_power_state(priv)) { | 299 | else if (iwl_tt_is_low_power_state(priv)) { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 907bd6e50aad..94314a8e1029 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -1088,7 +1088,7 @@ done: | |||
1088 | (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) | 1088 | (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) |
1089 | rs_program_fix_rate(priv, lq_sta); | 1089 | rs_program_fix_rate(priv, lq_sta); |
1090 | #endif | 1090 | #endif |
1091 | if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) | 1091 | if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist) |
1092 | rs_bt_update_lq(priv, ctx, lq_sta); | 1092 | rs_bt_update_lq(priv, ctx, lq_sta); |
1093 | } | 1093 | } |
1094 | 1094 | ||
@@ -3064,11 +3064,11 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
3064 | * overwrite if needed, pass aggregation time limit | 3064 | * overwrite if needed, pass aggregation time limit |
3065 | * to uCode in uSec | 3065 | * to uCode in uSec |
3066 | */ | 3066 | */ |
3067 | if (priv && priv->cfg->bt_params && | 3067 | if (priv && priv->lib->bt_params && |
3068 | priv->cfg->bt_params->agg_time_limit && | 3068 | priv->lib->bt_params->agg_time_limit && |
3069 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) | 3069 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) |
3070 | lq_cmd->agg_params.agg_time_limit = | 3070 | lq_cmd->agg_params.agg_time_limit = |
3071 | cpu_to_le16(priv->cfg->bt_params->agg_time_limit); | 3071 | cpu_to_le16(priv->lib->bt_params->agg_time_limit); |
3072 | } | 3072 | } |
3073 | 3073 | ||
3074 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 3074 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index a4eed2055fdb..2f3fd160ab44 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -1102,7 +1102,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1102 | iwl_notification_wait_init(&priv->notif_wait); | 1102 | iwl_notification_wait_init(&priv->notif_wait); |
1103 | 1103 | ||
1104 | /* Set up BT Rx handlers */ | 1104 | /* Set up BT Rx handlers */ |
1105 | if (priv->cfg->bt_params) | 1105 | if (priv->lib->bt_params) |
1106 | iwlagn_bt_rx_handler_setup(priv); | 1106 | iwlagn_bt_rx_handler_setup(priv); |
1107 | } | 1107 | } |
1108 | 1108 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index d69b55866714..8c686a5b90ac 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -801,8 +801,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
801 | * Internal scans are passive, so we can indiscriminately set | 801 | * Internal scans are passive, so we can indiscriminately set |
802 | * the BT ignore flag on 2.4 GHz since it applies to TX only. | 802 | * the BT ignore flag on 2.4 GHz since it applies to TX only. |
803 | */ | 803 | */ |
804 | if (priv->cfg->bt_params && | 804 | if (priv->lib->bt_params && |
805 | priv->cfg->bt_params->advanced_bt_coexist) | 805 | priv->lib->bt_params->advanced_bt_coexist) |
806 | scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; | 806 | scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; |
807 | break; | 807 | break; |
808 | case IEEE80211_BAND_5GHZ: | 808 | case IEEE80211_BAND_5GHZ: |
@@ -844,8 +844,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
844 | band = priv->scan_band; | 844 | band = priv->scan_band; |
845 | 845 | ||
846 | if (band == IEEE80211_BAND_2GHZ && | 846 | if (band == IEEE80211_BAND_2GHZ && |
847 | priv->cfg->bt_params && | 847 | priv->lib->bt_params && |
848 | priv->cfg->bt_params->advanced_bt_coexist) { | 848 | priv->lib->bt_params->advanced_bt_coexist) { |
849 | /* transmit 2.4 GHz probes only on first antenna */ | 849 | /* transmit 2.4 GHz probes only on first antenna */ |
850 | scan_tx_antennas = first_antenna(scan_tx_antennas); | 850 | scan_tx_antennas = first_antenna(scan_tx_antennas); |
851 | } | 851 | } |
@@ -873,8 +873,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
873 | 873 | ||
874 | rx_ant = first_antenna(active_chains); | 874 | rx_ant = first_antenna(active_chains); |
875 | } | 875 | } |
876 | if (priv->cfg->bt_params && | 876 | if (priv->lib->bt_params && |
877 | priv->cfg->bt_params->advanced_bt_coexist && | 877 | priv->lib->bt_params->advanced_bt_coexist && |
878 | priv->bt_full_concurrent) { | 878 | priv->bt_full_concurrent) { |
879 | /* operated as 1x1 in full concurrency mode */ | 879 | /* operated as 1x1 in full concurrency mode */ |
880 | rx_ant = first_antenna(rx_ant); | 880 | rx_ant = first_antenna(rx_ant); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index db183b44e038..c3c13ce96eb0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -735,7 +735,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
735 | memcpy(&lq, priv->stations[i].lq, | 735 | memcpy(&lq, priv->stations[i].lq, |
736 | sizeof(struct iwl_link_quality_cmd)); | 736 | sizeof(struct iwl_link_quality_cmd)); |
737 | 737 | ||
738 | if (!memcmp(&lq, &zero_lq, sizeof(lq))) | 738 | if (memcmp(&lq, &zero_lq, sizeof(lq))) |
739 | send_lq = true; | 739 | send_lq = true; |
740 | } | 740 | } |
741 | spin_unlock_bh(&priv->sta_lock); | 741 | spin_unlock_bh(&priv->sta_lock); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index 03f9bc01c0cc..fbeee081ee2f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -627,7 +627,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
627 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | 627 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); |
628 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | 628 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); |
629 | 629 | ||
630 | if (priv->cfg->base_params->adv_thermal_throttle) { | 630 | if (priv->lib->adv_thermal_throttle) { |
631 | IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n"); | 631 | IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n"); |
632 | tt->restriction = kcalloc(IWL_TI_STATE_MAX, | 632 | tt->restriction = kcalloc(IWL_TI_STATE_MAX, |
633 | sizeof(struct iwl_tt_restriction), | 633 | sizeof(struct iwl_tt_restriction), |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index a900aaf47790..353a053b4eb1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -83,8 +83,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
83 | else if (ieee80211_is_back_req(fc)) | 83 | else if (ieee80211_is_back_req(fc)) |
84 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | 84 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; |
85 | else if (info->band == IEEE80211_BAND_2GHZ && | 85 | else if (info->band == IEEE80211_BAND_2GHZ && |
86 | priv->cfg->bt_params && | 86 | priv->lib->bt_params && |
87 | priv->cfg->bt_params->advanced_bt_coexist && | 87 | priv->lib->bt_params->advanced_bt_coexist && |
88 | (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || | 88 | (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || |
89 | ieee80211_is_reassoc_req(fc) || | 89 | ieee80211_is_reassoc_req(fc) || |
90 | skb->protocol == cpu_to_be16(ETH_P_PAE))) | 90 | skb->protocol == cpu_to_be16(ETH_P_PAE))) |
@@ -202,8 +202,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
202 | rate_flags |= RATE_MCS_CCK_MSK; | 202 | rate_flags |= RATE_MCS_CCK_MSK; |
203 | 203 | ||
204 | /* Set up antennas */ | 204 | /* Set up antennas */ |
205 | if (priv->cfg->bt_params && | 205 | if (priv->lib->bt_params && |
206 | priv->cfg->bt_params->advanced_bt_coexist && | 206 | priv->lib->bt_params->advanced_bt_coexist && |
207 | priv->bt_full_concurrent) { | 207 | priv->bt_full_concurrent) { |
208 | /* operated as 1x1 in full concurrency mode */ | 208 | /* operated as 1x1 in full concurrency mode */ |
209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 209 | 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, | |||
986 | * notification again. | 986 | * notification again. |
987 | */ | 987 | */ |
988 | if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && | 988 | if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && |
989 | priv->cfg->bt_params && | 989 | priv->lib->bt_params && |
990 | priv->cfg->bt_params->advanced_bt_coexist) { | 990 | priv->lib->bt_params->advanced_bt_coexist) { |
991 | IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); | 991 | IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); |
992 | } | 992 | } |
993 | 993 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 0a1cdc5e856b..86270b69cd02 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -132,8 +132,8 @@ int iwl_init_alive_start(struct iwl_priv *priv) | |||
132 | { | 132 | { |
133 | int ret; | 133 | int ret; |
134 | 134 | ||
135 | if (priv->cfg->bt_params && | 135 | if (priv->lib->bt_params && |
136 | priv->cfg->bt_params->advanced_bt_coexist) { | 136 | priv->lib->bt_params->advanced_bt_coexist) { |
137 | /* | 137 | /* |
138 | * Tell uCode we are ready to perform calibration | 138 | * Tell uCode we are ready to perform calibration |
139 | * need to perform this before any calibration | 139 | * need to perform this before any calibration |
@@ -155,8 +155,8 @@ int iwl_init_alive_start(struct iwl_priv *priv) | |||
155 | * temperature offset calibration is only needed for runtime ucode, | 155 | * temperature offset calibration is only needed for runtime ucode, |
156 | * so prepare the value now. | 156 | * so prepare the value now. |
157 | */ | 157 | */ |
158 | if (priv->cfg->need_temp_offset_calib) { | 158 | if (priv->lib->need_temp_offset_calib) { |
159 | if (priv->cfg->temp_offset_v2) | 159 | if (priv->lib->temp_offset_v2) |
160 | return iwl_set_temperature_offset_calib_v2(priv); | 160 | return iwl_set_temperature_offset_calib_v2(priv); |
161 | else | 161 | else |
162 | return iwl_set_temperature_offset_calib(priv); | 162 | return iwl_set_temperature_offset_calib(priv); |
@@ -277,7 +277,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
277 | if (ret) | 277 | if (ret) |
278 | return ret; | 278 | return ret; |
279 | 279 | ||
280 | if (!priv->cfg->no_xtal_calib) { | 280 | if (!priv->lib->no_xtal_calib) { |
281 | ret = iwl_set_Xtal_calib(priv); | 281 | ret = iwl_set_Xtal_calib(priv); |
282 | if (ret) | 282 | if (ret) |
283 | return ret; | 283 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index c080ae3070b2..0d2afe098afc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -60,9 +60,6 @@ static const struct iwl_base_params iwl1000_base_params = { | |||
60 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 60 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
61 | .shadow_ram_support = false, | 61 | .shadow_ram_support = false, |
62 | .led_compensation = 51, | 62 | .led_compensation = 51, |
63 | .support_ct_kill_exit = true, | ||
64 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||
65 | .chain_noise_scale = 1000, | ||
66 | .wd_timeout = IWL_WATCHDOG_DISABLED, | 63 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
67 | .max_event_log_size = 128, | 64 | .max_event_log_size = 128, |
68 | }; | 65 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index a6ddd2f9fba0..c727ec7c90a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -72,14 +72,9 @@ static const struct iwl_base_params iwl2000_base_params = { | |||
72 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | 72 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, |
73 | .shadow_ram_support = true, | 73 | .shadow_ram_support = true, |
74 | .led_compensation = 51, | 74 | .led_compensation = 51, |
75 | .adv_thermal_throttle = true, | ||
76 | .support_ct_kill_exit = true, | ||
77 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
78 | .chain_noise_scale = 1000, | ||
79 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 75 | .wd_timeout = IWL_DEF_WD_TIMEOUT, |
80 | .max_event_log_size = 512, | 76 | .max_event_log_size = 512, |
81 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 77 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
82 | .hd_v2 = true, | ||
83 | }; | 78 | }; |
84 | 79 | ||
85 | 80 | ||
@@ -90,14 +85,9 @@ static const struct iwl_base_params iwl2030_base_params = { | |||
90 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | 85 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, |
91 | .shadow_ram_support = true, | 86 | .shadow_ram_support = true, |
92 | .led_compensation = 57, | 87 | .led_compensation = 57, |
93 | .adv_thermal_throttle = true, | ||
94 | .support_ct_kill_exit = true, | ||
95 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
96 | .chain_noise_scale = 1000, | ||
97 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 88 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
98 | .max_event_log_size = 512, | 89 | .max_event_log_size = 512, |
99 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 90 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
100 | .hd_v2 = true, | ||
101 | }; | 91 | }; |
102 | 92 | ||
103 | static const struct iwl_ht_params iwl2000_ht_params = { | 93 | static const struct iwl_ht_params iwl2000_ht_params = { |
@@ -106,16 +96,6 @@ static const struct iwl_ht_params iwl2000_ht_params = { | |||
106 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), | 96 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), |
107 | }; | 97 | }; |
108 | 98 | ||
109 | static const struct iwl_bt_params iwl2030_bt_params = { | ||
110 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
111 | .advanced_bt_coexist = true, | ||
112 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | ||
113 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
114 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32, | ||
115 | .bt_sco_disable = true, | ||
116 | .bt_session_2 = true, | ||
117 | }; | ||
118 | |||
119 | static const struct iwl_eeprom_params iwl20x0_eeprom_params = { | 99 | static const struct iwl_eeprom_params iwl20x0_eeprom_params = { |
120 | .regulatory_bands = { | 100 | .regulatory_bands = { |
121 | EEPROM_REG_BAND_1_CHANNELS, | 101 | EEPROM_REG_BAND_1_CHANNELS, |
@@ -137,12 +117,10 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = { | |||
137 | .device_family = IWL_DEVICE_FAMILY_2000, \ | 117 | .device_family = IWL_DEVICE_FAMILY_2000, \ |
138 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 118 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
139 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 119 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
140 | .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ | 120 | .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ |
141 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 121 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
142 | .base_params = &iwl2000_base_params, \ | 122 | .base_params = &iwl2000_base_params, \ |
143 | .eeprom_params = &iwl20x0_eeprom_params, \ | 123 | .eeprom_params = &iwl20x0_eeprom_params, \ |
144 | .need_temp_offset_calib = true, \ | ||
145 | .temp_offset_v2 = true, \ | ||
146 | .led_mode = IWL_LED_RF_STATE | 124 | .led_mode = IWL_LED_RF_STATE |
147 | 125 | ||
148 | const struct iwl_cfg iwl2000_2bgn_cfg = { | 126 | const struct iwl_cfg iwl2000_2bgn_cfg = { |
@@ -168,12 +146,8 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
168 | .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ | 146 | .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ |
169 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 147 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
170 | .base_params = &iwl2030_base_params, \ | 148 | .base_params = &iwl2030_base_params, \ |
171 | .bt_params = &iwl2030_bt_params, \ | ||
172 | .eeprom_params = &iwl20x0_eeprom_params, \ | 149 | .eeprom_params = &iwl20x0_eeprom_params, \ |
173 | .need_temp_offset_calib = true, \ | 150 | .led_mode = IWL_LED_RF_STATE |
174 | .temp_offset_v2 = true, \ | ||
175 | .led_mode = IWL_LED_RF_STATE, \ | ||
176 | .adv_pm = true | ||
177 | 151 | ||
178 | const struct iwl_cfg iwl2030_2bgn_cfg = { | 152 | const struct iwl_cfg iwl2030_2bgn_cfg = { |
179 | .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", | 153 | .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", |
@@ -193,10 +167,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | |||
193 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 167 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
194 | .base_params = &iwl2000_base_params, \ | 168 | .base_params = &iwl2000_base_params, \ |
195 | .eeprom_params = &iwl20x0_eeprom_params, \ | 169 | .eeprom_params = &iwl20x0_eeprom_params, \ |
196 | .need_temp_offset_calib = true, \ | ||
197 | .temp_offset_v2 = true, \ | ||
198 | .led_mode = IWL_LED_RF_STATE, \ | 170 | .led_mode = IWL_LED_RF_STATE, \ |
199 | .adv_pm = true, \ | ||
200 | .rx_with_siso_diversity = true | 171 | .rx_with_siso_diversity = true |
201 | 172 | ||
202 | const struct iwl_cfg iwl105_bgn_cfg = { | 173 | const struct iwl_cfg iwl105_bgn_cfg = { |
@@ -222,12 +193,8 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | |||
222 | .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ | 193 | .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ |
223 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 194 | .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
224 | .base_params = &iwl2030_base_params, \ | 195 | .base_params = &iwl2030_base_params, \ |
225 | .bt_params = &iwl2030_bt_params, \ | ||
226 | .eeprom_params = &iwl20x0_eeprom_params, \ | 196 | .eeprom_params = &iwl20x0_eeprom_params, \ |
227 | .need_temp_offset_calib = true, \ | ||
228 | .temp_offset_v2 = true, \ | ||
229 | .led_mode = IWL_LED_RF_STATE, \ | 197 | .led_mode = IWL_LED_RF_STATE, \ |
230 | .adv_pm = true, \ | ||
231 | .rx_with_siso_diversity = true | 198 | .rx_with_siso_diversity = true |
232 | 199 | ||
233 | const struct iwl_cfg iwl135_bgn_cfg = { | 200 | const struct iwl_cfg iwl135_bgn_cfg = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 403f3f224bf6..ecc01e1a61a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -59,11 +59,8 @@ static const struct iwl_base_params iwl5000_base_params = { | |||
59 | .num_of_queues = IWLAGN_NUM_QUEUES, | 59 | .num_of_queues = IWLAGN_NUM_QUEUES, |
60 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 60 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
61 | .led_compensation = 51, | 61 | .led_compensation = 51, |
62 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
63 | .chain_noise_scale = 1000, | ||
64 | .wd_timeout = IWL_WATCHDOG_DISABLED, | 62 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
65 | .max_event_log_size = 512, | 63 | .max_event_log_size = 512, |
66 | .no_idle_support = true, | ||
67 | }; | 64 | }; |
68 | 65 | ||
69 | static const struct iwl_ht_params iwl5000_ht_params = { | 66 | static const struct iwl_ht_params iwl5000_ht_params = { |
@@ -159,7 +156,6 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
159 | .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ | 156 | .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ |
160 | .base_params = &iwl5000_base_params, \ | 157 | .base_params = &iwl5000_base_params, \ |
161 | .eeprom_params = &iwl5000_eeprom_params, \ | 158 | .eeprom_params = &iwl5000_eeprom_params, \ |
162 | .no_xtal_calib = true, \ | ||
163 | .led_mode = IWL_LED_BLINK, \ | 159 | .led_mode = IWL_LED_BLINK, \ |
164 | .internal_wimax_coex = true | 160 | .internal_wimax_coex = true |
165 | 161 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b5ab8d1bcac0..30d45e2fc193 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -82,10 +82,6 @@ static const struct iwl_base_params iwl6000_base_params = { | |||
82 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 82 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
83 | .shadow_ram_support = true, | 83 | .shadow_ram_support = true, |
84 | .led_compensation = 51, | 84 | .led_compensation = 51, |
85 | .adv_thermal_throttle = true, | ||
86 | .support_ct_kill_exit = true, | ||
87 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
88 | .chain_noise_scale = 1000, | ||
89 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 85 | .wd_timeout = IWL_DEF_WD_TIMEOUT, |
90 | .max_event_log_size = 512, | 86 | .max_event_log_size = 512, |
91 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 87 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
@@ -98,10 +94,6 @@ static const struct iwl_base_params iwl6050_base_params = { | |||
98 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | 94 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
99 | .shadow_ram_support = true, | 95 | .shadow_ram_support = true, |
100 | .led_compensation = 51, | 96 | .led_compensation = 51, |
101 | .adv_thermal_throttle = true, | ||
102 | .support_ct_kill_exit = true, | ||
103 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
104 | .chain_noise_scale = 1500, | ||
105 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 97 | .wd_timeout = IWL_DEF_WD_TIMEOUT, |
106 | .max_event_log_size = 1024, | 98 | .max_event_log_size = 1024, |
107 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 99 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
@@ -114,10 +106,6 @@ static const struct iwl_base_params iwl6000_g2_base_params = { | |||
114 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 106 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
115 | .shadow_ram_support = true, | 107 | .shadow_ram_support = true, |
116 | .led_compensation = 57, | 108 | .led_compensation = 57, |
117 | .adv_thermal_throttle = true, | ||
118 | .support_ct_kill_exit = true, | ||
119 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
120 | .chain_noise_scale = 1000, | ||
121 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 109 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
122 | .max_event_log_size = 512, | 110 | .max_event_log_size = 512, |
123 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 111 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
@@ -129,15 +117,6 @@ static const struct iwl_ht_params iwl6000_ht_params = { | |||
129 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | 117 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), |
130 | }; | 118 | }; |
131 | 119 | ||
132 | static const struct iwl_bt_params iwl6000_bt_params = { | ||
133 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
134 | .advanced_bt_coexist = true, | ||
135 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | ||
136 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
137 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
138 | .bt_sco_disable = true, | ||
139 | }; | ||
140 | |||
141 | static const struct iwl_eeprom_params iwl6000_eeprom_params = { | 120 | static const struct iwl_eeprom_params iwl6000_eeprom_params = { |
142 | .regulatory_bands = { | 121 | .regulatory_bands = { |
143 | EEPROM_REG_BAND_1_CHANNELS, | 122 | EEPROM_REG_BAND_1_CHANNELS, |
@@ -163,7 +142,6 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = { | |||
163 | .nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ | 142 | .nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ |
164 | .base_params = &iwl6000_g2_base_params, \ | 143 | .base_params = &iwl6000_g2_base_params, \ |
165 | .eeprom_params = &iwl6000_eeprom_params, \ | 144 | .eeprom_params = &iwl6000_eeprom_params, \ |
166 | .need_temp_offset_calib = true, \ | ||
167 | .led_mode = IWL_LED_RF_STATE | 145 | .led_mode = IWL_LED_RF_STATE |
168 | 146 | ||
169 | const struct iwl_cfg iwl6005_2agn_cfg = { | 147 | const struct iwl_cfg iwl6005_2agn_cfg = { |
@@ -217,11 +195,8 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { | |||
217 | .nvm_ver = EEPROM_6030_EEPROM_VERSION, \ | 195 | .nvm_ver = EEPROM_6030_EEPROM_VERSION, \ |
218 | .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | 196 | .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
219 | .base_params = &iwl6000_g2_base_params, \ | 197 | .base_params = &iwl6000_g2_base_params, \ |
220 | .bt_params = &iwl6000_bt_params, \ | ||
221 | .eeprom_params = &iwl6000_eeprom_params, \ | 198 | .eeprom_params = &iwl6000_eeprom_params, \ |
222 | .need_temp_offset_calib = true, \ | 199 | .led_mode = IWL_LED_RF_STATE |
223 | .led_mode = IWL_LED_RF_STATE, \ | ||
224 | .adv_pm = true \ | ||
225 | 200 | ||
226 | const struct iwl_cfg iwl6030_2agn_cfg = { | 201 | const struct iwl_cfg iwl6030_2agn_cfg = { |
227 | .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", | 202 | .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", |
@@ -256,11 +231,8 @@ const struct iwl_cfg iwl6030_2bg_cfg = { | |||
256 | .nvm_ver = EEPROM_6030_EEPROM_VERSION, \ | 231 | .nvm_ver = EEPROM_6030_EEPROM_VERSION, \ |
257 | .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | 232 | .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
258 | .base_params = &iwl6000_g2_base_params, \ | 233 | .base_params = &iwl6000_g2_base_params, \ |
259 | .bt_params = &iwl6000_bt_params, \ | ||
260 | .eeprom_params = &iwl6000_eeprom_params, \ | 234 | .eeprom_params = &iwl6000_eeprom_params, \ |
261 | .need_temp_offset_calib = true, \ | 235 | .led_mode = IWL_LED_RF_STATE |
262 | .led_mode = IWL_LED_RF_STATE, \ | ||
263 | .adv_pm = true | ||
264 | 236 | ||
265 | const struct iwl_cfg iwl6035_2agn_cfg = { | 237 | const struct iwl_cfg iwl6035_2agn_cfg = { |
266 | .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", | 238 | .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 50263e87fe15..d4f3b4864ab1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -96,13 +96,9 @@ static const struct iwl_base_params iwl7000_base_params = { | |||
96 | .pll_cfg_val = 0, | 96 | .pll_cfg_val = 0, |
97 | .shadow_ram_support = true, | 97 | .shadow_ram_support = true, |
98 | .led_compensation = 57, | 98 | .led_compensation = 57, |
99 | .adv_thermal_throttle = true, | ||
100 | .support_ct_kill_exit = true, | ||
101 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
102 | .chain_noise_scale = 1000, | ||
103 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 99 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
104 | .max_event_log_size = 512, | 100 | .max_event_log_size = 512, |
105 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 101 | .shadow_reg_enable = true, |
106 | }; | 102 | }; |
107 | 103 | ||
108 | static const struct iwl_ht_params iwl7000_ht_params = { | 104 | static const struct iwl_ht_params iwl7000_ht_params = { |
@@ -118,14 +114,11 @@ static const struct iwl_ht_params iwl7000_ht_params = { | |||
118 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 114 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
119 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 115 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
120 | .base_params = &iwl7000_base_params, \ | 116 | .base_params = &iwl7000_base_params, \ |
121 | /* TODO: .bt_params? */ \ | 117 | .led_mode = IWL_LED_RF_STATE |
122 | .need_temp_offset_calib = true, \ | ||
123 | .led_mode = IWL_LED_RF_STATE, \ | ||
124 | .adv_pm = true \ | ||
125 | 118 | ||
126 | 119 | ||
127 | const struct iwl_cfg iwl7260_2ac_cfg = { | 120 | const struct iwl_cfg iwl7260_2ac_cfg = { |
128 | .name = "Intel(R) Dual Band Wireless AC7260", | 121 | .name = "Intel(R) Dual Band Wireless AC 7260", |
129 | .fw_name_pre = IWL7260_FW_PRE, | 122 | .fw_name_pre = IWL7260_FW_PRE, |
130 | IWL_DEVICE_7000, | 123 | IWL_DEVICE_7000, |
131 | .ht_params = &iwl7000_ht_params, | 124 | .ht_params = &iwl7000_ht_params, |
@@ -133,8 +126,44 @@ const struct iwl_cfg iwl7260_2ac_cfg = { | |||
133 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | 126 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, |
134 | }; | 127 | }; |
135 | 128 | ||
136 | const struct iwl_cfg iwl3160_ac_cfg = { | 129 | const struct iwl_cfg iwl7260_2n_cfg = { |
137 | .name = "Intel(R) Dual Band Wireless AC3160", | 130 | .name = "Intel(R) Dual Band Wireless N 7260", |
131 | .fw_name_pre = IWL7260_FW_PRE, | ||
132 | IWL_DEVICE_7000, | ||
133 | .ht_params = &iwl7000_ht_params, | ||
134 | .nvm_ver = IWL7260_NVM_VERSION, | ||
135 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | ||
136 | }; | ||
137 | |||
138 | const struct iwl_cfg iwl7260_n_cfg = { | ||
139 | .name = "Intel(R) Wireless N 7260", | ||
140 | .fw_name_pre = IWL7260_FW_PRE, | ||
141 | IWL_DEVICE_7000, | ||
142 | .ht_params = &iwl7000_ht_params, | ||
143 | .nvm_ver = IWL7260_NVM_VERSION, | ||
144 | .nvm_calib_ver = IWL7260_TX_POWER_VERSION, | ||
145 | }; | ||
146 | |||
147 | const struct iwl_cfg iwl3160_2ac_cfg = { | ||
148 | .name = "Intel(R) Dual Band Wireless AC 3160", | ||
149 | .fw_name_pre = IWL3160_FW_PRE, | ||
150 | IWL_DEVICE_7000, | ||
151 | .ht_params = &iwl7000_ht_params, | ||
152 | .nvm_ver = IWL3160_NVM_VERSION, | ||
153 | .nvm_calib_ver = IWL3160_TX_POWER_VERSION, | ||
154 | }; | ||
155 | |||
156 | const struct iwl_cfg iwl3160_2n_cfg = { | ||
157 | .name = "Intel(R) Dual Band Wireless N 3160", | ||
158 | .fw_name_pre = IWL3160_FW_PRE, | ||
159 | IWL_DEVICE_7000, | ||
160 | .ht_params = &iwl7000_ht_params, | ||
161 | .nvm_ver = IWL3160_NVM_VERSION, | ||
162 | .nvm_calib_ver = IWL3160_TX_POWER_VERSION, | ||
163 | }; | ||
164 | |||
165 | const struct iwl_cfg iwl3160_n_cfg = { | ||
166 | .name = "Intel(R) Wireless N 3160", | ||
138 | .fw_name_pre = IWL3160_FW_PRE, | 167 | .fw_name_pre = IWL3160_FW_PRE, |
139 | IWL_DEVICE_7000, | 168 | IWL_DEVICE_7000, |
140 | .ht_params = &iwl7000_ht_params, | 169 | .ht_params = &iwl7000_ht_params, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index c38aa8f77554..a193832fc790 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -136,17 +136,9 @@ enum iwl_led_mode { | |||
136 | * @led_compensation: compensate on the led on/off time per HW according | 136 | * @led_compensation: compensate on the led on/off time per HW according |
137 | * to the deviation to achieve the desired led frequency. | 137 | * to the deviation to achieve the desired led frequency. |
138 | * The detail algorithm is described in iwl-led.c | 138 | * The detail algorithm is described in iwl-led.c |
139 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | ||
140 | * @adv_thermal_throttle: support advance thermal throttle | ||
141 | * @support_ct_kill_exit: support ct kill exit condition | ||
142 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | ||
143 | * radio tuning when there is a high receiving plcp error rate | ||
144 | * @chain_noise_scale: default chain noise scale used for gain computation | ||
145 | * @wd_timeout: TX queues watchdog timeout | 139 | * @wd_timeout: TX queues watchdog timeout |
146 | * @max_event_log_size: size of event log buffer size for ucode event logging | 140 | * @max_event_log_size: size of event log buffer size for ucode event logging |
147 | * @shadow_reg_enable: HW shadow register support | 141 | * @shadow_reg_enable: HW shadow register support |
148 | * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up | ||
149 | * @no_idle_support: do not support idle mode | ||
150 | */ | 142 | */ |
151 | struct iwl_base_params { | 143 | struct iwl_base_params { |
152 | int eeprom_size; | 144 | int eeprom_size; |
@@ -157,31 +149,9 @@ struct iwl_base_params { | |||
157 | const u16 max_ll_items; | 149 | const u16 max_ll_items; |
158 | const bool shadow_ram_support; | 150 | const bool shadow_ram_support; |
159 | u16 led_compensation; | 151 | u16 led_compensation; |
160 | bool adv_thermal_throttle; | ||
161 | bool support_ct_kill_exit; | ||
162 | u8 plcp_delta_threshold; | ||
163 | s32 chain_noise_scale; | ||
164 | unsigned int wd_timeout; | 152 | unsigned int wd_timeout; |
165 | u32 max_event_log_size; | 153 | u32 max_event_log_size; |
166 | const bool shadow_reg_enable; | 154 | const bool shadow_reg_enable; |
167 | const bool hd_v2; | ||
168 | const bool no_idle_support; | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * @advanced_bt_coexist: support advanced bt coexist | ||
173 | * @bt_init_traffic_load: specify initial bt traffic load | ||
174 | * @bt_prio_boost: default bt priority boost value | ||
175 | * @agg_time_limit: maximum number of uSec in aggregation | ||
176 | * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode | ||
177 | */ | ||
178 | struct iwl_bt_params { | ||
179 | bool advanced_bt_coexist; | ||
180 | u8 bt_init_traffic_load; | ||
181 | u32 bt_prio_boost; | ||
182 | u16 agg_time_limit; | ||
183 | bool bt_sco_disable; | ||
184 | bool bt_session_2; | ||
185 | }; | 155 | }; |
186 | 156 | ||
187 | /* | 157 | /* |
@@ -231,16 +201,10 @@ struct iwl_eeprom_params { | |||
231 | * @nvm_calib_ver: NVM calibration version | 201 | * @nvm_calib_ver: NVM calibration version |
232 | * @lib: pointer to the lib ops | 202 | * @lib: pointer to the lib ops |
233 | * @base_params: pointer to basic parameters | 203 | * @base_params: pointer to basic parameters |
234 | * @ht_params: point to ht patameters | 204 | * @ht_params: point to ht parameters |
235 | * @bt_params: pointer to bt parameters | ||
236 | * @need_temp_offset_calib: need to perform temperature offset calibration | ||
237 | * @no_xtal_calib: some devices do not need crystal calibration data, | ||
238 | * don't send it to those | ||
239 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) | 205 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) |
240 | * @adv_pm: advance power management | ||
241 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | 206 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity |
242 | * @internal_wimax_coex: internal wifi/wimax combo device | 207 | * @internal_wimax_coex: internal wifi/wimax combo device |
243 | * @temp_offset_v2: support v2 of temperature offset calibration | ||
244 | * | 208 | * |
245 | * We enable the driver to be backward compatible wrt. hardware features. | 209 | * We enable the driver to be backward compatible wrt. hardware features. |
246 | * API differences in uCode shouldn't be handled here but through TLVs | 210 | * API differences in uCode shouldn't be handled here but through TLVs |
@@ -264,15 +228,10 @@ struct iwl_cfg { | |||
264 | const struct iwl_base_params *base_params; | 228 | const struct iwl_base_params *base_params; |
265 | /* params likely to change within a device family */ | 229 | /* params likely to change within a device family */ |
266 | const struct iwl_ht_params *ht_params; | 230 | const struct iwl_ht_params *ht_params; |
267 | const struct iwl_bt_params *bt_params; | ||
268 | const struct iwl_eeprom_params *eeprom_params; | 231 | const struct iwl_eeprom_params *eeprom_params; |
269 | const bool need_temp_offset_calib; /* if used set to true */ | ||
270 | const bool no_xtal_calib; | ||
271 | enum iwl_led_mode led_mode; | 232 | enum iwl_led_mode led_mode; |
272 | const bool adv_pm; | ||
273 | const bool rx_with_siso_diversity; | 233 | const bool rx_with_siso_diversity; |
274 | const bool internal_wimax_coex; | 234 | const bool internal_wimax_coex; |
275 | const bool temp_offset_v2; | ||
276 | }; | 235 | }; |
277 | 236 | ||
278 | /* | 237 | /* |
@@ -320,6 +279,10 @@ extern const struct iwl_cfg iwl105_bgn_cfg; | |||
320 | extern const struct iwl_cfg iwl105_bgn_d_cfg; | 279 | extern const struct iwl_cfg iwl105_bgn_d_cfg; |
321 | extern const struct iwl_cfg iwl135_bgn_cfg; | 280 | extern const struct iwl_cfg iwl135_bgn_cfg; |
322 | extern const struct iwl_cfg iwl7260_2ac_cfg; | 281 | extern const struct iwl_cfg iwl7260_2ac_cfg; |
323 | extern const struct iwl_cfg iwl3160_ac_cfg; | 282 | extern const struct iwl_cfg iwl7260_2n_cfg; |
283 | extern const struct iwl_cfg iwl7260_n_cfg; | ||
284 | extern const struct iwl_cfg iwl3160_2ac_cfg; | ||
285 | extern const struct iwl_cfg iwl3160_2n_cfg; | ||
286 | extern const struct iwl_cfg iwl3160_n_cfg; | ||
324 | 287 | ||
325 | #endif /* __IWL_CONFIG_H__ */ | 288 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 20e845d4da04..a276af476e2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -472,4 +472,23 @@ | |||
472 | #define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) | 472 | #define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) |
473 | #define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) | 473 | #define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) |
474 | 474 | ||
475 | /***************************************************************************** | ||
476 | * 7000/3000 series SHR DTS addresses * | ||
477 | *****************************************************************************/ | ||
478 | |||
479 | /* Diode Results Register Structure: */ | ||
480 | enum dtd_diode_reg { | ||
481 | DTS_DIODE_REG_DIG_VAL = 0x000000FF, /* bits [7:0] */ | ||
482 | DTS_DIODE_REG_VREF_LOW = 0x0000FF00, /* bits [15:8] */ | ||
483 | DTS_DIODE_REG_VREF_HIGH = 0x00FF0000, /* bits [23:16] */ | ||
484 | DTS_DIODE_REG_VREF_ID = 0x03000000, /* bits [25:24] */ | ||
485 | DTS_DIODE_REG_PASS_ONCE = 0x80000000, /* bits [31:31] */ | ||
486 | DTS_DIODE_REG_FLAGS_MSK = 0xFF000000, /* bits [31:24] */ | ||
487 | /* Those are the masks INSIDE the flags bit-field: */ | ||
488 | DTS_DIODE_REG_FLAGS_VREFS_ID_POS = 0, | ||
489 | DTS_DIODE_REG_FLAGS_VREFS_ID = 0x00000003, /* bits [1:0] */ | ||
490 | DTS_DIODE_REG_FLAGS_PASS_ONCE_POS = 7, | ||
491 | DTS_DIODE_REG_FLAGS_PASS_ONCE = 0x00000080, /* bits [7:7] */ | ||
492 | }; | ||
493 | |||
475 | #endif /* !__iwl_csr_h__ */ | 494 | #endif /* !__iwl_csr_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 39aad9893e0b..4f886133639a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -1234,6 +1234,9 @@ MODULE_PARM_DESC(wd_disable, | |||
1234 | "Disable stuck queue watchdog timer 0=system default, " | 1234 | "Disable stuck queue watchdog timer 0=system default, " |
1235 | "1=disable, 2=enable (default: 0)"); | 1235 | "1=disable, 2=enable (default: 0)"); |
1236 | 1236 | ||
1237 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); | ||
1238 | MODULE_PARM_DESC(nvm_file, "NVM file name"); | ||
1239 | |||
1237 | /* | 1240 | /* |
1238 | * set bt_coex_active to true, uCode will do kill/defer | 1241 | * set bt_coex_active to true, uCode will do kill/defer |
1239 | * every time the priority line is asserted (BT is sending signals on the | 1242 | * every time the priority line is asserted (BT is sending signals on the |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 600c9fdd7f71..4c887f365908 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -732,17 +732,16 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data, | |||
732 | void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | 732 | void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, |
733 | struct iwl_nvm_data *data, | 733 | struct iwl_nvm_data *data, |
734 | struct ieee80211_sta_ht_cap *ht_info, | 734 | struct ieee80211_sta_ht_cap *ht_info, |
735 | enum ieee80211_band band) | 735 | enum ieee80211_band band, |
736 | u8 tx_chains, u8 rx_chains) | ||
736 | { | 737 | { |
737 | int max_bit_rate = 0; | 738 | int max_bit_rate = 0; |
738 | u8 rx_chains; | ||
739 | u8 tx_chains; | ||
740 | 739 | ||
741 | tx_chains = hweight8(data->valid_tx_ant); | 740 | tx_chains = hweight8(tx_chains); |
742 | if (cfg->rx_with_siso_diversity) | 741 | if (cfg->rx_with_siso_diversity) |
743 | rx_chains = 1; | 742 | rx_chains = 1; |
744 | else | 743 | else |
745 | rx_chains = hweight8(data->valid_rx_ant); | 744 | rx_chains = hweight8(rx_chains); |
746 | 745 | ||
747 | if (!(data->sku_cap_11n_enable) || !cfg->ht_params) { | 746 | if (!(data->sku_cap_11n_enable) || !cfg->ht_params) { |
748 | ht_info->ht_supported = false; | 747 | ht_info->ht_supported = false; |
@@ -806,7 +805,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
806 | sband->n_bitrates = N_RATES_24; | 805 | sband->n_bitrates = N_RATES_24; |
807 | n_used += iwl_init_sband_channels(data, sband, n_channels, | 806 | n_used += iwl_init_sband_channels(data, sband, n_channels, |
808 | IEEE80211_BAND_2GHZ); | 807 | IEEE80211_BAND_2GHZ); |
809 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); | 808 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ, |
809 | data->valid_tx_ant, data->valid_rx_ant); | ||
810 | 810 | ||
811 | sband = &data->bands[IEEE80211_BAND_5GHZ]; | 811 | sband = &data->bands[IEEE80211_BAND_5GHZ]; |
812 | sband->band = IEEE80211_BAND_5GHZ; | 812 | sband->band = IEEE80211_BAND_5GHZ; |
@@ -814,7 +814,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
814 | sband->n_bitrates = N_RATES_52; | 814 | sband->n_bitrates = N_RATES_52; |
815 | n_used += iwl_init_sband_channels(data, sband, n_channels, | 815 | n_used += iwl_init_sband_channels(data, sband, n_channels, |
816 | IEEE80211_BAND_5GHZ); | 816 | IEEE80211_BAND_5GHZ); |
817 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | 817 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, |
818 | data->valid_tx_ant, data->valid_rx_ant); | ||
818 | 819 | ||
819 | if (n_channels != n_used) | 820 | if (n_channels != n_used) |
820 | IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", | 821 | IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index 37f115390b19..d73304a23ec2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -133,6 +133,7 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data, | |||
133 | void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | 133 | void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, |
134 | struct iwl_nvm_data *data, | 134 | struct iwl_nvm_data *data, |
135 | struct ieee80211_sta_ht_cap *ht_info, | 135 | struct ieee80211_sta_ht_cap *ht_info, |
136 | enum ieee80211_band band); | 136 | enum ieee80211_band band, |
137 | u8 tx_chains, u8 rx_chains); | ||
137 | 138 | ||
138 | #endif /* __iwl_eeprom_parse_h__ */ | 139 | #endif /* __iwl_eeprom_parse_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index c4c446d41eb0..f844d5c748c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -106,11 +106,14 @@ enum iwl_ucode_type { | |||
106 | 106 | ||
107 | /* | 107 | /* |
108 | * enumeration of ucode section. | 108 | * enumeration of ucode section. |
109 | * This enumeration is used for legacy tlv style (before 16.0 uCode). | 109 | * This enumeration is used directly for older firmware (before 16.0). |
110 | * For new firmware, there can be up to 4 sections (see below) but the | ||
111 | * first one packaged into the firmware file is the DATA section and | ||
112 | * some debugging code accesses that. | ||
110 | */ | 113 | */ |
111 | enum iwl_ucode_sec { | 114 | enum iwl_ucode_sec { |
112 | IWL_UCODE_SECTION_INST, | ||
113 | IWL_UCODE_SECTION_DATA, | 115 | IWL_UCODE_SECTION_DATA, |
116 | IWL_UCODE_SECTION_INST, | ||
114 | }; | 117 | }; |
115 | /* | 118 | /* |
116 | * For 16.0 uCode and above, there is no differentiation between sections, | 119 | * For 16.0 uCode and above, there is no differentiation between sections, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index d6f6c37c09fd..36dfe0919f6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -119,6 +119,7 @@ struct iwl_mod_params { | |||
119 | int ant_coupling; | 119 | int ant_coupling; |
120 | bool bt_ch_announce; | 120 | bool bt_ch_announce; |
121 | bool auto_agg; | 121 | bool auto_agg; |
122 | char *nvm_file; | ||
122 | }; | 123 | }; |
123 | 124 | ||
124 | #endif /* #__iwl_modparams_h__ */ | 125 | #endif /* #__iwl_modparams_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 6199a0a597a6..acd2665afb8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -89,6 +89,7 @@ enum nvm_sku_bits { | |||
89 | NVM_SKU_CAP_BAND_24GHZ = BIT(0), | 89 | NVM_SKU_CAP_BAND_24GHZ = BIT(0), |
90 | NVM_SKU_CAP_BAND_52GHZ = BIT(1), | 90 | NVM_SKU_CAP_BAND_52GHZ = BIT(1), |
91 | NVM_SKU_CAP_11N_ENABLE = BIT(2), | 91 | NVM_SKU_CAP_11N_ENABLE = BIT(2), |
92 | NVM_SKU_CAP_11AC_ENABLE = BIT(3), | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | /* radio config bits (actual values from NVM definition) */ | 95 | /* radio config bits (actual values from NVM definition) */ |
@@ -258,8 +259,6 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
258 | struct iwl_nvm_data *data, | 259 | struct iwl_nvm_data *data, |
259 | struct ieee80211_sta_vht_cap *vht_cap) | 260 | struct ieee80211_sta_vht_cap *vht_cap) |
260 | { | 261 | { |
261 | /* For now, assume new devices with NVM are VHT capable */ | ||
262 | |||
263 | vht_cap->vht_supported = true; | 262 | vht_cap->vht_supported = true; |
264 | 263 | ||
265 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | | 264 | 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, | |||
292 | } | 291 | } |
293 | 292 | ||
294 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 293 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
295 | struct iwl_nvm_data *data, const __le16 *nvm_sw) | 294 | struct iwl_nvm_data *data, const __le16 *nvm_sw, |
295 | bool enable_vht, u8 tx_chains, u8 rx_chains) | ||
296 | { | 296 | { |
297 | int n_channels = iwl_init_channel_map(dev, cfg, data, | 297 | int n_channels = iwl_init_channel_map(dev, cfg, data, |
298 | &nvm_sw[NVM_CHANNELS]); | 298 | &nvm_sw[NVM_CHANNELS]); |
@@ -305,7 +305,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
305 | sband->n_bitrates = N_RATES_24; | 305 | sband->n_bitrates = N_RATES_24; |
306 | n_used += iwl_init_sband_channels(data, sband, n_channels, | 306 | n_used += iwl_init_sband_channels(data, sband, n_channels, |
307 | IEEE80211_BAND_2GHZ); | 307 | IEEE80211_BAND_2GHZ); |
308 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); | 308 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ, |
309 | tx_chains, rx_chains); | ||
309 | 310 | ||
310 | sband = &data->bands[IEEE80211_BAND_5GHZ]; | 311 | sband = &data->bands[IEEE80211_BAND_5GHZ]; |
311 | sband->band = IEEE80211_BAND_5GHZ; | 312 | sband->band = IEEE80211_BAND_5GHZ; |
@@ -313,8 +314,10 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
313 | sband->n_bitrates = N_RATES_52; | 314 | sband->n_bitrates = N_RATES_52; |
314 | n_used += iwl_init_sband_channels(data, sband, n_channels, | 315 | n_used += iwl_init_sband_channels(data, sband, n_channels, |
315 | IEEE80211_BAND_5GHZ); | 316 | IEEE80211_BAND_5GHZ); |
316 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | 317 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, |
317 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); | 318 | tx_chains, rx_chains); |
319 | if (enable_vht) | ||
320 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); | ||
318 | 321 | ||
319 | if (n_channels != n_used) | 322 | if (n_channels != n_used) |
320 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", | 323 | 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, | |||
324 | struct iwl_nvm_data * | 327 | struct iwl_nvm_data * |
325 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 328 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
326 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 329 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
327 | const __le16 *nvm_calib) | 330 | const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains) |
328 | { | 331 | { |
329 | struct iwl_nvm_data *data; | 332 | struct iwl_nvm_data *data; |
330 | u8 hw_addr[ETH_ALEN]; | 333 | u8 hw_addr[ETH_ALEN]; |
@@ -380,7 +383,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
380 | data->hw_addr[4] = hw_addr[5]; | 383 | data->hw_addr[4] = hw_addr[5]; |
381 | data->hw_addr[5] = hw_addr[4]; | 384 | data->hw_addr[5] = hw_addr[4]; |
382 | 385 | ||
383 | iwl_init_sbands(dev, cfg, data, nvm_sw); | 386 | iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE, |
387 | tx_chains, rx_chains); | ||
384 | 388 | ||
385 | data->calib_version = 255; /* TODO: | 389 | data->calib_version = 255; /* TODO: |
386 | this value will prevent some checks from | 390 | this value will prevent some checks from |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index e57fb989661e..3325059c52d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | |||
@@ -75,6 +75,6 @@ | |||
75 | struct iwl_nvm_data * | 75 | struct iwl_nvm_data * |
76 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 76 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
77 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 77 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
78 | const __le16 *nvm_calib); | 78 | const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains); |
79 | 79 | ||
80 | #endif /* __iwl_nvm_parse_h__ */ | 80 | #endif /* __iwl_nvm_parse_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 386f2a7c87cb..ff8cc75c189d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -100,6 +100,18 @@ | |||
100 | /* Device system time */ | 100 | /* Device system time */ |
101 | #define DEVICE_SYSTEM_TIME_REG 0xA0206C | 101 | #define DEVICE_SYSTEM_TIME_REG 0xA0206C |
102 | 102 | ||
103 | /***************************************************************************** | ||
104 | * 7000/3000 series SHR DTS addresses * | ||
105 | *****************************************************************************/ | ||
106 | |||
107 | #define SHR_MISC_WFM_DTS_EN (0x00a10024) | ||
108 | #define DTSC_CFG_MODE (0x00a10604) | ||
109 | #define DTSC_VREF_AVG (0x00a10648) | ||
110 | #define DTSC_VREF5_AVG (0x00a1064c) | ||
111 | #define DTSC_CFG_MODE_PERIODIC (0x2) | ||
112 | #define DTSC_PTAT_AVG (0x00a10650) | ||
113 | |||
114 | |||
103 | /** | 115 | /** |
104 | * Tx Scheduler | 116 | * Tx Scheduler |
105 | * | 117 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7a13790b5bfe..84f1c8dc9741 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -189,7 +189,8 @@ enum CMD_MODE { | |||
189 | CMD_SYNC = 0, | 189 | CMD_SYNC = 0, |
190 | CMD_ASYNC = BIT(0), | 190 | CMD_ASYNC = BIT(0), |
191 | CMD_WANT_SKB = BIT(1), | 191 | CMD_WANT_SKB = BIT(1), |
192 | CMD_ON_DEMAND = BIT(2), | 192 | CMD_SEND_IN_RFKILL = BIT(2), |
193 | CMD_ON_DEMAND = BIT(3), | ||
193 | }; | 194 | }; |
194 | 195 | ||
195 | #define DEF_CMD_PAYLOAD_SIZE 320 | 196 | #define DEF_CMD_PAYLOAD_SIZE 320 |
@@ -455,7 +456,7 @@ struct iwl_trans_ops { | |||
455 | int (*read_mem)(struct iwl_trans *trans, u32 addr, | 456 | int (*read_mem)(struct iwl_trans *trans, u32 addr, |
456 | void *buf, int dwords); | 457 | void *buf, int dwords); |
457 | int (*write_mem)(struct iwl_trans *trans, u32 addr, | 458 | int (*write_mem)(struct iwl_trans *trans, u32 addr, |
458 | void *buf, int dwords); | 459 | const void *buf, int dwords); |
459 | void (*configure)(struct iwl_trans *trans, | 460 | void (*configure)(struct iwl_trans *trans, |
460 | const struct iwl_trans_config *trans_cfg); | 461 | const struct iwl_trans_config *trans_cfg); |
461 | void (*set_pmi)(struct iwl_trans *trans, bool state); | 462 | 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) | |||
761 | } | 762 | } |
762 | 763 | ||
763 | static inline int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, | 764 | static inline int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, |
764 | void *buf, int dwords) | 765 | const void *buf, int dwords) |
765 | { | 766 | { |
766 | return trans->ops->write_mem(trans, addr, buf, dwords); | 767 | return trans->ops->write_mem(trans, addr, buf, dwords); |
767 | } | 768 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 2acc44b40986..ff856e543ae8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
@@ -3,7 +3,7 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | |||
3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o |
4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
5 | iwlmvm-y += power.o bt-coex.o | 5 | iwlmvm-y += power.o bt-coex.o |
6 | iwlmvm-y += led.o | 6 | iwlmvm-y += led.o tt.o |
7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o |
8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
9 | 9 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 810bfa5f6de0..f03655f303aa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -351,6 +351,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
351 | enum ieee80211_band band; | 351 | enum ieee80211_band band; |
352 | int ave_rssi; | 352 | int ave_rssi; |
353 | 353 | ||
354 | lockdep_assert_held(&mvm->mutex); | ||
354 | if (vif->type != NL80211_IFTYPE_STATION) | 355 | if (vif->type != NL80211_IFTYPE_STATION) |
355 | return; | 356 | return; |
356 | 357 | ||
@@ -365,7 +366,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
365 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 366 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
366 | 367 | ||
367 | if (band != IEEE80211_BAND_2GHZ) { | 368 | if (band != IEEE80211_BAND_2GHZ) { |
368 | ieee80211_request_smps(vif, smps_mode); | 369 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, |
370 | smps_mode); | ||
369 | return; | 371 | return; |
370 | } | 372 | } |
371 | 373 | ||
@@ -380,7 +382,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
380 | mvmvif->id, data->notif->bt_status, | 382 | mvmvif->id, data->notif->bt_status, |
381 | data->notif->bt_traffic_load, smps_mode); | 383 | data->notif->bt_traffic_load, smps_mode); |
382 | 384 | ||
383 | ieee80211_request_smps(vif, smps_mode); | 385 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); |
384 | 386 | ||
385 | /* don't reduce the Tx power if in loose scheme */ | 387 | /* don't reduce the Tx power if in loose scheme */ |
386 | if (is_loose_coex()) | 388 | if (is_loose_coex()) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 16bbdcc8627a..4d3c978b5c76 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -1007,6 +1007,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
1007 | if (ret) | 1007 | if (ret) |
1008 | goto out; | 1008 | goto out; |
1009 | 1009 | ||
1010 | ret = iwl_mvm_power_update_mode(mvm, vif); | ||
1011 | if (ret) | ||
1012 | goto out; | ||
1013 | |||
1010 | /* must be last -- this switches firmware state */ | 1014 | /* must be last -- this switches firmware state */ |
1011 | ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, | 1015 | ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, |
1012 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); | 1016 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); |
@@ -1214,6 +1218,26 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1214 | iwl_free_resp(&cmd); | 1218 | iwl_free_resp(&cmd); |
1215 | } | 1219 | } |
1216 | 1220 | ||
1221 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) | ||
1222 | { | ||
1223 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1224 | const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN]; | ||
1225 | u32 len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
1226 | u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset; | ||
1227 | |||
1228 | if (!mvm->store_d3_resume_sram) | ||
1229 | return; | ||
1230 | |||
1231 | if (!mvm->d3_resume_sram) { | ||
1232 | mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL); | ||
1233 | if (!mvm->d3_resume_sram) | ||
1234 | return; | ||
1235 | } | ||
1236 | |||
1237 | iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len); | ||
1238 | #endif | ||
1239 | } | ||
1240 | |||
1217 | int iwl_mvm_resume(struct ieee80211_hw *hw) | 1241 | int iwl_mvm_resume(struct ieee80211_hw *hw) |
1218 | { | 1242 | { |
1219 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1243 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
@@ -1245,6 +1269,9 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) | |||
1245 | goto out_unlock; | 1269 | goto out_unlock; |
1246 | } | 1270 | } |
1247 | 1271 | ||
1272 | /* query SRAM first in case we want event logging */ | ||
1273 | iwl_mvm_read_d3_sram(mvm); | ||
1274 | |||
1248 | iwl_mvm_query_wakeup_reasons(mvm, vif); | 1275 | iwl_mvm_query_wakeup_reasons(mvm, vif); |
1249 | 1276 | ||
1250 | out_unlock: | 1277 | out_unlock: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 2053dccefcd6..69e0806075a2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -145,15 +145,18 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | |||
145 | char *buf; | 145 | char *buf; |
146 | u8 *ptr; | 146 | u8 *ptr; |
147 | 147 | ||
148 | if (!mvm->ucode_loaded) | ||
149 | return -EINVAL; | ||
150 | |||
148 | /* default is to dump the entire data segment */ | 151 | /* default is to dump the entire data segment */ |
149 | if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { | 152 | if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { |
150 | mvm->dbgfs_sram_offset = 0x800000; | ||
151 | if (!mvm->ucode_loaded) | ||
152 | return -EINVAL; | ||
153 | img = &mvm->fw->img[mvm->cur_ucode]; | 153 | img = &mvm->fw->img[mvm->cur_ucode]; |
154 | mvm->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; | 154 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; |
155 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
156 | } else { | ||
157 | ofs = mvm->dbgfs_sram_offset; | ||
158 | len = mvm->dbgfs_sram_len; | ||
155 | } | 159 | } |
156 | len = mvm->dbgfs_sram_len; | ||
157 | 160 | ||
158 | bufsz = len * 4 + 256; | 161 | bufsz = len * 4 + 256; |
159 | buf = kzalloc(bufsz, GFP_KERNEL); | 162 | buf = kzalloc(bufsz, GFP_KERNEL); |
@@ -167,12 +170,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | |||
167 | } | 170 | } |
168 | 171 | ||
169 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len); | 172 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len); |
170 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | 173 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", ofs); |
171 | mvm->dbgfs_sram_offset); | ||
172 | 174 | ||
173 | iwl_trans_read_mem_bytes(mvm->trans, | 175 | iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len); |
174 | mvm->dbgfs_sram_offset, | ||
175 | ptr, len); | ||
176 | for (ofs = 0; ofs < len; ofs += 16) { | 176 | for (ofs = 0; ofs < len; ofs += 16) { |
177 | pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs); | 177 | pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs); |
178 | hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos, | 178 | 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, | |||
300 | return count; | 300 | return count; |
301 | } | 301 | } |
302 | 302 | ||
303 | static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | ||
304 | struct ieee80211_vif *vif, | ||
305 | enum iwl_dbgfs_pm_mask param, int val) | ||
306 | { | ||
307 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
308 | struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm; | ||
309 | |||
310 | dbgfs_pm->mask |= param; | ||
311 | |||
312 | switch (param) { | ||
313 | case MVM_DEBUGFS_PM_KEEP_ALIVE: { | ||
314 | struct ieee80211_hw *hw = mvm->hw; | ||
315 | int dtimper = hw->conf.ps_dtim_period ?: 1; | ||
316 | int dtimper_msec = dtimper * vif->bss_conf.beacon_int; | ||
317 | |||
318 | IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val); | ||
319 | if (val * MSEC_PER_SEC < 3 * dtimper_msec) { | ||
320 | IWL_WARN(mvm, | ||
321 | "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n", | ||
322 | val * MSEC_PER_SEC, 3 * dtimper_msec); | ||
323 | } | ||
324 | dbgfs_pm->keep_alive_seconds = val; | ||
325 | break; | ||
326 | } | ||
327 | case MVM_DEBUGFS_PM_SKIP_OVER_DTIM: | ||
328 | IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n", | ||
329 | val ? "enabled" : "disabled"); | ||
330 | dbgfs_pm->skip_over_dtim = val; | ||
331 | break; | ||
332 | case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS: | ||
333 | IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val); | ||
334 | dbgfs_pm->skip_dtim_periods = val; | ||
335 | break; | ||
336 | case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT: | ||
337 | IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val); | ||
338 | dbgfs_pm->rx_data_timeout = val; | ||
339 | break; | ||
340 | case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT: | ||
341 | IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val); | ||
342 | dbgfs_pm->tx_data_timeout = val; | ||
343 | break; | ||
344 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: | ||
345 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); | ||
346 | dbgfs_pm->disable_power_off = val; | ||
347 | break; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | static ssize_t iwl_dbgfs_pm_params_write(struct file *file, | ||
352 | const char __user *user_buf, | ||
353 | size_t count, loff_t *ppos) | ||
354 | { | ||
355 | struct ieee80211_vif *vif = file->private_data; | ||
356 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
357 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; | ||
358 | enum iwl_dbgfs_pm_mask param; | ||
359 | char buf[32] = {}; | ||
360 | int val; | ||
361 | int ret; | ||
362 | |||
363 | if (copy_from_user(buf, user_buf, sizeof(buf))) | ||
364 | return -EFAULT; | ||
365 | |||
366 | if (!strncmp("keep_alive=", buf, 11)) { | ||
367 | if (sscanf(buf + 11, "%d", &val) != 1) | ||
368 | return -EINVAL; | ||
369 | param = MVM_DEBUGFS_PM_KEEP_ALIVE; | ||
370 | } else if (!strncmp("skip_over_dtim=", buf, 15)) { | ||
371 | if (sscanf(buf + 15, "%d", &val) != 1) | ||
372 | return -EINVAL; | ||
373 | param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM; | ||
374 | } else if (!strncmp("skip_dtim_periods=", buf, 18)) { | ||
375 | if (sscanf(buf + 18, "%d", &val) != 1) | ||
376 | return -EINVAL; | ||
377 | param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS; | ||
378 | } else if (!strncmp("rx_data_timeout=", buf, 16)) { | ||
379 | if (sscanf(buf + 16, "%d", &val) != 1) | ||
380 | return -EINVAL; | ||
381 | param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT; | ||
382 | } else if (!strncmp("tx_data_timeout=", buf, 16)) { | ||
383 | if (sscanf(buf + 16, "%d", &val) != 1) | ||
384 | return -EINVAL; | ||
385 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; | ||
386 | } else if (!strncmp("disable_power_off=", buf, 18)) { | ||
387 | if (sscanf(buf + 18, "%d", &val) != 1) | ||
388 | return -EINVAL; | ||
389 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; | ||
390 | } else { | ||
391 | return -EINVAL; | ||
392 | } | ||
393 | |||
394 | mutex_lock(&mvm->mutex); | ||
395 | iwl_dbgfs_update_pm(mvm, vif, param, val); | ||
396 | ret = iwl_mvm_power_update_mode(mvm, vif); | ||
397 | mutex_unlock(&mvm->mutex); | ||
398 | |||
399 | return ret ?: count; | ||
400 | } | ||
401 | |||
402 | static ssize_t iwl_dbgfs_pm_params_read(struct file *file, | ||
403 | char __user *user_buf, | ||
404 | size_t count, loff_t *ppos) | ||
405 | { | ||
406 | struct ieee80211_vif *vif = file->private_data; | ||
407 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
408 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; | ||
409 | struct iwl_powertable_cmd cmd = {}; | ||
410 | char buf[256]; | ||
411 | int bufsz = sizeof(buf); | ||
412 | int pos = 0; | ||
413 | |||
414 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | ||
415 | |||
416 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | ||
417 | (cmd.flags & | ||
418 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | ||
419 | 0 : 1); | ||
420 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", | ||
421 | le32_to_cpu(cmd.skip_dtim_periods)); | ||
422 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | ||
423 | iwlmvm_mod_params.power_scheme); | ||
424 | pos += scnprintf(buf+pos, bufsz-pos, "flags = %d\n", | ||
425 | le16_to_cpu(cmd.flags)); | ||
426 | pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", | ||
427 | cmd.keep_alive_seconds); | ||
428 | |||
429 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
430 | pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", | ||
431 | (cmd.flags & | ||
432 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? | ||
433 | 1 : 0); | ||
434 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", | ||
435 | le32_to_cpu(cmd.rx_data_timeout)); | ||
436 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", | ||
437 | le32_to_cpu(cmd.tx_data_timeout)); | ||
438 | } | ||
439 | |||
440 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
441 | } | ||
442 | |||
303 | static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | 443 | static ssize_t iwl_dbgfs_mac_params_read(struct file *file, |
304 | char __user *user_buf, | 444 | char __user *user_buf, |
305 | size_t count, loff_t *ppos) | 445 | size_t count, loff_t *ppos) |
@@ -481,6 +621,255 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | |||
481 | return count; | 621 | return count; |
482 | } | 622 | } |
483 | 623 | ||
624 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, | ||
625 | enum iwl_dbgfs_bf_mask param, int value) | ||
626 | { | ||
627 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
628 | struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; | ||
629 | |||
630 | dbgfs_bf->mask |= param; | ||
631 | |||
632 | switch (param) { | ||
633 | case MVM_DEBUGFS_BF_ENERGY_DELTA: | ||
634 | dbgfs_bf->bf_energy_delta = value; | ||
635 | break; | ||
636 | case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA: | ||
637 | dbgfs_bf->bf_roaming_energy_delta = value; | ||
638 | break; | ||
639 | case MVM_DEBUGFS_BF_ROAMING_STATE: | ||
640 | dbgfs_bf->bf_roaming_state = value; | ||
641 | break; | ||
642 | case MVM_DEBUGFS_BF_TEMPERATURE_DELTA: | ||
643 | dbgfs_bf->bf_temperature_delta = value; | ||
644 | break; | ||
645 | case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: | ||
646 | dbgfs_bf->bf_enable_beacon_filter = value; | ||
647 | break; | ||
648 | case MVM_DEBUGFS_BF_DEBUG_FLAG: | ||
649 | dbgfs_bf->bf_debug_flag = value; | ||
650 | break; | ||
651 | case MVM_DEBUGFS_BF_ESCAPE_TIMER: | ||
652 | dbgfs_bf->bf_escape_timer = value; | ||
653 | break; | ||
654 | case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT: | ||
655 | dbgfs_bf->ba_enable_beacon_abort = value; | ||
656 | break; | ||
657 | case MVM_DEBUGFS_BA_ESCAPE_TIMER: | ||
658 | dbgfs_bf->ba_escape_timer = value; | ||
659 | break; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | static ssize_t iwl_dbgfs_bf_params_write(struct file *file, | ||
664 | const char __user *user_buf, | ||
665 | size_t count, loff_t *ppos) | ||
666 | { | ||
667 | struct ieee80211_vif *vif = file->private_data; | ||
668 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
669 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; | ||
670 | enum iwl_dbgfs_bf_mask param; | ||
671 | char buf[256]; | ||
672 | int buf_size; | ||
673 | int value; | ||
674 | int ret = 0; | ||
675 | |||
676 | memset(buf, 0, sizeof(buf)); | ||
677 | buf_size = min(count, sizeof(buf) - 1); | ||
678 | if (copy_from_user(buf, user_buf, buf_size)) | ||
679 | return -EFAULT; | ||
680 | |||
681 | if (!strncmp("bf_energy_delta=", buf, 16)) { | ||
682 | if (sscanf(buf+16, "%d", &value) != 1) | ||
683 | return -EINVAL; | ||
684 | if (value < IWL_BF_ENERGY_DELTA_MIN || | ||
685 | value > IWL_BF_ENERGY_DELTA_MAX) | ||
686 | return -EINVAL; | ||
687 | param = MVM_DEBUGFS_BF_ENERGY_DELTA; | ||
688 | } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) { | ||
689 | if (sscanf(buf+24, "%d", &value) != 1) | ||
690 | return -EINVAL; | ||
691 | if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN || | ||
692 | value > IWL_BF_ROAMING_ENERGY_DELTA_MAX) | ||
693 | return -EINVAL; | ||
694 | param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA; | ||
695 | } else if (!strncmp("bf_roaming_state=", buf, 17)) { | ||
696 | if (sscanf(buf+17, "%d", &value) != 1) | ||
697 | return -EINVAL; | ||
698 | if (value < IWL_BF_ROAMING_STATE_MIN || | ||
699 | value > IWL_BF_ROAMING_STATE_MAX) | ||
700 | return -EINVAL; | ||
701 | param = MVM_DEBUGFS_BF_ROAMING_STATE; | ||
702 | } else if (!strncmp("bf_temperature_delta=", buf, 21)) { | ||
703 | if (sscanf(buf+21, "%d", &value) != 1) | ||
704 | return -EINVAL; | ||
705 | if (value < IWL_BF_TEMPERATURE_DELTA_MIN || | ||
706 | value > IWL_BF_TEMPERATURE_DELTA_MAX) | ||
707 | return -EINVAL; | ||
708 | param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA; | ||
709 | } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { | ||
710 | if (sscanf(buf+24, "%d", &value) != 1) | ||
711 | return -EINVAL; | ||
712 | if (value < 0 || value > 1) | ||
713 | return -EINVAL; | ||
714 | param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER; | ||
715 | } else if (!strncmp("bf_debug_flag=", buf, 14)) { | ||
716 | if (sscanf(buf+14, "%d", &value) != 1) | ||
717 | return -EINVAL; | ||
718 | if (value < 0 || value > 1) | ||
719 | return -EINVAL; | ||
720 | param = MVM_DEBUGFS_BF_DEBUG_FLAG; | ||
721 | } else if (!strncmp("bf_escape_timer=", buf, 16)) { | ||
722 | if (sscanf(buf+16, "%d", &value) != 1) | ||
723 | return -EINVAL; | ||
724 | if (value < IWL_BF_ESCAPE_TIMER_MIN || | ||
725 | value > IWL_BF_ESCAPE_TIMER_MAX) | ||
726 | return -EINVAL; | ||
727 | param = MVM_DEBUGFS_BF_ESCAPE_TIMER; | ||
728 | } else if (!strncmp("ba_escape_timer=", buf, 16)) { | ||
729 | if (sscanf(buf+16, "%d", &value) != 1) | ||
730 | return -EINVAL; | ||
731 | if (value < IWL_BA_ESCAPE_TIMER_MIN || | ||
732 | value > IWL_BA_ESCAPE_TIMER_MAX) | ||
733 | return -EINVAL; | ||
734 | param = MVM_DEBUGFS_BA_ESCAPE_TIMER; | ||
735 | } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) { | ||
736 | if (sscanf(buf+23, "%d", &value) != 1) | ||
737 | return -EINVAL; | ||
738 | if (value < 0 || value > 1) | ||
739 | return -EINVAL; | ||
740 | param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT; | ||
741 | } else { | ||
742 | return -EINVAL; | ||
743 | } | ||
744 | |||
745 | mutex_lock(&mvm->mutex); | ||
746 | iwl_dbgfs_update_bf(vif, param, value); | ||
747 | if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) { | ||
748 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | ||
749 | } else { | ||
750 | if (mvmvif->bf_enabled) | ||
751 | ret = iwl_mvm_enable_beacon_filter(mvm, vif); | ||
752 | else | ||
753 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | ||
754 | } | ||
755 | mutex_unlock(&mvm->mutex); | ||
756 | |||
757 | return ret ?: count; | ||
758 | } | ||
759 | |||
760 | static ssize_t iwl_dbgfs_bf_params_read(struct file *file, | ||
761 | char __user *user_buf, | ||
762 | size_t count, loff_t *ppos) | ||
763 | { | ||
764 | struct ieee80211_vif *vif = file->private_data; | ||
765 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
766 | char buf[256]; | ||
767 | int pos = 0; | ||
768 | const size_t bufsz = sizeof(buf); | ||
769 | struct iwl_beacon_filter_cmd cmd = { | ||
770 | .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, | ||
771 | .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, | ||
772 | .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, | ||
773 | .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, | ||
774 | .bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT, | ||
775 | .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, | ||
776 | .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), | ||
777 | .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT), | ||
778 | .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT, | ||
779 | }; | ||
780 | |||
781 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | ||
782 | if (mvmvif->bf_enabled) | ||
783 | cmd.bf_enable_beacon_filter = 1; | ||
784 | else | ||
785 | cmd.bf_enable_beacon_filter = 0; | ||
786 | |||
787 | pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", | ||
788 | cmd.bf_energy_delta); | ||
789 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", | ||
790 | cmd.bf_roaming_energy_delta); | ||
791 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", | ||
792 | cmd.bf_roaming_state); | ||
793 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n", | ||
794 | cmd.bf_temperature_delta); | ||
795 | pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", | ||
796 | cmd.bf_enable_beacon_filter); | ||
797 | pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", | ||
798 | cmd.bf_debug_flag); | ||
799 | pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", | ||
800 | cmd.bf_escape_timer); | ||
801 | pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", | ||
802 | cmd.ba_escape_timer); | ||
803 | pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", | ||
804 | cmd.ba_enable_beacon_abort); | ||
805 | |||
806 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
807 | } | ||
808 | |||
809 | #ifdef CONFIG_PM_SLEEP | ||
810 | static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, | ||
811 | const char __user *user_buf, | ||
812 | size_t count, loff_t *ppos) | ||
813 | { | ||
814 | struct iwl_mvm *mvm = file->private_data; | ||
815 | char buf[8] = {}; | ||
816 | int store; | ||
817 | |||
818 | if (copy_from_user(buf, user_buf, sizeof(buf))) | ||
819 | return -EFAULT; | ||
820 | |||
821 | if (sscanf(buf, "%d", &store) != 1) | ||
822 | return -EINVAL; | ||
823 | |||
824 | mvm->store_d3_resume_sram = store; | ||
825 | |||
826 | return count; | ||
827 | } | ||
828 | |||
829 | static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, | ||
830 | size_t count, loff_t *ppos) | ||
831 | { | ||
832 | struct iwl_mvm *mvm = file->private_data; | ||
833 | const struct fw_img *img; | ||
834 | int ofs, len, pos = 0; | ||
835 | size_t bufsz, ret; | ||
836 | char *buf; | ||
837 | u8 *ptr = mvm->d3_resume_sram; | ||
838 | |||
839 | img = &mvm->fw->img[IWL_UCODE_WOWLAN]; | ||
840 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | ||
841 | |||
842 | bufsz = len * 4 + 256; | ||
843 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
844 | if (!buf) | ||
845 | return -ENOMEM; | ||
846 | |||
847 | pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n", | ||
848 | mvm->store_d3_resume_sram ? "en" : "dis"); | ||
849 | |||
850 | if (ptr) { | ||
851 | for (ofs = 0; ofs < len; ofs += 16) { | ||
852 | pos += scnprintf(buf + pos, bufsz - pos, | ||
853 | "0x%.4x ", ofs); | ||
854 | hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos, | ||
855 | bufsz - pos, false); | ||
856 | pos += strlen(buf + pos); | ||
857 | if (bufsz - pos > 0) | ||
858 | buf[pos++] = '\n'; | ||
859 | } | ||
860 | } else { | ||
861 | pos += scnprintf(buf + pos, bufsz - pos, | ||
862 | "(no data captured)\n"); | ||
863 | } | ||
864 | |||
865 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
866 | |||
867 | kfree(buf); | ||
868 | |||
869 | return ret; | ||
870 | } | ||
871 | #endif | ||
872 | |||
484 | #define MVM_DEBUGFS_READ_FILE_OPS(name) \ | 873 | #define MVM_DEBUGFS_READ_FILE_OPS(name) \ |
485 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 874 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
486 | .read = iwl_dbgfs_##name##_read, \ | 875 | .read = iwl_dbgfs_##name##_read, \ |
@@ -524,9 +913,14 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif); | |||
524 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); | 913 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); |
525 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); | 914 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); |
526 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); | 915 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); |
916 | #ifdef CONFIG_PM_SLEEP | ||
917 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); | ||
918 | #endif | ||
527 | 919 | ||
528 | /* Interface specific debugfs entries */ | 920 | /* Interface specific debugfs entries */ |
529 | MVM_DEBUGFS_READ_FILE_OPS(mac_params); | 921 | MVM_DEBUGFS_READ_FILE_OPS(mac_params); |
922 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params); | ||
923 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params); | ||
530 | 924 | ||
531 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | 925 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) |
532 | { | 926 | { |
@@ -542,6 +936,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
542 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); | 936 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); |
543 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); | 937 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); |
544 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 938 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
939 | #ifdef CONFIG_PM_SLEEP | ||
940 | MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | ||
941 | #endif | ||
545 | 942 | ||
546 | /* | 943 | /* |
547 | * Create a symlink with mac80211. It will be removed when mac80211 | 944 | * 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) | |||
577 | return; | 974 | return; |
578 | } | 975 | } |
579 | 976 | ||
977 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && | ||
978 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p) | ||
979 | MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | | ||
980 | S_IRUSR); | ||
981 | |||
580 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, | 982 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, |
581 | S_IRUSR); | 983 | S_IRUSR); |
582 | 984 | ||
985 | if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && | ||
986 | mvmvif == mvm->bf_allowed_vif) | ||
987 | MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, | ||
988 | S_IRUSR | S_IWUSR); | ||
989 | |||
583 | /* | 990 | /* |
584 | * Create symlink for convenience pointing to interface specific | 991 | * Create symlink for convenience pointing to interface specific |
585 | * debugfs entries for the driver. For example, under | 992 | * debugfs entries for the driver. For example, under |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index 51e015d1dfb2..6f8b2c16ae17 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
@@ -75,13 +75,15 @@ enum iwl_d3_wakeup_flags { | |||
75 | * struct iwl_d3_manager_config - D3 manager configuration command | 75 | * struct iwl_d3_manager_config - D3 manager configuration command |
76 | * @min_sleep_time: minimum sleep time (in usec) | 76 | * @min_sleep_time: minimum sleep time (in usec) |
77 | * @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags | 77 | * @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags |
78 | * @wakeup_host_timer: force wakeup after this many seconds | ||
78 | * | 79 | * |
79 | * The structure is used for the D3_CONFIG_CMD command. | 80 | * The structure is used for the D3_CONFIG_CMD command. |
80 | */ | 81 | */ |
81 | struct iwl_d3_manager_config { | 82 | struct iwl_d3_manager_config { |
82 | __le32 min_sleep_time; | 83 | __le32 min_sleep_time; |
83 | __le32 wakeup_flags; | 84 | __le32 wakeup_flags; |
84 | } __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_3 */ | 85 | __le32 wakeup_host_timer; |
86 | } __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_4 */ | ||
85 | 87 | ||
86 | 88 | ||
87 | /* TODO: OFFLOADS_QUERY_API_S_VER_1 */ | 89 | /* TODO: OFFLOADS_QUERY_API_S_VER_1 */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 81fe45f46be7..d8e19290b0f3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -101,20 +101,107 @@ enum iwl_power_flags { | |||
101 | * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to | 101 | * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to |
102 | * PSM transition - legacy PM | 102 | * PSM transition - legacy PM |
103 | * @sleep_interval: not in use | 103 | * @sleep_interval: not in use |
104 | * @keep_alive_beacons: not in use | 104 | * @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag |
105 | * is set. For example, if it is required to skip over | ||
106 | * one DTIM, this value need to be set to 2 (DTIM periods). | ||
105 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. | 107 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. |
106 | * Default: 80dbm | 108 | * Default: 80dbm |
107 | */ | 109 | */ |
108 | struct iwl_powertable_cmd { | 110 | struct iwl_powertable_cmd { |
109 | /* PM_POWER_TABLE_CMD_API_S_VER_5 */ | 111 | /* PM_POWER_TABLE_CMD_API_S_VER_6 */ |
110 | __le16 flags; | 112 | __le16 flags; |
111 | u8 keep_alive_seconds; | 113 | u8 keep_alive_seconds; |
112 | u8 debug_flags; | 114 | u8 debug_flags; |
113 | __le32 rx_data_timeout; | 115 | __le32 rx_data_timeout; |
114 | __le32 tx_data_timeout; | 116 | __le32 tx_data_timeout; |
115 | __le32 sleep_interval[IWL_POWER_VEC_SIZE]; | 117 | __le32 sleep_interval[IWL_POWER_VEC_SIZE]; |
116 | __le32 keep_alive_beacons; | 118 | __le32 skip_dtim_periods; |
117 | __le32 lprx_rssi_threshold; | 119 | __le32 lprx_rssi_threshold; |
118 | } __packed; | 120 | } __packed; |
119 | 121 | ||
122 | /** | ||
123 | * struct iwl_beacon_filter_cmd | ||
124 | * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) | ||
125 | * @id_and_color: MAC contex identifier | ||
126 | * @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon | ||
127 | * to driver if delta in Energy values calculated for this and last | ||
128 | * passed beacon is greater than this threshold. Zero value means that | ||
129 | * the Energy change is ignored for beacon filtering, and beacon will | ||
130 | * not be forced to be sent to driver regardless of this delta. Typical | ||
131 | * energy delta 5dB. | ||
132 | * @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state. | ||
133 | * Send beacon to driver if delta in Energy values calculated for this | ||
134 | * and last passed beacon is greater than this threshold. Zero value | ||
135 | * means that the Energy change is ignored for beacon filtering while in | ||
136 | * Roaming state, typical energy delta 1dB. | ||
137 | * @bf_roaming_state: Used for RSSI filtering. If absolute Energy values | ||
138 | * calculated for current beacon is less than the threshold, use | ||
139 | * Roaming Energy Delta Threshold, otherwise use normal Energy Delta | ||
140 | * Threshold. Typical energy threshold is -72dBm. | ||
141 | * @bf_temperature_delta: Send Beacon to driver if delta in temperature values | ||
142 | * calculated for this and the last passed beacon is greater than this | ||
143 | * threshold. Zero value means that the temperature changeis ignored for | ||
144 | * beacon filtering; beacons will not be forced to be sent to driver | ||
145 | * regardless of whether its temerature has been changed. | ||
146 | * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled. | ||
147 | * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed | ||
148 | * for a specific period of time. Units: Beacons. | ||
149 | * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed | ||
150 | * for a longer period of time then this escape-timeout. Units: Beacons. | ||
151 | * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. | ||
152 | */ | ||
153 | struct iwl_beacon_filter_cmd { | ||
154 | u8 bf_energy_delta; | ||
155 | u8 bf_roaming_energy_delta; | ||
156 | u8 bf_roaming_state; | ||
157 | u8 bf_temperature_delta; | ||
158 | u8 bf_enable_beacon_filter; | ||
159 | u8 bf_debug_flag; | ||
160 | __le16 reserved1; | ||
161 | __le32 bf_escape_timer; | ||
162 | __le32 ba_escape_timer; | ||
163 | u8 ba_enable_beacon_abort; | ||
164 | u8 reserved2[3]; | ||
165 | } __packed; | ||
166 | |||
167 | /* Beacon filtering and beacon abort */ | ||
168 | #define IWL_BF_ENERGY_DELTA_DEFAULT 5 | ||
169 | #define IWL_BF_ENERGY_DELTA_MAX 255 | ||
170 | #define IWL_BF_ENERGY_DELTA_MIN 0 | ||
171 | |||
172 | #define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1 | ||
173 | #define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255 | ||
174 | #define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0 | ||
175 | |||
176 | #define IWL_BF_ROAMING_STATE_DEFAULT 72 | ||
177 | #define IWL_BF_ROAMING_STATE_MAX 255 | ||
178 | #define IWL_BF_ROAMING_STATE_MIN 0 | ||
179 | |||
180 | #define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5 | ||
181 | #define IWL_BF_TEMPERATURE_DELTA_MAX 255 | ||
182 | #define IWL_BF_TEMPERATURE_DELTA_MIN 0 | ||
183 | |||
184 | #define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1 | ||
185 | |||
186 | #define IWL_BF_DEBUG_FLAG_DEFAULT 0 | ||
187 | |||
188 | #define IWL_BF_ESCAPE_TIMER_DEFAULT 50 | ||
189 | #define IWL_BF_ESCAPE_TIMER_MAX 1024 | ||
190 | #define IWL_BF_ESCAPE_TIMER_MIN 0 | ||
191 | |||
192 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 3 | ||
193 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 | ||
194 | #define IWL_BA_ESCAPE_TIMER_MIN 0 | ||
195 | |||
196 | #define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 | ||
197 | |||
198 | #define IWL_BF_CMD_CONFIG_DEFAULTS \ | ||
199 | .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \ | ||
200 | .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \ | ||
201 | .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \ | ||
202 | .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \ | ||
203 | .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \ | ||
204 | .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \ | ||
205 | .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT) | ||
206 | |||
120 | #endif | 207 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 007a93b25bd7..6994232f5726 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -134,6 +134,7 @@ enum iwl_tx_flags { | |||
134 | #define TX_CMD_SEC_WEP 0x01 | 134 | #define TX_CMD_SEC_WEP 0x01 |
135 | #define TX_CMD_SEC_CCM 0x02 | 135 | #define TX_CMD_SEC_CCM 0x02 |
136 | #define TX_CMD_SEC_TKIP 0x03 | 136 | #define TX_CMD_SEC_TKIP 0x03 |
137 | #define TX_CMD_SEC_MSK 0x07 | ||
137 | #define TX_CMD_SEC_WEP_KEY_IDX_POS 6 | 138 | #define TX_CMD_SEC_WEP_KEY_IDX_POS 6 |
138 | #define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0 | 139 | #define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0 |
139 | #define TX_CMD_SEC_KEY128 0x08 | 140 | #define TX_CMD_SEC_KEY128 0x08 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 191dcae8ba47..cbfb3beae783 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -139,6 +139,9 @@ enum { | |||
139 | /* Power */ | 139 | /* Power */ |
140 | POWER_TABLE_CMD = 0x77, | 140 | POWER_TABLE_CMD = 0x77, |
141 | 141 | ||
142 | /* Thermal Throttling*/ | ||
143 | REPLY_THERMAL_MNG_BACKOFF = 0x7e, | ||
144 | |||
142 | /* Scanning */ | 145 | /* Scanning */ |
143 | SCAN_REQUEST_CMD = 0x80, | 146 | SCAN_REQUEST_CMD = 0x80, |
144 | SCAN_ABORT_CMD = 0x81, | 147 | SCAN_ABORT_CMD = 0x81, |
@@ -161,6 +164,8 @@ enum { | |||
161 | CARD_STATE_CMD = 0xa0, | 164 | CARD_STATE_CMD = 0xa0, |
162 | CARD_STATE_NOTIFICATION = 0xa1, | 165 | CARD_STATE_NOTIFICATION = 0xa1, |
163 | 166 | ||
167 | MISSED_BEACONS_NOTIFICATION = 0xa2, | ||
168 | |||
164 | REPLY_RX_PHY_CMD = 0xc0, | 169 | REPLY_RX_PHY_CMD = 0xc0, |
165 | REPLY_RX_MPDU_CMD = 0xc1, | 170 | REPLY_RX_MPDU_CMD = 0xc1, |
166 | BA_NOTIF = 0xc5, | 171 | BA_NOTIF = 0xc5, |
@@ -170,9 +175,13 @@ enum { | |||
170 | BT_COEX_PROT_ENV = 0xcd, | 175 | BT_COEX_PROT_ENV = 0xcd, |
171 | BT_PROFILE_NOTIFICATION = 0xce, | 176 | BT_PROFILE_NOTIFICATION = 0xce, |
172 | 177 | ||
178 | REPLY_BEACON_FILTERING_CMD = 0xd2, | ||
179 | |||
173 | REPLY_DEBUG_CMD = 0xf0, | 180 | REPLY_DEBUG_CMD = 0xf0, |
174 | DEBUG_LOG_MSG = 0xf7, | 181 | DEBUG_LOG_MSG = 0xf7, |
175 | 182 | ||
183 | MCAST_FILTER_CMD = 0xd0, | ||
184 | |||
176 | /* D3 commands/notifications */ | 185 | /* D3 commands/notifications */ |
177 | D3_CONFIG_CMD = 0xd3, | 186 | D3_CONFIG_CMD = 0xd3, |
178 | PROT_OFFLOAD_CONFIG_CMD = 0xd4, | 187 | PROT_OFFLOAD_CONFIG_CMD = 0xd4, |
@@ -936,6 +945,24 @@ struct iwl_card_state_notif { | |||
936 | } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */ | 945 | } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */ |
937 | 946 | ||
938 | /** | 947 | /** |
948 | * struct iwl_missed_beacons_notif - information on missed beacons | ||
949 | * ( MISSED_BEACONS_NOTIFICATION = 0xa2 ) | ||
950 | * @mac_id: interface ID | ||
951 | * @consec_missed_beacons_since_last_rx: number of consecutive missed | ||
952 | * beacons since last RX. | ||
953 | * @consec_missed_beacons: number of consecutive missed beacons | ||
954 | * @num_expected_beacons: | ||
955 | * @num_recvd_beacons: | ||
956 | */ | ||
957 | struct iwl_missed_beacons_notif { | ||
958 | __le32 mac_id; | ||
959 | __le32 consec_missed_beacons_since_last_rx; | ||
960 | __le32 consec_missed_beacons; | ||
961 | __le32 num_expected_beacons; | ||
962 | __le32 num_recvd_beacons; | ||
963 | } __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */ | ||
964 | |||
965 | /** | ||
939 | * struct iwl_set_calib_default_cmd - set default value for calibration. | 966 | * struct iwl_set_calib_default_cmd - set default value for calibration. |
940 | * ( SET_CALIB_DEFAULT_CMD = 0x8e ) | 967 | * ( SET_CALIB_DEFAULT_CMD = 0x8e ) |
941 | * @calib_index: the calibration to set value for | 968 | * @calib_index: the calibration to set value for |
@@ -948,4 +975,237 @@ struct iwl_set_calib_default_cmd { | |||
948 | u8 data[0]; | 975 | u8 data[0]; |
949 | } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */ | 976 | } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */ |
950 | 977 | ||
978 | #define MAX_PORT_ID_NUM 2 | ||
979 | |||
980 | /** | ||
981 | * struct iwl_mcast_filter_cmd - configure multicast filter. | ||
982 | * @filter_own: Set 1 to filter out multicast packets sent by station itself | ||
983 | * @port_id: Multicast MAC addresses array specifier. This is a strange way | ||
984 | * to identify network interface adopted in host-device IF. | ||
985 | * It is used by FW as index in array of addresses. This array has | ||
986 | * MAX_PORT_ID_NUM members. | ||
987 | * @count: Number of MAC addresses in the array | ||
988 | * @pass_all: Set 1 to pass all multicast packets. | ||
989 | * @bssid: current association BSSID. | ||
990 | * @addr_list: Place holder for array of MAC addresses. | ||
991 | * IMPORTANT: add padding if necessary to ensure DWORD alignment. | ||
992 | */ | ||
993 | struct iwl_mcast_filter_cmd { | ||
994 | u8 filter_own; | ||
995 | u8 port_id; | ||
996 | u8 count; | ||
997 | u8 pass_all; | ||
998 | u8 bssid[6]; | ||
999 | u8 reserved[2]; | ||
1000 | u8 addr_list[0]; | ||
1001 | } __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */ | ||
1002 | |||
1003 | struct mvm_statistics_dbg { | ||
1004 | __le32 burst_check; | ||
1005 | __le32 burst_count; | ||
1006 | __le32 wait_for_silence_timeout_cnt; | ||
1007 | __le32 reserved[3]; | ||
1008 | } __packed; /* STATISTICS_DEBUG_API_S_VER_2 */ | ||
1009 | |||
1010 | struct mvm_statistics_div { | ||
1011 | __le32 tx_on_a; | ||
1012 | __le32 tx_on_b; | ||
1013 | __le32 exec_time; | ||
1014 | __le32 probe_time; | ||
1015 | __le32 rssi_ant; | ||
1016 | __le32 reserved2; | ||
1017 | } __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */ | ||
1018 | |||
1019 | struct mvm_statistics_general_common { | ||
1020 | __le32 temperature; /* radio temperature */ | ||
1021 | __le32 temperature_m; /* radio voltage */ | ||
1022 | struct mvm_statistics_dbg dbg; | ||
1023 | __le32 sleep_time; | ||
1024 | __le32 slots_out; | ||
1025 | __le32 slots_idle; | ||
1026 | __le32 ttl_timestamp; | ||
1027 | struct mvm_statistics_div div; | ||
1028 | __le32 rx_enable_counter; | ||
1029 | /* | ||
1030 | * num_of_sos_states: | ||
1031 | * count the number of times we have to re-tune | ||
1032 | * in order to get out of bad PHY status | ||
1033 | */ | ||
1034 | __le32 num_of_sos_states; | ||
1035 | } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ | ||
1036 | |||
1037 | struct mvm_statistics_rx_non_phy { | ||
1038 | __le32 bogus_cts; /* CTS received when not expecting CTS */ | ||
1039 | __le32 bogus_ack; /* ACK received when not expecting ACK */ | ||
1040 | __le32 non_bssid_frames; /* number of frames with BSSID that | ||
1041 | * doesn't belong to the STA BSSID */ | ||
1042 | __le32 filtered_frames; /* count frames that were dumped in the | ||
1043 | * filtering process */ | ||
1044 | __le32 non_channel_beacons; /* beacons with our bss id but not on | ||
1045 | * our serving channel */ | ||
1046 | __le32 channel_beacons; /* beacons with our bss id and in our | ||
1047 | * serving channel */ | ||
1048 | __le32 num_missed_bcon; /* number of missed beacons */ | ||
1049 | __le32 adc_rx_saturation_time; /* count in 0.8us units the time the | ||
1050 | * ADC was in saturation */ | ||
1051 | __le32 ina_detection_search_time;/* total time (in 0.8us) searched | ||
1052 | * for INA */ | ||
1053 | __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */ | ||
1054 | __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */ | ||
1055 | __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */ | ||
1056 | __le32 interference_data_flag; /* flag for interference data | ||
1057 | * availability. 1 when data is | ||
1058 | * available. */ | ||
1059 | __le32 channel_load; /* counts RX Enable time in uSec */ | ||
1060 | __le32 dsp_false_alarms; /* DSP false alarm (both OFDM | ||
1061 | * and CCK) counter */ | ||
1062 | __le32 beacon_rssi_a; | ||
1063 | __le32 beacon_rssi_b; | ||
1064 | __le32 beacon_rssi_c; | ||
1065 | __le32 beacon_energy_a; | ||
1066 | __le32 beacon_energy_b; | ||
1067 | __le32 beacon_energy_c; | ||
1068 | __le32 num_bt_kills; | ||
1069 | __le32 mac_id; | ||
1070 | __le32 directed_data_mpdu; | ||
1071 | } __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */ | ||
1072 | |||
1073 | struct mvm_statistics_rx_phy { | ||
1074 | __le32 ina_cnt; | ||
1075 | __le32 fina_cnt; | ||
1076 | __le32 plcp_err; | ||
1077 | __le32 crc32_err; | ||
1078 | __le32 overrun_err; | ||
1079 | __le32 early_overrun_err; | ||
1080 | __le32 crc32_good; | ||
1081 | __le32 false_alarm_cnt; | ||
1082 | __le32 fina_sync_err_cnt; | ||
1083 | __le32 sfd_timeout; | ||
1084 | __le32 fina_timeout; | ||
1085 | __le32 unresponded_rts; | ||
1086 | __le32 rxe_frame_limit_overrun; | ||
1087 | __le32 sent_ack_cnt; | ||
1088 | __le32 sent_cts_cnt; | ||
1089 | __le32 sent_ba_rsp_cnt; | ||
1090 | __le32 dsp_self_kill; | ||
1091 | __le32 mh_format_err; | ||
1092 | __le32 re_acq_main_rssi_sum; | ||
1093 | __le32 reserved; | ||
1094 | } __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */ | ||
1095 | |||
1096 | struct mvm_statistics_rx_ht_phy { | ||
1097 | __le32 plcp_err; | ||
1098 | __le32 overrun_err; | ||
1099 | __le32 early_overrun_err; | ||
1100 | __le32 crc32_good; | ||
1101 | __le32 crc32_err; | ||
1102 | __le32 mh_format_err; | ||
1103 | __le32 agg_crc32_good; | ||
1104 | __le32 agg_mpdu_cnt; | ||
1105 | __le32 agg_cnt; | ||
1106 | __le32 unsupport_mcs; | ||
1107 | } __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */ | ||
1108 | |||
1109 | #define MAX_CHAINS 3 | ||
1110 | |||
1111 | struct mvm_statistics_tx_non_phy_agg { | ||
1112 | __le32 ba_timeout; | ||
1113 | __le32 ba_reschedule_frames; | ||
1114 | __le32 scd_query_agg_frame_cnt; | ||
1115 | __le32 scd_query_no_agg; | ||
1116 | __le32 scd_query_agg; | ||
1117 | __le32 scd_query_mismatch; | ||
1118 | __le32 frame_not_ready; | ||
1119 | __le32 underrun; | ||
1120 | __le32 bt_prio_kill; | ||
1121 | __le32 rx_ba_rsp_cnt; | ||
1122 | __s8 txpower[MAX_CHAINS]; | ||
1123 | __s8 reserved; | ||
1124 | __le32 reserved2; | ||
1125 | } __packed; /* STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */ | ||
1126 | |||
1127 | struct mvm_statistics_tx_channel_width { | ||
1128 | __le32 ext_cca_narrow_ch20[1]; | ||
1129 | __le32 ext_cca_narrow_ch40[2]; | ||
1130 | __le32 ext_cca_narrow_ch80[3]; | ||
1131 | __le32 ext_cca_narrow_ch160[4]; | ||
1132 | __le32 last_tx_ch_width_indx; | ||
1133 | __le32 rx_detected_per_ch_width[4]; | ||
1134 | __le32 success_per_ch_width[4]; | ||
1135 | __le32 fail_per_ch_width[4]; | ||
1136 | }; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */ | ||
1137 | |||
1138 | struct mvm_statistics_tx { | ||
1139 | __le32 preamble_cnt; | ||
1140 | __le32 rx_detected_cnt; | ||
1141 | __le32 bt_prio_defer_cnt; | ||
1142 | __le32 bt_prio_kill_cnt; | ||
1143 | __le32 few_bytes_cnt; | ||
1144 | __le32 cts_timeout; | ||
1145 | __le32 ack_timeout; | ||
1146 | __le32 expected_ack_cnt; | ||
1147 | __le32 actual_ack_cnt; | ||
1148 | __le32 dump_msdu_cnt; | ||
1149 | __le32 burst_abort_next_frame_mismatch_cnt; | ||
1150 | __le32 burst_abort_missing_next_frame_cnt; | ||
1151 | __le32 cts_timeout_collision; | ||
1152 | __le32 ack_or_ba_timeout_collision; | ||
1153 | struct mvm_statistics_tx_non_phy_agg agg; | ||
1154 | struct mvm_statistics_tx_channel_width channel_width; | ||
1155 | } __packed; /* STATISTICS_TX_API_S_VER_4 */ | ||
1156 | |||
1157 | |||
1158 | struct mvm_statistics_bt_activity { | ||
1159 | __le32 hi_priority_tx_req_cnt; | ||
1160 | __le32 hi_priority_tx_denied_cnt; | ||
1161 | __le32 lo_priority_tx_req_cnt; | ||
1162 | __le32 lo_priority_tx_denied_cnt; | ||
1163 | __le32 hi_priority_rx_req_cnt; | ||
1164 | __le32 hi_priority_rx_denied_cnt; | ||
1165 | __le32 lo_priority_rx_req_cnt; | ||
1166 | __le32 lo_priority_rx_denied_cnt; | ||
1167 | } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ | ||
1168 | |||
1169 | struct mvm_statistics_general { | ||
1170 | struct mvm_statistics_general_common common; | ||
1171 | __le32 beacon_filtered; | ||
1172 | __le32 missed_beacons; | ||
1173 | __s8 beacon_filter_everage_energy; | ||
1174 | __s8 beacon_filter_reason; | ||
1175 | __s8 beacon_filter_current_energy; | ||
1176 | __s8 beacon_filter_reserved; | ||
1177 | __le32 beacon_filter_delta_time; | ||
1178 | struct mvm_statistics_bt_activity bt_activity; | ||
1179 | } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ | ||
1180 | |||
1181 | struct mvm_statistics_rx { | ||
1182 | struct mvm_statistics_rx_phy ofdm; | ||
1183 | struct mvm_statistics_rx_phy cck; | ||
1184 | struct mvm_statistics_rx_non_phy general; | ||
1185 | struct mvm_statistics_rx_ht_phy ofdm_ht; | ||
1186 | } __packed; /* STATISTICS_RX_API_S_VER_3 */ | ||
1187 | |||
1188 | /* | ||
1189 | * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) | ||
1190 | * | ||
1191 | * By default, uCode issues this notification after receiving a beacon | ||
1192 | * while associated. To disable this behavior, set DISABLE_NOTIF flag in the | ||
1193 | * REPLY_STATISTICS_CMD 0x9c, above. | ||
1194 | * | ||
1195 | * Statistics counters continue to increment beacon after beacon, but are | ||
1196 | * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD | ||
1197 | * 0x9c with CLEAR_STATS bit set (see above). | ||
1198 | * | ||
1199 | * uCode also issues this notification during scans. uCode clears statistics | ||
1200 | * appropriately so that each notification contains statistics for only the | ||
1201 | * one channel that has just been scanned. | ||
1202 | */ | ||
1203 | |||
1204 | struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */ | ||
1205 | __le32 flag; | ||
1206 | struct mvm_statistics_rx rx; | ||
1207 | struct mvm_statistics_tx tx; | ||
1208 | struct mvm_statistics_general general; | ||
1209 | } __packed; | ||
1210 | |||
951 | #endif /* __fw_api_h__ */ | 1211 | #endif /* __fw_api_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index e18c92dd60ec..cd7c0032cc58 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -326,6 +326,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
326 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); | 326 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); |
327 | WARN_ON(ret); | 327 | WARN_ON(ret); |
328 | 328 | ||
329 | /* | ||
330 | * abort after reading the nvm in case RF Kill is on, we will complete | ||
331 | * the init seq later when RF kill will switch to off | ||
332 | */ | ||
333 | if (iwl_mvm_is_radio_killed(mvm)) { | ||
334 | IWL_DEBUG_RF_KILL(mvm, | ||
335 | "jump over all phy activities due to RF kill\n"); | ||
336 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); | ||
337 | return 1; | ||
338 | } | ||
339 | |||
329 | /* Send TX valid antennas before triggering calibrations */ | 340 | /* Send TX valid antennas before triggering calibrations */ |
330 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); | 341 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
331 | if (ret) | 342 | if (ret) |
@@ -388,6 +399,8 @@ out: | |||
388 | int iwl_mvm_up(struct iwl_mvm *mvm) | 399 | int iwl_mvm_up(struct iwl_mvm *mvm) |
389 | { | 400 | { |
390 | int ret, i; | 401 | int ret, i; |
402 | struct ieee80211_channel *chan; | ||
403 | struct cfg80211_chan_def chandef; | ||
391 | 404 | ||
392 | lockdep_assert_held(&mvm->mutex); | 405 | lockdep_assert_held(&mvm->mutex); |
393 | 406 | ||
@@ -400,8 +413,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
400 | ret = iwl_run_init_mvm_ucode(mvm, false); | 413 | ret = iwl_run_init_mvm_ucode(mvm, false); |
401 | if (ret && !iwlmvm_mod_params.init_dbg) { | 414 | if (ret && !iwlmvm_mod_params.init_dbg) { |
402 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); | 415 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); |
416 | /* this can't happen */ | ||
417 | if (WARN_ON(ret > 0)) | ||
418 | ret = -ERFKILL; | ||
403 | goto error; | 419 | goto error; |
404 | } | 420 | } |
421 | /* should stop & start HW since that INIT image just loaded */ | ||
422 | iwl_trans_stop_hw(mvm->trans, false); | ||
423 | ret = iwl_trans_start_hw(mvm->trans); | ||
424 | if (ret) | ||
425 | return ret; | ||
405 | } | 426 | } |
406 | 427 | ||
407 | if (iwlmvm_mod_params.init_dbg) | 428 | if (iwlmvm_mod_params.init_dbg) |
@@ -443,8 +464,22 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
443 | if (ret) | 464 | if (ret) |
444 | goto error; | 465 | goto error; |
445 | 466 | ||
446 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); | 467 | /* Add all the PHY contexts */ |
468 | chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; | ||
469 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); | ||
470 | for (i = 0; i < NUM_PHY_CTX; i++) { | ||
471 | /* | ||
472 | * The channel used here isn't relevant as it's | ||
473 | * going to be overwritten in the other flows. | ||
474 | * For now use the first channel we have. | ||
475 | */ | ||
476 | ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i], | ||
477 | &chandef, 1, 1); | ||
478 | if (ret) | ||
479 | goto error; | ||
480 | } | ||
447 | 481 | ||
482 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); | ||
448 | return 0; | 483 | return 0; |
449 | error: | 484 | error: |
450 | iwl_trans_stop_device(mvm->trans); | 485 | iwl_trans_stop_device(mvm->trans); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index e6eca4d66f6c..b4e8e597d2b7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -227,7 +227,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
227 | .found_vif = false, | 227 | .found_vif = false, |
228 | }; | 228 | }; |
229 | u32 ac; | 229 | u32 ac; |
230 | int ret; | 230 | int ret, i; |
231 | 231 | ||
232 | /* | 232 | /* |
233 | * Allocate a MAC ID and a TSF for this MAC, along with the queues | 233 | * 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, | |||
335 | mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT; | 335 | mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT; |
336 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; | 336 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; |
337 | 337 | ||
338 | for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) | ||
339 | mvmvif->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC; | ||
340 | |||
338 | return 0; | 341 | return 0; |
339 | 342 | ||
340 | exit_fail: | 343 | exit_fail: |
@@ -586,10 +589,12 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm, | |||
586 | */ | 589 | */ |
587 | static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, | 590 | static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, |
588 | struct ieee80211_vif *vif, | 591 | struct ieee80211_vif *vif, |
589 | struct iwl_mac_data_sta *ctxt_sta) | 592 | struct iwl_mac_data_sta *ctxt_sta, |
593 | bool force_assoc_off) | ||
590 | { | 594 | { |
591 | /* We need the dtim_period to set the MAC as associated */ | 595 | /* We need the dtim_period to set the MAC as associated */ |
592 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) { | 596 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period && |
597 | !force_assoc_off) { | ||
593 | u32 dtim_offs; | 598 | u32 dtim_offs; |
594 | 599 | ||
595 | /* | 600 | /* |
@@ -659,7 +664,8 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm, | |||
659 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); | 664 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); |
660 | 665 | ||
661 | /* Fill the data specific for station mode */ | 666 | /* Fill the data specific for station mode */ |
662 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta); | 667 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta, |
668 | action == FW_CTXT_ACTION_ADD); | ||
663 | 669 | ||
664 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 670 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
665 | } | 671 | } |
@@ -677,7 +683,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm, | |||
677 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 683 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
678 | 684 | ||
679 | /* Fill the data specific for station mode */ | 685 | /* Fill the data specific for station mode */ |
680 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta); | 686 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta, |
687 | action == FW_CTXT_ACTION_ADD); | ||
681 | 688 | ||
682 | cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow & | 689 | cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow & |
683 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); | 690 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); |
@@ -1043,3 +1050,28 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
1043 | rate); | 1050 | rate); |
1044 | return 0; | 1051 | return 0; |
1045 | } | 1052 | } |
1053 | |||
1054 | static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, | ||
1055 | struct ieee80211_vif *vif) | ||
1056 | { | ||
1057 | u16 *id = _data; | ||
1058 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
1059 | |||
1060 | if (mvmvif->id == *id) | ||
1061 | ieee80211_beacon_loss(vif); | ||
1062 | } | ||
1063 | |||
1064 | int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | ||
1065 | struct iwl_rx_cmd_buffer *rxb, | ||
1066 | struct iwl_device_cmd *cmd) | ||
1067 | { | ||
1068 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1069 | struct iwl_missed_beacons_notif *missed_beacons = (void *)pkt->data; | ||
1070 | u16 id = (u16)le32_to_cpu(missed_beacons->mac_id); | ||
1071 | |||
1072 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
1073 | IEEE80211_IFACE_ITER_NORMAL, | ||
1074 | iwl_mvm_beacon_loss_iterator, | ||
1075 | &id); | ||
1076 | return 0; | ||
1077 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index dd158ec571fb..dc50020d746d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -127,6 +127,17 @@ static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = { | |||
127 | }; | 127 | }; |
128 | #endif | 128 | #endif |
129 | 129 | ||
130 | static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) | ||
131 | { | ||
132 | int i; | ||
133 | |||
134 | memset(mvm->phy_ctxts, 0, sizeof(mvm->phy_ctxts)); | ||
135 | for (i = 0; i < NUM_PHY_CTX; i++) { | ||
136 | mvm->phy_ctxts[i].id = i; | ||
137 | mvm->phy_ctxts[i].ref = 0; | ||
138 | } | ||
139 | } | ||
140 | |||
130 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 141 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
131 | { | 142 | { |
132 | struct ieee80211_hw *hw = mvm->hw; | 143 | struct ieee80211_hw *hw = mvm->hw; |
@@ -141,7 +152,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
141 | IEEE80211_HW_SUPPORTS_PS | | 152 | IEEE80211_HW_SUPPORTS_PS | |
142 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 153 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
143 | IEEE80211_HW_AMPDU_AGGREGATION | | 154 | IEEE80211_HW_AMPDU_AGGREGATION | |
144 | IEEE80211_HW_TIMING_BEACON_ONLY; | 155 | IEEE80211_HW_TIMING_BEACON_ONLY | |
156 | IEEE80211_HW_CONNECTION_MONITOR; | ||
145 | 157 | ||
146 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; | 158 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; |
147 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 159 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
@@ -158,7 +170,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
158 | 170 | ||
159 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); | 171 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); |
160 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); | 172 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); |
161 | hw->chanctx_data_size = sizeof(struct iwl_mvm_phy_ctxt); | 173 | hw->chanctx_data_size = sizeof(u16); |
162 | 174 | ||
163 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 175 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
164 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 176 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
@@ -193,6 +205,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
193 | hw->wiphy->n_addresses++; | 205 | hw->wiphy->n_addresses++; |
194 | } | 206 | } |
195 | 207 | ||
208 | iwl_mvm_reset_phy_ctxts(mvm); | ||
209 | |||
196 | /* we create the 802.11 header and a max-length SSID element */ | 210 | /* we create the 802.11 header and a max-length SSID element */ |
197 | hw->wiphy->max_scan_ie_len = | 211 | hw->wiphy->max_scan_ie_len = |
198 | mvm->fw->ucode_capa.max_probe_length - 24 - 34; | 212 | mvm->fw->ucode_capa.max_probe_length - 24 - 34; |
@@ -252,8 +266,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | |||
252 | { | 266 | { |
253 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 267 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
254 | 268 | ||
255 | if (test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status)) { | 269 | if (iwl_mvm_is_radio_killed(mvm)) { |
256 | IWL_DEBUG_DROP(mvm, "Dropping - RF KILL\n"); | 270 | IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n"); |
257 | goto drop; | 271 | goto drop; |
258 | } | 272 | } |
259 | 273 | ||
@@ -345,8 +359,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
345 | iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); | 359 | iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); |
346 | spin_unlock_bh(&mvm->time_event_lock); | 360 | spin_unlock_bh(&mvm->time_event_lock); |
347 | 361 | ||
348 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) | 362 | mvmvif->phy_ctxt = NULL; |
349 | mvmvif->phy_ctxt = NULL; | ||
350 | } | 363 | } |
351 | 364 | ||
352 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | 365 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) |
@@ -363,6 +376,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | |||
363 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | 376 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
364 | iwl_mvm_cleanup_iterator, mvm); | 377 | iwl_mvm_cleanup_iterator, mvm); |
365 | 378 | ||
379 | mvm->p2p_device_vif = NULL; | ||
380 | |||
381 | iwl_mvm_reset_phy_ctxts(mvm); | ||
366 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | 382 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); |
367 | memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); | 383 | memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); |
368 | 384 | ||
@@ -456,6 +472,20 @@ static void iwl_mvm_power_update_iterator(void *data, u8 *mac, | |||
456 | iwl_mvm_power_update_mode(mvm, vif); | 472 | iwl_mvm_power_update_mode(mvm, vif); |
457 | } | 473 | } |
458 | 474 | ||
475 | static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) | ||
476 | { | ||
477 | u16 i; | ||
478 | |||
479 | lockdep_assert_held(&mvm->mutex); | ||
480 | |||
481 | for (i = 0; i < NUM_PHY_CTX; i++) | ||
482 | if (!mvm->phy_ctxts[i].ref) | ||
483 | return &mvm->phy_ctxts[i]; | ||
484 | |||
485 | IWL_ERR(mvm, "No available PHY context\n"); | ||
486 | return NULL; | ||
487 | } | ||
488 | |||
459 | static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | 489 | static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, |
460 | struct ieee80211_vif *vif) | 490 | struct ieee80211_vif *vif) |
461 | { | 491 | { |
@@ -530,32 +560,34 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
530 | */ | 560 | */ |
531 | iwl_mvm_power_update_mode(mvm, vif); | 561 | iwl_mvm_power_update_mode(mvm, vif); |
532 | 562 | ||
563 | /* beacon filtering */ | ||
564 | if (!mvm->bf_allowed_vif && | ||
565 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p){ | ||
566 | mvm->bf_allowed_vif = mvmvif; | ||
567 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; | ||
568 | } | ||
569 | |||
570 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | ||
571 | if (ret) | ||
572 | goto out_release; | ||
573 | |||
533 | /* | 574 | /* |
534 | * P2P_DEVICE interface does not have a channel context assigned to it, | 575 | * P2P_DEVICE interface does not have a channel context assigned to it, |
535 | * so a dedicated PHY context is allocated to it and the corresponding | 576 | * so a dedicated PHY context is allocated to it and the corresponding |
536 | * MAC context is bound to it at this stage. | 577 | * MAC context is bound to it at this stage. |
537 | */ | 578 | */ |
538 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 579 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { |
539 | struct ieee80211_channel *chan; | ||
540 | struct cfg80211_chan_def chandef; | ||
541 | |||
542 | mvmvif->phy_ctxt = &mvm->phy_ctxt_roc; | ||
543 | 580 | ||
544 | /* | 581 | mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); |
545 | * The channel used here isn't relevant as it's | 582 | if (!mvmvif->phy_ctxt) { |
546 | * going to be overwritten as part of the ROC flow. | 583 | ret = -ENOSPC; |
547 | * For now use the first channel we have. | ||
548 | */ | ||
549 | chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; | ||
550 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); | ||
551 | ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt, | ||
552 | &chandef, 1, 1); | ||
553 | if (ret) | ||
554 | goto out_remove_mac; | 584 | goto out_remove_mac; |
585 | } | ||
555 | 586 | ||
587 | iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); | ||
556 | ret = iwl_mvm_binding_add_vif(mvm, vif); | 588 | ret = iwl_mvm_binding_add_vif(mvm, vif); |
557 | if (ret) | 589 | if (ret) |
558 | goto out_remove_phy; | 590 | goto out_unref_phy; |
559 | 591 | ||
560 | ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta); | 592 | ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta); |
561 | if (ret) | 593 | if (ret) |
@@ -571,8 +603,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
571 | 603 | ||
572 | out_unbind: | 604 | out_unbind: |
573 | iwl_mvm_binding_remove_vif(mvm, vif); | 605 | iwl_mvm_binding_remove_vif(mvm, vif); |
574 | out_remove_phy: | 606 | out_unref_phy: |
575 | iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt); | 607 | iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); |
576 | out_remove_mac: | 608 | out_remove_mac: |
577 | mvmvif->phy_ctxt = NULL; | 609 | mvmvif->phy_ctxt = NULL; |
578 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 610 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
@@ -646,6 +678,11 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
646 | 678 | ||
647 | mutex_lock(&mvm->mutex); | 679 | mutex_lock(&mvm->mutex); |
648 | 680 | ||
681 | if (mvm->bf_allowed_vif == mvmvif) { | ||
682 | mvm->bf_allowed_vif = NULL; | ||
683 | vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; | ||
684 | } | ||
685 | |||
649 | iwl_mvm_vif_dbgfs_clean(mvm, vif); | 686 | iwl_mvm_vif_dbgfs_clean(mvm, vif); |
650 | 687 | ||
651 | /* | 688 | /* |
@@ -661,7 +698,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
661 | mvm->p2p_device_vif = NULL; | 698 | mvm->p2p_device_vif = NULL; |
662 | iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 699 | iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
663 | iwl_mvm_binding_remove_vif(mvm, vif); | 700 | iwl_mvm_binding_remove_vif(mvm, vif); |
664 | iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt); | 701 | iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); |
665 | mvmvif->phy_ctxt = NULL; | 702 | mvmvif->phy_ctxt = NULL; |
666 | } | 703 | } |
667 | 704 | ||
@@ -701,6 +738,20 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, | |||
701 | *total_flags = 0; | 738 | *total_flags = 0; |
702 | } | 739 | } |
703 | 740 | ||
741 | static int iwl_mvm_configure_mcast_filter(struct iwl_mvm *mvm, | ||
742 | struct ieee80211_vif *vif) | ||
743 | { | ||
744 | struct iwl_mcast_filter_cmd mcast_filter_cmd = { | ||
745 | .pass_all = 1, | ||
746 | }; | ||
747 | |||
748 | memcpy(mcast_filter_cmd.bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
749 | |||
750 | return iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, | ||
751 | sizeof(mcast_filter_cmd), | ||
752 | &mcast_filter_cmd); | ||
753 | } | ||
754 | |||
704 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | 755 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, |
705 | struct ieee80211_vif *vif, | 756 | struct ieee80211_vif *vif, |
706 | struct ieee80211_bss_conf *bss_conf, | 757 | struct ieee80211_bss_conf *bss_conf, |
@@ -722,6 +773,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
722 | return; | 773 | return; |
723 | } | 774 | } |
724 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | 775 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); |
776 | iwl_mvm_configure_mcast_filter(mvm, vif); | ||
725 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 777 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
726 | /* remove AP station now that the MAC is unassoc */ | 778 | /* remove AP station now that the MAC is unassoc */ |
727 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); | 779 | 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, | |||
931 | 983 | ||
932 | switch (cmd) { | 984 | switch (cmd) { |
933 | case STA_NOTIFY_SLEEP: | 985 | case STA_NOTIFY_SLEEP: |
934 | if (atomic_read(&mvmsta->pending_frames) > 0) | 986 | if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) |
935 | ieee80211_sta_block_awake(hw, sta, true); | 987 | ieee80211_sta_block_awake(hw, sta, true); |
936 | /* | 988 | /* |
937 | * The fw updates the STA to be asleep. Tx packets on the Tx | 989 | * 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, | |||
984 | mvmvif->phy_ctxt->channel->band); | 1036 | mvmvif->phy_ctxt->channel->band); |
985 | } else if (old_state == IEEE80211_STA_ASSOC && | 1037 | } else if (old_state == IEEE80211_STA_ASSOC && |
986 | new_state == IEEE80211_STA_AUTHORIZED) { | 1038 | new_state == IEEE80211_STA_AUTHORIZED) { |
1039 | /* enable beacon filtering */ | ||
1040 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif)); | ||
987 | ret = 0; | 1041 | ret = 0; |
988 | } else if (old_state == IEEE80211_STA_AUTHORIZED && | 1042 | } else if (old_state == IEEE80211_STA_AUTHORIZED && |
989 | new_state == IEEE80211_STA_ASSOC) { | 1043 | new_state == IEEE80211_STA_ASSOC) { |
1044 | /* disable beacon filtering */ | ||
1045 | WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif)); | ||
990 | ret = 0; | 1046 | ret = 0; |
991 | } else if (old_state == IEEE80211_STA_ASSOC && | 1047 | } else if (old_state == IEEE80211_STA_ASSOC && |
992 | new_state == IEEE80211_STA_AUTH) { | 1048 | new_state == IEEE80211_STA_AUTH) { |
@@ -1152,29 +1208,107 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
1152 | enum ieee80211_roc_type type) | 1208 | enum ieee80211_roc_type type) |
1153 | { | 1209 | { |
1154 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1210 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1211 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
1155 | struct cfg80211_chan_def chandef; | 1212 | struct cfg80211_chan_def chandef; |
1156 | int ret; | 1213 | struct iwl_mvm_phy_ctxt *phy_ctxt; |
1214 | int ret, i; | ||
1215 | |||
1216 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, | ||
1217 | duration, type); | ||
1157 | 1218 | ||
1158 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { | 1219 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { |
1159 | IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); | 1220 | IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); |
1160 | return -EINVAL; | 1221 | return -EINVAL; |
1161 | } | 1222 | } |
1162 | 1223 | ||
1163 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, | ||
1164 | duration, type); | ||
1165 | |||
1166 | mutex_lock(&mvm->mutex); | 1224 | mutex_lock(&mvm->mutex); |
1167 | 1225 | ||
1226 | for (i = 0; i < NUM_PHY_CTX; i++) { | ||
1227 | phy_ctxt = &mvm->phy_ctxts[i]; | ||
1228 | if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt) | ||
1229 | continue; | ||
1230 | |||
1231 | if (phy_ctxt->ref && channel == phy_ctxt->channel) { | ||
1232 | /* | ||
1233 | * Unbind the P2P_DEVICE from the current PHY context, | ||
1234 | * and if the PHY context is not used remove it. | ||
1235 | */ | ||
1236 | ret = iwl_mvm_binding_remove_vif(mvm, vif); | ||
1237 | if (WARN(ret, "Failed unbinding P2P_DEVICE\n")) | ||
1238 | goto out_unlock; | ||
1239 | |||
1240 | iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); | ||
1241 | |||
1242 | /* Bind the P2P_DEVICE to the current PHY Context */ | ||
1243 | mvmvif->phy_ctxt = phy_ctxt; | ||
1244 | |||
1245 | ret = iwl_mvm_binding_add_vif(mvm, vif); | ||
1246 | if (WARN(ret, "Failed binding P2P_DEVICE\n")) | ||
1247 | goto out_unlock; | ||
1248 | |||
1249 | iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); | ||
1250 | goto schedule_time_event; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | /* Need to update the PHY context only if the ROC channel changed */ | ||
1255 | if (channel == mvmvif->phy_ctxt->channel) | ||
1256 | goto schedule_time_event; | ||
1257 | |||
1168 | cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); | 1258 | cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); |
1169 | ret = iwl_mvm_phy_ctxt_changed(mvm, &mvm->phy_ctxt_roc, | ||
1170 | &chandef, 1, 1); | ||
1171 | 1259 | ||
1260 | /* | ||
1261 | * Change the PHY context configuration as it is currently referenced | ||
1262 | * only by the P2P Device MAC | ||
1263 | */ | ||
1264 | if (mvmvif->phy_ctxt->ref == 1) { | ||
1265 | ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, | ||
1266 | &chandef, 1, 1); | ||
1267 | if (ret) | ||
1268 | goto out_unlock; | ||
1269 | } else { | ||
1270 | /* | ||
1271 | * The PHY context is shared with other MACs. Need to remove the | ||
1272 | * P2P Device from the binding, allocate an new PHY context and | ||
1273 | * create a new binding | ||
1274 | */ | ||
1275 | phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); | ||
1276 | if (!phy_ctxt) { | ||
1277 | ret = -ENOSPC; | ||
1278 | goto out_unlock; | ||
1279 | } | ||
1280 | |||
1281 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef, | ||
1282 | 1, 1); | ||
1283 | if (ret) { | ||
1284 | IWL_ERR(mvm, "Failed to change PHY context\n"); | ||
1285 | goto out_unlock; | ||
1286 | } | ||
1287 | |||
1288 | /* Unbind the P2P_DEVICE from the current PHY context */ | ||
1289 | ret = iwl_mvm_binding_remove_vif(mvm, vif); | ||
1290 | if (WARN(ret, "Failed unbinding P2P_DEVICE\n")) | ||
1291 | goto out_unlock; | ||
1292 | |||
1293 | iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); | ||
1294 | |||
1295 | /* Bind the P2P_DEVICE to the new allocated PHY context */ | ||
1296 | mvmvif->phy_ctxt = phy_ctxt; | ||
1297 | |||
1298 | ret = iwl_mvm_binding_add_vif(mvm, vif); | ||
1299 | if (WARN(ret, "Failed binding P2P_DEVICE\n")) | ||
1300 | goto out_unlock; | ||
1301 | |||
1302 | iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); | ||
1303 | } | ||
1304 | |||
1305 | schedule_time_event: | ||
1172 | /* Schedule the time events */ | 1306 | /* Schedule the time events */ |
1173 | ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); | 1307 | ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); |
1174 | 1308 | ||
1309 | out_unlock: | ||
1175 | mutex_unlock(&mvm->mutex); | 1310 | mutex_unlock(&mvm->mutex); |
1176 | IWL_DEBUG_MAC80211(mvm, "leave\n"); | 1311 | IWL_DEBUG_MAC80211(mvm, "leave\n"); |
1177 | |||
1178 | return ret; | 1312 | return ret; |
1179 | } | 1313 | } |
1180 | 1314 | ||
@@ -1196,15 +1330,30 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, | |||
1196 | struct ieee80211_chanctx_conf *ctx) | 1330 | struct ieee80211_chanctx_conf *ctx) |
1197 | { | 1331 | { |
1198 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1332 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1199 | struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; | 1333 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; |
1334 | struct iwl_mvm_phy_ctxt *phy_ctxt; | ||
1200 | int ret; | 1335 | int ret; |
1201 | 1336 | ||
1337 | IWL_DEBUG_MAC80211(mvm, "Add channel context\n"); | ||
1338 | |||
1202 | mutex_lock(&mvm->mutex); | 1339 | mutex_lock(&mvm->mutex); |
1340 | phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); | ||
1341 | if (!phy_ctxt) { | ||
1342 | ret = -ENOSPC; | ||
1343 | goto out; | ||
1344 | } | ||
1345 | |||
1346 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, | ||
1347 | ctx->rx_chains_static, | ||
1348 | ctx->rx_chains_dynamic); | ||
1349 | if (ret) { | ||
1350 | IWL_ERR(mvm, "Failed to add PHY context\n"); | ||
1351 | goto out; | ||
1352 | } | ||
1203 | 1353 | ||
1204 | IWL_DEBUG_MAC80211(mvm, "Add PHY context\n"); | 1354 | iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt); |
1205 | ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def, | 1355 | *phy_ctxt_id = phy_ctxt->id; |
1206 | ctx->rx_chains_static, | 1356 | out: |
1207 | ctx->rx_chains_dynamic); | ||
1208 | mutex_unlock(&mvm->mutex); | 1357 | mutex_unlock(&mvm->mutex); |
1209 | return ret; | 1358 | return ret; |
1210 | } | 1359 | } |
@@ -1213,10 +1362,11 @@ static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw, | |||
1213 | struct ieee80211_chanctx_conf *ctx) | 1362 | struct ieee80211_chanctx_conf *ctx) |
1214 | { | 1363 | { |
1215 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1364 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1216 | struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; | 1365 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; |
1366 | struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; | ||
1217 | 1367 | ||
1218 | mutex_lock(&mvm->mutex); | 1368 | mutex_lock(&mvm->mutex); |
1219 | iwl_mvm_phy_ctxt_remove(mvm, phy_ctxt); | 1369 | iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt); |
1220 | mutex_unlock(&mvm->mutex); | 1370 | mutex_unlock(&mvm->mutex); |
1221 | } | 1371 | } |
1222 | 1372 | ||
@@ -1225,7 +1375,16 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
1225 | u32 changed) | 1375 | u32 changed) |
1226 | { | 1376 | { |
1227 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1377 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1228 | struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; | 1378 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; |
1379 | struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; | ||
1380 | |||
1381 | if (WARN_ONCE((phy_ctxt->ref > 1) && | ||
1382 | (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | | ||
1383 | IEEE80211_CHANCTX_CHANGE_RX_CHAINS | | ||
1384 | IEEE80211_CHANCTX_CHANGE_RADAR)), | ||
1385 | "Cannot change PHY. Ref=%d, changed=0x%X\n", | ||
1386 | phy_ctxt->ref, changed)) | ||
1387 | return; | ||
1229 | 1388 | ||
1230 | mutex_lock(&mvm->mutex); | 1389 | mutex_lock(&mvm->mutex); |
1231 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, | 1390 | 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, | |||
1239 | struct ieee80211_chanctx_conf *ctx) | 1398 | struct ieee80211_chanctx_conf *ctx) |
1240 | { | 1399 | { |
1241 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1400 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1242 | struct iwl_mvm_phy_ctxt *phyctx = (void *)ctx->drv_priv; | 1401 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; |
1402 | struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; | ||
1243 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1403 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
1244 | int ret; | 1404 | int ret; |
1245 | 1405 | ||
1246 | mutex_lock(&mvm->mutex); | 1406 | mutex_lock(&mvm->mutex); |
1247 | 1407 | ||
1248 | mvmvif->phy_ctxt = phyctx; | 1408 | mvmvif->phy_ctxt = phy_ctxt; |
1249 | 1409 | ||
1250 | switch (vif->type) { | 1410 | switch (vif->type) { |
1251 | case NL80211_IFTYPE_AP: | 1411 | case NL80211_IFTYPE_AP: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 8269bc562951..6a3220b6273e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -109,6 +109,7 @@ extern struct iwl_mvm_mod_params iwlmvm_mod_params; | |||
109 | struct iwl_mvm_phy_ctxt { | 109 | struct iwl_mvm_phy_ctxt { |
110 | u16 id; | 110 | u16 id; |
111 | u16 color; | 111 | u16 color; |
112 | u32 ref; | ||
112 | 113 | ||
113 | /* | 114 | /* |
114 | * TODO: This should probably be removed. Currently here only for rate | 115 | * TODO: This should probably be removed. Currently here only for rate |
@@ -149,6 +150,60 @@ enum iwl_power_scheme { | |||
149 | 150 | ||
150 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 | 151 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 |
151 | 152 | ||
153 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
154 | enum iwl_dbgfs_pm_mask { | ||
155 | MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0), | ||
156 | MVM_DEBUGFS_PM_SKIP_OVER_DTIM = BIT(1), | ||
157 | MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS = BIT(2), | ||
158 | MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3), | ||
159 | MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4), | ||
160 | MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), | ||
161 | }; | ||
162 | |||
163 | struct iwl_dbgfs_pm { | ||
164 | u8 keep_alive_seconds; | ||
165 | u32 rx_data_timeout; | ||
166 | u32 tx_data_timeout; | ||
167 | bool skip_over_dtim; | ||
168 | u8 skip_dtim_periods; | ||
169 | bool disable_power_off; | ||
170 | int mask; | ||
171 | }; | ||
172 | |||
173 | /* beacon filtering */ | ||
174 | |||
175 | enum iwl_dbgfs_bf_mask { | ||
176 | MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0), | ||
177 | MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1), | ||
178 | MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2), | ||
179 | MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3), | ||
180 | MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4), | ||
181 | MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5), | ||
182 | MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6), | ||
183 | MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7), | ||
184 | MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8), | ||
185 | }; | ||
186 | |||
187 | struct iwl_dbgfs_bf { | ||
188 | u8 bf_energy_delta; | ||
189 | u8 bf_roaming_energy_delta; | ||
190 | u8 bf_roaming_state; | ||
191 | u8 bf_temperature_delta; | ||
192 | u8 bf_enable_beacon_filter; | ||
193 | u8 bf_debug_flag; | ||
194 | u32 bf_escape_timer; | ||
195 | u32 ba_escape_timer; | ||
196 | u8 ba_enable_beacon_abort; | ||
197 | int mask; | ||
198 | }; | ||
199 | #endif | ||
200 | |||
201 | enum iwl_mvm_smps_type_request { | ||
202 | IWL_MVM_SMPS_REQ_BT_COEX, | ||
203 | IWL_MVM_SMPS_REQ_TT, | ||
204 | NUM_IWL_MVM_SMPS_REQ, | ||
205 | }; | ||
206 | |||
152 | /** | 207 | /** |
153 | * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context | 208 | * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context |
154 | * @id: between 0 and 3 | 209 | * @id: between 0 and 3 |
@@ -163,6 +218,8 @@ enum iwl_power_scheme { | |||
163 | * @bcast_sta: station used for broadcast packets. Used by the following | 218 | * @bcast_sta: station used for broadcast packets. Used by the following |
164 | * vifs: P2P_DEVICE, GO and AP. | 219 | * vifs: P2P_DEVICE, GO and AP. |
165 | * @beacon_skb: the skb used to hold the AP/GO beacon template | 220 | * @beacon_skb: the skb used to hold the AP/GO beacon template |
221 | * @smps_requests: the requests of of differents parts of the driver, regard | ||
222 | the desired smps mode. | ||
166 | */ | 223 | */ |
167 | struct iwl_mvm_vif { | 224 | struct iwl_mvm_vif { |
168 | u16 id; | 225 | u16 id; |
@@ -172,6 +229,8 @@ struct iwl_mvm_vif { | |||
172 | bool uploaded; | 229 | bool uploaded; |
173 | bool ap_active; | 230 | bool ap_active; |
174 | bool monitor_active; | 231 | bool monitor_active; |
232 | /* indicate whether beacon filtering is enabled */ | ||
233 | bool bf_enabled; | ||
175 | 234 | ||
176 | u32 ap_beacon_time; | 235 | u32 ap_beacon_time; |
177 | 236 | ||
@@ -214,7 +273,11 @@ struct iwl_mvm_vif { | |||
214 | struct dentry *dbgfs_dir; | 273 | struct dentry *dbgfs_dir; |
215 | struct dentry *dbgfs_slink; | 274 | struct dentry *dbgfs_slink; |
216 | void *dbgfs_data; | 275 | void *dbgfs_data; |
276 | struct iwl_dbgfs_pm dbgfs_pm; | ||
277 | struct iwl_dbgfs_bf dbgfs_bf; | ||
217 | #endif | 278 | #endif |
279 | |||
280 | enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; | ||
218 | }; | 281 | }; |
219 | 282 | ||
220 | static inline struct iwl_mvm_vif * | 283 | static inline struct iwl_mvm_vif * |
@@ -223,12 +286,6 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) | |||
223 | return (void *)vif->drv_priv; | 286 | return (void *)vif->drv_priv; |
224 | } | 287 | } |
225 | 288 | ||
226 | enum iwl_mvm_status { | ||
227 | IWL_MVM_STATUS_HW_RFKILL, | ||
228 | IWL_MVM_STATUS_ROC_RUNNING, | ||
229 | IWL_MVM_STATUS_IN_HW_RESTART, | ||
230 | }; | ||
231 | |||
232 | enum iwl_scan_status { | 289 | enum iwl_scan_status { |
233 | IWL_MVM_SCAN_NONE, | 290 | IWL_MVM_SCAN_NONE, |
234 | IWL_MVM_SCAN_OS, | 291 | IWL_MVM_SCAN_OS, |
@@ -246,6 +303,63 @@ struct iwl_nvm_section { | |||
246 | const u8 *data; | 303 | const u8 *data; |
247 | }; | 304 | }; |
248 | 305 | ||
306 | /* | ||
307 | * Tx-backoff threshold | ||
308 | * @temperature: The threshold in Celsius | ||
309 | * @backoff: The tx-backoff in uSec | ||
310 | */ | ||
311 | struct iwl_tt_tx_backoff { | ||
312 | s32 temperature; | ||
313 | u32 backoff; | ||
314 | }; | ||
315 | |||
316 | #define TT_TX_BACKOFF_SIZE 6 | ||
317 | |||
318 | /** | ||
319 | * struct iwl_tt_params - thermal throttling parameters | ||
320 | * @ct_kill_entry: CT Kill entry threshold | ||
321 | * @ct_kill_exit: CT Kill exit threshold | ||
322 | * @ct_kill_duration: The time intervals (in uSec) in which the driver needs | ||
323 | * to checks whether to exit CT Kill. | ||
324 | * @dynamic_smps_entry: Dynamic SMPS entry threshold | ||
325 | * @dynamic_smps_exit: Dynamic SMPS exit threshold | ||
326 | * @tx_protection_entry: TX protection entry threshold | ||
327 | * @tx_protection_exit: TX protection exit threshold | ||
328 | * @tx_backoff: Array of thresholds for tx-backoff , in ascending order. | ||
329 | * @support_ct_kill: Support CT Kill? | ||
330 | * @support_dynamic_smps: Support dynamic SMPS? | ||
331 | * @support_tx_protection: Support tx protection? | ||
332 | * @support_tx_backoff: Support tx-backoff? | ||
333 | */ | ||
334 | struct iwl_tt_params { | ||
335 | s32 ct_kill_entry; | ||
336 | s32 ct_kill_exit; | ||
337 | u32 ct_kill_duration; | ||
338 | s32 dynamic_smps_entry; | ||
339 | s32 dynamic_smps_exit; | ||
340 | s32 tx_protection_entry; | ||
341 | s32 tx_protection_exit; | ||
342 | struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE]; | ||
343 | bool support_ct_kill; | ||
344 | bool support_dynamic_smps; | ||
345 | bool support_tx_protection; | ||
346 | bool support_tx_backoff; | ||
347 | }; | ||
348 | |||
349 | /** | ||
350 | * struct iwl_mvm_tt_mgnt - Thermal Throttling Management structure | ||
351 | * @ct_kill_exit: worker to exit thermal kill | ||
352 | * @dynamic_smps: Is thermal throttling enabled dynamic_smps? | ||
353 | * @tx_backoff: The current thremal throttling tx backoff in uSec. | ||
354 | * @params: Parameters to configure the thermal throttling algorithm. | ||
355 | */ | ||
356 | struct iwl_mvm_tt_mgmt { | ||
357 | struct delayed_work ct_kill_exit; | ||
358 | bool dynamic_smps; | ||
359 | u32 tx_backoff; | ||
360 | const struct iwl_tt_params *params; | ||
361 | }; | ||
362 | |||
249 | struct iwl_mvm { | 363 | struct iwl_mvm { |
250 | /* for logger access */ | 364 | /* for logger access */ |
251 | struct device *dev; | 365 | struct device *dev; |
@@ -266,6 +380,12 @@ struct iwl_mvm { | |||
266 | 380 | ||
267 | unsigned long status; | 381 | unsigned long status; |
268 | 382 | ||
383 | /* | ||
384 | * for beacon filtering - | ||
385 | * currently only one interface can be supported | ||
386 | */ | ||
387 | struct iwl_mvm_vif *bf_allowed_vif; | ||
388 | |||
269 | enum iwl_ucode_type cur_ucode; | 389 | enum iwl_ucode_type cur_ucode; |
270 | bool ucode_loaded; | 390 | bool ucode_loaded; |
271 | bool init_ucode_run; | 391 | bool init_ucode_run; |
@@ -292,6 +412,7 @@ struct iwl_mvm { | |||
292 | struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT]; | 412 | struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT]; |
293 | struct work_struct sta_drained_wk; | 413 | struct work_struct sta_drained_wk; |
294 | unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; | 414 | unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; |
415 | atomic_t pending_frames[IWL_MVM_STATION_COUNT]; | ||
295 | 416 | ||
296 | /* configured by mac80211 */ | 417 | /* configured by mac80211 */ |
297 | u32 rts_threshold; | 418 | u32 rts_threshold; |
@@ -312,7 +433,7 @@ struct iwl_mvm { | |||
312 | bool prevent_power_down_d3; | 433 | bool prevent_power_down_d3; |
313 | #endif | 434 | #endif |
314 | 435 | ||
315 | struct iwl_mvm_phy_ctxt phy_ctxt_roc; | 436 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; |
316 | 437 | ||
317 | struct list_head time_event_list; | 438 | struct list_head time_event_list; |
318 | spinlock_t time_event_lock; | 439 | spinlock_t time_event_lock; |
@@ -337,11 +458,19 @@ struct iwl_mvm { | |||
337 | 458 | ||
338 | #ifdef CONFIG_PM_SLEEP | 459 | #ifdef CONFIG_PM_SLEEP |
339 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; | 460 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; |
461 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
462 | bool store_d3_resume_sram; | ||
463 | void *d3_resume_sram; | ||
464 | #endif | ||
340 | #endif | 465 | #endif |
341 | 466 | ||
342 | /* BT-Coex */ | 467 | /* BT-Coex */ |
343 | u8 bt_kill_msk; | 468 | u8 bt_kill_msk; |
344 | struct iwl_bt_coex_profile_notif last_bt_notif; | 469 | struct iwl_bt_coex_profile_notif last_bt_notif; |
470 | |||
471 | /* Thermal Throttling and CTkill */ | ||
472 | struct iwl_mvm_tt_mgmt thermal_throttle; | ||
473 | s32 temperature; /* Celsius */ | ||
345 | }; | 474 | }; |
346 | 475 | ||
347 | /* Extract MVM priv from op_mode and _hw */ | 476 | /* Extract MVM priv from op_mode and _hw */ |
@@ -351,6 +480,19 @@ struct iwl_mvm { | |||
351 | #define IWL_MAC80211_GET_MVM(_hw) \ | 480 | #define IWL_MAC80211_GET_MVM(_hw) \ |
352 | IWL_OP_MODE_GET_MVM((struct iwl_op_mode *)((_hw)->priv)) | 481 | IWL_OP_MODE_GET_MVM((struct iwl_op_mode *)((_hw)->priv)) |
353 | 482 | ||
483 | enum iwl_mvm_status { | ||
484 | IWL_MVM_STATUS_HW_RFKILL, | ||
485 | IWL_MVM_STATUS_HW_CTKILL, | ||
486 | IWL_MVM_STATUS_ROC_RUNNING, | ||
487 | IWL_MVM_STATUS_IN_HW_RESTART, | ||
488 | }; | ||
489 | |||
490 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) | ||
491 | { | ||
492 | return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status) || | ||
493 | test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); | ||
494 | } | ||
495 | |||
354 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 496 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
355 | 497 | ||
356 | struct iwl_rate_info { | 498 | struct iwl_rate_info { |
@@ -442,8 +584,10 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | |||
442 | int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | 584 | int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, |
443 | struct cfg80211_chan_def *chandef, | 585 | struct cfg80211_chan_def *chandef, |
444 | u8 chains_static, u8 chains_dynamic); | 586 | u8 chains_static, u8 chains_dynamic); |
445 | void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, | 587 | void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, |
446 | struct iwl_mvm_phy_ctxt *ctxt); | 588 | struct iwl_mvm_phy_ctxt *ctxt); |
589 | void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, | ||
590 | struct iwl_mvm_phy_ctxt *ctxt); | ||
447 | 591 | ||
448 | /* MAC (virtual interface) programming */ | 592 | /* MAC (virtual interface) programming */ |
449 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 593 | 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, | |||
458 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | 602 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, |
459 | struct iwl_rx_cmd_buffer *rxb, | 603 | struct iwl_rx_cmd_buffer *rxb, |
460 | struct iwl_device_cmd *cmd); | 604 | struct iwl_device_cmd *cmd); |
605 | int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | ||
606 | struct iwl_rx_cmd_buffer *rxb, | ||
607 | struct iwl_device_cmd *cmd); | ||
461 | 608 | ||
462 | /* Bindings */ | 609 | /* Bindings */ |
463 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 610 | 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, | |||
533 | enum ieee80211_rssi_event rssi_event); | 680 | enum ieee80211_rssi_event rssi_event); |
534 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 681 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
535 | 682 | ||
683 | /* beacon filtering */ | ||
684 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
685 | void | ||
686 | iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, | ||
687 | struct iwl_beacon_filter_cmd *cmd); | ||
688 | int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm); | ||
689 | #else | ||
690 | static inline void | ||
691 | iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, | ||
692 | struct iwl_beacon_filter_cmd *cmd) | ||
693 | {} | ||
694 | static inline int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm) | ||
695 | { | ||
696 | return 0; | ||
697 | } | ||
698 | #endif | ||
699 | int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | ||
700 | struct ieee80211_vif *vif); | ||
701 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | ||
702 | struct ieee80211_vif *vif); | ||
703 | |||
704 | /* SMPS */ | ||
705 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
706 | enum iwl_mvm_smps_type_request req_type, | ||
707 | enum ieee80211_smps_mode smps_request); | ||
708 | |||
709 | /* Thermal management and CT-kill */ | ||
710 | void iwl_mvm_tt_handler(struct iwl_mvm *mvm); | ||
711 | void iwl_mvm_tt_initialize(struct iwl_mvm *mvm); | ||
712 | void iwl_mvm_tt_exit(struct iwl_mvm *mvm); | ||
713 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); | ||
714 | |||
536 | #endif /* __IWL_MVM_H__ */ | 715 | #endif /* __IWL_MVM_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index b8ec02f89acc..edb94ea31654 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -60,6 +60,7 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/firmware.h> | ||
63 | #include "iwl-trans.h" | 64 | #include "iwl-trans.h" |
64 | #include "mvm.h" | 65 | #include "mvm.h" |
65 | #include "iwl-eeprom-parse.h" | 66 | #include "iwl-eeprom-parse.h" |
@@ -75,31 +76,56 @@ static const int nvm_to_read[] = { | |||
75 | }; | 76 | }; |
76 | 77 | ||
77 | /* Default NVM size to read */ | 78 | /* Default NVM size to read */ |
78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); | 79 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) |
80 | #define IWL_MAX_NVM_SECTION_SIZE 6000 | ||
79 | 81 | ||
80 | static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd, | 82 | #define NVM_WRITE_OPCODE 1 |
81 | u16 offset, u16 length, u16 section) | 83 | #define NVM_READ_OPCODE 0 |
84 | |||
85 | /* | ||
86 | * prepare the NVM host command w/ the pointers to the nvm buffer | ||
87 | * and send it to fw | ||
88 | */ | ||
89 | static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section, | ||
90 | u16 offset, u16 length, const u8 *data) | ||
82 | { | 91 | { |
83 | cmd->offset = cpu_to_le16(offset); | 92 | struct iwl_nvm_access_cmd nvm_access_cmd = { |
84 | cmd->length = cpu_to_le16(length); | 93 | .offset = cpu_to_le16(offset), |
85 | cmd->type = cpu_to_le16(section); | 94 | .length = cpu_to_le16(length), |
95 | .type = cpu_to_le16(section), | ||
96 | .op_code = NVM_WRITE_OPCODE, | ||
97 | }; | ||
98 | struct iwl_host_cmd cmd = { | ||
99 | .id = NVM_ACCESS_CMD, | ||
100 | .len = { sizeof(struct iwl_nvm_access_cmd), length }, | ||
101 | .flags = CMD_SYNC | CMD_SEND_IN_RFKILL, | ||
102 | .data = { &nvm_access_cmd, data }, | ||
103 | /* data may come from vmalloc, so use _DUP */ | ||
104 | .dataflags = { 0, IWL_HCMD_DFL_DUP }, | ||
105 | }; | ||
106 | |||
107 | return iwl_mvm_send_cmd(mvm, &cmd); | ||
86 | } | 108 | } |
87 | 109 | ||
88 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | 110 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, |
89 | u16 offset, u16 length, u8 *data) | 111 | u16 offset, u16 length, u8 *data) |
90 | { | 112 | { |
91 | struct iwl_nvm_access_cmd nvm_access_cmd = {}; | 113 | struct iwl_nvm_access_cmd nvm_access_cmd = { |
114 | .offset = cpu_to_le16(offset), | ||
115 | .length = cpu_to_le16(length), | ||
116 | .type = cpu_to_le16(section), | ||
117 | .op_code = NVM_READ_OPCODE, | ||
118 | }; | ||
92 | struct iwl_nvm_access_resp *nvm_resp; | 119 | struct iwl_nvm_access_resp *nvm_resp; |
93 | struct iwl_rx_packet *pkt; | 120 | struct iwl_rx_packet *pkt; |
94 | struct iwl_host_cmd cmd = { | 121 | struct iwl_host_cmd cmd = { |
95 | .id = NVM_ACCESS_CMD, | 122 | .id = NVM_ACCESS_CMD, |
96 | .flags = CMD_SYNC | CMD_WANT_SKB, | 123 | .flags = CMD_SYNC | CMD_WANT_SKB | CMD_SEND_IN_RFKILL, |
97 | .data = { &nvm_access_cmd, }, | 124 | .data = { &nvm_access_cmd, }, |
98 | }; | 125 | }; |
99 | int ret, bytes_read, offset_read; | 126 | int ret, bytes_read, offset_read; |
100 | u8 *resp_data; | 127 | u8 *resp_data; |
101 | 128 | ||
102 | iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section); | ||
103 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); | 129 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); |
104 | 130 | ||
105 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 131 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
@@ -144,6 +170,30 @@ exit: | |||
144 | return ret; | 170 | return ret; |
145 | } | 171 | } |
146 | 172 | ||
173 | static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section, | ||
174 | const u8 *data, u16 length) | ||
175 | { | ||
176 | int offset = 0; | ||
177 | |||
178 | /* copy data in chunks of 2k (and remainder if any) */ | ||
179 | |||
180 | while (offset < length) { | ||
181 | int chunk_size, ret; | ||
182 | |||
183 | chunk_size = min(IWL_NVM_DEFAULT_CHUNK_SIZE, | ||
184 | length - offset); | ||
185 | |||
186 | ret = iwl_nvm_write_chunk(mvm, section, offset, | ||
187 | chunk_size, data + offset); | ||
188 | if (ret < 0) | ||
189 | return ret; | ||
190 | |||
191 | offset += chunk_size; | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
147 | /* | 197 | /* |
148 | * Reads an NVM section completely. | 198 | * Reads an NVM section completely. |
149 | * NICs prior to 7000 family doesn't have a real NVM, but just read | 199 | * 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, | |||
177 | offset += ret; | 227 | offset += ret; |
178 | } | 228 | } |
179 | 229 | ||
180 | IWL_INFO(mvm, "NVM section %d read completed\n", section); | 230 | IWL_DEBUG_EEPROM(mvm->trans->dev, |
231 | "NVM section %d read completed\n", section); | ||
181 | return offset; | 232 | return offset; |
182 | } | 233 | } |
183 | 234 | ||
@@ -200,7 +251,130 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
200 | hw = (const __le16 *)sections[NVM_SECTION_TYPE_HW].data; | 251 | hw = (const __le16 *)sections[NVM_SECTION_TYPE_HW].data; |
201 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; | 252 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; |
202 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; | 253 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; |
203 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib); | 254 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, |
255 | iwl_fw_valid_tx_ant(mvm->fw), | ||
256 | iwl_fw_valid_rx_ant(mvm->fw)); | ||
257 | } | ||
258 | |||
259 | #define MAX_NVM_FILE_LEN 16384 | ||
260 | |||
261 | /* | ||
262 | * HOW TO CREATE THE NVM FILE FORMAT: | ||
263 | * ------------------------------ | ||
264 | * 1. create hex file, format: | ||
265 | * 3800 -> header | ||
266 | * 0000 -> header | ||
267 | * 5a40 -> data | ||
268 | * | ||
269 | * rev - 6 bit (word1) | ||
270 | * len - 10 bit (word1) | ||
271 | * id - 4 bit (word2) | ||
272 | * rsv - 12 bit (word2) | ||
273 | * | ||
274 | * 2. flip 8bits with 8 bits per line to get the right NVM file format | ||
275 | * | ||
276 | * 3. create binary file from the hex file | ||
277 | * | ||
278 | * 4. save as "iNVM_xxx.bin" under /lib/firmware | ||
279 | */ | ||
280 | static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) | ||
281 | { | ||
282 | int ret, section_id, section_size; | ||
283 | const struct firmware *fw_entry; | ||
284 | const struct { | ||
285 | __le16 word1; | ||
286 | __le16 word2; | ||
287 | u8 data[]; | ||
288 | } *file_sec; | ||
289 | const u8 *eof; | ||
290 | |||
291 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) | ||
292 | #define NVM_WORD2_ID(x) (x >> 12) | ||
293 | |||
294 | /* | ||
295 | * Obtain NVM image via request_firmware. Since we already used | ||
296 | * request_firmware_nowait() for the firmware binary load and only | ||
297 | * get here after that we assume the NVM request can be satisfied | ||
298 | * synchronously. | ||
299 | */ | ||
300 | ret = request_firmware(&fw_entry, iwlwifi_mod_params.nvm_file, | ||
301 | mvm->trans->dev); | ||
302 | if (ret) { | ||
303 | IWL_ERR(mvm, "ERROR: %s isn't available %d\n", | ||
304 | iwlwifi_mod_params.nvm_file, ret); | ||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", | ||
309 | iwlwifi_mod_params.nvm_file, fw_entry->size); | ||
310 | |||
311 | if (fw_entry->size < sizeof(*file_sec)) { | ||
312 | IWL_ERR(mvm, "NVM file too small\n"); | ||
313 | ret = -EINVAL; | ||
314 | goto out; | ||
315 | } | ||
316 | |||
317 | if (fw_entry->size > MAX_NVM_FILE_LEN) { | ||
318 | IWL_ERR(mvm, "NVM file too large\n"); | ||
319 | ret = -EINVAL; | ||
320 | goto out; | ||
321 | } | ||
322 | |||
323 | eof = fw_entry->data + fw_entry->size; | ||
324 | |||
325 | file_sec = (void *)fw_entry->data; | ||
326 | |||
327 | while (true) { | ||
328 | if (file_sec->data > eof) { | ||
329 | IWL_ERR(mvm, | ||
330 | "ERROR - NVM file too short for section header\n"); | ||
331 | ret = -EINVAL; | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | /* check for EOF marker */ | ||
336 | if (!file_sec->word1 && !file_sec->word2) { | ||
337 | ret = 0; | ||
338 | break; | ||
339 | } | ||
340 | |||
341 | section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1)); | ||
342 | section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2)); | ||
343 | |||
344 | if (section_size > IWL_MAX_NVM_SECTION_SIZE) { | ||
345 | IWL_ERR(mvm, "ERROR - section too large (%d)\n", | ||
346 | section_size); | ||
347 | ret = -EINVAL; | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | if (!section_size) { | ||
352 | IWL_ERR(mvm, "ERROR - section empty\n"); | ||
353 | ret = -EINVAL; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | if (file_sec->data + section_size > eof) { | ||
358 | IWL_ERR(mvm, | ||
359 | "ERROR - NVM file too short for section (%d bytes)\n", | ||
360 | section_size); | ||
361 | ret = -EINVAL; | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | ret = iwl_nvm_write_section(mvm, section_id, file_sec->data, | ||
366 | section_size); | ||
367 | if (ret < 0) { | ||
368 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | /* advance to the next section */ | ||
373 | file_sec = (void *)(file_sec->data + section_size); | ||
374 | } | ||
375 | out: | ||
376 | release_firmware(fw_entry); | ||
377 | return ret; | ||
204 | } | 378 | } |
205 | 379 | ||
206 | int iwl_nvm_init(struct iwl_mvm *mvm) | 380 | int iwl_nvm_init(struct iwl_mvm *mvm) |
@@ -208,6 +382,17 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
208 | int ret, i, section; | 382 | int ret, i, section; |
209 | u8 *nvm_buffer, *temp; | 383 | u8 *nvm_buffer, *temp; |
210 | 384 | ||
385 | /* load external NVM if configured */ | ||
386 | if (iwlwifi_mod_params.nvm_file) { | ||
387 | /* move to External NVM flow */ | ||
388 | ret = iwl_mvm_load_external_nvm(mvm); | ||
389 | if (ret) | ||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | /* Read From FW NVM */ | ||
394 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); | ||
395 | |||
211 | /* TODO: find correct NVM max size for a section */ | 396 | /* TODO: find correct NVM max size for a section */ |
212 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 397 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
213 | GFP_KERNEL); | 398 | GFP_KERNEL); |
@@ -231,8 +416,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
231 | if (ret < 0) | 416 | if (ret < 0) |
232 | return ret; | 417 | return ret; |
233 | 418 | ||
234 | ret = 0; | ||
235 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | 419 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
420 | if (!mvm->nvm_data) | ||
421 | return -ENODATA; | ||
236 | 422 | ||
237 | return ret; | 423 | return 0; |
238 | } | 424 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index fe031d304d1e..d7a199b1cdef 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -222,10 +222,14 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
222 | 222 | ||
223 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), | 223 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), |
224 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), | 224 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), |
225 | RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), | ||
225 | 226 | ||
226 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), | 227 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), |
227 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), | 228 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), |
228 | 229 | ||
230 | RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif, | ||
231 | false), | ||
232 | |||
229 | RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false), | 233 | RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false), |
230 | }; | 234 | }; |
231 | #undef RX_HANDLER | 235 | #undef RX_HANDLER |
@@ -288,10 +292,14 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
288 | CMD(NET_DETECT_HOTSPOTS_CMD), | 292 | CMD(NET_DETECT_HOTSPOTS_CMD), |
289 | CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), | 293 | CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), |
290 | CMD(CARD_STATE_NOTIFICATION), | 294 | CMD(CARD_STATE_NOTIFICATION), |
295 | CMD(MISSED_BEACONS_NOTIFICATION), | ||
291 | CMD(BT_COEX_PRIO_TABLE), | 296 | CMD(BT_COEX_PRIO_TABLE), |
292 | CMD(BT_COEX_PROT_ENV), | 297 | CMD(BT_COEX_PROT_ENV), |
293 | CMD(BT_PROFILE_NOTIFICATION), | 298 | CMD(BT_PROFILE_NOTIFICATION), |
294 | CMD(BT_CONFIG), | 299 | CMD(BT_CONFIG), |
300 | CMD(MCAST_FILTER_CMD), | ||
301 | CMD(REPLY_BEACON_FILTERING_CMD), | ||
302 | CMD(REPLY_THERMAL_MNG_BACKOFF), | ||
295 | }; | 303 | }; |
296 | #undef CMD | 304 | #undef CMD |
297 | 305 | ||
@@ -392,10 +400,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
392 | if (err) | 400 | if (err) |
393 | goto out_free; | 401 | goto out_free; |
394 | 402 | ||
403 | iwl_mvm_tt_initialize(mvm); | ||
404 | |||
395 | mutex_lock(&mvm->mutex); | 405 | mutex_lock(&mvm->mutex); |
396 | err = iwl_run_init_mvm_ucode(mvm, true); | 406 | err = iwl_run_init_mvm_ucode(mvm, true); |
397 | mutex_unlock(&mvm->mutex); | 407 | mutex_unlock(&mvm->mutex); |
398 | if (err && !iwlmvm_mod_params.init_dbg) { | 408 | /* returns 0 if successful, 1 if success but in rfkill */ |
409 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { | ||
399 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); | 410 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); |
400 | goto out_free; | 411 | goto out_free; |
401 | } | 412 | } |
@@ -438,10 +449,16 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
438 | 449 | ||
439 | iwl_mvm_leds_exit(mvm); | 450 | iwl_mvm_leds_exit(mvm); |
440 | 451 | ||
452 | iwl_mvm_tt_exit(mvm); | ||
453 | |||
441 | ieee80211_unregister_hw(mvm->hw); | 454 | ieee80211_unregister_hw(mvm->hw); |
442 | 455 | ||
443 | kfree(mvm->scan_cmd); | 456 | kfree(mvm->scan_cmd); |
444 | 457 | ||
458 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) | ||
459 | kfree(mvm->d3_resume_sram); | ||
460 | #endif | ||
461 | |||
445 | iwl_trans_stop_hw(mvm->trans, true); | 462 | iwl_trans_stop_hw(mvm->trans, true); |
446 | 463 | ||
447 | iwl_phy_db_free(mvm->phy_db); | 464 | 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) | |||
588 | ieee80211_wake_queue(mvm->hw, mq); | 605 | ieee80211_wake_queue(mvm->hw, mq); |
589 | } | 606 | } |
590 | 607 | ||
608 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) | ||
609 | { | ||
610 | if (state) | ||
611 | set_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); | ||
612 | else | ||
613 | clear_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); | ||
614 | |||
615 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); | ||
616 | } | ||
617 | |||
591 | static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 618 | static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
592 | { | 619 | { |
593 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 620 | 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) | |||
597 | else | 624 | else |
598 | clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); | 625 | clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); |
599 | 626 | ||
600 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state); | 627 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); |
601 | } | 628 | } |
602 | 629 | ||
603 | static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | 630 | static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index a28a1d1f23eb..1b4db25d53fb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
@@ -195,21 +195,6 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, | |||
195 | return ret; | 195 | return ret; |
196 | } | 196 | } |
197 | 197 | ||
198 | |||
199 | struct phy_ctx_used_data { | ||
200 | unsigned long used[BITS_TO_LONGS(NUM_PHY_CTX)]; | ||
201 | }; | ||
202 | |||
203 | static void iwl_mvm_phy_ctx_used_iter(struct ieee80211_hw *hw, | ||
204 | struct ieee80211_chanctx_conf *ctx, | ||
205 | void *_data) | ||
206 | { | ||
207 | struct phy_ctx_used_data *data = _data; | ||
208 | struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; | ||
209 | |||
210 | __set_bit(phy_ctxt->id, data->used); | ||
211 | } | ||
212 | |||
213 | /* | 198 | /* |
214 | * Send a command to add a PHY context based on the current HW configuration. | 199 | * Send a command to add a PHY context based on the current HW configuration. |
215 | */ | 200 | */ |
@@ -217,34 +202,27 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | |||
217 | struct cfg80211_chan_def *chandef, | 202 | struct cfg80211_chan_def *chandef, |
218 | u8 chains_static, u8 chains_dynamic) | 203 | u8 chains_static, u8 chains_dynamic) |
219 | { | 204 | { |
220 | struct phy_ctx_used_data data = { | 205 | int ret; |
221 | .used = { }, | ||
222 | }; | ||
223 | |||
224 | /* | ||
225 | * If this is a regular PHY context (not the ROC one) | ||
226 | * skip the ROC PHY context's ID. | ||
227 | */ | ||
228 | if (ctxt != &mvm->phy_ctxt_roc) | ||
229 | __set_bit(mvm->phy_ctxt_roc.id, data.used); | ||
230 | 206 | ||
207 | WARN_ON(ctxt->ref); | ||
231 | lockdep_assert_held(&mvm->mutex); | 208 | lockdep_assert_held(&mvm->mutex); |
232 | ctxt->color++; | ||
233 | 209 | ||
234 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | 210 | ctxt->channel = chandef->chan; |
235 | ieee80211_iter_chan_contexts_atomic( | 211 | ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, |
236 | mvm->hw, iwl_mvm_phy_ctx_used_iter, &data); | 212 | chains_static, chains_dynamic, |
213 | FW_CTXT_ACTION_ADD, 0); | ||
237 | 214 | ||
238 | ctxt->id = find_first_zero_bit(data.used, NUM_PHY_CTX); | 215 | return ret; |
239 | if (WARN_ONCE(ctxt->id == NUM_PHY_CTX, | 216 | } |
240 | "Failed to init PHY context - no free ID!\n")) | ||
241 | return -EIO; | ||
242 | } | ||
243 | 217 | ||
244 | ctxt->channel = chandef->chan; | 218 | /* |
245 | return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, | 219 | * Update the number of references to the given PHY context. This is valid only |
246 | chains_static, chains_dynamic, | 220 | * in case the PHY context was already created, i.e., its reference count > 0. |
247 | FW_CTXT_ACTION_ADD, 0); | 221 | */ |
222 | void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) | ||
223 | { | ||
224 | lockdep_assert_held(&mvm->mutex); | ||
225 | ctxt->ref++; | ||
248 | } | 226 | } |
249 | 227 | ||
250 | /* | 228 | /* |
@@ -264,23 +242,12 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | |||
264 | FW_CTXT_ACTION_MODIFY, 0); | 242 | FW_CTXT_ACTION_MODIFY, 0); |
265 | } | 243 | } |
266 | 244 | ||
267 | /* | 245 | void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) |
268 | * Send a command to the FW to remove the given phy context. | ||
269 | * Once the command is sent, regardless of success or failure, the context is | ||
270 | * marked as invalid | ||
271 | */ | ||
272 | void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) | ||
273 | { | 246 | { |
274 | struct iwl_phy_context_cmd cmd; | ||
275 | int ret; | ||
276 | |||
277 | lockdep_assert_held(&mvm->mutex); | 247 | lockdep_assert_held(&mvm->mutex); |
278 | 248 | ||
279 | iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, FW_CTXT_ACTION_REMOVE, 0); | 249 | if (WARN_ON_ONCE(!ctxt)) |
280 | ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC, | 250 | return; |
281 | sizeof(struct iwl_phy_context_cmd), | 251 | |
282 | &cmd); | 252 | ctxt->ref--; |
283 | if (ret) | ||
284 | IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n", | ||
285 | ctxt->id); | ||
286 | } | 253 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index ed77e437aac4..67cf24aa72f9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -75,6 +75,54 @@ | |||
75 | 75 | ||
76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 | 76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 |
77 | 77 | ||
78 | static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | ||
79 | struct iwl_beacon_filter_cmd *cmd) | ||
80 | { | ||
81 | int ret; | ||
82 | |||
83 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC, | ||
84 | sizeof(struct iwl_beacon_filter_cmd), cmd); | ||
85 | |||
86 | if (!ret) { | ||
87 | IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", | ||
88 | cmd->ba_enable_beacon_abort); | ||
89 | IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", | ||
90 | cmd->ba_escape_timer); | ||
91 | IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", | ||
92 | cmd->bf_debug_flag); | ||
93 | IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", | ||
94 | cmd->bf_enable_beacon_filter); | ||
95 | IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", | ||
96 | cmd->bf_energy_delta); | ||
97 | IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", | ||
98 | cmd->bf_escape_timer); | ||
99 | IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", | ||
100 | cmd->bf_roaming_energy_delta); | ||
101 | IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", | ||
102 | cmd->bf_roaming_state); | ||
103 | IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", | ||
104 | cmd->bf_temperature_delta); | ||
105 | } | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | ||
110 | struct ieee80211_vif *vif, bool enable) | ||
111 | { | ||
112 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
113 | struct iwl_beacon_filter_cmd cmd = { | ||
114 | IWL_BF_CMD_CONFIG_DEFAULTS, | ||
115 | .bf_enable_beacon_filter = 1, | ||
116 | .ba_enable_beacon_abort = enable, | ||
117 | }; | ||
118 | |||
119 | if (!mvmvif->bf_enabled) | ||
120 | return 0; | ||
121 | |||
122 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | ||
123 | return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | ||
124 | } | ||
125 | |||
78 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, | 126 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, |
79 | struct iwl_powertable_cmd *cmd) | 127 | struct iwl_powertable_cmd *cmd) |
80 | { | 128 | { |
@@ -91,6 +139,9 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, | |||
91 | le32_to_cpu(cmd->tx_data_timeout)); | 139 | le32_to_cpu(cmd->tx_data_timeout)); |
92 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | 140 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", |
93 | cmd->lprx_rssi_threshold); | 141 | cmd->lprx_rssi_threshold); |
142 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) | ||
143 | IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", | ||
144 | le32_to_cpu(cmd->skip_dtim_periods)); | ||
94 | } | 145 | } |
95 | } | 146 | } |
96 | 147 | ||
@@ -103,6 +154,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
103 | int dtimper, dtimper_msec; | 154 | int dtimper, dtimper_msec; |
104 | int keep_alive; | 155 | int keep_alive; |
105 | bool radar_detect = false; | 156 | bool radar_detect = false; |
157 | struct iwl_mvm_vif *mvmvif __maybe_unused = | ||
158 | iwl_mvm_vif_from_mac80211(vif); | ||
106 | 159 | ||
107 | /* | 160 | /* |
108 | * Regardless of power management state the driver must set | 161 | * 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, | |||
116 | 169 | ||
117 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 170 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
118 | 171 | ||
172 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
173 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && | ||
174 | mvmvif->dbgfs_pm.disable_power_off) | ||
175 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
176 | #endif | ||
119 | if (!vif->bss_conf.ps) | 177 | if (!vif->bss_conf.ps) |
120 | return; | 178 | return; |
121 | 179 | ||
@@ -135,8 +193,11 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
135 | 193 | ||
136 | /* Check skip over DTIM conditions */ | 194 | /* Check skip over DTIM conditions */ |
137 | if (!radar_detect && (dtimper <= 10) && | 195 | if (!radar_detect && (dtimper <= 10) && |
138 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) | 196 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || |
197 | mvm->cur_ucode == IWL_UCODE_WOWLAN)) { | ||
139 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | 198 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); |
199 | cmd->skip_dtim_periods = cpu_to_le32(3); | ||
200 | } | ||
140 | 201 | ||
141 | /* Check that keep alive period is at least 3 * DTIM */ | 202 | /* Check that keep alive period is at least 3 * DTIM */ |
142 | dtimper_msec = dtimper * vif->bss_conf.beacon_int; | 203 | 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, | |||
145 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | 206 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); |
146 | cmd->keep_alive_seconds = keep_alive; | 207 | cmd->keep_alive_seconds = keep_alive; |
147 | 208 | ||
148 | cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | 209 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { |
149 | cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | 210 | cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); |
211 | cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); | ||
212 | } else { | ||
213 | cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); | ||
214 | cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); | ||
215 | } | ||
216 | |||
217 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
218 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) | ||
219 | cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds; | ||
220 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { | ||
221 | if (mvmvif->dbgfs_pm.skip_over_dtim) | ||
222 | cmd->flags |= | ||
223 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
224 | else | ||
225 | cmd->flags &= | ||
226 | cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
227 | } | ||
228 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT) | ||
229 | cmd->rx_data_timeout = | ||
230 | cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout); | ||
231 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT) | ||
232 | cmd->tx_data_timeout = | ||
233 | cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); | ||
234 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) | ||
235 | cmd->skip_dtim_periods = | ||
236 | cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods); | ||
237 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | ||
150 | } | 238 | } |
151 | 239 | ||
152 | int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 240 | int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
153 | { | 241 | { |
242 | int ret; | ||
243 | bool ba_enable; | ||
154 | struct iwl_powertable_cmd cmd = {}; | 244 | struct iwl_powertable_cmd cmd = {}; |
155 | 245 | ||
156 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 246 | 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) | |||
159 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 249 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
160 | iwl_mvm_power_log(mvm, &cmd); | 250 | iwl_mvm_power_log(mvm, &cmd); |
161 | 251 | ||
162 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, | 252 | ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, |
163 | sizeof(cmd), &cmd); | 253 | sizeof(cmd), &cmd); |
254 | if (ret) | ||
255 | return ret; | ||
256 | |||
257 | ba_enable = !!(cmd.flags & | ||
258 | cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)); | ||
259 | |||
260 | return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); | ||
164 | } | 261 | } |
165 | 262 | ||
166 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 263 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
167 | { | 264 | { |
168 | struct iwl_powertable_cmd cmd = {}; | 265 | struct iwl_powertable_cmd cmd = {}; |
266 | struct iwl_mvm_vif *mvmvif __maybe_unused = | ||
267 | iwl_mvm_vif_from_mac80211(vif); | ||
169 | 268 | ||
170 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 269 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
171 | return 0; | 270 | return 0; |
@@ -173,8 +272,82 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
173 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) | 272 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) |
174 | cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 273 | cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
175 | 274 | ||
275 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
276 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && | ||
277 | mvmvif->dbgfs_pm.disable_power_off) | ||
278 | cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
279 | #endif | ||
176 | iwl_mvm_power_log(mvm, &cmd); | 280 | iwl_mvm_power_log(mvm, &cmd); |
177 | 281 | ||
178 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, | 282 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, |
179 | sizeof(cmd), &cmd); | 283 | sizeof(cmd), &cmd); |
180 | } | 284 | } |
285 | |||
286 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
287 | void | ||
288 | iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, | ||
289 | struct iwl_beacon_filter_cmd *cmd) | ||
290 | { | ||
291 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
292 | struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; | ||
293 | |||
294 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA) | ||
295 | cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta; | ||
296 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA) | ||
297 | cmd->bf_roaming_energy_delta = | ||
298 | dbgfs_bf->bf_roaming_energy_delta; | ||
299 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE) | ||
300 | cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state; | ||
301 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA) | ||
302 | cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta; | ||
303 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG) | ||
304 | cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag; | ||
305 | if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER) | ||
306 | cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer); | ||
307 | if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER) | ||
308 | cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer); | ||
309 | if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT) | ||
310 | cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort; | ||
311 | } | ||
312 | #endif | ||
313 | |||
314 | int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | ||
315 | struct ieee80211_vif *vif) | ||
316 | { | ||
317 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
318 | struct iwl_beacon_filter_cmd cmd = { | ||
319 | IWL_BF_CMD_CONFIG_DEFAULTS, | ||
320 | .bf_enable_beacon_filter = 1, | ||
321 | }; | ||
322 | int ret; | ||
323 | |||
324 | if (mvmvif != mvm->bf_allowed_vif || | ||
325 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
326 | return 0; | ||
327 | |||
328 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | ||
329 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | ||
330 | |||
331 | if (!ret) | ||
332 | mvmvif->bf_enabled = true; | ||
333 | |||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | ||
338 | struct ieee80211_vif *vif) | ||
339 | { | ||
340 | struct iwl_beacon_filter_cmd cmd = {}; | ||
341 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
342 | int ret; | ||
343 | |||
344 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
345 | return 0; | ||
346 | |||
347 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | ||
348 | |||
349 | if (!ret) | ||
350 | mvmvif->bf_enabled = false; | ||
351 | |||
352 | return ret; | ||
353 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 55334d542e26..6a050c69e7d0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -3080,3 +3080,29 @@ void iwl_mvm_rate_control_unregister(void) | |||
3080 | { | 3080 | { |
3081 | ieee80211_rate_control_unregister(&rs_mvm_ops); | 3081 | ieee80211_rate_control_unregister(&rs_mvm_ops); |
3082 | } | 3082 | } |
3083 | |||
3084 | /** | ||
3085 | * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable | ||
3086 | * Tx protection, according to this rquest and previous requests, | ||
3087 | * and send the LQ command. | ||
3088 | * @lq: The LQ command | ||
3089 | * @mvmsta: The station | ||
3090 | * @enable: Enable Tx protection? | ||
3091 | */ | ||
3092 | int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | ||
3093 | struct iwl_mvm_sta *mvmsta, bool enable) | ||
3094 | { | ||
3095 | lockdep_assert_held(&mvm->mutex); | ||
3096 | |||
3097 | if (enable) { | ||
3098 | if (mvmsta->tx_protection == 0) | ||
3099 | lq->flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK; | ||
3100 | mvmsta->tx_protection++; | ||
3101 | } else { | ||
3102 | mvmsta->tx_protection--; | ||
3103 | if (mvmsta->tx_protection == 0) | ||
3104 | lq->flags &= ~LQ_FLAG_SET_STA_TLC_RTS_MSK; | ||
3105 | } | ||
3106 | |||
3107 | return iwl_mvm_send_lq_cmd(mvm, lq, CMD_ASYNC, false); | ||
3108 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 219c6857cc0f..f66155a57238 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -390,4 +390,9 @@ extern int iwl_mvm_rate_control_register(void); | |||
390 | */ | 390 | */ |
391 | extern void iwl_mvm_rate_control_unregister(void); | 391 | extern void iwl_mvm_rate_control_unregister(void); |
392 | 392 | ||
393 | struct iwl_mvm_sta; | ||
394 | |||
395 | int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | ||
396 | struct iwl_mvm_sta *mvmsta, bool enable); | ||
397 | |||
393 | #endif /* __rs__ */ | 398 | #endif /* __rs__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 4dfc21a3e83e..e4930d5027d2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -363,3 +363,25 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
363 | rxb, &rx_status); | 363 | rxb, &rx_status); |
364 | return 0; | 364 | return 0; |
365 | } | 365 | } |
366 | |||
367 | /* | ||
368 | * iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler | ||
369 | * | ||
370 | * TODO: This handler is implemented partially. | ||
371 | * It only gets the NIC's temperature. | ||
372 | */ | ||
373 | int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | ||
374 | struct iwl_rx_cmd_buffer *rxb, | ||
375 | struct iwl_device_cmd *cmd) | ||
376 | { | ||
377 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
378 | struct iwl_notif_statistics *stats = (void *)&pkt->data; | ||
379 | struct mvm_statistics_general_common *common = &stats->general.common; | ||
380 | |||
381 | if (mvm->temperature != le32_to_cpu(common->temperature)) { | ||
382 | mvm->temperature = le32_to_cpu(common->temperature); | ||
383 | iwl_mvm_tt_handler(mvm); | ||
384 | } | ||
385 | |||
386 | return 0; | ||
387 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 0fd96e4da461..2278858d5658 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -64,6 +64,7 @@ | |||
64 | 64 | ||
65 | #include "mvm.h" | 65 | #include "mvm.h" |
66 | #include "sta.h" | 66 | #include "sta.h" |
67 | #include "rs.h" | ||
67 | 68 | ||
68 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) | 69 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) |
69 | { | 70 | { |
@@ -217,9 +218,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
217 | mvmvif->color); | 218 | mvmvif->color); |
218 | mvm_sta->vif = vif; | 219 | mvm_sta->vif = vif; |
219 | mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 220 | mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
221 | mvm_sta->tx_protection = 0; | ||
222 | mvm_sta->tt_tx_protection = false; | ||
220 | 223 | ||
221 | /* HW restart, don't assume the memory has been zeroed */ | 224 | /* HW restart, don't assume the memory has been zeroed */ |
222 | atomic_set(&mvm_sta->pending_frames, 0); | 225 | atomic_set(&mvm->pending_frames[sta_id], 0); |
223 | mvm_sta->tid_disable_agg = 0; | 226 | mvm_sta->tid_disable_agg = 0; |
224 | mvm_sta->tfd_queue_msk = 0; | 227 | mvm_sta->tfd_queue_msk = 0; |
225 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | 228 | for (i = 0; i < IEEE80211_NUM_ACS; i++) |
@@ -407,14 +410,21 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
407 | } | 410 | } |
408 | 411 | ||
409 | /* | 412 | /* |
413 | * Make sure that the tx response code sees the station as -EBUSY and | ||
414 | * calls the drain worker. | ||
415 | */ | ||
416 | spin_lock_bh(&mvm_sta->lock); | ||
417 | /* | ||
410 | * There are frames pending on the AC queues for this station. | 418 | * There are frames pending on the AC queues for this station. |
411 | * We need to wait until all the frames are drained... | 419 | * We need to wait until all the frames are drained... |
412 | */ | 420 | */ |
413 | if (atomic_read(&mvm_sta->pending_frames)) { | 421 | if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) { |
414 | ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); | ||
415 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | 422 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], |
416 | ERR_PTR(-EBUSY)); | 423 | ERR_PTR(-EBUSY)); |
424 | spin_unlock_bh(&mvm_sta->lock); | ||
425 | ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); | ||
417 | } else { | 426 | } else { |
427 | spin_unlock_bh(&mvm_sta->lock); | ||
418 | ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); | 428 | ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); |
419 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); | 429 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); |
420 | } | 430 | } |
@@ -791,21 +801,23 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
791 | min(mvmsta->max_agg_bufsize, buf_size); | 801 | min(mvmsta->max_agg_bufsize, buf_size); |
792 | mvmsta->lq_sta.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize; | 802 | mvmsta->lq_sta.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize; |
793 | 803 | ||
804 | IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n", | ||
805 | sta->addr, tid); | ||
806 | |||
794 | if (mvm->cfg->ht_params->use_rts_for_aggregation) { | 807 | if (mvm->cfg->ht_params->use_rts_for_aggregation) { |
795 | /* | 808 | /* |
796 | * switch to RTS/CTS if it is the prefer protection | 809 | * switch to RTS/CTS if it is the prefer protection |
797 | * method for HT traffic | 810 | * method for HT traffic |
811 | * this function also sends the LQ command | ||
798 | */ | 812 | */ |
799 | mvmsta->lq_sta.lq.flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK; | 813 | return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, |
814 | mvmsta, true); | ||
800 | /* | 815 | /* |
801 | * TODO: remove the TLC_RTS flag when we tear down the last | 816 | * TODO: remove the TLC_RTS flag when we tear down the last |
802 | * AGG session (agg_tids_count in DVM) | 817 | * AGG session (agg_tids_count in DVM) |
803 | */ | 818 | */ |
804 | } | 819 | } |
805 | 820 | ||
806 | IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n", | ||
807 | sta->addr, tid); | ||
808 | |||
809 | return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false); | 821 | return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false); |
810 | } | 822 | } |
811 | 823 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 12abd2d71835..3efa0a0cc987 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -274,8 +274,9 @@ struct iwl_mvm_tid_data { | |||
274 | * @bt_reduced_txpower: is reduced tx power enabled for this station | 274 | * @bt_reduced_txpower: is reduced tx power enabled for this station |
275 | * @lock: lock to protect the whole struct. Since %tid_data is access from Tx | 275 | * @lock: lock to protect the whole struct. Since %tid_data is access from Tx |
276 | * and from Tx response flow, it needs a spinlock. | 276 | * and from Tx response flow, it needs a spinlock. |
277 | * @pending_frames: number of frames for this STA on the shared Tx queues. | ||
278 | * @tid_data: per tid data. Look at %iwl_mvm_tid_data. | 277 | * @tid_data: per tid data. Look at %iwl_mvm_tid_data. |
278 | * @tx_protection: reference counter for controlling the Tx protection. | ||
279 | * @tt_tx_protection: is thermal throttling enable Tx protection? | ||
279 | * | 280 | * |
280 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) | 281 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) |
281 | * in the structure for use by driver. This structure is placed in that | 282 | * in the structure for use by driver. This structure is placed in that |
@@ -290,7 +291,6 @@ struct iwl_mvm_sta { | |||
290 | u8 max_agg_bufsize; | 291 | u8 max_agg_bufsize; |
291 | bool bt_reduced_txpower; | 292 | bool bt_reduced_txpower; |
292 | spinlock_t lock; | 293 | spinlock_t lock; |
293 | atomic_t pending_frames; | ||
294 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; | 294 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; |
295 | struct iwl_lq_sta lq_sta; | 295 | struct iwl_lq_sta lq_sta; |
296 | struct ieee80211_vif *vif; | 296 | struct ieee80211_vif *vif; |
@@ -298,6 +298,10 @@ struct iwl_mvm_sta { | |||
298 | #ifdef CONFIG_PM_SLEEP | 298 | #ifdef CONFIG_PM_SLEEP |
299 | u16 last_seq_ctl; | 299 | u16 last_seq_ctl; |
300 | #endif | 300 | #endif |
301 | |||
302 | /* Temporary, until the new TLC will control the Tx protection */ | ||
303 | s8 tx_protection; | ||
304 | bool tt_tx_protection; | ||
301 | }; | 305 | }; |
302 | 306 | ||
303 | /** | 307 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c new file mode 100644 index 000000000000..4665fc033c17 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -0,0 +1,509 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include "mvm.h" | ||
65 | #include "iwl-config.h" | ||
66 | #include "iwl-io.h" | ||
67 | #include "iwl-csr.h" | ||
68 | #include "iwl-prph.h" | ||
69 | |||
70 | #define OTP_DTS_DIODE_DEVIATION 96 /*in words*/ | ||
71 | /* VBG - Voltage Band Gap error data (temperature offset) */ | ||
72 | #define OTP_WP_DTS_VBG (OTP_DTS_DIODE_DEVIATION + 2) | ||
73 | #define MEAS_VBG_MIN_VAL 2300 | ||
74 | #define MEAS_VBG_MAX_VAL 3000 | ||
75 | #define MEAS_VBG_DEFAULT_VAL 2700 | ||
76 | #define DTS_DIODE_VALID(flags) (flags & DTS_DIODE_REG_FLAGS_PASS_ONCE) | ||
77 | #define MIN_TEMPERATURE 0 | ||
78 | #define MAX_TEMPERATURE 125 | ||
79 | #define TEMPERATURE_ERROR (MAX_TEMPERATURE + 1) | ||
80 | #define PTAT_DIGITAL_VALUE_MIN_VALUE 0 | ||
81 | #define PTAT_DIGITAL_VALUE_MAX_VALUE 0xFF | ||
82 | #define DTS_VREFS_NUM 5 | ||
83 | static inline u32 DTS_DIODE_GET_VREFS_ID(u32 flags) | ||
84 | { | ||
85 | return (flags & DTS_DIODE_REG_FLAGS_VREFS_ID) >> | ||
86 | DTS_DIODE_REG_FLAGS_VREFS_ID_POS; | ||
87 | } | ||
88 | |||
89 | #define CALC_VREFS_MIN_DIFF 43 | ||
90 | #define CALC_VREFS_MAX_DIFF 51 | ||
91 | #define CALC_LUT_SIZE (1 + CALC_VREFS_MAX_DIFF - CALC_VREFS_MIN_DIFF) | ||
92 | #define CALC_LUT_INDEX_OFFSET CALC_VREFS_MIN_DIFF | ||
93 | #define CALC_TEMPERATURE_RESULT_SHIFT_OFFSET 23 | ||
94 | |||
95 | /* | ||
96 | * @digital_value: The diode's digital-value sampled (temperature/voltage) | ||
97 | * @vref_low: The lower voltage-reference (the vref just below the diode's | ||
98 | * sampled digital-value) | ||
99 | * @vref_high: The higher voltage-reference (the vref just above the diode's | ||
100 | * sampled digital-value) | ||
101 | * @flags: bits[1:0]: The ID of the Vrefs pair (lowVref,highVref) | ||
102 | * bits[6:2]: Reserved. | ||
103 | * bits[7:7]: Indicates completion of at least 1 successful sample | ||
104 | * since last DTS reset. | ||
105 | */ | ||
106 | struct iwl_mvm_dts_diode_bits { | ||
107 | u8 digital_value; | ||
108 | u8 vref_low; | ||
109 | u8 vref_high; | ||
110 | u8 flags; | ||
111 | } __packed; | ||
112 | |||
113 | union dts_diode_results { | ||
114 | u32 reg_value; | ||
115 | struct iwl_mvm_dts_diode_bits bits; | ||
116 | } __packed; | ||
117 | |||
118 | static s16 iwl_mvm_dts_get_volt_band_gap(struct iwl_mvm *mvm) | ||
119 | { | ||
120 | struct iwl_nvm_section calib_sec; | ||
121 | const __le16 *calib; | ||
122 | u16 vbg; | ||
123 | |||
124 | /* TODO: move parsing to NVM code */ | ||
125 | calib_sec = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION]; | ||
126 | calib = (__le16 *)calib_sec.data; | ||
127 | |||
128 | vbg = le16_to_cpu(calib[OTP_WP_DTS_VBG]); | ||
129 | |||
130 | if (vbg < MEAS_VBG_MIN_VAL || vbg > MEAS_VBG_MAX_VAL) | ||
131 | vbg = MEAS_VBG_DEFAULT_VAL; | ||
132 | |||
133 | return vbg; | ||
134 | } | ||
135 | |||
136 | static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm) | ||
137 | { | ||
138 | const u8 *calib; | ||
139 | u8 ptat, pa1, pa2, median; | ||
140 | |||
141 | /* TODO: move parsing to NVM code */ | ||
142 | calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data; | ||
143 | ptat = calib[OTP_DTS_DIODE_DEVIATION]; | ||
144 | pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1]; | ||
145 | pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2]; | ||
146 | |||
147 | /* get the median: */ | ||
148 | if (ptat > pa1) { | ||
149 | if (ptat > pa2) | ||
150 | median = (pa1 > pa2) ? pa1 : pa2; | ||
151 | else | ||
152 | median = ptat; | ||
153 | } else { | ||
154 | if (pa1 > pa2) | ||
155 | median = (ptat > pa2) ? ptat : pa2; | ||
156 | else | ||
157 | median = pa1; | ||
158 | } | ||
159 | |||
160 | return ptat - median; | ||
161 | } | ||
162 | |||
163 | static u8 iwl_mvm_dts_calibrate_ptat_deviation(struct iwl_mvm *mvm, u8 value) | ||
164 | { | ||
165 | /* Calibrate the PTAT digital value, based on PTAT deviation data: */ | ||
166 | s16 new_val = value - iwl_mvm_dts_get_ptat_deviation_offset(mvm); | ||
167 | |||
168 | if (new_val > PTAT_DIGITAL_VALUE_MAX_VALUE) | ||
169 | new_val = PTAT_DIGITAL_VALUE_MAX_VALUE; | ||
170 | else if (new_val < PTAT_DIGITAL_VALUE_MIN_VALUE) | ||
171 | new_val = PTAT_DIGITAL_VALUE_MIN_VALUE; | ||
172 | |||
173 | return new_val; | ||
174 | } | ||
175 | |||
176 | static bool dts_get_adjacent_vrefs(struct iwl_mvm *mvm, | ||
177 | union dts_diode_results *avg_ptat) | ||
178 | { | ||
179 | u8 vrefs_results[DTS_VREFS_NUM]; | ||
180 | u8 low_vref_index = 0, flags; | ||
181 | u32 reg; | ||
182 | |||
183 | reg = iwl_read_prph(mvm->trans, DTSC_VREF_AVG); | ||
184 | memcpy(vrefs_results, ®, sizeof(reg)); | ||
185 | reg = iwl_read_prph(mvm->trans, DTSC_VREF5_AVG); | ||
186 | vrefs_results[4] = reg & 0xff; | ||
187 | |||
188 | if (avg_ptat->bits.digital_value < vrefs_results[0] || | ||
189 | avg_ptat->bits.digital_value > vrefs_results[4]) | ||
190 | return false; | ||
191 | |||
192 | if (avg_ptat->bits.digital_value > vrefs_results[3]) | ||
193 | low_vref_index = 3; | ||
194 | else if (avg_ptat->bits.digital_value > vrefs_results[2]) | ||
195 | low_vref_index = 2; | ||
196 | else if (avg_ptat->bits.digital_value > vrefs_results[1]) | ||
197 | low_vref_index = 1; | ||
198 | |||
199 | avg_ptat->bits.vref_low = vrefs_results[low_vref_index]; | ||
200 | avg_ptat->bits.vref_high = vrefs_results[low_vref_index + 1]; | ||
201 | flags = avg_ptat->bits.flags; | ||
202 | avg_ptat->bits.flags = | ||
203 | (flags & ~DTS_DIODE_REG_FLAGS_VREFS_ID) | | ||
204 | (low_vref_index & DTS_DIODE_REG_FLAGS_VREFS_ID); | ||
205 | return true; | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * return true it the results are valid, and false otherwise. | ||
210 | */ | ||
211 | static bool dts_read_ptat_avg_results(struct iwl_mvm *mvm, | ||
212 | union dts_diode_results *avg_ptat) | ||
213 | { | ||
214 | u32 reg; | ||
215 | u8 tmp; | ||
216 | |||
217 | /* fill the diode value and pass_once with avg-reg results */ | ||
218 | reg = iwl_read_prph(mvm->trans, DTSC_PTAT_AVG); | ||
219 | reg &= DTS_DIODE_REG_DIG_VAL | DTS_DIODE_REG_PASS_ONCE; | ||
220 | avg_ptat->reg_value = reg; | ||
221 | |||
222 | /* calibrate the PTAT digital value */ | ||
223 | tmp = avg_ptat->bits.digital_value; | ||
224 | tmp = iwl_mvm_dts_calibrate_ptat_deviation(mvm, tmp); | ||
225 | avg_ptat->bits.digital_value = tmp; | ||
226 | |||
227 | /* | ||
228 | * fill vrefs fields, based on the avgVrefs results | ||
229 | * and the diode value | ||
230 | */ | ||
231 | return dts_get_adjacent_vrefs(mvm, avg_ptat) && | ||
232 | DTS_DIODE_VALID(avg_ptat->bits.flags); | ||
233 | } | ||
234 | |||
235 | static s32 calculate_nic_temperature(union dts_diode_results avg_ptat, | ||
236 | u16 volt_band_gap) | ||
237 | { | ||
238 | u32 tmp_result; | ||
239 | u8 vrefs_diff; | ||
240 | /* | ||
241 | * For temperature calculation (at the end, shift right by 23) | ||
242 | * LUT[(D2-D1)] = ROUND{ 2^23 / ((D2-D1)*9*10) } | ||
243 | * (D2-D1) == 43 44 45 46 47 48 49 50 51 | ||
244 | */ | ||
245 | static const u16 calc_lut[CALC_LUT_SIZE] = { | ||
246 | 2168, 2118, 2071, 2026, 1983, 1942, 1902, 1864, 1828, | ||
247 | }; | ||
248 | |||
249 | /* | ||
250 | * The diff between the high and low voltage-references is assumed | ||
251 | * to be strictly be in range of [60,68] | ||
252 | */ | ||
253 | vrefs_diff = avg_ptat.bits.vref_high - avg_ptat.bits.vref_low; | ||
254 | |||
255 | if (vrefs_diff < CALC_VREFS_MIN_DIFF || | ||
256 | vrefs_diff > CALC_VREFS_MAX_DIFF) | ||
257 | return TEMPERATURE_ERROR; | ||
258 | |||
259 | /* calculate the result: */ | ||
260 | tmp_result = | ||
261 | vrefs_diff * (DTS_DIODE_GET_VREFS_ID(avg_ptat.bits.flags) + 9); | ||
262 | tmp_result += avg_ptat.bits.digital_value; | ||
263 | tmp_result -= avg_ptat.bits.vref_high; | ||
264 | |||
265 | /* multiply by the LUT value (based on the diff) */ | ||
266 | tmp_result *= calc_lut[vrefs_diff - CALC_LUT_INDEX_OFFSET]; | ||
267 | |||
268 | /* | ||
269 | * Get the BandGap (the voltage refereces source) error data | ||
270 | * (temperature offset) | ||
271 | */ | ||
272 | tmp_result *= volt_band_gap; | ||
273 | |||
274 | /* | ||
275 | * here, tmp_result value can be up to 32-bits. We want to right-shift | ||
276 | * it *without* sign-extend. | ||
277 | */ | ||
278 | tmp_result = tmp_result >> CALC_TEMPERATURE_RESULT_SHIFT_OFFSET; | ||
279 | |||
280 | /* | ||
281 | * at this point, tmp_result should be in the range: | ||
282 | * 200 <= tmp_result <= 365 | ||
283 | */ | ||
284 | return (s16)tmp_result - 240; | ||
285 | } | ||
286 | |||
287 | static s32 check_nic_temperature(struct iwl_mvm *mvm) | ||
288 | { | ||
289 | u16 volt_band_gap; | ||
290 | union dts_diode_results avg_ptat; | ||
291 | |||
292 | volt_band_gap = iwl_mvm_dts_get_volt_band_gap(mvm); | ||
293 | |||
294 | /* disable DTS */ | ||
295 | iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0); | ||
296 | |||
297 | /* SV initialization */ | ||
298 | iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 1); | ||
299 | iwl_write_prph(mvm->trans, DTSC_CFG_MODE, | ||
300 | DTSC_CFG_MODE_PERIODIC); | ||
301 | |||
302 | /* wait for results */ | ||
303 | msleep(100); | ||
304 | if (!dts_read_ptat_avg_results(mvm, &avg_ptat)) | ||
305 | return TEMPERATURE_ERROR; | ||
306 | |||
307 | /* disable DTS */ | ||
308 | iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0); | ||
309 | |||
310 | return calculate_nic_temperature(avg_ptat, volt_band_gap); | ||
311 | } | ||
312 | |||
313 | static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm) | ||
314 | { | ||
315 | u32 duration = mvm->thermal_throttle.params->ct_kill_duration; | ||
316 | |||
317 | IWL_ERR(mvm, "Enter CT Kill\n"); | ||
318 | iwl_mvm_set_hw_ctkill_state(mvm, true); | ||
319 | schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit, | ||
320 | round_jiffies_relative(duration * HZ)); | ||
321 | } | ||
322 | |||
323 | static void iwl_mvm_exit_ctkill(struct iwl_mvm *mvm) | ||
324 | { | ||
325 | IWL_ERR(mvm, "Exit CT Kill\n"); | ||
326 | iwl_mvm_set_hw_ctkill_state(mvm, false); | ||
327 | } | ||
328 | |||
329 | static void check_exit_ctkill(struct work_struct *work) | ||
330 | { | ||
331 | struct iwl_mvm_tt_mgmt *tt; | ||
332 | struct iwl_mvm *mvm; | ||
333 | u32 duration; | ||
334 | s32 temp; | ||
335 | |||
336 | tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work); | ||
337 | mvm = container_of(tt, struct iwl_mvm, thermal_throttle); | ||
338 | |||
339 | duration = tt->params->ct_kill_duration; | ||
340 | |||
341 | iwl_trans_start_hw(mvm->trans); | ||
342 | temp = check_nic_temperature(mvm); | ||
343 | iwl_trans_stop_hw(mvm->trans, false); | ||
344 | |||
345 | if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { | ||
346 | IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); | ||
347 | goto reschedule; | ||
348 | } | ||
349 | IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp); | ||
350 | |||
351 | if (temp <= tt->params->ct_kill_exit) { | ||
352 | iwl_mvm_exit_ctkill(mvm); | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | reschedule: | ||
357 | schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit, | ||
358 | round_jiffies(duration * HZ)); | ||
359 | } | ||
360 | |||
361 | static void iwl_mvm_tt_smps_iterator(void *_data, u8 *mac, | ||
362 | struct ieee80211_vif *vif) | ||
363 | { | ||
364 | struct iwl_mvm *mvm = _data; | ||
365 | enum ieee80211_smps_mode smps_mode; | ||
366 | |||
367 | lockdep_assert_held(&mvm->mutex); | ||
368 | |||
369 | if (mvm->thermal_throttle.dynamic_smps) | ||
370 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
371 | else | ||
372 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
373 | |||
374 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode); | ||
375 | } | ||
376 | |||
377 | static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable) | ||
378 | { | ||
379 | struct ieee80211_sta *sta; | ||
380 | struct iwl_mvm_sta *mvmsta; | ||
381 | int i, err; | ||
382 | |||
383 | for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { | ||
384 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], | ||
385 | lockdep_is_held(&mvm->mutex)); | ||
386 | if (IS_ERR_OR_NULL(sta)) | ||
387 | continue; | ||
388 | mvmsta = (void *)sta->drv_priv; | ||
389 | if (enable == mvmsta->tt_tx_protection) | ||
390 | continue; | ||
391 | err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, | ||
392 | mvmsta, enable); | ||
393 | if (err) { | ||
394 | IWL_ERR(mvm, "Failed to %s Tx protection\n", | ||
395 | enable ? "enable" : "disable"); | ||
396 | } else { | ||
397 | IWL_DEBUG_TEMP(mvm, "%s Tx protection\n", | ||
398 | enable ? "Enable" : "Disable"); | ||
399 | mvmsta->tt_tx_protection = enable; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff) | ||
405 | { | ||
406 | struct iwl_host_cmd cmd = { | ||
407 | .id = REPLY_THERMAL_MNG_BACKOFF, | ||
408 | .len = { sizeof(u32), }, | ||
409 | .data = { &backoff, }, | ||
410 | .flags = CMD_SYNC, | ||
411 | }; | ||
412 | |||
413 | if (iwl_mvm_send_cmd(mvm, &cmd) == 0) { | ||
414 | IWL_DEBUG_TEMP(mvm, "Set Thermal Tx backoff to: %u\n", | ||
415 | backoff); | ||
416 | mvm->thermal_throttle.tx_backoff = backoff; | ||
417 | } else { | ||
418 | IWL_ERR(mvm, "Failed to change Thermal Tx backoff\n"); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | void iwl_mvm_tt_handler(struct iwl_mvm *mvm) | ||
423 | { | ||
424 | const struct iwl_tt_params *params = mvm->thermal_throttle.params; | ||
425 | struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; | ||
426 | s32 temperature = mvm->temperature; | ||
427 | int i; | ||
428 | u32 tx_backoff; | ||
429 | |||
430 | IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", mvm->temperature); | ||
431 | |||
432 | if (params->support_ct_kill && temperature >= params->ct_kill_entry) { | ||
433 | iwl_mvm_enter_ctkill(mvm); | ||
434 | return; | ||
435 | } | ||
436 | |||
437 | if (params->support_dynamic_smps) { | ||
438 | if (!tt->dynamic_smps && | ||
439 | temperature >= params->dynamic_smps_entry) { | ||
440 | IWL_DEBUG_TEMP(mvm, "Enable dynamic SMPS\n"); | ||
441 | tt->dynamic_smps = true; | ||
442 | ieee80211_iterate_active_interfaces_atomic( | ||
443 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
444 | iwl_mvm_tt_smps_iterator, mvm); | ||
445 | } else if (tt->dynamic_smps && | ||
446 | temperature <= params->dynamic_smps_exit) { | ||
447 | IWL_DEBUG_TEMP(mvm, "Disable dynamic SMPS\n"); | ||
448 | tt->dynamic_smps = false; | ||
449 | ieee80211_iterate_active_interfaces_atomic( | ||
450 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
451 | iwl_mvm_tt_smps_iterator, mvm); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | if (params->support_tx_protection) { | ||
456 | if (temperature >= params->tx_protection_entry) | ||
457 | iwl_mvm_tt_tx_protection(mvm, true); | ||
458 | else if (temperature <= params->tx_protection_exit) | ||
459 | iwl_mvm_tt_tx_protection(mvm, false); | ||
460 | } | ||
461 | |||
462 | if (params->support_tx_backoff) { | ||
463 | tx_backoff = 0; | ||
464 | for (i = 0; i < TT_TX_BACKOFF_SIZE; i++) { | ||
465 | if (temperature < params->tx_backoff[i].temperature) | ||
466 | break; | ||
467 | tx_backoff = params->tx_backoff[i].backoff; | ||
468 | } | ||
469 | if (tt->tx_backoff != tx_backoff) | ||
470 | iwl_mvm_tt_tx_backoff(mvm, tx_backoff); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | static const struct iwl_tt_params iwl7000_tt_params = { | ||
475 | .ct_kill_entry = 118, | ||
476 | .ct_kill_exit = 96, | ||
477 | .ct_kill_duration = 5, | ||
478 | .dynamic_smps_entry = 114, | ||
479 | .dynamic_smps_exit = 110, | ||
480 | .tx_protection_entry = 114, | ||
481 | .tx_protection_exit = 108, | ||
482 | .tx_backoff = { | ||
483 | {.temperature = 112, .backoff = 200}, | ||
484 | {.temperature = 113, .backoff = 600}, | ||
485 | {.temperature = 114, .backoff = 1200}, | ||
486 | {.temperature = 115, .backoff = 2000}, | ||
487 | {.temperature = 116, .backoff = 4000}, | ||
488 | {.temperature = 117, .backoff = 10000}, | ||
489 | }, | ||
490 | .support_ct_kill = true, | ||
491 | .support_dynamic_smps = true, | ||
492 | .support_tx_protection = true, | ||
493 | .support_tx_backoff = true, | ||
494 | }; | ||
495 | |||
496 | void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) | ||
497 | { | ||
498 | struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; | ||
499 | |||
500 | IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); | ||
501 | tt->params = &iwl7000_tt_params; | ||
502 | INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); | ||
503 | } | ||
504 | |||
505 | void iwl_mvm_tt_exit(struct iwl_mvm *mvm) | ||
506 | { | ||
507 | cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit); | ||
508 | IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n"); | ||
509 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 479074303bd7..f212f16502ff 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -416,9 +416,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
416 | 416 | ||
417 | spin_unlock(&mvmsta->lock); | 417 | spin_unlock(&mvmsta->lock); |
418 | 418 | ||
419 | if (mvmsta->vif->type == NL80211_IFTYPE_AP && | 419 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE) |
420 | txq_id < IWL_MVM_FIRST_AGG_QUEUE) | 420 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); |
421 | atomic_inc(&mvmsta->pending_frames); | ||
422 | 421 | ||
423 | return 0; | 422 | return 0; |
424 | 423 | ||
@@ -680,16 +679,41 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
680 | /* | 679 | /* |
681 | * If the txq is not an AMPDU queue, there is no chance we freed | 680 | * If the txq is not an AMPDU queue, there is no chance we freed |
682 | * several skbs. Check that out... | 681 | * several skbs. Check that out... |
683 | * If there are no pending frames for this STA, notify mac80211 that | ||
684 | * this station can go to sleep in its STA table. | ||
685 | */ | 682 | */ |
686 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta && | 683 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && !WARN_ON(skb_freed > 1) && |
687 | !WARN_ON(skb_freed > 1) && | 684 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { |
688 | mvmsta->vif->type == NL80211_IFTYPE_AP && | 685 | if (mvmsta) { |
689 | atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { | 686 | /* |
690 | ieee80211_sta_block_awake(mvm->hw, sta, false); | 687 | * If there are no pending frames for this STA, notify |
691 | set_bit(sta_id, mvm->sta_drained); | 688 | * mac80211 that this station can go to sleep in its |
692 | schedule_work(&mvm->sta_drained_wk); | 689 | * STA table. |
690 | */ | ||
691 | if (mvmsta->vif->type == NL80211_IFTYPE_AP) | ||
692 | ieee80211_sta_block_awake(mvm->hw, sta, false); | ||
693 | /* | ||
694 | * We might very well have taken mvmsta pointer while | ||
695 | * the station was being removed. The remove flow might | ||
696 | * have seen a pending_frame (because we didn't take | ||
697 | * the lock) even if now the queues are drained. So make | ||
698 | * really sure now that this the station is not being | ||
699 | * removed. If it is, run the drain worker to remove it. | ||
700 | */ | ||
701 | spin_lock_bh(&mvmsta->lock); | ||
702 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | ||
703 | if (IS_ERR_OR_NULL(sta)) { | ||
704 | /* | ||
705 | * Station disappeared in the meantime: | ||
706 | * so we are draining. | ||
707 | */ | ||
708 | set_bit(sta_id, mvm->sta_drained); | ||
709 | schedule_work(&mvm->sta_drained_wk); | ||
710 | } | ||
711 | spin_unlock_bh(&mvmsta->lock); | ||
712 | } else if (!mvmsta) { | ||
713 | /* Tx response without STA, so we are draining */ | ||
714 | set_bit(sta_id, mvm->sta_drained); | ||
715 | schedule_work(&mvm->sta_drained_wk); | ||
716 | } | ||
693 | } | 717 | } |
694 | 718 | ||
695 | rcu_read_unlock(); | 719 | rcu_read_unlock(); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 687b34e387ac..c9b44ab4af07 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -471,3 +471,34 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | |||
471 | 471 | ||
472 | return iwl_mvm_send_cmd(mvm, &cmd); | 472 | return iwl_mvm_send_cmd(mvm, &cmd); |
473 | } | 473 | } |
474 | |||
475 | /** | ||
476 | * iwl_mvm_update_smps - Get a requst to change the SMPS mode | ||
477 | * @req_type: The part of the driver who call for a change. | ||
478 | * @smps_requests: The request to change the SMPS mode. | ||
479 | * | ||
480 | * Get a requst to change the SMPS mode, | ||
481 | * and change it according to all other requests in the driver. | ||
482 | */ | ||
483 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
484 | enum iwl_mvm_smps_type_request req_type, | ||
485 | enum ieee80211_smps_mode smps_request) | ||
486 | { | ||
487 | struct iwl_mvm_vif *mvmvif; | ||
488 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
489 | int i; | ||
490 | |||
491 | lockdep_assert_held(&mvm->mutex); | ||
492 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
493 | mvmvif->smps_requests[req_type] = smps_request; | ||
494 | for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { | ||
495 | if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC) { | ||
496 | smps_mode = IEEE80211_SMPS_STATIC; | ||
497 | break; | ||
498 | } | ||
499 | if (mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) | ||
500 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
501 | } | ||
502 | |||
503 | ieee80211_request_smps(vif, smps_mode); | ||
504 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 8cb53ec2b77b..db7bdd35a9c5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -256,10 +256,54 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
256 | 256 | ||
257 | /* 7000 Series */ | 257 | /* 7000 Series */ |
258 | {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, | 258 | {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, |
259 | {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_2ac_cfg)}, | 259 | {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, |
260 | {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)}, | ||
261 | {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)}, | ||
262 | {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)}, | ||
263 | {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)}, | ||
264 | {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)}, | ||
265 | {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)}, | ||
266 | {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)}, | ||
267 | {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)}, | ||
268 | {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)}, | ||
269 | {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, | ||
270 | {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, | ||
271 | {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, | ||
272 | {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)}, | ||
273 | {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)}, | ||
274 | {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)}, | ||
275 | {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, | ||
276 | {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, | ||
277 | {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, | ||
260 | {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)}, | 278 | {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)}, |
261 | {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_ac_cfg)}, | 279 | {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)}, |
262 | {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_ac_cfg)}, | 280 | {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)}, |
281 | {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)}, | ||
282 | {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)}, | ||
283 | {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)}, | ||
284 | {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)}, | ||
285 | {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)}, | ||
286 | {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)}, | ||
287 | {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)}, | ||
288 | {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)}, | ||
289 | {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)}, | ||
290 | {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)}, | ||
291 | {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)}, | ||
292 | {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)}, | ||
293 | |||
294 | /* 3160 Series */ | ||
295 | {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)}, | ||
296 | {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)}, | ||
297 | {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)}, | ||
298 | {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)}, | ||
299 | {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)}, | ||
300 | {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)}, | ||
301 | {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)}, | ||
302 | {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)}, | ||
303 | {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)}, | ||
304 | {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)}, | ||
305 | {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, | ||
306 | {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, | ||
263 | 307 | ||
264 | {0} | 308 | {0} |
265 | }; | 309 | }; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 50ba0a468f94..0b021305eedf 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -405,20 +405,27 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, | |||
405 | { | 405 | { |
406 | u8 *v_addr; | 406 | u8 *v_addr; |
407 | dma_addr_t p_addr; | 407 | dma_addr_t p_addr; |
408 | u32 offset; | 408 | u32 offset, chunk_sz = section->len; |
409 | int ret = 0; | 409 | int ret = 0; |
410 | 410 | ||
411 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", | 411 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", |
412 | section_num); | 412 | section_num); |
413 | 413 | ||
414 | v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL); | 414 | v_addr = dma_alloc_coherent(trans->dev, chunk_sz, &p_addr, |
415 | if (!v_addr) | 415 | GFP_KERNEL | __GFP_NOWARN); |
416 | return -ENOMEM; | 416 | if (!v_addr) { |
417 | IWL_DEBUG_INFO(trans, "Falling back to small chunks of DMA\n"); | ||
418 | chunk_sz = PAGE_SIZE; | ||
419 | v_addr = dma_alloc_coherent(trans->dev, chunk_sz, | ||
420 | &p_addr, GFP_KERNEL); | ||
421 | if (!v_addr) | ||
422 | return -ENOMEM; | ||
423 | } | ||
417 | 424 | ||
418 | for (offset = 0; offset < section->len; offset += PAGE_SIZE) { | 425 | for (offset = 0; offset < section->len; offset += chunk_sz) { |
419 | u32 copy_size; | 426 | u32 copy_size; |
420 | 427 | ||
421 | copy_size = min_t(u32, PAGE_SIZE, section->len - offset); | 428 | copy_size = min_t(u32, chunk_sz, section->len - offset); |
422 | 429 | ||
423 | memcpy(v_addr, (u8 *)section->data + offset, copy_size); | 430 | memcpy(v_addr, (u8 *)section->data + offset, copy_size); |
424 | ret = iwl_pcie_load_firmware_chunk(trans, | 431 | ret = iwl_pcie_load_firmware_chunk(trans, |
@@ -432,7 +439,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, | |||
432 | } | 439 | } |
433 | } | 440 | } |
434 | 441 | ||
435 | dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr); | 442 | dma_free_coherent(trans->dev, chunk_sz, v_addr, p_addr); |
436 | return ret; | 443 | return ret; |
437 | } | 444 | } |
438 | 445 | ||
@@ -573,10 +580,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
573 | 580 | ||
574 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) | 581 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) |
575 | { | 582 | { |
576 | /* let the ucode operate on its own */ | ||
577 | iwl_write32(trans, CSR_UCODE_DRV_GP1_SET, | ||
578 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
579 | |||
580 | iwl_disable_interrupts(trans); | 583 | iwl_disable_interrupts(trans); |
581 | iwl_pcie_disable_ict(trans); | 584 | iwl_pcie_disable_ict(trans); |
582 | 585 | ||
@@ -636,9 +639,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
636 | return ret; | 639 | return ret; |
637 | } | 640 | } |
638 | 641 | ||
639 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, | ||
640 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
641 | |||
642 | *status = IWL_D3_STATUS_ALIVE; | 642 | *status = IWL_D3_STATUS_ALIVE; |
643 | return 0; | 643 | return 0; |
644 | } | 644 | } |
@@ -917,11 +917,11 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, | |||
917 | } | 917 | } |
918 | 918 | ||
919 | static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, | 919 | static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, |
920 | void *buf, int dwords) | 920 | const void *buf, int dwords) |
921 | { | 921 | { |
922 | unsigned long flags; | 922 | unsigned long flags; |
923 | int offs, ret = 0; | 923 | int offs, ret = 0; |
924 | u32 *vals = buf; | 924 | const u32 *vals = buf; |
925 | 925 | ||
926 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { | 926 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
927 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); | 927 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index c5e30294c5ac..bf5f8246385e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1045,6 +1045,10 @@ static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans, | |||
1045 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | 1045 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | /* Receiver address (actually, Rx station's index into station table), | ||
1049 | * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ | ||
1050 | #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) | ||
1051 | |||
1048 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | 1052 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, |
1049 | int sta_id, int tid, int frame_limit, u16 ssn) | 1053 | int sta_id, int tid, int frame_limit, u16 ssn) |
1050 | { | 1054 | { |
@@ -1518,6 +1522,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1518 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { | 1522 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { |
1519 | IWL_ERR(trans, "FW error in SYNC CMD %s\n", | 1523 | IWL_ERR(trans, "FW error in SYNC CMD %s\n", |
1520 | get_cmd_string(trans_pcie, cmd->id)); | 1524 | get_cmd_string(trans_pcie, cmd->id)); |
1525 | dump_stack(); | ||
1521 | ret = -EIO; | 1526 | ret = -EIO; |
1522 | goto cancel; | 1527 | goto cancel; |
1523 | } | 1528 | } |
@@ -1564,7 +1569,8 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
1564 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) | 1569 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) |
1565 | return -EIO; | 1570 | return -EIO; |
1566 | 1571 | ||
1567 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { | 1572 | if (!(cmd->flags & CMD_SEND_IN_RFKILL) && |
1573 | test_bit(STATUS_RFKILL, &trans_pcie->status)) { | ||
1568 | IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", | 1574 | IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", |
1569 | cmd->id); | 1575 | cmd->id); |
1570 | return -ERFKILL; | 1576 | return -ERFKILL; |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index af79daa331d0..00a82817eb6b 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -2282,9 +2282,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2282 | if (wdev->netdev->reg_state == NETREG_REGISTERED) | 2282 | if (wdev->netdev->reg_state == NETREG_REGISTERED) |
2283 | unregister_netdevice(wdev->netdev); | 2283 | unregister_netdevice(wdev->netdev); |
2284 | 2284 | ||
2285 | if (wdev->netdev->reg_state == NETREG_UNREGISTERED) | ||
2286 | free_netdev(wdev->netdev); | ||
2287 | |||
2288 | /* Clear the priv in adapter */ | 2285 | /* Clear the priv in adapter */ |
2289 | priv->netdev = NULL; | 2286 | priv->netdev = NULL; |
2290 | 2287 | ||
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 4a32f2795c64..2d761477d15e 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -1192,6 +1192,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter) | |||
1192 | adapter->if_ops.wakeup(adapter); | 1192 | adapter->if_ops.wakeup(adapter); |
1193 | adapter->hs_activated = false; | 1193 | adapter->hs_activated = false; |
1194 | adapter->is_hs_configured = false; | 1194 | adapter->is_hs_configured = false; |
1195 | adapter->is_suspended = false; | ||
1195 | mwifiex_hs_activated_event(mwifiex_get_priv(adapter, | 1196 | mwifiex_hs_activated_event(mwifiex_get_priv(adapter, |
1196 | MWIFIEX_BSS_ROLE_ANY), | 1197 | MWIFIEX_BSS_ROLE_ANY), |
1197 | false); | 1198 | false); |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 29d83f0c1fb8..5bc7ef8d04d6 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -669,6 +669,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
669 | struct net_device *dev) | 669 | struct net_device *dev) |
670 | { | 670 | { |
671 | dev->netdev_ops = &mwifiex_netdev_ops; | 671 | dev->netdev_ops = &mwifiex_netdev_ops; |
672 | dev->destructor = free_netdev; | ||
672 | /* Initialize private structure */ | 673 | /* Initialize private structure */ |
673 | priv->current_key_index = 0; | 674 | priv->current_key_index = 0; |
674 | priv->media_connected = false; | 675 | priv->media_connected = false; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 311d0b26b81c..1a8a19dbd635 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -96,7 +96,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
96 | } else { | 96 | } else { |
97 | /* Multicast */ | 97 | /* Multicast */ |
98 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; | 98 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; |
99 | if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) { | 99 | if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) { |
100 | dev_dbg(priv->adapter->dev, | 100 | dev_dbg(priv->adapter->dev, |
101 | "info: Enabling All Multicast!\n"); | 101 | "info: Enabling All Multicast!\n"); |
102 | priv->curr_pkt_filter |= | 102 | priv->curr_pkt_filter |= |
@@ -108,20 +108,11 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
108 | dev_dbg(priv->adapter->dev, | 108 | dev_dbg(priv->adapter->dev, |
109 | "info: Set multicast list=%d\n", | 109 | "info: Set multicast list=%d\n", |
110 | mcast_list->num_multicast_addr); | 110 | mcast_list->num_multicast_addr); |
111 | /* Set multicast addresses to firmware */ | 111 | /* Send multicast addresses to firmware */ |
112 | if (old_pkt_filter == priv->curr_pkt_filter) { | 112 | ret = mwifiex_send_cmd_async(priv, |
113 | /* Send request to firmware */ | 113 | HostCmd_CMD_MAC_MULTICAST_ADR, |
114 | ret = mwifiex_send_cmd_async(priv, | 114 | HostCmd_ACT_GEN_SET, 0, |
115 | HostCmd_CMD_MAC_MULTICAST_ADR, | 115 | mcast_list); |
116 | HostCmd_ACT_GEN_SET, 0, | ||
117 | mcast_list); | ||
118 | } else { | ||
119 | /* Send request to firmware */ | ||
120 | ret = mwifiex_send_cmd_async(priv, | ||
121 | HostCmd_CMD_MAC_MULTICAST_ADR, | ||
122 | HostCmd_ACT_GEN_SET, 0, | ||
123 | mcast_list); | ||
124 | } | ||
125 | } | 116 | } |
126 | } | 117 | } |
127 | } | 118 | } |