Other Parts Discussed in Thread: WL1271
We currently have a number of customers where we are seeing many of the "corrupted packet in RX" messages. These customers have also complained of unstable wireless network connections.
One customer is also seeing large number of "wlcore: WARNING no fw rx ba on tid x" message in the log.
We are using Wilink 1807 with embedded linux
MAC Version: Rev 8.9.0.0.76
PHY Version: Rev 8.2.0.0.240
We have tried keeping track of the number of corrupt packets and forcing a wilink reset if the counts exceeds a threshold, but this doesn't seem to be a viable workaround as the corrupt packets are still being received as soon as the wilink comes back up.
--- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -84,6 +84,7 @@ EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats); DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); +DEBUGFS_READONLY_FILE(corrupted_packets, "%u", wl->corrupted_packets); DEBUGFS_READONLY_FILE(excessive_retries, "%u", wl->stats.excessive_retries); @@ -1249,6 +1250,7 @@ DEBUGFS_ADD(tx_queue_len, rootdir); DEBUGFS_ADD(retry_count, rootdir); + DEBUGFS_ADD(corrupted_packets, rootdir); DEBUGFS_ADD(excessive_retries, rootdir); DEBUGFS_ADD(gpio_power, rootdir); --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -557,6 +557,16 @@ if (!intr) { done = true; continue; + } + + if (wl->corrupted_packets > 50){ + wl1271_error("Too many corrupt packets received (%d>50)! starting recovery.",wl->corrupted_packets); + wl->corrupted_packets = 0; + wl->watchdog_recovery = true; + ret = -EIO; + + /* restarting the chip. ignore any other interrupt. */ + goto out; } if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { @@ -5968,6 +5978,7 @@ wl->active_sta_count = 0; wl->active_link_count = 0; wl->fwlog_size = 0; + wl->corrupted_packets = 0; init_waitqueue_head(&wl->fwlog_waitq); /* The system link is always allocated */ @@ -5968,6 +5978,7 @@ wl->active_sta_count = 0; wl->active_link_count = 0; wl->fwlog_size = 0; + wl->corrupted_packets = 0; init_waitqueue_head(&wl->fwlog_waitq); /* The system link is always allocated */ --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -148,13 +148,15 @@ /* discard corrupted packets */ if (desc->status & WL1271_RX_DESC_DECRYPT_FAIL) { - hdr = (void *)(data + sizeof(*desc) + offset_to_data); + /*hdr = (void *)(data + sizeof(*desc) + offset_to_data); wl1271_warning("corrupted packet in RX: status: 0x%x len: %d", desc->status & WL1271_RX_DESC_STATUS_MASK, pkt_data_len); wl1271_dump((DEBUG_RX|DEBUG_CMD), "PKT: ", data + sizeof(*desc), min(pkt_data_len, - ieee80211_hdrlen(hdr->frame_control))); + ieee80211_hdrlen(hdr->frame_control)));*/ + wl->corrupted_packets++; + wl1271_notice("corrupt packet rx:%d", wl->corrupted_packets); return -EINVAL; } --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -493,6 +493,8 @@ /* interface combinations supported by the hw */ const struct ieee80211_iface_combination *iface_combinations; u8 n_iface_combinations; + + unsigned int corrupted_packets; }; int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
--- a/drivers/net/wireless/ti/wl1251/main.c+++ b/drivers/net/wireless/ti/wl1251/main.c@@ -1464,7 +1464,7 @@ wl->mac80211_registered = true; - wl1251_notice("loaded");+ wl1251_notice("loaded (wl1251 main.c)"); return 0; }--- a/drivers/net/wireless/ti/wlcore/debugfs.c+++ b/drivers/net/wireless/ti/wlcore/debugfs.c@@ -84,6 +84,7 @@ EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats); DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count);+DEBUGFS_READONLY_FILE(corrupted_packets, "%u", wl->corrupted_packets); DEBUGFS_READONLY_FILE(excessive_retries, "%u", wl->stats.excessive_retries); @@ -1249,6 +1250,7 @@ DEBUGFS_ADD(tx_queue_len, rootdir); DEBUGFS_ADD(retry_count, rootdir);+ DEBUGFS_ADD(corrupted_packets, rootdir); DEBUGFS_ADD(excessive_retries, rootdir); DEBUGFS_ADD(gpio_power, rootdir);--- a/drivers/net/wireless/ti/wlcore/main.c+++ b/drivers/net/wireless/ti/wlcore/main.c@@ -557,6 +557,16 @@ if (!intr) { done = true; continue;+ }++ if (wl->corrupted_packets > 50){+ wl1271_error("Too many corrupt packets received (%d>50)! starting recovery.",wl->corrupted_packets);+ wl->corrupted_packets = 0; + wl->watchdog_recovery = true;+ ret = -EIO;++ /* restarting the chip. ignore any other interrupt. */+ goto out; } if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {@@ -5743,7 +5753,7 @@ wl1271_debugfs_init(wl); - wl1271_notice("loaded");+ wl1271_notice("loaded (wlcore.c main)"); out: return ret;@@ -5968,6 +5978,7 @@ wl->active_sta_count = 0; wl->active_link_count = 0; wl->fwlog_size = 0;+ wl->corrupted_packets = 0; init_waitqueue_head(&wl->fwlog_waitq); /* The system link is always allocated */
@@ -5743,7 +5753,7 @@ wl1271_debugfs_init(wl); - wl1271_notice("loaded");+ wl1271_notice("loaded (wlcore.c main)"); out: return ret;@@ -5968,6 +5978,7 @@ wl->active_sta_count = 0; wl->active_link_count = 0; wl->fwlog_size = 0;+ wl->corrupted_packets = 0; init_waitqueue_head(&wl->fwlog_waitq); /* The system link is always allocated */--- a/drivers/net/wireless/ti/wlcore/rx.c+++ b/drivers/net/wireless/ti/wlcore/rx.c@@ -148,13 +148,15 @@ /* discard corrupted packets */ if (desc->status & WL1271_RX_DESC_DECRYPT_FAIL) {- hdr = (void *)(data + sizeof(*desc) + offset_to_data);+ /*hdr = (void *)(data + sizeof(*desc) + offset_to_data); wl1271_warning("corrupted packet in RX: status: 0x%x len: %d", desc->status & WL1271_RX_DESC_STATUS_MASK, pkt_data_len); wl1271_dump((DEBUG_RX|DEBUG_CMD), "PKT: ", data + sizeof(*desc), min(pkt_data_len,- ieee80211_hdrlen(hdr->frame_control)));+ ieee80211_hdrlen(hdr->frame_control)));*/+ wl->corrupted_packets++;+ wl1271_notice("corrupt packet rx:%d", wl->corrupted_packets); return -EINVAL; } --- a/drivers/net/wireless/ti/wlcore/wlcore.h+++ b/drivers/net/wireless/ti/wlcore/wlcore.h@@ -493,6 +493,8 @@ /* interface combinations supported by the hw */ const struct ieee80211_iface_combination *iface_combinations; u8 n_iface_combinations;++ unsigned int corrupted_packets; }; int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);