Merge branch 'master' of ssh://infradead/~/public_git/wireless-next into for-davem

This commit is contained in:
John W. Linville 2011-09-19 15:00:16 -04:00
commit b53d63ecce
137 changed files with 9895 additions and 4629 deletions

View File

@ -1246,6 +1246,14 @@ W: http://wireless.kernel.org/en/users/Drivers/ath5k
S: Maintained S: Maintained
F: drivers/net/wireless/ath/ath5k/ F: drivers/net/wireless/ath/ath5k/
ATHEROS ATH6KL WIRELESS DRIVER
M: Kalle Valo <kvalo@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/ath6kl
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath6kl.git
S: Supported
F: drivers/net/wireless/ath/ath6kl/
ATHEROS ATH9K WIRELESS DRIVER ATHEROS ATH9K WIRELESS DRIVER
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com> M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
M: Jouni Malinen <jouni@qca.qualcomm.com> M: Jouni Malinen <jouni@qca.qualcomm.com>
@ -6145,12 +6153,6 @@ M: Jakub Schmidtke <sjakub@gmail.com>
S: Odd Fixes S: Odd Fixes
F: drivers/staging/asus_oled/ F: drivers/staging/asus_oled/
STAGING - ATHEROS ATH6KL WIRELESS DRIVER
M: Luis R. Rodriguez <mcgrof@gmail.com>
M: Naveen Singh <nsingh@atheros.com>
S: Odd Fixes
F: drivers/staging/ath6kl/
STAGING - COMEDI STAGING - COMEDI
M: Ian Abbott <abbotti@mev.co.uk> M: Ian Abbott <abbotti@mev.co.uk>
M: Mori Hess <fmhess@users.sourceforge.net> M: Mori Hess <fmhess@users.sourceforge.net>

View File

@ -133,6 +133,15 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
} }
bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
} }
int bcma_sprom_get(struct bcma_bus *bus) int bcma_sprom_get(struct bcma_bus *bus)

View File

