//============================================================ // // File Name: Hal8192CDMOutSrc.c // // Description: // // This file is for 92CE/92CU outsource dynamic mechanism for partner. // // //============================================================ #ifndef _HAL8192CDM_C_ #define _HAL8192CDM_C_ #ifdef __KERNEL__ #include #include #include #include #include #include #include #include #include #endif #include "./8192cd_cfg.h" #include "./8192cd.h" #include "./8192cd_hw.h" #include "./8192cd_headers.h" #include "./8192cd_debug.h" #ifdef __KERNEL__ #ifdef __LINUX_2_6__ #include #else #include #endif #endif //============================================================ // Global var //============================================================ static unsigned int OFDMSwingTable[] = { 0x7f8001fe, // 0, +6.0dB 0x788001e2, // 1, +5.5dB 0x71c001c7, // 2, +5.0dB 0x6b8001ae, // 3, +4.5dB 0x65400195, // 4, +4.0dB 0x5fc0017f, // 5, +3.5dB 0x5a400169, // 6, +3.0dB 0x55400155, // 7, +2.5dB 0x50800142, // 8, +2.0dB 0x4c000130, // 9, +1.5dB 0x47c0011f, // 10, +1.0dB 0x43c0010f, // 11, +0.5dB 0x40000100, // 12, +0dB 0x3c8000f2, // 13, -0.5dB 0x390000e4, // 14, -1.0dB 0x35c000d7, // 15, -1.5dB 0x32c000cb, // 16, -2.0dB 0x300000c0, // 17, -2.5dB 0x2d4000b5, // 18, -3.0dB 0x2ac000ab, // 19, -3.5dB 0x288000a2, // 20, -4.0dB 0x26000098, // 21, -4.5dB 0x24000090, // 22, -5.0dB 0x22000088, // 23, -5.5dB 0x20000080, // 24, -6.0dB 0x1e400079, // 25, -6.5dB 0x1c800072, // 26, -7.0dB 0x1b00006c, // 27. -7.5dB 0x19800066, // 28, -8.0dB 0x18000060, // 29, -8.5dB 0x16c0005b, // 30, -9.0dB 0x15800056, // 31, -9.5dB 0x14400051, // 32, -10.0dB 0x1300004c, // 33, -10.5dB 0x12000048, // 34, -11.0dB 0x11000044, // 35, -11.5dB 0x10000040, // 36, -12.0dB }; unsigned int TxPwrTrk_OFDM_SwingTbl[TxPwrTrk_OFDM_SwingTbl_Len] = { /* +6.0dB */ 0x7f8001fe, /* +5.5dB */ 0x788001e2, /* +5.0dB */ 0x71c001c7, /* +4.5dB */ 0x6b8001ae, /* +4.0dB */ 0x65400195, /* +3.5dB */ 0x5fc0017f, /* +3.0dB */ 0x5a400169, /* +2.5dB */ 0x55400155, /* +2.0dB */ 0x50800142, /* +1.5dB */ 0x4c000130, /* +1.0dB */ 0x47c0011f, /* +0.5dB */ 0x43c0010f, /* 0.0dB */ 0x40000100, /* -0.5dB */ 0x3c8000f2, /* -1.0dB */ 0x390000e4, /* -1.5dB */ 0x35c000d7, /* -2.0dB */ 0x32c000cb, /* -2.5dB */ 0x300000c0, /* -3.0dB */ 0x2d4000b5, /* -3.5dB */ 0x2ac000ab, /* -4.0dB */ 0x288000a2, /* -4.5dB */ 0x26000098, /* -5.0dB */ 0x24000090, /* -5.5dB */ 0x22000088, /* -6.0dB */ 0x20000080, /* -6.5dB */ 0x1a00006c, /* -7.0dB */ 0x1c800072, /* -7.5dB */ 0x18000060, /* -8.0dB */ 0x19800066, /* -8.5dB */ 0x15800056, /* -9.0dB */ 0x26c0005b, /* -9.5dB */ 0x14400051, /* -10.0dB */ 0x24400051, /* -10.5dB */ 0x1300004c, /* -11.0dB */ 0x12000048, /* -11.5dB */ 0x11000044, /* -12.0dB */ 0x10000040 }; unsigned char TxPwrTrk_CCK_SwingTbl[TxPwrTrk_CCK_SwingTbl_Len][8] = { /* 0.0dB */ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0.5dB */ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1.0dB */ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 1.5dB */ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 2.0dB */ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 2.5dB */ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 3.0dB */ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 3.5dB */ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 4.0dB */ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 4.5dB */ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 5.0dB */ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 5.5dB */ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 6.0dB */ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 6.5dB */ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 7.0dB */ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 7.5dB */ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 8.0dB */ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 8.5dB */ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 9.0dB */ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 9.5dB */ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 10.0dB */ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 10.5dB */ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11.0dB */ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} }; unsigned char TxPwrTrk_CCK_SwingTbl_CH14[TxPwrTrk_CCK_SwingTbl_Len][8] = { /* 0.0dB */ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0.5dB */ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1.0dB */ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 1.5dB */ {0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 2.0dB */ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 2.5dB */ {0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 3.0dB */ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 3.5dB */ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 4.0dB */ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 4.5dB */ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 5.0dB */ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 5.5dB */ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 6.0dB */ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 6.5dB */ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 7.0dB */ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 7.5dB */ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 8.0dB */ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 8.5dB */ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 9.0dB */ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 9.5dB */ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 10.0dB */ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 10.5dB */ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11.0dB */ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} }; unsigned char CCKSwingTable_Ch1_Ch13[][8] = { {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, // 0, +0dB {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, // 1, -0.5dB {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, // 2, -1.0dB {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, // 3, -1.5dB {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, // 4, -2.0dB {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, // 5, -2.5dB {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, // 6, -3.0dB {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, // 7, -3.5dB {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, // 8, -4.0dB {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, // 9, -4.5dB {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, // 10, -5.0dB {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, // 11, -5.5dB {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, // 12, -6.0dB {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, // 13, -6.5dB {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, // 14, -7.0dB {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, // 15, -7.5dB {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, // 16, -8.0dB {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, // 17, -8.5dB {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, // 18, -9.0dB {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 19, -9.5dB {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 20, -10.0dB {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, // 21, -10.5dB {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, // 22, -11.0dB {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, // 23, -11.5dB {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, // 24, -12.0dB {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, // 25, -12.5dB {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, // 26, -13.0dB {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, // 27, -13.5dB {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, // 28, -14.0dB {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, // 29, -14.5dB {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, // 30, -15.0dB {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, // 31, -15.5dB {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} // 32, -16.0dB }; unsigned char CCKSwingTable_Ch14 [][8]= { {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, // 0, +0dB {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, // 1, -0.5dB {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, // 2, -1.0dB {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, // 3, -1.5dB {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, // 4, -2.0dB {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, // 5, -2.5dB {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, // 6, -3.0dB {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, // 7, -3.5dB {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, // 8, -4.0dB {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, // 9, -4.5dB {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, // 10, -5.0dB {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 11, -5.5dB {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 12, -6.0dB {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, // 13, -6.5dB {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, // 14, -7.0dB {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 15, -7.5dB {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 16, -8.0dB {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 17, -8.5dB {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 18, -9.0dB {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 19, -9.5dB {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 20, -10.0dB {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, // 21, -10.5dB {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, // 22, -11.0dB {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, // 23, -11.5dB {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, // 24, -12.0dB {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, // 25, -12.5dB {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, // 26, -13.0dB {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, // 27, -13.5dB {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, // 28, -14.0dB {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, // 29, -14.5dB {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, // 30, -15.0dB {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, // 31, -15.5dB {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} // 32, -16.0dB }; const int OFDM_TABLE_SIZE= sizeof(OFDMSwingTable)/sizeof(int); const int CCK_TABLE_SIZE= sizeof(CCKSwingTable_Ch1_Ch13) >>3; #ifdef CONFIG_RTL_92D_SUPPORT static unsigned int OFDMSwingTable_92D[] = { 0x7f8001fe, // 0, +6.0dB 0x788001e2, // 1, +5.5dB 0x71c001c7, // 2, +5.0dB 0x6b8001ae, // 3, +4.5dB 0x65400195, // 4, +4.0dB 0x5fc0017f, // 5, +3.5dB 0x5a400169, // 6, +3.0dB 0x55400155, // 7, +2.5dB 0x50800142, // 8, +2.0dB 0x4c000130, // 9, +1.5dB 0x47c0011f, // 10, +1.0dB 0x43c0010f, // 11, +0.5dB 0x40000100, // 12, +0dB 0x3c8000f2, // 13, -0.5dB 0x390000e4, // 14, -1.0dB 0x35c000d7, // 15, -1.5dB 0x32c000cb, // 16, -2.0dB 0x300000c0, // 17, -2.5dB 0x2d4000b5, // 18, -3.0dB 0x2ac000ab, // 19, -3.5dB 0x288000a2, // 20, -4.0dB 0x26000098, // 21, -4.5dB 0x24000090, // 22, -5.0dB 0x22000088, // 23, -5.5dB 0x20000080, // 24, -6.0dB 0x1e400079, // 25, -6.5dB 0x1c800072, // 26, -7.0dB 0x1b00006c, // 27. -7.5dB 0x19800066, // 28, -8.0dB 0x18000060, // 29, -8.5dB 0x16c0005b, // 30, -9.0dB 0x15800056, // 31, -9.5dB 0x14400051, // 32, -10.0dB 0x1300004c, // 33, -10.5dB 0x12000048, // 34, -11.0dB 0x11000044, // 35, -11.5dB 0x10000040, // 36, -12.0dB 0x0f00003c,// 37, -12.5dB 0x0e400039,// 38, -13.0dB 0x0d800036,// 39, -13.5dB 0x0cc00033,// 40, -14.0dB 0x0c000030,// 41, -14.5dB 0x0b40002d,// 42, -15.0dB }; #endif #ifdef HW_ANT_SWITCH #define RXDVY_A_EN ((HW_DIV_ENABLE && !priv->pshare->rf_ft_var.antSw_select) ? 0x80 : 0) #define RXDVY_B_EN ((HW_DIV_ENABLE && priv->pshare->rf_ft_var.antSw_select) ? 0x80 : 0) #endif //3 ============================================================ //3 DIG related functions //3 ============================================================ int getIGIFor1RCCA(int value_IGI) { #define ONERCCA_LOW_TH 0x30 #define ONERCCA_LOW_DIFF 8 if (value_IGI < ONERCCA_LOW_TH) { if ((ONERCCA_LOW_TH - value_IGI) < ONERCCA_LOW_DIFF) return ONERCCA_LOW_TH; else return value_IGI + ONERCCA_LOW_DIFF; } else { return value_IGI; } } void set_DIG_state(struct rtl8192cd_priv *priv, int state) { int value_IGI; if (state) { priv->pshare->DIG_on = 1; priv->pshare->restore = 0; } else { priv->pshare->DIG_on = 0; if (priv->pshare->restore == 0) { if (priv->pshare->rf_ft_var.use_ext_lna == 1) value_IGI = 0x30; else value_IGI = 0x20; #if defined(HW_ANT_SWITCH) // wirte new initial gain index into regC50/C58 if (priv->pshare->rf_ft_var.one_path_cca == 0) { RTL_W8(0xc50, value_IGI | RXDVY_A_EN); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI | RXDVY_B_EN); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { RTL_W8(0xc50, value_IGI | RXDVY_A_EN); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, getIGIFor1RCCA(value_IGI) | RXDVY_B_EN); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { RTL_W8(0xc50, getIGIFor1RCCA(value_IGI) | RXDVY_A_EN); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI | RXDVY_B_EN); #endif } #else // Write IGI into HW if (priv->pshare->rf_ft_var.one_path_cca == 0) { RTL_W8(0xc50, value_IGI); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { RTL_W8(0xc50, value_IGI); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, getIGIFor1RCCA(value_IGI)); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { RTL_W8(0xc50, getIGIFor1RCCA(value_IGI)); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI); #endif } #endif priv->pshare->restore = 1; } #ifdef INTERFERENCE_CONTROL priv->pshare->phw->signal_strength = 0; #endif } } void DIG_process(struct rtl8192cd_priv *priv) { #define DEAD_POINT_TH 10000 #define DOWN_IG_HIT_TH 5 #define DEAD_POINT_HIT_TH 3 unsigned char value_IGI; signed char value8; #ifdef INTERFERENCE_CONTROL unsigned short thd0, thd1, thd2; #endif if (priv->pshare->DIG_on == 1) { if (priv->pshare->rf_ft_var.use_ext_lna == 1) { // priv->pshare->FA_upper = 0x42; priv->pshare->FA_upper = MIN_NUM(0x42, priv->pshare->rssi_min+36); priv->pshare->FA_lower = 0x30; } else { // Reset initial gain upper & lower bounds #ifdef DFS if (!priv->pmib->dot11DFSEntry.disable_DFS && (OPMODE & WIFI_AP_STATE) && (((priv->pmib->dot11RFEntry.dot11channel >= 52) && (priv->pmib->dot11RFEntry.dot11channel <= 64)) || ((priv->pmib->dot11RFEntry.dot11channel >= 100) && (priv->pmib->dot11RFEntry.dot11channel <= 140)))) priv->pshare->FA_upper = 0x24; else #endif { #ifdef INTERFERENCE_CONTROL priv->pshare->FA_lower = 0x20; if (priv->pshare->rssi_min != 0xFF) { // priv->pshare->FA_upper = 0x3E; if (priv->pshare->rssi_min > 30) priv->pshare->FA_lower = 0x24; else if (priv->pshare->rssi_min > 25) priv->pshare->FA_lower = 0x22; // limit upper bound to prevent the minimal signal sta from disconnect // if ((priv->pshare->rssi_min + 10) < priv->pshare->FA_upper) // priv->pshare->FA_upper = priv->pshare->rssi_min + 10; priv->pshare->FA_upper = MIN_NUM(0x3E, priv->pshare->rssi_min+20); thd0 = priv->pshare->threshold0; thd1 = priv->pshare->threshold1; thd2 = priv->pshare->threshold2; } else // before link { priv->pshare->FA_upper = 0x32; thd0 = 500; thd1 = 8000; thd2 = 10000; } #else if (priv->pmib->dot11RFEntry.tx2path) { if (priv->pmib->dot11BssType.net_work_type == WIRELESS_11B) priv->pshare->FA_upper = MIN_NUM(0x2A, priv->pshare->rssi_min+20); else priv->pshare->FA_upper = MIN_NUM(0x32, priv->pshare->rssi_min+20); } else priv->pshare->FA_upper = MIN_NUM(0x32, priv->pshare->rssi_min+20); priv->pshare->FA_lower = 0x20; if (priv->pshare->rssi_min > 30) priv->pshare->FA_lower = 0x24; else if (priv->pshare->rssi_min > 25) priv->pshare->FA_lower = 0x22; #endif } } // determine a new initial gain index according to the sumation of all FA counters as well as upper & lower bounds value8 = RTL_R8(0xc50); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) { if(priv->pshare->rf_ft_var.one_path_cca==2) value8 = RTL_R8(0xc58); } #endif value_IGI = (value8 & 0x7F); #if defined(CONFIG_RTL_NOISE_CONTROL_92C) if(priv->pshare->rf_ft_var.dnc_enable) if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; if(priv->pshare->rf_ft_var.use_ext_lna) { if( (priv->pshare->rssi_min > 50) ) { if((!priv->pshare->DNC_on) && (value_IGI >= priv->pshare->FA_upper) && (priv->pshare->FA_total_cnt > priv->pshare->threshold2)) { priv->pshare->DNC_on = 1; priv->ext_stats.tp_average_pre = tp_now; priv->pshare->FA_lower = 0x20; PHY_SetBBReg(priv, 0x870, bMaskDWord, RTL_R32(0x870)|BIT(5)|BIT(6)|BIT(21)|BIT(22)); #ifdef HW_ANT_SWITCH PHY_SetBBReg(priv, 0xc50, bMaskByte0, priv->pshare->FA_lower | RXDVY_A_EN); PHY_SetBBReg(priv, 0xc58, bMaskByte0, priv->pshare->FA_lower | RXDVY_B_EN); #else PHY_SetBBReg(priv, 0xc50, bMaskByte0, priv->pshare->FA_lower); PHY_SetBBReg(priv, 0xc58, bMaskByte0, priv->pshare->FA_lower); #endif } else if(priv->pshare->DNC_on ==1) { if(tp_now < priv->ext_stats.tp_average_pre + 2) { priv->pshare->DNC_on = 0; } else { priv->pshare->DNC_on =2; priv->ext_stats.tp_average_pre = tp_now; } } else if(priv->pshare->DNC_on >= 2 ) { if(( tp_now+10 < priv->ext_stats.tp_average_pre ) || (tp_now < 1) ) { priv->pshare->DNC_on = 0; } else if(priv->pshare->DNC_on<5) { priv->ext_stats.tp_average_pre = tp_now; ++priv->pshare->DNC_on; } } }else { priv->pshare->DNC_on = 0; } if( priv->pshare->DNC_on ) return; else PHY_SetBBReg(priv, 0x870, bMaskDWord, RTL_R32(0x870)& ~(BIT(5)|BIT(6)|BIT(21)|BIT(22))); } else { if( (priv->pshare->rssi_min > 40) && (value_IGI >= priv->pshare->FA_upper) ) { // unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; if((!priv->pshare->DNC_on) && (priv->pshare->FA_total_cnt > priv->pshare->threshold2)) { priv->pshare->DNC_on = 1; priv->ext_stats.tp_average_pre = tp_now; } else if(priv->pshare->DNC_on ==1) { if(tp_now < priv->ext_stats.tp_average_pre + 2) { priv->pshare->DNC_on = 0; } else { priv->pshare->DNC_on = 2; priv->ext_stats.tp_average_pre = tp_now; } } else if(priv->pshare->DNC_on >= 2 ) { if((tp_now +10 < priv->ext_stats.tp_average_pre ) || ((priv->ext_stats.tp_average_pre < 10) && (priv->pshare->FA_total_cnt < priv->pshare->threshold1))) { priv->pshare->DNC_on = 0; } else if(priv->pshare->DNC_on<6) { priv->ext_stats.tp_average_pre = tp_now; ++priv->pshare->DNC_on; } } if(priv->pshare->DNC_on) { priv->pshare->FA_upper = 0x3e; } }else { priv->pshare->DNC_on = 0; } } } #endif if ((priv->pshare->digDeadPoint == 0) && (priv->pshare->FA_total_cnt > DEAD_POINT_TH)) { if ((priv->pshare->digDeadPointHitCount > 0) && (priv->pshare->digDeadPointCandidate == value_IGI)) { priv->pshare->digDeadPointHitCount++; if (priv->pshare->digDeadPointHitCount == DEAD_POINT_HIT_TH) { priv->pshare->digDeadPoint = priv->pshare->digDeadPointCandidate; } } else { priv->pshare->digDeadPointCandidate = value_IGI; priv->pshare->digDeadPointHitCount = 1; } } #ifdef INTERFERENCE_CONTROL if (priv->pshare->FA_total_cnt < thd0) { #else if (priv->pshare->FA_total_cnt < priv->pshare->threshold0) { #endif priv->pshare->digDownCount++; if (priv->pshare->digDownCount > DOWN_IG_HIT_TH) { // Reset deadpoint hit count if ((priv->pshare->digDeadPoint == 0) && (priv->pshare->digDeadPointHitCount > 0) && (value_IGI == priv->pshare->digDeadPointCandidate)) priv->pshare->digDeadPointHitCount = 0; value_IGI--; // Check if the new value is dead point if ((priv->pshare->digDeadPoint > 0) && (value_IGI == priv->pshare->digDeadPoint)) value_IGI++; } #ifdef INTERFERENCE_CONTROL } else if (priv->pshare->FA_total_cnt < thd1) { #else } else if (priv->pshare->FA_total_cnt < priv->pshare->threshold1) { #endif value_IGI += 0; priv->pshare->digDownCount = 0; #ifdef INTERFERENCE_CONTROL } else if (priv->pshare->FA_total_cnt < thd2) { #else } else if (priv->pshare->FA_total_cnt < priv->pshare->threshold2) { #endif value_IGI++; priv->pshare->digDownCount = 0; #ifdef INTERFERENCE_CONTROL } else if (priv->pshare->FA_total_cnt >= thd2) { #else } else if (priv->pshare->FA_total_cnt >= priv->pshare->threshold2) { #endif value_IGI += 2; priv->pshare->digDownCount = 0; } else { priv->pshare->digDownCount = 0; } if (value_IGI > priv->pshare->FA_upper) value_IGI = priv->pshare->FA_upper; else if (value_IGI < priv->pshare->FA_lower) value_IGI = priv->pshare->FA_lower; #if defined(HW_ANT_SWITCH) // wirte new initial gain index into regC50/C58 if (priv->pshare->rf_ft_var.one_path_cca == 0) { RTL_W8(0xc50, value_IGI | RXDVY_A_EN); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI | RXDVY_B_EN); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { RTL_W8(0xc50, value_IGI | RXDVY_A_EN); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, getIGIFor1RCCA(value_IGI) | RXDVY_B_EN); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { RTL_W8(0xc50, getIGIFor1RCCA(value_IGI) | RXDVY_A_EN); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI| RXDVY_B_EN); #endif } #else // Write IGI into HW if (priv->pshare->rf_ft_var.one_path_cca == 0) { RTL_W8(0xc50, value_IGI); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { RTL_W8(0xc50, value_IGI); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, getIGIFor1RCCA(value_IGI)); #endif } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { RTL_W8(0xc50, getIGIFor1RCCA(value_IGI)); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, value_IGI); #endif } #endif } } void check_DIG_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength) { unsigned int dig_on = 0; if (OPMODE & WIFI_SITE_MONITOR) return; if ((rssi_strength > priv->pshare->rf_ft_var.digGoUpperLevel) && (rssi_strength < HP_LOWER+1) && (priv->pshare->phw->signal_strength != 2)) { #ifndef CONFIG_RTL_92D_SUPPORT if (priv->pshare->is_40m_bw) // RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D RTL_W8(0xc87, 0x30); else RTL_W8(0xc30, 0x44); #endif if (priv->pshare->phw->signal_strength != 3) dig_on++; priv->pshare->phw->signal_strength = 2; } else if ((rssi_strength > HP_LOWER+5) && (priv->pshare->phw->signal_strength != 3)) { #ifndef CONFIG_RTL_92D_SUPPORT if (priv->pshare->is_40m_bw) // RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D RTL_W8(0xc87, 0x30); else RTL_W8(0xc30, 0x44); #endif if (priv->pshare->phw->signal_strength != 2) dig_on++; priv->pshare->phw->signal_strength = 3; } else if (((rssi_strength < priv->pshare->rf_ft_var.digGoLowerLevel) && (priv->pshare->phw->signal_strength != 1)) || !priv->pshare->phw->signal_strength) { // DIG off // set_DIG_state(priv, 0); #ifndef CONFIG_RTL_92D_SUPPORT if (priv->pshare->is_40m_bw) //RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D RTL_W8(0xc87, 0x30); else RTL_W8(0xc30, 0x44); #endif priv->pshare->phw->signal_strength = 1; } if (dig_on) { // DIG on set_DIG_state(priv, 1); } //check_DC_TH_by_rssi(priv, rssi_strength); } void DIG_for_site_survey(struct rtl8192cd_priv *priv, int do_ss) { if (do_ss) { // DIG off set_DIG_state(priv, 0); } else { // DIG on #ifndef INTERFERENCE_CONTROL if (priv->pshare->phw->signal_strength > 1) #endif { set_DIG_state(priv, 1); } } } #ifdef INTERFERENCE_CONTROL void check_NBI_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength) { if (OPMODE & WIFI_SITE_MONITOR) return; if (priv->pshare->phw->nbi_filter_on) { if (rssi_strength < 20) { priv->pshare->phw->nbi_filter_on = 0; RTL_W16(rOFDM0_RxDSP, RTL_R16(rOFDM0_RxDSP) & ~ BIT(9)); // NBI off } } else { // NBI OFF previous if (rssi_strength > 25) { priv->pshare->phw->nbi_filter_on = 1; RTL_W16(rOFDM0_RxDSP, RTL_R16(rOFDM0_RxDSP) | BIT(9)); // NBI on } } } #endif /* * dynamic CCK CCA enhance by rssi */ void CCK_CCA_dynamic_enhance(struct rtl8192cd_priv *priv, unsigned char rssi_strength) { #if 1 unsigned int cck_fa = priv->pshare->FA_total_cnt; int rssi_thd = 30; if (rssi_strength == 0xff) { if (cck_fa < 1000) { if (priv->pshare->phw->CCK_CCA_enhanced != 2) { RTL_W8(0xa0a, 0x40); priv->pshare->phw->CCK_CCA_enhanced = 2; } } else { if (priv->pshare->phw->CCK_CCA_enhanced != 1) { RTL_W8(0xa0a, 0x83); priv->pshare->phw->CCK_CCA_enhanced = 1; } } return; } if (rssi_strength > rssi_thd+5) { if (priv->pshare->phw->CCK_CCA_enhanced != 0) { RTL_W8(0xa0a, 0xcd); priv->pshare->phw->CCK_CCA_enhanced = 0; } } else if (rssi_strength< rssi_thd) { if ((rssi_strength > 9) || (priv->assoc_num >1)) { if (priv->pshare->phw->CCK_CCA_enhanced != 1) { RTL_W8(0xa0a, 0x83); priv->pshare->phw->CCK_CCA_enhanced = 1; } } else { if(cck_fa<1000) { if (priv->pshare->phw->CCK_CCA_enhanced != 2) { RTL_W8(0xa0a, 0x40); priv->pshare->phw->CCK_CCA_enhanced = 2; } } else { if (priv->pshare->phw->CCK_CCA_enhanced != 1) { RTL_W8(0xa0a, 0x83); priv->pshare->phw->CCK_CCA_enhanced = 1; } } } } #else if (rssi_strength == 0xff) return; if (!priv->pshare->phw->CCK_CCA_enhanced && (rssi_strength < 30)) { priv->pshare->phw->CCK_CCA_enhanced = TRUE; RTL_W8(0xa0a, 0x83); } else if (priv->pshare->phw->CCK_CCA_enhanced && (rssi_strength > 35)) { priv->pshare->phw->CCK_CCA_enhanced = FALSE; RTL_W8(0xa0a, 0xcd); } #endif } //3 ============================================================ //3 Dynamic Tx Power / Power Tracking //3 ============================================================ #ifdef HIGH_POWER_EXT_PA void tx_power_control(struct rtl8192cd_priv *priv) { unsigned long x; int pwr_value = 0x10101010; if( priv->pshare->phw->signal_strength == 3 && priv->pshare->phw->lower_tx_power== 0) { SAVE_INT_AND_CLI(x); priv->pshare->phw->power_backup[0x00] = RTL_R32(rTxAGC_A_Rate18_06); priv->pshare->phw->power_backup[0x01] = RTL_R32(rTxAGC_A_Rate54_24); priv->pshare->phw->power_backup[0x02] = RTL_R32(rTxAGC_B_Rate18_06); priv->pshare->phw->power_backup[0x03] = RTL_R32(rTxAGC_B_Rate54_24); priv->pshare->phw->power_backup[0x04] = RTL_R32(rTxAGC_A_Mcs03_Mcs00); priv->pshare->phw->power_backup[0x05] = RTL_R32(rTxAGC_A_Mcs07_Mcs04); priv->pshare->phw->power_backup[0x06] = RTL_R32(rTxAGC_A_Mcs11_Mcs08); priv->pshare->phw->power_backup[0x07] = RTL_R32(rTxAGC_A_Mcs15_Mcs12); priv->pshare->phw->power_backup[0x08] = RTL_R32(rTxAGC_B_Mcs03_Mcs00); priv->pshare->phw->power_backup[0x09] = RTL_R32(rTxAGC_B_Mcs07_Mcs04); priv->pshare->phw->power_backup[0x0a] = RTL_R32(rTxAGC_B_Mcs11_Mcs08); priv->pshare->phw->power_backup[0x0b] = RTL_R32(rTxAGC_B_Mcs15_Mcs12); priv->pshare->phw->power_backup[0x0c] = RTL_R32(rTxAGC_A_CCK11_2_B_CCK11); priv->pshare->phw->power_backup[0x0d] = RTL_R32(rTxAGC_A_CCK1_Mcs32); priv->pshare->phw->power_backup[0x0e] = RTL_R32(rTxAGC_B_CCK5_1_Mcs32); RTL_W32(rTxAGC_A_Rate18_06, pwr_value); RTL_W32(rTxAGC_A_Rate54_24, pwr_value); RTL_W32(rTxAGC_B_Rate18_06, pwr_value); RTL_W32(rTxAGC_B_Rate54_24, pwr_value); RTL_W32(rTxAGC_A_Mcs03_Mcs00, pwr_value); RTL_W32(rTxAGC_A_Mcs07_Mcs04, pwr_value); RTL_W32(rTxAGC_A_Mcs11_Mcs08, pwr_value); RTL_W32(rTxAGC_A_Mcs15_Mcs12, pwr_value); RTL_W32(rTxAGC_B_Mcs03_Mcs00, pwr_value); RTL_W32(rTxAGC_B_Mcs07_Mcs04, pwr_value); RTL_W32(rTxAGC_B_Mcs11_Mcs08, pwr_value); RTL_W32(rTxAGC_B_Mcs15_Mcs12, pwr_value); RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, pwr_value); RTL_W32(rTxAGC_A_CCK1_Mcs32, (pwr_value & 0x0000ff00) | (priv->pshare->phw->power_backup[0x0d] &0xffff00ff)); RTL_W32(rTxAGC_B_CCK5_1_Mcs32, (pwr_value & 0xffffff00) | (priv->pshare->phw->power_backup[0x0e] &0x000000ff)); priv->pshare->phw->lower_tx_power = 1; RESTORE_INT(x); } else if( priv->pshare->phw->signal_strength != 3 && priv->pshare->phw->lower_tx_power) { SAVE_INT_AND_CLI(x); RTL_W32(rTxAGC_A_Rate18_06, priv->pshare->phw->power_backup[0x00]); RTL_W32(rTxAGC_A_Rate54_24, priv->pshare->phw->power_backup[0x01]); RTL_W32(rTxAGC_B_Rate18_06, priv->pshare->phw->power_backup[0x02]); RTL_W32(rTxAGC_B_Rate54_24, priv->pshare->phw->power_backup[0x03]); RTL_W32(rTxAGC_A_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x04]); RTL_W32(rTxAGC_A_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x05]); RTL_W32(rTxAGC_A_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x06]); RTL_W32(rTxAGC_A_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x07]); RTL_W32(rTxAGC_B_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x08]); RTL_W32(rTxAGC_B_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x09]); RTL_W32(rTxAGC_B_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x0a]); RTL_W32(rTxAGC_B_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x0b]); RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, priv->pshare->phw->power_backup[0x0c]); RTL_W32(rTxAGC_A_CCK1_Mcs32, priv->pshare->phw->power_backup[0x0d]); RTL_W32(rTxAGC_B_CCK5_1_Mcs32, priv->pshare->phw->power_backup[0x0e]); priv->pshare->phw->lower_tx_power = 0; RESTORE_INT(x); } } #endif int get_CCK_swing_index(struct rtl8192cd_priv *priv) { int TempCCk, index=12, i; short channel; #ifdef MP_TEST if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) channel=priv->pshare->working_channel; else #endif channel = (priv->pmib->dot11RFEntry.dot11channel); //Query CCK default setting From 0xa24 TempCCk = PHY_QueryBBReg(priv, rCCK0_TxFilter2, bMaskDWord)&bMaskCCK; TempCCk = cpu_to_le32(TempCCk); for(i=0 ; ipshare->rf_ft_var.mp_specific) channel=priv->pshare->working_channel; else #endif channel = (priv->pmib->dot11RFEntry.dot11channel); if(channel !=14) { RTL_W8( 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]); RTL_W8( 0xa23, CCKSwingTable_Ch1_Ch13[CCK_index][1]); RTL_W8( 0xa24, CCKSwingTable_Ch1_Ch13[CCK_index][2]); RTL_W8( 0xa25, CCKSwingTable_Ch1_Ch13[CCK_index][3]); RTL_W8( 0xa26, CCKSwingTable_Ch1_Ch13[CCK_index][4]); RTL_W8( 0xa27, CCKSwingTable_Ch1_Ch13[CCK_index][5]); RTL_W8( 0xa28, CCKSwingTable_Ch1_Ch13[CCK_index][6]); RTL_W8( 0xa29, CCKSwingTable_Ch1_Ch13[CCK_index][7]); } else{ RTL_W8( 0xa22, CCKSwingTable_Ch14[CCK_index][0]); RTL_W8( 0xa23, CCKSwingTable_Ch14[CCK_index][1]); RTL_W8( 0xa24, CCKSwingTable_Ch14[CCK_index][2]); RTL_W8( 0xa25, CCKSwingTable_Ch14[CCK_index][3]); RTL_W8( 0xa26, CCKSwingTable_Ch14[CCK_index][4]); RTL_W8( 0xa27, CCKSwingTable_Ch14[CCK_index][5]); RTL_W8( 0xa28, CCKSwingTable_Ch14[CCK_index][6]); RTL_W8( 0xa29, CCKSwingTable_Ch14[CCK_index][7]); } } unsigned char getThermalValue(struct rtl8192cd_priv *priv) { unsigned char ThermalValue; int sum=0, i=0; PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 0x60); while ((PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 1) > 0x1f) && ((i++) < 1000)) {//<20ms, test is in 20 us delay_us(20); } ThermalValue =(unsigned char)PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 1) & 0x01f; priv->pshare->Thermal_idx = (priv->pshare->Thermal_idx+1)%8; priv->pshare->Thermal_log[ priv->pshare->Thermal_idx ] = ThermalValue; for(i=0; i<8; i++) { if(!priv->pshare->Thermal_log[i]) return ThermalValue; sum += priv->pshare->Thermal_log[i]; } return (sum+4)>>3; } #ifdef _TRACKING_TABLE_FILE int get_tx_tracking_index(struct rtl8192cd_priv *priv, int channel, int i, int delta, int is_decrease, int is_CCK) { int index = 0; if(delta == 0) return 0; if(delta > index_mapping_NUM_MAX) delta = index_mapping_NUM_MAX; printk("\n\n_eric_tracking +++ channel = %d, i = %d, delta = %d, is_decrease = %d, is_CCK = %d\n", channel, i, delta, is_decrease, is_CCK); delta = delta - 1; if (channel > 14) { if(channel <= 99) { index = priv->pshare->txpwr_tracking_5GL[(i*2)+ is_decrease][delta]; } else if(channel <= 140) { index = priv->pshare->txpwr_tracking_5GM[(i*2)+ is_decrease][delta]; } else { index = priv->pshare->txpwr_tracking_5GH[(i*2)+ is_decrease][delta]; } } else { if(is_CCK) { index = priv->pshare->txpwr_tracking_2G_CCK[(i*2)+ is_decrease][delta]; } else { index = priv->pshare->txpwr_tracking_2G_OFDM[(i*2)+ is_decrease][delta]; } } printk("_eric_tracking +++ offset = %d\n\n", index); return index; } #endif #ifdef CONFIG_RTL_92C_SUPPORT #ifdef HIGH_POWER_EXT_PA void swingIndexRemap2(int *a, int b, int i) { u8 index_mapping_HighPower_92C[4][15] = { {0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 18, 18}, //2.4G, path A/MAC 0, decrease power {0, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22}, //2.4G, path A/MAC 0, increase power {0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 18, 18}, //2.4G, path A/MAC 0, decrease power {0, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23}, //2.4G, path A/MAC 0, increase power }; int d = RTL_ABS(*a, b); int offset = 0; if(i == 0) offset = 1; else offset = 3; if(*a < b ) { //printk("\n\n Increase Power !! \n\n"); *a = b - index_mapping_HighPower_92C[offset][d]; } else { //printk("\n\n Decrease Power !! \n\n"); offset = offset - 1; *a = b + index_mapping_HighPower_92C[offset][d]; } //printk("\n\ a = %d, b = %d, offset = %d, d = %d, diff = %d \n\n", //*a, b, offset, d, index_mapping_HighPower_92C[offset][d]); } void swingIndexRemap(int *a, int b) { int d = (RTL_ABS(*a, b) *3)>>1; if(*a < b ) *a = b - d; else *a = b + d; } #endif void tx_power_tracking(struct rtl8192cd_priv *priv) { unsigned char ThermalValue = 0, delta, delta_LCK, delta_IQK; int ele_A, ele_D, value32, X, Y, ele_C; int OFDM_index[2]={0,0}, CCK_index; int i = 0; char is2T = ((GET_CHIP_VER(priv) == VERSION_8192C) ?1 :0); unsigned char TxPwrLevel[2]; unsigned char channel, OFDM_min_index = 6, rf=1; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur #ifdef MP_TEST if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { channel=priv->pshare->working_channel; if(priv->pshare->mp_txpwr_tracking == FALSE) return; } else #endif { channel = (priv->pmib->dot11RFEntry.dot11channel); } ThermalValue = getThermalValue(priv); rf += is2T; if(ThermalValue) { if(!priv->pshare->ThermalValue) { priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; priv->pshare->ThermalValue_LCK = ThermalValue; priv->pshare->ThermalValue_IQK = ThermalValue; //Query OFDM path A default setting ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; for(i=0; ipshare->OFDM_index[0] = i; priv->pshare->OFDM_index0[0] = i; break; } } //Query OFDM path B default setting if(is2T) { ele_D = PHY_QueryBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D; for(i=0; ipshare->OFDM_index[1] = i; priv->pshare->OFDM_index0[1] = i; break; } } } priv->pshare->CCK_index = get_CCK_swing_index(priv); priv->pshare->CCK_index0 = priv->pshare->CCK_index; } delta = RTL_ABS(ThermalValue, priv->pshare->ThermalValue); delta_LCK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_LCK); delta_IQK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_IQK); // printk("Readback Thermal Meter = 0x%lx pre thermal meter 0x%lx EEPROMthermalmeter 0x%lx delta 0x%lx delta_LCK 0x%lx delta_IQK 0x%lx\n", // ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther, delta, delta_LCK, delta_IQK); if(delta_LCK > 1) { priv->pshare->ThermalValue_LCK = ThermalValue; #ifdef MP_TEST if(priv->pshare->rf_ft_var.mp_specific) { if((OPMODE & WIFI_MP_CTX_BACKGROUND) && !(OPMODE & WIFI_MP_CTX_PACKET)) printk("NOT do LCK during ctx !!!! \n"); else PHY_LCCalibrate(priv); } else #endif PHY_LCCalibrate(priv); } if(delta > 0) { if(ThermalValue > priv->pshare->ThermalValue) { for(i = 0; i < rf; i++) priv->pshare->OFDM_index[i] -= delta; priv->pshare->CCK_index -= delta; } else { for(i = 0; i < rf; i++) priv->pshare->OFDM_index[i] += delta; priv->pshare->CCK_index += delta; } if(ThermalValue > priv->pmib->dot11RFEntry.ther) { for(i = 0; i < rf; i++) OFDM_index[i] = priv->pshare->OFDM_index[i]+1; CCK_index = priv->pshare->CCK_index+1; } else { for(i = 0; i < rf; i++) OFDM_index[i] = priv->pshare->OFDM_index[i]; CCK_index = priv->pshare->CCK_index; } #ifdef MP_TEST if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { TxPwrLevel[0] = priv->pshare->mp_txpwr_patha; TxPwrLevel[1] = priv->pshare->mp_txpwr_pathb; } else #endif { TxPwrLevel[0] = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel-1]; TxPwrLevel[1] = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel-1]; if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { unsigned char offset = (priv->pmib->dot11RFEntry.pwrdiffHT20[channel-1] & 0x0f); TxPwrLevel[0] = COUNT_SIGN_OFFSET(TxPwrLevel[0], offset); offset = ((priv->pmib->dot11RFEntry.pwrdiffOFDM[channel-1] & 0xf0) >> 4); TxPwrLevel[1] = COUNT_SIGN_OFFSET(TxPwrLevel[1], offset); } } // printk("TxPwrLevel[0]=%d, TxPwrLevel[1]=%d\n", TxPwrLevel[0], TxPwrLevel[1]); for(i = 0; i < rf; i++) { if(/*TxPwrLevel[i] >=0 &&*/ TxPwrLevel[i] <=26) { if(ThermalValue > priv->pmib->dot11RFEntry.ther) { if (delta < 5) OFDM_index[i] -= 1; else OFDM_index[i] -= 2; } else if(delta > 5 && ThermalValue < priv->pmib->dot11RFEntry.ther) { OFDM_index[i] += 1; } } else if (TxPwrLevel[i] >= 27 && TxPwrLevel[i] <= 32 && ThermalValue > priv->pmib->dot11RFEntry.ther) { if (delta < 5) OFDM_index[i] -= 1; else OFDM_index[i] -= 2; } else if (TxPwrLevel[i] >= 32 && TxPwrLevel[i] <= 38 && ThermalValue > priv->pmib->dot11RFEntry.ther && delta > 5) { OFDM_index[i] -= 1; } #ifdef _TRACKING_TABLE_FILE { int d = 0; OFDM_index[i] = priv->pshare->OFDM_index[i]; d = RTL_ABS(OFDM_index[i], priv->pshare->OFDM_index0[i]); if(OFDM_index[i] < priv->pshare->OFDM_index0[i]) { OFDM_index[i] = priv->pshare->OFDM_index0[i] - get_tx_tracking_index(priv, channel, i, d, 0, 0); } else { OFDM_index[i] = priv->pshare->OFDM_index0[i] + get_tx_tracking_index(priv, channel, i, d, 1, 0); } } #else #ifdef HIGH_POWER_EXT_PA if (priv->pshare->rf_ft_var.use_ext_pa) { OFDM_index[i] = priv->pshare->OFDM_index[i]; swingIndexRemap2(&OFDM_index[i], priv->pshare->OFDM_index0[i], i); //Modify HP tracking table, from Arthur 2012.02.13 //swingIndexRemap(&OFDM_index[i], priv->pshare->OFDM_index0[i]); } #endif #endif if(OFDM_index[i] > OFDM_TABLE_SIZE-1) OFDM_index[i] = OFDM_TABLE_SIZE-1; else if (OFDM_index[i] < OFDM_min_index) OFDM_index[i] = OFDM_min_index; } i=0; { if(/*TxPwrLevel[i] >=0 &&*/ TxPwrLevel[i] <=26) { if(ThermalValue > priv->pmib->dot11RFEntry.ther) { if (delta < 5) CCK_index -= 1; else CCK_index -= 2; } else if(delta > 5 && ThermalValue < priv->pmib->dot11RFEntry.ther) { CCK_index += 1; } } else if (TxPwrLevel[i] >= 27 && TxPwrLevel[i] <= 32 && ThermalValue > priv->pmib->dot11RFEntry.ther) { if (delta < 5) CCK_index -= 1; else CCK_index -= 2; } else if (TxPwrLevel[i] >= 32 && TxPwrLevel[i] <= 38 && ThermalValue > priv->pmib->dot11RFEntry.ther && delta > 5) { CCK_index -= 1; } #ifdef _TRACKING_TABLE_FILE { int d = 0; CCK_index = priv->pshare->CCK_index; d = RTL_ABS(CCK_index, priv->pshare->CCK_index0); if(CCK_index < priv->pshare->CCK_index0) { CCK_index = priv->pshare->CCK_index0 - get_tx_tracking_index(priv, channel, i, d, 0, 1); } else { CCK_index = priv->pshare->CCK_index0 + get_tx_tracking_index(priv, channel, i, d, 1, 1); } } #else #ifdef HIGH_POWER_EXT_PA if (priv->pshare->rf_ft_var.use_ext_pa) { CCK_index = priv->pshare->CCK_index; swingIndexRemap2( &CCK_index, priv->pshare->CCK_index0, i); //Modify HP tracking table, from Arthur 2012.02.13 //swingIndexRemap( &CCK_index, priv->pshare->CCK_index0); } #endif #endif if(CCK_index > CCK_TABLE_SIZE-1) CCK_index = CCK_TABLE_SIZE-1; else if (CCK_index < 0) CCK_index = 0; } //Adujst OFDM Ant_A according to IQK result ele_D = (OFDMSwingTable[(unsigned int)OFDM_index[0]] & 0xFFC00000)>>22; X = priv->pshare->RegE94; Y = priv->pshare->RegE9C; if(X != 0) { if ((X & 0x00000200) != 0) X = X | 0xFFFFFC00; ele_A = ((X * ele_D)>>8)&0x000003FF; //new element C = element D x Y if ((Y & 0x00000200) != 0) Y = Y | 0xFFFFFC00; ele_C = ((Y * ele_D)>>8)&0x000003FF; //wirte new elements A, C, D to regC80 and regC94, element B is always 0 value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32); value32 = (ele_C&0x000003C0)>>6; PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32); value32 = ((X * ele_D)>>7)&0x01; PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32); } else { PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned int)OFDM_index[0]]); PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00); PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00); } set_CCK_swing_index(priv, CCK_index); if(is2T) { ele_D = (OFDMSwingTable[(unsigned int)OFDM_index[1]] & 0xFFC00000)>>22; X = priv->pshare->RegEB4; Y = priv->pshare->RegEBC; if(X != 0) { if ((X & 0x00000200) != 0) //consider minus X = X | 0xFFFFFC00; ele_A = ((X * ele_D)>>8)&0x000003FF; //new element C = element D x Y if ((Y & 0x00000200) != 0) Y = Y | 0xFFFFFC00; ele_C = ((Y * ele_D)>>8)&0x00003FF; //wirte new elements A, C, D to regC88 and regC9C, element B is always 0 value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A; PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); value32 = (ele_C&0x000003C0)>>6; PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32); value32 = ((X * ele_D)>>7)&0x01; PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32); } else { PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned int)OFDM_index[1]]); PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00); PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00); } } } if(delta_IQK > 3) { priv->pshare->ThermalValue_IQK = ThermalValue; #ifdef MP_TEST if(priv->pshare->rf_ft_var.mp_specific) { if((OPMODE & WIFI_MP_CTX_BACKGROUND) && !(OPMODE & WIFI_MP_CTX_PACKET)) printk("NOT do IQK during ctx !!!! \n"); else PHY_IQCalibrate(priv); } else #endif PHY_IQCalibrate(priv); } //update thermal meter value priv->pshare->ThermalValue = ThermalValue; } } #endif #ifdef RX_GAIN_TRACK_92D static void rx_gain_tracking_92D(struct rtl8192cd_priv *priv) { u8 index_mapping[Rx_index_mapping_NUM] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x04, 0x03, 0x02 }; u8 eRFPath, curMaxRFPath; u32 u4tmp; u4tmp = (index_mapping[(priv->pmib->dot11RFEntry.ther - priv->pshare->ThermalValue_RxGain)]) << 12; DEBUG_INFO("===>%s interface %d Rx Gain %x\n", __FUNCTION__, priv->pshare->wlandev_idx, u4tmp); if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) curMaxRFPath = RF92CD_PATH_B; else curMaxRFPath = RF92CD_PATH_MAX; for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) PHY_SetRFReg(priv, eRFPath, 0x3C, bMask20Bits, (priv->pshare->RegRF3C[eRFPath]&(~(0xF000)))|u4tmp); }; #endif #ifdef CONFIG_RTL_92D_SUPPORT void getDeltaValue(struct rtl8192cd_priv *priv) { unsigned int tempval[2]; tempval[0] = priv->pmib->dot11RFEntry.deltaIQK; tempval[1] = priv->pmib->dot11RFEntry.deltaLCK; switch(tempval[0]) { case 0: tempval[0] = 5; break; case 1: tempval[0] = 4; break; case 2: tempval[0] = 3; break; case 3: default: tempval[0] = 0; break; } switch(tempval[1]) { case 0: tempval[1] = 4; break; case 1: tempval[1] = 3; break; case 2: tempval[1] = 2; break; case 3: default: tempval[1] = 0; break; } priv->pshare->Delta_IQK = tempval[0]; priv->pshare->Delta_LCK = tempval[1]; } void tx_power_tracking_92D(struct rtl8192cd_priv *priv) { u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, index[2], offset, ThermalValue_AVG_count = 0; u32 ThermalValue_AVG = 0; int ele_A, ele_D, X, value32, Y, ele_C; char OFDM_index[2], CCK_index=0; int i = 0; char is2T = ((priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) ?1 :0); u8 OFDM_min_index = 6, OFDM_min_index_internalPA = 5, rf=1, channel; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur u1Byte OFDM_min_index = 6, rf; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur u8 index_mapping[5][index_mapping_NUM] = { {0, 1, 3, 6, 8, 9, //5G, path A/MAC 0, decrease power 11, 13, 14, 16, 17, 18, 18}, {0, 2, 4, 5, 7, 10, //5G, path A/MAC 0, increase power 12, 14, 16, 18, 18, 18, 18}, {0, 2, 3, 6, 8, 9, //5G, path B/MAC 1, decrease power 11, 13, 14, 16, 17, 18, 18}, {0, 2, 4, 5, 7, 10, //5G, path B/MAC 1, increase power 13, 16, 16, 18, 18, 18, 18}, {0, 1, 2, 3, 4, 5, //2.4G, for decreas power 6, 7, 7, 8, 9, 10, 10}, }; #if defined(RTL8192D_INT_PA) u8 index_mapping_internalPA[8][index_mapping_NUM] = { {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch36-64, decrease power 9, 11, 13, 15, 16, 16, 16}, {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch36-64, increase power 9, 11, 13, 15, 16, 18, 20}, {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch100-165, decrease power 9, 11, 13, 15, 16, 16, 16}, {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch100-165, increase power 9, 11, 13, 15, 16, 18, 20}, {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch36-64, decrease power 9, 11, 13, 15, 16, 16, 16}, {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch36-64, increase power 9, 11, 13, 15, 16, 18, 20}, {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch100-165, decrease power 9, 11, 13, 15, 16, 16, 16}, {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch100-165, increase power 9, 11, 13, 15, 16, 18, 20}, }; u8 bInteralPA[2]; #endif #ifdef DPK_92D short index_mapping_DPK[4][index_mapping_DPK_NUM]={ {0, 0, 1, 2, 2, //path A current thermal > PG thermal 3, 4, 5, 5, 6, 7, 7, 8, 9, 9}, {0, 0, -1, -2, -3, //path A current thermal < PG thermal -3, -4, -5, -6, -6, -7, -8, -9, -9, -10}, {0, 0, 1, 2, 2, //path B current thermal > PG thermal 3, 4, 5, 5, 6, 7, 7, 8, 9, 9}, {0, 0, -1, -2, -3, //path B current thermal < PG thermal -3, -4, -5, -6, -6, -7, -8, -9, -9, -10} }; u8 delta_DPK; short index_DPK[2] = { 0xb68, 0xb6c }, value_DPK, value_DPK_shift; int j; if(priv->pshare->bDPKworking) { DEBUG_INFO("DPK in progress abort tx power tracking \n"); return; } #endif #ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 u8 index_mapping_HighPower_PA[12][index_mapping_NUM] = { {0, 2, 3, 4, 7, 8, 10, 12, 13, 15, 16, 17, 18}, //5G, path A/MAC 0, ch36-64, decrease power {0, 2, 4, 7, 8, 10, 11, 15, 17, 19, 21, 23, 23}, //5G, path A/MAC 0, ch36-64, increase power {0, 4, 5, 8, 9, 11, 14, 15, 16, 17, 18, 19, 20}, //5G, path A/MAC 0, ch100-140, decrease power {0, 2, 4, 5, 7, 9, 13, 15, 19, 21, 22, 23, 23}, //5G, path A/MAC 0, ch100-140, increase power {0, 4, 5, 8, 9, 11, 14, 15, 17, 18, 19, 20, 21}, //5G, path A/MAC 0, ch149-165, decrease power {0, 2, 4, 6, 8, 10, 14, 16, 19, 21, 22, 24, 24}, //5G, path A/MAC 0, ch149-165, increase power {0, 4, 5, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17}, //5G, path B/MAC 1, ch36-64, decrease power {0, 2, 4, 7, 8, 10, 11, 15, 17, 19, 21, 23, 23}, //5G, path B/MAC 1, ch36-64, increase power {0, 3, 4, 6, 7, 9, 12, 13, 14, 15, 17, 18, 19}, //5G, path B/MAC 1, ch100-140, decrease power {0, 2, 4, 5, 7, 9, 13, 15, 19, 21, 22, 23, 23}, //5G, path B/MAC 1, ch100-140, increase power {0, 3, 4, 6, 7, 9, 12, 13, 15, 16, 17, 18, 19}, //5G, path B/MAC 1, ch149-165, decrease power {0, 3, 5, 7, 9, 11, 13, 17, 19, 21, 22, 23, 23}, //5G, path B/MAC 1, ch149-165, increase power }; #endif #ifdef MP_TEST if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { channel=priv->pshare->working_channel; if(priv->pshare->mp_txpwr_tracking == FALSE) return; } else #endif { channel = (priv->pmib->dot11RFEntry.dot11channel); } if (priv->pshare->pwr_trk_ongoing==0) { PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, bMask20Bits, 0x30000); priv->pshare->pwr_trk_ongoing = 1; return; }else{ ThermalValue =(unsigned char)PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, 0xf800, 1); priv->pshare->pwr_trk_ongoing = 0; #ifdef DPK_92D priv->pshare->ThermalValue_DPKtrack = ThermalValue; #endif } DEBUG_INFO("Readback Thermal Meter = 0x%lx pre thermal meter 0x%lx EEPROMthermalmeter 0x%lx\n", ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther); if(is2T) rf = 2; else rf = 1; if (ThermalValue) { //Query OFDM path A default setting ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; for(i=0; ipshare->OFDM_index0[0] = i; DEBUG_INFO("Initial pathA ele_D reg0x%x = 0x%lx, OFDM_index=0x%x\n", rOFDM0_XATxIQImbalance, ele_D, priv->pshare->OFDM_index0[0]); break; } } //Query OFDM path B default setting if(is2T) { ele_D = PHY_QueryBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D; for(i=0; ipshare->OFDM_index0[1] = i; DEBUG_INFO("Initial pathB ele_D reg0x%x = 0x%lx, OFDM_index=0x%x\n", rOFDM0_XBTxIQImbalance, ele_D, priv->pshare->OFDM_index0[1]); break; } } } if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { priv->pshare->CCK_index0 = get_CCK_swing_index(priv); } else { priv->pshare->CCK_index0 = 12; } if(!priv->pshare->ThermalValue) { priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; priv->pshare->ThermalValue_LCK = ThermalValue; priv->pshare->ThermalValue_IQK = ThermalValue; #ifdef RX_GAIN_TRACK_92D priv->pshare->ThermalValue_RxGain = priv->pmib->dot11RFEntry.ther; #endif #ifdef DPK_92D priv->pshare->ThermalValue_DPK = ThermalValue; #endif for(i = 0; i < rf; i++) priv->pshare->OFDM_index[i] = priv->pshare->OFDM_index0[i]; priv->pshare->CCK_index = priv->pshare->CCK_index0; } //calculate average thermal meter { priv->pshare->Thermal_log[priv->pshare->Thermal_idx] = ThermalValue; priv->pshare->Thermal_idx = (priv->pshare->Thermal_idx+1)%8; for(i=0; i<8; i++) { if(priv->pshare->Thermal_log[i]) { ThermalValue_AVG += priv->pshare->Thermal_log[i]; ThermalValue_AVG_count++; } } if(ThermalValue_AVG_count) ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count); } delta = RTL_ABS(ThermalValue, priv->pshare->ThermalValue); delta_LCK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_LCK); delta_IQK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_IQK); // printk("Readback Thermal Meter = 0x%lx pre thermal meter 0x%lx EEPROMthermalmeter 0x%lx delta 0x%lx delta_LCK 0x%lx delta_IQK 0x%lx\n", // ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther, delta, delta_LCK, delta_IQK); getDeltaValue(priv); #ifdef DPK_92D if(priv->pshare->bDPKstore) { priv->pshare->ThermalValue_DPK = ThermalValue; delta_DPK = 0; for(j = 0; j < rf; j++) { if(priv->pshare->ThermalValue_DPKstore > priv->pmib->dot11RFEntry.ther) value_DPK_shift = index_mapping_DPK[j*2][priv->pshare->ThermalValue_DPKstore- priv->pmib->dot11RFEntry.ther]; else value_DPK_shift = index_mapping_DPK[j*2+1][priv->pmib->dot11RFEntry.ther- priv->pshare->ThermalValue_DPKstore]; for(i = 0; i < index_mapping_DPK_NUM; i++) { priv->pshare->index_mapping_DPK_current[j*2][i] = index_mapping_DPK[j*2][i]-value_DPK_shift; priv->pshare->index_mapping_DPK_current[j*2+1][i] = index_mapping_DPK[j*2+1][i]-value_DPK_shift; } } } else { delta_DPK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_DPK); } for(j = 0; j < rf; j++) { if(!priv->pshare->bDPKdone[j]) priv->pshare->OFDM_min_index_internalPA_DPK[j] = 0; } #endif #if 1 if ((delta_LCK > priv->pshare->Delta_LCK) && (priv->pshare->Delta_LCK != 0)) { priv->pshare->ThermalValue_LCK = ThermalValue; PHY_LCCalibrate_92D(priv); } #endif if(delta > 0 #ifdef DPK_92D ||(priv->pshare->bDPKstore) #endif ){ if(delta == 0 && priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) goto TxPowerDPK; #ifdef DPK_92D if(priv->pshare->bDPKstore) priv->pshare->bDPKstore = FALSE; #endif delta = RTL_ABS(ThermalValue, priv->pmib->dot11RFEntry.ther); //calculate new OFDM / CCK offset { if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ #ifdef _TRACKING_TABLE_FILE if(ThermalValue > priv->pmib->dot11RFEntry.ther) { for(i = 0; i < rf; i++) OFDM_index[i] = priv->pshare->OFDM_index[i] - get_tx_tracking_index(priv, channel, i, delta, 0, 0); CCK_index = priv->pshare->CCK_index - get_tx_tracking_index(priv, channel, 0, delta, 0, 1); } else { for(i = 0; i < rf; i++) OFDM_index[i] = priv->pshare->OFDM_index[i] + get_tx_tracking_index(priv, channel, i, delta, 1, 0); CCK_index = priv->pshare->CCK_index + get_tx_tracking_index(priv, channel, i, delta, 1, 1); } #else offset = 4; if(delta > index_mapping_NUM-1) index[0] = index_mapping[offset][index_mapping_NUM-1]; else index[0] = index_mapping[offset][delta]; if(ThermalValue > priv->pmib->dot11RFEntry.ther) { for(i = 0; i < rf; i++) OFDM_index[i] = priv->pshare->OFDM_index[i] - delta; CCK_index = priv->pshare->CCK_index - delta; } else { for(i = 0; i < rf; i++) OFDM_index[i] = priv->pshare->OFDM_index[i] + index[0]; CCK_index = priv->pshare->CCK_index + index[0]; } #endif } else if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { for(i = 0; i < rf; i++){ #if defined(RTL8192D_INT_PA) if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx==1) //MAC 1 5G bInteralPA[i] = priv->pshare->phw->InternalPA5G[1]; else bInteralPA[i] = priv->pshare->phw->InternalPA5G[i]; if(bInteralPA[i]) { if(priv->pshare->wlandev_idx == 1 || i == 1/*rf*/) offset = 4; else offset = 0; if(channel >= 100 && channel <= 165) offset += 2; } else #endif { if(priv->pshare->wlandev_idx == 1 || i == 1) offset = 2; else offset = 0; } #ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 if(i == 0) { if(channel <= 99) offset = 0; else if(channel <= 140) offset = 2; else offset = 4; } else { if(channel <= 99) offset = 6; else if(channel <= 140) offset = 8; else offset = 10; } #endif if(ThermalValue > priv->pmib->dot11RFEntry.ther) //set larger Tx power offset++; #if defined(RTL8192D_INT_PA) if(bInteralPA[i]) { if(delta > index_mapping_NUM-1) index[i] = index_mapping_internalPA[offset][index_mapping_NUM-1]; else index[i] = index_mapping_internalPA[offset][delta]; } else #endif { if(delta > index_mapping_NUM-1) index[i] = index_mapping[offset][index_mapping_NUM-1]; else index[i] = index_mapping[offset][delta]; } #ifdef _TRACKING_TABLE_FILE { if(ThermalValue > priv->pmib->dot11RFEntry.ther) index[i] = get_tx_tracking_index(priv, channel, i, delta, 0, 0); else index[i] = get_tx_tracking_index(priv, channel, i, delta, 1, 0); } #else #ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 { if(delta > index_mapping_NUM-1) index[i] = index_mapping_HighPower_PA[offset][index_mapping_NUM-1]; else index[i] = index_mapping_HighPower_PA[offset][delta]; //printk("\n\n offset = %d delta = %d \n", offset, delta); //printk("index[%d]= %d\n\n", i, index[i]); } #endif #endif if(ThermalValue > priv->pmib->dot11RFEntry.ther) //set larger Tx power { #if 0 if(bInteralPA[i] && ThermalValue > 0x12) index[i] = ((delta/2)*3+(delta%2)); #endif OFDM_index[i] = priv->pshare->OFDM_index[i] -index[i]; } else { OFDM_index[i] = priv->pshare->OFDM_index[i] + index[i]; } } } if(is2T) { DEBUG_INFO("temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", priv->pshare->OFDM_index[0], priv->pshare->OFDM_index[1], priv->pshare->CCK_index); } else { DEBUG_INFO("temp OFDM_A_index=0x%x, CCK_index=0x%x\n", priv->pshare->OFDM_index[0], priv->pshare->CCK_index); } for(i = 0; i < rf; i++) { if(OFDM_index[i] > OFDM_TABLE_SIZE_92D-1) { OFDM_index[i] = OFDM_TABLE_SIZE_92D-1; } else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { if (OFDM_index[i] < (OFDM_min_index_internalPA)) OFDM_index[i] = (OFDM_min_index_internalPA); } else if(bInteralPA[i]) { #ifdef DPK_92D if (OFDM_index[i] < (OFDM_min_index_internalPA+ priv->pshare->OFDM_min_index_internalPA_DPK[i])) { priv->pshare->TxPowerLevelDPK[i] = OFDM_min_index_internalPA+ priv->pshare->OFDM_min_index_internalPA_DPK[i]-OFDM_index[i]; OFDM_index[i] = (OFDM_min_index_internalPA+ priv->pshare->OFDM_min_index_internalPA_DPK[i]); } else { priv->pshare->TxPowerLevelDPK[i] = 0; } #else if (OFDM_index[i] < (OFDM_min_index_internalPA)) { OFDM_index[i] = (OFDM_min_index_internalPA); } #endif } else if(OFDM_index[i] < OFDM_min_index) { #ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 #else OFDM_index[i] = OFDM_min_index; #endif } } if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ if(CCK_index > CCK_TABLE_SIZE_92D-1) CCK_index = CCK_TABLE_SIZE_92D-1; else if (CCK_index < 0) CCK_index = 0; } if(is2T) { DEBUG_INFO("new OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", OFDM_index[0], OFDM_index[1], CCK_index); } else { DEBUG_INFO("new OFDM_A_index=0x%x, CCK_index=0x%x\n", OFDM_index[0], CCK_index); } } //Config by SwingTable { //Adujst OFDM Ant_A according to IQK result ele_D = (OFDMSwingTable_92D[OFDM_index[0]] & 0xFFC00000)>>22; X = priv->pshare->RegE94; Y = priv->pshare->RegE9C; if(X != 0 && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)){ if ((X & 0x00000200) != 0) X = X | 0xFFFFFC00; ele_A = ((X * ele_D)>>8)&0x000003FF; //new element C = element D x Y if ((Y & 0x00000200) != 0) Y = Y | 0xFFFFFC00; ele_C = ((Y * ele_D)>>8)&0x000003FF; //wirte new elements A, C, D to regC80 and regC94, element B is always 0 value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32); value32 = (ele_C&0x000003C0)>>6; PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32); value32 = ((X * ele_D)>>7)&0x01; PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32); } else { PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable_92D[OFDM_index[0]]); PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00); PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00); #ifdef MP_TEST if ((priv->pshare->rf_ft_var.mp_specific) && (!is2T)) { unsigned char str[50]; sprintf(str, "patha=%d,pathb=%d", priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); mp_set_tx_power(priv, str); } #endif } DEBUG_INFO("TxPwrTracking for interface %d path A: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x\n", priv->pshare->wlandev_idx, X, Y, ele_A, ele_C, ele_D); if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { //Adjust CCK according to IQK result set_CCK_swing_index(priv, CCK_index); } if(is2T) { ele_D = (OFDMSwingTable_92D[OFDM_index[1]] & 0xFFC00000)>>22; //new element A = element D x X X = priv->pshare->RegEB4; Y = priv->pshare->RegEBC; if(X != 0 && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)){ if ((X & 0x00000200) != 0) //consider minus X = X | 0xFFFFFC00; ele_A = ((X * ele_D)>>8)&0x000003FF; //new element C = element D x Y if ((Y & 0x00000200) != 0) Y = Y | 0xFFFFFC00; ele_C = ((Y * ele_D)>>8)&0x00003FF; //wirte new elements A, C, D to regC88 and regC9C, element B is always 0 value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A; PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); value32 = (ele_C&0x000003C0)>>6; PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32); value32 = ((X * ele_D)>>7)&0x01; PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32); } else{ PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable_92D[OFDM_index[1]]); PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00); PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00); #ifdef MP_TEST if ((priv->pshare->rf_ft_var.mp_specific) ) { unsigned char str[50]; sprintf(str, "patha=%d,pathb=%d", priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); mp_set_tx_power(priv, str); } #endif } DEBUG_INFO("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x\n", X, Y, ele_A, ele_C, ele_D); } DEBUG_INFO("TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n", PHY_QueryBBReg(priv, 0xc80, bMaskDWord), PHY_QueryBBReg(priv, 0xc94, bMaskDWord), PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x24, bMask20Bits,1)); } } TxPowerDPK: #ifdef DPK_92D { char bNOPG = FALSE; unsigned char pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel-1]; if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel-1]; #ifdef CONFIG_RTL_92D_DMDP if ((priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY) && (priv->pshare->wlandev_idx == 1) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; if (pwrlevelHT40_1S_A == 0) bNOPG = TRUE; #endif //for DPK if(delta_DPK > 0 && !bNOPG /*&& pHalData->bDPKdone*/) { for(i = 0; i < rf; i++) { if(bInteralPA[i] && priv->pshare->bDPKdone[i]) { if(ThermalValue > priv->pmib->dot11RFEntry.ther) value_DPK = priv->pshare->index_mapping_DPK_current[i*2][ThermalValue-priv->pmib->dot11RFEntry.ther]; else value_DPK = priv->pshare->index_mapping_DPK_current[i*2+1][priv->pmib->dot11RFEntry.ther-ThermalValue]; PHY_SetBBReg(priv, index_DPK[i], 0x7c00, value_DPK); } } priv->pshare->ThermalValue_DPK = ThermalValue; } } #endif priv->pshare->pwr_trk_ongoing = 0; #if 1 if ((delta_IQK > priv->pshare->Delta_IQK) && (priv->pshare->Delta_IQK != 0)) { priv->pshare->ThermalValue_IQK = ThermalValue; PHY_IQCalibrate(priv); } #endif #ifdef RX_GAIN_TRACK_92D if(priv->pmib->dot11RFEntry.ther && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) && (ThermalValue < priv->pmib->dot11RFEntry.ther)) { priv->pshare->ThermalValue_RxGain = ThermalValue; rx_gain_tracking_92D(priv); } #endif //update thermal meter value priv->pshare->ThermalValue = ThermalValue; } } #endif //3 ============================================================ //3 EDCA Turbo //3 ============================================================ void init_EDCA_para(struct rtl8192cd_priv *priv, int mode) { static unsigned int slot_time, VO_TXOP, VI_TXOP, sifs_time; struct ParaRecord EDCA[4]; #ifdef RTL_MANUAL_EDCA //unsigned char acm_bitmap; #endif slot_time = 20; sifs_time = 10; if (mode & WIRELESS_11N) sifs_time = 16; #ifdef RTL_MANUAL_EDCA if( priv->pmib->dot11QosEntry.ManualEDCA ) { memset(EDCA, 0, 4*sizeof(struct ParaRecord)); if( OPMODE & WIFI_AP_STATE ) memcpy(EDCA, priv->pmib->dot11QosEntry.AP_manualEDCA, 4*sizeof(struct ParaRecord)); else memcpy(EDCA, priv->pmib->dot11QosEntry.STA_manualEDCA, 4*sizeof(struct ParaRecord)); if ((mode & WIRELESS_11N) || (mode & WIRELESS_11G)) { slot_time = 9; } RTL_W32(EDCA_VO_PARA, (EDCA[VO].TXOPlimit << 16) | (EDCA[VO].ECWmax << 12) | (EDCA[VO].ECWmin << 8) | (sifs_time + EDCA[VO].AIFSN * slot_time)); #ifdef WIFI_WMM if (QOS_ENABLE) RTL_W32(EDCA_VI_PARA, (EDCA[VI].TXOPlimit << 16) | (EDCA[VI].ECWmax << 12) | (EDCA[VI].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); else #endif RTL_W32(EDCA_VI_PARA, (EDCA[BE].TXOPlimit << 16) | (EDCA[BE].ECWmax << 12) | (EDCA[BE].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); RTL_W32(EDCA_BE_PARA, (EDCA[BE].TXOPlimit << 16) | (EDCA[BE].ECWmax << 12) | (EDCA[BE].ECWmin << 8) | (sifs_time + EDCA[BE].AIFSN * slot_time)); RTL_W32(EDCA_BK_PARA, (EDCA[BK].TXOPlimit << 16) | (EDCA[BK].ECWmax << 12) | (EDCA[BK].ECWmin << 8) | (sifs_time + EDCA[BK].AIFSN * slot_time)); }else #endif //RTL_MANUAL_EDCA { memset(EDCA, 0, 4*sizeof(struct ParaRecord)); /* copy BE, BK from static data */ if( OPMODE & WIFI_AP_STATE ) memcpy(EDCA, rtl_ap_EDCA, 2*sizeof(struct ParaRecord)); else memcpy(EDCA, rtl_sta_EDCA, 2*sizeof(struct ParaRecord)); /* VI, VO apply settings in AG by default */ if( OPMODE & WIFI_AP_STATE ) memcpy(&EDCA[2], &rtl_ap_EDCA[VI_AG], 2*sizeof(struct ParaRecord)); else memcpy(&EDCA[2], &rtl_sta_EDCA[VI_AG], 2*sizeof(struct ParaRecord)); if ((mode & WIRELESS_11N) || (mode & WIRELESS_11G)) { slot_time = 9; } else { /* replace with settings in B */ if( OPMODE & WIFI_AP_STATE ) memcpy(&EDCA[2], &rtl_ap_EDCA[VI], 2*sizeof(struct ParaRecord)); else memcpy(&EDCA[2], &rtl_sta_EDCA[VI], 2*sizeof(struct ParaRecord)); } VO_TXOP = EDCA[VO].TXOPlimit; VI_TXOP = EDCA[VI].TXOPlimit; RTL_W32(EDCA_VO_PARA, (VO_TXOP << 16) | (EDCA[VO].ECWmax << 12) | (EDCA[VO].ECWmin << 8) | (sifs_time + EDCA[VO].AIFSN * slot_time)); #ifdef WIFI_WMM if (QOS_ENABLE) RTL_W32(EDCA_VI_PARA, (VI_TXOP << 16) | (EDCA[VI].ECWmax << 12) | (EDCA[VI].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); else #endif RTL_W32(EDCA_VI_PARA, (EDCA[BK].ECWmax << 12) | (EDCA[BK].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); RTL_W32(EDCA_BE_PARA, ((EDCA[BE].ECWmax) << 12) | (EDCA[BE].ECWmin << 8) | (sifs_time + EDCA[BE].AIFSN * slot_time)); RTL_W32(EDCA_BK_PARA, (EDCA[BK].ECWmax << 12) | (EDCA[BK].ECWmin << 8) | (sifs_time + EDCA[BK].AIFSN * slot_time)); RTL_W8(ACMHWCTRL, 0x00); } priv->pshare->iot_mode_enable = 0; if (priv->pshare->rf_ft_var.wifi_beq_iot) priv->pshare->iot_mode_VI_exist = 0; priv->pshare->iot_mode_VO_exist = 0; #ifdef WMM_VIBE_PRI priv->pshare->iot_mode_BE_exist = 0; #endif #ifdef LOW_TP_TXOP priv->pshare->BE_cwmax_enhance = 0; #endif } void choose_IOT_main_sta(struct rtl8192cd_priv *priv, struct stat_info *pstat) { if ((GET_ROOT(priv)->up_time % 2) == 0) { unsigned int tx_2s_avg = 0; unsigned int rx_2s_avg = 0; int i=0, aggReady=0; unsigned long total_sum = (priv->pshare->current_tx_bytes+priv->pshare->current_rx_bytes); pstat->current_tx_bytes += pstat->tx_byte_cnt; pstat->current_rx_bytes += pstat->rx_byte_cnt; if (total_sum != 0) { if (total_sum <= 100) { tx_2s_avg = (unsigned int)((pstat->current_tx_bytes*100) / total_sum); rx_2s_avg = (unsigned int)((pstat->current_rx_bytes*100) / total_sum); } else { tx_2s_avg = (unsigned int)(pstat->current_tx_bytes / (total_sum / 100)); rx_2s_avg = (unsigned int)(pstat->current_rx_bytes / (total_sum / 100)); } } for(i=0; i<8; i++) aggReady += (pstat->ADDBA_ready[i]); if (pstat->ht_cap_len && aggReady) { if ((tx_2s_avg + rx_2s_avg >= 50)) { priv->pshare->highTP_found_pstat = pstat; } #ifdef CLIENT_MODE if (OPMODE & WIFI_STATION_STATE) { if(pstat->is_ralink_sta && ((tx_2s_avg + rx_2s_avg) >= 45)) priv->pshare->highTP_found_pstat = pstat; } #endif } } else { pstat->current_tx_bytes = pstat->tx_byte_cnt; pstat->current_rx_bytes = pstat->rx_byte_cnt; } } void rxBB_dm(struct rtl8192cd_priv *priv) { if ((priv->up_time % 3) == 1) { if (priv->pshare->rssi_min != 0xff) { if (priv->pshare->rf_ft_var.dig_enable) { // for DIG checking check_DIG_by_rssi(priv, priv->pshare->rssi_min); } #ifdef INTERFERENCE_CONTROL if (priv->pshare->rf_ft_var.nbi_filter_enable) { check_NBI_by_rssi(priv, priv->pshare->rssi_min); } #endif } check_EDCCA(priv, priv->pshare->rssi_min); #ifdef MP_TEST if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) #endif { if (!priv->pshare->rf_ft_var.use_ext_lna) CCK_CCA_dynamic_enhance(priv, priv->pshare->rssi_min); } } } /* * IOT related functions */ void IOT_engine(struct rtl8192cd_priv *priv) { #ifdef WIFI_WMM unsigned int switch_turbo = 0; #endif struct stat_info *pstat = priv->pshare->highTP_found_pstat; #if defined(RTL_MANUAL_EDCA) && defined(WIFI_WMM) if(priv->pmib->dot11QosEntry.ManualEDCA) return ; #endif #ifdef WIFI_WMM if (QOS_ENABLE) { if (!priv->pmib->dot11OperationEntry.wifi_specific || ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2))) { if (priv->pshare->iot_mode_enable && ((priv->pshare->phw->VO_pkt_count > 50) || (priv->pshare->phw->VI_pkt_count > 50) || (priv->pshare->phw->BK_pkt_count > 50))) { priv->pshare->iot_mode_enable = 0; switch_turbo++; } else if ((!priv->pshare->iot_mode_enable) && ((priv->pshare->phw->VO_pkt_count < 50) && (priv->pshare->phw->VI_pkt_count < 50) && (priv->pshare->phw->BK_pkt_count < 50))) { priv->pshare->iot_mode_enable++; switch_turbo++; } } if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11OperationEntry.wifi_specific) { if (!priv->pshare->iot_mode_VO_exist && (priv->pshare->phw->VO_pkt_count > 50)) { priv->pshare->iot_mode_VO_exist++; switch_turbo++; } else if (priv->pshare->iot_mode_VO_exist && (priv->pshare->phw->VO_pkt_count < 50)) { priv->pshare->iot_mode_VO_exist = 0; switch_turbo++; } #ifdef WMM_VIBE_PRI if (priv->pshare->iot_mode_VO_exist) { //printk("[%s %d] BE_pkt_count=%d\n", __FUNCTION__, __LINE__, priv->pshare->phw->BE_pkt_count); if (!priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BE_pkt_count > 250)) { priv->pshare->iot_mode_BE_exist++; switch_turbo++; } else if (priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BE_pkt_count < 250)) { priv->pshare->iot_mode_BE_exist = 0; switch_turbo++; } } #endif if (priv->pshare->rf_ft_var.wifi_beq_iot) { if (!priv->pshare->iot_mode_VI_exist && (priv->pshare->phw->VI_rx_pkt_count > 50)) { priv->pshare->iot_mode_VI_exist++; switch_turbo++; } else if (priv->pshare->iot_mode_VI_exist && (priv->pshare->phw->VI_rx_pkt_count < 50)) { priv->pshare->iot_mode_VI_exist = 0; switch_turbo++; } } } #ifdef CLIENT_MODE if ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) { if (priv->pshare->iot_mode_enable && (((priv->pshare->phw->VO_pkt_count > 50) || (priv->pshare->phw->VI_pkt_count > 50) || (priv->pshare->phw->BK_pkt_count > 50)) || (pstat && (!pstat->ADDBA_ready[0]) & (!pstat->ADDBA_ready[3])))) { priv->pshare->iot_mode_enable = 0; switch_turbo++; } else if ((!priv->pshare->iot_mode_enable) && (((priv->pshare->phw->VO_pkt_count < 50) && (priv->pshare->phw->VI_pkt_count < 50) && (priv->pshare->phw->BK_pkt_count < 50)) && (pstat && (pstat->ADDBA_ready[0] | pstat->ADDBA_ready[3])))) { priv->pshare->iot_mode_enable++; switch_turbo++; } } #endif priv->pshare->phw->VO_pkt_count = 0; priv->pshare->phw->VI_pkt_count = 0; if (priv->pshare->rf_ft_var.wifi_beq_iot) priv->pshare->phw->VI_rx_pkt_count = 0; priv->pshare->phw->BK_pkt_count = 0; #ifdef WMM_VIBE_PRI priv->pshare->phw->BE_pkt_count = 0; #endif } #endif if ((priv->up_time % 2) == 0) { /* * decide EDCA content for different chip vendor */ #ifdef WIFI_WMM if (QOS_ENABLE && (!priv->pmib->dot11OperationEntry.wifi_specific || ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) #ifdef CLIENT_MODE || ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) #endif )) { if (pstat && pstat->rssi >= priv->pshare->rf_ft_var.txop_enlarge_upper) { #ifdef LOW_TP_TXOP if (pstat->is_intel_sta) { if (priv->pshare->txop_enlarge != 0xe) { priv->pshare->txop_enlarge = 0xe; if (priv->pshare->iot_mode_enable) switch_turbo++; } } else if (priv->pshare->txop_enlarge != 2) { priv->pshare->txop_enlarge = 2; if (priv->pshare->iot_mode_enable) switch_turbo++; } #else if (priv->pshare->txop_enlarge != 2) { if (pstat->is_intel_sta) priv->pshare->txop_enlarge = 0xe; else if (pstat->is_ralink_sta) priv->pshare->txop_enlarge = 0xd; else priv->pshare->txop_enlarge = 2; if (priv->pshare->iot_mode_enable) switch_turbo++; } #endif } else if (!pstat || pstat->rssi < priv->pshare->rf_ft_var.txop_enlarge_lower) { if (priv->pshare->txop_enlarge) { priv->pshare->txop_enlarge = 0; if (priv->pshare->iot_mode_enable) switch_turbo++; } } #ifdef LOW_TP_TXOP // for Intel IOT, need to enlarge CW MAX from 6 to 10 if (pstat && pstat->is_intel_sta && (((pstat->tx_avarage+pstat->rx_avarage)>>10) < priv->pshare->rf_ft_var.cwmax_enhance_thd)) { if (!priv->pshare->BE_cwmax_enhance && priv->pshare->iot_mode_enable) { priv->pshare->BE_cwmax_enhance = 1; switch_turbo++; } } else { if (priv->pshare->BE_cwmax_enhance) { priv->pshare->BE_cwmax_enhance = 0; switch_turbo++; } } #endif } #endif priv->pshare->current_tx_bytes = 0; priv->pshare->current_rx_bytes = 0; } #ifdef SW_TX_QUEUE if ((priv->assoc_num > 1) && (AMPDU_ENABLE)) { if (priv->swq_txmac_chg >= priv->pshare->rf_ft_var.swq_en_highthd) { if ((priv->swq_en == 0)) { switch_turbo++; if (priv->pshare->txop_enlarge == 0) priv->pshare->txop_enlarge = 2; priv->swq_en = 1; } else { if ((switch_turbo > 0) && (priv->pshare->txop_enlarge == 0) && (priv->pshare->iot_mode_enable != 0)) { priv->pshare->txop_enlarge = 2; switch_turbo--; } } } else if(priv->swq_txmac_chg <= priv->pshare->rf_ft_var.swq_dis_lowthd) { priv->swq_en = 0; } else if ((priv->swq_en == 1) && (switch_turbo > 0) && (priv->pshare->txop_enlarge == 0) && (priv->pshare->iot_mode_enable != 0)) { priv->pshare->txop_enlarge = 2; switch_turbo--; } //debug msg //printk("swq=%d,sw=%d,en=%d,mode=%d\n", priv->swq_en, switch_turbo, priv->pshare->txop_enlarge, priv->pshare->iot_mode_enable); } #if defined(CONFIG_RTL_819XD) else if((priv->assoc_num == 1) && (AMPDU_ENABLE)) { if (pstat) { if ((pstat->current_tx_bytes > 14417920) && (pstat->current_rx_bytes > 14417920) && (priv->swq_en == 0)) { //55Mbps priv->swq_en = 1; } else if (((pstat->tx_avarage < 4587520) || (pstat->rx_avarage < 4587520)) && (priv->swq_en == 1)) { //35Mbps priv->swq_en = 0; } } else priv->swq_en = 0; } #endif #endif #ifdef WIFI_WMM #ifdef LOW_TP_TXOP if ((!priv->pmib->dot11OperationEntry.wifi_specific || (priv->pmib->dot11OperationEntry.wifi_specific == 2)) && QOS_ENABLE) { if (switch_turbo || priv->pshare->rf_ft_var.low_tp_txop) { unsigned int thd_tp; unsigned char under_thd; unsigned int curr_tp; if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N | WIRELESS_11G)) { // Determine the upper bound throughput threshold. if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { if (priv->assoc_num && priv->assoc_num != priv->pshare->ht_sta_num) thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_g; else thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_n; } else thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_g; // Determine to close txop. curr_tp = (unsigned int)(priv->ext_stats.tx_avarage>>17) + (unsigned int)(priv->ext_stats.rx_avarage>>17); if (curr_tp <= thd_tp && curr_tp >= priv->pshare->rf_ft_var.low_tp_txop_thd_low) under_thd = 1; else under_thd = 0; } else { under_thd = 0; } if (switch_turbo) { priv->pshare->rf_ft_var.low_tp_txop_close = under_thd; priv->pshare->rf_ft_var.low_tp_txop_count = 0; } else if (priv->pshare->iot_mode_enable && (priv->pshare->rf_ft_var.low_tp_txop_close != under_thd)) { priv->pshare->rf_ft_var.low_tp_txop_count++; if (priv->pshare->rf_ft_var.low_tp_txop_close) { priv->pshare->rf_ft_var.low_tp_txop_count = priv->pshare->rf_ft_var.low_tp_txop_delay; } if (priv->pshare->rf_ft_var.low_tp_txop_count == priv->pshare->rf_ft_var.low_tp_txop_delay) { priv->pshare->rf_ft_var.low_tp_txop_count = 0; priv->pshare->rf_ft_var.low_tp_txop_close = under_thd; switch_turbo++; } } else { priv->pshare->rf_ft_var.low_tp_txop_count = 0; } } } #endif if (switch_turbo) IOT_EDCA_switch(priv, priv->pmib->dot11BssType.net_work_type, priv->pshare->iot_mode_enable); #endif } #ifdef WIFI_WMM void IOT_EDCA_switch(struct rtl8192cd_priv *priv, int mode, char enable) { unsigned int slot_time = 20, sifs_time = 10, BE_TXOP = 47, VI_TXOP = 94; unsigned int vi_cw_max = 4, vi_cw_min = 3, vi_aifs; if (!(!priv->pmib->dot11OperationEntry.wifi_specific || ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) #ifdef CLIENT_MODE || ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) #endif )) return; if ((mode & WIRELESS_11N) && (priv->pshare->ht_sta_num #ifdef WDS || ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) #endif )) sifs_time = 16; if ((mode & WIRELESS_11N) || (mode & WIRELESS_11G)) { slot_time = 9; } else { BE_TXOP = 94; VI_TXOP = 188; } #if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) if (priv->pshare->is_40m_bw) { BE_TXOP = 23; } #endif if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11OperationEntry.wifi_specific) { if (priv->pshare->iot_mode_VO_exist) { #ifdef WMM_VIBE_PRI if (priv->pshare->iot_mode_BE_exist) { vi_cw_max = 5; vi_cw_min = 3; vi_aifs = (sifs_time + ((OPMODE & WIFI_AP_STATE)?1:2) * slot_time); } else #endif { vi_cw_max = 6; vi_cw_min = 4; vi_aifs = 0x2b; } } else { vi_aifs = (sifs_time + ((OPMODE & WIFI_AP_STATE)?1:2) * slot_time); } RTL_W32(EDCA_VI_PARA, ((VI_TXOP*(1-priv->pshare->iot_mode_VO_exist)) << 16) | (vi_cw_max << 12) | (vi_cw_min << 8) | vi_aifs); } if (!enable || (priv->pshare->rf_ft_var.wifi_beq_iot && priv->pshare->iot_mode_VI_exist)) { if (priv->pshare->rf_ft_var.wifi_beq_iot && priv->pshare->iot_mode_VI_exist) { RTL_W32(EDCA_BE_PARA, (10 << 12) | (4 << 8) | 0x4f); } else { RTL_W32(EDCA_BE_PARA, (((OPMODE & WIFI_AP_STATE)?6:10) << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); } } else { #ifdef LOW_TP_TXOP int txop; unsigned int cw_max; unsigned int txop_close; cw_max = ((priv->pshare->BE_cwmax_enhance) ? 10 : 6); txop_close = ((priv->pshare->rf_ft_var.low_tp_txop && priv->pshare->rf_ft_var.low_tp_txop_close) ? 1 : 0); txop = (txop_close ? 0 : (BE_TXOP*2)); #endif if (priv->pshare->ht_sta_num #ifdef WDS || ((OPMODE & WIFI_AP_STATE) && (mode & WIRELESS_11N) && priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) #endif ) { /* if (priv->pshare->txop_enlarge == 0xf) { // is 8192S client RTL_W32(EDCA_BE_PARA, ((BE_TXOP*2) << 16) | (6 << 12) | (4 << 8) | (sifs_time + slot_time+ 0xf)); // 0xf is 92s circuit delay priv->pshare->txop_enlarge = 2; } else */ if (priv->pshare->txop_enlarge == 0xe) { #ifndef LOW_TP_TXOP // is intel client, use a different edca value #if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (5 << 8) | 0x1f); #else RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (4 << 8) | 0x1f); #endif priv->pshare->txop_enlarge = 2; } else if (priv->pshare->txop_enlarge == 0xd) { // is intel ralink, use a different edca value RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (4 << 12) | (3 << 8) | 0x19); priv->pshare->txop_enlarge = 2; } else { if (get_rf_mimo_mode(priv) == MIMO_2T2R) #if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | (6 << 12) | (5 << 8) | (sifs_time + 3 * slot_time)); #else RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | (6 << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); #endif else #if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | (5 << 12) | (4 << 8) | (sifs_time + 2 * slot_time)); #else RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | (5 << 12) | (3 << 8) | (sifs_time + 2 * slot_time)); #endif #else // is intel client, use a different edca value RTL_W32(EDCA_BE_PARA, (txop << 16) | (cw_max << 12) | (4 << 8) | 0x1f); } else { txop = (txop_close ? 0: (BE_TXOP*priv->pshare->txop_enlarge)); if (get_rf_mimo_mode(priv) == MIMO_2T2R) RTL_W32(EDCA_BE_PARA, (txop << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); else RTL_W32(EDCA_BE_PARA, (txop << 16) | (((priv->pshare->BE_cwmax_enhance) ? 10 : 5) << 12) | (3 << 8) | (sifs_time + 2 * slot_time)); #endif } } else { #ifdef LOW_TP_TXOP RTL_W32(EDCA_BE_PARA, (txop << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); #else #if defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (5 << 8) | (sifs_time + 3 * slot_time)); #else RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); #endif #endif } /* if (priv->pmib->dot11OperationEntry.wifi_specific == 2) { RTL_W16(NAV_PROT_LEN, 0x01C0); RTL_W8(CFEND_TH, 0xFF); set_fw_reg(priv, 0xfd000ab0, 0, 0); } */ } } void check_NAV_prot_len(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned int disassoc) { if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat && pstat->ht_cap_len && pstat->is_intel_sta) { if (!disassoc && (pstat->MIMO_ps & _HT_MIMO_PS_DYNAMIC_)) { #ifdef STA_EXT if (pstat->aid <= FW_NUM_STAT) priv->pshare->mimo_ps_dynamic_sta |= BIT(pstat->aid - 1); else priv->pshare->mimo_ps_dynamic_sta_ext |= BIT(pstat->aid - 1 - FW_NUM_STAT); #else #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv) == VERSION_8188E) { if (pstat->aid <= 32) priv->pshare->mimo_ps_dynamic_sta |= BIT(pstat->aid - 1); else priv->pshare->mimo_ps_dynamic_sta_88e_hw_ext |= BIT(pstat->aid - 1 - 32); } else #endif { priv->pshare->mimo_ps_dynamic_sta |= BIT(pstat->aid -1); } #endif } else { #ifdef STA_EXT if (pstat->aid <= FW_NUM_STAT) priv->pshare->mimo_ps_dynamic_sta &= ~BIT(pstat->aid - 1); else priv->pshare->mimo_ps_dynamic_sta_ext &= ~BIT(pstat->aid - 1 - FW_NUM_STAT); #else #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv) == VERSION_8188E) { if (pstat->aid <= 32) priv->pshare->mimo_ps_dynamic_sta &= ~BIT(pstat->aid - 1); else priv->pshare->mimo_ps_dynamic_sta_88e_hw_ext &= ~BIT(pstat->aid - 1 - 32); } else #endif { priv->pshare->mimo_ps_dynamic_sta &= ~BIT(pstat->aid -1); } #endif } #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv) != VERSION_8188E) #endif { if (priv->pshare->mimo_ps_dynamic_sta #ifdef STA_EXT || priv->pshare->mimo_ps_dynamic_sta_ext #endif ) { RTL_W8(NAV_PROT_LEN, 0x40); } else { RTL_W8(NAV_PROT_LEN, 0x20); } } } } #endif //3 ============================================================ //3 FA statistic functions //3 ============================================================ #if !defined(CONFIG_RTL_NEW_AUTOCH) static #endif void reset_FA_reg(struct rtl8192cd_priv *priv) { #if !defined(CONFIG_RTL_NEW_AUTOCH) unsigned char value8; value8 = RTL_R8(0xd03); RTL_W8(0xd03, value8 | 0x08); // regD00[27]=1 to reset these OFDM FA counters value8 = RTL_R8(0xd03); RTL_W8(0xd03, value8 & 0xF7); // regD00[27]=0 to start counting value8 = RTL_R8(0xa2d); RTL_W8(0xa2d, value8 & 0x3F); // regA2D[7:6]=00 to disable counting value8 = RTL_R8(0xa2d); RTL_W8(0xa2d, value8 | 0x80); // regA2D[7:6]=10 to enable counting #ifdef INTERFERENCE_CONTROL // do BB reset to clear Reg0xCF0 & Reg0xCF2 RTL_W8(TXPAUSE, 0xff); value8 = RTL_R8(SYS_FUNC_EN); RTL_W8(SYS_FUNC_EN, value8 & ~FEN_BBRSTB); RTL_W8(SYS_FUNC_EN, value8 | FEN_BBRSTB); RTL_W8(TXPAUSE, 0x00); #endif #else unsigned char value8; /* cck CCA */ PHY_SetBBReg(priv, 0xa2c, BIT(13) | BIT(12), 0); PHY_SetBBReg(priv, 0xa2c, BIT(13) | BIT(12), 2); /* cck FA*/ PHY_SetBBReg(priv, 0xa2c, BIT(15) | BIT(14), 0); PHY_SetBBReg(priv, 0xa2c, BIT(15) | BIT(14), 2); /* ofdm */ PHY_SetBBReg(priv, 0xd00, BIT(27), 1); PHY_SetBBReg(priv, 0xd00, BIT(27), 0); #ifdef INTERFERENCE_CONTROL // do BB reset to clear Reg0xCF0 & Reg0xCF2 RTL_W8(TXPAUSE, 0xff); value8 = RTL_R8(SYS_FUNC_EN); RTL_W8(SYS_FUNC_EN, value8 & ~FEN_BBRSTB); RTL_W8(SYS_FUNC_EN, value8 | FEN_BBRSTB); RTL_W8(TXPAUSE, 0x00); #endif #endif #if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) if (GET_CHIP_VER(priv) == VERSION_8192D){ PHY_SetBBReg(priv, 0xf14, BIT(16),1); PHY_SetBBReg(priv, 0xf14, BIT(16),0); RTL_W32(RXERR_RPT, RTL_R32(RXERR_RPT)|BIT(27)); RTL_W32(RXERR_RPT, RTL_R32(RXERR_RPT)&(~BIT(27))); } #endif #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv)==VERSION_8188E) { PHY_SetBBReg(priv, 0xc0c, BIT(31), 1); PHY_SetBBReg(priv, 0xc0c, BIT(31), 0); } #endif } #if defined(CONFIG_RTL_NEW_AUTOCH) void hold_CCA_FA_counter(struct rtl8192cd_priv *priv) { /* hold cck CCA & FA counter */ PHY_SetBBReg(priv, 0xa2c, BIT(12), 1); PHY_SetBBReg(priv, 0xa2c, BIT(14), 1); /* hold ofdm CCA & FA counter */ PHY_SetBBReg(priv, 0xc00, BIT(31), 1); PHY_SetBBReg(priv, 0xd00, BIT(31), 1); } void release_CCA_FA_counter(struct rtl8192cd_priv *priv) { /* release cck CCA & FA counter */ PHY_SetBBReg(priv, 0xa2c, BIT(12), 0); PHY_SetBBReg(priv, 0xa2c, BIT(14), 0); /* release ofdm CCA & FA counter */ PHY_SetBBReg(priv, 0xc00, BIT(31), 0); PHY_SetBBReg(priv, 0xd00, BIT(31), 0); #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv)==VERSION_8188E) { PHY_SetBBReg(priv, 0xc0c, BIT(31), 1); PHY_SetBBReg(priv, 0xc0c, BIT(31), 0); } #endif } void _FA_statistic(struct rtl8192cd_priv *priv) { // read OFDM FA counters priv->pshare->ofdm_FA_cnt1 = RTL_R16(0xda2); priv->pshare->ofdm_FA_cnt2 = RTL_R16(0xda4); priv->pshare->ofdm_FA_cnt3 = RTL_R16(0xda6); priv->pshare->ofdm_FA_cnt4 = RTL_R16(0xda8); priv->pshare->cck_FA_cnt = (RTL_R8(0xa5b) << 8) + RTL_R8(0xa5c); #ifdef INTERFERENCE_CONTROL priv->pshare->ofdm_FA_total_cnt = (unsigned int) priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + RTL_R16(0xcf0) + RTL_R16(0xcf2); priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_total_cnt + priv->pshare->cck_FA_cnt; #else priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + priv->pshare->cck_FA_cnt + RTL_R16(0xcf0) + RTL_R16(0xcf2); #endif } #endif void FA_statistic(struct rtl8192cd_priv *priv) { #if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) if (GET_CHIP_VER(priv) == VERSION_8192D){ // priv->pshare->F90_cnt = PHY_QueryBBReg(priv, 0xf90, bMaskHWord); priv->pshare->F94_cnt = PHY_QueryBBReg(priv, 0xf94, bMaskHWord); priv->pshare->F94_cntOK = PHY_QueryBBReg(priv, 0xf94, bMaskLWord); RTL_W32(RXERR_RPT,(RTL_R32(RXERR_RPT)&0x0fffffff)|0x70000000); priv->pshare->Reg664_cnt = RTL_R32(RXERR_RPT) & 0xfffff; RTL_W32(RXERR_RPT,(RTL_R32(RXERR_RPT)&0x0fffffff)|0x60000000); priv->pshare->Reg664_cntOK = RTL_R32(RXERR_RPT) & 0xfffff; } #endif #if !defined(CONFIG_RTL_NEW_AUTOCH) signed char value8; // read OFDM FA counters priv->pshare->ofdm_FA_cnt1 = RTL_R16(0xda2); priv->pshare->ofdm_FA_cnt2 = RTL_R16(0xda4); priv->pshare->ofdm_FA_cnt3 = RTL_R16(0xda6); priv->pshare->ofdm_FA_cnt4 = RTL_R16(0xda8); // read the CCK FA counters value8 = RTL_R8(0xa2d); RTL_W8(0xa2d, value8 | 0x40); // regA2D[6]=1 to hold and read the CCK FA counters priv->pshare->cck_FA_cnt = RTL_R8(0xa5b); priv->pshare->cck_FA_cnt = priv->pshare->cck_FA_cnt << 8; priv->pshare->cck_FA_cnt += RTL_R8(0xa5c); priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + priv->pshare->cck_FA_cnt + RTL_R16(0xcf0) + RTL_R16(0xcf2); if (priv->pshare->rf_ft_var.rssi_dump) priv->pshare->CCA_total_cnt = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); #else hold_CCA_FA_counter(priv); _FA_statistic(priv); if (priv->pshare->rf_ft_var.rssi_dump) priv->pshare->CCA_total_cnt = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); release_CCA_FA_counter(priv); #endif reset_FA_reg(priv); #if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) if (GET_CHIP_VER(priv) == VERSION_8192D){ if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G && !(OPMODE & WIFI_SITE_MONITOR)) { if (priv->pshare->DNC_on == 0){ //if ((priv->pshare->F94_cnt + priv->pshare->F90_cnt)> 3000){ /* Reg 664: x > y && x > 1000 Reg F94: x > 0.75*y && x > 1000 */ if (((priv->pshare->Reg664_cnt>priv->pshare->Reg664_cntOK) && (priv->pshare->Reg664_cnt > 1000))|| ((priv->pshare->F94_cnt > ((priv->pshare->Reg664_cntOK*3)>>2)) && (priv->pshare->F94_cnt > 1000))) { priv->ext_stats.tp_average_pre = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; priv->pshare->DNC_on = 1; priv->pshare->DNC_chk_cnt = 1; priv->pshare->DNC_chk = 2; // 0: don't check, 1; check, 2: just entering DNC //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07600760); PHY_SetBBReg(priv, 0xc50, bMaskByte0, 0x20); PHY_SetBBReg(priv, 0xc58, bMaskByte0, 0x20); //printk("Dynamic Noise Control ON\n"); } } else { if ((priv->pshare->DNC_chk_cnt % 5)==0){ // check every 5*2=10 seconds unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; priv->pshare->DNC_chk_cnt = 0; if ((priv->pshare->DNC_chk == 2) && (tp_now < priv->ext_stats.tp_average_pre+5)){ //no advantage, leave DNC state priv->pshare->DNC_on = 0; priv->pshare->DNC_chk = 0; //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); } else { priv->pshare->DNC_chk = 0; /* If TP < 20M or TP varies more than 5M. Start Checking...*/ if ((tp_now < 20) || ((tp_now < (priv->ext_stats.tp_average_pre-5))|| (tp_now > (priv->ext_stats.tp_average_pre+5)))){ priv->pshare->DNC_chk = 1; //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); if (!timer_pending(&priv->dnc_timer)) { //printk("... Start Check Noise ...\n"); mod_timer(&priv->dnc_timer, jiffies + 10); // 100 ms } } } priv->ext_stats.tp_average_pre = tp_now; } else if ((priv->pshare->DNC_chk_cnt % 5)==1 && priv->pshare->DNC_chk == 1) { priv->pshare->DNC_chk = 0; //if ((priv->pshare->F94_cnt + priv->pshare->F90_cnt) < 120) { if ((priv->pshare->F94_cnt + priv->pshare->Reg664_cnt) < 120) { priv->pshare->DNC_on = 0; //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); //printk("Dynamic Noise Control OFF\n"); } } priv->pshare->DNC_chk_cnt++; } } } #endif } //3 ============================================================ //3 Rate Adaptive //3 ============================================================ void check_RA_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat) { int level = 0; switch (pstat->rssi_level) { case 1: if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) level = 1; else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) level = 2; else level = 3; break; case 2: if (pstat->rssi > priv->pshare->rf_ft_var.raGoUpUpper) level = 1; else if ((pstat->rssi < priv->pshare->rf_ft_var.raGoDown40MLower) || ((!pstat->ht_cap_len || !priv->pshare->is_40m_bw || !(pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) && (pstat->rssi < priv->pshare->rf_ft_var.raGoDown20MLower))) level = 3; else level = 2; break; case 3: if (pstat->rssi > priv->pshare->rf_ft_var.raGoUpUpper) level = 1; else if ((pstat->rssi > priv->pshare->rf_ft_var.raGoUp20MLower) || ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && (pstat->rssi > priv->pshare->rf_ft_var.raGoUp40MLower) && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) level = 2; else level = 3; break; default: if (isErpSta(pstat)) DEBUG_ERR("wrong rssi level setting\n"); break; } if (level != pstat->rssi_level) { pstat->rssi_level = level; #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv)==VERSION_8188E) { #ifdef TXREPORT add_RATid(priv, pstat); #endif } else #endif { add_update_RATid(priv, pstat); } } } void check_txrate_by_reg(struct rtl8192cd_priv *priv, struct stat_info *pstat) { unsigned char initial_rate = 0x7f; unsigned char legacyRA =0 ; if( should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv)) legacyRA = 1; #ifdef STA_EXT if (pstat->remapped_aid && (pstat->remapped_aid < FW_NUM_STAT-1)) #else if (pstat->aid && (pstat->aid < 32)) #endif { #ifdef WDS if (((pstat->state & WIFI_WDS) && (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate == 0)) || (!(pstat->state & WIFI_WDS) && (priv->pmib->dot11StationConfigEntry.autoRate)) || legacyRA) #else if (priv->pmib->dot11StationConfigEntry.autoRate || legacyRA) #endif { initial_rate = RTL_R8(INIDATA_RATE_SEL + REMAP_AID(pstat)) & 0x7f; if (initial_rate == 0x7f) return; if ((initial_rate&0x3f) < 12) { pstat->current_tx_rate = dot11_rate_table[initial_rate&0x3f]; pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; } else { pstat->current_tx_rate = 0x80|((initial_rate&0x3f) -12); if (initial_rate & BIT(6)) pstat->ht_current_tx_info |= TX_USE_SHORT_GI; else pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; } priv->pshare->current_tx_rate = pstat->current_tx_rate; priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; } else if (pstat->ht_cap_len) { unsigned int is_sgi = 0; if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) #ifdef WIFI_11N_2040_COEXIST && !((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11nConfigEntry.dot11nCoexist && (priv->bg_ap_timeout || priv->force_20_sta || priv->switch_20_sta #ifdef CONFIG_RTL_88E_SUPPORT || (GET_CHIP_VER(priv) == VERSION_8188E)?(priv->force_20_sta_88e_hw_ext || priv->switch_20_sta_88e_hw_ext):(0) #endif #ifdef STA_EXT || priv->force_20_sta_ext || priv->switch_20_sta_ext #endif )) #endif ) { if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) is_sgi++; } else if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) { is_sgi++; } if (is_sgi) pstat->ht_current_tx_info |= TX_USE_SHORT_GI; else pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; } if (pstat->ht_cap_len) { if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40)) pstat->ht_current_tx_info |= TX_USE_40M_MODE; else pstat->ht_current_tx_info &= ~TX_USE_40M_MODE; } priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; } else { DEBUG_INFO("sta has no aid found to check current tx rate\n"); } } void add_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat) { unsigned char limit=16; int i; unsigned long flags; unsigned int update_reg=0; SAVE_INT_AND_CLI(flags); pstat->tx_ra_bitmap = 0; for (i=0; i<32; i++) { if (pstat->bssrateset[i]) pstat->tx_ra_bitmap |= get_bit_value_from_ieee_value(pstat->bssrateset[i]&0x7f); } if (pstat->ht_cap_len) { if ((pstat->MIMO_ps & _HT_MIMO_PS_STATIC_) || (get_rf_mimo_mode(priv)== MIMO_1T2R) || (get_rf_mimo_mode(priv)== MIMO_1T1R)) limit=8; for (i=0; iht_cap_buf.support_mcs[i/8] & BIT(i%8)) pstat->tx_ra_bitmap |= BIT(i+12); } } if (pstat->ht_cap_len) { unsigned int set_sgi = 0; if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) #ifdef WIFI_11N_2040_COEXIST && !((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11nConfigEntry.dot11nCoexist && (priv->bg_ap_timeout || priv->force_20_sta || priv->switch_20_sta #ifdef CONFIG_RTL_88E_SUPPORT || (GET_CHIP_VER(priv) == VERSION_8188E)?(priv->force_20_sta_88e_hw_ext || priv->switch_20_sta_88e_hw_ext):(0) #endif #ifdef STA_EXT || priv->force_20_sta_ext || priv->switch_20_sta_ext #endif )) #endif ) { if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_) && priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) set_sgi++; } else if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_) && priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) { set_sgi++; } if (set_sgi) { #if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) if (GET_CHIP_VER(priv)==VERSION_8188E) priv->pshare->RaInfo[pstat->aid].SGIEnable = 1; else #endif pstat->tx_ra_bitmap |= BIT(28); } #if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) else { if (GET_CHIP_VER(priv)==VERSION_8188E) priv->pshare->RaInfo[pstat->aid].SGIEnable = 0; } #endif } #if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) else { if (GET_CHIP_VER(priv)==VERSION_8188E) priv->pshare->RaInfo[pstat->aid].SGIEnable = 0; } #endif if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) { if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) pstat->rssi_level = 1; else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) pstat->rssi_level = 2; else pstat->rssi_level = 3; } if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G))) pstat->tx_ra_bitmap &= 0xfffffff0; //disable cck rate #ifdef P2P_SUPPORT if(pstat->is_p2p_client){ pstat->tx_ra_bitmap &= 0xfffffff0; //disable cck rate } #endif // rate adaptive by rssi if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && (!should_restrict_Nrate(priv, pstat))) { if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R)) { switch (pstat->rssi_level) { case 1: pstat->tx_ra_bitmap &= 0x100f0000; break; case 2: pstat->tx_ra_bitmap &= 0x100ff000; break; case 3: if (priv->pshare->is_40m_bw) pstat->tx_ra_bitmap &= 0x100ff005; else pstat->tx_ra_bitmap &= 0x100ff001; break; } } else { switch (pstat->rssi_level) { case 1: pstat->tx_ra_bitmap &= 0x1f8f0000; break; case 2: pstat->tx_ra_bitmap &= 0x1f8ff000; break; case 3: if (priv->pshare->is_40m_bw) pstat->tx_ra_bitmap &= 0x010ff005; else pstat->tx_ra_bitmap &= 0x010ff001; break; } // Don't need to mask high rates due to new rate adaptive parameters //if (pstat->is_broadcom_sta) // use MCS12 as the highest rate vs. Broadcom sta // pstat->tx_ra_bitmap &= 0x81ffffff; // NIC driver will report not supporting MCS15 and MCS14 in asoc req //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta) // pstat->tx_ra_bitmap &= 0x83ffffff; // if Realtek 1x2 sta, don't use MCS15 and MCS14 } } else if (((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat)) || ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)))) { switch (pstat->rssi_level) { case 1: pstat->tx_ra_bitmap &= 0x00000f00; break; case 2: pstat->tx_ra_bitmap &= 0x00000ff0; break; case 3: pstat->tx_ra_bitmap &= 0x00000ff5; break; } } else { pstat->tx_ra_bitmap &= 0x0000000d; } // Client mode IOT issue, Button 2009.07.17 #ifdef CLIENT_MODE if(OPMODE & WIFI_STATION_STATE) { if(!pstat->is_rtl8192s_sta && pstat->is_realtek_sta && pstat->is_legacy_encrpt) pstat->tx_ra_bitmap &= 0x0001ffff; // up to MCS4 } #endif #if defined(CONFIG_RTL_92D_SUPPORT) && defined (USB_POWER_SUPPORT) if ((GET_CHIP_VER(priv)==VERSION_8192D) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) pstat->tx_ra_bitmap &= USB_RA_MASK; #endif #ifdef STA_EXT //update STA_map { int remapped_aid = 0; remapped_aid = find_reampped_aid(priv, pstat->aid); if(remapped_aid == 0) { /*WARNING: THIS SHOULD NOT HAPPEN*/ printk("add AID fail!!\n"); BUG(); } if(remapped_aid >= (FW_NUM_STAT-1)){// no room for the STA // priv->STA_map |= (1<< pstat->aid) ; pstat->remapped_aid = FW_NUM_STAT-1; pstat->sta_in_firmware = 0; // this value will updated in expire_timer } else if(priv->pshare->remapped_aidarray[remapped_aid] == 0) { // if not 0, it should have been added before //we got a room //clear STA_map // priv->STA_map &= ~(BIT(pstat->aid)); pstat->remapped_aid = remapped_aid; priv->pshare->remapped_aidarray[remapped_aid] = pstat->aid; pstat->sta_in_firmware = 1; // this value will updated in expire_timer priv->pshare->fw_free_space --; } else {// added before pstat->sta_in_firmware = 1; } } #endif// STA_EXT #if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) if (GET_CHIP_VER(priv)==VERSION_8188E) { if (pstat->tx_ra_bitmap & 0xff000) { if (priv->pshare->is_40m_bw) priv->pshare->RaInfo[pstat->aid].RateID = ARFR_1T_40M; else priv->pshare->RaInfo[pstat->aid].RateID = ARFR_1T_20M; } else if (pstat->tx_ra_bitmap & 0xff0) { priv->pshare->RaInfo[pstat->aid].RateID = ARFR_BG_MIX; } else { priv->pshare->RaInfo[pstat->aid].RateID = ARFR_B_ONLY; } priv->pshare->RaInfo[pstat->aid].RateMask = pstat->tx_ra_bitmap; ARFBRefresh(priv, &priv->pshare->RaInfo[pstat->aid]); } else #endif { #ifdef STA_EXT if (REMAP_AID(pstat) < FW_NUM_STAT-1) #else if (REMAP_AID(pstat) < 32) #endif { #ifdef CONFIG_RTL_92D_SUPPORT if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { pstat->tx_ra_bitmap &= 0xfffffff0; if (pstat->tx_ra_bitmap & 0xff00000) { if (priv->pshare->is_40m_bw) set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_40M, pstat->tx_ra_bitmap); else set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_20M, pstat->tx_ra_bitmap); update_reg++; } else if (pstat->tx_ra_bitmap & 0xff000) { if (priv->pshare->is_40m_bw) set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_40M, pstat->tx_ra_bitmap); else set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_20M, pstat->tx_ra_bitmap); } else if (pstat->tx_ra_bitmap & 0xff0) { set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_Band_A_BMC, pstat->tx_ra_bitmap); } else { set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_Band_A_BMC, pstat->tx_ra_bitmap); } } else #endif { if (pstat->tx_ra_bitmap & 0xff00000) { if (priv->pshare->is_40m_bw) set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_40M, pstat->tx_ra_bitmap); else set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_20M, pstat->tx_ra_bitmap); update_reg++; } else if (pstat->tx_ra_bitmap & 0xff000) { if (priv->pshare->is_40m_bw) set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_1T_40M, pstat->tx_ra_bitmap); else set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_1T_20M, pstat->tx_ra_bitmap); } else if (pstat->tx_ra_bitmap & 0xff0) { set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_BG_MIX, pstat->tx_ra_bitmap); } else { set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_B_ONLY, pstat->tx_ra_bitmap); } } /* * Rate adaptive algorithm. * If the STA is 2R, we set the inti rate to MCS 15 */ if (update_reg) { if (!pstat->check_init_tx_rate && (pstat->rssi > 55)) { RTL_W8(INIDATA_RATE_SEL + REMAP_AID(pstat), 0x1b); pstat->check_init_tx_rate = 1; } } DEBUG_INFO("Add id %d val %08x to ratr\n", pstat->aid, pstat->tx_ra_bitmap); } else { #ifdef STA_EXT #ifdef CONFIG_RTL_92D_SUPPORT if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { if (priv->pshare->is_40m_bw) set_RATid_cmd(priv, (FW_NUM_STAT-1), ARFR_2T_Band_A_40M, 0x1ffffff0); else set_RATid_cmd(priv, (FW_NUM_STAT-1), ARFR_2T_Band_A_20M, 0x1ffffff0); } else #endif { if (priv->pshare->is_40m_bw) set_RATid_cmd(priv, (FW_NUM_STAT-1), ARFR_2T_40M, 0x1fffffff); else set_RATid_cmd(priv, (FW_NUM_STAT-1), ARFR_2T_20M, 0x1fffffff); } #else DEBUG_ERR("station aid %d exceed the max number\n", pstat->aid); #endif } } RESTORE_INT(flags); } void set_rssi_cmd(struct rtl8192cd_priv *priv, struct stat_info *pstat) { unsigned long flags; unsigned int content = 0; int rssi = pstat->rssi; #ifdef HIGH_POWER_EXT_PA if( priv->pshare->rf_ft_var.use_ext_pa ) rssi += RSSI_DIFF_PA; if( rssi > 100) rssi = 100; #endif SAVE_INT_AND_CLI(flags); /* * set rssi */ content = rssi<< 24; #ifdef CONFIG_RTL_92D_SUPPORT /* * set max macid */ if (GET_CHIP_VER(priv) == VERSION_8192D){ content |= priv->pshare->max_fw_macid << 16; } #endif /* * set macid */ content |= pstat->aid << 8; /* * set cmd id */ content |= H2C_CMD_RSSI; signin_h2c_cmd(priv, content, 0); RESTORE_INT(flags); } void add_rssi_timer(unsigned long task_priv) { struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; struct stat_info *pstat = NULL; unsigned int set_timer = 0; unsigned long flags; if (!(priv->drv_state & DRV_STATE_OPEN)) return; if (timer_pending(&priv->add_rssi_timer)) del_timer_sync(&priv->add_rssi_timer); #ifdef PCIE_POWER_SAVING if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) return; #endif if (!list_empty(&priv->addrssi_list)) { pstat = list_entry(priv->addrssi_list.next, struct stat_info, addrssi_list); if (!pstat) return; if (!is_h2c_buf_occupy(priv)) { set_rssi_cmd(priv, pstat); if (!list_empty(&pstat->addrssi_list)) { SAVE_INT_AND_CLI(flags); SMP_LOCK(flags); list_del_init(&pstat->addrssi_list); RESTORE_INT(flags); SMP_UNLOCK(flags); } if (!list_empty(&priv->addrssi_list)) set_timer++; } else { set_timer++; } } if (set_timer) mod_timer(&priv->add_rssi_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms } void add_update_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat) { unsigned long flags; if (is_h2c_buf_occupy(priv)) { if (list_empty(&pstat->addrssi_list)) { SAVE_INT_AND_CLI(flags); list_add_tail(&(pstat->addrssi_list), &(priv->addrssi_list)); RESTORE_INT(flags); if (!timer_pending(&priv->add_rssi_timer)) mod_timer(&priv->add_rssi_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms } } else { set_rssi_cmd(priv, pstat); } } void set_RATid_cmd(struct rtl8192cd_priv *priv, unsigned int macid, unsigned int rateid, unsigned int ratemask) { unsigned int content = 0; unsigned short ext_content = 0; /* * set ratemask */ ext_content = ratemask & 0xffff; content = ((ratemask & 0xfff0000) >> 16) << 8; /* * set short GI */ if (ratemask & BIT(28)) content |= BIT(29); /* * set macid (station aid) */ content |= (macid & 0x1f) << 24; /* * set rateid (ARFR table) */ content |= (rateid & 0xf) << 20; /* * set ext_content used */ content |= BIT(7); /* * set cmd id */ content |= H2C_CMD_MACID; signin_h2c_cmd(priv, content, ext_content); } //3 ============================================================ //3 EDCCA //3 ============================================================ void check_EDCCA(struct rtl8192cd_priv *priv, short rssi) { if ((priv->pshare->rf_ft_var.edcca_thd) && (priv->pmib->dot11RFEntry.dot11channel==14 || priv->pshare->is_40m_bw #if defined(CONFIG_RTL_92D_SUPPORT) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) #endif )) { if((rssi > priv->pshare->rf_ft_var.edcca_thd) && (priv->pshare->phw->EDCCA_on == 0)) { RTL_W32(rOFDM0_ECCAThreshold, 0xfc03fd); priv->pshare->phw->EDCCA_on =1; } else if( (rssi < priv->pshare->rf_ft_var.edcca_thd-5) && priv->pshare->phw->EDCCA_on) { RTL_W32(rOFDM0_ECCAThreshold, 0x7f037f); priv->pshare->phw->EDCCA_on =0; } } if ((!priv->pshare->rf_ft_var.edcca_thd) && priv->pshare->phw->EDCCA_on) { RTL_W32(0xc4c, 0x7f037f); priv->pshare->phw->EDCCA_on = 0; } } //3 ============================================================ //3 Antenna Diversity //3 ============================================================ #ifdef SW_ANT_SWITCH // // 20100514 Luke/Joseph: // Add new function to reset antenna diversity state after link. // void resetSwAntDivVariable(struct rtl8192cd_priv *priv) { priv->pshare->RSSI_sum_R = 0; priv->pshare->RSSI_cnt_R = 0; priv->pshare->RSSI_sum_L = 0; priv->pshare->RSSI_cnt_L = 0; priv->pshare->TXByteCnt_R = 0; priv->pshare->TXByteCnt_L = 0; priv->pshare->RXByteCnt_R = 0; priv->pshare->RXByteCnt_L = 0; } void SwAntDivRestAfterLink(struct rtl8192cd_priv *priv) { priv->pshare->RSSI_test = FALSE; priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_RESET; memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); priv->pshare->DM_SWAT_Table.mapIndex = 0; priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; resetSwAntDivVariable(priv); } void dm_SW_AntennaSwitchInit(struct rtl8192cd_priv *priv) { if(!priv->pshare->rf_ft_var.antSw_enable) return; // if (GET_CHIP_VER(priv) == VERSION_8188C) if(get_rf_mimo_mode(priv)== MIMO_1T1R) priv->pshare->rf_ft_var.antSw_select = 0; //RT_TRACE(COMP_SWAS, DBG_LOUD, ("SWAS:Init SW Antenna Switch\n")); resetSwAntDivVariable(priv); priv->pshare->DM_SWAT_Table.CurAntenna = Antenna_L; priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_RESET; memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); priv->pshare->DM_SWAT_Table.mapIndex = 0; #ifdef GPIO_ANT_SWITCH #ifdef CONFIG_RTL_92D_DMDP if(priv->pshare->wlandev_idx==0) priv->pshare->rf_ft_var.antHw_enable=0; else return; #endif // GPIO 45 : // GPIO_MOD => data port // GPIO_IO_SEL => output RTL_W32(GPIO_PIN_CTRL, 0x00300000| RTL_R32(GPIO_PIN_CTRL)); PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, priv->pshare->DM_SWAT_Table.CurAntenna); RTL_W32(rFPGA0_XCD_RFParameter, RTL_R32(rFPGA0_XCD_RFParameter)| BIT(15)|BIT(16)); // enable ANTSEL #else RTL_W32(LEDCFG, RTL_R32(LEDCFG) | BIT(23) ); //enable LED[1:0] pin as ANTSEL if ( !priv->pshare->rf_ft_var.antSw_select) { RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) | BIT(13) ); //select ANTESEL from path A RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(8)| BIT(9) ); // enable ANTSEL A as SW control RTL_W32(rFPGA0_XA_RFInterfaceOE, (RTL_R32(rFPGA0_XA_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna } else { RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) & ~ BIT(13) ); //select ANTESEL from path B RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(24)| BIT(25) ); // enable ANTSEL B as SW control RTL_W32(rFPGA0_XB_RFInterfaceOE, (RTL_R32(rFPGA0_XB_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna } RTL_W16(rFPGA0_TxInfo, (RTL_R16(rFPGA0_TxInfo)&0xf0ff) | BIT(8) ); // b11-b8=0001 #endif // Move the timer initialization to InitializeVariables function. //PlatformInitializeTimer(Adapter, &pMgntInfo->SwAntennaSwitchTimer, (RT_TIMER_CALL_BACK)dm_SW_AntennaSwitchCallback, NULL, "SwAntennaSwitchTimer"); } // // 20100514 Luke/Joseph: // Add new function for antenna diversity after link. // This is the main function of antenna diversity after link. // This function is called in HalDmWatchDog() and dm_SW_AntennaSwitchCallback(). // HalDmWatchDog() calls this function with SWAW_STEP_PEAK to initialize the antenna test. // In SWAW_STEP_PEAK, another antenna and a 500ms timer will be set for testing. // After 500ms, dm_SW_AntennaSwitchCallback() calls this function to compare the signal just // listened on the air with the RSSI of original antenna. // It chooses the antenna with better RSSI. // There is also a aged policy for error trying. Each error trying will cost more 5 seconds waiting // penalty to get next try. // void dm_SW_AntennaSwitch(struct rtl8192cd_priv *priv, char Step) { unsigned int curTxOkCnt, curRxOkCnt; unsigned int CurByteCnt, PreByteCnt; int Score_R=0, Score_L=0; int RSSI_R, RSSI_L; char nextAntenna=priv->pshare->DM_SWAT_Table.CurAntenna; int i; //1 1. Determine which condition should turn off Antenna Diversity #ifdef MP_TEST if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) return; #endif // if(!(GET_CHIP_VER(priv) == VERSION_8188C) || !priv->pshare->rf_ft_var.antSw_enable) // return; if((!priv->assoc_num) #ifdef PCIE_POWER_SAVING || (priv->pwr_state == L2) || (priv->pwr_state == L1) #endif ){ SwAntDivRestAfterLink(priv); return; } // Handling step mismatch condition. // Peak step is not finished at last time. Recover the variable and check again. if( Step != priv->pshare->DM_SWAT_Table.try_flag) { SwAntDivRestAfterLink(priv); } //1 2. Initialization: Select a assocaiated AP or STA as RSSI target if(priv->pshare->DM_SWAT_Table.try_flag == SWAW_STEP_RESET) { #ifdef CLIENT_MODE if((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) { // Target: Infrastructure mode AP. priv->pshare->RSSI_target = NULL; } #endif resetSwAntDivVariable(priv); priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_PEAK; return; } else { //1 3. Antenna Diversity //2 Calculate TX and RX OK bytes curTxOkCnt = priv->net_stats.tx_bytes - priv->pshare->lastTxOkCnt; curRxOkCnt = priv->net_stats.rx_bytes - priv->pshare->lastRxOkCnt; priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; //2 Try State if(priv->pshare->DM_SWAT_Table.try_flag == SWAW_STEP_DETERMINE) { //3 1. Seperately caculate TX and RX OK byte counter for ant A and B if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { priv->pshare->TXByteCnt_R += curTxOkCnt; priv->pshare->RXByteCnt_R += curRxOkCnt; } else { priv->pshare->TXByteCnt_L += curTxOkCnt; priv->pshare->RXByteCnt_L += curRxOkCnt; } //3 2. Change anntena for testing if(priv->pshare->DM_SWAT_Table.RSSI_Trying != 0) { nextAntenna = (priv->pshare->DM_SWAT_Table.CurAntenna ) ^ Antenna_MAX; priv->pshare->DM_SWAT_Table.RSSI_Trying--; } //2 Try State End: Determine the best antenna if(priv->pshare->DM_SWAT_Table.RSSI_Trying==0) { nextAntenna = priv->pshare->DM_SWAT_Table.CurAntenna; priv->pshare->DM_SWAT_Table.mapIndex = (priv->pshare->DM_SWAT_Table.mapIndex+1)%SELANT_MAP_SIZE; //3 TP Mode: Determine the best antenna by throuhgput if(priv->pshare->DM_SWAT_Table.TestMode == TP_MODE) { //3 (1) Saperately caculate total byte count for two antennas if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { CurByteCnt = (priv->pshare->TXByteCnt_R + (priv->pshare->RXByteCnt_R<<1)); PreByteCnt = (priv->pshare->TXByteCnt_L + (priv->pshare->RXByteCnt_L<<1)); } else { CurByteCnt = (priv->pshare->TXByteCnt_L + (priv->pshare->RXByteCnt_L<<1)); PreByteCnt = (priv->pshare->TXByteCnt_R + (priv->pshare->RXByteCnt_R<<1)); } //3 (2) Throughput Normalization if(priv->pshare->TrafficLoad == TRAFFIC_HIGH) CurByteCnt >>=3; else if(priv->pshare->TrafficLoad == TRAFFIC_LOW) CurByteCnt >>=1; if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { priv->pshare->DM_SWAT_Table.SelectAntennaMap[0][priv->pshare->DM_SWAT_Table.mapIndex] = PreByteCnt; priv->pshare->DM_SWAT_Table.SelectAntennaMap[1][priv->pshare->DM_SWAT_Table.mapIndex] = CurByteCnt; } else { priv->pshare->DM_SWAT_Table.SelectAntennaMap[0][priv->pshare->DM_SWAT_Table.mapIndex] = CurByteCnt; priv->pshare->DM_SWAT_Table.SelectAntennaMap[1][priv->pshare->DM_SWAT_Table.mapIndex] = PreByteCnt; } Score_R = Score_L=0; for (i= 0; ipshare->DM_SWAT_Table.SelectAntennaMap[0][i]; Score_R += priv->pshare->DM_SWAT_Table.SelectAntennaMap[1][i]; } nextAntenna = (Score_L > Score_R) ? Antenna_L : Antenna_R; if(priv->pshare->rf_ft_var.ant_dump&8) panic_printk("Mode TP, select Ant%d, [Score1=%d,Score2=%d]\n", nextAntenna, Score_L, Score_R); } //3 RSSI Mode: Determine the best anntena by RSSI else if(priv->pshare->DM_SWAT_Table.TestMode == RSSI_MODE) { //2 Saperately caculate average RSSI for two antennas RSSI_L = RSSI_R = 0; if(priv->pshare->RSSI_cnt_R > 0) RSSI_R = priv->pshare->RSSI_sum_R/priv->pshare->RSSI_cnt_R; if(priv->pshare->RSSI_cnt_L > 0) RSSI_L = priv->pshare->RSSI_sum_L/priv->pshare->RSSI_cnt_L; if(RSSI_L && RSSI_R ) nextAntenna = (RSSI_L > RSSI_R) ? Antenna_L : Antenna_R; if(priv->pshare->rf_ft_var.ant_dump&8) panic_printk("Mode RSSI, RSSI_R=%d(%d), RSSI_L=%d(%d), Ant=%d\n", RSSI_R, priv->pshare->RSSI_cnt_R, RSSI_L, priv->pshare->RSSI_cnt_L, nextAntenna); } //3 Reset state resetSwAntDivVariable(priv); priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_PEAK; priv->pshare->RSSI_test = FALSE; } } //1 Normal State else if(priv->pshare->DM_SWAT_Table.try_flag == SWAW_STEP_PEAK) { //3 Determine TP/RSSI mode by TRX OK count if((curRxOkCnt+curTxOkCnt) > TP_MODE_THD) { //2 Determine current traffic is high or low if((curTxOkCnt+curRxOkCnt) > TRAFFIC_THRESHOLD) priv->pshare->TrafficLoad = TRAFFIC_HIGH; else priv->pshare->TrafficLoad = TRAFFIC_LOW; priv->pshare->DM_SWAT_Table.RSSI_Trying = 10; priv->pshare->DM_SWAT_Table.TestMode = TP_MODE; } else { int idx = 0; struct stat_info* pEntry = findNextSTA(priv, &idx); priv->pshare->RSSI_target = NULL; while(pEntry) { if(pEntry && pEntry->expire_to) { if(!priv->pshare->RSSI_target) priv->pshare->RSSI_target = pEntry; else if( pEntry->rssi < priv->pshare->RSSI_target->rssi ) priv->pshare->RSSI_target = pEntry; } pEntry = findNextSTA(priv, &idx); }; priv->pshare->DM_SWAT_Table.RSSI_Trying = 6; priv->pshare->DM_SWAT_Table.TestMode = RSSI_MODE; if(priv->pshare->RSSI_target == NULL) { SwAntDivRestAfterLink(priv); return; } //3 reset state memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); } //3 Begin to enter Try State nextAntenna = (priv->pshare->DM_SWAT_Table.CurAntenna ) ^ Antenna_MAX; priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_DETERMINE; priv->pshare->RSSI_test = TRUE; //3 Reset variables resetSwAntDivVariable(priv); } } //1 4.Change TRX antenna if(nextAntenna != priv->pshare->DM_SWAT_Table.CurAntenna) { #ifdef GPIO_ANT_SWITCH PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, nextAntenna); #else if (!priv->pshare->rf_ft_var.antSw_select) PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, 0x300, nextAntenna); else PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, 0x300, nextAntenna); #endif } //1 5.Reset Statistics priv->pshare->DM_SWAT_Table.CurAntenna = nextAntenna; //1 6.Set next timer if(priv->pshare->DM_SWAT_Table.RSSI_Trying == 0) { return; } if(priv->pshare->DM_SWAT_Table.TestMode == RSSI_MODE) { mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies +40); // 400 ms } else if(priv->pshare->DM_SWAT_Table.TestMode == TP_MODE) { if(priv->pshare->TrafficLoad == TRAFFIC_HIGH) { if(priv->pshare->DM_SWAT_Table.RSSI_Trying%2 == 0) mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + 1); // 10 ms else mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + 8); // 80 ms } else if(priv->pshare->TrafficLoad == TRAFFIC_LOW) { if(priv->pshare->DM_SWAT_Table.RSSI_Trying%2 == 0) mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + 4); // 40 ms else mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + 8); // 80 ms } } } void dm_SW_AntennaSwitchCallback(unsigned long task_priv) { struct rtl8192cd_priv *priv = (struct rtl8192cd_priv*)task_priv; unsigned long flags; SAVE_INT_AND_CLI(flags); dm_SW_AntennaSwitch(priv, SWAW_STEP_DETERMINE); RESTORE_INT(flags); } // // 20100514 Luke/Joseph: // This function is used to gather the RSSI information for antenna testing. // It selects the RSSI of the peer STA that we want to know. // void dm_SWAW_RSSI_Check(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) { struct stat_info* pEntry = NULL; pEntry = get_stainfo(priv, GetAddr2Ptr(get_pframe(pfrinfo))); if((priv->pshare->RSSI_target==NULL)||(priv->pshare->RSSI_target==pEntry)) { //1 RSSI for SW Antenna Switch if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { priv->pshare->RSSI_sum_R += pfrinfo->rssi; priv->pshare->RSSI_cnt_R++; } else { priv->pshare->RSSI_sum_L += pfrinfo->rssi; priv->pshare->RSSI_cnt_L++; } } } #ifndef HW_ANT_SWITCH int diversity_antenna_select(struct rtl8192cd_priv *priv, unsigned char *data) { int ant = _atoi(data, 16); // if(GET_CHIP_VER(priv) != VERSION_8188C) // return 0; #ifdef PCIE_POWER_SAVING PCIeWakeUp(priv, POWER_DOWN_T0); #endif if(ant==Antenna_L || ant==Antenna_R) { #ifdef GPIO_ANT_SWITCH PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, ant); #else if (!priv->pshare->rf_ft_var.antSw_select) PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, 0x300, ant); else PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, 0x300, ant); #endif priv->pshare->DM_SWAT_Table.CurAntenna = ant; priv->pshare->rf_ft_var.antSw_enable = 0; SwAntDivRestAfterLink(priv); memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); return 1; } else { priv->pshare->rf_ft_var.antSw_enable = 1; priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; return 0; } } #endif #endif #if defined(HW_ANT_SWITCH) void dm_HW_AntennaSwitchInit(struct rtl8192cd_priv *priv) { if(!priv->pshare->rf_ft_var.antHw_enable) return; #ifdef SW_ANT_SWITCH priv->pshare->rf_ft_var.antSw_enable =0; #endif // if (GET_CHIP_VER(priv) == VERSION_8188C) if(get_rf_mimo_mode(priv)== MIMO_1T1R) priv->pshare->rf_ft_var.antSw_select = 0; if ( !priv->pshare->rf_ft_var.antSw_select) { RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) | BIT(13) ); //select ANTESEL from path A RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(8)| BIT(9)) ); // ANTSEL as HW control RTL_W32(rFPGA0_XA_RFInterfaceOE, (RTL_R32(rFPGA0_XA_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna RTL_W8(0xc50, RTL_R8(0xc50) | BIT(7)); // Enable Hardware antenna switch RTL_W32(0xc54, RTL_R32(0xc54) | BIT(23) ); // Decide final antenna by comparing 2 antennas' pwdb } else { RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) & ~ BIT(13) ); //select ANTESEL from path B RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(24)| BIT(25)) ); // ANTSEL as HW control RTL_W32(rFPGA0_XB_RFInterfaceOE, (RTL_R32(rFPGA0_XB_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, RTL_R8(0xc58) | BIT(7)); // Enable Hardware antenna switch #endif RTL_W32(0xc5C, RTL_R32(0xc5c) | BIT(23) ); // Decide final antenna by comparing 2 antennas' pwdb } priv->pshare->rf_ft_var.CurAntenna = 0; RTL_W32(LEDCFG, RTL_R32(LEDCFG) | BIT(23) ); //enable LED[1:0] pin as ANTSEL RTL_W16(0xca4, (RTL_R16(0xca4) & ~(0xfff))|0x0c0); // Pwdb threshold=12dB RTL_W32(0x874, RTL_R32(0x874) & ~ BIT(23) ); // No update ANTSEL during GNT_BT=1 RTL_W16(rFPGA0_TxInfo, (RTL_R16(rFPGA0_TxInfo)&0xf0ff) | BIT(8) ); // b11-b8=0001 RTL_W32(0x80c, RTL_R32(0x80c) | BIT(21) ); // assign antenna by tx desc // CCK setting RTL_W8(0xa01, RTL_R8(0xa01) | BIT(7)); // enable hw ant diversity RTL_W8(0xa0c, (RTL_R8(0xa0c) & 0xe0) | 0x0f ); // b4=0, b3:0 = 1111 32 sample RTL_W8(0xa11, RTL_R8(0xa11) | BIT(5)); // do not change default optional antenna RTL_W8(0xa14, (RTL_R8(0xa14) & 0xe0) | 0x08 ); // default : optional = 1:1 #ifdef GPIO_ANT_SWITCH PHY_SetBBReg(priv, rFPGA0_XCD_RFParameter, 0x40000000, 0x01); // enable ANTSEL #endif } void setRxIdleAnt(struct rtl8192cd_priv *priv, char Ant) { if(priv->pshare->rf_ft_var.CurAntenna != Ant) { if(Ant) { RTL_W32(0x858, 0x65a965a9); // RTL_W8(0x6d8, RTL_R8(0x6d8) | BIT(6) ); } else { RTL_W32(0x858, 0x569a569a); // RTL_W8(0x6d8, RTL_R8(0x6d8) & (~ BIT(6))); } priv->pshare->rf_ft_var.CurAntenna = Ant; } } void dm_STA_Ant_Select(struct rtl8192cd_priv *priv, struct stat_info *pstat) { int ScoreA=0, ScoreB=0, i, nextAnt= pstat->CurAntenna, idleAnt=priv->pshare->rf_ft_var.CurAntenna; if((priv->pshare->rf_ft_var.CurAntenna & 0x80) || ((pstat->hwRxAntSel[0] + pstat->hwRxAntSel[1])==0 && (pstat->cckPktCount[0] + pstat->cckPktCount[1])<10) ) return; for(i=0; i<2; i++) { if(pstat->cckPktCount[i]==0 && pstat->hwRxAntSel[i]==0) pstat->AntRSSI[i] = 0; } if(pstat->hwRxAntSel[0] || pstat->hwRxAntSel[1]) { ScoreA = pstat->hwRxAntSel[0]; ScoreB = pstat->hwRxAntSel[1]; if(ScoreA != ScoreB) { if(ScoreA > ScoreB) nextAnt = 0; else nextAnt = 1; } } else { ScoreA = pstat->cckPktCount[0]; ScoreB = pstat->cckPktCount[1]; if(ScoreA > 5*ScoreB) nextAnt = 0; else if(ScoreB > 5*ScoreA) nextAnt = 1; else if(ScoreA > ScoreB) nextAnt = 1; else if(ScoreB > ScoreA) nextAnt = 0; } pstat->CurAntenna = nextAnt; if(priv->pshare->rf_ft_var.ant_dump&2) { panic_printk("id=%d, OFDM/CCK: (%d, %d/%d, %d), RSSI:(%d, %d), ant=%d, RxIdle=%d\n", pstat->aid, pstat->hwRxAntSel[1], pstat->hwRxAntSel[0], pstat->cckPktCount[1], pstat->cckPktCount[0], pstat->AntRSSI[1], pstat->AntRSSI[0], (pstat->CurAntenna==0 ? 2: 1) ,((priv->pshare->rf_ft_var.CurAntenna&1)==0 ? 2 : 1) ); } if(pstat->AntRSSI[idleAnt]==0) pstat->AntRSSI[idleAnt] = pstat->AntRSSI[idleAnt^1]; // reset variables pstat->hwRxAntSel[1] = pstat->hwRxAntSel[0] =0; pstat->cckPktCount[1]= pstat->cckPktCount[0] =0; } void dm_HW_IdleAntennaSelect(struct rtl8192cd_priv *priv) { struct stat_info *pstat, *pstat_min=NULL; struct list_head *phead, *plist; int rssi_min= 0xff, i; if(priv->pshare->rf_ft_var.CurAntenna & 0x80) return; phead = &priv->asoc_list; plist = phead->next; while(plist != phead) { pstat = list_entry(plist, struct stat_info, asoc_list); if((pstat->expire_to) && (pstat->AntRSSI[0] || pstat->AntRSSI[1])) { int rssi = (pstat->AntRSSI[0] < pstat->AntRSSI[1]) ? pstat->AntRSSI[0] : pstat->AntRSSI[1]; if((!pstat_min) || ( rssi < rssi_min) ) { pstat_min = pstat; rssi_min = rssi; } } if (plist == plist->next) break; plist = plist->next; }; if(pstat_min) setRxIdleAnt(priv, pstat_min->CurAntenna); #ifdef TX_SHORTCUT if (!priv->pmib->dot11OperationEntry.disable_txsc) { plist = phead->next; while(plist != phead) { pstat = list_entry(plist, struct stat_info, asoc_list); if(pstat->expire_to) { for (i=0; itx_sc_ent[i].hwdesc1); pdesc->Dword2 &= set_desc(~ (BIT(24)|BIT(25))); if((pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1) pdesc->Dword2 |= set_desc(BIT(24)|BIT(25)); pdesc= &(pstat->tx_sc_ent[i].hwdesc2); pdesc->Dword2 &= set_desc(~ (BIT(24)|BIT(25))); if((pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1) pdesc->Dword2 |= set_desc(BIT(24)|BIT(25)); } } if (plist == plist->next) break; plist = plist->next; }; } #endif } int diversity_antenna_select(struct rtl8192cd_priv *priv, unsigned char *data) { int ant = _atoi(data, 16); #ifdef PCIE_POWER_SAVING PCIeWakeUp(priv, POWER_DOWN_T0); #endif if (ant==Antenna_L || ant==Antenna_R) { #ifdef GPIO_ANT_SWITCH if(priv->pshare->rf_ft_var.antSw_enable) { PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, ant); } else #endif { if ( !priv->pshare->rf_ft_var.antSw_select) { RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(8)| BIT(9) ); // ANTSEL A as SW control RTL_W8(0xc50, RTL_R8(0xc50) & (~ BIT(7))); // rx OFDM SW control PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, 0x300, ant); } else { RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(24)| BIT(25) ); // ANTSEL B as HW control PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, 0x300, ant); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, RTL_R8(0xc58) & (~ BIT(7))); // rx OFDM SW control #endif } RTL_W8(0xa01, RTL_R8(0xa01) & (~ BIT(7))); // rx CCK SW control RTL_W32(0x80c, RTL_R32(0x80c) & (~ BIT(21))); // select ant by tx desc RTL_W32(0x858, 0x569a569a); } if(HW_DIV_ENABLE) priv->pshare->rf_ft_var.antHw_enable = BIT(5); priv->pshare->rf_ft_var.CurAntenna = (ant%2); #ifdef SW_ANT_SWITCH if(priv->pshare->rf_ft_var.antSw_enable) priv->pshare->rf_ft_var.antSw_enable = BIT(5); priv->pshare->DM_SWAT_Table.CurAntenna = ant; priv->pshare->RSSI_test =0; #endif } else if(ant==0){ #ifdef GPIO_ANT_SWITCH if(priv->pshare->rf_ft_var.antHw_enable) #endif { if (!priv->pshare->rf_ft_var.antSw_select) { RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(8)| BIT(9)) ); RTL_W8(0xc50, RTL_R8(0xc50) | BIT(7)); // OFDM HW control } else { RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(24)| BIT(25)) ); #if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) if ( #ifdef CONFIG_RTL_92C_SUPPORT (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) #endif #ifdef CONFIG_RTL_92D_SUPPORT #ifdef CONFIG_RTL_92C_SUPPORT || #endif (GET_CHIP_VER(priv)==VERSION_8192D) #endif ) RTL_W8(0xc58, RTL_R8(0xc58) | BIT(7)); // OFDM HW control #endif } RTL_W8(0xa01, RTL_R8(0xa01) | BIT(7)); // CCK HW control RTL_W32(0x80c, RTL_R32(0x80c) | BIT(21) ); // by tx desc priv->pshare->rf_ft_var.CurAntenna = 0; RTL_W32(0x858, 0x569a569a); priv->pshare->rf_ft_var.antHw_enable = 1; #ifdef SW_ANT_SWITCH priv->pshare->rf_ft_var.antSw_enable = 0; priv->pshare->RSSI_test =0; #endif } #ifdef SW_ANT_SWITCH if(priv->pshare->rf_ft_var.antSw_enable) { dm_SW_AntennaSwitchInit(priv); RTL_W32(0x858, 0x569a569a); priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; priv->pshare->rf_ft_var.antHw_enable = 0; priv->pshare->rf_ft_var.antSw_enable = 1; } #endif } #if defined(SW_ANT_SWITCH) && !defined(GPIO_ANT_SWITCH) else if(ant==3) { if(!priv->pshare->rf_ft_var.antSw_enable) { dm_SW_AntennaSwitchInit(priv); RTL_W32(0x858, 0x569a569a); priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; } #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv)==VERSION_8188E) { RTL_W8(0xc50, RTL_R8(0xc50) & (~ BIT(7))); // rx OFDM SW control } else #endif { if ( !priv->pshare->rf_ft_var.antSw_select) RTL_W8(0xc50, RTL_R8(0xc50) & (~ BIT(7))); // rx OFDM SW control else RTL_W8(0xc58, RTL_R8(0xc58) & (~ BIT(7))); // rx OFDM SW control } RTL_W8(0xa01, RTL_R8(0xa01) & (~ BIT(7))); // rx CCK SW control RTL_W32(0x80c, RTL_R32(0x80c) & (~ BIT(21))); // select ant by tx desc priv->pshare->rf_ft_var.antHw_enable = 0; priv->pshare->rf_ft_var.antSw_enable = 1; } #endif return 1; } #endif //3 ============================================================ //3 Dynamic Noise Control //3 ============================================================ #if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) void dnc_timer(unsigned long task_priv) { struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; struct stat_info *pstat = NULL; unsigned int set_timer = 0; unsigned long flags; if (!(priv->drv_state & DRV_STATE_OPEN)) return; if (timer_pending(&priv->dnc_timer)) del_timer_sync(&priv->dnc_timer); #ifdef PCIE_POWER_SAVING if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) return; #endif if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07600760); PHY_SetBBReg(priv, 0xc50, bMaskByte0, 0x20); PHY_SetBBReg(priv, 0xc58, bMaskByte0, 0x20); } } #endif //3 ============================================================ //3 Leaving STA check //3 ============================================================ #if defined(DETECT_STA_EXISTANCE) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) // Check for STA existance. If STA disappears, disconnect it. Added by Annie, 2010-08-10. void DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat) { unsigned char tmpbuf[16]; // Parameters const unsigned int maxTxFailCnt = 300; // MAX Tx fail packet count const unsigned int minTxFailCnt = 30; // MIN Tx fail packet count; this value should be less than maxTxFailCnt. const unsigned int txFailSecThr= 3; // threshold of Tx Fail Time (in second) // Temporarily change Retry Limit when TxFail. (tfrl: TxFailRetryLimit) const unsigned char TFRL = 7; // New Retry Limit value const unsigned char TFRL_FailCnt = 2; // Tx Fail Count threshold to set Retry Limit const unsigned char TFRL_SetTime = 2; // Time to set Retry Limit (in second) const unsigned char TFRL_RcvTime = 10; // Time to recover Retry Limit (in second) if( report->txok != 0 ) { // Reset Counter pstat->tx_conti_fail_cnt = 0; pstat->tx_last_good_time = priv->up_time; pstat->leave = 0; } else if( report->txfail != 0 ) { pstat->tx_conti_fail_cnt += report->txfail; DEBUG_WARN( "detect: txfail=%d, tx_conti_fail_cnt=%d\n", report->txfail, pstat->tx_conti_fail_cnt ); if( priv->up_time >= (pstat->tx_last_good_time+TFRL_SetTime) && pstat->tx_conti_fail_cnt >= TFRL_FailCnt && //!pstat->ht_cap_len && // legacy rate only !priv->pshare->bRLShortened ) { // Shorten retry limit, because AP spending too much time to send out g mode STA pending packets in HW queue. RTL_W16(RL, (TFRL&SRL_Mask)<pshare->bRLShortened = TRUE; DEBUG_WARN( "== Shorten RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); } if( (pstat->tx_conti_fail_cnt >= maxTxFailCnt) || (pstat->tx_conti_fail_cnt >= minTxFailCnt && priv->up_time >= (pstat->tx_last_good_time+txFailSecThr) ) ) { // This STA is considered as disappeared, so delete it. DEBUG_WARN( "** tx_conti_fail_cnt=%d (min=%d,max=%d)\n", pstat->tx_conti_fail_cnt, minTxFailCnt, maxTxFailCnt); DEBUG_WARN( "** tx_last_good_time=%d, up_time=%d (Thr:%d)\n", (int)pstat->tx_last_good_time, (int)priv->up_time, txFailSecThr ); DEBUG_WARN( "AP is going to del_sta %02X:%02X:%02X:%02X:%02X:%02X\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5] ); sprintf((char *)tmpbuf, "%02x%02x%02x%02x%02x%02x", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); // del_sta(priv, tmpbuf); ++(pstat->leave); if (timer_pending(&priv->pshare->rl_recover_timer)) del_timer_sync (&priv->pshare->rl_recover_timer); mod_timer(&priv->pshare->rl_recover_timer, jiffies + EXPIRE_TO*TFRL_RcvTime); // Reset Counter pstat->tx_conti_fail_cnt = 0; pstat->tx_last_good_time = priv->up_time; } } } // Timer callback function to recover hardware retry limit register. Added by Annie, 2010-08-10. void RetryLimitRecovery(unsigned long task_priv) { struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; if( priv->pshare->bRLShortened ) { RTL_W16(RL, (priv->pshare->RLShort&SRL_Mask)<pshare->RLLong&LRL_Mask)<pshare->bRLShortened = FALSE; DEBUG_WARN( "== Recover RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); } } // Chack STA leaving status; per interface. Added by Annie, 2010-08-10. unsigned char NoLeavingSTA(struct rtl8192cd_priv *priv) { unsigned char bStaAllOK = TRUE; struct list_head *phead, *plist; struct stat_info *pstat; phead = &priv->asoc_list; if (!netif_running(priv->dev) || list_empty(phead)) return bStaAllOK; plist = phead->next; while (plist != phead) { pstat = list_entry(plist, struct stat_info, asoc_list); if( pstat->tx_conti_fail_cnt != 0 ) { bStaAllOK = FALSE; break; } plist = plist->next; } return bStaAllOK; } // Chack STA leaving status for all active interface and recover retry limit register value. Added by Annie, 2010-08-10. void LeavingSTA_RLCheck(struct rtl8192cd_priv *priv) { unsigned char bIfAllOK = TRUE; static int AllOKTimes = 0; #ifdef MBSSID int i; #endif // Parameter const unsigned char TFRL_RcvTime = 10; // Time to recover Retry Limit (in second) if( !NoLeavingSTA(priv) ) bIfAllOK = FALSE; #ifdef UNIVERSAL_REPEATER if (IS_ROOT_INTERFACE(priv) && GET_VXD_PRIV(priv) ) { if( !NoLeavingSTA(GET_VXD_PRIV(priv)) ) bIfAllOK = FALSE; } #endif #ifdef MBSSID if (IS_ROOT_INTERFACE(priv)) { if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { for (i=0; ipvap_priv[i])) { if( !NoLeavingSTA(priv->pvap_priv[i]) ) bIfAllOK = FALSE; } } } } #endif if( bIfAllOK ) { AllOKTimes ++; if( AllOKTimes >= TFRL_RcvTime ) RetryLimitRecovery((unsigned long)priv); } else { AllOKTimes = 0; } } #endif #endif