# Base git commit: e8f897f4afef # (Linux 6.8) # # Author: Russell King (Oracle) (Sat 20 Apr 22:02:29 BST 2024) # Committer: Russell King (Oracle) (Mon 22 Apr 17:50:10 BST 2024) # # net: wlcore: add support for AES-CMAC # # Add support for the AES-CMAC cipher to TI Wireless. Based on patch from # https://git.ti.com/cgit/wilink8-wlan/build-utilites/tree/patches/kernel_patches/4.19.38/0007-Adding-support-to-IGTK-key-AES-CMAC128-in-the-wlcore.patch?h=r8.8 # # Signed-off-by: Russell King (Oracle) # # 0739fdf67092222c85ea42b0ff6a4d950f8350e6 # drivers/net/wireless/ti/wlcore/cmd.h | 1 + # drivers/net/wireless/ti/wlcore/main.c | 4 ++++ # 2 files changed, 5 insertions(+) # # Author: Russell King (Oracle) (Sun 14 Apr 18:11:54 BST 2024) # Committer: Russell King (Oracle) (Tue 16 Apr 16:39:47 BST 2024) # # net: wl18xx: allow firmwares > 8.9.0.x.58 # # With WL18xx ignoring the major firmware version, it doesn't recognise # 8.9.1.x.0 as being newer than 8.9.0.x.58. We need to change the major # version from "ignore" to "0" for this later firmware to be correctly # detected, and allow the dual-firmware version support to work. # # Signed-off-by: Russell King (Oracle) # # d6f80baf438279019c863020c5d42da8b29882bd # drivers/net/wireless/ti/wl18xx/wl18xx.h | 2 +- # 1 file changed, 1 insertion(+), 1 deletion(-) # # Author: Russell King (Oracle) (Sun 14 Apr 16:57:06 BST 2024) # Committer: Russell King (Oracle) (Tue 16 Apr 16:39:46 BST 2024) # # net: wl18xx: add support for reading 8.9.1 fw status # # Add the necessary code to read the 8.9.1 firmware status into the # driver private status structure, augmenting the 8.9.0 firmware # status code. # # Signed-off-by: Russell King (Oracle) # # 1f44f1fc7b5c03e87bcd02bd253f669b93f36aef # drivers/net/wireless/ti/wl18xx/main.c | 71 ++++++++++++++++++++++++++++++++- # drivers/net/wireless/ti/wl18xx/wl18xx.h | 60 ++++++++++++++++++++++++++++ # 2 files changed, 129 insertions(+), 2 deletions(-) # # Author: Russell King (Oracle) (Thu 11 May 13:23:37 BST 2023) # Committer: Russell King (Oracle) (Tue 16 Apr 16:39:46 BST 2024) # # net: wlcore: add pn16 support # # Signed-off-by: Russell King (Oracle) # # 4322ce2e9fd0d6bc295057d01f1d2f2ff87a891c # drivers/net/wireless/ti/wlcore/cmd.c | 9 ++++ # drivers/net/wireless/ti/wlcore/main.c | 89 +++++++++++++++++++++++++++++-- # drivers/net/wireless/ti/wlcore/wlcore_i.h | 4 ++ # 3 files changed, 97 insertions(+), 5 deletions(-) # # Author: Russell King (Oracle) (Thu 11 May 13:25:44 BST 2023) # Committer: Russell King (Oracle) (Mon 15 Apr 11:54:04 BST 2024) # # net: wlcore: store AP encryption key type # # Updates for WL18xx firmware 8.9.1.x.x need to know the AP encryption # key type. Store this when a new key is set. # # Signed-off-by: Russell King (Oracle) # # 58334553dd8ba482666d35880d3ebd101da645ce # drivers/net/wireless/ti/wlcore/main.c | 4 ++++ # 1 file changed, 4 insertions(+) # # Author: Russell King (Oracle) (Thu 11 May 17:09:50 BST 2023) # Committer: Russell King (Oracle) (Mon 15 Apr 11:54:04 BST 2024) # # net: wlcore: export tx_total via debugfs # # Signed-off-by: Russell King (Oracle) # # f6e7bcd3c72a402c85deaafab1643c88005cda80 # drivers/net/wireless/ti/wlcore/debugfs.c | 1 + # drivers/net/wireless/ti/wlcore/main.c | 1 + # drivers/net/wireless/ti/wlcore/wlcore.h | 1 + # 3 files changed, 3 insertions(+) # # Author: Russell King (Oracle) (Thu 11 May 15:15:14 BST 2023) # Committer: Russell King (Oracle) (Mon 15 Apr 11:54:03 BST 2024) # # net: wlcore: improve code in wlcore_fw_status() # # Referring to status->counters.tx_lnk_free_pkts[i] multiple times leads # to less efficient code. Cache this value in a local variable. This # also makes the code clearer. # # Signed-off-by: Russell King (Oracle) # # 7081e7645698bdc0e9b02a496f4cc11912a54e7f # drivers/net/wireless/ti/wlcore/main.c | 8 ++++---- # 1 file changed, 4 insertions(+), 4 deletions(-) # # Author: Russell King (Oracle) (Thu 11 May 17:07:26 BST 2023) # Committer: Russell King (Oracle) (Mon 15 Apr 11:54:03 BST 2024) # # net: wl18xx: make wl18xx_tx_immediate_complete() more efficient # # wl18xx_tx_immediate_complete() iterates through the completed transmit # descriptors in a circular fashion, and in doing so uses a modulus # operation that is not a power of two. This leads to inefficient code # generation, which can be easily solved by providing a helper to # increment to the next descriptor. Use this more efficient solution. # # Signed-off-by: Russell King (Oracle) # # d892cc8041c0ce5cea2a62ae5d9832aa3a1bb269 # drivers/net/wireless/ti/wl18xx/tx.c | 13 ++++++++++--- # 1 file changed, 10 insertions(+), 3 deletions(-) # # Author: Russell King (Oracle) (Fri 12 May 15:07:10 BST 2023) # Committer: Russell King (Oracle) (Mon 15 Apr 11:54:02 BST 2024) # # net: wlcore: correctness fix fwlog reading # # Fix the calculation of clear_offset, which may overflow the end of # the buffer. However, this is harmless if it does because in that case # it will be recalculated when we copy the chunk of messages at the # start of the buffer. # # Signed-off-by: Russell King (Oracle) # # 8e84c4317565652b41fefc9e685330fb5baabc6e # drivers/net/wireless/ti/wlcore/event.c | 2 +- # 1 file changed, 1 insertion(+), 1 deletion(-) # diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 2ccac1cdec01..39d8eebb9b6e 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1177,8 +1177,49 @@ static int wl18xx_hw_init(struct wl1271 *wl) return ret; } -static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, - struct wl_fw_status *fw_status) +static void wl18xx_convert_fw_status_8_9_1(struct wl1271 *wl, + void *raw_fw_status, + struct wl_fw_status *fw_status) +{ + struct wl18xx_fw_status_8_9_1 *int_fw_status = raw_fw_status; + + fw_status->intr = le32_to_cpu(int_fw_status->intr); + fw_status->fw_rx_counter = int_fw_status->fw_rx_counter; + fw_status->drv_rx_counter = int_fw_status->drv_rx_counter; + fw_status->tx_results_counter = int_fw_status->tx_results_counter; + fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs; + + fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime); + fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap); + fw_status->link_fast_bitmap = + le32_to_cpu(int_fw_status->link_fast_bitmap); + fw_status->total_released_blks = + le32_to_cpu(int_fw_status->total_released_blks); + fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total); + + fw_status->counters.tx_released_pkts = + int_fw_status->counters.tx_released_pkts; + fw_status->counters.tx_lnk_free_pkts = + int_fw_status->counters.tx_lnk_free_pkts; + fw_status->counters.tx_lnk_sec_pn16 = + int_fw_status->counters.tx_lnk_sec_pn16; + fw_status->counters.tx_voice_released_blks = + int_fw_status->counters.tx_voice_released_blks; + fw_status->counters.tx_last_rate = + int_fw_status->counters.tx_last_rate; + fw_status->counters.tx_last_rate_mbps = + int_fw_status->counters.tx_last_rate_mbps; + fw_status->counters.hlid = + int_fw_status->counters.hlid; + + fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr); + + fw_status->priv = &int_fw_status->priv; +} + +static void wl18xx_convert_fw_status_8_9_0(struct wl1271 *wl, + void *raw_fw_status, + struct wl_fw_status *fw_status) { struct wl18xx_fw_status *int_fw_status = raw_fw_status; @@ -1214,6 +1255,15 @@ static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, fw_status->priv = &int_fw_status->priv; } +static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, + struct wl_fw_status *fw_status) +{ + if (wl->chip.fw_ver[FW_VER_MAJOR] == 0) + wl18xx_convert_fw_status_8_9_0(wl, raw_fw_status, fw_status); + else + wl18xx_convert_fw_status_8_9_1(wl, raw_fw_status, fw_status); +} + static void wl18xx_set_tx_desc_csum(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, struct sk_buff *skb) @@ -1515,12 +1565,29 @@ static int wl18xx_handle_static_data(struct wl1271 *wl, { struct wl18xx_static_data_priv *static_data_priv = (struct wl18xx_static_data_priv *) static_data->priv; + size_t fw_status_len; strscpy(wl->chip.phy_fw_ver_str, static_data_priv->phy_version, sizeof(wl->chip.phy_fw_ver_str)); wl1271_info("PHY firmware version: %s", static_data_priv->phy_version); + /* Adjust the firmware status size according to the firmware version */ + if (wl->chip.fw_ver[FW_VER_MAJOR] == 0) + fw_status_len = sizeof(struct wl18xx_fw_status); + else + fw_status_len = sizeof(struct wl18xx_fw_status_8_9_1); + + if (wl->fw_status_len != fw_status_len) { + void *new_status = krealloc(wl->raw_fw_status, fw_status_len, + GFP_KERNEL | __GFP_ZERO); + if (!new_status) + return -ENOMEM; + + wl->raw_fw_status = new_status; + wl->fw_status_len = fw_status_len; + } + return 0; } diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c index 55d9b0861c53..beef393853ef 100644 --- a/drivers/net/wireless/ti/wl18xx/tx.c +++ b/drivers/net/wireless/ti/wl18xx/tx.c @@ -129,6 +129,14 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) wl1271_free_tx_id(wl, id); } +static u8 wl18xx_next_tx_idx(u8 idx) +{ + if (++idx >= WL18XX_FW_MAX_TX_STATUS_DESC) + idx = 0; + + return idx; +} + void wl18xx_tx_immediate_complete(struct wl1271 *wl) { struct wl18xx_fw_status_priv *status_priv = @@ -161,9 +169,8 @@ void wl18xx_tx_immediate_complete(struct wl1271 *wl) return; } - for (i = priv->last_fw_rls_idx; - i != status_priv->fw_release_idx; - i = (i + 1) % WL18XX_FW_MAX_TX_STATUS_DESC) { + for (i = priv->last_fw_rls_idx; i != status_priv->fw_release_idx; + i = wl18xx_next_tx_idx(i)) { wl18xx_tx_complete_packet(wl, status_priv->released_tx_desc[i]); diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index b642e0c437bb..9fc2972bcb4f 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -13,7 +13,7 @@ /* minimum FW required for driver */ #define WL18XX_CHIP_VER 8 #define WL18XX_IFTYPE_VER 9 -#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE +#define WL18XX_MAJOR_VER 0 #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE #define WL18XX_MINOR_VER 58 @@ -155,6 +155,66 @@ struct wl18xx_fw_status { struct wl18xx_fw_status_priv priv; } __packed; +struct wl18xx_fw_packet_counters_8_9_1 { + /* Cumulative counter of released packets per AC */ + u8 tx_released_pkts[NUM_TX_QUEUES]; + + /* Cumulative counter of freed packets per HLID */ + u8 tx_lnk_free_pkts[WL18XX_MAX_LINKS]; + + /* PN16 of last TKIP/AES seq-num per HLID */ + u16 tx_lnk_sec_pn16[WL18XX_MAX_LINKS]; + + /* Cumulative counter of released Voice memory blocks */ + u8 tx_voice_released_blks; + + /* Tx rate of the last transmitted packet */ + u8 tx_last_rate; + + /* Tx rate or Tx rate estimate pre-calculated by fw in mbps units */ + u8 tx_last_rate_mbps; + + /* hlid for which the rates were reported */ + u8 hlid; +} __packed; + +/* FW status registers */ +struct wl18xx_fw_status_8_9_1 { + __le32 intr; + u8 fw_rx_counter; + u8 drv_rx_counter; + u8 reserved; + u8 tx_results_counter; + __le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS]; + + __le32 fw_localtime; + + /* + * A bitmap (where each bit represents a single HLID) + * to indicate if the station is in PS mode. + */ + __le32 link_ps_bitmap; + + /* + * A bitmap (where each bit represents a single HLID) to indicate + * if the station is in Fast mode + */ + __le32 link_fast_bitmap; + + /* Cumulative counter of total released mem blocks since FW-reset */ + __le32 total_released_blks; + + /* Size (in Memory Blocks) of TX pool */ + __le32 tx_total; + + struct wl18xx_fw_packet_counters_8_9_1 counters; + + __le32 log_start_addr; + + /* Private status to be used by the lower drivers */ + struct wl18xx_fw_status_priv priv; +} __packed; + #define WL18XX_PHY_VERSION_MAX_LEN 20 struct wl18xx_static_data_priv { 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 @@ -332,6 +332,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) wl->fw_status->counters.tx_lnk_free_pkts[link]; 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/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index f2609d5b6bf7..1d59eb481dec 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -458,6 +458,7 @@ enum wl1271_cmd_key_type { KEY_TKIP = 2, KEY_AES = 3, KEY_GEM = 4, + KEY_IGTK = 5, }; struct wl1271_cmd_set_keys { diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index eb3d3f0e0b4d..cc5a5411d781 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -457,6 +457,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, wlvif->p2p ? "P2P-GO" : "AP"); + DRIVER_STATE_PRINT_INT(tx_blocks_total); DRIVER_STATE_PRINT_INT(tx_blocks_available); DRIVER_STATE_PRINT_INT(tx_allocated_blocks); DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 1e082d039b82..3bb6ff6e0853 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -83,7 +83,7 @@ int wlcore_event_fw_logger(struct wl1271 *wl) /* Copy initial part up to the end of ring buffer */ len = min(actual_len, available_len); wl12xx_copy_fwlog(wl, &buffer[start_loc], len); - clear_ptr = addr_ptr + start_loc + actual_len; + clear_ptr = addr_ptr + start_loc + len; if (clear_ptr == buff_end_ptr) clear_ptr = buff_start_ptr; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 5736acb4d206..fd52862d098a 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) { - u8 diff; + u16 diff16, sec_pn16; + u8 diff, tx_lnk_free_pkts; + lnk = &wl->links[i]; /* prevent wrap-around in freed-packets counter */ - diff = (status->counters.tx_lnk_free_pkts[i] - - lnk->prev_freed_pkts) & 0xff; + tx_lnk_free_pkts = status->counters.tx_lnk_free_pkts[i]; + diff = (tx_lnk_free_pkts - lnk->prev_freed_pkts) & 0xff; + + 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; - if (diff == 0) + /* 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 = status->counters.tx_lnk_free_pkts[i]; + /* 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 */ @@ -453,6 +532,7 @@ static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status) cancel_delayed_work(&wl->tx_watchdog_work); } + wl->tx_blocks_total = status->tx_total; avail = status->tx_total - wl->tx_allocated_blocks; /* @@ -3518,6 +3598,9 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, case WL1271_CIPHER_SUITE_GEM: key_type = KEY_GEM; break; + case WLAN_CIPHER_SUITE_AES_CMAC: + key_type = KEY_IGTK; + break; default: wl1271_error("Unknown key algo 0x%x", key_conf->cipher); @@ -3537,6 +3620,10 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, return ret; } + /* Store AP encryption key type */ + if (wlvif->bss_type == BSS_TYPE_AP_BSS) + wlvif->encryption_type = key_type; + /* * reconfiguring arp response if the unicast (or common) * encryption key type was changed @@ -6146,6 +6233,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, WL1271_CIPHER_SUITE_GEM, + WLAN_CIPHER_SUITE_AES_CMAC, }; /* The tx descriptor buffer */ diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 1f8511bf9bb3..97ade837c343 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -242,6 +242,7 @@ struct wl1271 { struct wl1271_acx_mem_map *target_mem_map; /* Accounting for allocated / available TX blocks on HW */ + u32 tx_blocks_total; u32 tx_blocks_freed; u32 tx_blocks_available; u32 tx_allocated_blocks; 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];