@ -140,9 +140,6 @@ struct ath_common {
u8 curbssid[ETH_ALEN]; u8 curbssid[ETH_ALEN];
u8 bssidmask[ETH_ALEN]; u8 bssidmask[ETH_ALEN];
u8 tx_chainmask;
u8 rx_chainmask;
u32 rx_bufsize; u32 rx_bufsize;
u32 keymax; u32 keymax;

View File

@ -14,70 +14,71 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
static const u32 ar5416Modes[][6] = { static const u32 ar5416Modes[][5] = {
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
{0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf}, {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
{0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
{0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
{0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
{0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0}, {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
{0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0},
{0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de}, {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de},
{0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
{0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18}, {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
{0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
{0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190}, {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
{0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
{0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
{0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134}, {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
{0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b}, {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134},
{0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020}, {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
{0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80}, {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
{0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80}, {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
{0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80}, {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
{0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120}, {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
{0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00}, {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120},
{0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
{0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
{0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c}, {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
{0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
{0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
{0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
{0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788}, {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
{0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
{0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
{0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
{0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
{0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
{0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa}, {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
{0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
{0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402}, {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
{0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06}, {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
{0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b}, {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
{0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b}, {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
{0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a}, {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
{0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf}, {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
{0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f}, {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
{0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f}, {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
{0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f}, {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
{0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000}, {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
{0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
{0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
}; };
static const u32 ar5416Common[][2] = { static const u32 ar5416Common[][2] = {
@ -668,6 +669,6 @@ static const u32 ar5416Addac[][2] = {
{0x0000989c, 0x00000000}, {0x0000989c, 0x00000000},
{0x0000989c, 0x00000000}, {0x0000989c, 0x00000000},
{0x0000989c, 0x00000000}, {0x0000989c, 0x00000000},
{0x000098cc, 0x00000000}, {0x000098c4, 0x00000000},
}; };

View File

@ -14,73 +14,74 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
static const u32 ar5416Modes_9100[][6] = { static const u32 ar5416Modes_9100[][5] = {
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
{0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf}, {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
{0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
{0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
{0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
{0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0}, {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
{0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
{0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2}, {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
{0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
{0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18}, {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
{0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
{0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0}, {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
{0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
{0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
{0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
{0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
{0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204}, {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
{0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020}, {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204},
{0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e}, {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
{0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff}, {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e},
{0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff},
{0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
{0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
{0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120}, {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
{0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00}, {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
{0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00},
{0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
{0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329}, {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
{0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
{0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
{0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
{0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788}, {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
{0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
{0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
{0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
{0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
{0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
{0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa}, {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
{0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
{0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402}, {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
{0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06}, {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
{0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b}, {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
{0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b}, {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
{0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a}, {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
{0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf}, {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
{0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f}, {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
{0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f}, {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
{0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f}, {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
{0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000}, {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
{0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
{0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
}; };
static const u32 ar5416Common_9100[][2] = { static const u32 ar5416Common_9100[][2] = {
@ -666,71 +667,72 @@ static const u32 ar5416Addac_9100[][2] = {
{0x000098cc, 0x00000000}, {0x000098cc, 0x00000000},
}; };
static const u32 ar5416Modes_9160[][6] = { static const u32 ar5416Modes_9160[][5] = {
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
{0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
{0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf}, {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
{0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
{0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
{0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
{0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
{0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
{0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0}, {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
{0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
{0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2}, {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
{0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
{0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
{0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18}, {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
{0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
{0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0}, {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
{0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
{0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
{0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
{0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
{0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020}, {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
{0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
{0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
{0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
{0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120}, {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
{0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce}, {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
{0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00}, {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00},
{0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
{0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329}, {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
{0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
{0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
{0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
{0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788}, {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
{0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
{0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
{0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
{0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
{0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
{0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa}, {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
{0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
{0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402}, {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
{0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06}, {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
{0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b}, {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
{0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b}, {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
{0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a}, {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
{0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf}, {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
{0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f}, {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
{0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f}, {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
{0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f}, {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
{0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000}, {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
{0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
{0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
}; };
static const u32 ar5416Common_9160[][2] = { static const u32 ar5416Common_9160[][2] = {

View File

@ -30,7 +30,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
{ {
if (AR_SREV_9271(ah)) { if (AR_SREV_9271(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
ARRAY_SIZE(ar9271Modes_9271), 6); ARRAY_SIZE(ar9271Modes_9271), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2); ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
@ -41,21 +41,21 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only, ar9271Modes_9271_1_0_only,
ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
ar9271Modes_high_power_tx_gain_9271, ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
ar9271Modes_normal_power_tx_gain_9271, ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
return; return;
} }
if (AR_SREV_9287_11_OR_LATER(ah)) { if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
ARRAY_SIZE(ar9287Modes_9287_1_1), 6); ARRAY_SIZE(ar9287Modes_9287_1_1), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
ARRAY_SIZE(ar9287Common_9287_1_1), 2); ARRAY_SIZE(ar9287Common_9287_1_1), 2);
if (ah->config.pcie_clock_req) if (ah->config.pcie_clock_req)
@ -71,7 +71,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
ARRAY_SIZE(ar9285Modes_9285_1_2), 6); ARRAY_SIZE(ar9285Modes_9285_1_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
ARRAY_SIZE(ar9285Common_9285_1_2), 2); ARRAY_SIZE(ar9285Common_9285_1_2), 2);
@ -87,7 +87,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
} }
} else if (AR_SREV_9280_20_OR_LATER(ah)) { } else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
ARRAY_SIZE(ar9280Modes_9280_2), 6); ARRAY_SIZE(ar9280Modes_9280_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2); ARRAY_SIZE(ar9280Common_9280_2), 2);
@ -105,7 +105,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9160_10_OR_LATER(ah)) { } else if (AR_SREV_9160_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
ARRAY_SIZE(ar5416Modes_9160), 6); ARRAY_SIZE(ar5416Modes_9160), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
ARRAY_SIZE(ar5416Common_9160), 2); ARRAY_SIZE(ar5416Common_9160), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
@ -134,7 +134,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
} }
} else if (AR_SREV_9100_OR_LATER(ah)) { } else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
ARRAY_SIZE(ar5416Modes_9100), 6); ARRAY_SIZE(ar5416Modes_9100), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
ARRAY_SIZE(ar5416Common_9100), 2); ARRAY_SIZE(ar5416Common_9100), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
@ -157,7 +157,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar5416Addac_9100), 2); ARRAY_SIZE(ar5416Addac_9100), 2);
} else { } else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
ARRAY_SIZE(ar5416Modes), 6); ARRAY_SIZE(ar5416Modes), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
ARRAY_SIZE(ar5416Common), 2); ARRAY_SIZE(ar5416Common), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
@ -207,19 +207,19 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_13db_rxgain_9280_2, ar9280Modes_backoff_13db_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5);
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_23db_rxgain_9280_2, ar9280Modes_backoff_23db_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5);
else else
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2, ar9280Modes_original_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
} else { } else {
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2, ar9280Modes_original_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
} }
} }
@ -234,15 +234,15 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2, ar9280Modes_high_power_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5);
else else
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2, ar9280Modes_original_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
} else { } else {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2, ar9280Modes_original_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
} }
} }
@ -251,14 +251,14 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
if (AR_SREV_9287_11_OR_LATER(ah)) if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1, ar9287Modes_rx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5);
else if (AR_SREV_9280_20(ah)) else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah); ar9280_20_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11_OR_LATER(ah)) { if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1, ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
} else if (AR_SREV_9280_20(ah)) { } else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah); ar9280_20_hw_init_txgain_ini(ah);
} else if (AR_SREV_9285_12_OR_LATER(ah)) { } else if (AR_SREV_9285_12_OR_LATER(ah)) {
@ -270,24 +270,24 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_high_power, ar9285Modes_XE2_0_high_power,
ARRAY_SIZE( ARRAY_SIZE(
ar9285Modes_XE2_0_high_power), 6); ar9285Modes_XE2_0_high_power), 5);
} else { } else {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2, ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE( ARRAY_SIZE(
ar9285Modes_high_power_tx_gain_9285_1_2), 6); ar9285Modes_high_power_tx_gain_9285_1_2), 5);
} }
} else { } else {
if (AR_SREV_9285E_20(ah)) { if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_normal_power, ar9285Modes_XE2_0_normal_power,
ARRAY_SIZE( ARRAY_SIZE(
ar9285Modes_XE2_0_normal_power), 6); ar9285Modes_XE2_0_normal_power), 5);
} else { } else {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2, ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE( ARRAY_SIZE(
ar9285Modes_original_tx_gain_9285_1_2), 6); ar9285Modes_original_tx_gain_9285_1_2), 5);
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -170,33 +170,104 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true; return true;
} }
static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, static void
bool is_firstseg, bool is_lastseg, ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{ {
struct ar5416_desc *ads = AR5416DESC(ds); struct ar5416_desc *ads = AR5416DESC(ds);
u32 ctl1, ctl6;
ads->ds_data = buf_addr;
if (is_firstseg) {
ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
} else if (is_lastseg) {
ads->ds_ctl0 = 0;
ads->ds_ctl1 = seglen;
ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
} else {
ads->ds_ctl0 = 0;
ads->ds_ctl1 = seglen | AR_TxMore;
ads->ds_ctl2 = 0;
ads->ds_ctl3 = 0;
}
ads->ds_txstatus0 = ads->ds_txstatus1 = 0; ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0; ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0; ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0; ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0; ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
ACCESS_ONCE(ads->ds_link) = i->link;
ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
ctl6 = SM(i->keytype, AR_EncrType);
if (AR_SREV_9285(ah)) {
ads->ds_ctl8 = 0;
ads->ds_ctl9 = 0;
ads->ds_ctl10 = 0;
ads->ds_ctl11 = 0;
}
if ((i->is_first || i->is_last) &&
i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
| set11nTries(i->rates, 1)
| set11nTries(i->rates, 2)
| set11nTries(i->rates, 3)
| (i->dur_update ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
| set11nRate(i->rates, 1)
| set11nRate(i->rates, 2)
| set11nRate(i->rates, 3);
} else {
ACCESS_ONCE(ads->ds_ctl2) = 0;
ACCESS_ONCE(ads->ds_ctl3) = 0;
}
if (!i->is_first) {
ACCESS_ONCE(ads->ds_ctl0) = 0;
ACCESS_ONCE(ads->ds_ctl1) = ctl1;
ACCESS_ONCE(ads->ds_ctl6) = ctl6;
return;
}
ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
| SM(i->type, AR_FrameType)
| (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
switch (i->aggr) {
case AGGR_BUF_FIRST:
ctl6 |= SM(i->aggr_len, AR_AggrLen);
/* fall through */
case AGGR_BUF_MIDDLE:
ctl1 |= AR_IsAggr | AR_MoreAggr;
ctl6 |= SM(i->ndelim, AR_PadDelim);
break;
case AGGR_BUF_LAST:
ctl1 |= AR_IsAggr;
break;
case AGGR_BUF_NONE:
break;
}
ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(i->txpower, AR_XmitPower)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
(i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
ACCESS_ONCE(ads->ds_ctl1) = ctl1;
ACCESS_ONCE(ads->ds_ctl6) = ctl6;
if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
return;
ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
| set11nPktDurRTSCTS(i->rates, 1);
ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
| set11nPktDurRTSCTS(i->rates, 3);
ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
| set11nRateFlags(i->rates, 1)
| set11nRateFlags(i->rates, 2)
| set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate);
} }
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
@ -271,145 +342,6 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return 0; return 0;
} }
static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u8 keyIx,
enum ath9k_key_type keyType, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if (txPower > 63)
txPower = 63;
ads->ds_ctl0 = (pktLen & AR_FrameLen)
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txPower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
ads->ds_ctl1 =
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
| SM(type, AR_FrameType)
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ads->ds_ctl6 = SM(keyType, AR_EncrType);
if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
ads->ds_ctl8 = 0;
ads->ds_ctl9 = 0;
ads->ds_ctl10 = 0;
ads->ds_ctl11 = 0;
}
}
static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if (val)
ads->ds_ctl0 |= AR_ClrDestMask;
else
ads->ds_ctl0 &= ~AR_ClrDestMask;
}
static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
struct ar5416_desc *last_ads = AR5416DESC(lastds);
u32 ds_ctl0;
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
ds_ctl0 = ads->ds_ctl0;
if (flags & ATH9K_TXDESC_RTSENA) {
ds_ctl0 &= ~AR_CTSEnable;
ds_ctl0 |= AR_RTSEnable;
} else {
ds_ctl0 &= ~AR_RTSEnable;
ds_ctl0 |= AR_CTSEnable;
}
ads->ds_ctl0 = ds_ctl0;
} else {
ads->ds_ctl0 =
(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
}
ads->ds_ctl2 = set11nTries(series, 0)
| set11nTries(series, 1)
| set11nTries(series, 2)
| set11nTries(series, 3)
| (durUpdateEn ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ads->ds_ctl3 = set11nRate(series, 0)
| set11nRate(series, 1)
| set11nRate(series, 2)
| set11nRate(series, 3);
ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
| set11nPktDurRTSCTS(series, 1);
ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
| set11nPktDurRTSCTS(series, 3);
ads->ds_ctl7 = set11nRateFlags(series, 0)
| set11nRateFlags(series, 1)
| set11nRateFlags(series, 2)
| set11nRateFlags(series, 3)
| SM(rtsctsRate, AR_RTSCTSRate);
last_ads->ds_ctl2 = ads->ds_ctl2;
last_ads->ds_ctl3 = ads->ds_ctl3;
}
static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
ads->ds_ctl6 &= ~AR_AggrLen;
ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
}
static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
struct ar5416_desc *ads = AR5416DESC(ds);
unsigned int ctl6;
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
ctl6 = ads->ds_ctl6;
ctl6 &= ~AR_PadDelim;
ctl6 |= SM(numDelims, AR_PadDelim);
ads->ds_ctl6 = ctl6;
}
static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 |= AR_IsAggr;
ads->ds_ctl1 &= ~AR_MoreAggr;
ads->ds_ctl6 &= ~AR_PadDelim;
}
static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
}
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags) u32 size, u32 flags)
{ {
@ -433,13 +365,6 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops->rx_enable = ar9002_hw_rx_enable; ops->rx_enable = ar9002_hw_rx_enable;
ops->set_desc_link = ar9002_hw_set_desc_link; ops->set_desc_link = ar9002_hw_set_desc_link;
ops->get_isr = ar9002_hw_get_isr; ops->get_isr = ar9002_hw_get_isr;
ops->fill_txdesc = ar9002_hw_fill_txdesc; ops->set_txdesc = ar9002_set_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc; ops->proc_txdesc = ar9002_hw_proc_txdesc;
ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
ops->set_clrdmask = ar9002_hw_set_clrdmask;
} }

View File

@ -615,11 +615,10 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
{ {
int mp_max = -64, max_idx = 0; int mp_max = -64, max_idx = 0;
int mp_min = 63, min_idx = 0; int mp_min = 63, min_idx = 0;
int mp_avg = 0, i, outlier_idx = 0; int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
/* find min/max mismatch across all calibrated gains */ /* find min/max mismatch across all calibrated gains */
for (i = 0; i < nmeasurement; i++) { for (i = 0; i < nmeasurement; i++) {
mp_avg += mp_coeff[i];
if (mp_coeff[i] > mp_max) { if (mp_coeff[i] > mp_max) {
mp_max = mp_coeff[i]; mp_max = mp_coeff[i];
max_idx = i; max_idx = i;
@ -632,10 +631,20 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
/* find average (exclude max abs value) */ /* find average (exclude max abs value) */
for (i = 0; i < nmeasurement; i++) { for (i = 0; i < nmeasurement; i++) {
if ((abs(mp_coeff[i]) < abs(mp_max)) || if ((abs(mp_coeff[i]) < abs(mp_max)) ||
(abs(mp_coeff[i]) < abs(mp_min))) (abs(mp_coeff[i]) < abs(mp_min))) {
mp_avg += mp_coeff[i]; mp_avg += mp_coeff[i];
mp_count++;
}
} }
mp_avg /= (nmeasurement - 1);
/*
* finding mean magnitude/phase if possible, otherwise
* just use the last value as the mean
*/
if (mp_count)
mp_avg /= mp_count;
else
mp_avg = mp_coeff[nmeasurement - 1];
/* detect outlier */ /* detect outlier */
if (abs(mp_max - mp_min) > max_delta) { if (abs(mp_max - mp_min) > max_delta) {

View File

@ -22,25 +22,6 @@
#define COMP_HDR_LEN 4 #define COMP_HDR_LEN 4
#define COMP_CKSUM_LEN 2 #define COMP_CKSUM_LEN 2
#define AR_CH0_TOP (0x00016288)
#define AR_CH0_TOP_XPABIASLVL (0x300)
#define AR_CH0_TOP_XPABIASLVL_S (8)
#define AR_CH0_THERM (0x00016290)
#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
#define AR_CH0_THERM_XPASHORT2GND 0x4
#define AR_CH0_THERM_XPASHORT2GND_S 2
#define AR_SWITCH_TABLE_COM_ALL (0xffff)
#define AR_SWITCH_TABLE_COM_ALL_S (0)
#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
#define AR_SWITCH_TABLE_COM2_ALL_S (0)
#define AR_SWITCH_TABLE_ALL (0xfff)
#define AR_SWITCH_TABLE_ALL_S (0)
#define LE16(x) __constant_cpu_to_le16(x) #define LE16(x) __constant_cpu_to_le16(x)
#define LE32(x) __constant_cpu_to_le32(x) #define LE32(x) __constant_cpu_to_le32(x)
@ -158,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0), .papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0), .papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext1 = { .base_ext1 = {
@ -360,7 +341,7 @@ static const struct ar9300_eeprom ar9300_default = {
.papdRateMaskHt20 = LE32(0x0c80c080), .papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080), .papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext2 = { .base_ext2 = {
@ -735,7 +716,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.papdRateMaskHt20 = LE32(0x0c80c080), .papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080), .papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext1 = { .base_ext1 = {
@ -937,7 +918,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0), .papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0), .papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext2 = { .base_ext2 = {
@ -1313,7 +1294,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.papdRateMaskHt20 = LE32(0x80c080), .papdRateMaskHt20 = LE32(0x80c080),
.papdRateMaskHt40 = LE32(0x80c080), .papdRateMaskHt40 = LE32(0x80c080),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext1 = { .base_ext1 = {
@ -1515,7 +1496,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0), .papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0), .papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext2 = { .base_ext2 = {
@ -1891,7 +1872,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.papdRateMaskHt20 = LE32(0x0c80c080), .papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080), .papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext1 = { .base_ext1 = {
@ -2093,7 +2074,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0), .papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0), .papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext2 = { .base_ext2 = {
@ -2468,7 +2449,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.papdRateMaskHt20 = LE32(0x0c80C080), .papdRateMaskHt20 = LE32(0x0c80C080),
.papdRateMaskHt40 = LE32(0x0080C080), .papdRateMaskHt40 = LE32(0x0080C080),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext1 = { .base_ext1 = {
@ -2670,7 +2651,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0), .papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0), .papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext2 = { .base_ext2 = {
@ -3573,6 +3554,8 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
else if (AR_SREV_9480(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
else { else {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
REG_RMW_FIELD(ah, AR_CH0_THERM, REG_RMW_FIELD(ah, AR_CH0_THERM,
@ -3583,6 +3566,19 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
} }
} }
static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is_2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
__le32 val;
if (is_2ghz)
val = eep->modalHeader2G.switchcomspdt;
else
val = eep->modalHeader5G.switchcomspdt;
return le32_to_cpu(val);
}
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
{ {
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@ -3637,7 +3633,36 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); if (AR_SREV_9480(ah)) {
if (AR_SREV_9480_10(ah)) {
value &= ~AR_SWITCH_TABLE_COM_SPDT;
value |= 0x00100000;
}
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_AR9480_ALL, value);
} else
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_ALL, value);
/*
* AR9480 defines new switch table for BT/WLAN,
* here's new field name in XXX.ref for both 2G and 5G.
* Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
* 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX
* SWITCH_TABLE_COM_SPDT_WLAN_RX
*
* 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX
* SWITCH_TABLE_COM_SPDT_WLAN_TX
*
* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
* SWITCH_TABLE_COM_SPDT_WLAN_IDLE
*/
if (AR_SREV_9480_20_OR_LATER(ah)) {
value = ar9003_switch_com_spdt_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
AR_SWITCH_TABLE_COM_SPDT_ALL, value);
}
value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
@ -3837,6 +3862,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
{ {
int internal_regulator = int internal_regulator =
ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR); ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
u32 reg_val;
if (internal_regulator) { if (internal_regulator) {
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) { if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
@ -3881,13 +3907,16 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return; return;
} else if (AR_SREV_9480(ah)) {
reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
REG_WRITE(ah, AR_PHY_PMU1, reg_val);
} else { } else {
/* Internal regulator is ON. Write swreg register. */ /* Internal regulator is ON. Write swreg register. */
int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
REG_WRITE(ah, AR_RTC_REG_CONTROL1, REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah, AR_RTC_REG_CONTROL1) & REG_READ(ah, AR_RTC_REG_CONTROL1) &
(~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); REG_WRITE(ah, AR_RTC_REG_CONTROL0, reg_val);
/* Set REG_CONTROL1.SWREG_PROGRAM */ /* Set REG_CONTROL1.SWREG_PROGRAM */
REG_WRITE(ah, AR_RTC_REG_CONTROL1, REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah, REG_READ(ah,
@ -3898,22 +3927,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) { if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0); REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
while (REG_READ_FIELD(ah, AR_PHY_PMU2, while (REG_READ_FIELD(ah, AR_PHY_PMU2,
AR_PHY_PMU2_PGM)) AR_PHY_PMU2_PGM))
udelay(10); udelay(10);
REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1); REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
while (!REG_READ_FIELD(ah, AR_PHY_PMU1, while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
AR_PHY_PMU1_PWD)) AR_PHY_PMU1_PWD))
udelay(10); udelay(10);
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1); REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
while (!REG_READ_FIELD(ah, AR_PHY_PMU2, while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
AR_PHY_PMU2_PGM)) AR_PHY_PMU2_PGM))
udelay(10); udelay(10);
} else } else if (AR_SREV_9480(ah))
REG_WRITE(ah, AR_RTC_SLEEP_CLK, REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
(REG_READ(ah, else {
AR_RTC_SLEEP_CLK) | reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) |
AR_RTC_FORCE_SWREG_PRD)); AR_RTC_FORCE_SWREG_PRD;
REG_WRITE(ah, AR_RTC_SLEEP_CLK, reg_val);
}
} }
} }
@ -4493,6 +4524,12 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
tempSlope = eep->modalHeader5G.tempSlope; tempSlope = eep->modalHeader5G.tempSlope;
REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
if (AR_SREV_9480_20(ah))
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope);
REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
temperature[0]); temperature[0]);

View File

@ -233,7 +233,8 @@ struct ar9300_modal_eep_header {
u8 thresh62; u8 thresh62;
__le32 papdRateMaskHt20; __le32 papdRateMaskHt20;
__le32 papdRateMaskHt40; __le32 papdRateMaskHt40;
u8 futureModal[10]; __le16 switchcomspdt;
u8 futureModal[8];
} __packed; } __packed;
struct ar9300_cal_data_per_freq_op_loop { struct ar9300_cal_data_per_freq_op_loop {

View File

@ -22,6 +22,8 @@
#include "ar9330_1p1_initvals.h" #include "ar9330_1p1_initvals.h"
#include "ar9330_1p2_initvals.h" #include "ar9330_1p2_initvals.h"
#include "ar9580_1p0_initvals.h" #include "ar9580_1p0_initvals.h"
#include "ar9480_1p0_initvals.h"
#include "ar9480_2p0_initvals.h"
/* General hardware code for the AR9003 hadware family */ /* General hardware code for the AR9003 hadware family */
@ -32,6 +34,14 @@
*/ */
static void ar9003_hw_init_mode_regs(struct ath_hw *ah) static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{ {
#define PCIE_PLL_ON_CREQ_DIS_L1_2P0 \
ar9480_pciephy_pll_on_clkreq_disable_L1_2p0
#define AR9480_BB_CTX_COEFJ(x) \
ar9480_##x##_baseband_core_txfir_coeff_japan_2484
#define AR9480_BBC_TXIFR_COEFFJ \
ar9480_2p0_baseband_core_txfir_coeff_japan_2484
if (AR_SREV_9330_11(ah)) { if (AR_SREV_9330_11(ah)) {
/* mac */ /* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@ -254,6 +264,132 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ar9485_1_1_pcie_phy_clkreq_disable_L1, ar9485_1_1_pcie_phy_clkreq_disable_L1,
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
2); 2);
} else if (AR_SREV_9480_10(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9480_1p0_mac_core,
ARRAY_SIZE(ar9480_1p0_mac_core), 2);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9480_1p0_mac_postamble,
ARRAY_SIZE(ar9480_1p0_mac_postamble),
5);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9480_1p0_baseband_core,
ARRAY_SIZE(ar9480_1p0_baseband_core),
2);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9480_1p0_baseband_postamble,
ARRAY_SIZE(ar9480_1p0_baseband_postamble), 5);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9480_1p0_radio_core,
ARRAY_SIZE(ar9480_1p0_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9480_1p0_radio_postamble,
ARRAY_SIZE(ar9480_1p0_radio_postamble), 5);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9480_1p0_soc_preamble,
ARRAY_SIZE(ar9480_1p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9480_1p0_soc_postamble,
ARRAY_SIZE(ar9480_1p0_soc_postamble), 5);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_rx_gain_table_1p0,
ARRAY_SIZE(ar9480_common_rx_gain_table_1p0), 2);
/* Awake -> Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9480_pcie_phy_clkreq_disable_L1_1p0,
ARRAY_SIZE(ar9480_pcie_phy_clkreq_disable_L1_1p0),
2);
/* Sleep -> Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9480_pcie_phy_clkreq_disable_L1_1p0,
ARRAY_SIZE(ar9480_pcie_phy_clkreq_disable_L1_1p0),
2);
INIT_INI_ARRAY(&ah->iniModesAdditional,
ar9480_modes_fast_clock_1p0,
ARRAY_SIZE(ar9480_modes_fast_clock_1p0), 3);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
AR9480_BB_CTX_COEFJ(1p0),
ARRAY_SIZE(AR9480_BB_CTX_COEFJ(1p0)), 2);
} else if (AR_SREV_9480_20(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9480_2p0_mac_core,
ARRAY_SIZE(ar9480_2p0_mac_core), 2);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9480_2p0_mac_postamble,
ARRAY_SIZE(ar9480_2p0_mac_postamble), 5);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9480_2p0_baseband_core,
ARRAY_SIZE(ar9480_2p0_baseband_core), 2);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9480_2p0_baseband_postamble,
ARRAY_SIZE(ar9480_2p0_baseband_postamble), 5);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9480_2p0_radio_core,
ARRAY_SIZE(ar9480_2p0_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9480_2p0_radio_postamble,
ARRAY_SIZE(ar9480_2p0_radio_postamble), 5);
INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
ar9480_2p0_radio_postamble_sys2ant,
ARRAY_SIZE(ar9480_2p0_radio_postamble_sys2ant),
5);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9480_2p0_soc_preamble,
ARRAY_SIZE(ar9480_2p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9480_2p0_soc_postamble,
ARRAY_SIZE(ar9480_2p0_soc_postamble), 5);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_rx_gain_table_2p0,
ARRAY_SIZE(ar9480_common_rx_gain_table_2p0), 2);
INIT_INI_ARRAY(&ah->ini_BTCOEX_MAX_TXPWR,
ar9480_2p0_BTCOEX_MAX_TXPWR_table,
ARRAY_SIZE(ar9480_2p0_BTCOEX_MAX_TXPWR_table),
2);
/* Awake -> Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
PCIE_PLL_ON_CREQ_DIS_L1_2P0,
ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
2);
/* Sleep -> Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
PCIE_PLL_ON_CREQ_DIS_L1_2P0,
ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
2);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional,
ar9480_modes_fast_clock_2p0,
ARRAY_SIZE(ar9480_modes_fast_clock_2p0), 3);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
AR9480_BB_CTX_COEFJ(2p0),
ARRAY_SIZE(AR9480_BB_CTX_COEFJ(2p0)), 2);
INIT_INI_ARRAY(&ah->ini_japan2484, AR9480_BBC_TXIFR_COEFFJ,
ARRAY_SIZE(AR9480_BBC_TXIFR_COEFFJ), 2);
} else if (AR_SREV_9580(ah)) { } else if (AR_SREV_9580(ah)) {
/* mac */ /* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@ -374,208 +510,293 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
} }
} }
static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485_modes_lowest_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
5);
else if (AR_SREV_9480_10(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9480_modes_low_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9480_modes_low_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9480_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9480_modes_low_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9480_modes_low_ob_db_tx_gain_table_2p0),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
5);
}
static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_high_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
5);
else if (AR_SREV_9480_10(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9480_modes_high_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9480_modes_high_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9480_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9480_modes_high_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9480_modes_high_ob_db_tx_gain_table_2p0),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
5);
}
static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_low_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_low_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_low_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
5);
}
static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_power_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_power_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_high_power_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_power_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_power_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
5);
}
static void ar9003_tx_gain_table_apply(struct ath_hw *ah) static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
{ {
switch (ar9003_hw_get_tx_gain_idx(ah)) { switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0: case 0:
default: default:
if (AR_SREV_9330_12(ah)) ar9003_tx_gain_table_mode0(ah);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485_modes_lowest_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
5);
break; break;
case 1: case 1:
if (AR_SREV_9330_12(ah)) ar9003_tx_gain_table_mode1(ah);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_high_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
5);
break; break;
case 2: case 2:
if (AR_SREV_9330_12(ah)) ar9003_tx_gain_table_mode2(ah);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_low_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_low_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_low_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
5);
break; break;
case 3: case 3:
if (AR_SREV_9330_12(ah)) ar9003_tx_gain_table_mode3(ah);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_power_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
5);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_power_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
5);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_high_power_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_power_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_power_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
5);
break; break;
} }
} }
static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p2,
ARRAY_SIZE(ar9331_common_rx_gain_1p2),
2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_rx_gain_1p1),
2);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
2);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table),
2);
else if (AR_SREV_9480_10(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_rx_gain_table_1p0,
ARRAY_SIZE(ar9480_common_rx_gain_table_1p0),
2);
else if (AR_SREV_9480_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_rx_gain_table_2p0,
ARRAY_SIZE(ar9480_common_rx_gain_table_2p0),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
2);
}
static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_wo_xlna_rx_gain_1p2,
ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_wo_xlna_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
2);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_wo_xlna_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
2);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
else if (AR_SREV_9480_10(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_wo_xlna_rx_gain_table_1p0,
ARRAY_SIZE(ar9480_common_wo_xlna_rx_gain_table_1p0),
2);
else if (AR_SREV_9480_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_wo_xlna_rx_gain_table_2p0,
ARRAY_SIZE(ar9480_common_wo_xlna_rx_gain_table_2p0),
2);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
2);
}
static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
{
if (AR_SREV_9480_10(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_mixed_rx_gain_table_1p0,
ARRAY_SIZE(ar9480_common_mixed_rx_gain_table_1p0), 2);
else if (AR_SREV_9480_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9480_common_mixed_rx_gain_table_2p0,
ARRAY_SIZE(ar9480_common_mixed_rx_gain_table_2p0), 2);
}
static void ar9003_rx_gain_table_apply(struct ath_hw *ah) static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
{ {
switch (ar9003_hw_get_rx_gain_idx(ah)) { switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0: case 0:
default: default:
if (AR_SREV_9330_12(ah)) ar9003_rx_gain_table_mode0(ah);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p2,
ARRAY_SIZE(ar9331_common_rx_gain_1p2),
2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_rx_gain_1p1),
2);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
2);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
2);
break; break;
case 1: case 1:
if (AR_SREV_9330_12(ah)) ar9003_rx_gain_table_mode1(ah);
INIT_INI_ARRAY(&ah->iniModesRxGain, break;
ar9331_common_wo_xlna_rx_gain_1p2, case 2:
ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2), ar9003_rx_gain_table_mode2(ah);
2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_wo_xlna_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
2);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_wo_xlna_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
2);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
2);
break; break;
} }
} }

View File

@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw)
REG_WRITE(hw, AR_CR, 0); REG_WRITE(hw, AR_CR, 0);
} }
static void
ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
{
struct ar9003_txc *ads = ds;
int checksum = 0;
u32 val, ctl12, ctl17;
val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
(1 << AR_TxRxDesc_S) |
(1 << AR_CtrlStat_S) |
(i->qcu << AR_TxQcuNum_S) | 0x17;
checksum += val;
ACCESS_ONCE(ads->info) = val;
checksum += i->link;
ACCESS_ONCE(ads->link) = i->link;
checksum += i->buf_addr[0];
ACCESS_ONCE(ads->data0) = i->buf_addr[0];
checksum += i->buf_addr[1];
ACCESS_ONCE(ads->data1) = i->buf_addr[1];
checksum += i->buf_addr[2];
ACCESS_ONCE(ads->data2) = i->buf_addr[2];
checksum += i->buf_addr[3];
ACCESS_ONCE(ads->data3) = i->buf_addr[3];
checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
ACCESS_ONCE(ads->ctl3) = val;
checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
ACCESS_ONCE(ads->ctl5) = val;
checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
ACCESS_ONCE(ads->ctl7) = val;
checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
ACCESS_ONCE(ads->ctl9) = val;
checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
ACCESS_ONCE(ads->ctl10) = checksum;
if (i->is_first || i->is_last) {
ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
| set11nTries(i->rates, 1)
| set11nTries(i->rates, 2)
| set11nTries(i->rates, 3)
| (i->dur_update ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
| set11nRate(i->rates, 1)
| set11nRate(i->rates, 2)
| set11nRate(i->rates, 3);
} else {
ACCESS_ONCE(ads->ctl13) = 0;
ACCESS_ONCE(ads->ctl14) = 0;
}
ads->ctl20 = 0;
ads->ctl21 = 0;
ads->ctl22 = 0;
ctl17 = SM(i->keytype, AR_EncrType);
if (!i->is_first) {
ACCESS_ONCE(ads->ctl11) = 0;
ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
ACCESS_ONCE(ads->ctl15) = 0;
ACCESS_ONCE(ads->ctl16) = 0;
ACCESS_ONCE(ads->ctl17) = ctl17;
ACCESS_ONCE(ads->ctl18) = 0;
ACCESS_ONCE(ads->ctl19) = 0;
return;
}
ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(i->txpower, AR_XmitPower)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
| (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
(i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
SM(i->keyix, AR_DestIdx) : 0)
| SM(i->type, AR_FrameType)
| (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
switch (i->aggr) {
case AGGR_BUF_FIRST:
ctl17 |= SM(i->aggr_len, AR_AggrLen);
/* fall through */
case AGGR_BUF_MIDDLE:
ctl12 |= AR_IsAggr | AR_MoreAggr;
ctl17 |= SM(i->ndelim, AR_PadDelim);
break;
case AGGR_BUF_LAST:
ctl12 |= AR_IsAggr;
break;
case AGGR_BUF_NONE:
break;
}
val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
ctl12 |= SM(val, AR_PAPRDChainMask);
ACCESS_ONCE(ads->ctl12) = ctl12;
ACCESS_ONCE(ads->ctl17) = ctl17;
ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
| set11nPktDurRTSCTS(i->rates, 1);
ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
| set11nPktDurRTSCTS(i->rates, 3);
ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
| set11nRateFlags(i->rates, 1)
| set11nRateFlags(i->rates, 2)
| set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate);
ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
}
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
{ {
int checksum; int checksum;
@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true; return true;
} }
static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
bool is_firstseg, bool is_lastseg,
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
unsigned int descid = 0;
ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
(1 << AR_TxRxDesc_S) |
(1 << AR_CtrlStat_S) |
(qcu << AR_TxQcuNum_S) | 0x17;
ads->data0 = buf_addr;
ads->data1 = 0;
ads->data2 = 0;
ads->data3 = 0;
ads->ctl3 = (seglen << AR_BufLen_S);
ads->ctl3 &= AR_BufLen;
/* Fill in pointer checksum and descriptor id */
ads->ctl10 = ar9003_calc_ptr_chksum(ads);
ads->ctl10 |= (descid << AR_TxDescId_S);
if (is_firstseg) {
ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
} else if (is_lastseg) {
ads->ctl11 = 0;
ads->ctl12 = 0;
ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
} else {
/* XXX Intermediate descriptor in a multi-descriptor frame.*/
ads->ctl11 = 0;
ads->ctl12 = AR_TxMore;
ads->ctl13 = 0;
ads->ctl14 = 0;
}
}
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts) struct ath_tx_status *ts)
{ {
@ -310,161 +395,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return 0; return 0;
} }
static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
u8 keyIx, enum ath9k_key_type keyType, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
if (txpower > ah->txpower_limit)
txpower = ah->txpower_limit;
if (txpower > 63)
txpower = 63;
ads->ctl11 = (pktlen & AR_FrameLen)
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txpower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
ads->ctl12 =
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
| SM(type, AR_FrameType)
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ads->ctl17 = SM(keyType, AR_EncrType) |
(flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
ads->ctl18 = 0;
ads->ctl19 = AR_Not_Sounding;
ads->ctl20 = 0;
ads->ctl21 = 0;
ads->ctl22 = 0;
}
static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
if (val)
ads->ctl11 |= AR_ClrDestMask;
else
ads->ctl11 &= ~AR_ClrDestMask;
}
static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
u_int32_t ctl11;
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
ctl11 = ads->ctl11;
if (flags & ATH9K_TXDESC_RTSENA) {
ctl11 &= ~AR_CTSEnable;
ctl11 |= AR_RTSEnable;
} else {
ctl11 &= ~AR_RTSEnable;
ctl11 |= AR_CTSEnable;
}
ads->ctl11 = ctl11;
} else {
ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
}
ads->ctl13 = set11nTries(series, 0)
| set11nTries(series, 1)
| set11nTries(series, 2)
| set11nTries(series, 3)
| (durUpdateEn ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ads->ctl14 = set11nRate(series, 0)
| set11nRate(series, 1)
| set11nRate(series, 2)
| set11nRate(series, 3);
ads->ctl15 = set11nPktDurRTSCTS(series, 0)
| set11nPktDurRTSCTS(series, 1);
ads->ctl16 = set11nPktDurRTSCTS(series, 2)
| set11nPktDurRTSCTS(series, 3);
ads->ctl18 = set11nRateFlags(series, 0)
| set11nRateFlags(series, 1)
| set11nRateFlags(series, 2)
| set11nRateFlags(series, 3)
| SM(rtsctsRate, AR_RTSCTSRate);
ads->ctl19 = AR_Not_Sounding;
last_ads->ctl13 = ads->ctl13;
last_ads->ctl14 = ads->ctl14;
}
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
ads->ctl17 &= ~AR_AggrLen;
ads->ctl17 |= SM(aggrLen, AR_AggrLen);
}
static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
unsigned int ctl17;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
/*
* We use a stack variable to manipulate ctl6 to reduce uncached
* read modify, modfiy, write.
*/
ctl17 = ads->ctl17;
ctl17 &= ~AR_PadDelim;
ctl17 |= SM(numDelims, AR_PadDelim);
ads->ctl17 = ctl17;
}
static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= AR_IsAggr;
ads->ctl12 &= ~AR_MoreAggr;
ads->ctl17 &= ~AR_PadDelim;
}
static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
}
void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains)
{
struct ar9003_txc *ads = ds;
ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
}
EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc);
void ar9003_hw_attach_mac_ops(struct ath_hw *hw) void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{ {
struct ath_hw_ops *ops = ath9k_hw_ops(hw); struct ath_hw_ops *ops = ath9k_hw_ops(hw);
@ -472,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
ops->rx_enable = ar9003_hw_rx_enable; ops->rx_enable = ar9003_hw_rx_enable;
ops->set_desc_link = ar9003_hw_set_desc_link; ops->set_desc_link = ar9003_hw_set_desc_link;
ops->get_isr = ar9003_hw_get_isr; ops->get_isr = ar9003_hw_get_isr;
ops->fill_txdesc = ar9003_hw_fill_txdesc; ops->set_txdesc = ar9003_set_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc; ops->proc_txdesc = ar9003_hw_proc_txdesc;
ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
ops->set_clrdmask = ar9003_hw_set_clrdmask;
} }
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)

View File

@ -113,7 +113,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
if (delta > scale) if (delta > scale)
return -1; return -1;
switch (get_streams(common->tx_chainmask)) { switch (get_streams(ah->txchainmask)) {
case 1: case 1:
delta = 6; delta = 6;
break; break;
@ -126,7 +126,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
default: default:
delta = 0; delta = 0;
ath_dbg(common, ATH_DBG_CALIBRATE, ath_dbg(common, ATH_DBG_CALIBRATE,
"Invalid tx-chainmask: %u\n", common->tx_chainmask); "Invalid tx-chainmask: %u\n", ah->txchainmask);
} }
power += delta; power += delta;
@ -147,7 +147,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_CTRL1_B2 AR_PHY_PAPRD_CTRL1_B2
}; };
int training_power; int training_power;
int i; int i, val;
if (IS_CHAN_2GHZ(ah->curchan)) if (IS_CHAN_2GHZ(ah->curchan))
training_power = ar9003_get_training_power_2g(ah); training_power = ar9003_get_training_power_2g(ah);
@ -207,8 +207,9 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28); AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1); AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);
val = AR_SREV_9480(ah) ? 0x91 : 147;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147); AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4); AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
@ -217,7 +218,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
if (AR_SREV_9485(ah)) if (AR_SREV_9485(ah) || AR_SREV_9480(ah))
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
-3); -3);
@ -225,9 +226,10 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
-6); -6);
val = AR_SREV_9480(ah) ? -10 : -15;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
-15); val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1); AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
@ -757,6 +759,7 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
training_power); training_power);
if (ah->caps.tx_chainmask & BIT(2)) if (ah->caps.tx_chainmask & BIT(2))
/* val AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL correct? */
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
training_power); training_power);

View File

@ -559,6 +559,9 @@ static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
else if (AR_SREV_9480(ah))
/* xxx only when MCI support is enabled */
REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
else else
REG_WRITE(ah, AR_SELFGEN_MASK, tx); REG_WRITE(ah, AR_SELFGEN_MASK, tx);
@ -658,6 +661,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
if (i == ATH_INI_POST && AR_SREV_9480_20(ah))
ar9003_hw_prog_ini(ah,
&ah->ini_radio_post_sys2ant,
modesIndex);
} }
REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
@ -677,6 +684,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz) if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites); REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
if (AR_SREV_9480(ah))
ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
ar9003_hw_override_ini(ah); ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan); ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);

View File

@ -581,6 +581,9 @@
#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \
(AR_SREV_9485(ah) ? \ (AR_SREV_9485(ah) ? \
0x3d0 : 0x450) + ((_i) << 2)) 0x3d0 : 0x450) + ((_i) << 2))
#define AR_PHY_RTT_CTRL (AR_SM_BASE + 0x380)
#define AR_PHY_RTT_TABLE_SW_INTF_B (AR_SM_BASE + 0x384)
#define AR_PHY_RTT_TABLE_SW_INTF_1_B0 (AR_SM_BASE + 0x388)
#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0)
#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4)
@ -600,6 +603,17 @@
#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00 #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00
#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8 #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8
/* AIC Registers */
#define AR_PHY_AIC_CTRL_0_B0 (AR_SM_BASE + 0x4b0)
#define AR_PHY_AIC_CTRL_1_B0 (AR_SM_BASE + 0x4b4)
#define AR_PHY_AIC_CTRL_2_B0 (AR_SM_BASE + 0x4b8)
#define AR_PHY_AIC_CTRL_3_B0 (AR_SM_BASE + 0x4bc)
#define AR_PHY_AIC_STAT_0_B0 (AR_SM_BASE + (AR_SREV_9480_10(ah) ? \
0x4c0 : 0x4c4))
#define AR_PHY_AIC_STAT_1_B0 (AR_SM_BASE + (AR_SREV_9480_10(ah) ? \
0x4c4 : 0x4c8))
#define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
#define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
#define AR_PHY_65NM_CH0_SYNTH4 0x1608c #define AR_PHY_65NM_CH0_SYNTH4 0x1608c
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002
@ -609,7 +623,35 @@
#define AR_PHY_65NM_CH0_BIAS2 0x160c4 #define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc #define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX4 0x1610c #define AR_PHY_65NM_CH0_RXTX4 0x1610c
#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c)
#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
((AR_SREV_9480(ah) ? 0x1628c : 0x16280)))
#define AR_CH0_TOP_XPABIASLVL (0x300)
#define AR_CH0_TOP_XPABIASLVL_S (8)
#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \
((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
#define AR_CH0_THERM_XPASHORT2GND 0x4
#define AR_CH0_THERM_XPASHORT2GND_S 2
#define AR_SWITCH_TABLE_COM_ALL (0xffff)
#define AR_SWITCH_TABLE_COM_ALL_S (0)
#define AR_SWITCH_TABLE_COM_AR9480_ALL (0xffffff)
#define AR_SWITCH_TABLE_COM_AR9480_ALL_S (0)
#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
#define AR_SWITCH_TABLE_COM2_ALL_S (0)
#define AR_SWITCH_TABLE_ALL (0xfff)
#define AR_SWITCH_TABLE_ALL_S (0)
#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\
(AR_SREV_9485(ah) ? 0x1628c : 0x16294))
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
@ -625,21 +667,23 @@
#define AR_PHY_65NM_CH2_RXTX1 0x16900 #define AR_PHY_65NM_CH2_RXTX1 0x16900
#define AR_PHY_65NM_CH2_RXTX2 0x16904 #define AR_PHY_65NM_CH2_RXTX2 0x16904
#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : 0x16284) #define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
(AR_SREV_9485(ah) ? 0x16284 : 0x16290))
#define AR_CH0_TOP2_XPABIASLVL 0xf000 #define AR_CH0_TOP2_XPABIASLVL 0xf000
#define AR_CH0_TOP2_XPABIASLVL_S 12 #define AR_CH0_TOP2_XPABIASLVL_S 12
#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : 0x16290) #define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \
(AR_SREV_9485(ah) ? 0x16290 : 0x16298))
#define AR_CH0_XTAL_CAPINDAC 0x7f000000 #define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24 #define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 #define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
#define AR_CH0_XTAL_CAPOUTDAC_S 17 #define AR_CH0_XTAL_CAPOUTDAC_S 17
#define AR_PHY_PMU1 0x16c40 #define AR_PHY_PMU1 (AR_SREV_9480(ah) ? 0x16340 : 0x16c40)
#define AR_PHY_PMU1_PWD 0x1 #define AR_PHY_PMU1_PWD 0x1
#define AR_PHY_PMU1_PWD_S 0 #define AR_PHY_PMU1_PWD_S 0
#define AR_PHY_PMU2 0x16c44 #define AR_PHY_PMU2 (AR_SREV_9480(ah) ? 0x16344 : 0x16c44)
#define AR_PHY_PMU2_PGM 0x00200000 #define AR_PHY_PMU2_PGM 0x00200000
#define AR_PHY_PMU2_PGM_S 21 #define AR_PHY_PMU2_PGM_S 21
@ -839,19 +883,38 @@
*/ */
#define AR_SM1_BASE 0xb200 #define AR_SM1_BASE 0xb200
#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84) #define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0) #define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4) #define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100) #define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180) #define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204) #define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208) #define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c) #define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240) #define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9300(ah) ? \
0x240 : 0x280))
#define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240)
#define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff
#define AR_PHY_TPC_19_B1_ALPHA_THERM_S 0
#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c)
#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2)) #define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2))
/* SM 1 AIC Registers */
#define AR_PHY_AIC_CTRL_0_B1 (AR_SM1_BASE + 0x4b0)
#define AR_PHY_AIC_CTRL_1_B1 (AR_SM1_BASE + 0x4b4)
#define AR_PHY_AIC_CTRL_2_B1 (AR_SM1_BASE + 0x4b8)
#define AR_PHY_AIC_STAT_0_B1 (AR_SM1_BASE + (AR_SREV_9480_10(ah) ? \
0x4c0 : 0x4c4))
#define AR_PHY_AIC_STAT_1_B1 (AR_SM1_BASE + (AR_SREV_9480_10(ah) ? \
0x4c4 : 0x4c8))
#define AR_PHY_AIC_CTRL_4_B1 (AR_SM1_BASE + 0x4c0)
#define AR_PHY_AIC_STAT_2_B1 (AR_SM1_BASE + 0x4cc)
#define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0)
#define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4)
/* /*
* Channel 2 Register Map * Channel 2 Register Map
*/ */
@ -914,6 +977,13 @@
#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180) #define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180)
/* GLB Registers */
#define AR_GLB_BASE 0x20000
#define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44)
#define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \
(AR_SREV_9480_20(_ah) ? 0x4c : 0x50))
#define AR_GLB_STATUS (AR_GLB_BASE + 0x48)
/* /*
* Misc helper defines * Misc helper defines
*/ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -87,17 +87,14 @@ struct ath_config {
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
* @BUF_AGGR: Indicates whether the buffer can be aggregated * @BUF_AGGR: Indicates whether the buffer can be aggregated
* (used in aggregation scheduling) * (used in aggregation scheduling)
* @BUF_XRETRY: To denote excessive retries of the buffer
*/ */
enum buffer_type { enum buffer_type {
BUF_AMPDU = BIT(0), BUF_AMPDU = BIT(0),
BUF_AGGR = BIT(1), BUF_AGGR = BIT(1),
BUF_XRETRY = BIT(2),
}; };
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
#define ATH_TXSTATUS_RING_SIZE 64 #define ATH_TXSTATUS_RING_SIZE 64
@ -216,6 +213,7 @@ struct ath_frame_info {
struct ath_buf_state { struct ath_buf_state {
u8 bf_type; u8 bf_type;
u8 bfs_paprd; u8 bfs_paprd;
u8 ndelim;
u16 seqno; u16 seqno;
unsigned long bfs_paprd_timestamp; unsigned long bfs_paprd_timestamp;
}; };
@ -230,7 +228,6 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale; bool bf_stale;
u16 bf_flags;
struct ath_buf_state bf_state; struct ath_buf_state bf_state;
}; };
@ -277,8 +274,7 @@ struct ath_tx_control {
}; };
#define ATH_TX_ERROR 0x01 #define ATH_TX_ERROR 0x01
#define ATH_TX_XRETRY 0x02 #define ATH_TX_BAR 0x02
#define ATH_TX_BAR 0x04
/** /**
* @txq_map: Index is mac80211 queue number. This is * @txq_map: Index is mac80211 queue number. This is
@ -425,6 +421,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
#define ATH_PAPRD_TIMEOUT 100 /* msecs */ #define ATH_PAPRD_TIMEOUT 100 /* msecs */
void ath_reset_work(struct work_struct *work);
void ath_hw_check(struct work_struct *work); void ath_hw_check(struct work_struct *work);
void ath_hw_pll_work(struct work_struct *work); void ath_hw_pll_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work); void ath_paprd_calibrate(struct work_struct *work);
@ -460,6 +457,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
#define ATH_LED_PIN_9287 8 #define ATH_LED_PIN_9287 8
#define ATH_LED_PIN_9300 10 #define ATH_LED_PIN_9300 10
#define ATH_LED_PIN_9485 6 #define ATH_LED_PIN_9485 6
#define ATH_LED_PIN_9480 0
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS
void ath_init_leds(struct ath_softc *sc); void ath_init_leds(struct ath_softc *sc);
@ -604,6 +602,7 @@ struct ath_softc {
struct mutex mutex; struct mutex mutex;
struct work_struct paprd_work; struct work_struct paprd_work;
struct work_struct hw_check_work; struct work_struct hw_check_work;
struct work_struct hw_reset_work;
struct completion paprd_complete; struct completion paprd_complete;
unsigned int hw_busy_count; unsigned int hw_busy_count;
@ -647,10 +646,10 @@ struct ath_softc {
struct ath_descdma txsdma; struct ath_descdma txsdma;
struct ath_ant_comb ant_comb; struct ath_ant_comb ant_comb;
u8 ant_tx, ant_rx;
}; };
void ath9k_tasklet(unsigned long data); void ath9k_tasklet(unsigned long data);
int ath_reset(struct ath_softc *sc, bool retry_tx);
int ath_cabq_update(struct ath_softc *); int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_common *common, int *csz) static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@ -668,6 +667,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops); const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc); void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath9k_reload_chainmask_settings(struct ath_softc *sc);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_uses_beacons(int type); bool ath9k_uses_beacons(int type);

View File

@ -73,44 +73,39 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
struct sk_buff *skb = bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ath_desc *ds; struct ath_tx_info info;
struct ath9k_11n_rate_series series[4];
int flags, ctsrate = 0, ctsduration = 0;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
u8 chainmask = ah->txchainmask;
u8 rate = 0; u8 rate = 0;
ath9k_reset_beacon_status(sc); ath9k_reset_beacon_status(sc);
ds = bf->bf_desc;
flags = ATH9K_TXDESC_NOACK;
ds->ds_link = 0;
sband = &sc->sbands[common->hw->conf.channel->band]; sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value; rate = sband->bitrates[rateidx].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
rate |= sband->bitrates[rateidx].hw_value_short; rate |= sband->bitrates[rateidx].hw_value_short;
ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, memset(&info, 0, sizeof(info));
ATH9K_PKT_TYPE_BEACON, info.pkt_len = skb->len + FCS_LEN;
MAX_RATE_POWER, info.type = ATH9K_PKT_TYPE_BEACON;
ATH9K_TXKEYIX_INVALID, info.txpower = MAX_RATE_POWER;
ATH9K_KEY_TYPE_CLEAR, info.keyix = ATH9K_TXKEYIX_INVALID;
flags); info.keytype = ATH9K_KEY_TYPE_CLEAR;
info.flags = ATH9K_TXDESC_NOACK;
/* NB: beacon's BufLen must be a multiple of 4 bytes */ info.buf_addr[0] = bf->bf_buf_addr;
ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), info.buf_len[0] = roundup(skb->len, 4);
true, true, ds, bf->bf_buf_addr,
sc->beacon.beaconq);
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); info.is_first = true;
series[0].Tries = 1; info.is_last = true;
series[0].Rate = rate;
series[0].ChSel = ath_txchainmask_reduction(sc, info.qcu = sc->beacon.beaconq;
common->tx_chainmask, series[0].Rate);
series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; info.rates[0].Tries = 1;
ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, info.rates[0].Rate = rate;
series, 4, 0); info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
} }
static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
@ -386,9 +381,7 @@ void ath_beacon_tasklet(unsigned long data)
ath_dbg(common, ATH_DBG_BSTUCK, ath_dbg(common, ATH_DBG_BSTUCK,
"beacon is officially stuck\n"); "beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET; sc->sc_flags |= SC_OP_TSF_RESET;
spin_lock(&sc->sc_pcu_lock); ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath_reset(sc, true);
spin_unlock(&sc->sc_pcu_lock);
} }
return; return;
@ -519,6 +512,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
/* Set the computed AP beacon timers */ /* Set the computed AP beacon timers */
ath9k_hw_disable_interrupts(ah); ath9k_hw_disable_interrupts(ah);
sc->sc_flags |= SC_OP_TSF_RESET;
ath9k_beacon_init(sc, nexttbtt, intval); ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0; sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, ah->imask); ath9k_hw_set_interrupts(ah, ah->imask);

View File

@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath_softc *sc = file->private_data; struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah;
char buf[32]; char buf[32];
unsigned int len; unsigned int len;
len = sprintf(buf, "0x%08x\n", common->tx_chainmask); len = sprintf(buf, "0x%08x\n", ah->txchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len); return simple_read_from_buffer(user_buf, count, ppos, buf, len);
} }
@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath_softc *sc = file->private_data; struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah;
unsigned long mask; unsigned long mask;
char buf[32]; char buf[32];
ssize_t len; ssize_t len;
@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
if (strict_strtoul(buf, 0, &mask)) if (strict_strtoul(buf, 0, &mask))
return -EINVAL; return -EINVAL;
common->tx_chainmask = mask; ah->txchainmask = mask;
sc->sc_ah->caps.tx_chainmask = mask; ah->caps.tx_chainmask = mask;
return count; return count;
} }
@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath_softc *sc = file->private_data; struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah;
char buf[32]; char buf[32];
unsigned int len; unsigned int len;
len = sprintf(buf, "0x%08x\n", common->rx_chainmask); len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len); return simple_read_from_buffer(user_buf, count, ppos, buf, len);
} }
@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath_softc *sc = file->private_data; struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah;
unsigned long mask; unsigned long mask;
char buf[32]; char buf[32];
ssize_t len; ssize_t len;
@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
if (strict_strtoul(buf, 0, &mask)) if (strict_strtoul(buf, 0, &mask))
return -EINVAL; return -EINVAL;
common->rx_chainmask = mask; ah->rxchainmask = mask;
sc->sc_ah->caps.rx_chainmask = mask; ah->caps.rx_chainmask = mask;
return count; return count;
} }
@ -826,7 +826,8 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
} }
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq) struct ath_tx_status *ts, struct ath_txq *txq,
unsigned int flags)
{ {
#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\ #define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
[sc->debug.tsidx].c) [sc->debug.tsidx].c)
@ -836,12 +837,12 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
if (bf_isampdu(bf)) { if (bf_isampdu(bf)) {
if (bf_isxretried(bf)) if (flags & ATH_TX_BAR)
TX_STAT_INC(qnum, a_xretries); TX_STAT_INC(qnum, a_xretries);
else else
TX_STAT_INC(qnum, a_completed); TX_STAT_INC(qnum, a_completed);
} else { } else {
if (bf_isxretried(bf)) if (ts->ts_status & ATH9K_TXERR_XRETRY)
TX_STAT_INC(qnum, xretries); TX_STAT_INC(qnum, xretries);
else else
TX_STAT_INC(qnum, completed); TX_STAT_INC(qnum, completed);
@ -1323,16 +1324,17 @@ void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->debug.samp_lock);
spin_lock_irqsave(&common->cc_lock, flags); spin_lock_irqsave(&common->cc_lock, flags);
ath_hw_cycle_counters_update(common); ath_hw_cycle_counters_update(common);
spin_unlock_irqrestore(&common->cc_lock, flags);
spin_lock_bh(&sc->debug.samp_lock);
ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles; ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy; ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame; ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame; ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
spin_unlock_irqrestore(&common->cc_lock, flags);
ATH_SAMP_DBG(noise) = ah->noise; ATH_SAMP_DBG(noise) = ah->noise;
REG_WRITE_D(ah, AR_MACMISC, REG_WRITE_D(ah, AR_MACMISC,
@ -1373,6 +1375,9 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
u8 nread; u8 nread;
if (sc->sc_flags & SC_OP_INVALID)
return -EAGAIN;
buf = vmalloc(size); buf = vmalloc(size);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
@ -1381,10 +1386,14 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
vfree(buf); vfree(buf);
return -ENOMEM; return -ENOMEM;
} }
/* Account the current state too */
ath9k_debug_samp_bb_mac(sc);
spin_lock_bh(&sc->debug.samp_lock); spin_lock_bh(&sc->debug.samp_lock);
memcpy(bb_mac_samp, sc->debug.bb_mac_samp, memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
len += snprintf(buf + len, size - len,
"Current Sample Index: %d\n", sc->debug.sampidx);
spin_unlock_bh(&sc->debug.samp_lock); spin_unlock_bh(&sc->debug.samp_lock);
len += snprintf(buf + len, size - len, len += snprintf(buf + len, size - len,

View File

@ -230,7 +230,8 @@ int ath9k_init_debug(struct ath_hw *ah);
void ath9k_debug_samp_bb_mac(struct ath_softc *sc); void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq); struct ath_tx_status *ts, struct ath_txq *txq,
unsigned int flags);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
#else #else
@ -252,7 +253,8 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
static inline void ath_debug_stat_tx(struct ath_softc *sc, static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_buf *bf, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_tx_status *ts,
struct ath_txq *txq) struct ath_txq *txq,
unsigned int flags)
{ {
} }

View File

@ -48,6 +48,8 @@ void ath_init_leds(struct ath_softc *sc)
sc->sc_ah->led_pin = ATH_LED_PIN_9485; sc->sc_ah->led_pin = ATH_LED_PIN_9485;
else if (AR_SREV_9300(sc->sc_ah)) else if (AR_SREV_9300(sc->sc_ah))
sc->sc_ah->led_pin = ATH_LED_PIN_9300; sc->sc_ah->led_pin = ATH_LED_PIN_9300;
else if (AR_SREV_9480(sc->sc_ah))
sc->sc_ah->led_pin = ATH_LED_PIN_9480;
else else
sc->sc_ah->led_pin = ATH_LED_PIN_DEF; sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
} }

View File

@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv,
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
/* ath9k_htc supports only 1 or 2 stream devices */ /* ath9k_htc supports only 1 or 2 stream devices */
tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n", "TX streams %d, RX streams: %d\n",
@ -601,9 +601,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
{ {
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
common->tx_chainmask = priv->ah->caps.tx_chainmask;
common->rx_chainmask = priv->ah->caps.rx_chainmask;
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
priv->ah->opmode = NL80211_IFTYPE_STATION; priv->ah->opmode = NL80211_IFTYPE_STATION;

View File

@ -826,8 +826,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
if (longcal || shortcal) if (longcal || shortcal)
common->ani.caldone = common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan, ath9k_hw_calibrate(ah, ah->curchan,
common->rx_chainmask, ah->rxchainmask, longcal);
longcal);
ath9k_htc_ps_restore(priv); ath9k_htc_ps_restore(priv);
} }

View File

@ -54,13 +54,10 @@ static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
return ath9k_hw_ops(ah)->get_isr(ah, masked); return ath9k_hw_ops(ah)->get_isr(ah, masked);
} }
static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen, static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
bool is_firstseg, bool is_lastseg, struct ath_tx_info *i)
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{ {
ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg, return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
ds0, buf_addr, qcu);
} }
static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
@ -69,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
} }
static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx,
enum ath9k_key_type keyType,
u32 flags)
{
ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
keyType, flags);
}
static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
rtsctsRate, rtsctsDuration, series,
nseries, flags);
}
static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
}
static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
}
static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
}
static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
}
static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
{
ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
}
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf) struct ath_hw_antcomb_conf *antconf)
{ {

View File

@ -580,6 +580,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9330: case AR_SREV_VERSION_9330:
case AR_SREV_VERSION_9485: case AR_SREV_VERSION_9485:
case AR_SREV_VERSION_9340: case AR_SREV_VERSION_9340:
case AR_SREV_VERSION_9480:
break; break;
default: default:
ath_err(common, ath_err(common,
@ -664,6 +665,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9300_DEVID_AR9330: case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340: case AR9300_DEVID_AR9340:
case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9580:
case AR9300_DEVID_AR9480:
break; break;
default: default:
if (common->bus_ops->ath_bus_type == ATH_USB) if (common->bus_ops->ath_bus_type == ATH_USB)
@ -960,7 +962,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf; struct ieee80211_conf *conf = &common->hw->conf;
const struct ath9k_channel *chan = ah->curchan; const struct ath9k_channel *chan = ah->curchan;
int acktimeout; int acktimeout, ctstimeout;
int slottime; int slottime;
int sifstime; int sifstime;
int rx_lat = 0, tx_lat = 0, eifs = 0; int rx_lat = 0, tx_lat = 0, eifs = 0;
@ -975,7 +977,10 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (ah->misc_mode != 0) if (ah->misc_mode != 0)
REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
rx_lat = 37; if (IS_CHAN_A_FAST_CLOCK(ah, chan))
rx_lat = 41;
else
rx_lat = 37;
tx_lat = 54; tx_lat = 54;
if (IS_CHAN_HALF_RATE(chan)) { if (IS_CHAN_HALF_RATE(chan)) {
@ -989,7 +994,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
sifstime = 32; sifstime = 32;
} else if (IS_CHAN_QUARTER_RATE(chan)) { } else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340; eifs = 340;
rx_lat *= 4; rx_lat = (rx_lat * 4) - 1;
tx_lat *= 4; tx_lat *= 4;
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 22; tx_lat += 22;
@ -1017,6 +1022,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
/* As defined by IEEE 802.11-2007 17.3.8.6 */ /* As defined by IEEE 802.11-2007 17.3.8.6 */
acktimeout = slottime + sifstime + 3 * ah->coverage_class; acktimeout = slottime + sifstime + 3 * ah->coverage_class;
ctstimeout = acktimeout;
/* /*
* Workaround for early ACK timeouts, add an offset to match the * Workaround for early ACK timeouts, add an offset to match the
@ -1031,7 +1037,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
ath9k_hw_set_sifs_time(ah, sifstime); ath9k_hw_set_sifs_time(ah, sifstime);
ath9k_hw_setslottime(ah, slottime); ath9k_hw_setslottime(ah, slottime);
ath9k_hw_set_ack_timeout(ah, acktimeout); ath9k_hw_set_ack_timeout(ah, acktimeout);
ath9k_hw_set_cts_timeout(ah, acktimeout); ath9k_hw_set_cts_timeout(ah, ctstimeout);
if (ah->globaltxtimeout != (u32) -1) if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
@ -1336,6 +1342,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
{ {
if (AR_SREV_9300_20_OR_LATER(ah)) { if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal); REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10); udelay(10);
@ -1475,9 +1482,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
u64 tsf = 0; u64 tsf = 0;
int i, r; int i, r;
ah->txchainmask = common->tx_chainmask;
ah->rxchainmask = common->rx_chainmask;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO; return -EIO;
@ -1495,14 +1499,16 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
} }
ah->noise = ath9k_hw_getchan_noise(ah, chan); ah->noise = ath9k_hw_getchan_noise(ah, chan);
if ((AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) ||
(AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
bChannelChange = false;
if (bChannelChange && if (bChannelChange &&
(ah->chip_fullsleep != true) && (ah->chip_fullsleep != true) &&
(ah->curchan != NULL) && (ah->curchan != NULL) &&
(chan->channel != ah->curchan->channel) && (chan->channel != ah->curchan->channel) &&
((chan->channelFlags & CHANNEL_ALL) == ((chan->channelFlags & CHANNEL_ALL) ==
(ah->curchan->channelFlags & CHANNEL_ALL)) && (ah->curchan->channelFlags & CHANNEL_ALL))) {
(!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
if (ath9k_hw_channel_change(ah, chan)) { if (ath9k_hw_channel_change(ah, chan)) {
ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true); ath9k_hw_start_nfcal(ah, true);
@ -1742,25 +1748,41 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
{ {
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (setChip) { if (setChip) {
if (AR_SREV_9480(ah)) {
REG_WRITE(ah, AR_TIMER_MODE,
REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00);
REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah,
AR_NDP2_TIMER_MODE) & 0xFFFFFF00);
REG_WRITE(ah, AR_SLP32_INC,
REG_READ(ah, AR_SLP32_INC) & 0xFFF00000);
/* xxx Required for WLAN only case ? */
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
udelay(100);
}
/* /*
* Clear the RTC force wake bit to allow the * Clear the RTC force wake bit to allow the
* mac to go to sleep. * mac to go to sleep.
*/ */
REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
AR_RTC_FORCE_WAKE_EN);
if (AR_SREV_9480(ah))
udelay(100);
if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
/* Shutdown chip. Active low */ /* Shutdown chip. Active low */
if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) if (!AR_SREV_5416(ah) &&
REG_CLR_BIT(ah, (AR_RTC_RESET), !AR_SREV_9271(ah) && !AR_SREV_9480_10(ah)) {
AR_RTC_RESET_EN); REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
udelay(2);
}
} }
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
if (AR_SREV_9300_20_OR_LATER(ah)) if (!AR_SREV_9480(ah))
REG_WRITE(ah, AR_WA, REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
} }
/* /*
@ -1770,6 +1792,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
*/ */
static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
{ {
u32 val;
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (setChip) { if (setChip) {
struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_hw_capabilities *pCap = &ah->caps;
@ -1779,12 +1803,30 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
REG_WRITE(ah, AR_RTC_FORCE_WAKE, REG_WRITE(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_ON_INT); AR_RTC_FORCE_WAKE_ON_INT);
} else { } else {
/* When chip goes into network sleep, it could be waken
* up by MCI_INT interrupt caused by BT's HW messages
* (LNA_xxx, CONT_xxx) which chould be in a very fast
* rate (~100us). This will cause chip to leave and
* re-enter network sleep mode frequently, which in
* consequence will have WLAN MCI HW to generate lots of
* SYS_WAKING and SYS_SLEEPING messages which will make
* BT CPU to busy to process.
*/
if (AR_SREV_9480(ah)) {
val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) &
~AR_MCI_INTERRUPT_RX_HW_MSG_MASK;
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val);
}
/* /*
* Clear the RTC force wake bit to allow the * Clear the RTC force wake bit to allow the
* mac to go to sleep. * mac to go to sleep.
*/ */
REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_EN); AR_RTC_FORCE_WAKE_EN);
if (AR_SREV_9480(ah))
udelay(30);
} }
} }
@ -2091,6 +2133,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
ah->txchainmask = pCap->tx_chainmask;
ah->rxchainmask = pCap->rx_chainmask;
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
@ -2401,6 +2445,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
ENABLE_REGWRITE_BUFFER(ah); ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9480(ah))
bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
REG_WRITE(ah, AR_RX_FILTER, bits); REG_WRITE(ah, AR_RX_FILTER, bits);
phybits = 0; phybits = 0;
@ -2447,13 +2494,13 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan; struct ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan; struct ieee80211_channel *channel = chan->chan;
int reg_pwr = min_t(int, MAX_RATE_POWER, regulatory->power_limit); int reg_pwr = min_t(int, MAX_RATE_POWER, limit);
int chan_pwr = channel->max_power * 2; int chan_pwr = channel->max_power * 2;
if (test) if (test)
reg_pwr = chan_pwr = MAX_RATE_POWER; reg_pwr = chan_pwr = MAX_RATE_POWER;
regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); regulatory->power_limit = reg_pwr;
ah->eep_ops->set_txpower(ah, chan, ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(regulatory, chan), ath9k_regd_get_ctl(regulatory, chan),
@ -2657,6 +2704,20 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask); gen_tmr_configuration[timer->index].mode_mask);
if (AR_SREV_9480(ah)) {
/*
* Starting from AR9480, each generic timer can select which tsf
* to use. But we still follow the old rule, 0 - 7 use tsf and
* 8 - 15 use tsf2.
*/
if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
(1 << timer->index));
else
REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
(1 << timer->index));
}
/* Enable both trigger and thresh interrupt masks */ /* Enable both trigger and thresh interrupt masks */
REG_SET_BIT(ah, AR_IMR_S5, REG_SET_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
@ -2762,6 +2823,7 @@ static struct {
{ AR_SREV_VERSION_9330, "9330" }, { AR_SREV_VERSION_9330, "9330" },
{ AR_SREV_VERSION_9340, "9340" }, { AR_SREV_VERSION_9340, "9340" },
{ AR_SREV_VERSION_9485, "9485" }, { AR_SREV_VERSION_9485, "9485" },
{ AR_SREV_VERSION_9480, "9480" },
}; };
/* For devices with external radios */ /* For devices with external radios */

