RTL8192CU and Linux 3.13.10

Hardware: TP-Link TL-WN823N v1.1

Status: As of kernel 3.13.10, the in-tree rtl8192cu driver (in drivers/net/wireless/rtlwifi) is still broken. It will work and connect, but will silently disconnect after some time (and light traffic?). There is also some packet loss (around 1%).

Realtek’s vendor driver “8192cu” (version 4.0.2_9000.20130911) has worked flawlessly so far. There are some fixes needed to compile Realtek’s driver with kernel 3.11+, available here: https://github.com/pvaret/rtl8192cu-fixes

I’ve only tested it with 802.11g. No comment on 802.11n.


Debugging notes

I don’t have much understanding of the Linux 802.11 drivers or Realtek chips to understand what’s going on. The following are some observations of the debug output around the time the connection is lost.

Looking at the debug messages when loading rtl8192cu with debug=5, the only messages that correlate with the moment the connection drops appears to be messages from rtl92c_dm_write_dig(). In the following messages, the failure occurred at 12:04:08 +/- 0.5 seconds. cur_igvalue is fairly stable around 0x20 until just before failure, after which it steadily increases to around 0x2a. Notice also that dm_digitable->large_fa_hit (second-last parameter in the list of “dig values”) becomes 1 a few seconds before failure, corresponding to a “false alarm” cnt_all greater than 0x2710 (10000).

