Commit f1b98bb3 authored by John W. Linville's avatar John W. Linville
Browse files
parents 97ea6d0f af390f4d
......@@ -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;
hw = wlcore_alloc_hw(sizeof(*priv));
if (IS_ERR(hw)) {
wl1271_error("can't allocate hw");
return PTR_ERR(hw);
}
struct wl12xx_priv *priv = wl->priv;
struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data;
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 0;
}
return wlcore_probe(wl, pdev);
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 */