View File

@ -46,6 +46,7 @@
#define AR9300_DEVID_AR9340 0x0031 #define AR9300_DEVID_AR9340 0x0031
#define AR9300_DEVID_AR9485_PCIE 0x0032 #define AR9300_DEVID_AR9485_PCIE 0x0032
#define AR9300_DEVID_AR9580 0x0033 #define AR9300_DEVID_AR9580 0x0033
#define AR9300_DEVID_AR9480 0x0034
#define AR9300_DEVID_AR9330 0x0035 #define AR9300_DEVID_AR9330 0x0035
#define AR5416_AR9100_DEVID 0x000b #define AR5416_AR9100_DEVID 0x000b
@ -615,30 +616,10 @@ struct ath_hw_ops {
u8 rxchainmask, u8 rxchainmask,
bool longcal); bool longcal);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen, void (*set_txdesc)(struct ath_hw *ah, void *ds,
bool is_firstseg, bool is_is_lastseg, struct ath_tx_info *i);
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu);
int (*proc_txdesc)(struct ath_hw *ah, void *ds, int (*proc_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts); struct ath_tx_status *ts);
void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u8 keyIx,
enum ath9k_key_type keyType,
u32 flags);
void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags);
void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
u32 aggrLen);
void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
u32 numDelims);
void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
void (*antdiv_comb_conf_get)(struct ath_hw *ah, void (*antdiv_comb_conf_get)(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf); struct ath_hw_antcomb_conf *antconf);
void (*antdiv_comb_conf_set)(struct ath_hw *ah, void (*antdiv_comb_conf_set)(struct ath_hw *ah,
@ -827,11 +808,14 @@ struct ath_hw {
struct ar5416IniArray iniModes_9271_1_0_only; struct ar5416IniArray iniModes_9271_1_0_only;
struct ar5416IniArray iniCckfirNormal; struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484; struct ar5416IniArray iniCckfirJapan2484;
struct ar5416IniArray ini_japan2484;
struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271; struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271; struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray iniModes_high_power_tx_gain_9271; struct ar5416IniArray iniModes_high_power_tx_gain_9271;
struct ar5416IniArray iniModes_normal_power_tx_gain_9271; struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
struct ar5416IniArray ini_radio_post_sys2ant;
struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];

View File

@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_softc *sc,
/* set up supported mcs set */ /* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n", "TX streams %d, RX streams: %d\n",
@ -506,9 +506,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->sc_flags |= SC_OP_RXAGGR; sc->sc_flags |= SC_OP_RXAGGR;
} }
common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
ath9k_hw_set_diversity(sc->sc_ah, true); ath9k_hw_set_diversity(sc->sc_ah, true);
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
@ -646,10 +643,8 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
static void ath9k_init_txpower_limits(struct ath_softc *sc) static void ath9k_init_txpower_limits(struct ath_softc *sc)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_channel *curchan = ah->curchan; struct ath9k_channel *curchan = ah->curchan;
ah->txchainmask = common->tx_chainmask;
if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
@ -658,9 +653,22 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc)
ah->curchan = curchan; ah->curchan = curchan;
} }
void ath9k_reload_chainmask_settings(struct ath_softc *sc)
{
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
return;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
@ -698,6 +706,16 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->sta_data_size = sizeof(struct ath_node); hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif); hw->vif_data_size = sizeof(struct ath_vif);
hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
/* single chain devices with rx diversity */
if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
sc->ant_rx = hw->wiphy->available_antennas_rx;
sc->ant_tx = hw->wiphy->available_antennas_tx;
#ifdef CONFIG_ATH9K_RATE_CONTROL #ifdef CONFIG_ATH9K_RATE_CONTROL
hw->rate_control_algorithm = "ath9k_rate_control"; hw->rate_control_algorithm = "ath9k_rate_control";
#endif #endif
@ -709,12 +727,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ]; &sc->sbands[IEEE80211_BAND_5GHZ];
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { ath9k_reload_chainmask_settings(sc);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
SET_IEEE80211_PERM_ADDR(hw, common->macaddr); SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
} }
@ -782,6 +795,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
goto error_world; goto error_world;
} }
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->hw_check_work, ath_hw_check); INIT_WORK(&sc->hw_check_work, ath_hw_check);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);

View File

@ -62,18 +62,6 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
} }
EXPORT_SYMBOL(ath9k_hw_txstart); EXPORT_SYMBOL(ath9k_hw_txstart);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
}
EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
{ {
u32 npend; u32 npend;

View File

@ -263,7 +263,11 @@ struct ath_desc {
#define ATH9K_TXDESC_VMF 0x0100 #define ATH9K_TXDESC_VMF 0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200 #define ATH9K_TXDESC_FRAG_IS_ON 0x0200
#define ATH9K_TXDESC_LOWRXCHAIN 0x0400 #define ATH9K_TXDESC_LOWRXCHAIN 0x0400
#define ATH9K_TXDESC_LDPC 0x00010000 #define ATH9K_TXDESC_LDPC 0x0800
#define ATH9K_TXDESC_CLRDMASK 0x1000
#define ATH9K_TXDESC_PAPRD 0x70000
#define ATH9K_TXDESC_PAPRD_S 16
#define ATH9K_RXDESC_INTREQ 0x0020 #define ATH9K_RXDESC_INTREQ 0x0020
@ -644,6 +648,7 @@ enum ath9k_rx_filter {
ATH9K_RX_FILTER_PSPOLL = 0x00004000, ATH9K_RX_FILTER_PSPOLL = 0x00004000,
ATH9K_RX_FILTER_PHYRADAR = 0x00002000, ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
}; };
#define ATH9K_RATESERIES_RTS_CTS 0x0001 #define ATH9K_RATESERIES_RTS_CTS 0x0001
@ -659,6 +664,13 @@ struct ath9k_11n_rate_series {
u32 RateFlags; u32 RateFlags;
}; };
enum aggr_type {
AGGR_BUF_NONE,
AGGR_BUF_FIRST,
AGGR_BUF_MIDDLE,
AGGR_BUF_LAST,
};
enum ath9k_key_type { enum ath9k_key_type {
ATH9K_KEY_TYPE_CLEAR, ATH9K_KEY_TYPE_CLEAR,
ATH9K_KEY_TYPE_WEP, ATH9K_KEY_TYPE_WEP,
@ -666,6 +678,33 @@ enum ath9k_key_type {
ATH9K_KEY_TYPE_TKIP, ATH9K_KEY_TYPE_TKIP,
}; };
struct ath_tx_info {
u8 qcu;
bool is_first;
bool is_last;
enum aggr_type aggr;
u8 ndelim;
u16 aggr_len;
dma_addr_t link;
int pkt_len;
u32 flags;
dma_addr_t buf_addr[4];
int buf_len[4];
struct ath9k_11n_rate_series rates[4];
u8 rtscts_rate;
bool dur_update;
enum ath9k_pkt_type type;
enum ath9k_key_type keytype;
u8 keyix;
u8 txpower;
};
struct ath_hw; struct ath_hw;
struct ath9k_channel; struct ath9k_channel;
enum ath9k_int; enum ath9k_int;
@ -673,7 +712,6 @@ enum ath9k_int;
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
void ath9k_hw_txstart(struct ath_hw *ah, u32 q); void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q); bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);

View File

@ -111,24 +111,29 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
void ath9k_ps_restore(struct ath_softc *sc) void ath9k_ps_restore(struct ath_softc *sc)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
enum ath9k_power_mode mode;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags); spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (--sc->ps_usecount != 0) if (--sc->ps_usecount != 0)
goto unlock; goto unlock;
spin_lock(&common->cc_lock);
ath_hw_cycle_counters_update(common);
spin_unlock(&common->cc_lock);
if (sc->ps_idle) if (sc->ps_idle)
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled && else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON | !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB | PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_PSPOLL_DATA |
PS_WAIT_FOR_TX_ACK))) PS_WAIT_FOR_TX_ACK)))
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); mode = ATH9K_PM_NETWORK_SLEEP;
else
goto unlock;
spin_lock(&common->cc_lock);
ath_hw_cycle_counters_update(common);
spin_unlock(&common->cc_lock);
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
unlock: unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags); spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
@ -212,6 +217,149 @@ static int ath_update_survey_stats(struct ath_softc *sc)
return ret; return ret;
} }
static void __ath_cancel_work(struct ath_softc *sc)
{
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
}
static void ath_cancel_work(struct ath_softc *sc)
{
__ath_cancel_work(sc);
cancel_work_sync(&sc->hw_reset_work);
}
static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool ret;
ieee80211_stop_queues(sc->hw);
sc->hw_busy_count = 0;
del_timer_sync(&common->ani.timer);
ath9k_debug_samp_bb_mac(sc);
ath9k_hw_disable_interrupts(ah);
ret = ath_drain_all_txq(sc, retry_tx);
if (!ath_stoprecv(sc))
ret = false;
if (!flush) {
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_rx_tasklet(sc, 1, true);
ath_rx_tasklet(sc, 1, false);
} else {
ath_flushrecv(sc);
}
return ret;
}
static bool ath_complete_reset(struct ath_softc *sc, bool start)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
return false;
}
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_hw_enable_interrupts(ah);
if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
if (sc->sc_flags & SC_OP_BEACONS)
ath_set_beacon(sc);
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
if (!common->disable_ani)
ath_start_ani(common);
}
if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
struct ath_hw_antcomb_conf div_ant_conf;
u8 lna_conf;
ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
if (sc->ant_rx == 1)
lna_conf = ATH_ANT_DIV_COMB_LNA1;
else
lna_conf = ATH_ANT_DIV_COMB_LNA2;
div_ant_conf.main_lna_conf = lna_conf;
div_ant_conf.alt_lna_conf = lna_conf;
ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
}
ieee80211_wake_queues(sc->hw);
return true;
}
static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
bool retry_tx)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_cal_data *caldata = NULL;
bool fastcc = true;
bool flush = false;
int r;
__ath_cancel_work(sc);
spin_lock_bh(&sc->sc_pcu_lock);
if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
fastcc = false;
caldata = &sc->caldata;
}
if (!hchan) {
fastcc = false;
flush = true;
hchan = ah->curchan;
}
if (fastcc && !ath9k_hw_check_alive(ah))
fastcc = false;
if (!ath_prepare_reset(sc, retry_tx, flush))
fastcc = false;
ath_dbg(common, ATH_DBG_CONFIG,
"Reset to %u MHz, HT40: %d fastcc: %d\n",
hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
CHANNEL_HT40PLUS)),
fastcc);
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
if (r) {
ath_err(common,
"Unable to reset channel, reset status %d\n", r);
goto out;
}
if (!ath_complete_reset(sc, true))
r = -EIO;
out:
spin_unlock_bh(&sc->sc_pcu_lock);
return r;
}
/* /*
* Set/change channels. If the channel is really being changed, it's done * Set/change channels. If the channel is really being changed, it's done
* by reseting the chip. To accomplish this we must first cleanup any pending * by reseting the chip. To accomplish this we must first cleanup any pending
@ -220,97 +368,17 @@ static int ath_update_survey_stats(struct ath_softc *sc)
static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *hchan) struct ath9k_channel *hchan)
{ {
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
bool fastcc = true, stopped;
struct ieee80211_channel *channel = hw->conf.channel;
struct ath9k_hw_cal_data *caldata = NULL;
int r; int r;
if (sc->sc_flags & SC_OP_INVALID) if (sc->sc_flags & SC_OP_INVALID)
return -EIO; return -EIO;
sc->hw_busy_count = 0;
del_timer_sync(&common->ani.timer);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock); r = ath_reset_internal(sc, hchan, false);
/*
* This is only performed if the channel settings have
* actually changed.
*
* To switch channels clear any pending DMA operations;
* wait long enough for the RX fifo to drain, reset the
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
ath9k_hw_disable_interrupts(ah);
stopped = ath_drain_all_txq(sc, false);
if (!ath_stoprecv(sc))
stopped = false;
if (!ath9k_hw_check_alive(ah))
stopped = false;
/* XXX: do not flush receive queue here. We don't want
* to flush data frames already in queue because of
* changing channel. */
if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
fastcc = false;
if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
caldata = &sc->caldata;
ath_dbg(common, ATH_DBG_CONFIG,
"(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
sc->sc_ah->curchan->channel,
channel->center_freq, conf_is_ht40(conf),
fastcc);
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
if (r) {
ath_err(common,
"Unable to reset channel (%u MHz), reset status %d\n",
channel->center_freq, r);
goto ps_restore;
}
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
r = -EIO;
goto ps_restore;
}
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_hw_enable_interrupts(ah);
if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
if (sc->sc_flags & SC_OP_BEACONS)
ath_set_beacon(sc);
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
if (!common->disable_ani)
ath_start_ani(common);
}
ps_restore:
ieee80211_wake_queues(hw);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
return r; return r;
} }
@ -318,7 +386,6 @@ static void ath_paprd_activate(struct ath_softc *sc)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah);
int chain; int chain;
if (!caldata || !caldata->paprd_done) if (!caldata || !caldata->paprd_done)
@ -327,7 +394,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false); ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(common->tx_chainmask & BIT(chain))) if (!(ah->txchainmask & BIT(chain)))
continue; continue;
ar9003_paprd_populate_single_table(ah, caldata, chain); ar9003_paprd_populate_single_table(ah, caldata, chain);
@ -414,7 +481,7 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(common->tx_chainmask & BIT(chain))) if (!(ah->txchainmask & BIT(chain)))
continue; continue;
chain_ok = 0; chain_ok = 0;
@ -535,7 +602,7 @@ void ath_ani_calibrate(unsigned long data)
if (longcal || shortcal) { if (longcal || shortcal) {
common->ani.caldone = common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan, ath9k_hw_calibrate(ah, ah->curchan,
common->rx_chainmask, longcal); ah->rxchainmask, longcal);
} }
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
@ -597,74 +664,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
ath_tx_node_cleanup(sc, an); ath_tx_node_cleanup(sc, an);
} }
void ath_hw_check(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
int busy;
ath9k_ps_wakeup(sc);
if (ath9k_hw_check_alive(sc->sc_ah))
goto out;
spin_lock_irqsave(&common->cc_lock, flags);
busy = ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
if (busy >= 99) {
if (++sc->hw_busy_count >= 3) {
spin_lock_bh(&sc->sc_pcu_lock);
ath_reset(sc, true);
spin_unlock_bh(&sc->sc_pcu_lock);
}
} else if (busy >= 0)
sc->hw_busy_count = 0;
out:
ath9k_ps_restore(sc);
}
static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
{
static int count;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
if (pll_sqsum >= 0x40000) {
count++;
if (count == 3) {
/* Rx is hung for more than 500ms. Reset it */
ath_dbg(common, ATH_DBG_RESET,
"Possible RX hang, resetting");
spin_lock_bh(&sc->sc_pcu_lock);
ath_reset(sc, true);
spin_unlock_bh(&sc->sc_pcu_lock);
count = 0;
}
} else
count = 0;
}
void ath_hw_pll_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc,
hw_pll_work.work);
u32 pll_sqsum;
if (AR_SREV_9485(sc->sc_ah)) {
ath9k_ps_wakeup(sc);
pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
ath9k_ps_restore(sc);
ath_hw_pll_rx_hang_check(sc, pll_sqsum);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
}
}
void ath9k_tasklet(unsigned long data) void ath9k_tasklet(unsigned long data)
{ {
@ -675,17 +674,15 @@ void ath9k_tasklet(unsigned long data)
u32 status = sc->intrstatus; u32 status = sc->intrstatus;
u32 rxmask; u32 rxmask;
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
spin_lock(&sc->sc_pcu_lock);
ath_reset(sc, true);
spin_unlock(&sc->sc_pcu_lock);
return;
}
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
spin_lock(&sc->sc_pcu_lock); spin_lock(&sc->sc_pcu_lock);
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
goto out;
}
/* /*
* Only run the baseband hang check if beacons stop working in AP or * Only run the baseband hang check if beacons stop working in AP or
* IBSS mode, because it has a high false positive rate. For station * IBSS mode, because it has a high false positive rate. For station
@ -733,6 +730,7 @@ void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_GENTIMER) if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah); ath_gen_timer_isr(sc->sc_ah);
out:
/* re-enable hardware interrupt */ /* re-enable hardware interrupt */
ath9k_hw_enable_interrupts(ah); ath9k_hw_enable_interrupts(ah);
@ -895,28 +893,13 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
channel->center_freq, r); channel->center_freq, r);
} }
ath9k_cmn_update_txpow(ah, sc->curtxpow, ath_complete_reset(sc, true);
sc->config.txpowlimit, &sc->curtxpow);
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
goto out;
}
if (sc->sc_flags & SC_OP_BEACONS)
ath_set_beacon(sc); /* restart beacons */
/* Re-Enable interrupts */
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_hw_enable_interrupts(ah);
/* Enable LED */ /* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin, ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT); AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0); ath9k_hw_set_gpio(ah, ah->led_pin, 0);
ieee80211_wake_queues(hw);
ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
out:
spin_unlock_bh(&sc->sc_pcu_lock); spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
@ -929,12 +912,11 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
int r; int r;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
cancel_delayed_work_sync(&sc->hw_pll_work);
ath_cancel_work(sc);
spin_lock_bh(&sc->sc_pcu_lock); spin_lock_bh(&sc->sc_pcu_lock);
ieee80211_stop_queues(hw);
/* /*
* Keep the LED on when the radio is disabled * Keep the LED on when the radio is disabled
* during idle unassociated state. * during idle unassociated state.
@ -944,13 +926,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_cfg_gpio_input(ah, ah->led_pin); ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
} }
/* Disable interrupts */ ath_prepare_reset(sc, false, true);
ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, false); /* clear pending tx frames */
ath_stoprecv(sc); /* turn off frame recv */
ath_flushrecv(sc); /* flush recv queue */
if (!ah->curchan) if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah); ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
@ -970,51 +946,13 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
} }
int ath_reset(struct ath_softc *sc, bool retry_tx) static int ath_reset(struct ath_softc *sc, bool retry_tx)
{ {
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_hw *hw = sc->hw;
int r; int r;
sc->hw_busy_count = 0;
ath9k_debug_samp_bb_mac(sc);
/* Stop ANI */
del_timer_sync(&common->ani.timer);
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ieee80211_stop_queues(hw); r = ath_reset_internal(sc, NULL, retry_tx);
ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, retry_tx);
ath_stoprecv(sc);
ath_flushrecv(sc);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
if (r)
ath_err(common,
"Unable to reset hardware; reset status %d\n", r);
if (ath_startrecv(sc) != 0)
ath_err(common, "Unable to start recv logic\n");
/*
* We may be doing a reset in response to a request
* that changes the channel so update any state that
* might change as a result.
*/
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
ath_set_beacon(sc); /* restart beacons */
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_hw_enable_interrupts(ah);
if (retry_tx) { if (retry_tx) {
int i; int i;
@ -1027,17 +965,82 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
} }
} }
ieee80211_wake_queues(hw);
/* Start ANI */
if (!common->disable_ani)
ath_start_ani(common);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
return r; return r;
} }
void ath_reset_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
ath_reset(sc, true);
}
void ath_hw_check(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
int busy;
ath9k_ps_wakeup(sc);
if (ath9k_hw_check_alive(sc->sc_ah))
goto out;
spin_lock_irqsave(&common->cc_lock, flags);
busy = ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
if (busy >= 99) {
if (++sc->hw_busy_count >= 3)
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
} else if (busy >= 0)
sc->hw_busy_count = 0;
out:
ath9k_ps_restore(sc);
}
static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
{
static int count;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
if (pll_sqsum >= 0x40000) {
count++;
if (count == 3) {
/* Rx is hung for more than 500ms. Reset it */
ath_dbg(common, ATH_DBG_RESET,
"Possible RX hang, resetting");
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
count = 0;
}
} else
count = 0;
}
void ath_hw_pll_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc,
hw_pll_work.work);
u32 pll_sqsum;
if (AR_SREV_9485(sc->sc_ah)) {
ath9k_ps_wakeup(sc);
pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
ath9k_ps_restore(sc);
ath_hw_pll_rx_hang_check(sc, pll_sqsum);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
}
}
/**********************/ /**********************/
/* mac80211 callbacks */ /* mac80211 callbacks */
/**********************/ /**********************/
@ -1084,28 +1087,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
goto mutex_unlock; goto mutex_unlock;
} }
/*
* This is needed only to setup initial state
* but it's best done after a reset.
*/
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
/*
* Setup the hardware after reset:
* The receive engine is set going.
* Frame transmit is handled entirely
* in the frame output path; there's nothing to do
* here except setup the interrupt mask.
*/
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to start recv logic\n");
r = -EIO;
spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
spin_unlock_bh(&sc->sc_pcu_lock);
/* Setup our intr mask. */ /* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
ATH9K_INT_RXORN | ATH9K_INT_FATAL | ATH9K_INT_RXORN | ATH9K_INT_FATAL |
@ -1128,12 +1109,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
/* Disable BMISS interrupt when we're not associated */ /* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
ath9k_hw_set_interrupts(ah, ah->imask);
ath9k_hw_enable_interrupts(ah);
ieee80211_wake_queues(hw); if (!ath_complete_reset(sc, false)) {
r = -EIO;
spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); spin_unlock_bh(&sc->sc_pcu_lock);
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
!ah->btcoex_hw.enabled) { !ah->btcoex_hw.enabled) {
@ -1226,10 +1209,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
cancel_delayed_work_sync(&sc->tx_complete_work); ath_cancel_work(sc);
cancel_delayed_work_sync(&sc->hw_pll_work);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
if (sc->sc_flags & SC_OP_INVALID) { if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
@ -2340,9 +2320,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock); spin_lock_bh(&sc->sc_pcu_lock);
drain_txq = ath_drain_all_txq(sc, false); drain_txq = ath_drain_all_txq(sc, false);
spin_unlock_bh(&sc->sc_pcu_lock);
if (!drain_txq) if (!drain_txq)
ath_reset(sc, false); ath_reset(sc, false);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
ieee80211_wake_queues(hw); ieee80211_wake_queues(hw);
@ -2419,6 +2401,59 @@ static int ath9k_get_stats(struct ieee80211_hw *hw,
return 0; return 0;
} }
static u32 fill_chainmask(u32 cap, u32 new)
{
u32 filled = 0;
int i;
for (i = 0; cap && new; i++, cap >>= 1) {
if (!(cap & BIT(0)))
continue;
if (new & BIT(0))
filled |= BIT(i);
new >>= 1;
}
return filled;
}
static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
if (!rx_ant || !tx_ant)
return -EINVAL;
sc->ant_rx = rx_ant;
sc->ant_tx = tx_ant;
if (ah->caps.rx_chainmask == 1)
return 0;
/* AR9100 runs into calibration issues if not all rx chains are enabled */
if (AR_SREV_9100(ah))
ah->rxchainmask = 0x7;
else
ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
ath9k_reload_chainmask_settings(sc);
return 0;
}
static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
{
struct ath_softc *sc = hw->priv;
*tx_ant = sc->ant_tx;
*rx_ant = sc->ant_rx;
return 0;
}
struct ieee80211_ops ath9k_ops = { struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx, .tx = ath9k_tx,
.start = ath9k_start, .start = ath9k_start,
@ -2445,4 +2480,6 @@ struct ieee80211_ops ath9k_ops = {
.tx_frames_pending = ath9k_tx_frames_pending, .tx_frames_pending = ath9k_tx_frames_pending,
.tx_last_beacon = ath9k_tx_last_beacon, .tx_last_beacon = ath9k_tx_last_beacon,
.get_stats = ath9k_get_stats, .get_stats = ath9k_get_stats,
.set_antenna = ath9k_set_antenna,
.get_antenna = ath9k_get_antenna,
}; };

View File

@ -33,6 +33,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */
{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
{ PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9480 */
{ 0 } { 0 }
}; };
@ -332,16 +333,16 @@ static int ath_pci_resume(struct device *device)
if ((val & 0x0000ff00) != 0) if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
ath9k_ps_wakeup(sc);
/* Enable LED */ /* Enable LED */
ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT); AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
/* /*
* Reset key cache to sane defaults (all entries cleared) instead of * Reset key cache to sane defaults (all entries cleared) instead of
* semi-random values after suspend/resume. * semi-random values after suspend/resume.
*/ */
ath9k_ps_wakeup(sc);
ath9k_cmn_init_crypto(sc->sc_ah); ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);

View File

@ -1839,7 +1839,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
* If we're asked to flush receive queue, directly * If we're asked to flush receive queue, directly
* chain it back at the queue without processing it. * chain it back at the queue without processing it.
*/ */
if (flush) if (sc->sc_flags & SC_OP_RXFLUSH)
goto requeue_drop_frag; goto requeue_drop_frag;
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
@ -1950,7 +1950,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
ath_rx_ps(sc, skb); ath_rx_ps(sc, skb);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags); spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
ath_ant_comb_scan(sc, &rs); ath_ant_comb_scan(sc, &rs);
ieee80211_rx(hw, skb); ieee80211_rx(hw, skb);
@ -1967,7 +1967,8 @@ requeue:
} else { } else {
list_move_tail(&bf->list, &sc->rx.rxbuf); list_move_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_buf_link(sc, bf); ath_rx_buf_link(sc, bf);
ath9k_hw_rxena(ah); if (!flush)
ath9k_hw_rxena(ah);
} }
} while (1); } while (1);

View File