Apr 21 12:03:41 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x22, pre_igvalue = 0x20, back_val = 12
Apr 21 12:03:41 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x21 0x21 0x22 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:41 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 86, cnt_rate_illegal = 112, cnt_crc8_fail = 4, cnt_mcs_fail = 4
Apr 21 12:03:41 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = d0, cnt_cck_fail = 16, cnt_all = e4
Apr 21 12:03:43 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x21, pre_igvalue = 0x21, back_val = 12
Apr 21 12:03:43 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x20 0x20 0x22 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:43 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 113, cnt_rate_illegal = 138, cnt_crc8_fail = 3, cnt_mcs_fail = 3
Apr 21 12:03:43 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 102, cnt_cck_fail = 0, cnt_all = 101
Apr 21 12:03:45 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x1f, pre_igvalue = 0x20, back_val = 12
Apr 21 12:03:45 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x1e 0x1e 0x28 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:45 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 123, cnt_rate_illegal = 120, cnt_crc8_fail = 6, cnt_mcs_fail = 5
Apr 21 12:03:45 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 105, cnt_cck_fail = 0, cnt_all = fe
Apr 21 12:03:47 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x1e, pre_igvalue = 0x1e, back_val = 12
Apr 21 12:03:47 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x1e 0x1e 0x28 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:47 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 3863, cnt_rate_illegal = 3909, cnt_crc8_fail = 146, cnt_mcs_fail = 133
Apr 21 12:03:47 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 1f7c, cnt_cck_fail = 1e, cnt_all = 1f91
Apr 21 12:03:49 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x20, pre_igvalue = 0x1e, back_val = 12
Apr 21 12:03:49 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x1f 0x1f 0x1c 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:49 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 3768, cnt_rate_illegal = 3831, cnt_crc8_fail = 139, cnt_mcs_fail = 125
Apr 21 12:03:49 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 1ec2, cnt_cck_fail = 33, cnt_all = 1eea
Apr 21 12:03:51 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x21, pre_igvalue = 0x1f, back_val = 12
Apr 21 12:03:51 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x20 0x20 0x22 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:51 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 3842, cnt_rate_illegal = 3845, cnt_crc8_fail = 152, cnt_mcs_fail = 129
Apr 21 12:03:51 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 1f32, cnt_cck_fail = 44, cnt_all = 1f64
Apr 21 12:03:53 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x22, pre_igvalue = 0x20, back_val = 12
Apr 21 12:03:53 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x21 0x21 0x22 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:53 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 94, cnt_rate_illegal = 99, cnt_crc8_fail = 4, cnt_mcs_fail = 4
Apr 21 12:03:53 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = cb, cnt_cck_fail = 45, cnt_all = 10e
Apr 21 12:03:55 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x20, pre_igvalue = 0x21, back_val = 12
Apr 21 12:03:55 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x1f 0x1f 0x1c 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:55 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 128, cnt_rate_illegal = 117, cnt_crc8_fail = 4, cnt_mcs_fail = 3
Apr 21 12:03:55 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 104, cnt_cck_fail = 0, cnt_all = fc
Apr 21 12:03:57 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x1e, pre_igvalue = 0x1f, back_val = 12
Apr 21 12:03:57 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x1e 0x1e 0x22 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:57 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 4199, cnt_rate_illegal = 4250, cnt_crc8_fail = 153, cnt_mcs_fail = 129
Apr 21 12:03:57 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 2257, cnt_cck_fail = 27, cnt_all = 2242
Apr 21 12:03:59 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x20, pre_igvalue = 0x1e, back_val = 12
Apr 21 12:03:59 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x1f 0x1f 0x22 0xc 0x3e 0x1e 0x0 0x1e
Apr 21 12:03:59 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 4953, cnt_rate_illegal = 5025, cnt_crc8_fail = 212, cnt_mcs_fail = 170
Apr 21 12:03:59 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 2a9d, cnt_cck_fail = 13, cnt_all = 288b
Apr 21 12:04:01 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x21, pre_igvalue = 0x1f, back_val = 12
Apr 21 12:04:01 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x20 0x20 0x1c 0xc 0x3e 0x1e 0x1 0x1f
Apr 21 12:04:01 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 5058, cnt_rate_illegal = 5003, cnt_crc8_fail = 180, cnt_mcs_fail = 157
Apr 21 12:04:01 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 2dc4, cnt_cck_fail = 18, cnt_all = 28b6
Apr 21 12:04:03 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x22, pre_igvalue = 0x20, back_val = 12
Apr 21 12:04:03 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x21 0x21 0x26 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:03 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 1564, cnt_rate_illegal = 1586, cnt_crc8_fail = 61, cnt_mcs_fail = 55
Apr 21 12:04:03 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 11fd, cnt_cck_fail = 4, cnt_all = cc6
Apr 21 12:04:05 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x23, pre_igvalue = 0x21, back_val = 12
Apr 21 12:04:05 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x22 0x22 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:05 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 1527, cnt_rate_illegal = 1512, cnt_crc8_fail = 61, cnt_mcs_fail = 54
Apr 21 12:04:05 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 14ff, cnt_cck_fail = a, cnt_all = c5c
Apr 21 12:04:07 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x24, pre_igvalue = 0x22, back_val = 12
Apr 21 12:04:07 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x23 0x23 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:07 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 1518, cnt_rate_illegal = 1501, cnt_crc8_fail = 49, cnt_mcs_fail = 44
Apr 21 12:04:07 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = c75, cnt_cck_fail = 9, cnt_all = c31
Apr 21 12:04:09 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x25, pre_igvalue = 0x23, back_val = 12
Apr 21 12:04:09 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x24 0x24 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:09 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 1416, cnt_rate_illegal = 1497, cnt_crc8_fail = 58, cnt_mcs_fail = 55
Apr 21 12:04:09 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = fd3, cnt_cck_fail = 7, cnt_all = bd9
Apr 21 12:04:11 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x26, pre_igvalue = 0x24, back_val = 12
Apr 21 12:04:11 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x25 0x25 0x1e 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:11 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 1436, cnt_rate_illegal = 1462, cnt_crc8_fail = 55, cnt_mcs_fail = 52
Apr 21 12:04:11 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 108f, cnt_cck_fail = 4, cnt_all = bc1
Apr 21 12:04:13 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x27, pre_igvalue = 0x25, back_val = 12
Apr 21 12:04:13 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x26 0x26 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:13 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 1496, cnt_rate_illegal = 1529, cnt_crc8_fail = 56, cnt_mcs_fail = 51
Apr 21 12:04:13 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = dfc, cnt_cck_fail = b, cnt_all = c47
Apr 21 12:04:15 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x26, back_val = 12
Apr 21 12:04:15 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:15 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 415, cnt_rate_illegal = 408, cnt_crc8_fail = 13, cnt_mcs_fail = 12
Apr 21 12:04:15 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 3ab, cnt_cck_fail = 0, cnt_all = 350
Apr 21 12:04:17 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:17 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:17 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 430, cnt_rate_illegal = 438, cnt_crc8_fail = 18, cnt_mcs_fail = 18
Apr 21 12:04:17 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 3ae, cnt_cck_fail = 0, cnt_all = 388
Apr 21 12:04:19 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:19 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:19 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 372, cnt_rate_illegal = 387, cnt_crc8_fail = 11, cnt_mcs_fail = 10
Apr 21 12:04:19 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 32e, cnt_cck_fail = 3, cnt_all = 30f
Apr 21 12:04:21 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:21 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x28 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:21 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 392, cnt_rate_illegal = 421, cnt_crc8_fail = 17, cnt_mcs_fail = 15
Apr 21 12:04:21 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 36a, cnt_cck_fail = 0, cnt_all = 34d
Apr 21 12:04:23 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:23 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x28 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:23 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 467, cnt_rate_illegal = 473, cnt_crc8_fail = 17, cnt_mcs_fail = 15
Apr 21 12:04:23 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 3e6, cnt_cck_fail = 0, cnt_all = 3cc
Apr 21 12:04:25 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:25 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x28 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:25 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 416, cnt_rate_illegal = 403, cnt_crc8_fail = 13, cnt_mcs_fail = 12
Apr 21 12:04:25 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 367, cnt_cck_fail = 0, cnt_all = 34c
Apr 21 12:04:27 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:27 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x28 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:27 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 415, cnt_rate_illegal = 398, cnt_crc8_fail = 16, cnt_mcs_fail = 12
Apr 21 12:04:27 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 35c, cnt_cck_fail = 4, cnt_all = 34d
Apr 21 12:04:29 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x28, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:29 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x27 0x27 0x28 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:29 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 609, cnt_rate_illegal = 608, cnt_crc8_fail = 29, cnt_mcs_fail = 26
Apr 21 12:04:29 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 4f9, cnt_cck_fail = 0, cnt_all = 4f8
Apr 21 12:04:31 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x29, pre_igvalue = 0x27, back_val = 12
Apr 21 12:04:31 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x28 0x28 0x27 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:31 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 683, cnt_rate_illegal = 666, cnt_crc8_fail = 20, cnt_mcs_fail = 16
Apr 21 12:04:31 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 56a, cnt_cck_fail = 3, cnt_all = 56c
Apr 21 12:04:33 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2a, pre_igvalue = 0x28, back_val = 12
Apr 21 12:04:33 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x29 0x29 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:33 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 672, cnt_rate_illegal = 675, cnt_crc8_fail = 24, cnt_mcs_fail = 19
Apr 21 12:04:33 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 57f, cnt_cck_fail = 0, cnt_all = 56e
Apr 21 12:04:35 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2b, pre_igvalue = 0x29, back_val = 12
Apr 21 12:04:35 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x2a 0x2a 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:35 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 593, cnt_rate_illegal = 580, cnt_crc8_fail = 21, cnt_mcs_fail = 19
Apr 21 12:04:35 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 567, cnt_cck_fail = 0, cnt_all = 4bd
Apr 21 12:04:37 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2c, pre_igvalue = 0x2a, back_val = 12
Apr 21 12:04:37 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x2b 0x2b 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:37 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 612, cnt_rate_illegal = 575, cnt_crc8_fail = 21, cnt_mcs_fail = 21
Apr 21 12:04:37 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 565, cnt_cck_fail = 0, cnt_all = 4cd
Apr 21 12:04:39 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2d, pre_igvalue = 0x2b, back_val = 12
Apr 21 12:04:39 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x2c 0x2c 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:39 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 559, cnt_rate_illegal = 576, cnt_crc8_fail = 22, cnt_mcs_fail = 19
Apr 21 12:04:39 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 5f4, cnt_cck_fail = 0, cnt_all = 498
Apr 21 12:04:41 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2e, pre_igvalue = 0x2c, back_val = 12
Apr 21 12:04:41 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x2d 0x2d 0x1c 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:41 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 180, cnt_rate_illegal = 189, cnt_crc8_fail = 7, cnt_mcs_fail = 7
Apr 21 12:04:41 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 17f, cnt_cck_fail = 0, cnt_all = 17f
Apr 21 12:04:43 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2c, pre_igvalue = 0x2d, back_val = 12
Apr 21 12:04:43 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x2b 0x2b 0x26 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:43 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 184, cnt_rate_illegal = 183, cnt_crc8_fail = 6, cnt_mcs_fail = 5
Apr 21 12:04:43 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 17c, cnt_cck_fail = 4, cnt_all = 17e
Apr 21 12:04:45 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2a, pre_igvalue = 0x2b, back_val = 12
Apr 21 12:04:45 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x29 0x29 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:45 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 598, cnt_rate_illegal = 584, cnt_crc8_fail = 20, cnt_mcs_fail = 16
Apr 21 12:04:45 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 5b0, cnt_cck_fail = 3, cnt_all = 4c5
Apr 21 12:04:47 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> cur_igvalue = 0x2b, pre_igvalue = 0x29, back_val = 12
Apr 21 12:04:47 pvr kernel: rtl8192c_common:rtl92c_dm_write_dig():<0-0> dig values 0x2a 0x2a 0x22 0xc 0x3e 0x1e 0x1 0x20
Apr 21 12:04:47 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_parity_fail = 541, cnt_rate_illegal = 577, cnt_crc8_fail = 27, cnt_mcs_fail = 26
Apr 21 12:04:47 pvr kernel: rtl8192c_common:rtl92c_dm_false_alarm_counter_statistics():<0-0> cnt_ofdm_fail = 66d, cnt_cck_fail = 0, cnt_all = 493

