mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-17 12:34:01 +00:00
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
This commit is contained in:
commit
f1b98bb367
21 changed files with 476 additions and 339 deletions
|
@ -32,7 +32,6 @@
|
|||
#include "../wlcore/acx.h"
|
||||
#include "../wlcore/tx.h"
|
||||
#include "../wlcore/rx.h"
|
||||
#include "../wlcore/io.h"
|
||||
#include "../wlcore/boot.h"
|
||||
|
||||
#include "wl12xx.h"
|
||||
|
@ -1185,9 +1184,16 @@ static int wl12xx_enable_interrupts(struct wl1271 *wl)
|
|||
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
goto disable_interrupts;
|
||||
|
||||
ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
|
||||
if (ret < 0)
|
||||
goto disable_interrupts;
|
||||
|
||||
return ret;
|
||||
|
||||
disable_interrupts:
|
||||
wlcore_disable_interrupts(wl);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
@ -1583,7 +1589,10 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
return wlcore_set_key(wl, cmd, vif, sta, key_conf);
|
||||
}
|
||||
|
||||
static int wl12xx_setup(struct wl1271 *wl);
|
||||
|
||||
static struct wlcore_ops wl12xx_ops = {
|
||||
.setup = wl12xx_setup,
|
||||
.identify_chip = wl12xx_identify_chip,
|
||||
.identify_fw = wl12xx_identify_fw,
|
||||
.boot = wl12xx_boot,
|
||||
|
@ -1624,26 +1633,15 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __devinit wl12xx_probe(struct platform_device *pdev)
|
||||
static int wl12xx_setup(struct wl1271 *wl)
|
||||
{
|
||||
struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct wl1271 *wl;
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl12xx_priv *priv;
|
||||
struct wl12xx_priv *priv = wl->priv;
|
||||
struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data;
|
||||
|
||||
hw = wlcore_alloc_hw(sizeof(*priv));
|
||||
if (IS_ERR(hw)) {
|
||||
wl1271_error("can't allocate hw");
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
|
||||
wl = hw->priv;
|
||||
priv = wl->priv;
|
||||
wl->ops = &wl12xx_ops;
|
||||
wl->ptable = wl12xx_ptable;
|
||||
wl->rtable = wl12xx_rtable;
|
||||
wl->num_tx_desc = 16;
|
||||
wl->num_rx_desc = 8;
|
||||
wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
|
||||
wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS;
|
||||
wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES;
|
||||
wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
|
||||
wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
|
||||
wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
|
||||
|
@ -1695,7 +1693,36 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
|
|||
wl1271_error("Invalid tcxo parameter %s", tcxo_param);
|
||||
}
|
||||
|
||||
return wlcore_probe(wl, pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit wl12xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wl1271 *wl;
|
||||
struct ieee80211_hw *hw;
|
||||
int ret;
|
||||
|
||||
hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv),
|
||||
WL12XX_AGGR_BUFFER_SIZE);
|
||||
if (IS_ERR(hw)) {
|
||||
wl1271_error("can't allocate hw");
|
||||
ret = PTR_ERR(hw);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl = hw->priv;
|
||||
wl->ops = &wl12xx_ops;
|
||||
wl->ptable = wl12xx_ptable;
|
||||
ret = wlcore_probe(wl, pdev);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
return ret;
|
||||
|
||||
out_free:
|
||||
wlcore_free_hw(wl);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
|
||||
|
@ -1714,17 +1741,7 @@ static struct platform_driver wl12xx_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static int __init wl12xx_init(void)
|
||||
{
|
||||
return platform_driver_register(&wl12xx_driver);
|
||||
}
|
||||
module_init(wl12xx_init);
|
||||
|
||||
static void __exit wl12xx_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wl12xx_driver);
|
||||
}
|
||||
module_exit(wl12xx_exit);
|
||||
module_platform_driver(wl12xx_driver);
|
||||
|
||||
module_param_named(fref, fref_param, charp, 0);
|
||||
MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52");
|
||||
|
|
|
@ -38,6 +38,13 @@
|
|||
#define WL128X_SUBTYPE_VER 2
|
||||
#define WL128X_MINOR_VER 115
|
||||
|
||||
#define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
|
||||
|
||||
#define WL12XX_NUM_TX_DESCRIPTORS 16
|
||||
#define WL12XX_NUM_RX_DESCRIPTORS 8
|
||||
|
||||
#define WL12XX_NUM_MAC_ADDRESSES 2
|
||||
|
||||
struct wl127x_rx_mem_pool_addr {
|
||||
u32 addr;
|
||||
u32 addr_extra;
|
||||
|
|
|
@ -220,7 +220,7 @@ static ssize_t clear_fw_stats_write(struct file *file,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl18xx_acx_clear_statistics(wl);
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
static char *ht_mode_param = NULL;
|
||||
static char *board_type_param = NULL;
|
||||
static bool checksum_param = false;
|
||||
static bool enable_11a_param = true;
|
||||
static int num_rx_desc_param = -1;
|
||||
|
||||
/* phy paramters */
|
||||
|
@ -415,7 +414,7 @@ static struct wlcore_conf wl18xx_conf = {
|
|||
.snr_threshold = 0,
|
||||
},
|
||||
.ht = {
|
||||
.rx_ba_win_size = 10,
|
||||
.rx_ba_win_size = 32,
|
||||
.tx_ba_win_size = 64,
|
||||
.inactivity_timeout = 10000,
|
||||
.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
|
||||
|
@ -505,8 +504,8 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
|
|||
.rdl = 0x01,
|
||||
.auto_detect = 0x00,
|
||||
.dedicated_fem = FEM_NONE,
|
||||
.low_band_component = COMPONENT_2_WAY_SWITCH,
|
||||
.low_band_component_type = 0x06,
|
||||
.low_band_component = COMPONENT_3_WAY_SWITCH,
|
||||
.low_band_component_type = 0x04,
|
||||
.high_band_component = COMPONENT_2_WAY_SWITCH,
|
||||
.high_band_component_type = 0x09,
|
||||
.tcxo_ldo_voltage = 0x00,
|
||||
|
@ -812,6 +811,13 @@ static int wl18xx_enable_interrupts(struct wl1271 *wl)
|
|||
|
||||
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~intr_mask);
|
||||
if (ret < 0)
|
||||
goto disable_interrupts;
|
||||
|
||||
return ret;
|
||||
|
||||
disable_interrupts:
|
||||
wlcore_disable_interrupts(wl);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
@ -1202,6 +1208,12 @@ 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;
|
||||
|
||||
strncpy(wl->chip.phy_fw_ver_str, static_data_priv->phy_version,
|
||||
sizeof(wl->chip.phy_fw_ver_str));
|
||||
|
||||
/* make sure the string is NULL-terminated */
|
||||
wl->chip.phy_fw_ver_str[sizeof(wl->chip.phy_fw_ver_str) - 1] = '\0';
|
||||
|
||||
wl1271_info("PHY firmware version: %s", static_data_priv->phy_version);
|
||||
|
||||
return 0;
|
||||
|
@ -1240,13 +1252,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
if (!change_spare)
|
||||
return wlcore_set_key(wl, cmd, vif, sta, key_conf);
|
||||
|
||||
/*
|
||||
* stop the queues and flush to ensure the next packets are
|
||||
* in sync with FW spare block accounting
|
||||
*/
|
||||
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
|
||||
wl1271_tx_flush(wl);
|
||||
|
||||
ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -1269,7 +1274,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
}
|
||||
|
||||
out:
|
||||
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1292,7 +1296,10 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
|
|||
return buf_offset;
|
||||
}
|
||||
|
||||
static int wl18xx_setup(struct wl1271 *wl);
|
||||
|
||||
static struct wlcore_ops wl18xx_ops = {
|
||||
.setup = wl18xx_setup,
|
||||
.identify_chip = wl18xx_identify_chip,
|
||||
.boot = wl18xx_boot,
|
||||
.plt_init = wl18xx_plt_init,
|
||||
|
@ -1373,27 +1380,15 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __devinit wl18xx_probe(struct platform_device *pdev)
|
||||
static int wl18xx_setup(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271 *wl;
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl18xx_priv *priv;
|
||||
struct wl18xx_priv *priv = wl->priv;
|
||||
int ret;
|
||||
|
||||
hw = wlcore_alloc_hw(sizeof(*priv));
|
||||
if (IS_ERR(hw)) {
|
||||
wl1271_error("can't allocate hw");
|
||||
ret = PTR_ERR(hw);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl = hw->priv;
|
||||
priv = wl->priv;
|
||||
wl->ops = &wl18xx_ops;
|
||||
wl->ptable = wl18xx_ptable;
|
||||
wl->rtable = wl18xx_rtable;
|
||||
wl->num_tx_desc = 32;
|
||||
wl->num_rx_desc = 32;
|
||||
wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
|
||||
wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS;
|
||||
wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES;
|
||||
wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
|
||||
wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
|
||||
wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
|
||||
|
@ -1404,9 +1399,9 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
|
|||
if (num_rx_desc_param != -1)
|
||||
wl->num_rx_desc = num_rx_desc_param;
|
||||
|
||||
ret = wl18xx_conf_init(wl, &pdev->dev);
|
||||
ret = wl18xx_conf_init(wl, wl->dev);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
return ret;
|
||||
|
||||
/* If the module param is set, update it in conf */
|
||||
if (board_type_param) {
|
||||
|
@ -1423,27 +1418,14 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
|
|||
} else {
|
||||
wl1271_error("invalid board type '%s'",
|
||||
board_type_param);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* HACK! Just for now we hardcode COM8 and HDK to 0x06 */
|
||||
switch (priv->conf.phy.board_type) {
|
||||
case BOARD_TYPE_HDK_18XX:
|
||||
case BOARD_TYPE_COM8_18XX:
|
||||
priv->conf.phy.low_band_component_type = 0x06;
|
||||
break;
|
||||
case BOARD_TYPE_FPGA_18XX:
|
||||
case BOARD_TYPE_DVP_18XX:
|
||||
case BOARD_TYPE_EVB_18XX:
|
||||
priv->conf.phy.low_band_component_type = 0x05;
|
||||
break;
|
||||
default:
|
||||
if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) {
|
||||
wl1271_error("invalid board type '%d'",
|
||||
priv->conf.phy.board_type);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (low_band_component_param != -1)
|
||||
|
@ -1475,22 +1457,21 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
|
|||
priv->conf.ht.mode = HT_MODE_SISO20;
|
||||
else {
|
||||
wl1271_error("invalid ht_mode '%s'", ht_mode_param);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->conf.ht.mode == HT_MODE_DEFAULT) {
|
||||
/*
|
||||
* Only support mimo with multiple antennas. Fall back to
|
||||
* siso20.
|
||||
* siso40.
|
||||
*/
|
||||
if (wl18xx_is_mimo_supported(wl))
|
||||
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
|
||||
&wl18xx_mimo_ht_cap_2ghz);
|
||||
else
|
||||
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
|
||||
&wl18xx_siso20_ht_cap);
|
||||
&wl18xx_siso40_ht_cap_2ghz);
|
||||
|
||||
/* 5Ghz is always wide */
|
||||
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
|
||||
|
@ -1512,9 +1493,34 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
|
|||
wl18xx_ops.init_vif = NULL;
|
||||
}
|
||||
|
||||
wl->enable_11a = enable_11a_param;
|
||||
/* Enable 11a Band only if we have 5G antennas */
|
||||
wl->enable_11a = (priv->conf.phy.number_of_assembled_ant5 != 0);
|
||||
|
||||
return wlcore_probe(wl, pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit wl18xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wl1271 *wl;
|
||||
struct ieee80211_hw *hw;
|
||||
int ret;
|
||||
|
||||
hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv),
|
||||
WL18XX_AGGR_BUFFER_SIZE);
|
||||
if (IS_ERR(hw)) {
|
||||
wl1271_error("can't allocate hw");
|
||||
ret = PTR_ERR(hw);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl = hw->priv;
|
||||
wl->ops = &wl18xx_ops;
|
||||
wl->ptable = wl18xx_ptable;
|
||||
ret = wlcore_probe(wl, pdev);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
return ret;
|
||||
|
||||
out_free:
|
||||
wlcore_free_hw(wl);
|
||||
|
@ -1538,18 +1544,7 @@ static struct platform_driver wl18xx_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static int __init wl18xx_init(void)
|
||||
{
|
||||
return platform_driver_register(&wl18xx_driver);
|
||||
}
|
||||
module_init(wl18xx_init);
|
||||
|
||||
static void __exit wl18xx_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wl18xx_driver);
|
||||
}
|
||||
module_exit(wl18xx_exit);
|
||||
|
||||
module_platform_driver(wl18xx_driver);
|
||||
module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
|
||||
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20");
|
||||
|
||||
|
@ -1560,9 +1555,6 @@ MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or "
|
|||
module_param_named(checksum, checksum_param, bool, S_IRUSR);
|
||||
MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)");
|
||||
|
||||
module_param_named(enable_11a, enable_11a_param, bool, S_IRUSR);
|
||||
MODULE_PARM_DESC(enable_11a, "Enable 11a (5GHz): boolean (defaults to true)");
|
||||
|
||||
module_param_named(dc2dc, dc2dc_param, int, S_IRUSR);
|
||||
MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)");
|
||||
|
||||
|
|
|
@ -33,6 +33,13 @@
|
|||
|
||||
#define WL18XX_CMD_MAX_SIZE 740
|
||||
|
||||
#define WL18XX_AGGR_BUFFER_SIZE (13 * PAGE_SIZE)
|
||||
|
||||
#define WL18XX_NUM_TX_DESCRIPTORS 32
|
||||
#define WL18XX_NUM_RX_DESCRIPTORS 32
|
||||
|
||||
#define WL18XX_NUM_MAC_ADDRESSES 3
|
||||
|
||||
struct wl18xx_priv {
|
||||
/* buffer for sending commands to FW */
|
||||
u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
|
||||
|
|
|
@ -59,6 +59,9 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
|||
u16 status;
|
||||
u16 poll_count = 0;
|
||||
|
||||
if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING)))
|
||||
return -EIO;
|
||||
|
||||
cmd = buf;
|
||||
cmd->id = cpu_to_le16(id);
|
||||
cmd->status = 0;
|
||||
|
@ -990,7 +993,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
|
|||
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV,
|
||||
skb->data, skb->len,
|
||||
CMD_TEMPL_KLV_IDX_NULL_DATA,
|
||||
wlvif->sta.klv_template_id,
|
||||
wlvif->basic_rate);
|
||||
|
||||
out:
|
||||
|
@ -1785,10 +1788,17 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
wlvif->bss_type == BSS_TYPE_IBSS)))
|
||||
return -EINVAL;
|
||||
|
||||
ret = wl12xx_cmd_role_start_dev(wl, wlvif);
|
||||
ret = wl12xx_cmd_role_enable(wl,
|
||||
wl12xx_wlvif_to_vif(wlvif)->addr,
|
||||
WL1271_ROLE_DEVICE,
|
||||
&wlvif->dev_role_id);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl12xx_cmd_role_start_dev(wl, wlvif);
|
||||
if (ret < 0)
|
||||
goto out_disable;
|
||||
|
||||
ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
|
||||
if (ret < 0)
|
||||
goto out_stop;
|
||||
|
@ -1797,6 +1807,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
|
||||
out_stop:
|
||||
wl12xx_cmd_role_stop_dev(wl, wlvif);
|
||||
out_disable:
|
||||
wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1824,6 +1836,11 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
ret = wl12xx_cmd_role_stop_dev(wl, wlvif);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -157,11 +157,6 @@ enum wl1271_commands {
|
|||
|
||||
#define MAX_CMD_PARAMS 572
|
||||
|
||||
enum {
|
||||
CMD_TEMPL_KLV_IDX_NULL_DATA = 0,
|
||||
CMD_TEMPL_KLV_IDX_MAX = 4
|
||||
};
|
||||
|
||||
enum cmd_templ {
|
||||
CMD_TEMPL_NULL_DATA = 0,
|
||||
CMD_TEMPL_BEACON,
|
||||
|
|
|
@ -412,8 +412,7 @@ struct conf_rx_settings {
|
|||
#define CONF_TX_RATE_RETRY_LIMIT 10
|
||||
|
||||
/* basic rates for p2p operations (probe req/resp, etc.) */
|
||||
#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \
|
||||
CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS)
|
||||
#define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS
|
||||
|
||||
/*
|
||||
* Rates supported for data packets when operating as AP. Note the absence
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
#define DRIVER_NAME "wl12xx"
|
||||
#define DRIVER_NAME "wlcore"
|
||||
#define DRIVER_PREFIX DRIVER_NAME ": "
|
||||
|
||||
enum {
|
||||
|
@ -73,11 +73,21 @@ extern u32 wl12xx_debug_level;
|
|||
#define wl1271_info(fmt, arg...) \
|
||||
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
|
||||
|
||||
/* define the debug macro differently if dynamic debug is supported */
|
||||
#if defined(CONFIG_DYNAMIC_DEBUG)
|
||||
#define wl1271_debug(level, fmt, arg...) \
|
||||
do { \
|
||||
if (level & wl12xx_debug_level) \
|
||||
pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \
|
||||
if (unlikely(level & wl12xx_debug_level)) \
|
||||
dynamic_pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \
|
||||
} while (0)
|
||||
#else
|
||||
#define wl1271_debug(level, fmt, arg...) \
|
||||
do { \
|
||||
if (unlikely(level & wl12xx_debug_level)) \
|
||||
printk(KERN_DEBUG pr_fmt(DRIVER_PREFIX fmt "\n"), \
|
||||
##arg); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* TODO: use pr_debug_hex_dump when it becomes available */
|
||||
#define wl1271_dump(level, prefix, buf, len) \
|
||||
|
|
|
@ -62,11 +62,14 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (wl->state == WL1271_STATE_ON && !wl->plt &&
|
||||
if (!wl->plt &&
|
||||
time_after(jiffies, wl->stats.fw_stats_update +
|
||||
msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
|
||||
wl1271_acx_statistics(wl, wl->stats.fw_stats);
|
||||
|
@ -286,7 +289,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file,
|
|||
|
||||
wl->conf.conn.dynamic_ps_timeout = value;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -353,7 +356,7 @@ static ssize_t forced_ps_write(struct file *file,
|
|||
|
||||
wl->conf.conn.forced_ps = value;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -486,6 +489,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
|
|||
DRIVER_STATE_PRINT_HEX(platform_quirks);
|
||||
DRIVER_STATE_PRINT_HEX(chip.id);
|
||||
DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
|
||||
DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
|
||||
DRIVER_STATE_PRINT_INT(sched_scanning);
|
||||
|
||||
#undef DRIVER_STATE_PRINT_INT
|
||||
|
@ -999,7 +1003,7 @@ static ssize_t sleep_auth_write(struct file *file,
|
|||
|
||||
wl->conf.conn.sta_sleep_auth = value;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
/* this will show up on "read" in case we are off */
|
||||
wl->sleep_auth = value;
|
||||
goto out;
|
||||
|
@ -1060,14 +1064,16 @@ static ssize_t dev_mem_read(struct file *file,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state == WLCORE_STATE_OFF)) {
|
||||
ret = -EFAULT;
|
||||
goto skip_read;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto skip_read;
|
||||
/*
|
||||
* Don't fail if elp_wakeup returns an error, so the device's memory
|
||||
* could be read even if the FW crashed
|
||||
*/
|
||||
wl1271_ps_elp_wakeup(wl);
|
||||
|
||||
/* store current partition and switch partition */
|
||||
memcpy(&old_part, &wl->curr_part, sizeof(old_part));
|
||||
|
@ -1145,14 +1151,16 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state == WLCORE_STATE_OFF)) {
|
||||
ret = -EFAULT;
|
||||
goto skip_write;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto skip_write;
|
||||
/*
|
||||
* Don't fail if elp_wakeup returns an error, so the device's memory
|
||||
* could be read even if the FW crashed
|
||||
*/
|
||||
wl1271_ps_elp_wakeup(wl);
|
||||
|
||||
/* store current partition and switch partition */
|
||||
memcpy(&old_part, &wl->curr_part, sizeof(old_part));
|
||||
|
|
|
@ -141,7 +141,7 @@ int wl1271_init_templates_config(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
|
||||
for (i = 0; i < WLCORE_MAX_KLV_TEMPLATES; i++) {
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_KLV, NULL,
|
||||
sizeof(struct ieee80211_qos_hdr),
|
||||
|
@ -371,15 +371,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
int ret, i;
|
||||
|
||||
/* disable all keep-alive templates */
|
||||
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
|
||||
ret = wl1271_acx_keep_alive_config(wl, wlvif, i,
|
||||
ACX_KEEP_ALIVE_TPL_INVALID);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
int ret;
|
||||
|
||||
/* disable the keep-alive feature */
|
||||
ret = wl1271_acx_keep_alive_mode(wl, wlvif, false);
|
||||
|
|
|
@ -64,7 +64,7 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
|
|||
return -EIO;
|
||||
|
||||
ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
|
||||
if (ret && wl->state != WL1271_STATE_OFF)
|
||||
if (ret && wl->state != WLCORE_STATE_OFF)
|
||||
set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
|
||||
|
||||
return ret;
|
||||
|
@ -80,7 +80,7 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
|
|||
return -EIO;
|
||||
|
||||
ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
|
||||
if (ret && wl->state != WL1271_STATE_OFF)
|
||||
if (ret && wl->state != WLCORE_STATE_OFF)
|
||||
set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -248,7 +248,7 @@ static void wl12xx_tx_watchdog_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
/* Tx went out in the meantime - everything is ok */
|
||||
|
@ -512,7 +512,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
|
|||
|
||||
wl1271_debug(DEBUG_IRQ, "IRQ work");
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -696,7 +696,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
|
|||
* we can't call wl12xx_get_vif_count() here because
|
||||
* wl->mutex is taken, so use the cached last_vif_count value
|
||||
*/
|
||||
if (wl->last_vif_count > 1) {
|
||||
if (wl->last_vif_count > 1 && wl->mr_fw_name) {
|
||||
fw_type = WL12XX_FW_TYPE_MULTI;
|
||||
fw_name = wl->mr_fw_name;
|
||||
} else {
|
||||
|
@ -744,38 +744,14 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void wl1271_fetch_nvs(struct wl1271 *wl)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev);
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_debug(DEBUG_BOOT, "could not get nvs file %s: %d",
|
||||
WL12XX_NVS_NAME, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
||||
|
||||
if (!wl->nvs) {
|
||||
wl1271_error("could not allocate memory for the nvs file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl->nvs_len = fw->size;
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
void wl12xx_queue_recovery_work(struct wl1271 *wl)
|
||||
{
|
||||
WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
|
||||
|
||||
/* Avoid a recursive recovery */
|
||||
if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
|
||||
if (wl->state == WLCORE_STATE_ON) {
|
||||
wl->state = WLCORE_STATE_RESTARTING;
|
||||
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
|
||||
wlcore_disable_interrupts_nosync(wl);
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
}
|
||||
|
@ -913,7 +889,7 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state != WL1271_STATE_ON || wl->plt)
|
||||
if (wl->state == WLCORE_STATE_OFF || wl->plt)
|
||||
goto out_unlock;
|
||||
|
||||
if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) {
|
||||
|
@ -1081,7 +1057,7 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode)
|
|||
|
||||
wl1271_notice("power up");
|
||||
|
||||
if (wl->state != WL1271_STATE_OFF) {
|
||||
if (wl->state != WLCORE_STATE_OFF) {
|
||||
wl1271_error("cannot go into PLT state because not "
|
||||
"in off state: %d", wl->state);
|
||||
ret = -EBUSY;
|
||||
|
@ -1102,7 +1078,7 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode)
|
|||
if (ret < 0)
|
||||
goto power_off;
|
||||
|
||||
wl->state = WL1271_STATE_ON;
|
||||
wl->state = WLCORE_STATE_ON;
|
||||
wl1271_notice("firmware booted in PLT mode %s (%s)",
|
||||
PLT_MODE[plt_mode],
|
||||
wl->chip.fw_ver_str);
|
||||
|
@ -1171,7 +1147,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
|
|||
wl1271_power_off(wl);
|
||||
wl->flags = 0;
|
||||
wl->sleep_auth = WL1271_PSM_ILLEGAL;
|
||||
wl->state = WL1271_STATE_OFF;
|
||||
wl->state = WLCORE_STATE_OFF;
|
||||
wl->plt = false;
|
||||
wl->plt_mode = PLT_OFF;
|
||||
wl->rx_counter = 0;
|
||||
|
@ -1602,12 +1578,6 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
|
|||
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
||||
goto out;
|
||||
|
||||
if ((wl->conf.conn.suspend_wake_up_event ==
|
||||
wl->conf.conn.wake_up_event) &&
|
||||
(wl->conf.conn.suspend_listen_interval ==
|
||||
wl->conf.conn.listen_interval))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -1616,6 +1586,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
|
|||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
if ((wl->conf.conn.suspend_wake_up_event ==
|
||||
wl->conf.conn.wake_up_event) &&
|
||||
(wl->conf.conn.suspend_listen_interval ==
|
||||
wl->conf.conn.listen_interval))
|
||||
goto out_sleep;
|
||||
|
||||
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
||||
wl->conf.conn.suspend_wake_up_event,
|
||||
wl->conf.conn.suspend_listen_interval);
|
||||
|
@ -1671,11 +1647,7 @@ static void wl1271_configure_resume(struct wl1271 *wl,
|
|||
if ((!is_ap) && (!is_sta))
|
||||
return;
|
||||
|
||||
if (is_sta &&
|
||||
((wl->conf.conn.suspend_wake_up_event ==
|
||||
wl->conf.conn.wake_up_event) &&
|
||||
(wl->conf.conn.suspend_listen_interval ==
|
||||
wl->conf.conn.listen_interval)))
|
||||
if (is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
||||
return;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -1685,6 +1657,12 @@ static void wl1271_configure_resume(struct wl1271 *wl,
|
|||
if (is_sta) {
|
||||
wl1271_configure_wowlan(wl, NULL);
|
||||
|
||||
if ((wl->conf.conn.suspend_wake_up_event ==
|
||||
wl->conf.conn.wake_up_event) &&
|
||||
(wl->conf.conn.suspend_listen_interval ==
|
||||
wl->conf.conn.listen_interval))
|
||||
goto out_sleep;
|
||||
|
||||
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
||||
wl->conf.conn.wake_up_event,
|
||||
wl->conf.conn.listen_interval);
|
||||
|
@ -1697,6 +1675,7 @@ static void wl1271_configure_resume(struct wl1271 *wl,
|
|||
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
}
|
||||
|
||||
|
@ -1833,7 +1812,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (wl->state == WLCORE_STATE_OFF) {
|
||||
if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
|
||||
&wl->flags))
|
||||
wlcore_enable_interrupts(wl);
|
||||
|
@ -1845,7 +1824,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
|
|||
* this must be before the cancel_work calls below, so that the work
|
||||
* functions don't perform further work.
|
||||
*/
|
||||
wl->state = WL1271_STATE_OFF;
|
||||
wl->state = WLCORE_STATE_OFF;
|
||||
|
||||
/*
|
||||
* Use the nosync variant to disable interrupts, so the mutex could be
|
||||
|
@ -1856,6 +1835,8 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
|
|||
mutex_unlock(&wl->mutex);
|
||||
|
||||
wlcore_synchronize_interrupts(wl);
|
||||
if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
|
||||
cancel_work_sync(&wl->recovery_work);
|
||||
wl1271_flush_deferred_work(wl);
|
||||
cancel_delayed_work_sync(&wl->scan_complete_work);
|
||||
cancel_work_sync(&wl->netstack_work);
|
||||
|
@ -1958,6 +1939,27 @@ static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx)
|
|||
*idx = WL12XX_MAX_RATE_POLICIES;
|
||||
}
|
||||
|
||||
static int wlcore_allocate_klv_template(struct wl1271 *wl, u8 *idx)
|
||||
{
|
||||
u8 policy = find_first_zero_bit(wl->klv_templates_map,
|
||||
WLCORE_MAX_KLV_TEMPLATES);
|
||||
if (policy >= WLCORE_MAX_KLV_TEMPLATES)
|
||||
return -EBUSY;
|
||||
|
||||
__set_bit(policy, wl->klv_templates_map);
|
||||
*idx = policy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wlcore_free_klv_template(struct wl1271 *wl, u8 *idx)
|
||||
{
|
||||
if (WARN_ON(*idx >= WLCORE_MAX_KLV_TEMPLATES))
|
||||
return;
|
||||
|
||||
__clear_bit(*idx, wl->klv_templates_map);
|
||||
*idx = WLCORE_MAX_KLV_TEMPLATES;
|
||||
}
|
||||
|
||||
static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
{
|
||||
switch (wlvif->bss_type) {
|
||||
|
@ -2022,6 +2024,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
|
|||
wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx);
|
||||
wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx);
|
||||
wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx);
|
||||
wlcore_allocate_klv_template(wl, &wlvif->sta.klv_template_id);
|
||||
wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC;
|
||||
wlvif->rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
|
@ -2098,7 +2101,7 @@ irq_disable:
|
|||
/* Unlocking the mutex in the middle of handling is
|
||||
inherently unsafe. In this case we deem it safe to do,
|
||||
because we need to let any possibly pending IRQ out of
|
||||
the system (and while we are WL1271_STATE_OFF the IRQ
|
||||
the system (and while we are WLCORE_STATE_OFF the IRQ
|
||||
work function will not do anything.) Also, any other
|
||||
possible concurrent operations will fail due to the
|
||||
current state, hence the wl1271 struct should be safe. */
|
||||
|
@ -2133,7 +2136,7 @@ power_off:
|
|||
wl1271_debug(DEBUG_MAC80211, "11a is %ssupported",
|
||||
wl->enable_11a ? "" : "not ");
|
||||
|
||||
wl->state = WL1271_STATE_ON;
|
||||
wl->state = WLCORE_STATE_ON;
|
||||
out:
|
||||
return booted;
|
||||
}
|
||||
|
@ -2167,7 +2170,11 @@ static bool wl12xx_need_fw_change(struct wl1271 *wl,
|
|||
wl->last_vif_count = vif_count;
|
||||
|
||||
/* no need for fw change if the device is OFF */
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (wl->state == WLCORE_STATE_OFF)
|
||||
return false;
|
||||
|
||||
/* no need for fw change if a single fw is used */
|
||||
if (!wl->mr_fw_name)
|
||||
return false;
|
||||
|
||||
if (vif_count > 1 && current_fw == WL12XX_FW_TYPE_NORMAL)
|
||||
|
@ -2249,7 +2256,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
* TODO: after the nvs issue will be solved, move this block
|
||||
* to start(), and make sure here the driver is ON.
|
||||
*/
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (wl->state == WLCORE_STATE_OFF) {
|
||||
/*
|
||||
* we still need this in order to configure the fw
|
||||
* while uploading the nvs
|
||||
|
@ -2263,21 +2270,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
|
||||
wlvif->bss_type == BSS_TYPE_IBSS) {
|
||||
/*
|
||||
* The device role is a special role used for
|
||||
* rx and tx frames prior to association (as
|
||||
* the STA role can get packets only from
|
||||
* its associated bssid)
|
||||
*/
|
||||
ret = wl12xx_cmd_role_enable(wl, vif->addr,
|
||||
WL1271_ROLE_DEVICE,
|
||||
&wlvif->dev_role_id);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl12xx_cmd_role_enable(wl, vif->addr,
|
||||
role_type, &wlvif->role_id);
|
||||
if (ret < 0)
|
||||
|
@ -2316,7 +2308,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|||
return;
|
||||
|
||||
/* because of hardware recovery, we may get here twice */
|
||||
if (wl->state != WL1271_STATE_ON)
|
||||
if (wl->state == WLCORE_STATE_OFF)
|
||||
return;
|
||||
|
||||
wl1271_info("down");
|
||||
|
@ -2346,10 +2338,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|||
wlvif->bss_type == BSS_TYPE_IBSS) {
|
||||
if (wl12xx_dev_role_started(wlvif))
|
||||
wl12xx_stop_dev(wl, wlvif);
|
||||
|
||||
ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
|
||||
if (ret < 0)
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id);
|
||||
|
@ -2368,6 +2356,7 @@ deinit:
|
|||
wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx);
|
||||
wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx);
|
||||
wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx);
|
||||
wlcore_free_klv_template(wl, &wlvif->sta.klv_template_id);
|
||||
} else {
|
||||
wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
|
||||
wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
|
||||
|
@ -2432,12 +2421,11 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
|||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
struct wl12xx_vif *iter;
|
||||
struct vif_counter_data vif_count;
|
||||
bool cancel_recovery = true;
|
||||
|
||||
wl12xx_get_vif_count(hw, vif, &vif_count);
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF ||
|
||||
if (wl->state == WLCORE_STATE_OFF ||
|
||||
!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))
|
||||
goto out;
|
||||
|
||||
|
@ -2457,12 +2445,9 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
|||
wl12xx_force_active_psm(wl);
|
||||
set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
|
||||
wl12xx_queue_recovery_work(wl);
|
||||
cancel_recovery = false;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
if (cancel_recovery)
|
||||
cancel_work_sync(&wl->recovery_work);
|
||||
}
|
||||
|
||||
static int wl12xx_op_change_interface(struct ieee80211_hw *hw,
|
||||
|
@ -2536,7 +2521,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||
goto out;
|
||||
|
||||
ret = wl1271_acx_keep_alive_config(wl, wlvif,
|
||||
CMD_TEMPL_KLV_IDX_NULL_DATA,
|
||||
wlvif->sta.klv_template_id,
|
||||
ACX_KEEP_ALIVE_TPL_VALID);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -2556,6 +2541,11 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
ieee80211_chswitch_done(vif, false);
|
||||
}
|
||||
|
||||
/* invalidate keep-alive template */
|
||||
wl1271_acx_keep_alive_config(wl, wlvif,
|
||||
wlvif->sta.klv_template_id,
|
||||
ACX_KEEP_ALIVE_TPL_INVALID);
|
||||
|
||||
/* to stop listening to a channel, we disconnect */
|
||||
ret = wl12xx_cmd_role_stop_sta(wl, wlvif);
|
||||
if (ret < 0)
|
||||
|
@ -2594,11 +2584,6 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||
wlvif->rate_set =
|
||||
wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
|
||||
ret = wl1271_acx_sta_rate_policies(wl, wlvif);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = wl1271_acx_keep_alive_config(
|
||||
wl, wlvif, CMD_TEMPL_KLV_IDX_NULL_DATA,
|
||||
ACX_KEEP_ALIVE_TPL_INVALID);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
|
||||
|
@ -2772,7 +2757,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
if (changed & IEEE80211_CONF_CHANGE_POWER)
|
||||
wl->power_level = conf->power_level;
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -2806,10 +2791,6 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct wl1271_filter_params *fp;
|
||||
struct netdev_hw_addr *ha;
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
return 0;
|
||||
|
||||
fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
|
||||
if (!fp) {
|
||||
|
@ -2858,7 +2839,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
|
|||
*total &= WL1271_SUPPORTED_FILTERS;
|
||||
changed &= WL1271_SUPPORTED_FILTERS;
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -3082,8 +3063,45 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
struct ieee80211_key_conf *key_conf)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int ret;
|
||||
bool might_change_spare =
|
||||
key_conf->cipher == WL1271_CIPHER_SUITE_GEM ||
|
||||
key_conf->cipher == WLAN_CIPHER_SUITE_TKIP;
|
||||
|
||||
return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf);
|
||||
if (might_change_spare) {
|
||||
/*
|
||||
* stop the queues and flush to ensure the next packets are
|
||||
* in sync with FW spare block accounting
|
||||
*/
|
||||
mutex_lock(&wl->mutex);
|
||||
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
wl1271_tx_flush(wl);
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EAGAIN;
|
||||
goto out_wake_queues;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out_wake_queues;
|
||||
|
||||
ret = wlcore_hw_set_key(wl, cmd, vif, sta, key_conf);
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out_wake_queues:
|
||||
if (might_change_spare)
|
||||
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
||||
|
@ -3105,17 +3123,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
key_conf->keylen, key_conf->flags);
|
||||
wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
switch (key_conf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
|
@ -3145,8 +3152,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
default:
|
||||
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
|
||||
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out_sleep;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -3157,7 +3163,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
tx_seq_32, tx_seq_16, sta);
|
||||
if (ret < 0) {
|
||||
wl1271_error("Could not add or replace key");
|
||||
goto out_sleep;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3171,7 +3177,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
ret = wl1271_cmd_build_arp_rsp(wl, wlvif);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("build arp rsp failed: %d", ret);
|
||||
goto out_sleep;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -3183,22 +3189,15 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
|||
0, 0, sta);
|
||||
if (ret < 0) {
|
||||
wl1271_error("Could not remove key");
|
||||
goto out_sleep;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wl1271_error("Unsupported key cmd 0x%x", cmd);
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wlcore_set_key);
|
||||
|
@ -3221,7 +3220,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
/*
|
||||
* We cannot return -EBUSY here because cfg80211 will expect
|
||||
* a call to ieee80211_scan_completed if we do - in this case
|
||||
|
@ -3261,7 +3260,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
|
||||
|
@ -3310,7 +3309,7 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
@ -3347,7 +3346,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -3368,7 +3367,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
@ -3397,7 +3396,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
@ -4173,7 +4172,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)))
|
||||
|
@ -4257,7 +4256,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -4456,7 +4455,7 @@ static int wl12xx_op_sta_state(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
@ -4495,7 +4494,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
@ -4613,7 +4612,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
|
|||
mask->control[i].legacy,
|
||||
i);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
if (wlvif->bss_type == BSS_TYPE_STA_BSS &&
|
||||
|
@ -4649,12 +4648,14 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
if (unlikely(wl->state == WLCORE_STATE_OFF)) {
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
ieee80211_chswitch_done(vif, false);
|
||||
}
|
||||
goto out;
|
||||
} else if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -4689,7 +4690,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
/* packets are considered pending if in the TX queue or the FW */
|
||||
|
@ -4938,7 +4939,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev,
|
|||
|
||||
wl->sg_enabled = res;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
|
@ -5056,7 +5057,7 @@ static void wl1271_connection_loss_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
/* Call mac80211 connection loss */
|
||||
|
@ -5070,18 +5071,17 @@ out:
|
|||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
|
||||
u32 oui, u32 nic, int n)
|
||||
static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic)
|
||||
{
|
||||
int i;
|
||||
|
||||
wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d",
|
||||
oui, nic, n);
|
||||
wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x",
|
||||
oui, nic);
|
||||
|
||||
if (nic + n - 1 > 0xffffff)
|
||||
if (nic + WLCORE_NUM_MAC_ADDRESSES - wl->num_mac_addr > 0xffffff)
|
||||
wl1271_warning("NIC part of the MAC address wraps around!");
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (i = 0; i < wl->num_mac_addr; i++) {
|
||||
wl->addresses[i].addr[0] = (u8)(oui >> 16);
|
||||
wl->addresses[i].addr[1] = (u8)(oui >> 8);
|
||||
wl->addresses[i].addr[2] = (u8) oui;
|
||||
|
@ -5091,7 +5091,22 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
|
|||
nic++;
|
||||
}
|
||||
|
||||
wl->hw->wiphy->n_addresses = n;
|
||||
/* we may be one address short at the most */
|
||||
WARN_ON(wl->num_mac_addr + 1 < WLCORE_NUM_MAC_ADDRESSES);
|
||||
|
||||
/*
|
||||
* turn on the LAA bit in the first address and use it as
|
||||
* the last address.
|
||||
*/
|
||||
if (wl->num_mac_addr < WLCORE_NUM_MAC_ADDRESSES) {
|
||||
int idx = WLCORE_NUM_MAC_ADDRESSES - 1;
|
||||
memcpy(&wl->addresses[idx], &wl->addresses[0],
|
||||
sizeof(wl->addresses[0]));
|
||||
/* LAA bit */
|
||||
wl->addresses[idx].addr[2] |= BIT(1);
|
||||
}
|
||||
|
||||
wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES;
|
||||
wl->hw->wiphy->addresses = wl->addresses;
|
||||
}
|
||||
|
||||
|
@ -5130,8 +5145,7 @@ static int wl1271_register_hw(struct wl1271 *wl)
|
|||
if (wl->mac80211_registered)
|
||||
return 0;
|
||||
|
||||
wl1271_fetch_nvs(wl);
|
||||
if (wl->nvs != NULL) {
|
||||
if (wl->nvs_len >= 12) {
|
||||
/* NOTE: The wl->nvs->nvs element must be first, in
|
||||
* order to simplify the casting, we assume it is at
|
||||
* the beginning of the wl->nvs structure.
|
||||
|
@ -5151,7 +5165,7 @@ static int wl1271_register_hw(struct wl1271 *wl)
|
|||
nic_addr = wl->fuse_nic_addr + 1;
|
||||
}
|
||||
|
||||
wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2);
|
||||
wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr);
|
||||
|
||||
ret = ieee80211_register_hw(wl->hw);
|
||||
if (ret < 0) {
|
||||
|
@ -5181,7 +5195,7 @@ static void wl1271_unregister_hw(struct wl1271 *wl)
|
|||
|
||||
static const struct ieee80211_iface_limit wlcore_iface_limits[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.max = 3,
|
||||
.types = BIT(NL80211_IFTYPE_STATION),
|
||||
},
|
||||
{
|
||||
|
@ -5196,7 +5210,7 @@ static const struct ieee80211_iface_combination
|
|||
wlcore_iface_combinations[] = {
|
||||
{
|
||||
.num_different_channels = 1,
|
||||
.max_interfaces = 2,
|
||||
.max_interfaces = 3,
|
||||
.limits = wlcore_iface_limits,
|
||||
.n_limits = ARRAY_SIZE(wlcore_iface_limits),
|
||||
},
|
||||
|
@ -5312,7 +5326,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
|
||||
#define WL1271_DEFAULT_CHANNEL 0
|
||||
|
||||
struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
|
||||
struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl1271 *wl;
|
||||
|
@ -5392,17 +5406,19 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
|
|||
|
||||
spin_lock_init(&wl->wl_lock);
|
||||
|
||||
wl->state = WL1271_STATE_OFF;
|
||||
wl->state = WLCORE_STATE_OFF;
|
||||
wl->fw_type = WL12XX_FW_TYPE_NONE;
|
||||
mutex_init(&wl->mutex);
|
||||
mutex_init(&wl->flush_mutex);
|
||||
init_completion(&wl->nvs_loading_complete);
|
||||
|
||||
order = get_order(WL1271_AGGR_BUFFER_SIZE);
|
||||
order = get_order(aggr_buf_size);
|
||||
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
|
||||
if (!wl->aggr_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto err_wq;
|
||||
}
|
||||
wl->aggr_buf_size = aggr_buf_size;
|
||||
|
||||
wl->dummy_packet = wl12xx_alloc_dummy_packet(wl);
|
||||
if (!wl->dummy_packet) {
|
||||
|
@ -5465,8 +5481,7 @@ int wlcore_free_hw(struct wl1271 *wl)
|
|||
device_remove_file(wl->dev, &dev_attr_bt_coex_state);
|
||||
free_page((unsigned long)wl->fwlog);
|
||||
dev_kfree_skb(wl->dummy_packet);
|
||||
free_pages((unsigned long)wl->aggr_buf,
|
||||
get_order(WL1271_AGGR_BUFFER_SIZE));
|
||||
free_pages((unsigned long)wl->aggr_buf, get_order(wl->aggr_buf_size));
|
||||
|
||||
wl1271_debugfs_exit(wl);
|
||||
|
||||
|
@ -5516,17 +5531,32 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
|
|||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
||||
static void wlcore_nvs_cb(const struct firmware *fw, void *context)
|
||||
{
|
||||
struct wl1271 *wl = context;
|
||||
struct platform_device *pdev = wl->pdev;
|
||||
struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
|
||||
unsigned long irqflags;
|
||||
int ret;
|
||||
|
||||
if (!wl->ops || !wl->ptable) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_hw;
|
||||
if (fw) {
|
||||
wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
||||
if (!wl->nvs) {
|
||||
wl1271_error("Could not allocate nvs data");
|
||||
goto out;
|
||||
}
|
||||
wl->nvs_len = fw->size;
|
||||
} else {
|
||||
wl1271_debug(DEBUG_BOOT, "Could not get nvs file %s",
|
||||
WL12XX_NVS_NAME);
|
||||
wl->nvs = NULL;
|
||||
wl->nvs_len = 0;
|
||||
}
|
||||
|
||||
ret = wl->ops->setup(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_nvs;
|
||||
|
||||
BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS);
|
||||
|
||||
/* adjust some runtime configuration parameters */
|
||||
|
@ -5535,11 +5565,8 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|||
wl->irq = platform_get_irq(pdev, 0);
|
||||
wl->platform_quirks = pdata->platform_quirks;
|
||||
wl->set_power = pdata->set_power;
|
||||
wl->dev = &pdev->dev;
|
||||
wl->if_ops = pdata->ops;
|
||||
|
||||
platform_set_drvdata(pdev, wl);
|
||||
|
||||
if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
|
||||
irqflags = IRQF_TRIGGER_RISING;
|
||||
else
|
||||
|
@ -5550,7 +5577,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|||
pdev->name, wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("request_irq() failed: %d", ret);
|
||||
goto out_free_hw;
|
||||
goto out_free_nvs;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -5609,6 +5636,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|||
goto out_hw_pg_ver;
|
||||
}
|
||||
|
||||
wl->initialized = true;
|
||||
goto out;
|
||||
|
||||
out_hw_pg_ver:
|
||||
|
@ -5623,10 +5651,33 @@ out_unreg:
|
|||
out_irq:
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
out_free_hw:
|
||||
wlcore_free_hw(wl);
|
||||
out_free_nvs:
|
||||
kfree(wl->nvs);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
complete_all(&wl->nvs_loading_complete);
|
||||
}
|
||||
|
||||
int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!wl->ops || !wl->ptable)
|
||||
return -EINVAL;
|
||||
|
||||
wl->dev = &pdev->dev;
|
||||
wl->pdev = pdev;
|
||||
platform_set_drvdata(pdev, wl);
|
||||
|
||||
ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
|
||||
WL12XX_NVS_NAME, &pdev->dev, GFP_KERNEL,
|
||||
wl, wlcore_nvs_cb);
|
||||
if (ret < 0) {
|
||||
wl1271_error("request_firmware_nowait failed: %d", ret);
|
||||
complete_all(&wl->nvs_loading_complete);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wlcore_probe);
|
||||
|
@ -5635,6 +5686,10 @@ int __devexit wlcore_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct wl1271 *wl = platform_get_drvdata(pdev);
|
||||
|
||||
wait_for_completion(&wl->nvs_loading_complete);
|
||||
if (!wl->initialized)
|
||||
return 0;
|
||||
|
||||
if (wl->irq_wake_enabled) {
|
||||
device_init_wakeup(wl->dev, 0);
|
||||
disable_irq_wake(wl->irq);
|
||||
|
@ -5665,3 +5720,4 @@ MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck.");
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL12XX_NVS_NAME);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#define WL1271_WAKEUP_TIMEOUT 500
|
||||
|
||||
#define ELP_ENTRY_DELAY 5
|
||||
#define ELP_ENTRY_DELAY 30
|
||||
|
||||
void wl1271_elp_work(struct work_struct *work)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ void wl1271_elp_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
/* our work might have been already cancelled */
|
||||
|
@ -98,11 +98,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
|||
return;
|
||||
}
|
||||
|
||||
if (wl->conf.conn.forced_ps)
|
||||
timeout = ELP_ENTRY_DELAY;
|
||||
else
|
||||
timeout = wl->conf.conn.dynamic_ps_timeout;
|
||||
|
||||
timeout = ELP_ENTRY_DELAY;
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(timeout));
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
|
|||
pkt_len = wlcore_rx_get_buf_size(wl, des);
|
||||
align_pkt_len = wlcore_rx_get_align_buf_size(wl,
|
||||
pkt_len);
|
||||
if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE)
|
||||
if (buf_size + align_pkt_len > wl->aggr_buf_size)
|
||||
break;
|
||||
buf_size += align_pkt_len;
|
||||
rx_counter++;
|
||||
|
|
|
@ -46,7 +46,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
|
||||
|
@ -184,11 +184,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
|
|||
if (passive)
|
||||
scan_options |= WL1271_SCAN_OPT_PASSIVE;
|
||||
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS ||
|
||||
test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
||||
cmd->params.role_id = wlvif->role_id;
|
||||
else
|
||||
cmd->params.role_id = wlvif->dev_role_id;
|
||||
cmd->params.role_id = wlvif->role_id;
|
||||
|
||||
if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) {
|
||||
ret = -EINVAL;
|
||||
|
@ -593,7 +589,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
|
|||
goto out;
|
||||
}
|
||||
|
||||
cmd->role_id = wlvif->dev_role_id;
|
||||
cmd->role_id = wlvif->role_id;
|
||||
if (!n_match_ssids) {
|
||||
/* No filter, with ssids */
|
||||
type = SCAN_SSID_FILTER_DISABLED;
|
||||
|
@ -683,7 +679,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
|||
if (!cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
cfg->role_id = wlvif->dev_role_id;
|
||||
cfg->role_id = wlvif->role_id;
|
||||
cfg->rssi_threshold = c->rssi_threshold;
|
||||
cfg->snr_threshold = c->snr_threshold;
|
||||
cfg->n_probe_reqs = c->num_probe_reqs;
|
||||
|
@ -718,7 +714,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
|||
if (!force_passive && cfg->active[0]) {
|
||||
u8 band = IEEE80211_BAND_2GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
wlvif->dev_role_id, band,
|
||||
wlvif->role_id, band,
|
||||
req->ssids[0].ssid,
|
||||
req->ssids[0].ssid_len,
|
||||
ies->ie[band],
|
||||
|
@ -732,7 +728,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
|||
if (!force_passive && cfg->active[1]) {
|
||||
u8 band = IEEE80211_BAND_5GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
wlvif->dev_role_id, band,
|
||||
wlvif->role_id, band,
|
||||
req->ssids[0].ssid,
|
||||
req->ssids[0].ssid_len,
|
||||
ies->ie[band],
|
||||
|
@ -774,7 +770,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
if (!start)
|
||||
return -ENOMEM;
|
||||
|
||||
start->role_id = wlvif->dev_role_id;
|
||||
start->role_id = wlvif->role_id;
|
||||
start->tag = WL1271_SCAN_DEFAULT_TAG;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start,
|
||||
|
@ -810,7 +806,7 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
return;
|
||||
}
|
||||
|
||||
stop->role_id = wlvif->dev_role_id;
|
||||
stop->role_id = wlvif->role_id;
|
||||
stop->tag = WL1271_SCAN_DEFAULT_TAG;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop,
|
||||
|
|
|
@ -66,7 +66,13 @@
|
|||
/* HW limitation: maximum possible chunk size is 4095 bytes */
|
||||
#define WSPI_MAX_CHUNK_SIZE 4092
|
||||
|
||||
#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
|
||||
/*
|
||||
* only support SPI for 12xx - this code should be reworked when 18xx
|
||||
* support is introduced
|
||||
*/
|
||||
#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
|
||||
|
||||
#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
|
||||
|
||||
struct wl12xx_spi_glue {
|
||||
struct device *dev;
|
||||
|
@ -271,7 +277,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
|
|||
u32 chunk_len;
|
||||
int i;
|
||||
|
||||
WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
|
||||
WARN_ON(len > SPI_AGGR_BUFFER_SIZE);
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
|
|
|
@ -92,7 +92,7 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
|
|||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF) {
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||
int id, ret = -EBUSY, ac;
|
||||
u32 spare_blocks;
|
||||
|
||||
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
|
||||
if (buf_offset + total_len > wl->aggr_buf_size)
|
||||
return -EAGAIN;
|
||||
|
||||
spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem);
|
||||
|
@ -319,8 +319,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||
if (hlid == wlvif->ap.global_hlid)
|
||||
rate_idx = wlvif->ap.mgmt_rate_idx;
|
||||
else if (hlid == wlvif->ap.bcast_hlid ||
|
||||
skb->protocol == cpu_to_be16(ETH_P_PAE))
|
||||
/* send AP bcast and EAPOLs using the min basic rate */
|
||||
skb->protocol == cpu_to_be16(ETH_P_PAE) ||
|
||||
!ieee80211_is_data(frame_control))
|
||||
/*
|
||||
* send non-data, bcast and EAPOLs using the
|
||||
* min basic rate
|
||||
*/
|
||||
rate_idx = wlvif->ap.bcast_rate_idx;
|
||||
else
|
||||
rate_idx = wlvif->ap.ucast_rate_idx[ac];
|
||||
|
@ -687,7 +691,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
|
|||
int bus_ret = 0;
|
||||
u8 hlid;
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
return 0;
|
||||
|
||||
while ((skb = wl1271_skb_dequeue(wl, &hlid))) {
|
||||
|
@ -1072,39 +1076,54 @@ void wl12xx_tx_reset(struct wl1271 *wl)
|
|||
/* caller must *NOT* hold wl->mutex */
|
||||
void wl1271_tx_flush(struct wl1271 *wl)
|
||||
{
|
||||
unsigned long timeout;
|
||||
unsigned long timeout, start_time;
|
||||
int i;
|
||||
timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
|
||||
start_time = jiffies;
|
||||
timeout = start_time + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
|
||||
|
||||
/* only one flush should be in progress, for consistent queue state */
|
||||
mutex_lock(&wl->flush_mutex);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (wl->tx_frames_cnt == 0 && wl1271_tx_total_queue_count(wl) == 0) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH);
|
||||
|
||||
while (!time_after(jiffies, timeout)) {
|
||||
mutex_lock(&wl->mutex);
|
||||
wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
|
||||
wl1271_debug(DEBUG_MAC80211, "flushing tx buffer: %d %d",
|
||||
wl->tx_frames_cnt,
|
||||
wl1271_tx_total_queue_count(wl));
|
||||
|
||||
/* force Tx and give the driver some time to flush data */
|
||||
mutex_unlock(&wl->mutex);
|
||||
if (wl1271_tx_total_queue_count(wl))
|
||||
wl1271_tx_work(&wl->tx_work);
|
||||
msleep(20);
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if ((wl->tx_frames_cnt == 0) &&
|
||||
(wl1271_tx_total_queue_count(wl) == 0)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
goto out;
|
||||
wl1271_debug(DEBUG_MAC80211, "tx flush took %d ms",
|
||||
jiffies_to_msecs(jiffies - start_time));
|
||||
goto out_wake;
|
||||
}
|
||||
mutex_unlock(&wl->mutex);
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
wl1271_warning("Unable to flush all TX buffers, timed out.");
|
||||
wl1271_warning("Unable to flush all TX buffers, "
|
||||
"timed out (timeout %d ms",
|
||||
WL1271_TX_FLUSH_TIMEOUT / 1000);
|
||||
|
||||
/* forcibly flush all Tx buffers on our queues */
|
||||
mutex_lock(&wl->mutex);
|
||||
for (i = 0; i < WL12XX_MAX_LINKS; i++)
|
||||
wl1271_tx_reset_link_queues(wl, i);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
out:
|
||||
out_wake:
|
||||
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH);
|
||||
mutex_unlock(&wl->mutex);
|
||||
out:
|
||||
mutex_unlock(&wl->flush_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wl1271_tx_flush);
|
||||
|
|
|
@ -31,12 +31,19 @@
|
|||
/* The maximum number of Tx descriptors in all chip families */
|
||||
#define WLCORE_MAX_TX_DESCRIPTORS 32
|
||||
|
||||
/*
|
||||
* We always allocate this number of mac addresses. If we don't
|
||||
* have enough allocated addresses, the LAA bit is used
|
||||
*/
|
||||
#define WLCORE_NUM_MAC_ADDRESSES 3
|
||||
|
||||
/* forward declaration */
|
||||
struct wl1271_tx_hw_descr;
|
||||
enum wl_rx_buf_align;
|
||||
struct wl1271_rx_descriptor;
|
||||
|
||||
struct wlcore_ops {
|
||||
int (*setup)(struct wl1271 *wl);
|
||||
int (*identify_chip)(struct wl1271 *wl);
|
||||
int (*identify_fw)(struct wl1271 *wl);
|
||||
int (*boot)(struct wl1271 *wl);
|
||||
|
@ -139,10 +146,12 @@ struct wl1271_stats {
|
|||
};
|
||||
|
||||
struct wl1271 {
|
||||
bool initialized;
|
||||
struct ieee80211_hw *hw;
|
||||
bool mac80211_registered;
|
||||
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
|
||||
void *if_priv;
|
||||
|
||||
|
@ -153,7 +162,7 @@ struct wl1271 {
|
|||
|
||||
spinlock_t wl_lock;
|
||||
|
||||
enum wl1271_state state;
|
||||
enum wlcore_state state;
|
||||
enum wl12xx_fw_type fw_type;
|
||||
bool plt;
|
||||
enum plt_mode plt_mode;
|
||||
|
@ -181,7 +190,7 @@ struct wl1271 {
|
|||
u32 fuse_nic_addr;
|
||||
|
||||
/* we have up to 2 MAC addresses */
|
||||
struct mac_address addresses[2];
|
||||
struct mac_address addresses[WLCORE_NUM_MAC_ADDRESSES];
|
||||
int channel;
|
||||
u8 system_hlid;
|
||||
|
||||
|
@ -190,6 +199,8 @@ struct wl1271 {
|
|||
unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
|
||||
unsigned long rate_policies_map[
|
||||
BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)];
|
||||
unsigned long klv_templates_map[
|
||||
BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)];
|
||||
|
||||
struct list_head wlvif_list;
|
||||
|
||||
|
@ -237,6 +248,7 @@ struct wl1271 {
|
|||
|
||||
/* Intermediate buffer, used for packet aggregation */
|
||||
u8 *aggr_buf;
|
||||
u32 aggr_buf_size;
|
||||
|
||||
/* Reusable dummy packet template */
|
||||
struct sk_buff *dummy_packet;
|
||||
|
@ -393,13 +405,18 @@ struct wl1271 {
|
|||
/* sleep auth value currently configured to FW */
|
||||
int sleep_auth;
|
||||
|
||||
/* the number of allocated MAC addresses in this chip */
|
||||
int num_mac_addr;
|
||||
|
||||
/* the minimum FW version required for the driver to work */
|
||||
unsigned int min_fw_ver[NUM_FW_VER];
|
||||
|
||||
struct completion nvs_loading_complete;
|
||||
};
|
||||
|
||||
int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
|
||||
int __devexit wlcore_remove(struct platform_device *pdev);
|
||||
struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size);
|
||||
struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size);
|
||||
int wlcore_free_hw(struct wl1271 *wl);
|
||||
int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif,
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#define WLCORE_NUM_BANDS 2
|
||||
|
||||
#define WL12XX_MAX_RATE_POLICIES 16
|
||||
#define WLCORE_MAX_KLV_TEMPLATES 4
|
||||
|
||||
/* Defined by FW as 0. Will not be freed or allocated. */
|
||||
#define WL12XX_SYSTEM_HLID 0
|
||||
|
@ -83,11 +84,10 @@
|
|||
#define WL1271_AP_BSS_INDEX 0
|
||||
#define WL1271_AP_DEF_BEACON_EXP 20
|
||||
|
||||
#define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE)
|
||||
|
||||
enum wl1271_state {
|
||||
WL1271_STATE_OFF,
|
||||
WL1271_STATE_ON,
|
||||
enum wlcore_state {
|
||||
WLCORE_STATE_OFF,
|
||||
WLCORE_STATE_RESTARTING,
|
||||
WLCORE_STATE_ON,
|
||||
};
|
||||
|
||||
enum wl12xx_fw_type {
|
||||
|
@ -124,6 +124,7 @@ struct wl1271_chip {
|
|||
u32 id;
|
||||
char fw_ver_str[ETHTOOL_BUSINFO_LEN];
|
||||
unsigned int fw_ver[NUM_FW_VER];
|
||||
char phy_fw_ver_str[ETHTOOL_BUSINFO_LEN];
|
||||
};
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
|
@ -337,6 +338,8 @@ struct wl12xx_vif {
|
|||
u8 ap_rate_idx;
|
||||
u8 p2p_rate_idx;
|
||||
|
||||
u8 klv_template_id;
|
||||
|
||||
bool qos;
|
||||
} sta;
|
||||
struct {
|
||||
|
|
Loading…
Add table
Reference in a new issue