@ -796,6 +796,9 @@
#define AR_SREV_VERSION_9340 0x300 #define AR_SREV_VERSION_9340 0x300
#define AR_SREV_VERSION_9580 0x1C0 #define AR_SREV_VERSION_9580 0x1C0
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
#define AR_SREV_VERSION_9480 0x280
#define AR_SREV_REVISION_9480_10 0
#define AR_SREV_REVISION_9480_20 2
#define AR_SREV_5416(_ah) \ #define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@ -896,6 +899,21 @@
(AR_SREV_9285_12_OR_LATER(_ah) && \ (AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
#define AR_SREV_9480(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480))
#define AR_SREV_9480_10(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9480_10))
#define AR_SREV_9480_20(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9480_20))
#define AR_SREV_9480_20_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9480_20))
#define AR_SREV_9580(_ah) \ #define AR_SREV_9580(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
@ -1132,7 +1150,7 @@ enum {
#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
#define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP 0x40d8
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
#define AR_ENT_OTP_MPSD 0x00800000 #define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000
#define AR_CH0_BB_DPLL1 0x16180 #define AR_CH0_BB_DPLL1 0x16180
#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000 #define AR_CH0_BB_DPLL1_REFDIV 0xF8000000
@ -1779,6 +1797,7 @@ enum {
#define AR_TXOP_12_15 0x81fc #define AR_TXOP_12_15 0x81fc
#define AR_NEXT_NDP2_TIMER 0x8180 #define AR_NEXT_NDP2_TIMER 0x8180
#define AR_GEN_TIMER_BANK_1_LEN 8
#define AR_FIRST_NDP_TIMER 7 #define AR_FIRST_NDP_TIMER 7
#define AR_NDP2_PERIOD 0x81a0 #define AR_NDP2_PERIOD 0x81a0
#define AR_NDP2_TIMER_MODE 0x81c0 #define AR_NDP2_TIMER_MODE 0x81c0
@ -1867,9 +1886,10 @@ enum {
#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 #define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000 #define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358 #define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400 #define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
#define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8
#define AR_AES_MUTE_MASK0 0x805c #define AR_AES_MUTE_MASK0 0x805c
@ -1920,4 +1940,38 @@ enum {
#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0 #define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0
#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 #define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6
/* MCI Registers */
#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c
#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0
#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1
#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2
#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3
#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4
#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5
#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6
#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8
#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9
#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10
#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11
#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12
#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \
AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
#endif #endif

View File

@ -56,10 +56,9 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int txok, int sendbar); struct ath_tx_status *ts, int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
struct list_head *head, bool internal); struct list_head *head, bool internal);
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad, struct ath_tx_status *ts, int nframes, int nbad,
int txok, bool update_rc); int txok);
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
int seqno); int seqno);
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
@ -390,11 +389,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
while (bf) { while (bf) {
bf_next = bf->bf_next; bf_next = bf->bf_next;
bf->bf_state.bf_type |= BUF_XRETRY;
if (!bf->bf_stale || bf_next != NULL) if (!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head); list_move_tail(&bf->list, &bf_head);
ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0); 0, 0);
@ -470,7 +467,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
clear_filter = true; clear_filter = true;
txpending = 1; txpending = 1;
} else { } else {
bf->bf_state.bf_type |= BUF_XRETRY;
txfail = 1; txfail = 1;
sendbar = 1; sendbar = 1;
txfail_cnt++; txfail_cnt++;
@ -497,17 +493,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates)); memcpy(tx_info->control.rates, rates, sizeof(rates));
ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true); ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
rc_update = false; rc_update = false;
} else {
ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
} }
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
!txfail, sendbar); !txfail, sendbar);
} else { } else {
/* retry the un-acked ones */ /* retry the un-acked ones */
ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
if (bf->bf_next == NULL && bf_last->bf_stale) { if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf; struct ath_buf *tbf;
@ -523,26 +516,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_update_baw(sc, tid, seqno); ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
bf->bf_state.bf_type |=
BUF_XRETRY;
ath_tx_rc_status(sc, bf, ts, nframes,
nbad, 0, false);
ath_tx_complete_buf(sc, bf, txq, ath_tx_complete_buf(sc, bf, txq,
&bf_head, &bf_head,
ts, 0, 0); ts, 0, 1);
break; break;
} }
ath9k_hw_cleartxdesc(sc->sc_ah,
tbf->bf_desc);
fi->bf = tbf; fi->bf = tbf;
} else {
/*
* Clear descriptor status words for
* software retry
*/
ath9k_hw_cleartxdesc(sc->sc_ah,
bf->bf_desc);
} }
} }
@ -582,7 +562,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_unlock(); rcu_read_unlock();
if (needreset) if (needreset)
ath_reset(sc, false); ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
} }
static bool ath_lookup_legacy(struct ath_buf *bf) static bool ath_lookup_legacy(struct ath_buf *bf)
@ -709,7 +689,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
* Add delimiter when using RTS/CTS with aggregation * Add delimiter when using RTS/CTS with aggregation
* and non enterprise AR9003 card * and non enterprise AR9003 card
*/ */
if (first_subfrm) if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
(sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
ndelim = max(ndelim, FIRST_DESC_NDELIMS); ndelim = max(ndelim, FIRST_DESC_NDELIMS);
/* /*
@ -777,7 +758,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
if (!bf) if (!bf)
continue; continue;
bf->bf_state.bf_type |= BUF_AMPDU; bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
seqno = bf->bf_state.seqno; seqno = bf->bf_state.seqno;
if (!bf_first) if (!bf_first)
bf_first = bf; bf_first = bf;
@ -804,8 +785,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
} }
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) || if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
break; break;
/* do not exceed subframe limit */ /* do not exceed subframe limit */
@ -827,20 +807,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
nframes++; nframes++;
bf->bf_next = NULL; bf->bf_next = NULL;
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
/* link buffers of this frame to the aggregate */ /* link buffers of this frame to the aggregate */
if (!fi->retries) if (!fi->retries)
ath_tx_addto_baw(sc, tid, seqno); ath_tx_addto_baw(sc, tid, seqno);
ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); bf->bf_state.ndelim = ndelim;
__skb_unlink(skb, &tid->buf_q); __skb_unlink(skb, &tid->buf_q);
list_add_tail(&bf->list, bf_q); list_add_tail(&bf->list, bf_q);
if (bf_prev) { if (bf_prev)
bf_prev->bf_next = bf; bf_prev->bf_next = bf;
ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
bf->bf_daddr);
}
bf_prev = bf; bf_prev = bf;
} while (!skb_queue_empty(&tid->buf_q)); } while (!skb_queue_empty(&tid->buf_q));
@ -851,12 +828,245 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
#undef PADBYTES #undef PADBYTES
} }
/*
* rix - rate index
* pktlen - total bytes (delims + data + fcs + pads + pad delims)
* width - 0 for 20 MHz, 1 for 40 MHz
* half_gi - to use 4us v/s 3.6 us for symbol time
*/
static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
int width, int half_gi, bool shortPreamble)
{
u32 nbits, nsymbits, duration, nsymbols;
int streams;
/* find number of symbols: PLCP + data */
streams = HT_RC_2_STREAMS(rix);
nbits = (pktlen << 3) + OFDM_PLCP_BITS;
nsymbits = bits_per_symbol[rix % 8][width] * streams;
nsymbols = (nbits + nsymbits - 1) / nsymbits;
if (!half_gi)
duration = SYMBOL_TIME(nsymbols);
else
duration = SYMBOL_TIME_HALFGI(nsymbols);
/* addup duration for legacy/ht training and signal fields */
duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
return duration;
}
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_info *info, int len)
{
struct ath_hw *ah = sc->sc_ah;
struct sk_buff *skb;
struct ieee80211_tx_info *tx_info;
struct ieee80211_tx_rate *rates;
const struct ieee80211_rate *rate;
struct ieee80211_hdr *hdr;
int i;
u8 rix = 0;
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
rates = tx_info->control.rates;
hdr = (struct ieee80211_hdr *)skb->data;
/* set dur_update_en for l-sig computation except for PS-Poll frames */
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
/*
* We check if Short Preamble is needed for the CTS rate by
* checking the BSS's global flag.
* But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
*/
rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
info->rtscts_rate = rate->hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
info->rtscts_rate |= rate->hw_value_short;
for (i = 0; i < 4; i++) {
bool is_40, is_sgi, is_sp;
int phy;
if (!rates[i].count || (rates[i].idx < 0))
continue;
rix = rates[i].idx;
info->rates[i].Tries = rates[i].count;
if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
info->flags |= ATH9K_TXDESC_RTSENA;
} else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
info->flags |= ATH9K_TXDESC_CTSENA;
}
if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
if (rates[i].flags & IEEE80211_TX_RC_MCS) {
/* MCS rates */
info->rates[i].Rate = rix | 0x80;
info->rates[i].ChSel = ath_txchainmask_reduction(sc,
ah->txchainmask, info->rates[i].Rate);
info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
continue;
}
/* legacy rates */
if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
phy = WLAN_RC_PHY_CCK;
else
phy = WLAN_RC_PHY_OFDM;
rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
info->rates[i].Rate = rate->hw_value;
if (rate->hw_value_short) {
if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
info->rates[i].Rate |= rate->hw_value_short;
} else {
is_sp = false;
}
if (bf->bf_state.bfs_paprd)
info->rates[i].ChSel = ah->txchainmask;
else
info->rates[i].ChSel = ath_txchainmask_reduction(sc,
ah->txchainmask, info->rates[i].Rate);
info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
phy, rate->bitrate * 100, len, rix, is_sp);
}
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
info->flags &= ~ATH9K_TXDESC_RTSENA;
/* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
if (info->flags & ATH9K_TXDESC_RTSENA)
info->flags &= ~ATH9K_TXDESC_CTSENA;
}
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
enum ath9k_pkt_type htype;
__le16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
if (ieee80211_is_beacon(fc))
htype = ATH9K_PKT_TYPE_BEACON;
else if (ieee80211_is_probe_resp(fc))
htype = ATH9K_PKT_TYPE_PROBE_RESP;
else if (ieee80211_is_atim(fc))
htype = ATH9K_PKT_TYPE_ATIM;
else if (ieee80211_is_pspoll(fc))
htype = ATH9K_PKT_TYPE_PSPOLL;
else
htype = ATH9K_PKT_TYPE_NORMAL;
return htype;
}
static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, int len)
{
struct ath_hw *ah = sc->sc_ah;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
struct ath_buf *bf_first = bf;
struct ath_tx_info info;
bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
memset(&info, 0, sizeof(info));
info.is_first = true;
info.is_last = true;
info.txpower = MAX_RATE_POWER;
info.qcu = txq->axq_qnum;
info.flags = ATH9K_TXDESC_INTREQ;
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
info.flags |= ATH9K_TXDESC_NOACK;
if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
info.flags |= ATH9K_TXDESC_LDPC;
ath_buf_set_rate(sc, bf, &info, len);
if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
info.flags |= ATH9K_TXDESC_CLRDMASK;
if (bf->bf_state.bfs_paprd)
info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
while (bf) {
struct sk_buff *skb = bf->bf_mpdu;
struct ath_frame_info *fi = get_frame_info(skb);
struct ieee80211_hdr *hdr;
int padpos, padsize;
info.type = get_hw_packet_type(skb);
if (bf->bf_next)
info.link = bf->bf_next->bf_daddr;
else
info.link = 0;
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
hdr = (struct ieee80211_hdr *)skb->data;
padpos = ath9k_cmn_padpos(hdr->frame_control);
padsize = padpos & 3;
info.buf_addr[0] = bf->bf_buf_addr;
info.buf_len[0] = padpos + padsize;
info.buf_addr[1] = info.buf_addr[0] + padpos;
info.buf_len[1] = skb->len - padpos;
} else {
info.buf_addr[0] = bf->bf_buf_addr;
info.buf_len[0] = skb->len;
}
info.pkt_len = fi->framelen;
info.keyix = fi->keyix;
info.keytype = fi->keytype;
if (aggr) {
if (bf == bf_first)
info.aggr = AGGR_BUF_FIRST;
else if (!bf->bf_next)
info.aggr = AGGR_BUF_LAST;
else
info.aggr = AGGR_BUF_MIDDLE;
info.ndelim = bf->bf_state.ndelim;
info.aggr_len = len;
}
ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
bf = bf->bf_next;
}
}
static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid) struct ath_atx_tid *tid)
{ {
struct ath_buf *bf; struct ath_buf *bf;
enum ATH_AGGR_STATUS status; enum ATH_AGGR_STATUS status;
struct ath_frame_info *fi; struct ieee80211_tx_info *tx_info;
struct list_head bf_q; struct list_head bf_q;
int aggr_len; int aggr_len;
@ -877,34 +1087,25 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf = list_first_entry(&bf_q, struct ath_buf, list); bf = list_first_entry(&bf_q, struct ath_buf, list);
bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
if (tid->ac->clear_ps_filter) { if (tid->ac->clear_ps_filter) {
tid->ac->clear_ps_filter = false; tid->ac->clear_ps_filter = false;
ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
} else {
tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
} }
/* if only one frame, send as non-aggregate */ /* if only one frame, send as non-aggregate */
if (bf == bf->bf_lastbf) { if (bf == bf->bf_lastbf) {
fi = get_frame_info(bf->bf_mpdu); aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
bf->bf_state.bf_type = BUF_AMPDU;
bf->bf_state.bf_type &= ~BUF_AGGR; } else {
ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); TX_STAT_INC(txq->axq_qnum, a_aggr);
ath_buf_set_rate(sc, bf, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_q, false);
continue;
} }
/* setup first desc of aggregate */ ath_tx_fill_desc(sc, bf, txq, aggr_len);
bf->bf_state.bf_type |= BUF_AGGR;
ath_buf_set_rate(sc, bf, aggr_len);
ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
/* anchor last desc of aggregate */
ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
ath_tx_txqaddbuf(sc, txq, &bf_q, false); ath_tx_txqaddbuf(sc, txq, &bf_q, false);
TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED); status != ATH_AGGR_BAW_CLOSED);
} }
@ -1332,7 +1533,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
struct ath_atx_ac *ac, *ac_tmp, *last_ac; struct ath_atx_ac *ac, *ac_tmp, *last_ac;
struct ath_atx_tid *tid, *last_tid; struct ath_atx_tid *tid, *last_tid;
if (list_empty(&txq->axq_acq) || if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return; return;
@ -1482,7 +1683,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
if (!bf) if (!bf)
return; return;
bf->bf_state.bf_type |= BUF_AMPDU; bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head); list_add(&bf->list, &bf_head);
@ -1492,7 +1693,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
/* Queue to h/w without aggregation */ /* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false); ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
} }
@ -1512,41 +1713,18 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
list_add_tail(&bf->list, &bf_head); list_add_tail(&bf->list, &bf_head);
bf->bf_state.bf_type &= ~BUF_AMPDU; bf->bf_state.bf_type = 0;
/* update starting sequence number for subsequent ADDBA request */ /* update starting sequence number for subsequent ADDBA request */
if (tid) if (tid)
INCR(tid->seq_start, IEEE80211_SEQ_MAX); INCR(tid->seq_start, IEEE80211_SEQ_MAX);
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_fill_desc(sc, bf, txq, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_head, false); ath_tx_txqaddbuf(sc, txq, &bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued); TX_STAT_INC(txq->axq_qnum, queued);
} }
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
enum ath9k_pkt_type htype;
__le16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
if (ieee80211_is_beacon(fc))
htype = ATH9K_PKT_TYPE_BEACON;
else if (ieee80211_is_probe_resp(fc))
htype = ATH9K_PKT_TYPE_PROBE_RESP;
else if (ieee80211_is_atim(fc))
htype = ATH9K_PKT_TYPE_ATIM;
else if (ieee80211_is_pspoll(fc))
htype = ATH9K_PKT_TYPE_PSPOLL;
else
htype = ATH9K_PKT_TYPE_NORMAL;
return htype;
}
static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
int framelen) int framelen)
{ {
@ -1574,51 +1752,6 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->framelen = framelen; fi->framelen = framelen;
} }
static int setup_tx_flags(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
int flags = 0;
flags |= ATH9K_TXDESC_INTREQ;
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
flags |= ATH9K_TXDESC_NOACK;
if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
flags |= ATH9K_TXDESC_LDPC;
return flags;
}
/*
* rix - rate index
* pktlen - total bytes (delims + data + fcs + pads + pad delims)
* width - 0 for 20 MHz, 1 for 40 MHz
* half_gi - to use 4us v/s 3.6 us for symbol time
*/
static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
int width, int half_gi, bool shortPreamble)
{
u32 nbits, nsymbits, duration, nsymbols;
int streams;
/* find number of symbols: PLCP + data */
streams = HT_RC_2_STREAMS(rix);
nbits = (pktlen << 3) + OFDM_PLCP_BITS;
nsymbits = bits_per_symbol[rix % 8][width] * streams;
nsymbols = (nbits + nsymbits - 1) / nsymbits;
if (!half_gi)
duration = SYMBOL_TIME(nsymbols);
else
duration = SYMBOL_TIME_HALFGI(nsymbols);
/* addup duration for legacy/ht training and signal fields */
duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
return duration;
}
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
@ -1631,118 +1764,6 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
return chainmask; return chainmask;
} }
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_11n_rate_series series[4];
struct sk_buff *skb;
struct ieee80211_tx_info *tx_info;
struct ieee80211_tx_rate *rates;
const struct ieee80211_rate *rate;
struct ieee80211_hdr *hdr;
int i, flags = 0;
u8 rix = 0, ctsrate = 0;
bool is_pspoll;
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
rates = tx_info->control.rates;
hdr = (struct ieee80211_hdr *)skb->data;
is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
/*
* We check if Short Preamble is needed for the CTS rate by
* checking the BSS's global flag.
* But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
*/
rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
ctsrate = rate->hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
ctsrate |= rate->hw_value_short;
for (i = 0; i < 4; i++) {
bool is_40, is_sgi, is_sp;
int phy;
if (!rates[i].count || (rates[i].idx < 0))
continue;
rix = rates[i].idx;
series[i].Tries = rates[i].count;
if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
flags |= ATH9K_TXDESC_RTSENA;
} else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
flags |= ATH9K_TXDESC_CTSENA;
}
if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
series[i].RateFlags |= ATH9K_RATESERIES_2040;
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
if (rates[i].flags & IEEE80211_TX_RC_MCS) {
/* MCS rates */
series[i].Rate = rix | 0x80;
series[i].ChSel = ath_txchainmask_reduction(sc,
common->tx_chainmask, series[i].Rate);
series[i].PktDuration = ath_pkt_duration(sc, rix, len,
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
series[i].RateFlags |= ATH9K_RATESERIES_STBC;
continue;
}
/* legacy rates */
if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
phy = WLAN_RC_PHY_CCK;
else
phy = WLAN_RC_PHY_OFDM;
rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
series[i].Rate = rate->hw_value;
if (rate->hw_value_short) {
if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
series[i].Rate |= rate->hw_value_short;
} else {
is_sp = false;
}
if (bf->bf_state.bfs_paprd)
series[i].ChSel = common->tx_chainmask;
else
series[i].ChSel = ath_txchainmask_reduction(sc,
common->tx_chainmask, series[i].Rate);
series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
phy, rate->bitrate * 100, len, rix, is_sp);
}
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
flags &= ~ATH9K_TXDESC_RTSENA;
/* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
if (flags & ATH9K_TXDESC_RTSENA)
flags &= ~ATH9K_TXDESC_CTSENA;
/* set dur_update_en for l-sig computation except for PS-Poll frames */
ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
bf->bf_lastbf->bf_desc,
!is_pspoll, ctsrate,
0, series, 4, flags);
}
/* /*
* Assign a descriptor (and sequence number if necessary, * Assign a descriptor (and sequence number if necessary,
* and map buffer for DMA. Frees skb on error * and map buffer for DMA. Frees skb on error
@ -1752,13 +1773,10 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_atx_tid *tid, struct ath_atx_tid *tid,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_frame_info *fi = get_frame_info(skb); struct ath_frame_info *fi = get_frame_info(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_buf *bf; struct ath_buf *bf;
struct ath_desc *ds;
int frm_type;
u16 seqno; u16 seqno;
bf = ath_tx_get_buffer(sc); bf = ath_tx_get_buffer(sc);
@ -1776,7 +1794,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
bf->bf_state.seqno = seqno; bf->bf_state.seqno = seqno;
} }
bf->bf_flags = setup_tx_flags(skb);
bf->bf_mpdu = skb; bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
@ -1790,22 +1807,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
goto error; goto error;
} }
frm_type = get_hw_packet_type(skb);
ds = bf->bf_desc;
ath9k_hw_set_desc_link(ah, ds, 0);
ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
fi->keyix, fi->keytype, bf->bf_flags);
ath9k_hw_filltxdesc(ah, ds,
skb->len, /* segment length */
true, /* first segment */
true, /* last segment */
ds, /* first descriptor */
bf->bf_buf_addr,
txq->axq_qnum);
fi->bf = bf; fi->bf = bf;
return bf; return bf;
@ -1848,16 +1849,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
bf->bf_state.bfs_paprd = txctl->paprd; bf->bf_state.bfs_paprd = txctl->paprd;
if (bf->bf_state.bfs_paprd)
ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
bf->bf_state.bfs_paprd);
if (txctl->paprd) if (txctl->paprd)
bf->bf_state.bfs_paprd_timestamp = jiffies; bf->bf_state.bfs_paprd_timestamp = jiffies;
if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
ath_tx_send_normal(sc, txctl->txq, tid, skb); ath_tx_send_normal(sc, txctl->txq, tid, skb);
} }
@ -1898,15 +1892,17 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
} }
/* Add the padding after the header if this is not already done */ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
padpos = ath9k_cmn_padpos(hdr->frame_control); /* Add the padding after the header if this is not already done */
padsize = padpos & 3; padpos = ath9k_cmn_padpos(hdr->frame_control);
if (padsize && skb->len > padpos) { padsize = padpos & 3;
if (skb_headroom(skb) < padsize) if (padsize && skb->len > padpos) {
return -ENOMEM; if (skb_headroom(skb) < padsize)
return -ENOMEM;
skb_push(skb, padsize); skb_push(skb, padsize);
memmove(skb->data, skb->data + padsize, padpos); memmove(skb->data, skb->data + padsize, padpos);
}
} }
if ((vif && vif->type != NL80211_IFTYPE_AP && if ((vif && vif->type != NL80211_IFTYPE_AP &&
@ -1952,20 +1948,21 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
if (tx_flags & ATH_TX_BAR) if (tx_flags & ATH_TX_BAR)
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */ /* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK; tx_info->flags |= IEEE80211_TX_STAT_ACK;
}
padpos = ath9k_cmn_padpos(hdr->frame_control); if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
padsize = padpos & 3; padpos = ath9k_cmn_padpos(hdr->frame_control);
if (padsize && skb->len>padpos+padsize) { padsize = padpos & 3;
/* if (padsize && skb->len>padpos+padsize) {
* Remove MAC header padding before giving the frame back to /*
* mac80211. * Remove MAC header padding before giving the frame back to
*/ * mac80211.
memmove(skb->data + padsize, skb->data, padpos); */
skb_pull(skb, padsize); memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
}
} }
if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
@ -1999,18 +1996,18 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int txok, int sendbar) struct ath_tx_status *ts, int txok, int sendbar)
{ {
struct sk_buff *skb = bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
unsigned long flags; unsigned long flags;
int tx_flags = 0; int tx_flags = 0;
if (sendbar) if (sendbar)
tx_flags = ATH_TX_BAR; tx_flags = ATH_TX_BAR;
if (!txok) { if (!txok)
tx_flags |= ATH_TX_ERROR; tx_flags |= ATH_TX_ERROR;
if (bf_isxretried(bf)) if (ts->ts_status & ATH9K_TXERR_FILT)
tx_flags |= ATH_TX_XRETRY; tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
}
dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = 0; bf->bf_buf_addr = 0;
@ -2023,7 +2020,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
else else
complete(&sc->paprd_complete); complete(&sc->paprd_complete);
} else { } else {
ath_debug_stat_tx(sc, bf, ts, txq); ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
ath_tx_complete(sc, skb, tx_flags, txq); ath_tx_complete(sc, skb, tx_flags, txq);
} }
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
@ -2041,7 +2038,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad, struct ath_tx_status *ts, int nframes, int nbad,
int txok, bool update_rc) int txok)
{ {
struct sk_buff *skb = bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@ -2056,9 +2053,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
tx_rateindex = ts->ts_rateindex; tx_rateindex = ts->ts_rateindex;
WARN_ON(tx_rateindex >= hw->max_rates); WARN_ON(tx_rateindex >= hw->max_rates);
if (ts->ts_status & ATH9K_TXERR_FILT) if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU; tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
BUG_ON(nbad > nframes); BUG_ON(nbad > nframes);
@ -2068,7 +2063,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
} }
if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
/* /*
* If an underrun error is seen assume it as an excessive * If an underrun error is seen assume it as an excessive
* retry only if max frame trigger level has been reached * retry only if max frame trigger level has been reached
@ -2081,9 +2076,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
* successfully by eventually preferring slower rates. * successfully by eventually preferring slower rates.
* This itself should also alleviate congestion on the bus. * This itself should also alleviate congestion on the bus.
*/ */
if (ieee80211_is_data(hdr->frame_control) && if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) &&
ATH9K_TX_DELIM_UNDERRUN)) && ieee80211_is_data(hdr->frame_control) &&
ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level) ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
tx_info->status.rates[tx_rateindex].count = tx_info->status.rates[tx_rateindex].count =
hw->max_rate_tries; hw->max_rate_tries;
@ -2114,13 +2109,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
if (!bf_isampdu(bf)) { if (!bf_isampdu(bf)) {
/* ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
* This frame is sent out as a single frame.
* Use hardware retry status for this frame.
*/
if (ts->ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0); ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
} else } else
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
@ -2147,6 +2136,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
for (;;) { for (;;) {
if (work_pending(&sc->hw_reset_work))
break;
if (list_empty(&txq->axq_q)) { if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL; txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR) if (sc->sc_flags & SC_OP_TXAGGR)
@ -2234,9 +2226,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) { if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n"); "tx hung, resetting the chip\n");
spin_lock_bh(&sc->sc_pcu_lock); ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath_reset(sc, true);
spin_unlock_bh(&sc->sc_pcu_lock);
} }
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@ -2269,6 +2259,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
int status; int status;
for (;;) { for (;;) {
if (work_pending(&sc->hw_reset_work))
break;
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS) if (status == -EINPROGRESS)
break; break;

View File

@ -110,6 +110,8 @@
#define B43_MMIO_TSF_CFP_START_LOW 0x604 #define B43_MMIO_TSF_CFP_START_LOW 0x604
#define B43_MMIO_TSF_CFP_START_HIGH 0x606 #define B43_MMIO_TSF_CFP_START_HIGH 0x606
#define B43_MMIO_TSF_CFP_PRETBTT 0x612 #define B43_MMIO_TSF_CFP_PRETBTT 0x612
#define B43_MMIO_TSF_CLK_FRAC_LOW 0x62E
#define B43_MMIO_TSF_CLK_FRAC_HIGH 0x630
#define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */ #define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
#define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
Bus abstraction layer Bus abstraction layer
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or

View File

@ -7,6 +7,7 @@
Copyright (c) 2005-2009 Michael Buesch <m@bues.ch> Copyright (c) 2005-2009 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
SDIO support SDIO support
Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es> Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
@ -64,6 +65,7 @@ MODULE_AUTHOR("Martin Langer");
MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch"); MODULE_AUTHOR("Michael Buesch");
MODULE_AUTHOR("Gábor Stefanik"); MODULE_AUTHOR("Gábor Stefanik");
MODULE_AUTHOR("Rafał Miłecki");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE("b43/ucode11.fw"); MODULE_FIRMWARE("b43/ucode11.fw");
@ -2953,6 +2955,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT: case B43_PHYTYPE_HT:
case B43_PHYTYPE_LCN:
b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
IEEE 802.11n HT-PHY support IEEE 802.11n HT-PHY support
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
IEEE 802.11n LCN-PHY support IEEE 802.11n LCN-PHY support
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
@ -31,24 +33,78 @@
* Radio 2064. * Radio 2064.
**************************************************/ **************************************************/
/* wlc_lcnphy_radio_2064_channel_tune_4313 */
static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
{
u16 save[2];
b43_radio_set(dev, 0x09d, 0x4);
b43_radio_write(dev, 0x09e, 0xf);
/* Channel specific values in theory, in practice always the same */
b43_radio_write(dev, 0x02a, 0xb);
b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
b43_radio_maskset(dev, 0x091, ~0x3, 0);
b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
b43_radio_write(dev, 0x06c, 0x80);
save[0] = b43_radio_read(dev, 0x044);
save[1] = b43_radio_read(dev, 0x12b);
b43_radio_set(dev, 0x044, 0x7);
b43_radio_set(dev, 0x12b, 0xe);
/* TODO */
b43_radio_write(dev, 0x040, 0xfb);
b43_radio_write(dev, 0x041, 0x9a);
b43_radio_write(dev, 0x042, 0xa3);
b43_radio_write(dev, 0x043, 0x0c);
/* TODO */
b43_radio_set(dev, 0x044, 0x0c);
udelay(1);
b43_radio_write(dev, 0x044, save[0]);
b43_radio_write(dev, 0x12b, save[1]);
if (dev->phy.rev == 1) {
/* brcmsmac uses outdated 0x3 for 0x038 */
b43_radio_write(dev, 0x038, 0x0);
b43_radio_write(dev, 0x091, 0x7);
}
}
/* wlc_radio_2064_init */
static void b43_radio_2064_init(struct b43_wldev *dev) static void b43_radio_2064_init(struct b43_wldev *dev)
{ {
b43_radio_write(dev, 0x09c, 0x0020); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_radio_write(dev, 0x105, 0x0008); b43_radio_write(dev, 0x09c, 0x0020);
b43_radio_write(dev, 0x105, 0x0008);
} else {
/* TODO */
}
b43_radio_write(dev, 0x032, 0x0062); b43_radio_write(dev, 0x032, 0x0062);
b43_radio_write(dev, 0x033, 0x0019); b43_radio_write(dev, 0x033, 0x0019);
b43_radio_write(dev, 0x090, 0x0010); b43_radio_write(dev, 0x090, 0x0010);
b43_radio_write(dev, 0x010, 0x0000); b43_radio_write(dev, 0x010, 0x0000);
b43_radio_write(dev, 0x060, 0x007f); if (dev->phy.rev == 1) {
b43_radio_write(dev, 0x061, 0x0072); b43_radio_write(dev, 0x060, 0x007f);
b43_radio_write(dev, 0x062, 0x007f); b43_radio_write(dev, 0x061, 0x0072);
b43_radio_write(dev, 0x062, 0x007f);
}
b43_radio_write(dev, 0x01d, 0x0002); b43_radio_write(dev, 0x01d, 0x0002);
b43_radio_write(dev, 0x01e, 0x0006); b43_radio_write(dev, 0x01e, 0x0006);
b43_phy_write(dev, 0x4ea, 0x4688); b43_phy_write(dev, 0x4ea, 0x4688);
b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2); b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
b43_phy_mask(dev, 0x4eb, ~0x01c0); b43_phy_mask(dev, 0x4eb, ~0x01c0);
b43_phy_maskset(dev, 0x4eb, 0xff00, 0x19); b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0); b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
@ -80,6 +136,7 @@ static void b43_radio_2064_init(struct b43_wldev *dev)
* Various PHY ops * Various PHY ops
**************************************************/ **************************************************/
/* wlc_lcnphy_toggle_afe_pwdn */
static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev) static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
{ {
u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2); u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
@ -95,22 +152,17 @@ static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1); b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
} }
static void b43_phy_lcn_clean_0x18_table(struct b43_wldev *dev) /* wlc_lcnphy_clear_tx_power_offsets */
static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
{ {
u8 i; u8 i;
for (i = 0; i < 0x80; i++) if (1) { /* FIXME */
b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000); b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
} for (i = 0; i < 30; i++) {
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
{ }
u8 i;
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
for (i = 0; i < 30; i++) {
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
} }
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80); b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
@ -120,6 +172,134 @@ static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev)
} }
} }
/* wlc_lcnphy_rev0_baseband_init */
static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
{
b43_radio_write(dev, 0x11c, 0);
b43_phy_write(dev, 0x43b, 0);
b43_phy_write(dev, 0x43c, 0);
b43_phy_write(dev, 0x44c, 0);
b43_phy_write(dev, 0x4e6, 0);
b43_phy_write(dev, 0x4f9, 0);
b43_phy_write(dev, 0x4b0, 0);
b43_phy_write(dev, 0x938, 0);
b43_phy_write(dev, 0x4b0, 0);
b43_phy_write(dev, 0x44e, 0);
b43_phy_set(dev, 0x567, 0x03);
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
; /* TODO */
b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
b43_phy_write(dev, 0x910, 0x1);
}
b43_phy_write(dev, 0x910, 0x1);
b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
}
/* wlc_lcnphy_bu_tweaks */
static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
{
b43_phy_set(dev, 0x805, 0x1);
b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
b43_phy_write(dev, 0x414, 0x1e10);
b43_phy_write(dev, 0x415, 0x0640);
b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
if (dev->dev->bus_sprom->board_rev >= 0x1204)
b43_radio_set(dev, 0x09b, 0xf0);
b43_phy_write(dev, 0x7d6, 0x0902);
/* TODO: more ops */
if (dev->phy.rev == 1) {
/* TODO: more ops */
b43_phy_lcn_clear_tx_power_offsets(dev);
}
}
/* wlc_lcnphy_vbat_temp_sense_setup */
static void b43_phy_lcn_sense_setup(struct b43_wldev *dev)
{
u8 i;
u16 save_radio_regs[6][2] = {
{ 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
{ 0x025, 0 }, { 0x112, 0 },
};
u16 save_phy_regs[14][2] = {
{ 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
{ 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
{ 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
{ 0x40d, 0 }, { 0x4a2, 0 },
};
u16 save_radio_4a4;
for (i = 0; i < 6; i++)
save_radio_regs[i][1] = b43_radio_read(dev,
save_radio_regs[i][0]);
for (i = 0; i < 14; i++)
save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
save_radio_4a4 = b43_radio_read(dev, 0x4a4);
/* TODO: config sth */
for (i = 0; i < 6; i++)
b43_radio_write(dev, save_radio_regs[i][0],
save_radio_regs[i][1]);
for (i = 0; i < 14; i++)
b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
b43_radio_write(dev, 0x4a4, save_radio_4a4);
}
/**************************************************
* Channel switching ops.
**************************************************/
static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type)
{
/* TODO: PLL and PHY ops */
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
b43_phy_set(dev, 0x44a, 0x44);
b43_phy_write(dev, 0x44a, 0x80);
b43_radio_2064_channel_setup(dev);
mdelay(1);
b43_phy_lcn_afe_set_unset(dev);
/* TODO */
return 0;
}
/************************************************** /**************************************************
* Basic PHY ops. * Basic PHY ops.
**************************************************/ **************************************************/
@ -153,6 +333,7 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
memset(phy_lcn, 0, sizeof(*phy_lcn)); memset(phy_lcn, 0, sizeof(*phy_lcn));
} }
/* wlc_phy_init_lcnphy */
static int b43_phy_lcn_op_init(struct b43_wldev *dev) static int b43_phy_lcn_op_init(struct b43_wldev *dev)
{ {
b43_phy_set(dev, 0x44a, 0x80); b43_phy_set(dev, 0x44a, 0x80);
@ -167,18 +348,17 @@ static int b43_phy_lcn_op_init(struct b43_wldev *dev)
b43_phy_maskset(dev, 0x663, 0xFF00, 0x64); b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
b43_phy_lcn_tables_init(dev); b43_phy_lcn_tables_init(dev);
/* TODO: various tables ops here */
b43_phy_lcn_clean_0x18_table(dev);
/* TODO: some ops here */ b43_phy_lcn_rev0_baseband_init(dev);
b43_phy_lcn_bu_tweaks(dev);
b43_phy_lcn_clear_0x07_table(dev);
if (dev->phy.radio_ver == 0x2064) if (dev->phy.radio_ver == 0x2064)
b43_radio_2064_init(dev); b43_radio_2064_init(dev);
else else
B43_WARN_ON(1); B43_WARN_ON(1);
b43_phy_lcn_sense_setup(dev);
return 0; return 0;
} }
@ -215,6 +395,22 @@ static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
} }
} }
static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
return -EINVAL;
} else {
return -EINVAL;
}
return b43_phy_lcn_set_channel(dev, channel, channel_type);
}
static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
{ {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@ -232,6 +428,46 @@ static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
{ {
} }
/**************************************************
* R/W ops.
**************************************************/
static u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg)
{
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
return b43_read16(dev, B43_MMIO_PHY_DATA);
}
static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value)
{
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA, value);
}
static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
u16 set)
{
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA,
(b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
}
static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
{
/* LCN-PHY needs 0x200 for read access */
reg |= 0x200;
b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
u16 value)
{
b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
}
/************************************************** /**************************************************
* PHY ops struct. * PHY ops struct.
**************************************************/ **************************************************/
@ -241,18 +477,14 @@ const struct b43_phy_operations b43_phyops_lcn = {
.free = b43_phy_lcn_op_free, .free = b43_phy_lcn_op_free,
.prepare_structs = b43_phy_lcn_op_prepare_structs, .prepare_structs = b43_phy_lcn_op_prepare_structs,
.init = b43_phy_lcn_op_init, .init = b43_phy_lcn_op_init,
/*
.phy_read = b43_phy_lcn_op_read, .phy_read = b43_phy_lcn_op_read,
.phy_write = b43_phy_lcn_op_write, .phy_write = b43_phy_lcn_op_write,
.phy_maskset = b43_phy_lcn_op_maskset, .phy_maskset = b43_phy_lcn_op_maskset,
.radio_read = b43_phy_lcn_op_radio_read, .radio_read = b43_phy_lcn_op_radio_read,
.radio_write = b43_phy_lcn_op_radio_write, .radio_write = b43_phy_lcn_op_radio_write,
*/
.software_rfkill = b43_phy_lcn_op_software_rfkill, .software_rfkill = b43_phy_lcn_op_software_rfkill,
.switch_analog = b43_phy_lcn_op_switch_analog, .switch_analog = b43_phy_lcn_op_switch_analog,
/*
.switch_channel = b43_phy_lcn_op_switch_channel, .switch_channel = b43_phy_lcn_op_switch_channel,
*/
.get_default_chan = b43_phy_lcn_op_get_default_chan, .get_default_chan = b43_phy_lcn_op_get_default_chan,
.recalc_txpower = b43_phy_lcn_op_recalc_txpower, .recalc_txpower = b43_phy_lcn_op_recalc_txpower,
.adjust_txpower = b43_phy_lcn_op_adjust_txpower, .adjust_txpower = b43_phy_lcn_op_adjust_txpower,

View File

@ -4,6 +4,7 @@
IEEE 802.11n PHY support IEEE 802.11n PHY support
Copyright (c) 2008 Michael Buesch <m@bues.ch> Copyright (c) 2008 Michael Buesch <m@bues.ch>
Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -77,6 +78,7 @@ enum b43_nphy_rssi_type {
B43_NPHY_RSSI_TBD, B43_NPHY_RSSI_TBD,
}; };
/* TODO: reorder functions */
static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
bool enable); bool enable);
static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
@ -87,6 +89,14 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
u16 value, u8 core, bool off); u16 value, u8 core, bool off);
static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
u16 value, u8 core); u16 value, u8 core);
static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev);
static inline bool b43_nphy_ipa(struct b43_wldev *dev)
{
enum ieee80211_band band = b43_current_band(dev->wl);
return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
(dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
}
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO {//TODO
@ -248,15 +258,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
{ {
struct b43_phy_n *nphy = dev->phy.n; struct b43_phy_n *nphy = dev->phy.n;
u8 i; u8 i;
u16 tmp; u16 bmask, val, tmp;
enum ieee80211_band band = b43_current_band(dev->wl);
if (nphy->hang_avoid) if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 1); b43_nphy_stay_in_carrier_search(dev, 1);
nphy->txpwrctrl = enable; nphy->txpwrctrl = enable;
if (!enable) { if (!enable) {
if (dev->phy.rev >= 3) if (dev->phy.rev >= 3 &&
; /* TODO */ (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
(B43_NPHY_TXPCTL_CMD_COEFF |
B43_NPHY_TXPCTL_CMD_HWPCTLEN |
B43_NPHY_TXPCTL_CMD_PCTLEN))) {
/* We disable enabled TX pwr ctl, save it's state */
nphy->tx_pwr_idx[0] = b43_phy_read(dev,
B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
nphy->tx_pwr_idx[1] = b43_phy_read(dev,
B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
}
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
for (i = 0; i < 84; i++) for (i = 0; i < 84; i++)
@ -285,10 +305,67 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
~B43_NPHY_BPHY_CTL3_SCALE, 0x5A); ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
if (dev->phy.rev < 2 && 0) if (dev->phy.rev < 2 && dev->phy.is_40mhz)
; /* TODO */ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
} else { } else {
b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n"); b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
nphy->adj_pwr_tbl);
b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
nphy->adj_pwr_tbl);
bmask = B43_NPHY_TXPCTL_CMD_COEFF |
B43_NPHY_TXPCTL_CMD_HWPCTLEN;
/* wl does useless check for "enable" param here */
val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
if (dev->phy.rev >= 3) {
bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
if (val)
val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
}
b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
if (band == IEEE80211_BAND_5GHZ) {
b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
if (dev->phy.rev > 1)
b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
~B43_NPHY_TXPCTL_INIT_PIDXI1,
0x64);
}
if (dev->phy.rev >= 3) {
if (nphy->tx_pwr_idx[0] != 128 &&
nphy->tx_pwr_idx[1] != 128) {
/* Recover TX pwr ctl state */
b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
~B43_NPHY_TXPCTL_CMD_INIT,
nphy->tx_pwr_idx[0]);
if (dev->phy.rev > 1)
b43_phy_maskset(dev,
B43_NPHY_TXPCTL_INIT,
~0xff, nphy->tx_pwr_idx[1]);
}
}
if (dev->phy.rev >= 3) {
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
} else {
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
}
if (dev->phy.rev == 2)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
else if (dev->phy.rev < 2)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
if (dev->phy.rev < 2 && dev->phy.is_40mhz)
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
if (b43_nphy_ipa(dev)) {
b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
}
} }
if (nphy->hang_avoid) if (nphy->hang_avoid)
@ -369,22 +446,23 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
else else
b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain); b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i); b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
if (i == 0) if (i == 0)
tmp = (tmp & 0x00FF) | (bbmult << 8); tmp = (tmp & 0x00FF) | (bbmult << 8);
else else
tmp = (tmp & 0xFF00) | bbmult; tmp = (tmp & 0xFF00) | bbmult;
b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); if (b43_nphy_ipa(dev)) {
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp); u32 tmp32;
u16 reg = (i == 0) ?
if (0) B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
; /* TODO */ tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i]));
b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
b43_phy_set(dev, reg, 0x4);
}
} }
b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
@ -393,6 +471,57 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, 0); b43_nphy_stay_in_carrier_search(dev, 0);
} }
static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
const u32 *table = NULL;
#if 0
TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
u32 rfpwr_offset;
u8 pga_gain;
int i;
#endif
if (phy->rev >= 3) {
if (b43_nphy_ipa(dev)) {
table = b43_nphy_get_ipa_gain_table(dev);
} else {
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
if (phy->rev == 3)
table = b43_ntab_tx_gain_rev3_5ghz;
if (phy->rev == 4)
table = b43_ntab_tx_gain_rev4_5ghz;
else
table = b43_ntab_tx_gain_rev5plus_5ghz;
} else {
table = b43_ntab_tx_gain_rev3plus_2ghz;
}
}
} else {
table = b43_ntab_tx_gain_rev0_1_2;
}
b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
if (phy->rev >= 3) {
#if 0
nphy->gmval = (table[0] >> 16) & 0x7000;
for (i = 0; i < 128; i++) {
pga_gain = (table[i] >> 24) & 0xF;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
else
rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
rfpwr_offset);
b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
rfpwr_offset);
}
#endif
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
static void b43_radio_2055_setup(struct b43_wldev *dev, static void b43_radio_2055_setup(struct b43_wldev *dev,
@ -581,14 +710,10 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */ /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
{ {
struct b43_phy_n *nphy = dev->phy.n;
u16 tmp; u16 tmp;
enum ieee80211_band band = b43_current_band(dev->wl);
bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
(nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
if (dev->phy.rev >= 3) { if (dev->phy.rev >= 3) {
if (ipa) { if (b43_nphy_ipa(dev)) {
tmp = 4; tmp = 4;
b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
(((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
@ -899,11 +1024,7 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
{ {
u16 array[4]; u16 array[4];
int i; b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
for (i = 0; i < 4; i++)
array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
@ -1366,8 +1487,118 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
} }
} }
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
static void b43_nphy_workarounds(struct b43_wldev *dev) {
struct b43_phy_n *nphy = dev->phy.n;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
/* TX to RX */
u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 };
/* RX to TX */
u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
0x1F };
u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
u16 tmp16;
u32 tmp32;
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
tmp32 &= 0xffffff;
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
b43_phy_write(dev, 0x2AE, 0x000C);
/* TX to RX */
b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9);
/* RX to TX */
if (b43_nphy_ipa(dev))
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa,
rx2tx_delays_ipa, 9);
if (nphy->hw_phyrxchain != 3 &&
nphy->hw_phyrxchain != nphy->hw_phytxchain) {
if (b43_nphy_ipa(dev)) {
rx2tx_delays[5] = 59;
rx2tx_delays[6] = 1;
rx2tx_events[7] = 0x1F;
}
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9);
}
tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
0x2 : 0x9C40;
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
b43_nphy_gain_ctrl_workarounds(dev);
b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
/* TODO */
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
(sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
tmp32 = 0x00088888;
else
tmp32 = 0x88888888;
b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
if (dev->phy.rev == 4 &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
0x70);
b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
0x70);
}
b43_phy_write(dev, 0x224, 0x039C);
b43_phy_write(dev, 0x225, 0x0357);
b43_phy_write(dev, 0x226, 0x0317);
b43_phy_write(dev, 0x227, 0x02D7);
b43_phy_write(dev, 0x228, 0x039C);
b43_phy_write(dev, 0x229, 0x0357);
b43_phy_write(dev, 0x22A, 0x0317);
b43_phy_write(dev, 0x22B, 0x02D7);
b43_phy_write(dev, 0x22C, 0x039C);
b43_phy_write(dev, 0x22D, 0x0357);
b43_phy_write(dev, 0x22E, 0x0317);
b43_phy_write(dev, 0x22F, 0x02D7);
}
static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
{ {
struct ssb_sprom *sprom = dev->dev->bus_sprom; struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
@ -1379,8 +1610,81 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
u16 tmp16; if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
u32 tmp32; nphy->band5g_pwrgain) {
b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
} else {
b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
}
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
if (dev->phy.rev < 2) {
b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
}
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
dev->dev->board_type == 0x8B) {
delays1[0] = 0x1;
delays1[5] = 0x14;
}
b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
b43_nphy_gain_ctrl_workarounds(dev);
if (dev->phy.rev < 2) {
if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
b43_hf_write(dev, b43_hf_read(dev) |
B43_HF_MLADVW);
} else if (dev->phy.rev == 2) {
b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
}
if (dev->phy.rev < 2)
b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
~B43_NPHY_SCRAM_SIGCTL_SCM);
/* Set phase track alpha and beta */
b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
if (dev->phy.rev == 2)
b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
B43_NPHY_FINERX2_CGC_DECGC);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
static void b43_nphy_workarounds(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
b43_nphy_classifier(dev, 1, 0); b43_nphy_classifier(dev, 1, 0);
@ -1393,153 +1697,10 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
b43_phy_set(dev, B43_NPHY_IQFLIP, b43_phy_set(dev, B43_NPHY_IQFLIP,
B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
if (dev->phy.rev >= 3) { if (dev->phy.rev >= 3)
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); b43_nphy_workarounds_rev3plus(dev);
tmp32 &= 0xffffff; else
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); b43_nphy_workarounds_rev1_2(dev);
b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
b43_phy_write(dev, 0x2AE, 0x000C);
/* TODO */
tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
0x2 : 0x9C40;
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
b43_nphy_gain_ctrl_workarounds(dev);
b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
/* TODO */
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
(sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
tmp32 = 0x00088888;
else
tmp32 = 0x88888888;
b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
if (dev->phy.rev == 4 &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
0x70);
b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
0x70);
}
b43_phy_write(dev, 0x224, 0x039C);
b43_phy_write(dev, 0x225, 0x0357);
b43_phy_write(dev, 0x226, 0x0317);
b43_phy_write(dev, 0x227, 0x02D7);
b43_phy_write(dev, 0x228, 0x039C);
b43_phy_write(dev, 0x229, 0x0357);
b43_phy_write(dev, 0x22A, 0x0317);
b43_phy_write(dev, 0x22B, 0x02D7);
b43_phy_write(dev, 0x22C, 0x039C);
b43_phy_write(dev, 0x22D, 0x0357);
b43_phy_write(dev, 0x22E, 0x0317);
b43_phy_write(dev, 0x22F, 0x02D7);
} else {
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
nphy->band5g_pwrgain) {
b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
} else {
b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
}
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
if (dev->phy.rev < 2) {
b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
}
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
if (sprom->boardflags2_lo & 0x100 &&
dev->dev->board_type == 0x8B) {
delays1[0] = 0x1;
delays1[5] = 0x14;
}
b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
b43_nphy_gain_ctrl_workarounds(dev);
if (dev->phy.rev < 2) {
if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
b43_hf_write(dev, b43_hf_read(dev) |
B43_HF_MLADVW);
} else if (dev->phy.rev == 2) {
b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
}
if (dev->phy.rev < 2)
b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
~B43_NPHY_SCRAM_SIGCTL_SCM);
/* Set phase track alpha and beta */
b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
if (dev->phy.rev == 2)
b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
B43_NPHY_FINERX2_CGC_DECGC);
}
if (nphy->hang_avoid) if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 0); b43_nphy_stay_in_carrier_search(dev, 0);
@ -2135,7 +2296,6 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
{ {
struct b43_phy_n *nphy = dev->phy.n;
u8 i; u8 i;
u16 reg, val; u16 reg, val;
@ -2199,10 +2359,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
enum ieee80211_band band = enum ieee80211_band band =
b43_current_band(dev->wl); b43_current_band(dev->wl);
if ((nphy->ipa2g_on && if (b43_nphy_ipa(dev))
band == IEEE80211_BAND_2GHZ) ||
(nphy->ipa5g_on &&
band == IEEE80211_BAND_5GHZ))
val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
else else
val = 0x11; val = 0x11;
@ -2577,8 +2734,8 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
{ {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if (dev->phy.rev >= 6) { if (dev->phy.rev >= 6) {
/* TODO If the chip is 47162 if (dev->dev->chip_id == 47162)
return txpwrctrl_tx_gain_ipa_rev5 */ return txpwrctrl_tx_gain_ipa_rev5;
return txpwrctrl_tx_gain_ipa_rev6; return txpwrctrl_tx_gain_ipa_rev6;
} else if (dev->phy.rev >= 5) { } else if (dev->phy.rev >= 5) {
return txpwrctrl_tx_gain_ipa_rev5; return txpwrctrl_tx_gain_ipa_rev5;
@ -2828,10 +2985,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
enum ieee80211_band band = enum ieee80211_band band =
b43_current_band(dev->wl); b43_current_band(dev->wl);
if ((nphy->ipa2g_on && if (b43_nphy_ipa(dev)) {
band == IEEE80211_BAND_2GHZ) ||
(nphy->ipa5g_on &&
band == IEEE80211_BAND_5GHZ)) {
table = b43_nphy_get_ipa_gain_table(dev); table = b43_nphy_get_ipa_gain_table(dev);
} else { } else {
if (band == IEEE80211_BAND_5GHZ) { if (band == IEEE80211_BAND_5GHZ) {
@ -3648,7 +3802,7 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
if (sprom->boardflags2_lo & 0x100 || if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
(dev->dev->board_vendor == PCI_VENDOR_ID_APPLE && (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
dev->dev->board_type == 0x8B)) dev->dev->board_type == 0x8B))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
@ -3667,8 +3821,7 @@ int b43_phy_initn(struct b43_wldev *dev)
} }
tmp2 = b43_current_band(dev->wl); tmp2 = b43_current_band(dev->wl);
if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) || if (b43_nphy_ipa(dev)) {
(nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
nphy->papd_epsilon_offset[0] << 7); nphy->papd_epsilon_offset[0] << 7);
@ -3706,15 +3859,7 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_tx_power_fix(dev); b43_nphy_tx_power_fix(dev);
/* TODO N PHY TX Power Control Idle TSSI */ /* TODO N PHY TX Power Control Idle TSSI */
/* TODO N PHY TX Power Control Setup */ /* TODO N PHY TX Power Control Setup */
b43_nphy_tx_gain_table_upload(dev);
if (phy->rev >= 3) {
/* TODO */
} else {
b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
b43_ntab_tx_gain_rev0_1_2);
b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
b43_ntab_tx_gain_rev0_1_2);
}
if (nphy->phyrxchain != 3) if (nphy->phyrxchain != 3)
b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
@ -3918,6 +4063,10 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
* 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
nphy->tx_pwr_idx[0] = 128;
nphy->tx_pwr_idx[1] = 128;
} }
static void b43_nphy_op_free(struct b43_wldev *dev) static void b43_nphy_op_free(struct b43_wldev *dev)

View File

@ -764,6 +764,8 @@ struct b43_phy_n {
u8 cal_orig_pwr_idx[2]; u8 cal_orig_pwr_idx[2];
u8 measure_hold; u8 measure_hold;
u8 phyrxchain; u8 phyrxchain;
u8 hw_phyrxchain;
u8 hw_phytxchain;
u8 perical; u8 perical;
u32 deaf_count; u32 deaf_count;
u32 rxcalparams; u32 rxcalparams;
@ -783,6 +785,8 @@ struct b43_phy_n {
u16 mphase_txcal_bestcoeffs[11]; u16 mphase_txcal_bestcoeffs[11];
bool txpwrctrl; bool txpwrctrl;
u8 tx_pwr_idx[2];
u16 adj_pwr_tbl[84];
u16 txcal_bbmult; u16 txcal_bbmult;
u16 txiqlocal_bestc[11]; u16 txiqlocal_bestc[11];
bool txiqlocal_coeffsvalid; bool txiqlocal_coeffsvalid;

View File

@ -4,6 +4,7 @@
IEEE 802.11n PHY and radio device data tables IEEE 802.11n PHY and radio device data tables
Copyright (c) 2008 Michael Buesch <m@bues.ch> Copyright (c) 2008 Michael Buesch <m@bues.ch>
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
IEEE 802.11n 2056 radio device data tables IEEE 802.11n 2056 radio device data tables
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or

View File

@ -1,29 +1,3 @@
/*
Broadcom B43 wireless driver
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
Some parts of the code in this file are derived from the brcm80211
driver Copyright (c) 2010 Broadcom Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef B43_RADIO_2056_H_ #ifndef B43_RADIO_2056_H_
#define B43_RADIO_2056_H_ #define B43_RADIO_2056_H_

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
IEEE 802.11n 2059 radio device data tables IEEE 802.11n 2059 radio device data tables
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or

View File

@ -4,6 +4,7 @@
IEEE 802.11n PHY data tables IEEE 802.11n PHY data tables
Copyright (c) 2008 Michael Buesch <m@bues.ch> Copyright (c) 2008 Michael Buesch <m@bues.ch>
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
IEEE 802.11n HT-PHY data tables IEEE 802.11n HT-PHY data tables
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or

View File

@ -3,6 +3,8 @@
Broadcom B43 wireless driver Broadcom B43 wireless driver
IEEE 802.11n LCN-PHY data tables IEEE 802.11n LCN-PHY data tables
Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
@ -25,6 +27,18 @@
#include "phy_common.h" #include "phy_common.h"
#include "phy_lcn.h" #include "phy_lcn.h"
struct b43_lcntab_tx_gain_tbl_entry {
u8 gm;
u8 pga;
u8 pad;
u8 dac;
u8 bb_mult;
};
/**************************************************
* Static tables.
**************************************************/
static const u16 b43_lcntab_0x02[] = { static const u16 b43_lcntab_0x02[] = {
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
@ -295,6 +309,160 @@ static const u32 b43_lcntab_0x18[] = {
0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000,
}; };
/**************************************************
* TX gain.
**************************************************/
const struct b43_lcntab_tx_gain_tbl_entry
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
{ 0x03, 0x00, 0x1f, 0x0, 0x44 },
{ 0x03, 0x00, 0x1e, 0x0, 0x43 },
{ 0x03, 0x00, 0x1d, 0x0, 0x44 },
{ 0x03, 0x00, 0x1c, 0x0, 0x44 },
{ 0x03, 0x00, 0x1b, 0x0, 0x45 },
{ 0x03, 0x00, 0x1a, 0x0, 0x46 },
{ 0x03, 0x00, 0x19, 0x0, 0x46 },
{ 0x03, 0x00, 0x18, 0x0, 0x47 },
{ 0x03, 0x00, 0x17, 0x0, 0x48 },
{ 0x03, 0x00, 0x17, 0x0, 0x46 },
{ 0x03, 0x00, 0x16, 0x0, 0x47 },
{ 0x03, 0x00, 0x15, 0x0, 0x48 },
{ 0x03, 0x00, 0x15, 0x0, 0x46 },
{ 0x03, 0x00, 0x15, 0x0, 0x44 },
{ 0x03, 0x00, 0x15, 0x0, 0x42 },
{ 0x03, 0x00, 0x15, 0x0, 0x40 },
{ 0x03, 0x00, 0x15, 0x0, 0x3f },
{ 0x03, 0x00, 0x14, 0x0, 0x40 },
{ 0x03, 0x00, 0x13, 0x0, 0x41 },
{ 0x03, 0x00, 0x13, 0x0, 0x40 },
{ 0x03, 0x00, 0x12, 0x0, 0x41 },
{ 0x03, 0x00, 0x12, 0x0, 0x40 },
{ 0x03, 0x00, 0x11, 0x0, 0x41 },
{ 0x03, 0x00, 0x11, 0x0, 0x40 },
{ 0x03, 0x00, 0x10, 0x0, 0x41 },
{ 0x03, 0x00, 0x10, 0x0, 0x40 },
{ 0x03, 0x00, 0x10, 0x0, 0x3e },
{ 0x03, 0x00, 0x10, 0x0, 0x3c },
{ 0x03, 0x00, 0x10, 0x0, 0x3a },
{ 0x03, 0x00, 0x0f, 0x0, 0x3d },
{ 0x03, 0x00, 0x0f, 0x0, 0x3b },
{ 0x03, 0x00, 0x0e, 0x0, 0x3d },
{ 0x03, 0x00, 0x0e, 0x0, 0x3c },
{ 0x03, 0x00, 0x0e, 0x0, 0x3a },
{ 0x03, 0x00, 0x0d, 0x0, 0x3c },
{ 0x03, 0x00, 0x0d, 0x0, 0x3b },
{ 0x03, 0x00, 0x0c, 0x0, 0x3e },
{ 0x03, 0x00, 0x0c, 0x0, 0x3c },
{ 0x03, 0x00, 0x0c, 0x0, 0x3a },
{ 0x03, 0x00, 0x0b, 0x0, 0x3e },
{ 0x03, 0x00, 0x0b, 0x0, 0x3c },
{ 0x03, 0x00, 0x0b, 0x0, 0x3b },
{ 0x03, 0x00, 0x0b, 0x0, 0x39 },
{ 0x03, 0x00, 0x0a, 0x0, 0x3d },
{ 0x03, 0x00, 0x0a, 0x0, 0x3b },
{ 0x03, 0x00, 0x0a, 0x0, 0x39 },
{ 0x03, 0x00, 0x09, 0x0, 0x3e },
{ 0x03, 0x00, 0x09, 0x0, 0x3c },
{ 0x03, 0x00, 0x09, 0x0, 0x3a },
{ 0x03, 0x00, 0x09, 0x0, 0x39 },
{ 0x03, 0x00, 0x08, 0x0, 0x3e },
{ 0x03, 0x00, 0x08, 0x0, 0x3c },
{ 0x03, 0x00, 0x08, 0x0, 0x3a },
{ 0x03, 0x00, 0x08, 0x0, 0x39 },
{ 0x03, 0x00, 0x08, 0x0, 0x37 },
{ 0x03, 0x00, 0x07, 0x0, 0x3d },
{ 0x03, 0x00, 0x07, 0x0, 0x3c },
{ 0x03, 0x00, 0x07, 0x0, 0x3a },
{ 0x03, 0x00, 0x07, 0x0, 0x38 },
{ 0x03, 0x00, 0x07, 0x0, 0x37 },
{ 0x03, 0x00, 0x06, 0x0, 0x3e },
{ 0x03, 0x00, 0x06, 0x0, 0x3c },
{ 0x03, 0x00, 0x06, 0x0, 0x3a },
{ 0x03, 0x00, 0x06, 0x0, 0x39 },
{ 0x03, 0x00, 0x06, 0x0, 0x37 },
{ 0x03, 0x00, 0x06, 0x0, 0x36 },
{ 0x03, 0x00, 0x06, 0x0, 0x34 },
{ 0x03, 0x00, 0x05, 0x0, 0x3d },
{ 0x03, 0x00, 0x05, 0x0, 0x3b },
{ 0x03, 0x00, 0x05, 0x0, 0x39 },
{ 0x03, 0x00, 0x05, 0x0, 0x38 },
{ 0x03, 0x00, 0x05, 0x0, 0x36 },
{ 0x03, 0x00, 0x05, 0x0, 0x35 },
{ 0x03, 0x00, 0x05, 0x0, 0x33 },
{ 0x03, 0x00, 0x04, 0x0, 0x3e },
{ 0x03, 0x00, 0x04, 0x0, 0x3c },
{ 0x03, 0x00, 0x04, 0x0, 0x3a },
{ 0x03, 0x00, 0x04, 0x0, 0x39 },
{ 0x03, 0x00, 0x04, 0x0, 0x37 },
{ 0x03, 0x00, 0x04, 0x0, 0x36 },
{ 0x03, 0x00, 0x04, 0x0, 0x34 },
{ 0x03, 0x00, 0x04, 0x0, 0x33 },
{ 0x03, 0x00, 0x04, 0x0, 0x31 },
{ 0x03, 0x00, 0x04, 0x0, 0x30 },
{ 0x03, 0x00, 0x04, 0x0, 0x2e },
{ 0x03, 0x00, 0x03, 0x0, 0x3c },
{ 0x03, 0x00, 0x03, 0x0, 0x3a },
{ 0x03, 0x00, 0x03, 0x0, 0x39 },
{ 0x03, 0x00, 0x03, 0x0, 0x37 },
{ 0x03, 0x00, 0x03, 0x0, 0x36 },
{ 0x03, 0x00, 0x03, 0x0, 0x34 },
{ 0x03, 0x00, 0x03, 0x0, 0x33 },
{ 0x03, 0x00, 0x03, 0x0, 0x31 },
{ 0x03, 0x00, 0x03, 0x0, 0x30 },
{ 0x03, 0x00, 0x03, 0x0, 0x2e },
{ 0x03, 0x00, 0x03, 0x0, 0x2d },
{ 0x03, 0x00, 0x03, 0x0, 0x2c },
{ 0x03, 0x00, 0x03, 0x0, 0x2b },
{ 0x03, 0x00, 0x03, 0x0, 0x29 },
{ 0x03, 0x00, 0x02, 0x0, 0x3d },
{ 0x03, 0x00, 0x02, 0x0, 0x3b },
{ 0x03, 0x00, 0x02, 0x0, 0x39 },
{ 0x03, 0x00, 0x02, 0x0, 0x38 },
{ 0x03, 0x00, 0x02, 0x0, 0x36 },
{ 0x03, 0x00, 0x02, 0x0, 0x35 },
{ 0x03, 0x00, 0x02, 0x0, 0x33 },
{ 0x03, 0x00, 0x02, 0x0, 0x32 },
{ 0x03, 0x00, 0x02, 0x0, 0x30 },
{ 0x03, 0x00, 0x02, 0x0, 0x2f },
{ 0x03, 0x00, 0x02, 0x0, 0x2e },
{ 0x03, 0x00, 0x02, 0x0, 0x2c },
{ 0x03, 0x00, 0x02, 0x0, 0x2b },
{ 0x03, 0x00, 0x02, 0x0, 0x2a },
{ 0x03, 0x00, 0x02, 0x0, 0x29 },
{ 0x03, 0x00, 0x02, 0x0, 0x27 },
{ 0x03, 0x00, 0x02, 0x0, 0x26 },
{ 0x03, 0x00, 0x02, 0x0, 0x25 },
{ 0x03, 0x00, 0x02, 0x0, 0x24 },
{ 0x03, 0x00, 0x02, 0x0, 0x23 },
{ 0x03, 0x00, 0x02, 0x0, 0x22 },
{ 0x03, 0x00, 0x02, 0x0, 0x21 },
{ 0x03, 0x00, 0x02, 0x0, 0x20 },
{ 0x03, 0x00, 0x01, 0x0, 0x3f },
{ 0x03, 0x00, 0x01, 0x0, 0x3d },
{ 0x03, 0x00, 0x01, 0x0, 0x3b },
{ 0x03, 0x00, 0x01, 0x0, 0x39 },
};
/**************************************************
* SW control.
**************************************************/
const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
0x0002, 0x0008, 0x0004, 0x0001,
};
/************************************************** /**************************************************
* R/W ops. * R/W ops.
**************************************************/ **************************************************/
@ -318,9 +486,8 @@ u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
break; break;
case B43_LCNTAB_32BIT: case B43_LCNTAB_32BIT:
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI); value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
value <<= 16; value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
value |= b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
break; break;
default: default:
B43_WARN_ON(1); B43_WARN_ON(1);
@ -357,10 +524,9 @@ void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
break; break;
case B43_LCNTAB_32BIT: case B43_LCNTAB_32BIT:
*((u32 *)data) = b43_phy_read(dev, *((u32 *)data) = b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATAHI);
*((u32 *)data) <<= 16;
*((u32 *)data) |= b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATALO); B43_PHY_LCN_TABLE_DATALO);
*((u32 *)data) |= (b43_phy_read(dev,
B43_PHY_LCN_TABLE_DATAHI) << 16);
data += 4; data += 4;
break; break;
default: default:
@ -447,7 +613,7 @@ void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
#define lcntab_upload(dev, offset, data) do { \ #define lcntab_upload(dev, offset, data) do { \
b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \ b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0) } while (0)
void b43_phy_lcn_tables_init(struct b43_wldev *dev) static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
{ {
lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02); lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01); lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
@ -464,3 +630,78 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev)
lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00); lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
} }
void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
{
u32 i;
u32 val;
u16 pa_gain = 0x70;
if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
pa_gain = 0x10;
for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
val = ((pa_gain << 24) |
(gain_table[i].pad << 16) |
(gain_table[i].pga << 8) |
gain_table[i].gm);
b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
/* brcmsmac doesn't maskset, we follow newer wl here */
val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
val &= 0x000fffff;
val |= ((gain_table[i].dac << 28) |
(gain_table[i].bb_mult << 20));
b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
}
}
/* Not implemented in brcmsmac, noticed in wl in MMIO dump */
static void b43_phy_lcn_rewrite_tables(struct b43_wldev *dev)
{
int i;
u32 tmp;
for (i = 0; i < 128; i++) {
tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
}
}
/* wlc_lcnphy_clear_papd_comptable */
static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
{
u8 i;
for (i = 0; i < 0x80; i++)
b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
}
/* wlc_lcnphy_tbl_init */
void b43_phy_lcn_tables_init(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
b43_phy_lcn_upload_static_tables(dev);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if (sprom->boardflags_lo & B43_BFL_EXTLNA)
b43_phy_lcn_load_tx_gain_tab(dev,
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
else
b43err(dev->wl,
"TX gain table unknown for this card\n");
}
if (sprom->boardflags_lo & B43_BFL_FEM &&
!(sprom->boardflags_hi & B43_BFH_FEM_BT))
b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
b43_lcntab_sw_ctl_4313_epa_rev0);
else
b43err(dev->wl, "SW ctl table is unknown for this card\n");
/* TODO: various tables ops here */
b43_phy_lcn_rewrite_tables(dev);
b43_phy_lcn_clean_papd_comp_table(dev);
}