My guess is that rtl92c_dm_write_dig() is being called from rtl92c_dm_ctrl_initgain_by_rssi (rtlwifi/rtl8192c/dm_common.c). Inside there, digtable->large_fa_hit seems to be counting instances (two-second periods?) where there are more than 10000 “false alarm” cnt_all (whatever that is), giving it three chances before setting some 2-hour timer (line 358). The logic around line 365 doesn’t look quite right for large_fa_hit greater than 0 but less than 3, because large_fa_hit never decreases until it reaches 3 and a two-hour timeout, but some digtable->forbidden_igi updates get turned off when large_fa_hit is non-zero. However, the Realtek vendor driver also has the same code, so this may not be the direct cause of the problem.

rtlwifi/rtl8192c/dm_common.c:

static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct dig_t *digtable = &rtlpriv->dm_digtable;
	u32 isbt;

	/* modify DIG lower bound, deal with abnorally large false alarm */
	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
		digtable->large_fa_hit++;
		if (digtable->forbidden_igi < digtable->cur_igvalue) {
			digtable->forbidden_igi = digtable->cur_igvalue;
			digtable->large_fa_hit = 1;
		}

		if (digtable->large_fa_hit >= 3) {
			if ((digtable->forbidden_igi + 1) >
			    digtable->rx_gain_max)
				digtable->rx_gain_min = digtable->rx_gain_max;
			else
				digtable->rx_gain_min = (digtable->forbidden_igi + 1);
			digtable->recover_cnt = 3600; /* 3600=2hr */
		}
	} else {
		/* Recovery mechanism for IGI lower bound */
		if (digtable->recover_cnt != 0) {
			digtable->recover_cnt--;
		} else {
			if (digtable->large_fa_hit == 0) {   // <--- what about for 0 < large_fa_hit < 3 ?
				if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {
					digtable->forbidden_igi = DM_DIG_MIN;
					digtable->rx_gain_min = DM_DIG_MIN;
				} else {
					digtable->forbidden_igi--;
					digtable->rx_gain_min = digtable->forbidden_igi + 1;
				}
			} else if (digtable->large_fa_hit == 3) {
				digtable->large_fa_hit = 0;
			}
		}
	}
	if (rtlpriv->falsealm_cnt.cnt_all < 250) {
		isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;

		if (!isbt) {
			if (rtlpriv->falsealm_cnt.cnt_all >
			    digtable->fa_lowthresh) {
				if ((digtable->back_val - 2) <
				   digtable->back_range_min)
					digtable->back_val = digtable->back_range_min;
				else
					digtable->back_val -= 2;
			} else if (rtlpriv->falsealm_cnt.cnt_all <
				   digtable->fa_lowthresh) {
				if ((digtable->back_val + 2) >
				    digtable->back_range_max)
					digtable->back_val = digtable->back_range_max;
				else
					digtable->back_val += 2;
			}
		} else {
			digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
		}
	} else {
		/* Adjust initial gain by false alarm */
		if (rtlpriv->falsealm_cnt.cnt_all > 1000)
			digtable->cur_igvalue = digtable->pre_igvalue + 2;
		else if (rtlpriv->falsealm_cnt.cnt_all > 750)
			digtable->cur_igvalue = digtable->pre_igvalue + 1;
		else if (rtlpriv->falsealm_cnt.cnt_all < 500)
			digtable->cur_igvalue = digtable->pre_igvalue - 1;
	}

	/* Check initial gain by upper/lower bound */
	if (digtable->cur_igvalue > digtable->rx_gain_max)
		digtable->cur_igvalue = digtable->rx_gain_max;

	if (digtable->cur_igvalue < digtable->rx_gain_min)
		digtable->cur_igvalue = digtable->rx_gain_min;

	rtl92c_dm_write_dig(hw);
}

Perhaps a better question is why the “false alarm” count is suddenly so high (is this some kind of error counter?). Why is it called “false alarm”? Hmm… this looks familiar: http://www.google.com/patents/US20130308731

16 comments to RTL8192CU and Linux 3.13.10

  • Peter

    Coming across your article cheered me up enormously. Rather than rant about the rtl8192cu support on linux, you seem to want to really get to the bottom of what’s wrong with it.

    I’ve struggled for a couple of years to get this thing to work. The Realtek driver worked fine till I stopped being able to build it. (I’m now on kernel 3.14.4 under fedora.) Then the standard linux driver amazingly seemed to work for a bit with an old wireless router I had. It simply won’t work with a new router, however I configure things. The networking seems to be perfectly set up, with all the right IP addresses and gateways and routing. But unless I run a perpetual 1-a-second ping against the router, within seconds the thing dies, and I have to ifdown it, ifup it, and immediately start the ping. (Then, it seems to work fine, and indeed seems to function rather well.)

    I wish I could help. Its been over 3 decades since I worked in system software. But I’m just about narked enough to try to get my head around the bloody driver.

    Have you any hypotheses about why the thing works providing there’s a perpetual ping (in *or* out, BTW)?

    [I might mention that although the dongle and the router are quite close in the same room, for marital reasons they’re also quite close to a phone base-station, so noise may be an issue. OTOH, the situation was even worse with my old router, with which the dongle worked without special measures.]

    I’m not really looking for tips or configuration tweaks. This thing has consumed, end-to-end weeks of my time, and I guess the same goes for maybe a hundred thousand other people. What a waste of human life. It’s time to get to the bottom of it.

    • Henry

      Did you try compiling with the 8192-fixes changes? That worked for me in 3.13, which hopefully isn’t too different from 3.14.

      I have no hypothesis about why perpetual ping keeps the connection going. That actually wasn’t enough for me.

      It’s actually a little strange because the code is quite similar between the vendor driver and the kernel driver. I read through some of the functions and they’re actually identical code with different formatting (to conform with Kernel code styles, I suppose). The drivers are subtly different somewhere, but not in the parts that I read though and could understand.

  • Peter

    Well, I haven’t yet, partly because my (fedora19) distribution uses .rpms rather than whatever Ubuntu uses. But I’ve just now cloned the git repository, and it might not be beyond me to figure out what needs to be done. Certainly worth a try. I did something similar on fedora (applying patches from somewhere) till about a year(?) ago when the linux driver started to work for me with the router I was using at the time. (Probably by the skin on its teeth…)

    I’ll if I can get anywhere with what’s in rtl8192cu-fixes. A quick google tells me ” DKMS supports both the RPM and DEB package formats out-of-the-box” so it may be easier than I thought.

    • Henry

      I’m using Mageia, so it’s also RPM based. In my case, I just compiled it without DKMS or packaging it as an RPM, so package management didn’t get involved. (Though without DKMS, you’d have to manually recompile after every kernel upgrade)

      If I remember correctly, it was as simple as running make to build 8192cu.ko, copying that into /lib/modules/<kernel version>/drivers/net/wireless, running depmod -a, and blacklisting rtl8192cu.

  • Peter

    Thanks! By the time you wrote that I’d installed dkms and did what the README.md told me to do. I’m not sure exactly what went on but it built me a new initramfs and heaven knows what else. The new module turned up in /lib/modules/3.14.5-100.fc19.i686/extra/8192cu.ko. After depmod -a, and blacklisting the old module, the system booted fine, though sadly with no wireless. In a way I wish I’d not involved dkms.

    I’m sure it’s something trivial, but someone else needs to use that machine for a while. The old initramfs was preserved, and using it I booted back to the original situation.
    I’ll investigate later on this evening.

  • Peter

    After a little “user error”, the driver at https://github.com/pvaret/rtl8192cu-fixes.git apparently works — when installed by hand (your way) rather than dkms. (I’d an old file in /etc/modprobe.d that blacklisted 8192cu!)

    My first observation is that the ping times to the machine are now about 5ms (with the occasional 100ms), whereas with the “native” driver, the times were about 1ms (with the occassional 20ms). (But now I don’t need pings to keep the machine on the air.)

    Also the new driver has a lot of (inscrutable!) parameters (37), whereas the native one had only 2 (swenc and debug).

    I’ll have a browse around the two bodies of code.

    • Henry

      Glad to hear it worked 🙂 Given how dkms did manage to build a .ko, it probably would have worked too, if 8192cu weren’t blacklisted…

      I think the ping times are a lot higher due to power management. It’s particularly noticeable when pinging from another machine. It’s typically 70-90ms for me. You can tell it’s power management because if you ping it at a higher packet rate (say, 10 per second or more), the ping time drops to just under 1ms. The vendor driver package has documentation about what it does: (documentation/HowTo_enable_the_power_saving_functionality.pdf). The device wakes up at beacon intervals (typically 102.4ms?) to check for traffic when in sleep mode.

  • Peter

    I’m feeling rather crosseyed after browsing through the code — basically almost nothing makes any sense to me and I doubt it ever will.

    However there’s been some recent discussion on a kernel mailing list about a logic error in a function called _rtl92cu_set_media_status in drivers/net/wireless/rtlwifi/rtl8192cu/hw.c. I found it at:
    http://www.gossamer-threads.com/lists/linux/kernel/1940427?search_string=rtlwifi;#1940427

    There’s another bug people seem to know about where the driver disables interrupts for some horrific length of time (same file):
    http://www.gossamer-threads.com/lists/linux/kernel/1940727?search_string=rtlwifi;#1940727

    I suppose eventually these will get patched. Frankly I can’t remember the rigmarole to make corrections myself and rebuild the kernel.

    To me it was interesting to read that the first bug was found using some tool (cppcheck) doing a static analysis of the code. Maybe we’d all get more of lives back if it was routine to use such tools.

    I expect there are several bugs in the driver, and fixing one may only make others worse.

    BTW, I switched back to using the native driver (with a perpetual ping). At one point I noticed that my wireless device seemed to be associated without any authentication, which ought to have been utterly impossible, for several reasons….

  • Reinhard

    Thank you very very much ! Your fixed version compiles with Linux 3.16.0 and works on my seagate dockstar (ARM).

  • Marty

    I’ve been fighting this problem all day. I am using Arch Linux on a Raspberry Pi B+ with a no-name b/g/n USB 2.0 wifi adapter I bought on eBay which uses the Realtek RTL8192cu chip.

    I use wifi-menu to scan and connect to my home network and it seems to work fine, but after a short period of inactivity the wifi adapter stops responding, to inbound pings for example, or any other inbound traffic. If I do something outbound, ping for example, it comes back to life until more inactivity. I found that I could keep it working by running a neverending ping with a 5 second interval (I was pinging out from the Pi to another host on my network but seems like either direction would have worked).

    It seemed like some kind of power saving feature messing us up.

    Anyway, I didn’t want to have the hokey ping running all the time and that got me googling and that eventually lead me here.

    My Linux:
    [root@alarmpi ~]# uname -a
    Linux alarmpi 3.12.32-1-ARCH #1 PREEMPT Sat Nov 8 16:51:12 MST 2014 armv6l GNU/Linux

    [root@alarmpi ~]# lsb_release -a
    LSB Version: 1.4
    Distributor ID: Arch
    Description: Arch Linux
    Release: rolling
    Codename: n/a

    I am not much of a UNIX/Linux guy so the prospect of compiling the kernel and/or “kernel modules” was daunting and seemed like a huge detour from what I am actually working on. I was just going to switch to a different wifi dongle when I found this workaround.

    I downloaded the fixes:

    Per the Troubleshooting note here:

    I did:
    sudo cp ./rtl8192cu-fixes/8192cu-disable-power-management.conf /etc/modprobe.d/

    Then rebooted, and no more problem! THANK YOU, HENRY AND PETER! I’ve had an ssh session open all night and the connection is still alive. Previously it could not survive 5 minutes.

    So it was not necessary for me to build a KO driver file or build the “latest” kernel (I did not want to do this because of comments that it would be “less stable” – my project needs to run unattended for long periods of time).

    In retrospect, it *seems* like I could have just done:

    echo "options 8192cu rtw_power_mgnt=0 rtw_enusbss=0" > /etc/modprobe.d/8192cu-disable-power-management.conf

    and then rebooted and it would have fixed the problem, or at least implemented the workaround (I don’t actually care about the power saving junk).

    I’m just posting this for any other noobs like me who are not comfortable with all the detours in Linux, i.e. I just wanted to use a wifi dongle and the next thing you know I have to build this and that and it requires some additional package and that package requires three more packages but I really should use a cross-compile to “save time” (LOL) and then the repository is down and then I also need to make a “simple” configuration change but the change is obscured by having to learn the intricacies of the configuration utility for THIS particular distribution, etc etc etc.

    It is a lot of fun, though, when you finally get something to work and learn a new trick. Thank God for search engines and all the helpful people on the Internet.

  • Marty

    Third time charm? Troubleshooting note HERE: https://github.com/pvaret/rtl8192cu-fixes

  • Marty

    The “fix” I described doesn’t seem to be working reliably. Please disregard my previous posts. I think I’m going to go for the perpetual ping. As much as I hate to do it that way, it seems to work.

  • Avi

    Thanks for the links to github/pvaret – I finally got it to work!

  • glasspusher

    Hey, thanks for this. I bought a couple of monoprice USB/wifi dongles this week and have been suffering intermittent connections on a little single board computer I’m sending weather station data from. It’ll go OK for an hour or so, then drop out for an hour, re-connect. The chip is an Realtek 8192cu. I’ll try the ping method for the moment. I also have an old thinkpad T42 running xubuntu 14, I thought it was working OK on it, but what was I doing to check? Continual pinging of something!

    I’m no linux expert at all but will be happy to report how things work for me here and if I get really ambitious will try to build your solution from github. Trying to get my startup company going at the moment 😉

  • glasspusher

    Oh, hey, FWIW, these data give you an idea of the on/off nature of my connection. You can see where the data were being transmitted, and not. Very regular, at least…and it was able to re-connect regularly. Hmm.

    http://tinyurl.com/kvczb6c

Leave a Reply to Peter Cancel reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>