diff options
author | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2023-05-11 13:23:37 +0100 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2024-04-16 16:39:46 +0100 |
commit | 4322ce2e9fd0d6bc295057d01f1d2f2ff87a891c (patch) | |
tree | cfd2e49a7e4d56b14f70efbd05d9ca86dffe9dba | |
parent | 58334553dd8ba482666d35880d3ebd101da645ce (diff) |
net: wlcore: add pn16 support
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 89 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore_i.h | 4 |
3 files changed, 97 insertions, 5 deletions
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index a939fd89a7f5..a77370c76950 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -333,6 +333,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) wl->links[link].wlvif = wlvif; /* + * Take the last sec_pn16 value from the current FW status. On recovery, + * we might not have fw_status yet, and tx_lnk_sec_pn16[] will be NULL. + */ + if (wl->fw_status->counters.tx_lnk_sec_pn16) + wl->links[link].prev_sec_pn16 = + wl->fw_status->counters.tx_lnk_sec_pn16[link]; + + /* * Take saved value for total freed packets from wlvif, in case this is * recovery/resume */ @@ -360,6 +368,7 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) wl->links[*hlid].allocated_pkts = 0; wl->links[*hlid].prev_freed_pkts = 0; + wl->links[*hlid].prev_sec_pn16 = 0; wl->links[*hlid].ba_bitmap = 0; eth_zero_addr(wl->links[*hlid].addr); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index d48dc659423f..8f244c19f49e 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -379,6 +379,8 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status) { + struct wl12xx_vif *wlvifsta; + struct wl12xx_vif *wlvifap; struct wl12xx_vif *wlvif; u32 old_tx_blk_count = wl->tx_blocks_available; int avail, freed_blocks; @@ -410,23 +412,100 @@ static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status) wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i]; } + /* Find an authorized STA vif */ + wlvifsta = NULL; + wl12xx_for_each_wlvif_sta(wl, wlvif) { + if (wlvif->sta.hlid != WL12XX_INVALID_LINK_ID && + test_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags)) { + wlvifsta = wlvif; + break; + } + } + + /* Find a started AP vif */ + wlvifap = NULL; + wl12xx_for_each_wlvif(wl, wlvif) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS && + wlvif->inconn_count == 0 && + test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { + wlvifap = wlvif; + break; + } + } for_each_set_bit(i, wl->links_map, wl->num_links) { + u16 diff16, sec_pn16; u8 diff, tx_lnk_free_pkts; + lnk = &wl->links[i]; /* prevent wrap-around in freed-packets counter */ tx_lnk_free_pkts = status->counters.tx_lnk_free_pkts[i]; diff = (tx_lnk_free_pkts - lnk->prev_freed_pkts) & 0xff; - if (diff == 0) + if (diff) { + lnk->allocated_pkts -= diff; + lnk->prev_freed_pkts = tx_lnk_free_pkts; + } + + /* Get the current sec_pn16 value if present */ + if (status->counters.tx_lnk_sec_pn16) + sec_pn16 = status->counters.tx_lnk_sec_pn16[i]; + else + sec_pn16 = 0; + /* prevent wrap-around in pn16 counter */ + diff16 = (sec_pn16 - lnk->prev_sec_pn16) & 0xffff; + + /* FIXME: since free_pkts is a 8-bit counter of packets that + * rolls over, it can become zero. If it is zero, then we + * omit processing below. Is that really correct? + */ + if (tx_lnk_free_pkts <= 0) continue; - lnk->allocated_pkts -= diff; - lnk->prev_freed_pkts = tx_lnk_free_pkts; + /* For a station that has an authorized link: */ + if (wlvifsta && wlvifsta->sta.hlid == i) { + if (wlvifsta->encryption_type == KEY_TKIP || + wlvifsta->encryption_type == KEY_AES) { + if (diff16) { + lnk->prev_sec_pn16 = sec_pn16; + /* accumulate the prev_freed_pkts + * counter according to the PN from + * firmware + */ + lnk->total_freed_pkts += diff16; + } + } else { + if (diff) + /* accumulate the prev_freed_pkts + * counter according to the free packets + * count from firmware + */ + lnk->total_freed_pkts += diff; + } + } - /* accumulate the prev_freed_pkts counter */ - lnk->total_freed_pkts += diff; + /* For an AP that has been started */ + if (wlvifap && test_bit(i, wlvifap->ap.sta_hlid_map)) { + if (wlvifap->encryption_type == KEY_TKIP || + wlvifap->encryption_type == KEY_AES) { + if (diff16) { + lnk->prev_sec_pn16 = sec_pn16; + /* accumulate the prev_freed_pkts + * counter according to the PN from + * firmware + */ + lnk->total_freed_pkts += diff16; + } + } else { + if (diff) + /* accumulate the prev_freed_pkts + * counter according to the free packets + * count from firmware + */ + lnk->total_freed_pkts += diff; + } + } } /* prevent wrap-around in total blocks counter */ diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index eefae3f867b9..3894215e2bd3 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -151,6 +151,9 @@ struct wl_fw_status { */ u8 *tx_lnk_free_pkts; + /* PN16 of last TKIP/AES seq-num per HLID */ + u16 *tx_lnk_sec_pn16; + /* Cumulative counter of released Voice memory blocks */ u8 tx_voice_released_blks; @@ -259,6 +262,7 @@ struct wl1271_link { /* accounting for allocated / freed packets in FW */ u8 allocated_pkts; u8 prev_freed_pkts; + u16 prev_sec_pn16; u8 addr[ETH_ALEN]; |