View File

@ -10,6 +10,8 @@
#define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT) #define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT)
#define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT) #define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT)
#define B43_LCNTAB_TX_GAIN_SIZE 128
u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset); u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset);
void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data); unsigned int nr_elements, void *_data);

View File

@ -285,6 +285,7 @@ struct iwl_cfg iwl2000_2bg_cfg = {
struct iwl_cfg iwl2000_2bgn_d_cfg = { struct iwl_cfg iwl2000_2bgn_d_cfg = {
.name = "2000D Series 2x2 BGN", .name = "2000D Series 2x2 BGN",
IWL_DEVICE_2000, IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params,
}; };
#define IWL_DEVICE_2030 \ #define IWL_DEVICE_2030 \

View File

@ -659,7 +659,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
IWL_SCD_MGMT_MSK; IWL_SCD_MGMT_MSK;
if ((flush_control & BIT(IWL_RXON_CTX_PAN)) && if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
(priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) (priv->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK | flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |

View File

@ -311,7 +311,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
int slot0 = 300, slot1 = 0; int slot0 = 300, slot1 = 0;
int ret; int ret;
if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) if (priv->shrd->valid_contexts == BIT(IWL_RXON_CTX_BSS))
return 0; return 0;
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
@ -456,7 +456,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
else else
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
iwl_print_rx_config_cmd(priv, ctx); iwl_print_rx_config_cmd(priv, ctx->ctxid);
ret = iwl_check_rxon_cmd(priv, ctx); ret = iwl_check_rxon_cmd(priv, ctx);
if (ret) { if (ret) {
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");

View File

@ -117,7 +117,6 @@ struct iwl_tt_mgmt {
u8 iwl_tt_current_power_mode(struct iwl_priv *priv); u8 iwl_tt_current_power_mode(struct iwl_priv *priv);
bool iwl_tt_is_low_power_state(struct iwl_priv *priv); bool iwl_tt_is_low_power_state(struct iwl_priv *priv);
bool iwl_ht_enabled(struct iwl_priv *priv); bool iwl_ht_enabled(struct iwl_priv *priv);
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
void iwl_tt_enter_ct_kill(struct iwl_priv *priv); void iwl_tt_enter_ct_kill(struct iwl_priv *priv);

View File

@ -741,7 +741,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence); u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence); int txq_id = SEQ_TO_QUEUE(sequence);
int cmd_index = SEQ_TO_INDEX(sequence); int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
u32 status = le16_to_cpu(tx_resp->status.status); u32 status = le16_to_cpu(tx_resp->status.status);

View File

@ -114,7 +114,7 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name); IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
ret = wait_event_interruptible_timeout(priv->wait_command_queue, ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue,
priv->ucode_write_complete, 5 * HZ); priv->ucode_write_complete, 5 * HZ);
if (ret == -ERESTARTSYS) { if (ret == -ERESTARTSYS) {
IWL_ERR(priv, "Could not load the %s uCode section due " IWL_ERR(priv, "Could not load the %s uCode section due "
@ -349,6 +349,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
static int iwlagn_alive_notify(struct iwl_priv *priv) static int iwlagn_alive_notify(struct iwl_priv *priv)
{ {
struct iwl_rxon_context *ctx;
int ret; int ret;
if (!priv->tx_cmd_pool) if (!priv->tx_cmd_pool)
@ -361,6 +362,8 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
return -ENOMEM; return -ENOMEM;
iwl_trans_tx_start(trans(priv)); iwl_trans_tx_start(trans(priv));
for_each_context(priv, ctx)
ctx->last_tx_rejected = false;
ret = iwlagn_send_wimax_coex(priv); ret = iwlagn_send_wimax_coex(priv);
if (ret) if (ret)

View File

@ -623,9 +623,9 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
* The default context is always valid, * The default context is always valid,
* the PAN context depends on uCode. * the PAN context depends on uCode.
*/ */
priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); priv->shrd->valid_contexts = BIT(IWL_RXON_CTX_BSS);
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)
priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); priv->shrd->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
for (i = 0; i < NUM_IWL_RXON_CTX; i++) for (i = 0; i < NUM_IWL_RXON_CTX; i++)
priv->contexts[i].ctxid = i; priv->contexts[i].ctxid = i;
@ -2880,7 +2880,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
int err = 0; int err = 0;
if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
@ -2945,7 +2945,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
{ {
struct iwl_priv *priv = hw->priv; struct iwl_priv *priv = hw->priv;
if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->shrd->mutex);
@ -3032,7 +3032,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
{ {
priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME); priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
init_waitqueue_head(&priv->wait_command_queue); init_waitqueue_head(&priv->shrd->wait_command_queue);
INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->restart, iwl_bg_restart);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);

View File

@ -98,7 +98,6 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
enum iwlagn_ucode_type ucode_type); enum iwlagn_ucode_type ucode_type);
/* lib */ /* lib */
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
int iwlagn_send_tx_power(struct iwl_priv *priv); int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv);
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
@ -109,7 +108,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
/* rx */ /* rx */
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
void iwl_setup_rx_handlers(struct iwl_priv *priv); void iwl_setup_rx_handlers(struct iwl_priv *priv);
void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/* tx */ /* tx */

View File

@ -3213,12 +3213,7 @@ enum iwl_ucode_calib_cfg {
IWL_CALIB_CFG_LO_IDX | \ IWL_CALIB_CFG_LO_IDX | \
IWL_CALIB_CFG_TX_IQ_IDX | \ IWL_CALIB_CFG_TX_IQ_IDX | \
IWL_CALIB_CFG_RX_IQ_IDX | \ IWL_CALIB_CFG_RX_IQ_IDX | \
IWL_CALIB_CFG_NOISE_IDX | \ IWL_CALIB_CFG_CRYSTAL_IDX)
IWL_CALIB_CFG_CRYSTAL_IDX | \
IWL_CALIB_CFG_TEMPERATURE_IDX | \
IWL_CALIB_CFG_PAPD_IDX | \
IWL_CALIB_CFG_SENSITIVITY_IDX | \
IWL_CALIB_CFG_TX_PWR_IDX)
#define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK cpu_to_le32(BIT(0)) #define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK cpu_to_le32(BIT(0))

