Commit 32bb2c03 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho

wlcore/wl12xx/wl18xx: handle spare blocks spacial cases per arch

Add a HW op for getting spare blocks.

12xx cards require 2 spare blocks for GEM encrypted SKBs, regardless
of VIFs or keys programmed into the FW.

18xx cards require 2 spare blocks when there are any connected TKIP or
GEM VIFs. For now always return 2 spare blocks, as this works with all
networks. The special case TKIP/GEM functionality is added at a later
patch.
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 2c0133a4
...@@ -1361,6 +1361,14 @@ static int wl12xx_plt_init(struct wl1271 *wl) ...@@ -1361,6 +1361,14 @@ static int wl12xx_plt_init(struct wl1271 *wl)
return ret; return ret;
} }
static int wl12xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
{
if (is_gem)
return WL12XX_TX_HW_BLOCK_GEM_SPARE;
return WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
}
static struct wlcore_ops wl12xx_ops = { static struct wlcore_ops wl12xx_ops = {
.identify_chip = wl12xx_identify_chip, .identify_chip = wl12xx_identify_chip,
.identify_fw = wl12xx_identify_fw, .identify_fw = wl12xx_identify_fw,
...@@ -1384,6 +1392,7 @@ static struct wlcore_ops wl12xx_ops = { ...@@ -1384,6 +1392,7 @@ static struct wlcore_ops wl12xx_ops = {
.set_rx_csum = NULL, .set_rx_csum = NULL,
.ap_get_mimo_wide_rate_mask = NULL, .ap_get_mimo_wide_rate_mask = NULL,
.debugfs_init = wl12xx_debugfs_add_files, .debugfs_init = wl12xx_debugfs_add_files,
.get_spare_blocks = wl12xx_get_spare_blocks,
}; };
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
...@@ -1419,8 +1428,6 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) ...@@ -1419,8 +1428,6 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
wl->rtable = wl12xx_rtable; wl->rtable = wl12xx_rtable;
wl->num_tx_desc = 16; wl->num_tx_desc = 16;
wl->num_rx_desc = 8; wl->num_rx_desc = 8;
wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
wl->band_rate_to_idx = wl12xx_band_rate_to_idx; wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
......
...@@ -874,7 +874,7 @@ static int wl18xx_hw_init(struct wl1271 *wl) ...@@ -874,7 +874,7 @@ static int wl18xx_hw_init(struct wl1271 *wl)
ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap, ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap,
sdio_align_size, sdio_align_size,
WL18XX_TX_HW_BLOCK_SPARE, WL18XX_TX_HW_EXTRA_BLOCK_SPARE,
WL18XX_HOST_IF_LEN_SIZE_FIELD); WL18XX_HOST_IF_LEN_SIZE_FIELD);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1034,6 +1034,12 @@ static int wl18xx_handle_static_data(struct wl1271 *wl, ...@@ -1034,6 +1034,12 @@ static int wl18xx_handle_static_data(struct wl1271 *wl,
return 0; return 0;
} }
static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
{
/* TODO: dynamically change to extra only when we have GEM or TKIP */
return WL18XX_TX_HW_EXTRA_BLOCK_SPARE;
}
static struct wlcore_ops wl18xx_ops = { static struct wlcore_ops wl18xx_ops = {
.identify_chip = wl18xx_identify_chip, .identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot, .boot = wl18xx_boot,
...@@ -1056,6 +1062,7 @@ static struct wlcore_ops wl18xx_ops = { ...@@ -1056,6 +1062,7 @@ static struct wlcore_ops wl18xx_ops = {
.get_mac = wl18xx_get_mac, .get_mac = wl18xx_get_mac,
.debugfs_init = wl18xx_debugfs_add_files, .debugfs_init = wl18xx_debugfs_add_files,
.handle_static_data = wl18xx_handle_static_data, .handle_static_data = wl18xx_handle_static_data,
.get_spare_blocks = wl18xx_get_spare_blocks,
}; };
/* HT cap appropriate for wide channels */ /* HT cap appropriate for wide channels */
...@@ -1129,8 +1136,6 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) ...@@ -1129,8 +1136,6 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
wl->rtable = wl18xx_rtable; wl->rtable = wl18xx_rtable;
wl->num_tx_desc = 32; wl->num_tx_desc = 32;
wl->num_rx_desc = 16; wl->num_rx_desc = 16;
wl->normal_tx_spare = WL18XX_TX_HW_BLOCK_SPARE;
wl->gem_tx_spare = WL18XX_TX_HW_GEM_BLOCK_SPARE;
wl->band_rate_to_idx = wl18xx_band_rate_to_idx; wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
#include "../wlcore/wlcore.h" #include "../wlcore/wlcore.h"
#define WL18XX_TX_HW_BLOCK_SPARE 1 #define WL18XX_TX_HW_BLOCK_SPARE 1
#define WL18XX_TX_HW_GEM_BLOCK_SPARE 2 /* for special cases - namely, TKIP and GEM */
#define WL18XX_TX_HW_EXTRA_BLOCK_SPARE 2
#define WL18XX_TX_HW_BLOCK_SIZE 268 #define WL18XX_TX_HW_BLOCK_SIZE 268
#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F #define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F
......
...@@ -507,7 +507,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, ...@@ -507,7 +507,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT(last_rssi_event); VIF_STATE_PRINT_INT(last_rssi_event);
VIF_STATE_PRINT_INT(ba_support); VIF_STATE_PRINT_INT(ba_support);
VIF_STATE_PRINT_INT(ba_allowed); VIF_STATE_PRINT_INT(ba_allowed);
VIF_STATE_PRINT_INT(is_gem);
VIF_STATE_PRINT_LLHEX(tx_security_seq); VIF_STATE_PRINT_LLHEX(tx_security_seq);
VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
} }
......
...@@ -167,4 +167,13 @@ wlcore_handle_static_data(struct wl1271 *wl, void *static_data) ...@@ -167,4 +167,13 @@ wlcore_handle_static_data(struct wl1271 *wl, void *static_data)
return 0; return 0;
} }
static inline int
wlcore_hw_get_spare_blocks(struct wl1271 *wl, bool is_gem)
{
if (!wl->ops->get_spare_blocks)
BUG_ON(1);
return wl->ops->get_spare_blocks(wl, is_gem);
}
#endif #endif
...@@ -2799,17 +2799,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -2799,17 +2799,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int ret; int ret;
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
/*
* A role set to GEM cipher requires different Tx settings (namely
* spare blocks). Note when we are in this mode so the HW can adjust.
*/
if (key_type == KEY_GEM) {
if (action == KEY_ADD_OR_REPLACE)
wlvif->is_gem = true;
else if (action == KEY_REMOVE)
wlvif->is_gem = false;
}
if (is_ap) { if (is_ap) {
struct wl1271_station *wl_sta; struct wl1271_station *wl_sta;
u8 hlid; u8 hlid;
......
...@@ -187,28 +187,24 @@ EXPORT_SYMBOL(wlcore_calc_packet_alignment); ...@@ -187,28 +187,24 @@ EXPORT_SYMBOL(wlcore_calc_packet_alignment);
static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, u32 extra, u32 buf_offset, struct sk_buff *skb, u32 extra, u32 buf_offset,
u8 hlid) u8 hlid, bool is_gem)
{ {
struct wl1271_tx_hw_descr *desc; struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 total_blocks; u32 total_blocks;
int id, ret = -EBUSY, ac; int id, ret = -EBUSY, ac;
u32 spare_blocks = wl->normal_tx_spare; u32 spare_blocks;
bool is_dummy = false;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN; return -EAGAIN;
spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem);
/* allocate free identifier for the packet */ /* allocate free identifier for the packet */
id = wl1271_alloc_tx_id(wl, skb); id = wl1271_alloc_tx_id(wl, skb);
if (id < 0) if (id < 0)
return id; return id;
if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
is_dummy = true;
else if (wlvif->is_gem)
spare_blocks = wl->gem_tx_spare;
total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
if (total_blocks <= wl->tx_blocks_available) { if (total_blocks <= wl->tx_blocks_available) {
...@@ -230,7 +226,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -230,7 +226,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->tx_allocated_pkts[ac]++; wl->tx_allocated_pkts[ac]++;
if (!is_dummy && wlvif && if (!wl12xx_is_dummy_packet(wl, skb) && wlvif &&
wlvif->bss_type == BSS_TYPE_AP_BSS && wlvif->bss_type == BSS_TYPE_AP_BSS &&
test_bit(hlid, wlvif->ap.sta_hlid_map)) test_bit(hlid, wlvif->ap.sta_hlid_map))
wl->links[hlid].allocated_pkts++; wl->links[hlid].allocated_pkts++;
...@@ -349,6 +345,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -349,6 +345,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u32 total_len; u32 total_len;
u8 hlid; u8 hlid;
bool is_dummy; bool is_dummy;
bool is_gem = false;
if (!skb) if (!skb)
return -EINVAL; return -EINVAL;
...@@ -377,6 +374,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -377,6 +374,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return ret; return ret;
wlvif->default_key = idx; wlvif->default_key = idx;
} }
is_gem = (cipher == WL1271_CIPHER_SUITE_GEM);
} }
hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
if (hlid == WL12XX_INVALID_LINK_ID) { if (hlid == WL12XX_INVALID_LINK_ID) {
...@@ -384,7 +383,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -384,7 +383,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return -EINVAL; return -EINVAL;
} }
ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid); ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid,
is_gem);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -75,6 +75,7 @@ struct wlcore_ops { ...@@ -75,6 +75,7 @@ struct wlcore_ops {
int (*debugfs_init)(struct wl1271 *wl, struct dentry *rootdir); int (*debugfs_init)(struct wl1271 *wl, struct dentry *rootdir);
int (*handle_static_data)(struct wl1271 *wl, int (*handle_static_data)(struct wl1271 *wl,
struct wl1271_static_data *static_data); struct wl1271_static_data *static_data);
int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem);
}; };
enum wlcore_partitions { enum wlcore_partitions {
...@@ -354,10 +355,6 @@ struct wl1271 { ...@@ -354,10 +355,6 @@ struct wl1271 {
/* number of RX descriptors the HW supports. */ /* number of RX descriptors the HW supports. */
u32 num_rx_desc; u32 num_rx_desc;
/* spare Tx blocks for normal/GEM operating modes */
u32 normal_tx_spare;
u32 gem_tx_spare;
/* translate HW Tx rates to standard rate-indices */ /* translate HW Tx rates to standard rate-indices */
const u8 **band_rate_to_idx; const u8 **band_rate_to_idx;
......
...@@ -417,9 +417,6 @@ struct wl12xx_vif { ...@@ -417,9 +417,6 @@ struct wl12xx_vif {
struct work_struct rx_streaming_disable_work; struct work_struct rx_streaming_disable_work;
struct timer_list rx_streaming_timer; struct timer_list rx_streaming_timer;
/* does the current role use GEM for encryption (AP or STA) */
bool is_gem;
/* /*
* This struct must be last! * This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery) * data that has to be saved acrossed reconfigs (e.g. recovery)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment