Commit f1b98bb3 authored by John W. Linville's avatar John W. Linville
parents 97ea6d0f af390f4d
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "../wlcore/acx.h" #include "../wlcore/acx.h"
#include "../wlcore/tx.h" #include "../wlcore/tx.h"
#include "../wlcore/rx.h" #include "../wlcore/rx.h"
#include "../wlcore/io.h"
#include "../wlcore/boot.h" #include "../wlcore/boot.h"
#include "wl12xx.h" #include "wl12xx.h"
...@@ -1185,9 +1184,16 @@ static int wl12xx_enable_interrupts(struct wl1271 *wl) ...@@ -1185,9 +1184,16 @@ static int wl12xx_enable_interrupts(struct wl1271 *wl)
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
if (ret < 0) if (ret < 0)
goto out; goto disable_interrupts;
ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); 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: out:
return ret; return ret;
...@@ -1583,7 +1589,10 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, ...@@ -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); return wlcore_set_key(wl, cmd, vif, sta, key_conf);
} }
static int wl12xx_setup(struct wl1271 *wl);
static struct wlcore_ops wl12xx_ops = { static struct wlcore_ops wl12xx_ops = {
.setup = wl12xx_setup,
.identify_chip = wl12xx_identify_chip, .identify_chip = wl12xx_identify_chip,
.identify_fw = wl12xx_identify_fw, .identify_fw = wl12xx_identify_fw,
.boot = wl12xx_boot, .boot = wl12xx_boot,
...@@ -1624,26 +1633,15 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { ...@@ -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 wl12xx_priv *priv = wl->priv;
struct wl1271 *wl; struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data;
struct ieee80211_hw *hw;
struct wl12xx_priv *priv;
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->rtable = wl12xx_rtable;
wl->num_tx_desc = 16; wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
wl->num_rx_desc = 8; 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->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;
...@@ -1695,7 +1693,36 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) ...@@ -1695,7 +1693,36 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
wl1271_error("Invalid tcxo parameter %s", tcxo_param); 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 = { static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
...@@ -1714,17 +1741,7 @@ static struct platform_driver wl12xx_driver = { ...@@ -1714,17 +1741,7 @@ static struct platform_driver wl12xx_driver = {
} }
}; };
static int __init wl12xx_init(void) module_platform_driver(wl12xx_driver);
{
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_param_named(fref, fref_param, charp, 0); module_param_named(fref, fref_param, charp, 0);
MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52"); MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52");
......
...@@ -38,6 +38,13 @@ ...@@ -38,6 +38,13 @@
#define WL128X_SUBTYPE_VER 2 #define WL128X_SUBTYPE_VER 2
#define WL128X_MINOR_VER 115 #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 { struct wl127x_rx_mem_pool_addr {
u32 addr; u32 addr;
u32 addr_extra; u32 addr_extra;
......
...@@ -220,7 +220,7 @@ static ssize_t clear_fw_stats_write(struct file *file, ...@@ -220,7 +220,7 @@ static ssize_t clear_fw_stats_write(struct file *file,
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) if (unlikely(wl->state != WLCORE_STATE_ON))
goto out; goto out;
ret = wl18xx_acx_clear_statistics(wl); ret = wl18xx_acx_clear_statistics(wl);
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
static char *ht_mode_param = NULL; static char *ht_mode_param = NULL;
static char *board_type_param = NULL; static char *board_type_param = NULL;
static bool checksum_param = false; static bool checksum_param = false;
static bool enable_11a_param = true;
static int num_rx_desc_param = -1; static int num_rx_desc_param = -1;
/* phy paramters */ /* phy paramters */
...@@ -415,7 +414,7 @@ static struct wlcore_conf wl18xx_conf = { ...@@ -415,7 +414,7 @@ static struct wlcore_conf wl18xx_conf = {
.snr_threshold = 0, .snr_threshold = 0,
}, },
.ht = { .ht = {
.rx_ba_win_size = 10, .rx_ba_win_size = 32,
.tx_ba_win_size = 64, .tx_ba_win_size = 64,
.inactivity_timeout = 10000, .inactivity_timeout = 10000,
.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
...@@ -505,8 +504,8 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { ...@@ -505,8 +504,8 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
.rdl = 0x01, .rdl = 0x01,
.auto_detect = 0x00, .auto_detect = 0x00,
.dedicated_fem = FEM_NONE, .dedicated_fem = FEM_NONE,
.low_band_component = COMPONENT_2_WAY_SWITCH, .low_band_component = COMPONENT_3_WAY_SWITCH,
.low_band_component_type = 0x06, .low_band_component_type = 0x04,
.high_band_component = COMPONENT_2_WAY_SWITCH, .high_band_component = COMPONENT_2_WAY_SWITCH,
.high_band_component_type = 0x09, .high_band_component_type = 0x09,
.tcxo_ldo_voltage = 0x00, .tcxo_ldo_voltage = 0x00,
...@@ -812,6 +811,13 @@ static int wl18xx_enable_interrupts(struct wl1271 *wl) ...@@ -812,6 +811,13 @@ static int wl18xx_enable_interrupts(struct wl1271 *wl)
ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
WL1271_ACX_INTR_ALL & ~intr_mask); WL1271_ACX_INTR_ALL & ~intr_mask);
if (ret < 0)
goto disable_interrupts;
return ret;
disable_interrupts:
wlcore_disable_interrupts(wl);
out: out:
return ret; return ret;
...@@ -1202,6 +1208,12 @@ static int wl18xx_handle_static_data(struct wl1271 *wl, ...@@ -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 =
(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); wl1271_info("PHY firmware version: %s", static_data_priv->phy_version);
return 0; return 0;
...@@ -1240,13 +1252,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, ...@@ -1240,13 +1252,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
if (!change_spare) if (!change_spare)
return wlcore_set_key(wl, cmd, vif, sta, key_conf); 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); ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -1269,7 +1274,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, ...@@ -1269,7 +1274,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
} }
out: out:
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
return ret; return ret;
} }
...@@ -1292,7 +1296,10 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, ...@@ -1292,7 +1296,10 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
return buf_offset; return buf_offset;
} }
static int wl18xx_setup(struct wl1271 *wl);
static struct wlcore_ops wl18xx_ops = { static struct wlcore_ops wl18xx_ops = {
.setup = wl18xx_setup,
.identify_chip = wl18xx_identify_chip, .identify_chip = wl18xx_identify_chip,
.boot = wl18xx_boot, .boot = wl18xx_boot,
.plt_init = wl18xx_plt_init, .plt_init = wl18xx_plt_init,
...@@ -1373,27 +1380,15 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { ...@@ -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 wl18xx_priv *priv = wl->priv;
struct ieee80211_hw *hw;
struct wl18xx_priv *priv;
int ret; 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->rtable = wl18xx_rtable;
wl->num_tx_desc = 32; wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
wl->num_rx_desc = 32; 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->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;
...@@ -1404,9 +1399,9 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) ...@@ -1404,9 +1399,9 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
if (num_rx_desc_param != -1) if (num_rx_desc_param != -1)
wl->num_rx_desc = num_rx_desc_param; 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) if (ret < 0)
goto out_free; return ret;
/* If the module param is set, update it in conf */ /* If the module param is set, update it in conf */
if (board_type_param) { if (board_type_param) {
...@@ -1423,27 +1418,14 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) ...@@ -1423,27 +1418,14 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
} else { } else {
wl1271_error("invalid board type '%s'", wl1271_error("invalid board type '%s'",
board_type_param); board_type_param);
ret = -EINVAL; return -EINVAL;
goto out_free;
} }
} }
/* HACK! Just for now we hardcode COM8 and HDK to 0x06 */ if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) {
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:
wl1271_error("invalid board type '%d'", wl1271_error("invalid board type '%d'",
priv->conf.phy.board_type); priv->conf.phy.board_type);
ret = -EINVAL; return -EINVAL;
goto out_free;
} }
if (low_band_component_param != -1) if (low_band_component_param != -1)
...@@ -1475,22 +1457,21 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) ...@@ -1475,22 +1457,21 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
priv->conf.ht.mode = HT_MODE_SISO20; priv->conf.ht.mode = HT_MODE_SISO20;
else { else {
wl1271_error("invalid ht_mode '%s'", ht_mode_param); wl1271_error("invalid ht_mode '%s'", ht_mode_param);
ret = -EINVAL; return -EINVAL;
goto out_free;
} }
} }
if (priv->conf.ht.mode == HT_MODE_DEFAULT) { if (priv->conf.ht.mode == HT_MODE_DEFAULT) {
/* /*
* Only support mimo with multiple antennas. Fall back to * Only support mimo with multiple antennas. Fall back to
* siso20. * siso40.
*/ */
if (wl18xx_is_mimo_supported(wl)) if (wl18xx_is_mimo_supported(wl))
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
&wl18xx_mimo_ht_cap_2ghz); &wl18xx_mimo_ht_cap_2ghz);
else else
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
&wl18xx_siso20_ht_cap); &wl18xx_siso40_ht_cap_2ghz);
/* 5Ghz is always wide */ /* 5Ghz is always wide */
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
...@@ -1512,9 +1493,34 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) ...@@ -1512,9 +1493,34 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
wl18xx_ops.init_vif = NULL; 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: out_free:
wlcore_free_hw(wl); wlcore_free_hw(wl);
...@@ -1538,18 +1544,7 @@ static struct platform_driver wl18xx_driver = { ...@@ -1538,18 +1544,7 @@ static struct platform_driver wl18xx_driver = {
} }
}; };
static int __init wl18xx_init(void) module_platform_driver(wl18xx_driver);
{
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_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20"); 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 " ...@@ -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_param_named(checksum, checksum_param, bool, S_IRUSR);
MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)"); 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_param_named(dc2dc, dc2dc_param, int, S_IRUSR);
MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)"); MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)");
......
...@@ -33,6 +33,13 @@ ...@@ -33,6 +33,13 @@
#define WL18XX_CMD_MAX_SIZE 740 #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 { struct wl18xx_priv {
/* buffer for sending commands to FW */ /* buffer for sending commands to FW */
u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; 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, ...@@ -59,6 +59,9 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
u16 status; u16 status;
u16 poll_count = 0; u16 poll_count = 0;
if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING)))
return -EIO;
cmd = buf; cmd = buf;
cmd->id = cpu_to_le16(id); cmd->id = cpu_to_le16(id);
cmd->status = 0; cmd->status = 0;
...@@ -990,7 +993,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, ...@@ -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, ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV,
skb->data, skb->len, skb->data, skb->len,
CMD_TEMPL_KLV_IDX_NULL_DATA, wlvif->sta.klv_template_id,
wlvif->basic_rate); wlvif->basic_rate);
out: out:
...@@ -1785,10 +1788,17 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) ...@@ -1785,10 +1788,17 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
wlvif->bss_type == BSS_TYPE_IBSS))) wlvif->bss_type == BSS_TYPE_IBSS)))
return -EINVAL; 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) if (ret < 0)
goto out; 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); ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
if (ret < 0) if (ret < 0)
goto out_stop; goto out_stop;
...@@ -1797,6 +1807,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) ...@@ -1797,6 +1807,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
out_stop: out_stop:
wl12xx_cmd_role_stop_dev(wl, wlvif); wl12xx_cmd_role_stop_dev(wl, wlvif);
out_disable:
wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
out: out:
return ret; return ret;
} }
...@@ -1824,6 +1836,11 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) ...@@ -1824,6 +1836,11 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
ret = wl12xx_cmd_role_stop_dev(wl, wlvif); ret = wl12xx_cmd_role_stop_dev(wl, wlvif);
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
if (ret < 0)
goto out;
out: out:
return ret; return ret;
} }
...@@ -157,11 +157,6 @@ enum wl1271_commands { ...@@ -157,11 +157,6 @@ enum wl1271_commands {
#define MAX_CMD_PARAMS 572 #define MAX_CMD_PARAMS 572
enum {
CMD_TEMPL_KLV_IDX_NULL_DATA = 0,
CMD_TEMPL_KLV_IDX_MAX = 4
};
enum cmd_templ { enum cmd_templ {
CMD_TEMPL_NULL_DATA = 0, CMD_TEMPL_NULL_DATA = 0,
CMD_TEMPL_BEACON, CMD_TEMPL_BEACON,
......
...@@ -412,8 +412,7 @@ struct conf_rx_settings { ...@@ -412,8 +412,7 @@ struct conf_rx_settings {
#define CONF_TX_RATE_RETRY_LIMIT 10 #define CONF_TX_RATE_RETRY_LIMIT 10
/* basic rates for p2p operations (probe req/resp, etc.) */ /* basic rates for p2p operations (probe req/resp, etc.) */
#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \ #define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS
CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS)
/* /*
* Rates supported for data packets when operating as AP. Note the absence * Rates supported for data packets when operating as AP. Note the absence
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/printk.h> #include <linux/printk.h>
#define DRIVER_NAME "wl12xx" #define DRIVER_NAME "wlcore"
#define DRIVER_PREFIX DRIVER_NAME ": " #define DRIVER_PREFIX DRIVER_NAME ": "
enum { enum {
...@@ -73,11 +73,21 @@ extern u32 wl12xx_debug_level; ...@@ -73,11 +73,21 @@ extern u32 wl12xx_debug_level;
#define wl1271_info(fmt, arg...) \ #define wl1271_info(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##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...) \ #define wl1271_debug(level, fmt, arg...) \
do { \ do { \
if (level & wl12xx_debug_level) \ if (unlikely(level & wl12xx_debug_level)) \
pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ 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) } while (0)
#endif
/* TODO: use pr_debug_hex_dump when it becomes available */ /* TODO: use pr_debug_hex_dump when it becomes available */
#define wl1271_dump(level, prefix, buf, len) \ #define wl1271_dump(level, prefix, buf, len) \
......
...@@ -62,11 +62,14 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) ...@@ -62,11 +62,14 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;
ret = wl1271_ps_elp_wakeup(wl); ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
if (wl->state == WL1271_STATE_ON && !wl->plt && if (!wl->plt &&
time_after(jiffies, wl->stats.fw_stats_update + time_after(jiffies, wl->stats.fw_stats_update +
msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
wl1271_acx_statistics(wl, wl->stats.fw_stats); wl1271_acx_statistics(wl, wl->stats.fw_stats);
...@@ -286,7 +289,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, ...@@ -286,7 +289,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file,
wl->conf.conn.dynamic_ps_timeout = value; wl->conf.conn.dynamic_ps_timeout = value;
if (wl->state == WL1271_STATE_OFF) if (unlikely(wl->state != WLCORE_STATE_ON))
goto out; goto out;
ret = wl1271_ps_elp_wakeup(wl); ret = wl1271_ps_elp_wakeup(wl);
...@@ -353,7 +356,7 @@ static ssize_t forced_ps_write(struct file *file, ...@@ -353,7 +356,7 @@ static ssize_t forced_ps_write(struct file *file,
wl->conf.conn.forced_ps = value; wl->conf.conn.forced_ps = value;
if (wl->state == WL1271_STATE_OFF) if (unlikely(wl->state != WLCORE_STATE_ON))
goto out; goto out;
ret = wl1271_ps_elp_wakeup(wl); ret = wl1271_ps_elp_wakeup(wl);
...@@ -486,6 +489,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, ...@@ -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(platform_quirks);
DRIVER_STATE_PRINT_HEX(chip.id); DRIVER_STATE_PRINT_HEX(chip.id);
DRIVER_STATE_PRINT_STR(chip.fw_ver_str); DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
DRIVER_STATE_PRINT_INT(sched_scanning); DRIVER_STATE_PRINT_INT(sched_scanning);
#undef DRIVER_STATE_PRINT_INT #undef DRIVER_STATE_PRINT_INT
...@@ -999,7 +1003,7 @@ static ssize_t sleep_auth_write(struct file *file, ...@@ -999,7 +1003,7 @@ static ssize_t sleep_auth_write(struct file *file,
wl->conf.conn.sta_sleep_auth = value; 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 */ /* this will show up on "read" in case we are off */
wl->sleep_auth = value; wl->sleep_auth = value;
goto out; goto out;
...@@ -1060,14 +1064,16 @@ static ssize_t dev_mem_read(struct file *file, ...@@ -1060,14 +1064,16 @@ static ssize_t dev_mem_read(struct file *file,
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) { if (unlikely(wl->state == WLCORE_STATE_OFF)) {
ret = -EFAULT; ret = -EFAULT;
goto skip_read; goto skip_read;
} }
ret = wl1271_ps_elp_wakeup(wl); /*
if (ret < 0) * Don't fail if elp_wakeup returns an error, so the device's memory
goto skip_read; * could be read even if the FW crashed
*/
wl1271_ps_elp_wakeup(wl);
/* store current partition and switch partition */ /* store current partition and switch partition */
memcpy(&old_part, &wl->curr_part, sizeof(old_part)); 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, ...@@ -1145,14 +1151,16 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) { if (unlikely(wl->state == WLCORE_STATE_OFF)) {
ret = -EFAULT; ret = -EFAULT;
goto skip_write; goto skip_write;
} }
ret = wl1271_ps_elp_wakeup(wl); /*
if (ret < 0) * Don't fail if elp_wakeup returns an error, so the device's memory
goto skip_write; * could be read even if the FW crashed
*/
wl1271_ps_elp_wakeup(wl);
/* store current partition and switch partition */ /* store current partition and switch partition */
memcpy(&old_part, &wl->curr_part, sizeof(old_part)); memcpy(&old_part, &wl->curr_part, sizeof(old_part));
......
...@@ -141,7 +141,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) ...@@ -141,7 +141,7 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
return ret; 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, ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
CMD_TEMPL_KLV, NULL, CMD_TEMPL_KLV, NULL,
sizeof(struct ieee80211_qos_hdr), sizeof(struct ieee80211_qos_hdr),
...@@ -371,15 +371,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl, ...@@ -371,15 +371,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int ret, i; int ret;
/* 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;
}
/* disable the keep-alive feature */ /* disable the keep-alive feature */
ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); 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, ...@@ -64,7 +64,7 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
return -EIO; return -EIO;
ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); 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); set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
return ret; return ret;
...@@ -80,7 +80,7 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, ...@@ -80,7 +80,7 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
return -EIO; return -EIO;
ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); 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); set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
return ret; return ret;
......
This diff is collapsed.
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define WL1271_WAKEUP_TIMEOUT 500 #define WL1271_WAKEUP_TIMEOUT 500
#define ELP_ENTRY_DELAY 5 #define ELP_ENTRY_DELAY 30
void wl1271_elp_work(struct work_struct *work) void wl1271_elp_work(struct work_struct *work)
{ {
...@@ -44,7 +44,7 @@ void wl1271_elp_work(struct work_struct *work) ...@@ -44,7 +44,7 @@ void wl1271_elp_work(struct work_struct *work)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (unlikely(wl->state == WL1271_STATE_OFF)) if (unlikely(wl->state != WLCORE_STATE_ON))
goto out; goto out;
/* our work might have been already cancelled */ /* our work might have been already cancelled */
...@@ -98,11 +98,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) ...@@ -98,11 +98,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
return; return;
} }
if (wl->conf.conn.forced_ps)
timeout = ELP_ENTRY_DELAY; timeout = ELP_ENTRY_DELAY;
else
timeout = wl->conf.conn.dynamic_ps_timeout;
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
msecs_to_jiffies(timeout)); msecs_to_jiffies(timeout));
} }
......
...@@ -221,7 +221,7 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) ...@@ -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); pkt_len = wlcore_rx_get_buf_size(wl, des);
align_pkt_len = wlcore_rx_get_align_buf_size(wl, align_pkt_len = wlcore_rx_get_align_buf_size(wl,
pkt_len); pkt_len);
if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE) if (buf_size + align_pkt_len > wl->aggr_buf_size)
break; break;
buf_size += align_pkt_len; buf_size += align_pkt_len;
rx_counter++; rx_counter++;
......
...@@ -46,7 +46,7 @@ void wl1271_scan_complete_work(struct work_struct *work) ...@@ -46,7 +46,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) if (unlikely(wl->state != WLCORE_STATE_ON))
goto out; goto out;
if (wl->scan.state == WL1271_SCAN_STATE_IDLE) if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
...@@ -184,11 +184,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, ...@@ -184,11 +184,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
if (passive) if (passive)
scan_options |= WL1271_SCAN_OPT_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; cmd->params.role_id = wlvif->role_id;
else
cmd->params.role_id = wlvif->dev_role_id;
if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL; ret = -EINVAL;
...@@ -593,7 +589,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, ...@@ -593,7 +589,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
goto out; goto out;
} }
cmd->role_id = wlvif->dev_role_id; cmd->role_id = wlvif->role_id;
if (!n_match_ssids) { if (!n_match_ssids) {
/* No filter, with ssids */ /* No filter, with ssids */
type = SCAN_SSID_FILTER_DISABLED; type = SCAN_SSID_FILTER_DISABLED;
...@@ -683,7 +679,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, ...@@ -683,7 +679,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
if (!cfg) if (!cfg)
return -ENOMEM; return -ENOMEM;
cfg->role_id = wlvif->dev_role_id; cfg->role_id = wlvif->role_id;
cfg->rssi_threshold = c->rssi_threshold; cfg->rssi_threshold = c->rssi_threshold;
cfg->snr_threshold = c->snr_threshold; cfg->snr_threshold = c->snr_threshold;
cfg->n_probe_reqs = c->num_probe_reqs; cfg->n_probe_reqs = c->num_probe_reqs;
...@@ -718,7 +714,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, ...@@ -718,7 +714,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
if (!force_passive && cfg->active[0]) { if (!force_passive && cfg->active[0]) {
u8 band = IEEE80211_BAND_2GHZ; u8 band = IEEE80211_BAND_2GHZ;
ret = wl12xx_cmd_build_probe_req(wl, wlvif, 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,
req->ssids[0].ssid_len, req->ssids[0].ssid_len,
ies->ie[band], ies->ie[band],
...@@ -732,7 +728,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, ...@@ -732,7 +728,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
if (!force_passive && cfg->active[1]) { if (!force_passive && cfg->active[1]) {
u8 band = IEEE80211_BAND_5GHZ; u8 band = IEEE80211_BAND_5GHZ;
ret = wl12xx_cmd_build_probe_req(wl, wlvif, 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,
req->ssids[0].ssid_len, req->ssids[0].ssid_len,
ies->ie[band], ies->ie[band],
...@@ -774,7 +770,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) ...@@ -774,7 +770,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if (!start) if (!start)
return -ENOMEM; return -ENOMEM;
start->role_id = wlvif->dev_role_id; start->role_id = wlvif->role_id;
start->tag = WL1271_SCAN_DEFAULT_TAG; start->tag = WL1271_SCAN_DEFAULT_TAG;
ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, 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) ...@@ -810,7 +806,7 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return; return;
} }
stop->role_id = wlvif->dev_role_id; stop->role_id = wlvif->role_id;
stop->tag = WL1271_SCAN_DEFAULT_TAG; stop->tag = WL1271_SCAN_DEFAULT_TAG;
ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop,
......
...@@ -66,7 +66,13 @@ ...@@ -66,7 +66,13 @@
/* HW limitation: maximum possible chunk size is 4095 bytes */ /* HW limitation: maximum possible chunk size is 4095 bytes */
#define WSPI_MAX_CHUNK_SIZE 4092 #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 wl12xx_spi_glue {
struct device *dev; struct device *dev;
...@@ -271,7 +277,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, ...@@ -271,7 +277,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
u32 chunk_len; u32 chunk_len;
int i; int i;
WARN_ON(len > WL1271_AGGR_BUFFER_SIZE); WARN_ON(len > SPI_AGGR_BUFFER_SIZE);
spi_message_init(&m); spi_message_init(&m);
memset(t, 0, sizeof(t)); memset(t, 0, sizeof(t));
......
...@@ -92,7 +92,7 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) ...@@ -92,7 +92,7 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) { if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
...@@ -164,7 +164,7 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) ...@@ -164,7 +164,7 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) { if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
......
...@@ -193,7 +193,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -193,7 +193,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int id, ret = -EBUSY, ac; int id, ret = -EBUSY, ac;
u32 spare_blocks; u32 spare_blocks;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) if (buf_offset + total_len > wl->aggr_buf_size)
return -EAGAIN; return -EAGAIN;
spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem); 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, ...@@ -319,8 +319,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (hlid == wlvif->ap.global_hlid) if (hlid == wlvif->ap.global_hlid)
rate_idx = wlvif->ap.mgmt_rate_idx; rate_idx = wlvif->ap.mgmt_rate_idx;
else if (hlid == wlvif->ap.bcast_hlid || else if (hlid == wlvif->ap.bcast_hlid ||
skb->protocol == cpu_to_be16(ETH_P_PAE)) skb->protocol == cpu_to_be16(ETH_P_PAE) ||
/* send AP bcast and EAPOLs using the min basic rate */ !ieee80211_is_data(frame_control))
/*
* send non-data, bcast and EAPOLs using the
* min basic rate
*/
rate_idx = wlvif->ap.bcast_rate_idx; rate_idx = wlvif->ap.bcast_rate_idx;
else else
rate_idx = wlvif->ap.ucast_rate_idx[ac]; rate_idx = wlvif->ap.ucast_rate_idx[ac];
...@@ -687,7 +691,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl) ...@@ -687,7 +691,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
int bus_ret = 0; int bus_ret = 0;
u8 hlid; u8 hlid;
if (unlikely(wl->state == WL1271_STATE_OFF)) if (unlikely(wl->state != WLCORE_STATE_ON))
return 0; return 0;
while ((skb = wl1271_skb_dequeue(wl, &hlid))) { while ((skb = wl1271_skb_dequeue(wl, &hlid))) {
...@@ -1072,39 +1076,54 @@ void wl12xx_tx_reset(struct wl1271 *wl) ...@@ -1072,39 +1076,54 @@ void wl12xx_tx_reset(struct wl1271 *wl)
/* caller must *NOT* hold wl->mutex */ /* caller must *NOT* hold wl->mutex */
void wl1271_tx_flush(struct wl1271 *wl) void wl1271_tx_flush(struct wl1271 *wl)
{ {
unsigned long timeout; unsigned long timeout, start_time;
int i; 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 */ /* only one flush should be in progress, for consistent queue state */
mutex_lock(&wl->flush_mutex); 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); wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH);
while (!time_after(jiffies, timeout)) { while (!time_after(jiffies, timeout)) {
mutex_lock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "flushing tx buffer: %d %d",
wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
wl->tx_frames_cnt, wl->tx_frames_cnt,
wl1271_tx_total_queue_count(wl)); 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) && if ((wl->tx_frames_cnt == 0) &&
(wl1271_tx_total_queue_count(wl) == 0)) { (wl1271_tx_total_queue_count(wl) == 0)) {
mutex_unlock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "tx flush took %d ms",
goto out; 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 */ /* forcibly flush all Tx buffers on our queues */
mutex_lock(&wl->mutex);
for (i = 0; i < WL12XX_MAX_LINKS; i++) for (i = 0; i < WL12XX_MAX_LINKS; i++)
wl1271_tx_reset_link_queues(wl, i); wl1271_tx_reset_link_queues(wl, i);
mutex_unlock(&wl->mutex);
out: out_wake:
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH);
mutex_unlock(&wl->mutex);
out:
mutex_unlock(&wl->flush_mutex); mutex_unlock(&wl->flush_mutex);
} }
EXPORT_SYMBOL_GPL(wl1271_tx_flush); EXPORT_SYMBOL_GPL(wl1271_tx_flush);
......
...@@ -31,12 +31,19 @@ ...@@ -31,12 +31,19 @@
/* The maximum number of Tx descriptors in all chip families */ /* The maximum number of Tx descriptors in all chip families */
#define WLCORE_MAX_TX_DESCRIPTORS 32 #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 */ /* forward declaration */
struct wl1271_tx_hw_descr; struct wl1271_tx_hw_descr;
enum wl_rx_buf_align; enum wl_rx_buf_align;
struct wl1271_rx_descriptor; struct wl1271_rx_descriptor;
struct wlcore_ops { struct wlcore_ops {
int (*setup)(struct wl1271 *wl);
int (*identify_chip)(struct wl1271 *wl); int (*identify_chip)(struct wl1271 *wl);
int (*identify_fw)(struct wl1271 *wl); int (*identify_fw)(struct wl1271 *wl);
int (*boot)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl);
...@@ -139,10 +146,12 @@ struct wl1271_stats { ...@@ -139,10 +146,12 @@ struct wl1271_stats {
}; };
struct wl1271 { struct wl1271 {
bool initialized;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
bool mac80211_registered; bool mac80211_registered;
struct device *dev; struct device *dev;
struct platform_device *pdev;
void *if_priv; void *if_priv;
...@@ -153,7 +162,7 @@ struct wl1271 { ...@@ -153,7 +162,7 @@ struct wl1271 {
spinlock_t wl_lock; spinlock_t wl_lock;
enum wl1271_state state; enum wlcore_state state;
enum wl12xx_fw_type fw_type; enum wl12xx_fw_type fw_type;
bool plt; bool plt;
enum plt_mode plt_mode; enum plt_mode plt_mode;
...@@ -181,7 +190,7 @@ struct wl1271 { ...@@ -181,7 +190,7 @@ struct wl1271 {
u32 fuse_nic_addr; u32 fuse_nic_addr;
/* we have up to 2 MAC addresses */ /* we have up to 2 MAC addresses */
struct mac_address addresses[2]; struct mac_address addresses[WLCORE_NUM_MAC_ADDRESSES];
int channel; int channel;
u8 system_hlid; u8 system_hlid;
...@@ -190,6 +199,8 @@ struct wl1271 { ...@@ -190,6 +199,8 @@ struct wl1271 {
unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
unsigned long rate_policies_map[ unsigned long rate_policies_map[
BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)];
unsigned long klv_templates_map[
BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)];
struct list_head wlvif_list; struct list_head wlvif_list;
...@@ -237,6 +248,7 @@ struct wl1271 { ...@@ -237,6 +248,7 @@ struct wl1271 {
/* Intermediate buffer, used for packet aggregation */ /* Intermediate buffer, used for packet aggregation */
u8 *aggr_buf; u8 *aggr_buf;
u32 aggr_buf_size;
/* Reusable dummy packet template */ /* Reusable dummy packet template */
struct sk_buff *dummy_packet; struct sk_buff *dummy_packet;
...@@ -393,13 +405,18 @@ struct wl1271 { ...@@ -393,13 +405,18 @@ struct wl1271 {
/* sleep auth value currently configured to FW */ /* sleep auth value currently configured to FW */
int sleep_auth; 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 */ /* the minimum FW version required for the driver to work */
unsigned int min_fw_ver[NUM_FW_VER]; 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 __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
int __devexit wlcore_remove(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_free_hw(struct wl1271 *wl);
int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#define WLCORE_NUM_BANDS 2 #define WLCORE_NUM_BANDS 2
#define WL12XX_MAX_RATE_POLICIES 16 #define WL12XX_MAX_RATE_POLICIES 16
#define WLCORE_MAX_KLV_TEMPLATES 4
/* Defined by FW as 0. Will not be freed or allocated. */ /* Defined by FW as 0. Will not be freed or allocated. */
#define WL12XX_SYSTEM_HLID 0 #define WL12XX_SYSTEM_HLID 0
...@@ -83,11 +84,10 @@ ...@@ -83,11 +84,10 @@
#define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_BSS_INDEX 0
#define WL1271_AP_DEF_BEACON_EXP 20 #define WL1271_AP_DEF_BEACON_EXP 20
#define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE) enum wlcore_state {
WLCORE_STATE_OFF,
enum wl1271_state { WLCORE_STATE_RESTARTING,
WL1271_STATE_OFF, WLCORE_STATE_ON,
WL1271_STATE_ON,
}; };
enum wl12xx_fw_type { enum wl12xx_fw_type {
...@@ -124,6 +124,7 @@ struct wl1271_chip { ...@@ -124,6 +124,7 @@ struct wl1271_chip {
u32 id; u32 id;
char fw_ver_str[ETHTOOL_BUSINFO_LEN]; char fw_ver_str[ETHTOOL_BUSINFO_LEN];
unsigned int fw_ver[NUM_FW_VER]; unsigned int fw_ver[NUM_FW_VER];
char phy_fw_ver_str[ETHTOOL_BUSINFO_LEN];
}; };
#define NUM_TX_QUEUES 4 #define NUM_TX_QUEUES 4
...@@ -337,6 +338,8 @@ struct wl12xx_vif { ...@@ -337,6 +338,8 @@ struct wl12xx_vif {
u8 ap_rate_idx; u8 ap_rate_idx;
u8 p2p_rate_idx; u8 p2p_rate_idx;
u8 klv_template_id;
bool qos; bool qos;
} sta; } sta;
struct { struct {
......
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