View File

@ -817,9 +817,9 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
} }
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv, void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid)
struct iwl_rxon_context *ctx)
{ {
struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
struct iwl_rxon_cmd *rxon = &ctx->staging; struct iwl_rxon_cmd *rxon = &ctx->staging;
IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
@ -868,7 +868,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
* commands by clearing the ready bit */ * commands by clearing the ready bit */
clear_bit(STATUS_READY, &priv->shrd->status); clear_bit(STATUS_READY, &priv->shrd->status);
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->shrd->wait_command_queue);
if (!ondemand) { if (!ondemand) {
/* /*
@ -1842,7 +1842,7 @@ void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx, enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid) u8 sta_id, u8 tid)
{ {
struct ieee80211_vif *vif = priv->contexts[ctx].vif; struct ieee80211_vif *vif;
u8 *addr = priv->stations[sta_id].sta.sta.addr; u8 *addr = priv->stations[sta_id].sta.sta.addr;
if (ctx == NUM_IWL_RXON_CTX) if (ctx == NUM_IWL_RXON_CTX)
@ -1865,3 +1865,14 @@ void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
} }
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
{
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
}
void iwl_nic_config(struct iwl_priv *priv)
{
priv->cfg->lib->nic_config(priv);
}

View File

@ -73,8 +73,6 @@ struct iwl_cmd;
#define TIME_UNIT 1024 #define TIME_UNIT 1024
#define IWL_CMD(x) case x: return #x
struct iwl_lib_ops { struct iwl_lib_ops {
/* set hw dependent parameters */ /* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv); int (*set_hw_params)(struct iwl_priv *priv);
@ -271,7 +269,6 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw,
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_alloc_traffic_mem(struct iwl_priv *priv); int iwl_alloc_traffic_mem(struct iwl_priv *priv);
void iwl_free_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv);
void iwl_reset_traffic_log(struct iwl_priv *priv);
void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
u16 length, struct ieee80211_hdr *header); u16 length, struct ieee80211_hdr *header);
void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
@ -360,26 +357,12 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
* S e n d i n g H o s t C o m m a n d s * * S e n d i n g H o s t C o m m a n d s *
*****************************************************/ *****************************************************/
const char *get_cmd_string(u8 cmd);
void iwl_bg_watchdog(unsigned long data); void iwl_bg_watchdog(unsigned long data);
u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
u32 addon, u32 beacon_interval); u32 addon, u32 beacon_interval);
/*****************************************************
* Error Handling Debugging
******************************************************/
#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
#else
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
}
#endif
/***************************************************** /*****************************************************
* GEOS * GEOS
******************************************************/ ******************************************************/
@ -389,8 +372,6 @@ void iwl_free_geos(struct iwl_priv *priv);
extern void iwl_send_bt_config(struct iwl_priv *priv); extern void iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv, extern int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear); u8 flags, bool clear);
void iwl_apm_stop(struct iwl_priv *priv);
int iwl_apm_init(struct iwl_priv *priv);
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@ -408,7 +389,4 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
extern bool bt_siso_mode; extern bool bt_siso_mode;
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
#endif /* __iwl_core_h__ */ #endif /* __iwl_core_h__ */

View File

@ -439,4 +439,22 @@
*/ */
#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) #define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
/**********************************************************
* CSR values
**********************************************************/
/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
*
* default interrupt coalescing timer is 64 x 32 = 2048 usecs
* default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
*/
#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
#endif /* !__iwl_csr_h__ */ #endif /* !__iwl_csr_h__ */

View File

@ -804,6 +804,89 @@ DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
DEBUGFS_READ_FILE_OPS(current_sleep_command); DEBUGFS_READ_FILE_OPS(current_sleep_command);
static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0, ofs = 0;
int cnt = 0, entry;
char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
(hw_params(priv).max_txq_num * 32 * 8) + 400;
const u8 *ptr;
ssize_t ret;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate buffer\n");
return -ENOMEM;
}
if (priv->tx_traffic &&
(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
ptr = priv->tx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Tx Traffic idx: %u\n", priv->tx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
}
}
if (priv->rx_traffic &&
(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
ptr = priv->rx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Rx Traffic idx: %u\n", priv->rx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
}
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
char buf[8];
int buf_size;
int traffic_log;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%d", &traffic_log) != 1)
return -EFAULT;
if (traffic_log == 0)
iwl_reset_traffic_log(priv);
return count;
}
static const char *fmt_value = " %-30s %10u\n"; static const char *fmt_value = " %-30s %10u\n";
static const char *fmt_hex = " %-30s 0x%02X\n"; static const char *fmt_hex = " %-30s 0x%02X\n";
static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; static const char *fmt_table = " %-30s %10u %10u %10u %10u\n";
@ -2340,6 +2423,7 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
DEBUGFS_READ_FILE_OPS(ucode_rx_stats); DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
DEBUGFS_READ_FILE_OPS(ucode_general_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats);
@ -2400,6 +2484,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);

View File

@ -32,7 +32,6 @@
#define __iwl_dev_h__ #define __iwl_dev_h__
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/leds.h> #include <linux/leds.h>
@ -89,100 +88,6 @@ struct iwl_tx_queue;
#define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_SHORT_RETRY_LIMIT 7U
#define DEFAULT_LONG_RETRY_LIMIT 4U #define DEFAULT_LONG_RETRY_LIMIT 4U
/* defined below */
struct iwl_device_cmd;
struct iwl_cmd_meta {
/* only for SYNC commands, iff the reply skb is wanted */
struct iwl_host_cmd *source;
/*
* only for ASYNC commands
* (which is somewhat stupid -- look at iwl-sta.c for instance
* which duplicates a bunch of code because the callback isn't
* invoked for SYNC commands, if it were and its result passed
* through it would be simpler...)
*/
void (*callback)(struct iwl_priv *priv,
struct iwl_device_cmd *cmd,
struct iwl_rx_packet *pkt);
u32 flags;
DEFINE_DMA_UNMAP_ADDR(mapping);
DEFINE_DMA_UNMAP_LEN(len);
};
/*
* Generic queue structure
*
* Contains common data for Rx and Tx queues.
*
* Note the difference between n_bd and n_window: the hardware
* always assumes 256 descriptors, so n_bd is always 256 (unless
* there might be HW changes in the future). For the normal TX
* queues, n_window, which is the size of the software queue data
* is also 256; however, for the command queue, n_window is only
* 32 since we don't need so many commands pending. Since the HW
* still uses 256 BDs for DMA though, n_bd stays 256. As a result,
* the software buffers (in the variables @meta, @txb in struct
* iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
* in the same struct) have 256.
* This means that we end up with the following:
* HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
* SW entries: | 0 | ... | 31 |
* where N is a number between 0 and 7. This means that the SW
* data is a window overlayed over the HW queue.
*/
struct iwl_queue {
int n_bd; /* number of BDs in this queue */
int write_ptr; /* 1-st empty entry (index) host_w*/
int read_ptr; /* last used entry (index) host_r*/
/* use for monitoring and recovering the stuck queue */
dma_addr_t dma_addr; /* physical addr for BD's */
int n_window; /* safe queue window */
u32 id;
int low_mark; /* low watermark, resume queue if free
* space more than this */
int high_mark; /* high watermark, stop queue if free
* space less than this */
};
/**
* struct iwl_tx_queue - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor
* @bd: base of circular buffer of TFDs
* @cmd: array of command/TX buffer pointers
* @meta: array of meta data for each command/tx buffer
* @dma_addr_cmd: physical address of cmd/tx buffer array
* @txb: array of per-TFD driver data
* @time_stamp: time (in jiffies) of last read_ptr change
* @need_update: indicates need to update read/write index
* @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
* @sta_id: valid if sched_retry is set
* @tid: valid if sched_retry is set
*
* A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
* descriptors) and required locking structures.
*/
#define TFD_TX_CMD_SLOTS 256
#define TFD_CMD_SLOTS 32
struct iwl_tx_queue {
struct iwl_queue q;
struct iwl_tfd *tfds;
struct iwl_device_cmd **cmd;
struct iwl_cmd_meta *meta;
struct sk_buff **skbs;
unsigned long time_stamp;
u8 need_update;
u8 sched_retry;
u8 active;
u8 swq_id;
u16 sta_id;
u16 tid;
};
#define IWL_NUM_SCAN_RATES (2) #define IWL_NUM_SCAN_RATES (2)
/* /*
@ -212,21 +117,6 @@ struct iwl_channel_info {
u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
}; };
#define IWL_TX_FIFO_BK 0 /* shared */
#define IWL_TX_FIFO_BE 1
#define IWL_TX_FIFO_VI 2 /* shared */
#define IWL_TX_FIFO_VO 3
#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
#define IWL_TX_FIFO_BE_IPAN 4
#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
#define IWL_TX_FIFO_VO_IPAN 5
/* re-uses the VO FIFO, uCode will properly flush/schedule */
#define IWL_TX_FIFO_AUX 5
#define IWL_TX_FIFO_UNUSED -1
/* AUX (TX during scan dwell) queue */
#define IWL_AUX_QUEUE 10
/* /*
* Minimum number of queues. MAX_NUM is defined in hw specific files. * Minimum number of queues. MAX_NUM is defined in hw specific files.
* Set the minimum to accommodate * Set the minimum to accommodate
@ -249,70 +139,6 @@ struct iwl_channel_info {
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
enum {
CMD_SYNC = 0,
CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1),
CMD_ON_DEMAND = BIT(2),
};
#define DEF_CMD_PAYLOAD_SIZE 320
/**
* struct iwl_device_cmd
*
* For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for commands that
* aren't fully copied and use other TFD space.
*/
struct iwl_device_cmd {
struct iwl_cmd_header hdr; /* uCode API */
union {
u32 flags;
u8 val8;
u16 val16;
u32 val32;
struct iwl_tx_cmd tx;
struct iwl6000_channel_switch_cmd chswitch;
u8 payload[DEF_CMD_PAYLOAD_SIZE];
} __packed cmd;
} __packed;
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
#define IWL_MAX_CMD_TFDS 2
enum iwl_hcmd_dataflag {
IWL_HCMD_DFL_NOCOPY = BIT(0),
};
/**
* struct iwl_host_cmd - Host command to the uCode
* @data: array of chunks that composes the data of the host command
* @reply_page: pointer to the page that holds the response to the host command
* @callback:
* @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
* @len: array of the lenths of the chunks in data
* @dataflags:
* @id: id of the host command
*/
struct iwl_host_cmd {
const void *data[IWL_MAX_CMD_TFDS];
unsigned long reply_page;
void (*callback)(struct iwl_priv *priv,
struct iwl_device_cmd *cmd,
struct iwl_rx_packet *pkt);
u32 flags;
u16 len[IWL_MAX_CMD_TFDS];
u8 dataflags[IWL_MAX_CMD_TFDS];
u8 id;
};
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 #define SUP_RATE_11A_MAX_NUM_CHANNELS 8
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11B_MAX_NUM_CHANNELS 4
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12
@ -580,9 +406,6 @@ extern const u8 iwl_bcast_addr[ETH_ALEN];
#define IWL_OPERATION_MODE_MIXED 2 #define IWL_OPERATION_MODE_MIXED 2
#define IWL_OPERATION_MODE_20MHZ 3 #define IWL_OPERATION_MODE_20MHZ 3
#define IWL_TX_CRC_SIZE 4
#define IWL_TX_DELIMITER_SIZE 4
#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
/* Sensitivity and chain noise calibration */ /* Sensitivity and chain noise calibration */
@ -706,9 +529,6 @@ struct iwl_chain_noise_data {
#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
#define IWL_TRAFFIC_ENTRIES (256)
#define IWL_TRAFFIC_ENTRY_SIZE (64)
enum { enum {
MEASUREMENT_READY = (1 << 0), MEASUREMENT_READY = (1 << 0),
MEASUREMENT_ACTIVE = (1 << 1), MEASUREMENT_ACTIVE = (1 << 1),
@ -849,21 +669,6 @@ struct iwl_event_log {
int wraps_more_count; int wraps_more_count;
}; };
/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
*
* default interrupt coalescing timer is 64 x 32 = 2048 usecs
* default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
*/
#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
/* /*
* This is the threshold value of plcp error rate per 100mSecs. It is * This is the threshold value of plcp error rate per 100mSecs. It is
* used to set and check for the validity of plcp_delta. * used to set and check for the validity of plcp_delta.
@ -1095,9 +900,6 @@ struct iwl_priv {
/*TODO: remove these pointers - use bus(priv) instead */ /*TODO: remove these pointers - use bus(priv) instead */
struct iwl_bus *bus; /* bus specific data */ struct iwl_bus *bus; /* bus specific data */
/* microcode/device supports multiple contexts */
u8 valid_contexts;
/* max number of station keys */ /* max number of station keys */
u8 sta_key_max_num; u8 sta_key_max_num;
@ -1142,8 +944,6 @@ struct iwl_priv {
/* Rate scaling data */ /* Rate scaling data */
u8 retry_rate; u8 retry_rate;
wait_queue_head_t wait_command_queue;
int activity_timer_active; int activity_timer_active;
/* counts mgmt, ctl, and data packets */ /* counts mgmt, ctl, and data packets */
@ -1327,7 +1127,7 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
#define for_each_context(priv, ctx) \ #define for_each_context(priv, ctx) \
for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \ for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \
ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \
if (priv->valid_contexts & BIT(ctx->ctxid)) if (priv->shrd->valid_contexts & BIT(ctx->ctxid))
static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
{ {

View File

@ -35,35 +35,12 @@
#include "iwl-io.h" #include "iwl-io.h"
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
static inline struct ieee80211_conf *ieee80211_get_hw_conf( static inline struct ieee80211_conf *ieee80211_get_hw_conf(
struct ieee80211_hw *hw) struct ieee80211_hw *hw)
{ {
return &hw->conf; return &hw->conf;
} }
/**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index
* @n_bd -- total number of entries in queue (must be power of 2)
*/
static inline int iwl_queue_inc_wrap(int index, int n_bd)
{
return ++index & (n_bd - 1);
}
/**
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
* @index -- current index
* @n_bd -- total number of entries in queue (must be power of 2)
*/
static inline int iwl_queue_dec_wrap(int index, int n_bd)
{
return --index & (n_bd - 1);
}
static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
{ {
IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");

View File

@ -483,9 +483,13 @@ out_no_pci:
return err; return err;
} }
static void iwl_pci_down(struct iwl_bus *bus) static void __devexit iwl_pci_remove(struct pci_dev *pdev)
{ {
struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific; struct iwl_shared *shrd = pci_get_drvdata(pdev);
struct iwl_bus *bus = shrd->bus;
struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus);
iwl_remove(shrd->priv);
pci_disable_msi(pci_bus->pci_dev); pci_disable_msi(pci_bus->pci_dev);
pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
@ -496,16 +500,6 @@ static void iwl_pci_down(struct iwl_bus *bus)
kfree(bus); kfree(bus);
} }
static void __devexit iwl_pci_remove(struct pci_dev *pdev)
{
struct iwl_shared *shrd = pci_get_drvdata(pdev);
struct iwl_bus *bus = shrd->bus;
iwl_remove(shrd->priv);
iwl_pci_down(bus);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int iwl_pci_suspend(struct device *device) static int iwl_pci_suspend(struct device *device)

View File

@ -42,6 +42,87 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-shared.h" #include "iwl-shared.h"
const char *get_cmd_string(u8 cmd)
{
switch (cmd) {
IWL_CMD(REPLY_ALIVE);
IWL_CMD(REPLY_ERROR);
IWL_CMD(REPLY_RXON);
IWL_CMD(REPLY_RXON_ASSOC);
IWL_CMD(REPLY_QOS_PARAM);
IWL_CMD(REPLY_RXON_TIMING);
IWL_CMD(REPLY_ADD_STA);
IWL_CMD(REPLY_REMOVE_STA);
IWL_CMD(REPLY_REMOVE_ALL_STA);
IWL_CMD(REPLY_TXFIFO_FLUSH);
IWL_CMD(REPLY_WEPKEY);
IWL_CMD(REPLY_TX);
IWL_CMD(REPLY_LEDS_CMD);
IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
IWL_CMD(COEX_PRIORITY_TABLE_CMD);
IWL_CMD(COEX_MEDIUM_NOTIFICATION);
IWL_CMD(COEX_EVENT_CMD);
IWL_CMD(REPLY_QUIET_CMD);
IWL_CMD(REPLY_CHANNEL_SWITCH);
IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
IWL_CMD(POWER_TABLE_CMD);
IWL_CMD(PM_SLEEP_NOTIFICATION);
IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
IWL_CMD(REPLY_SCAN_CMD);
IWL_CMD(REPLY_SCAN_ABORT_CMD);
IWL_CMD(SCAN_START_NOTIFICATION);
IWL_CMD(SCAN_RESULTS_NOTIFICATION);
IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
IWL_CMD(BEACON_NOTIFICATION);
IWL_CMD(REPLY_TX_BEACON);
IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
IWL_CMD(QUIET_NOTIFICATION);
IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
IWL_CMD(MEASURE_ABORT_NOTIFICATION);
IWL_CMD(REPLY_BT_CONFIG);
IWL_CMD(REPLY_STATISTICS_CMD);
IWL_CMD(STATISTICS_NOTIFICATION);
IWL_CMD(REPLY_CARD_STATE_CMD);
IWL_CMD(CARD_STATE_NOTIFICATION);
IWL_CMD(MISSED_BEACONS_NOTIFICATION);
IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
IWL_CMD(SENSITIVITY_CMD);
IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
IWL_CMD(REPLY_RX_PHY_CMD);
IWL_CMD(REPLY_RX_MPDU_CMD);
IWL_CMD(REPLY_RX);
IWL_CMD(REPLY_COMPRESSED_BA);
IWL_CMD(CALIBRATION_CFG_CMD);
IWL_CMD(CALIBRATION_RES_NOTIFICATION);
IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
IWL_CMD(REPLY_TX_POWER_DBM_CMD);
IWL_CMD(TEMPERATURE_NOTIFICATION);
IWL_CMD(TX_ANT_CONFIGURATION_CMD);
IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
IWL_CMD(REPLY_BT_COEX_PROT_ENV);
IWL_CMD(REPLY_WIPAN_PARAMS);
IWL_CMD(REPLY_WIPAN_RXON);
IWL_CMD(REPLY_WIPAN_RXON_TIMING);
IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
IWL_CMD(REPLY_WIPAN_QOS_PARAM);
IWL_CMD(REPLY_WIPAN_WEPKEY);
IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
IWL_CMD(REPLY_WOWLAN_PATTERNS);
IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
IWL_CMD(REPLY_WOWLAN_GET_STATUS);
default:
return "UNKNOWN";
}
}
/****************************************************************************** /******************************************************************************
* *
@ -563,7 +644,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
wiphy_rfkill_set_hw_state(priv->hw->wiphy, wiphy_rfkill_set_hw_state(priv->hw->wiphy,
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
else else
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->shrd->wait_command_queue);
} }
static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,

View File

@ -67,6 +67,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/mm.h> /* for page_address */
#include <net/mac80211.h> #include <net/mac80211.h>
#include "iwl-commands.h" #include "iwl-commands.h"
@ -212,6 +213,7 @@ struct iwl_tid_data {
* @ucode_owner: IWL_OWNERSHIP_* * @ucode_owner: IWL_OWNERSHIP_*
* @cmd_queue: command queue number * @cmd_queue: command queue number
* @status: STATUS_* * @status: STATUS_*
* @valid_contexts: microcode/device supports multiple contexts
* @bus: pointer to the bus layer data * @bus: pointer to the bus layer data
* @priv: pointer to the upper layer data * @priv: pointer to the upper layer data
* @hw_params: see struct iwl_hw_params * @hw_params: see struct iwl_hw_params
@ -232,6 +234,7 @@ struct iwl_shared {
u8 cmd_queue; u8 cmd_queue;
unsigned long status; unsigned long status;
bool wowlan; bool wowlan;
u8 valid_contexts;
struct iwl_bus *bus; struct iwl_bus *bus;
struct iwl_priv *priv; struct iwl_priv *priv;
@ -250,6 +253,8 @@ struct iwl_shared {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
wait_queue_head_t wait_command_queue;
}; };
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
@ -285,6 +290,26 @@ static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
free_pages(page, shrd->hw_params.rx_page_order); free_pages(page, shrd->hw_params.rx_page_order);
} }
/**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index
* @n_bd -- total number of entries in queue (must be power of 2)
*/
static inline int iwl_queue_inc_wrap(int index, int n_bd)
{
return ++index & (n_bd - 1);
}
/**
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
* @index -- current index
* @n_bd -- total number of entries in queue (must be power of 2)
*/
static inline int iwl_queue_dec_wrap(int index, int n_bd)
{
return --index & (n_bd - 1);
}
struct iwl_rx_mem_buffer { struct iwl_rx_mem_buffer {
dma_addr_t page_dma; dma_addr_t page_dma;
struct page *page; struct page *page;
@ -355,12 +380,39 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
struct iwl_cfg *cfg); struct iwl_cfg *cfg);
void __devexit iwl_remove(struct iwl_priv * priv); void __devexit iwl_remove(struct iwl_priv * priv);
void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx, enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid); u8 sta_id, u8 tid);
void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx, enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid); u8 sta_id, u8 tid);
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
void iwl_nic_config(struct iwl_priv *priv);
void iwl_apm_stop(struct iwl_priv *priv);
int iwl_apm_init(struct iwl_priv *priv);
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
const char *get_cmd_string(u8 cmd);
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_reset_traffic_log(struct iwl_priv *priv);
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid);
#else
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid)
{
}
#endif
#define IWL_CMD(x) case x: return #x
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
#define IWL_TRAFFIC_ENTRIES (256)
#define IWL_TRAFFIC_ENTRY_SIZE (64)
/***************************************************** /*****************************************************
* DRIVER STATUS FUNCTIONS * DRIVER STATUS FUNCTIONS

View File

@ -123,14 +123,14 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
return ret; return ret;
} }
static void iwl_add_sta_callback(struct iwl_priv *priv, static void iwl_add_sta_callback(struct iwl_shared *shrd,
struct iwl_device_cmd *cmd, struct iwl_device_cmd *cmd,
struct iwl_rx_packet *pkt) struct iwl_rx_packet *pkt)
{ {
struct iwl_addsta_cmd *addsta = struct iwl_addsta_cmd *addsta =
(struct iwl_addsta_cmd *)cmd->cmd.payload; (struct iwl_addsta_cmd *)cmd->cmd.payload;
iwl_process_add_sta_resp(priv, addsta, pkt, false); iwl_process_add_sta_resp(shrd->priv, addsta, pkt, false);
} }

View File

@ -63,6 +63,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/dma-mapping.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>

View File

@ -32,6 +32,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/pci.h>
#include "iwl-fh.h" #include "iwl-fh.h"
#include "iwl-csr.h" #include "iwl-csr.h"
@ -114,6 +115,97 @@ struct iwl_dma_ptr {
*/ */
#define IWL_IPAN_MCAST_QUEUE 8 #define IWL_IPAN_MCAST_QUEUE 8
struct iwl_cmd_meta {
/* only for SYNC commands, iff the reply skb is wanted */
struct iwl_host_cmd *source;
/*
* only for ASYNC commands
* (which is somewhat stupid -- look at iwl-sta.c for instance
* which duplicates a bunch of code because the callback isn't
* invoked for SYNC commands, if it were and its result passed
* through it would be simpler...)
*/
void (*callback)(struct iwl_shared *shrd,
struct iwl_device_cmd *cmd,
struct iwl_rx_packet *pkt);
u32 flags;
DEFINE_DMA_UNMAP_ADDR(mapping);
DEFINE_DMA_UNMAP_LEN(len);
};
/*
* Generic queue structure
*
* Contains common data for Rx and Tx queues.
*
* Note the difference between n_bd and n_window: the hardware
* always assumes 256 descriptors, so n_bd is always 256 (unless
* there might be HW changes in the future). For the normal TX
* queues, n_window, which is the size of the software queue data
* is also 256; however, for the command queue, n_window is only
* 32 since we don't need so many commands pending. Since the HW
* still uses 256 BDs for DMA though, n_bd stays 256. As a result,
* the software buffers (in the variables @meta, @txb in struct
* iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
* in the same struct) have 256.
* This means that we end up with the following:
* HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
* SW entries: | 0 | ... | 31 |
* where N is a number between 0 and 7. This means that the SW
* data is a window overlayed over the HW queue.
*/
struct iwl_queue {
int n_bd; /* number of BDs in this queue */
int write_ptr; /* 1-st empty entry (index) host_w*/
int read_ptr; /* last used entry (index) host_r*/
/* use for monitoring and recovering the stuck queue */
dma_addr_t dma_addr; /* physical addr for BD's */
int n_window; /* safe queue window */
u32 id;
int low_mark; /* low watermark, resume queue if free
* space more than this */
int high_mark; /* high watermark, stop queue if free
* space less than this */
};
/**
* struct iwl_tx_queue - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor
* @bd: base of circular buffer of TFDs
* @cmd: array of command/TX buffer pointers
* @meta: array of meta data for each command/tx buffer
* @dma_addr_cmd: physical address of cmd/tx buffer array
* @txb: array of per-TFD driver data
* @time_stamp: time (in jiffies) of last read_ptr change
* @need_update: indicates need to update read/write index
* @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
* @sta_id: valid if sched_retry is set
* @tid: valid if sched_retry is set
*
* A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
* descriptors) and required locking structures.
*/
#define TFD_TX_CMD_SLOTS 256
#define TFD_CMD_SLOTS 32
struct iwl_tx_queue {
struct iwl_queue q;
struct iwl_tfd *tfds;
struct iwl_device_cmd **cmd;
struct iwl_cmd_meta *meta;
struct sk_buff **skbs;
unsigned long time_stamp;
u8 need_update;
u8 sched_retry;
u8 active;
u8 swq_id;
u16 sta_id;
u16 tid;
};
/** /**
* struct iwl_trans_pcie - PCIe transport specific data * struct iwl_trans_pcie - PCIe transport specific data
* @rxq: all the RX queue data * @rxq: all the RX queue data
@ -195,7 +287,8 @@ int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id,
u32 flags, u16 len, const void *data); u32 flags, u16 len, const void *data);
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_tx_cmd_complete(struct iwl_trans *trans,
struct iwl_rx_mem_buffer *rxb);
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
u16 byte_cnt); u16 byte_cnt);
@ -343,4 +436,19 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
return index & (q->n_window - 1); return index & (q->n_window - 1);
} }
#define IWL_TX_FIFO_BK 0 /* shared */
#define IWL_TX_FIFO_BE 1
#define IWL_TX_FIFO_VI 2 /* shared */
#define IWL_TX_FIFO_VO 3
#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
#define IWL_TX_FIFO_BE_IPAN 4
#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
#define IWL_TX_FIFO_VO_IPAN 5
/* re-uses the VO FIFO, uCode will properly flush/schedule */
#define IWL_TX_FIFO_AUX 5
#define IWL_TX_FIFO_UNUSED -1
/* AUX (TX during scan dwell) queue */
#define IWL_AUX_QUEUE 10
#endif /* __iwl_trans_int_pcie_h__ */ #endif /* __iwl_trans_int_pcie_h__ */

View File

@ -30,8 +30,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include "iwl-dev.h" /*TODO: Remove include to iwl-core.h*/
#include "iwl-agn.h"
#include "iwl-core.h" #include "iwl-core.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-helpers.h" #include "iwl-helpers.h"
@ -453,7 +452,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
* iwl_trans_send_cmd() * iwl_trans_send_cmd()
* as we reclaim the driver command queue */ * as we reclaim the driver command queue */
if (rxb->page) if (rxb->page)
iwl_tx_cmd_complete(priv(trans), rxb); iwl_tx_cmd_complete(trans, rxb);
else else
IWL_WARN(trans, "Claim null rxb?\n"); IWL_WARN(trans, "Claim null rxb?\n");
} }
@ -646,7 +645,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
*/ */
clear_bit(STATUS_READY, &trans->shrd->status); clear_bit(STATUS_READY, &trans->shrd->status);
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->shrd->wait_command_queue);
IWL_ERR(trans, "RF is used by WiMAX\n"); IWL_ERR(trans, "RF is used by WiMAX\n");
return; return;
} }
@ -660,8 +659,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
iwl_dump_nic_event_log(trans, false, NULL, false); iwl_dump_nic_event_log(trans, false, NULL, false);
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS)
iwl_print_rx_config_cmd(priv, iwl_print_rx_config_cmd(priv(trans), IWL_RXON_CTX_BSS);
&priv->contexts[IWL_RXON_CTX_BSS]);
#endif #endif
iwlagn_fw_error(priv, false); iwlagn_fw_error(priv, false);
@ -705,18 +703,18 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
ptr = base + EVENT_START_OFFSET + (start_idx * event_size); ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
/* Make sure device is powered up for SRAM reads */ /* Make sure device is powered up for SRAM reads */
spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); spin_lock_irqsave(&bus(trans)->reg_lock, reg_flags);
iwl_grab_nic_access(bus(priv)); iwl_grab_nic_access(bus(trans));
/* Set starting address; reads will auto-increment */ /* Set starting address; reads will auto-increment */
iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); iwl_write32(bus(trans), HBUS_TARG_MEM_RADDR, ptr);
rmb(); rmb();
/* "time" is actually "data" for mode 0 (no timestamp). /* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing. */ * place event id # at far right for easier visual parsing. */
for (i = 0; i < num_events; i++) { for (i = 0; i < num_events; i++) {
ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); ev = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); time = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
if (mode == 0) { if (mode == 0) {
/* data, ev */ /* data, ev */
if (bufsz) { if (bufsz) {
@ -730,7 +728,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
time, ev); time, ev);
} }
} else { } else {
data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); data = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
if (bufsz) { if (bufsz) {
pos += scnprintf(*buf + pos, bufsz - pos, pos += scnprintf(*buf + pos, bufsz - pos,
"EVT_LOGT:%010u:0x%08x:%04u\n", "EVT_LOGT:%010u:0x%08x:%04u\n",
@ -745,8 +743,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
} }
/* Allow device to power down */ /* Allow device to power down */
iwl_release_nic_access(bus(priv)); iwl_release_nic_access(bus(trans));
spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); spin_unlock_irqrestore(&bus(trans)->reg_lock, reg_flags);
return pos; return pos;
} }
@ -823,10 +821,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
} }
/* event log header */ /* event log header */
capacity = iwl_read_targ_mem(bus(priv), base); capacity = iwl_read_targ_mem(bus(trans), base);
mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32)));
num_wraps = iwl_read_targ_mem(bus(priv), base + (2 * sizeof(u32))); num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32)));
next_entry = iwl_read_targ_mem(bus(priv), base + (3 * sizeof(u32))); next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32)));
if (capacity > logsize) { if (capacity > logsize) {
IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " IWL_ERR(trans, "Log capacity %d is bogus, limit to %d "
@ -848,9 +846,6 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
return pos; return pos;
} }
/* enable/disable bt channel inhibition */
priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce;
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log) if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
@ -908,8 +903,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
u32 inta_mask; u32 inta_mask;
#endif #endif
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats; struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
@ -1003,8 +997,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
else else
clear_bit(STATUS_RF_KILL_HW, clear_bit(STATUS_RF_KILL_HW,
&trans->shrd->status); &trans->shrd->status);
wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, iwl_set_hw_rfkill_state(priv(trans), hw_rf_kill);
hw_rf_kill);
} }
handled |= CSR_INT_BIT_RF_KILL; handled |= CSR_INT_BIT_RF_KILL;
@ -1093,7 +1086,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
handled |= CSR_INT_BIT_FH_TX; handled |= CSR_INT_BIT_FH_TX;
/* Wake up uCode load routine, now that load is complete */ /* Wake up uCode load routine, now that load is complete */
priv(trans)->ucode_write_complete = 1; priv(trans)->ucode_write_complete = 1;
wake_up_interruptible(&priv(trans)->wait_command_queue); wake_up_interruptible(&trans->shrd->wait_command_queue);
} }
if (inta & ~handled) { if (inta & ~handled) {

View File

@ -30,13 +30,19 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sched.h> #include <linux/sched.h>
#include "iwl-agn.h" /* TODO: remove include to iwl-dev.h */
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.h" #include "iwl-debug.h"
#include "iwl-csr.h"
#include "iwl-prph.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-agn-hw.h"
#include "iwl-helpers.h" #include "iwl-helpers.h"
#include "iwl-trans-int-pcie.h" #include "iwl-trans-int-pcie.h"
#define IWL_TX_CRC_SIZE 4
#define IWL_TX_DELIMITER_SIZE 4
/** /**
* iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/ */
@ -535,8 +541,7 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
unsigned long flags; unsigned long flags;
u16 txq_id; int txq_id;
struct iwl_priv *priv = priv(trans);
txq_id = iwlagn_txq_ctx_activate_free(trans); txq_id = iwlagn_txq_ctx_activate_free(trans);
if (txq_id == -1) { if (txq_id == -1) {
@ -560,7 +565,7 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
"queue\n", tid_data->tfds_in_queue); "queue\n", tid_data->tfds_in_queue);
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
} }
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
return 0; return 0;
} }
@ -856,16 +861,16 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
* need to be reclaimed. As result, some free space forms. If there is * need to be reclaimed. As result, some free space forms. If there is
* enough free space (> low mark), wake the stack that feeds us. * enough free space (> low mark), wake the stack that feeds us.
*/ */
static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
int idx)
{ {
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_TRANS_GET_PCIE_TRANS(trans(priv));
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
int nfreed = 0; int nfreed = 0;
if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
"index %d is out of range [0-%d] %d %d.\n", __func__, "index %d is out of range [0-%d] %d %d.\n", __func__,
txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr); txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);
return; return;
@ -875,9 +880,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (nfreed++ > 0) { if (nfreed++ > 0) {
IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx,
q->write_ptr, q->read_ptr); q->write_ptr, q->read_ptr);
iwlagn_fw_error(priv, false); iwlagn_fw_error(priv(trans), false);
} }
} }
@ -891,7 +896,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
* will be executed. The attached skb (if present) will only be freed * will be executed. The attached skb (if present) will only be freed
* if the callback returns 1 * if the callback returns 1
*/ */
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence); u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@ -900,7 +905,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
int cmd_index; int cmd_index;
struct iwl_device_cmd *cmd; struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta; struct iwl_cmd_meta *meta;
struct iwl_trans *trans = trans(priv);
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
unsigned long flags; unsigned long flags;
@ -913,7 +917,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
txq_id, trans->shrd->cmd_queue, sequence, txq_id, trans->shrd->cmd_queue, sequence,
trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr, trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) { trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
iwl_print_hex_error(priv, pkt, 32); iwl_print_hex_error(trans, pkt, 32);
return; return;
} }
@ -929,17 +933,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
meta->source->reply_page = (unsigned long)rxb_addr(rxb); meta->source->reply_page = (unsigned long)rxb_addr(rxb);
rxb->page = NULL; rxb->page = NULL;
} else if (meta->callback) } else if (meta->callback)
meta->callback(priv, cmd, pkt); meta->callback(trans->shrd, cmd, pkt);
spin_lock_irqsave(&trans->hcmd_lock, flags); spin_lock_irqsave(&trans->hcmd_lock, flags);
iwl_hcmd_queue_reclaim(priv, txq_id, index); iwl_hcmd_queue_reclaim(trans, txq_id, index);
if (!(meta->flags & CMD_ASYNC)) { if (!(meta->flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->hdr.cmd)); get_cmd_string(cmd->hdr.cmd));
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&trans->shrd->wait_command_queue);
} }
meta->flags = 0; meta->flags = 0;
@ -947,96 +951,14 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
spin_unlock_irqrestore(&trans->hcmd_lock, flags); spin_unlock_irqrestore(&trans->hcmd_lock, flags);
} }
const char *get_cmd_string(u8 cmd)
{
switch (cmd) {
IWL_CMD(REPLY_ALIVE);
IWL_CMD(REPLY_ERROR);
IWL_CMD(REPLY_RXON);
IWL_CMD(REPLY_RXON_ASSOC);
IWL_CMD(REPLY_QOS_PARAM);
IWL_CMD(REPLY_RXON_TIMING);
IWL_CMD(REPLY_ADD_STA);
IWL_CMD(REPLY_REMOVE_STA);
IWL_CMD(REPLY_REMOVE_ALL_STA);
IWL_CMD(REPLY_TXFIFO_FLUSH);
IWL_CMD(REPLY_WEPKEY);
IWL_CMD(REPLY_TX);
IWL_CMD(REPLY_LEDS_CMD);
IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
IWL_CMD(COEX_PRIORITY_TABLE_CMD);
IWL_CMD(COEX_MEDIUM_NOTIFICATION);
IWL_CMD(COEX_EVENT_CMD);
IWL_CMD(REPLY_QUIET_CMD);
IWL_CMD(REPLY_CHANNEL_SWITCH);
IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
IWL_CMD(POWER_TABLE_CMD);
IWL_CMD(PM_SLEEP_NOTIFICATION);
IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
IWL_CMD(REPLY_SCAN_CMD);
IWL_CMD(REPLY_SCAN_ABORT_CMD);
IWL_CMD(SCAN_START_NOTIFICATION);
IWL_CMD(SCAN_RESULTS_NOTIFICATION);
IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
IWL_CMD(BEACON_NOTIFICATION);
IWL_CMD(REPLY_TX_BEACON);
IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
IWL_CMD(QUIET_NOTIFICATION);
IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
IWL_CMD(MEASURE_ABORT_NOTIFICATION);
IWL_CMD(REPLY_BT_CONFIG);
IWL_CMD(REPLY_STATISTICS_CMD);
IWL_CMD(STATISTICS_NOTIFICATION);
IWL_CMD(REPLY_CARD_STATE_CMD);
IWL_CMD(CARD_STATE_NOTIFICATION);
IWL_CMD(MISSED_BEACONS_NOTIFICATION);
IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
IWL_CMD(SENSITIVITY_CMD);
IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
IWL_CMD(REPLY_RX_PHY_CMD);
IWL_CMD(REPLY_RX_MPDU_CMD);
IWL_CMD(REPLY_RX);
IWL_CMD(REPLY_COMPRESSED_BA);
IWL_CMD(CALIBRATION_CFG_CMD);
IWL_CMD(CALIBRATION_RES_NOTIFICATION);
IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
IWL_CMD(REPLY_TX_POWER_DBM_CMD);
IWL_CMD(TEMPERATURE_NOTIFICATION);
IWL_CMD(TX_ANT_CONFIGURATION_CMD);
IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
IWL_CMD(REPLY_BT_COEX_PROT_ENV);
IWL_CMD(REPLY_WIPAN_PARAMS);
IWL_CMD(REPLY_WIPAN_RXON);
IWL_CMD(REPLY_WIPAN_RXON_TIMING);
IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
IWL_CMD(REPLY_WIPAN_QOS_PARAM);
IWL_CMD(REPLY_WIPAN_WEPKEY);
IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
IWL_CMD(REPLY_WOWLAN_PATTERNS);
IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
IWL_CMD(REPLY_WOWLAN_GET_STATUS);
default:
return "UNKNOWN";
}
}
#define HOST_COMPLETE_TIMEOUT (2 * HZ) #define HOST_COMPLETE_TIMEOUT (2 * HZ)
static void iwl_generic_cmd_callback(struct iwl_priv *priv, static void iwl_generic_cmd_callback(struct iwl_shared *shrd,
struct iwl_device_cmd *cmd, struct iwl_device_cmd *cmd,
struct iwl_rx_packet *pkt) struct iwl_rx_packet *pkt)
{ {
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from %s (0x%08X)\n", IWL_ERR(shrd->trans, "Bad return from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
return; return;
} }
@ -1045,11 +967,11 @@ static void iwl_generic_cmd_callback(struct iwl_priv *priv,
switch (cmd->hdr.cmd) { switch (cmd->hdr.cmd) {
case REPLY_TX_LINK_QUALITY_CMD: case REPLY_TX_LINK_QUALITY_CMD:
case SENSITIVITY_CMD: case SENSITIVITY_CMD:
IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", IWL_DEBUG_HC_DUMP(shrd->trans, "back from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
break; break;
default: default:
IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", IWL_DEBUG_HC(shrd->trans, "back from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
} }
#endif #endif
@ -1107,7 +1029,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
return ret; return ret;
} }
ret = wait_event_interruptible_timeout(priv(trans)->wait_command_queue, ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue,
!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
HOST_COMPLETE_TIMEOUT); HOST_COMPLETE_TIMEOUT);
if (!ret) { if (!ret) {

View File

@ -65,14 +65,13 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include "iwl-dev.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-core.h"
#include "iwl-helpers.h"
#include "iwl-trans-int-pcie.h" #include "iwl-trans-int-pcie.h"
/*TODO remove uneeded includes when the transport layer tx_free will be here */ #include "iwl-csr.h"
#include "iwl-agn.h" #include "iwl-prph.h"
#include "iwl-shared.h" #include "iwl-shared.h"
#include "iwl-eeprom.h"
#include "iwl-agn-hw.h"
static int iwl_trans_rx_alloc(struct iwl_trans *trans) static int iwl_trans_rx_alloc(struct iwl_trans *trans)
{ {
@ -604,9 +603,8 @@ error:
return ret; return ret;
} }
static void iwl_set_pwr_vmain(struct iwl_priv *priv) static void iwl_set_pwr_vmain(struct iwl_trans *trans)
{ {
struct iwl_trans *trans = trans(priv);
/* /*
* (for documentation purposes) * (for documentation purposes)
* to set power to V_AUX, do: * to set power to V_AUX, do:
@ -625,11 +623,10 @@ static void iwl_set_pwr_vmain(struct iwl_priv *priv)
static int iwl_nic_init(struct iwl_trans *trans) static int iwl_nic_init(struct iwl_trans *trans)
{ {
unsigned long flags; unsigned long flags;
struct iwl_priv *priv = priv(trans);
/* nic_init */ /* nic_init */
spin_lock_irqsave(&trans->shrd->lock, flags); spin_lock_irqsave(&trans->shrd->lock, flags);
iwl_apm_init(priv); iwl_apm_init(priv(trans));
/* Set interrupt coalescing calibration timer to default (512 usecs) */ /* Set interrupt coalescing calibration timer to default (512 usecs) */
iwl_write8(bus(trans), CSR_INT_COALESCING, iwl_write8(bus(trans), CSR_INT_COALESCING,
@ -637,9 +634,9 @@ static int iwl_nic_init(struct iwl_trans *trans)
spin_unlock_irqrestore(&trans->shrd->lock, flags); spin_unlock_irqrestore(&trans->shrd->lock, flags);
iwl_set_pwr_vmain(priv); iwl_set_pwr_vmain(trans);
priv->cfg->lib->nic_config(priv); iwl_nic_config(priv(trans));
/* Allocate the RX queue, or reset if it is already allocated */ /* Allocate the RX queue, or reset if it is already allocated */
iwl_rx_init(trans); iwl_rx_init(trans);
@ -764,7 +761,6 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
static int iwl_trans_pcie_start_device(struct iwl_trans *trans) static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
{ {
int ret; int ret;
struct iwl_priv *priv = priv(trans);
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans); IWL_TRANS_GET_PCIE_TRANS(trans);
@ -792,7 +788,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
if (iwl_is_rfkill(trans->shrd)) { if (iwl_is_rfkill(trans->shrd)) {
wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); iwl_set_hw_rfkill_state(priv(trans), true);
iwl_enable_interrupts(trans); iwl_enable_interrupts(trans);
return -ERFKILL; return -ERFKILL;
} }
@ -833,8 +829,6 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
{ {
const struct queue_to_fifo_ac *queue_to_fifo; const struct queue_to_fifo_ac *queue_to_fifo;
struct iwl_rxon_context *ctx;
struct iwl_priv *priv = priv(trans);
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans); IWL_TRANS_GET_PCIE_TRANS(trans);
u32 a; u32 a;
@ -902,7 +896,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
/* map queues to FIFOs */ /* map queues to FIFOs */
if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS))
queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
else else
queue_to_fifo = iwlagn_default_queue_to_tx_fifo; queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
@ -914,8 +908,6 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
sizeof(trans_pcie->queue_stopped)); sizeof(trans_pcie->queue_stopped));
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
atomic_set(&trans_pcie->queue_stop_count[i], 0); atomic_set(&trans_pcie->queue_stop_count[i], 0);
for_each_context(priv, ctx)
ctx->last_tx_rejected = false;
/* reset to 0 to enable all the queue first */ /* reset to 0 to enable all the queue first */
trans_pcie->txq_ctx_active_msk = 0; trans_pcie->txq_ctx_active_msk = 0;
@ -1397,7 +1389,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
else else
clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, hw_rfkill); iwl_set_hw_rfkill_state(priv(trans), hw_rfkill);
return 0; return 0;
} }
@ -1505,12 +1497,144 @@ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id,
hw_params(trans).wd_timeout); hw_params(trans).wd_timeout);
IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n",
q->read_ptr, q->write_ptr);
return 1; return 1;
} }
return 0; return 0;
} }
static const char *get_fh_string(int cmd)
{
switch (cmd) {
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
IWL_CMD(FH_TSSR_TX_STATUS_REG);
IWL_CMD(FH_TSSR_TX_ERROR_REG);
default:
return "UNKNOWN";
}
}
int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
{
int i;
#ifdef CONFIG_IWLWIFI_DEBUG
int pos = 0;
size_t bufsz = 0;
#endif
static const u32 fh_tbl[] = {
FH_RSCSR_CHNL0_STTS_WPTR_REG,
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
FH_RSCSR_CHNL0_WPTR,
FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_MEM_RSSR_SHARED_CTRL_REG,
FH_MEM_RSSR_RX_STATUS_REG,
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_ERROR_REG
};
#ifdef CONFIG_IWLWIFI_DEBUG
if (display) {
bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return -ENOMEM;
pos += scnprintf(*buf + pos, bufsz - pos,
"FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
pos += scnprintf(*buf + pos, bufsz - pos,
" %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(bus(trans), fh_tbl[i]));
}
return pos;
}
#endif
IWL_ERR(trans, "FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
IWL_ERR(trans, " %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(bus(trans), fh_tbl[i]));
}
return 0;
}
static const char *get_csr_string(int cmd)
{
switch (cmd) {
IWL_CMD(CSR_HW_IF_CONFIG_REG);
IWL_CMD(CSR_INT_COALESCING);
IWL_CMD(CSR_INT);
IWL_CMD(CSR_INT_MASK);
IWL_CMD(CSR_FH_INT_STATUS);
IWL_CMD(CSR_GPIO_IN);
IWL_CMD(CSR_RESET);
IWL_CMD(CSR_GP_CNTRL);
IWL_CMD(CSR_HW_REV);
IWL_CMD(CSR_EEPROM_REG);
IWL_CMD(CSR_EEPROM_GP);
IWL_CMD(CSR_OTP_GP_REG);
IWL_CMD(CSR_GIO_REG);
IWL_CMD(CSR_GP_UCODE_REG);
IWL_CMD(CSR_GP_DRIVER_REG);
IWL_CMD(CSR_UCODE_DRV_GP1);
IWL_CMD(CSR_UCODE_DRV_GP2);
IWL_CMD(CSR_LED_REG);
IWL_CMD(CSR_DRAM_INT_TBL_REG);
IWL_CMD(CSR_GIO_CHICKEN_BITS);
IWL_CMD(CSR_ANA_PLL_CFG);
IWL_CMD(CSR_HW_REV_WA_REG);
IWL_CMD(CSR_DBG_HPET_MEM_REG);
default:
return "UNKNOWN";
}
}
void iwl_dump_csr(struct iwl_trans *trans)
{
int i;
static const u32 csr_tbl[] = {
CSR_HW_IF_CONFIG_REG,
CSR_INT_COALESCING,
CSR_INT,
CSR_INT_MASK,
CSR_FH_INT_STATUS,
CSR_GPIO_IN,
CSR_RESET,
CSR_GP_CNTRL,
CSR_HW_REV,
CSR_EEPROM_REG,
CSR_EEPROM_GP,
CSR_OTP_GP_REG,
CSR_GIO_REG,
CSR_GP_UCODE_REG,
CSR_GP_DRIVER_REG,
CSR_UCODE_DRV_GP1,
CSR_UCODE_DRV_GP2,
CSR_LED_REG,
CSR_DRAM_INT_TBL_REG,
CSR_GIO_CHICKEN_BITS,
CSR_ANA_PLL_CFG,
CSR_HW_REV_WA_REG,
CSR_DBG_HPET_MEM_REG
};
IWL_ERR(trans, "CSR values:\n");
IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is "
"CSR_INT_PERIODIC_REG)\n");
for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
IWL_ERR(trans, " %25s: 0X%08x\n",
get_csr_string(csr_tbl[i]),
iwl_read32(bus(trans), csr_tbl[i]));
}
}
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
/* create and remove of files */ /* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \
@ -1563,118 +1687,12 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
.llseek = generic_file_llseek, \ .llseek = generic_file_llseek, \
}; };
static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_trans *trans = file->private_data;
struct iwl_priv *priv = priv(trans);
int pos = 0, ofs = 0;
int cnt = 0, entry;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue *txq;
struct iwl_queue *q;
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
(hw_params(trans).max_txq_num * 32 * 8) + 400;
const u8 *ptr;
ssize_t ret;
if (!trans_pcie->txq) {
IWL_ERR(trans, "txq not ready\n");
return -EAGAIN;
}
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(trans, "Can not allocate buffer\n");
return -ENOMEM;
}
pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
txq = &trans_pcie->txq[cnt];
q = &txq->q;
pos += scnprintf(buf + pos, bufsz - pos,
"q[%d]: read_ptr: %u, write_ptr: %u\n",
cnt, q->read_ptr, q->write_ptr);
}
if (priv->tx_traffic &&
(iwl_get_debug_level(trans->shrd) & IWL_DL_TX)) {
ptr = priv->tx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Tx Traffic idx: %u\n", priv->tx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
}
}
pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
pos += scnprintf(buf + pos, bufsz - pos,
"read: %u, write: %u\n",
rxq->read, rxq->write);
if (priv->rx_traffic &&
(iwl_get_debug_level(trans->shrd) & IWL_DL_RX)) {
ptr = priv->rx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Rx Traffic idx: %u\n", priv->rx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
}
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_trans *trans = file->private_data;
char buf[8];
int buf_size;
int traffic_log;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%d", &traffic_log) != 1)
return -EFAULT;
if (traffic_log == 0)
iwl_reset_traffic_log(priv(trans));
return count;
}
static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iwl_trans *trans = file->private_data; struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_priv *priv = priv(trans);
struct iwl_tx_queue *txq; struct iwl_tx_queue *txq;
struct iwl_queue *q; struct iwl_queue *q;
char *buf; char *buf;
@ -1684,7 +1702,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
if (!trans_pcie->txq) { if (!trans_pcie->txq) {
IWL_ERR(priv, "txq not ready\n"); IWL_ERR(trans, "txq not ready\n");
return -EAGAIN; return -EAGAIN;
} }
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -1864,75 +1882,6 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
return count; return count;
} }
static const char *get_csr_string(int cmd)
{
switch (cmd) {
IWL_CMD(CSR_HW_IF_CONFIG_REG);
IWL_CMD(CSR_INT_COALESCING);
IWL_CMD(CSR_INT);
IWL_CMD(CSR_INT_MASK);
IWL_CMD(CSR_FH_INT_STATUS);
IWL_CMD(CSR_GPIO_IN);
IWL_CMD(CSR_RESET);
IWL_CMD(CSR_GP_CNTRL);
IWL_CMD(CSR_HW_REV);
IWL_CMD(CSR_EEPROM_REG);
IWL_CMD(CSR_EEPROM_GP);
IWL_CMD(CSR_OTP_GP_REG);
IWL_CMD(CSR_GIO_REG);
IWL_CMD(CSR_GP_UCODE_REG);
IWL_CMD(CSR_GP_DRIVER_REG);
IWL_CMD(CSR_UCODE_DRV_GP1);
IWL_CMD(CSR_UCODE_DRV_GP2);
IWL_CMD(CSR_LED_REG);
IWL_CMD(CSR_DRAM_INT_TBL_REG);
IWL_CMD(CSR_GIO_CHICKEN_BITS);
IWL_CMD(CSR_ANA_PLL_CFG);
IWL_CMD(CSR_HW_REV_WA_REG);
IWL_CMD(CSR_DBG_HPET_MEM_REG);
default:
return "UNKNOWN";
}
}
void iwl_dump_csr(struct iwl_trans *trans)
{
int i;
static const u32 csr_tbl[] = {
CSR_HW_IF_CONFIG_REG,
CSR_INT_COALESCING,
CSR_INT,
CSR_INT_MASK,
CSR_FH_INT_STATUS,
CSR_GPIO_IN,
CSR_RESET,
CSR_GP_CNTRL,
CSR_HW_REV,
CSR_EEPROM_REG,
CSR_EEPROM_GP,
CSR_OTP_GP_REG,
CSR_GIO_REG,
CSR_GP_UCODE_REG,
CSR_GP_DRIVER_REG,
CSR_UCODE_DRV_GP1,
CSR_UCODE_DRV_GP2,
CSR_LED_REG,
CSR_DRAM_INT_TBL_REG,
CSR_GIO_CHICKEN_BITS,
CSR_ANA_PLL_CFG,
CSR_HW_REV_WA_REG,
CSR_DBG_HPET_MEM_REG
};
IWL_ERR(trans, "CSR values:\n");
IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is "
"CSR_INT_PERIODIC_REG)\n");
for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
IWL_ERR(trans, " %25s: 0X%08x\n",
get_csr_string(csr_tbl[i]),
iwl_read32(bus(trans), csr_tbl[i]));
}
}
static ssize_t iwl_dbgfs_csr_write(struct file *file, static ssize_t iwl_dbgfs_csr_write(struct file *file,
const char __user *user_buf, const char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
@ -1954,67 +1903,6 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
return count; return count;
} }
static const char *get_fh_string(int cmd)
{
switch (cmd) {
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
IWL_CMD(FH_TSSR_TX_STATUS_REG);
IWL_CMD(FH_TSSR_TX_ERROR_REG);
default:
return "UNKNOWN";
}
}
int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
{
int i;
#ifdef CONFIG_IWLWIFI_DEBUG
int pos = 0;
size_t bufsz = 0;
#endif
static const u32 fh_tbl[] = {
FH_RSCSR_CHNL0_STTS_WPTR_REG,
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
FH_RSCSR_CHNL0_WPTR,
FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_MEM_RSSR_SHARED_CTRL_REG,
FH_MEM_RSSR_RX_STATUS_REG,
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_ERROR_REG
};
#ifdef CONFIG_IWLWIFI_DEBUG
if (display) {
bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return -ENOMEM;
pos += scnprintf(*buf + pos, bufsz - pos,
"FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
pos += scnprintf(*buf + pos, bufsz - pos,
" %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(bus(trans), fh_tbl[i]));
}
return pos;
}
#endif
IWL_ERR(trans, "FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
IWL_ERR(trans, " %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(bus(trans), fh_tbl[i]));
}
return 0;
}
static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
@ -2034,7 +1922,6 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
return ret; return ret;
} }
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_FILE_OPS(fh_reg);
@ -2049,7 +1936,6 @@ DEBUGFS_WRITE_FILE_OPS(csr);
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir) struct dentry *dir)
{ {
DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR);

View File

@ -73,10 +73,70 @@
* layer */ * layer */
struct iwl_priv; struct iwl_priv;
struct iwl_rxon_context;
struct iwl_host_cmd;
struct iwl_shared; struct iwl_shared;
struct iwl_device_cmd;
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
enum {
CMD_SYNC = 0,
CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1),
CMD_ON_DEMAND = BIT(2),
};
#define DEF_CMD_PAYLOAD_SIZE 320
/**
* struct iwl_device_cmd
*
* For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for commands that
* aren't fully copied and use other TFD space.
*/
struct iwl_device_cmd {
struct iwl_cmd_header hdr; /* uCode API */
union {
u32 flags;
u8 val8;
u16 val16;
u32 val32;
struct iwl_tx_cmd tx;
struct iwl6000_channel_switch_cmd chswitch;
u8 payload[DEF_CMD_PAYLOAD_SIZE];
} __packed cmd;
} __packed;
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
#define IWL_MAX_CMD_TFDS 2
enum iwl_hcmd_dataflag {
IWL_HCMD_DFL_NOCOPY = BIT(0),
};
/**
* struct iwl_host_cmd - Host command to the uCode
* @data: array of chunks that composes the data of the host command
* @reply_page: pointer to the page that holds the response to the host command
* @callback:
* @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
* @len: array of the lenths of the chunks in data
* @dataflags:
* @id: id of the host command
*/
struct iwl_host_cmd {
const void *data[IWL_MAX_CMD_TFDS];
unsigned long reply_page;
void (*callback)(struct iwl_shared *shrd,
struct iwl_device_cmd *cmd,
struct iwl_rx_packet *pkt);
u32 flags;
u16 len[IWL_MAX_CMD_TFDS];
u8 dataflags[IWL_MAX_CMD_TFDS];
u8 id;
};
/** /**
* struct iwl_trans_ops - transport specific operations * struct iwl_trans_ops - transport specific operations

View File

@ -973,6 +973,23 @@ static const struct {
{ MODEL_8682, "libertas/usb8682.bin" } { MODEL_8682, "libertas/usb8682.bin" }
}; };
#ifdef CONFIG_OLPC
static int try_olpc_fw(struct if_usb_card *cardp)
{
int retval = -ENOENT;
/* try the OLPC firmware first; fall back to fw_table list */
if (machine_is_olpc() && cardp->model == MODEL_8388)
retval = request_firmware(&cardp->fw,
"libertas/usb8388_olpc.bin", &cardp->udev->dev);
return retval;
}
#else
static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; }
#endif /* !CONFIG_OLPC */
static int get_fw(struct if_usb_card *cardp, const char *fwname) static int get_fw(struct if_usb_card *cardp, const char *fwname)
{ {
int i; int i;
@ -981,6 +998,10 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname)
if (fwname) if (fwname)
return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
/* Handle OLPC firmware */
if (try_olpc_fw(cardp) == 0)
return 0;
/* Otherwise search for firmware to use */ /* Otherwise search for firmware to use */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) { for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (fw_table[i].model != cardp->model) if (fw_table[i].model != cardp->model)

View File

@ -147,13 +147,12 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
u8 *ptr = rate1, *tmp; u8 *ptr = rate1, *tmp;
u32 i, j; u32 i, j;
tmp = kmalloc(rate1_size, GFP_KERNEL); tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
if (!tmp) { if (!tmp) {
dev_err(priv->adapter->dev, "failed to alloc tmp buf\n"); dev_err(priv->adapter->dev, "failed to alloc tmp buf\n");
return -ENOMEM; return -ENOMEM;
} }
memcpy(tmp, rate1, rate1_size);
memset(rate1, 0, rate1_size); memset(rate1, 0, rate1_size);
for (i = 0; rate2[i] && i < rate2_size; i++) { for (i = 0; rate2[i] && i < rate2_size; i++) {

View File

@ -1479,12 +1479,12 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
return -ENOMEM; return -ENOMEM;
} }
beacon_ie = kzalloc(ie_len, GFP_KERNEL);
beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
if (!beacon_ie) { if (!beacon_ie) {
dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
return -ENOMEM; return -ENOMEM;
} }
memcpy(beacon_ie, ie_buf, ie_len);
ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie, ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
ie_len, beacon_period, ie_len, beacon_period,
@ -1986,7 +1986,7 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
priv->curr_bcn_size = curr_bss->beacon_buf_size; priv->curr_bcn_size = curr_bss->beacon_buf_size;
kfree(priv->curr_bcn_buf); kfree(priv->curr_bcn_buf);
priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size, priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
GFP_KERNEL); GFP_KERNEL);
if (!priv->curr_bcn_buf) { if (!priv->curr_bcn_buf) {
dev_err(priv->adapter->dev, dev_err(priv->adapter->dev,

View File

@ -199,13 +199,14 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
return -ENOMEM; return -ENOMEM;
} }
beacon_ie = kzalloc(bss->len_beacon_ies, GFP_KERNEL);
beacon_ie = kmemdup(bss->information_elements,
bss->len_beacon_ies, GFP_KERNEL);
if (!beacon_ie) { if (!beacon_ie) {
dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
return -ENOMEM; return -ENOMEM;
} }
memcpy(beacon_ie, bss->information_elements,
bss->len_beacon_ies);
ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal, ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
beacon_ie, bss->len_beacon_ies, beacon_ie, bss->len_beacon_ies,
bss->beacon_interval, bss->beacon_interval,

View File

@ -5501,6 +5501,14 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
/* Set rssi values to dBm */ /* Set rssi values to dBm */
hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
/*
* Ask mac80211 to not to trigger PS mode
* based on PM bit of incoming frames.
*/
if (priv->ap_fw)
hw->flags |= IEEE80211_HW_AP_LINK_PS;
hw->vif_data_size = sizeof(struct mwl8k_vif); hw->vif_data_size = sizeof(struct mwl8k_vif);
hw->sta_data_size = sizeof(struct mwl8k_sta); hw->sta_data_size = sizeof(struct mwl8k_sta);

View File

@ -664,6 +664,9 @@
/* /*
* LED_CFG: LED control * LED_CFG: LED control
* ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1)
* OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1)
* SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)
* color LED's: * color LED's:
* 0: off * 0: off
* 1: blinking upon TX2 * 1: blinking upon TX2

View File

@ -493,7 +493,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size); rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
txdesc->key_idx : 0xff); txdesc->key_idx : txdesc->u.ht.wcid);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length); txdesc->length);
rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
@ -601,7 +601,7 @@ void rt2800_process_rxwi(struct queue_entry *entry,
} }
EXPORT_SYMBOL_GPL(rt2800_process_rxwi); EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
void rt2800_txdone_entry(struct queue_entry *entry, u32 status) void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
{ {
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@ -609,13 +609,11 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
u32 word; u32 word;
u16 mcs, real_mcs; u16 mcs, real_mcs;
int aggr, ampdu; int aggr, ampdu;
__le32 *txwi;
/* /*
* Obtain the status about this packet. * Obtain the status about this packet.
*/ */
txdesc.flags = 0; txdesc.flags = 0;
txwi = rt2800_drv_get_txwi(entry);
rt2x00_desc_read(txwi, 0, &word); rt2x00_desc_read(txwi, 0, &word);
mcs = rt2x00_get_field32(word, TXWI_W0_MCS); mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
@ -899,28 +897,12 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
} }
} }
static int rt2800_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on, unsigned long *delay_off)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
return 0;
}
static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led, enum led_type type) struct rt2x00_led *led, enum led_type type)
{ {
led->rt2x00dev = rt2x00dev; led->rt2x00dev = rt2x00dev;
led->type = type; led->type = type;
led->led_dev.brightness_set = rt2800_brightness_set; led->led_dev.brightness_set = rt2800_brightness_set;
led->led_dev.blink_set = rt2800_blink_set;
led->flags = LED_INITIALIZED; led->flags = LED_INITIALIZED;
} }
#endif /* CONFIG_RT2X00_LIB_LEDS */ #endif /* CONFIG_RT2X00_LIB_LEDS */
@ -928,11 +910,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
/* /*
* Configuration handlers. * Configuration handlers.
*/ */
static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto, const u8 *address,
struct ieee80211_key_conf *key) int wcid)
{ {
struct mac_wcid_entry wcid_entry; struct mac_wcid_entry wcid_entry;
u32 offset;
offset = MAC_WCID_ENTRY(wcid);
memset(&wcid_entry, 0xff, sizeof(wcid_entry));
if (address)
memcpy(wcid_entry.mac, address, ETH_ALEN);
rt2800_register_multiwrite(rt2x00dev, offset,
&wcid_entry, sizeof(wcid_entry));
}
static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
{
u32 offset;
offset = MAC_WCID_ATTR_ENTRY(wcid);
rt2800_register_write(rt2x00dev, offset, 0);
}
static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
int wcid, u32 bssidx)
{
u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
u32 reg;
/*
* The BSS Idx numbers is split in a main value of 3 bits,
* and a extended field for adding one additional bit to the value.
*/
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
(bssidx & 0x8) >> 3);
rt2800_register_write(rt2x00dev, offset, reg);
}
static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key)
{
struct mac_iveiv_entry iveiv_entry; struct mac_iveiv_entry iveiv_entry;
u32 offset; u32 offset;
u32 reg; u32 reg;
@ -952,14 +974,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
(crypto->cipher & 0x7)); (crypto->cipher & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
(crypto->cipher & 0x8) >> 3); (crypto->cipher & 0x8) >> 3);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
(crypto->bssidx & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
(crypto->bssidx & 0x8) >> 3);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
rt2800_register_write(rt2x00dev, offset, reg); rt2800_register_write(rt2x00dev, offset, reg);
} else { } else {
rt2800_register_write(rt2x00dev, offset, 0); /* Delete the cipher without touching the bssidx */
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
rt2800_register_write(rt2x00dev, offset, reg);
} }
offset = MAC_IVEIV_ENTRY(key->hw_key_idx); offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
@ -972,14 +996,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
iveiv_entry.iv[3] |= key->keyidx << 6; iveiv_entry.iv[3] |= key->keyidx << 6;
rt2800_register_multiwrite(rt2x00dev, offset, rt2800_register_multiwrite(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry)); &iveiv_entry, sizeof(iveiv_entry));
offset = MAC_WCID_ENTRY(key->hw_key_idx);
memset(&wcid_entry, 0, sizeof(wcid_entry));
if (crypto->cmd == SET_KEY)
memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
rt2800_register_multiwrite(rt2x00dev, offset,
&wcid_entry, sizeof(wcid_entry));
} }
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@ -1026,20 +1042,24 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
/* /*
* Update WCID information * Update WCID information
*/ */
rt2800_config_wcid_attr(rt2x00dev, crypto, key); rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
crypto->bssidx);
rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2800_config_shared_key); EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev) static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
{ {
struct mac_wcid_entry wcid_entry;
int idx; int idx;
u32 offset, reg; u32 offset;
/* /*
* Search for the first free pairwise key entry and return the * Search for the first free WCID entry and return the corresponding
* corresponding index. * index.
* *
* Make sure the WCID starts _after_ the last possible shared key * Make sure the WCID starts _after_ the last possible shared key
* entry (>32). * entry (>32).
@ -1049,11 +1069,17 @@ static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
* first 222 entries. * first 222 entries.
*/ */
for (idx = 33; idx <= 222; idx++) { for (idx = 33; idx <= 222; idx++) {
offset = MAC_WCID_ATTR_ENTRY(idx); offset = MAC_WCID_ENTRY(idx);
rt2800_register_read(rt2x00dev, offset, &reg); rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
if (!reg) sizeof(wcid_entry));
if (is_broadcast_ether_addr(wcid_entry.mac))
return idx; return idx;
} }
/*
* Use -1 to indicate that we don't have any more space in the WCID
* table.
*/
return -1; return -1;
} }
@ -1063,13 +1089,15 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
{ {
struct hw_key_entry key_entry; struct hw_key_entry key_entry;
u32 offset; u32 offset;
int idx;
if (crypto->cmd == SET_KEY) { if (crypto->cmd == SET_KEY) {
idx = rt2800_find_pairwise_keyslot(rt2x00dev); /*
if (idx < 0) * Allow key configuration only for STAs that are
* known by the hw.
*/
if (crypto->wcid < 0)
return -ENOSPC; return -ENOSPC;
key->hw_key_idx = idx; key->hw_key_idx = crypto->wcid;
memcpy(key_entry.key, crypto->key, memcpy(key_entry.key, crypto->key,
sizeof(key_entry.key)); sizeof(key_entry.key));
@ -1086,12 +1114,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
/* /*
* Update WCID information * Update WCID information
*/ */
rt2800_config_wcid_attr(rt2x00dev, crypto, key); rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
int wcid;
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
/*
* Find next free WCID.
*/
wcid = rt2800_find_wcid(rt2x00dev);
/*
* Store selected wcid even if it is invalid so that we can
* later decide if the STA is uploaded into the hw.
*/
sta_priv->wcid = wcid;
/*
* No space left in the device, however, we can still communicate
* with the STA -> No error.
*/
if (wcid < 0)
return 0;
/*
* Clean up WCID attributes and write STA address to the device.
*/
rt2800_delete_wcid_attr(rt2x00dev, wcid);
rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
rt2x00lib_get_bssidx(rt2x00dev, vif));
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_sta_add);
int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
{
/*
* Remove WCID entry, no need to clean the attributes as they will
* get renewed when the WCID is reused.
*/
rt2800_config_wcid(rt2x00dev, NULL, wcid);
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_sta_remove);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags) const unsigned int filter_flags)
{ {
@ -2771,11 +2846,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
SHARED_KEY_MODE_ENTRY(i), 0); SHARED_KEY_MODE_ENTRY(i), 0);
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; rt2800_config_wcid(rt2x00dev, NULL, i);
rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), rt2800_delete_wcid_attr(rt2x00dev, i);
wcid, sizeof(wcid));
rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0);
rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
} }
@ -4409,8 +4481,19 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn, struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size) u8 buf_size)
{ {
struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
int ret = 0; int ret = 0;
/*
* Don't allow aggregation for stations the hardware isn't aware
* of because tx status reports for frames to an unknown station
* always contain wcid=255 and thus we can't distinguish between
* multiple stations which leads to unwanted situations when the
* hw reorders frames due to aggregation.
*/
if (sta_priv->wcid < 0)
return 1;
switch (action) { switch (action) {
case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP: case IEEE80211_AMPDU_RX_STOP:

View File

@ -152,7 +152,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc); struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
void rt2800_txdone_entry(struct queue_entry *entry, u32 status); void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry); void rt2800_clear_beacon(struct queue_entry *entry);
@ -166,6 +166,9 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto, struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key); struct ieee80211_key_conf *key);
int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags); const unsigned int filter_flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,

View File

@ -619,11 +619,11 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
/* /*
* Initialize TX descriptor * Initialize TX descriptor
*/ */
rt2x00_desc_read(txd, 0, &word); word = 0;
rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
rt2x00_desc_write(txd, 0, word); rt2x00_desc_write(txd, 0, word);
rt2x00_desc_read(txd, 1, &word); word = 0;
rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
@ -634,12 +634,12 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
rt2x00_desc_write(txd, 1, word); rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(txd, 2, &word); word = 0;
rt2x00_set_field32(&word, TXD_W2_SD_PTR1, rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
skbdesc->skb_dma + TXWI_DESC_SIZE); skbdesc->skb_dma + TXWI_DESC_SIZE);
rt2x00_desc_write(txd, 2, word); rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 3, &word); word = 0;
rt2x00_set_field32(&word, TXD_W3_WIV, rt2x00_set_field32(&word, TXD_W3_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W3_QSEL, 2); rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
@ -760,7 +760,7 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
} }
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
rt2800_txdone_entry(entry, status); rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));
if (--max_tx_done == 0) if (--max_tx_done == 0)
break; break;
@ -1015,6 +1015,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats, .get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq, .get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold, .set_rts_threshold = rt2800_set_rts_threshold,
.sta_add = rt2x00mac_sta_add,
.sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed, .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx, .conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf, .get_tsf = rt2800_get_tsf,
@ -1076,6 +1078,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.config_erp = rt2800_config_erp, .config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant, .config_ant = rt2800_config_ant,
.config = rt2800_config, .config = rt2800_config,
.sta_add = rt2800_sta_add,
.sta_remove = rt2800_sta_remove,
}; };
static const struct data_queue_desc rt2800pci_queue_rx = { static const struct data_queue_desc rt2800pci_queue_rx = {
@ -1153,6 +1157,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
#endif #endif
#ifdef CONFIG_RT2800PCI_RT53XX #ifdef CONFIG_RT2800PCI_RT53XX
{ PCI_DEVICE(0x1814, 0x5390) }, { PCI_DEVICE(0x1814, 0x5390) },
{ PCI_DEVICE(0x1814, 0x539a) },
{ PCI_DEVICE(0x1814, 0x539f) }, { PCI_DEVICE(0x1814, 0x539f) },
#endif #endif
{ 0, } { 0, }

View File

@ -534,7 +534,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
if (!entry || rt2x00queue_empty(queue)) if (!entry || rt2x00queue_empty(queue))
break; break;
rt2800_txdone_entry(entry, reg); rt2800_txdone_entry(entry, reg,
rt2800usb_get_txwi(entry));
} }
} }
@ -749,6 +750,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.get_stats = rt2x00mac_get_stats, .get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq, .get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold, .set_rts_threshold = rt2800_set_rts_threshold,
.sta_add = rt2x00mac_sta_add,
.sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed, .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx, .conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf, .get_tsf = rt2800_get_tsf,
@ -806,6 +809,8 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.config_erp = rt2800_config_erp, .config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant, .config_ant = rt2800_config_ant,
.config = rt2800_config, .config = rt2800_config,
.sta_add = rt2800_sta_add,
.sta_remove = rt2800_sta_remove,
}; };
static const struct data_queue_desc rt2800usb_queue_rx = { static const struct data_queue_desc rt2800usb_queue_rx = {

View File

@ -478,6 +478,8 @@ struct rt2x00lib_crypto {
u8 key[16]; u8 key[16];
u8 tx_mic[8]; u8 tx_mic[8];
u8 rx_mic[8]; u8 rx_mic[8];
int wcid;
}; };
/* /*
@ -511,6 +513,19 @@ struct rt2x00intf_conf {
__le32 bssid[2]; __le32 bssid[2];
}; };
/*
* Private structure for storing STA details
* wcid: Wireless Client ID
*/
struct rt2x00_sta {
int wcid;
};
static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
{
return (struct rt2x00_sta *)sta->drv_priv;
}
/* /*
* rt2x00lib callback functions. * rt2x00lib callback functions.
*/ */
@ -620,6 +635,11 @@ struct rt2x00lib_ops {
void (*config) (struct rt2x00_dev *rt2x00dev, void (*config) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf, struct rt2x00lib_conf *libconf,
const unsigned int changed_flags); const unsigned int changed_flags);
int (*sta_add) (struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
int wcid);
}; };
/* /*
@ -1225,6 +1245,12 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
} }
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
* Utility functions.
*/
u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif);
/* /*
* Interrupt context handlers. * Interrupt context handlers.
*/ */
@ -1261,6 +1287,10 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
#else #else
#define rt2x00mac_set_key NULL #define rt2x00mac_set_key NULL
#endif /* CONFIG_RT2X00_LIB_CRYPTO */ #endif /* CONFIG_RT2X00_LIB_CRYPTO */
int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
int rt2x00mac_get_stats(struct ieee80211_hw *hw, int rt2x00mac_get_stats(struct ieee80211_hw *hw,

View File

@ -32,6 +32,22 @@
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00lib.h" #include "rt2x00lib.h"
/*
* Utility functions.
*/
u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif)
{
/*
* When in STA mode, bssidx is always 0 otherwise local_address[5]
* contains the bss number, see BSS_ID_MASK comments for details.
*/
if (rt2x00dev->intf_sta_count)
return 0;
return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
}
EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx);
/* /*
* Radio control handlers. * Radio control handlers.
*/ */
@ -914,6 +930,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
/*
* Tell mac80211 about the size of our private STA structure.
*/
rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta);
/* /*
* Allocate tx status FIFO for driver use. * Allocate tx status FIFO for driver use.
*/ */

View File

@ -494,6 +494,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct rt2x00lib_crypto crypto; struct rt2x00lib_crypto crypto;
static const u8 bcast_addr[ETH_ALEN] = static const u8 bcast_addr[ETH_ALEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
struct rt2x00_sta *sta_priv = NULL;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0; return 0;
@ -504,24 +505,18 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
memset(&crypto, 0, sizeof(crypto)); memset(&crypto, 0, sizeof(crypto));
/* crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);
* When in STA mode, bssidx is always 0 otherwise local_address[5]
* contains the bss number, see BSS_ID_MASK comments for details.
*/
if (rt2x00dev->intf_sta_count)
crypto.bssidx = 0;
else
crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
crypto.cipher = rt2x00crypto_key_to_cipher(key); crypto.cipher = rt2x00crypto_key_to_cipher(key);
if (crypto.cipher == CIPHER_NONE) if (crypto.cipher == CIPHER_NONE)
return -EOPNOTSUPP; return -EOPNOTSUPP;
crypto.cmd = cmd; crypto.cmd = cmd;
if (sta) if (sta) {
crypto.address = sta->addr; crypto.address = sta->addr;
else sta_priv = sta_to_rt2x00_sta(sta);
crypto.wcid = sta_priv->wcid;
} else
crypto.address = bcast_addr; crypto.address = bcast_addr;
if (crypto.cipher == CIPHER_TKIP) if (crypto.cipher == CIPHER_TKIP)
@ -560,6 +555,39 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
EXPORT_SYMBOL_GPL(rt2x00mac_set_key); EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
#endif /* CONFIG_RT2X00_LIB_CRYPTO */ #endif /* CONFIG_RT2X00_LIB_CRYPTO */
int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
/*
* If there's no space left in the device table store
* -1 as wcid but tell mac80211 everything went ok.
*/
if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
sta_priv->wcid = -1;
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
/*
* If we never sent the STA to the device no need to clean it up.
*/
if (sta_priv->wcid < 0)
return 0;
return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
}
EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;

View File

@ -310,11 +310,16 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct rt2x00_sta *sta_priv = NULL;
if (tx_info->control.sta) if (tx_info->control.sta) {
txdesc->u.ht.mpdu_density = txdesc->u.ht.mpdu_density =
tx_info->control.sta->ht_cap.ampdu_density; tx_info->control.sta->ht_cap.ampdu_density;
sta_priv = sta_to_rt2x00_sta(tx_info->control.sta);
txdesc->u.ht.wcid = sta_priv->wcid;
}
txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
/* /*

View File

@ -288,8 +288,8 @@ enum txentry_desc_flags {
* @signal: PLCP signal. * @signal: PLCP signal.
* @service: PLCP service. * @service: PLCP service.
* @msc: MCS. * @msc: MCS.
* @stbc: STBC. * @stbc: Use Space Time Block Coding (only available for MCS rates < 8).
* @ba_size: BA size. * @ba_size: Size of the recepients RX reorder buffer - 1.
* @rate_mode: Rate mode (See @enum rate_modulation). * @rate_mode: Rate mode (See @enum rate_modulation).
* @mpdu_density: MDPU density. * @mpdu_density: MDPU density.
* @retry_limit: Max number of retries. * @retry_limit: Max number of retries.
@ -321,6 +321,7 @@ struct txentry_desc {
u8 ba_size; u8 ba_size;
u8 mpdu_density; u8 mpdu_density;
enum txop txop; enum txop txop;
int wcid;
} ht; } ht;
} u; } u;

View File

@ -294,9 +294,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/ */
if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
/* for now 11a is unsupported in AP mode */ if (nvs->general_params.dual_mode_select)
if (wl->bss_type != BSS_TYPE_AP_BSS &&
nvs->general_params.dual_mode_select)
wl->enable_11a = true; wl->enable_11a = true;
} }

View File

@ -236,7 +236,7 @@ static struct conf_drv_settings default_conf = {
.ps_poll_recovery_period = 700, .ps_poll_recovery_period = 700,
.bet_enable = CONF_BET_MODE_ENABLE, .bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 50, .bet_max_consecutive = 50,
.psm_entry_retries = 5, .psm_entry_retries = 8,
.psm_exit_retries = 16, .psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3, .psm_entry_nullfunc_retries = 3,
.psm_entry_hangover_period = 1, .psm_entry_hangover_period = 1,
@ -2064,6 +2064,7 @@ deinit:
wl->session_counter = 0; wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->vif = NULL; wl->vif = NULL;
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl1271_free_ap_keys(wl); wl1271_free_ap_keys(wl);
memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
wl->ap_fw_ps_map = 0; wl->ap_fw_ps_map = 0;
@ -2199,10 +2200,14 @@ out:
static void wl1271_set_band_rate(struct wl1271 *wl) static void wl1271_set_band_rate(struct wl1271 *wl)
{ {
if (wl->band == IEEE80211_BAND_2GHZ) if (wl->band == IEEE80211_BAND_2GHZ) {
wl->basic_rate_set = wl->conf.tx.basic_rate; wl->basic_rate_set = wl->conf.tx.basic_rate;
else wl->rate_set = wl->conf.tx.basic_rate;
} else {
wl->basic_rate_set = wl->conf.tx.basic_rate_5; wl->basic_rate_set = wl->conf.tx.basic_rate_5;
wl->rate_set = wl->conf.tx.basic_rate_5;
}
} }
static bool wl12xx_is_roc(struct wl1271 *wl) static bool wl12xx_is_roc(struct wl1271 *wl)
@ -2653,6 +2658,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
}; };
/*
* A STA set to GEM cipher requires 2 tx spare blocks.
* Return to default value when GEM cipher key is removed
*/
if (key_type == KEY_GEM) {
if (action == KEY_ADD_OR_REPLACE)
wl->tx_spare_blocks = 2;
else if (action == KEY_REMOVE)
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
}
addr = sta ? sta->addr : bcast_addr; addr = sta ? sta->addr : bcast_addr;
if (is_zero_ether_addr(addr)) { if (is_zero_ether_addr(addr)) {
@ -3345,19 +3361,6 @@ sta_not_found:
ret = wl1271_acx_conn_monit_params(wl, true); ret = wl1271_acx_conn_monit_params(wl, true);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* If we want to go in PSM but we're not there yet */
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
enum wl1271_cmd_ps_mode mode;
mode = STATION_POWER_SAVE_MODE;
ret = wl1271_ps_set_mode(wl, mode,
wl->basic_rate,
true);
if (ret < 0)
goto out;
}
} else { } else {
/* use defaults when not associated */ /* use defaults when not associated */
bool was_assoc = bool was_assoc =
@ -3501,6 +3504,19 @@ sta_not_found:
if (ret < 0) if (ret < 0)
goto out; goto out;
} }
/* If we want to go in PSM but we're not there yet */
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
enum wl1271_cmd_ps_mode mode;
mode = STATION_POWER_SAVE_MODE;
ret = wl1271_ps_set_mode(wl, mode,
wl->basic_rate,
true);
if (ret < 0)
goto out;
}
} }
/* Handle new association with HT. Do this after join. */ /* Handle new association with HT. Do this after join. */
@ -4475,6 +4491,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
wl->hw->wiphy->max_scan_ssids = 1; wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->max_sched_scan_ssids = 8;
/* /*
* Maximum length of elements in scanning probe request templates * Maximum length of elements in scanning probe request templates
* should be the maximum length possible for a template, without * should be the maximum length possible for a template, without
@ -4599,6 +4616,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->sched_scanning = false; wl->sched_scanning = false;
wl->tx_security_seq = 0; wl->tx_security_seq = 0;
wl->tx_security_last_seq_lsb = 0; wl->tx_security_last_seq_lsb = 0;
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl->role_id = WL12XX_INVALID_ROLE_ID; wl->role_id = WL12XX_INVALID_ROLE_ID;
wl->system_hlid = WL12XX_SYSTEM_HLID; wl->system_hlid = WL12XX_SYSTEM_HLID;
wl->sta_hlid = WL12XX_INVALID_LINK_ID; wl->sta_hlid = WL12XX_INVALID_LINK_ID;

View File

@ -473,6 +473,51 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->passive[2] || cfg->active[2]; cfg->passive[2] || cfg->active[2];
} }
/* Returns 0 if no wildcard is used, 1 if wildcard is used or a
* negative value on error */
static int
wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req)
{
struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
struct cfg80211_ssid *ssid = req->ssids;
int ret, wildcard = 0;
wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
while ((cmd->n_ssids < req->n_ssids) && ssid) {
if (ssid->ssid_len == 0) {
wildcard = 1;
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
} else {
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN;
}
cmd->ssids[cmd->n_ssids].len = ssid->ssid_len;
memcpy(cmd->ssids[cmd->n_ssids].ssid, ssid->ssid,
ssid->ssid_len);
ssid++;
cmd->n_ssids++;
}
wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("cmd sched scan ssid list failed");
goto out;
}
ret = wildcard;
out:
kfree(cmd);
return ret;
}
int wl1271_scan_sched_scan_config(struct wl1271 *wl, int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req, struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies) struct ieee80211_sched_scan_ies *ies)
@ -504,14 +549,21 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
cfg->intervals[i] = cpu_to_le32(req->interval); cfg->intervals[i] = cpu_to_le32(req->interval);
if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) { cfg->ssid_len = 0;
cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC; if (req->n_ssids == 0) {
cfg->ssid_len = req->ssids[0].ssid_len; wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY");
memcpy(cfg->ssid, req->ssids[0].ssid,
req->ssids[0].ssid_len);
} else {
cfg->filter_type = SCAN_SSID_FILTER_ANY; cfg->filter_type = SCAN_SSID_FILTER_ANY;
cfg->ssid_len = 0; } else {
ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
if (ret < 0)
goto out;
if (ret) {
wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_DISABLED");
cfg->filter_type = SCAN_SSID_FILTER_DISABLED;
} else {
wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_LIST");
cfg->filter_type = SCAN_SSID_FILTER_LIST;
}
} }
if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) { if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {

View File

@ -204,9 +204,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 len; u32 len;
u32 total_blocks; u32 total_blocks;
int id, ret = -EBUSY, ac; int id, ret = -EBUSY, ac;
u32 spare_blocks = wl->tx_spare_blocks;
/* we use 1 spare block */
u32 spare_blocks = 1;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN; return -EAGAIN;
@ -220,6 +218,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
in the firmware */ in the firmware */
len = wl12xx_calc_packet_alignment(wl, total_len); len = wl12xx_calc_packet_alignment(wl, total_len);
/* in case of a dummy packet, use default amount of spare mem blocks */
if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
spare_blocks; spare_blocks;

View File

@ -25,6 +25,7 @@
#ifndef __TX_H__ #ifndef __TX_H__
#define __TX_H__ #define __TX_H__
#define TX_HW_BLOCK_SPARE_DEFAULT 1
#define TX_HW_BLOCK_SIZE 252 #define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000 #define TX_HW_MGMT_PKT_LIFETIME_TU 2000

View File

@ -425,6 +425,9 @@ struct wl1271 {
u32 tx_allocated_blocks; u32 tx_allocated_blocks;
u32 tx_results_count; u32 tx_results_count;
/* amount of spare TX blocks to use */
u32 tx_spare_blocks;
/* Accounting for allocated / available Tx packets in HW */ /* Accounting for allocated / available Tx packets in HW */
u32 tx_pkts_freed[NUM_TX_QUEUES]; u32 tx_pkts_freed[NUM_TX_QUEUES];
u32 tx_allocated_pkts[NUM_TX_QUEUES]; u32 tx_allocated_pkts[NUM_TX_QUEUES];

View File

@ -130,6 +130,8 @@
#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060 #define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
/* A-MSDU 802.11n */ /* A-MSDU 802.11n */
#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080 #define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080
/* Mesh Control 802.11s */
#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100
/* U-APSD queue for WMM IEs sent by AP */ /* U-APSD queue for WMM IEs sent by AP */
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)

View File

@ -769,6 +769,8 @@ enum nl80211_commands {
* that can be added to a scan request * that can be added to a scan request
* @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information
* elements that can be added to a scheduled scan request * elements that can be added to a scheduled scan request
* @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be
* used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute.
* *
* @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
* @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
@ -1011,6 +1013,24 @@ enum nl80211_commands {
* @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
* cycles, in msecs. * cycles, in msecs.
* @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more
* sets of attributes to match during scheduled scans. Only BSSs
* that match any of the sets will be reported. These are
* pass-thru filter rules.
* For a match to succeed, the BSS must match all attributes of a
* set. Since not every hardware supports matching all types of
* attributes, there is no guarantee that the reported BSSs are
* fully complying with the match sets and userspace needs to be
* able to ignore them by itself.
* Thus, the implementation is somewhat hardware-dependent, but
* this is only an optimization and the userspace application
* needs to handle all the non-filtered results anyway.
* If the match attributes don't make sense when combined with
* the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID
* is included in the probe request, but the match attributes
* will never let it go through), -EINVAL may be returned.
* If ommited, no filtering is done.
* *
* @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
* interface combinations. In each nested item, it contains attributes * interface combinations. In each nested item, it contains attributes
@ -1044,6 +1064,11 @@ enum nl80211_commands {
* *
* @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
* of the station, see &enum nl80211_sta_wme_attr. * of the station, see &enum nl80211_sta_wme_attr.
* @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
* as AP.
*
* @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
* roaming to another AP in the same ESS if the signal lever is low.
* *
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
@ -1256,6 +1281,12 @@ enum nl80211_attrs {
NL80211_ATTR_IE_ASSOC_RESP, NL80211_ATTR_IE_ASSOC_RESP,
NL80211_ATTR_STA_WME, NL80211_ATTR_STA_WME,
NL80211_ATTR_SUPPORT_AP_UAPSD,
NL80211_ATTR_ROAM_SUPPORT,
NL80211_ATTR_SCHED_SCAN_MATCH,
NL80211_ATTR_MAX_MATCH_SETS,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
@ -1715,6 +1746,26 @@ enum nl80211_reg_rule_attr {
NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
}; };
/**
* enum nl80211_sched_scan_match_attr - scheduled scan match attributes
* @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
* @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
* only report BSS with matching SSID.
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
* attribute number currently defined
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
*/
enum nl80211_sched_scan_match_attr {
__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID,
NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
/* keep last */
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
NL80211_SCHED_SCAN_MATCH_ATTR_MAX =
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1
};
/** /**
* enum nl80211_reg_rule_flags - regulatory rule flags * enum nl80211_reg_rule_flags - regulatory rule flags
* *
@ -2490,8 +2541,10 @@ enum nl80211_hidden_ssid {
/** /**
* enum nl80211_sta_wme_attr - station WME attributes * enum nl80211_sta_wme_attr - station WME attributes
* @__NL80211_STA_WME_INVALID: invalid number for nested attribute * @__NL80211_STA_WME_INVALID: invalid number for nested attribute
* @NL80211_STA_WME_QUEUES: bitmap of uapsd queues. * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format
* @NL80211_STA_WME_MAX_SP: max service period. * is the same as the AC bitmap in the QoS info field.
* @NL80211_STA_WME_MAX_SP: max service period. the format is the same
* as the MAX_SP field in the QoS info field (but already shifted down).
* @__NL80211_STA_WME_AFTER_LAST: internal * @__NL80211_STA_WME_AFTER_LAST: internal
* @NL80211_STA_WME_MAX: highest station WME attribute * @NL80211_STA_WME_MAX: highest station WME attribute
*/ */

View File

@ -25,7 +25,7 @@ struct ssb_sprom {
u8 et1phyaddr; /* MII address for enet1 */ u8 et1phyaddr; /* MII address for enet1 */
u8 et0mdcport; /* MDIO for enet0 */ u8 et0mdcport; /* MDIO for enet0 */
u8 et1mdcport; /* MDIO for enet1 */ u8 et1mdcport; /* MDIO for enet1 */
u8 board_rev; /* Board revision number from SPROM. */ u16 board_rev; /* Board revision number from SPROM. */
u8 country_code; /* Country Code */ u8 country_code; /* Country Code */
u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */ u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */
u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */ u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */

Some files were not shown because too many files have changed in this diff Show More