Commit f2776834 authored by John W. Linville's avatar John W. Linville
parents e9676695 916ef361
......@@ -6669,6 +6669,16 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: sound/soc/codecs/twl4030*
TI WILINK WIRELESS DRIVERS
M: Luciano Coelho <coelho@ti.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/wl12xx
W: http://wireless.kernel.org/en/users/Drivers/wl1251
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
S: Maintained
F: drivers/net/wireless/ti/
F: include/linux/wl12xx.h
TIPC NETWORK LAYER
M: Jon Maloy <jon.maloy@ericsson.com>
M: Allan Stephens <allan.stephens@windriver.com>
......@@ -7425,23 +7435,6 @@ M: Miloslav Trmac <mitr@volny.cz>
S: Maintained
F: drivers/input/misc/wistron_btns.c
WL1251 WIRELESS DRIVER
M: Luciano Coelho <coelho@ti.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/wl1251
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
F: drivers/net/wireless/wl1251/*
WL1271 WIRELESS DRIVER
M: Luciano Coelho <coelho@ti.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/wl12xx
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
S: Maintained
F: drivers/net/wireless/wl12xx/
F: include/linux/wl12xx.h
WL3501 WIRELESS PCMCIA CARD DRIVER
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
L: linux-wireless@vger.kernel.org
......
......@@ -282,8 +282,7 @@ source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/rt2x00/Kconfig"
source "drivers/net/wireless/rtlwifi/Kconfig"
source "drivers/net/wireless/wl1251/Kconfig"
source "drivers/net/wireless/wl12xx/Kconfig"
source "drivers/net/wireless/ti/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
source "drivers/net/wireless/mwifiex/Kconfig"
......
......@@ -51,9 +51,7 @@ obj-$(CONFIG_ATH_COMMON) += ath/
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_WL1251) += wl1251/
obj-$(CONFIG_WL12XX) += wl12xx/
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
obj-$(CONFIG_WL_TI) += ti/
obj-$(CONFIG_IWM) += iwmc3200wifi/
......
menuconfig WL_TI
bool "TI Wireless LAN support"
---help---
This section contains support for all the wireless drivers
for Texas Instruments WLAN chips, such as wl1251 and the wl12xx
family.
if WL_TI
source "drivers/net/wireless/ti/wl1251/Kconfig"
source "drivers/net/wireless/ti/wl12xx/Kconfig"
# keep last for automatic dependencies
source "drivers/net/wireless/ti/wlcore/Kconfig"
endif # WL_TI
obj-$(CONFIG_WLCORE) += wlcore/
obj-$(CONFIG_WL12XX) += wl12xx/
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/
obj-$(CONFIG_WL1251) += wl1251/
config WL12XX
tristate "TI wl12xx support"
select WLCORE
---help---
This module adds support for wireless adapters based on TI wl1271,
wl1273, wl1281 and wl1283 chipsets. This module does *not* include
support for wl1251. For wl1251 support, use the separate homonymous
driver instead.
wl12xx-objs = main.o cmd.o acx.o
obj-$(CONFIG_WL12XX) += wl12xx.o
/*
* This file is part of wl12xx
*
* Copyright (C) 2008-2009 Nokia Corporation
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
#include "../wlcore/acx.h"
#include "acx.h"
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
{
struct wl1271_acx_host_config_bitmap *bitmap_conf;
int ret;
bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
if (!bitmap_conf) {
ret = -ENOMEM;
goto out;
}
bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap);
ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP,
bitmap_conf, sizeof(*bitmap_conf));
if (ret < 0) {
wl1271_warning("wl1271 bitmap config opt failed: %d", ret);
goto out;
}
out:
kfree(bitmap_conf);
return ret;
}
/*
* This file is part of wl12xx
*
* Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved.
* Copyright (C) 2008-2010 Nokia Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_ACX_H__
#define __WL12XX_ACX_H__
#include "../wlcore/wlcore.h"
struct wl1271_acx_host_config_bitmap {
struct acx_header header;
__le32 host_cfg_bitmap;
} __packed;
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
#endif /* __WL12XX_ACX_H__ */
/*
* This file is part of wl12xx
*
* Copyright (C) 2009-2010 Nokia Corporation
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
#include "wl12xx.h"
#include "cmd.h"
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
{
struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
struct wl12xx_priv *priv = wl->priv;
struct wl12xx_conf_rf *rf = &priv->conf.rf;
int ret;
if (!wl->nvs)
return -ENODEV;
ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
if (!ext_radio_parms)
return -ENOMEM;
ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
rf->tx_per_channel_power_compensation_2,
CONF_TX_PWR_COMPENSATION_LEN_2);
memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
rf->tx_per_channel_power_compensation_5,
CONF_TX_PWR_COMPENSATION_LEN_5);
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
ext_radio_parms, sizeof(*ext_radio_parms));
ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
if (ret < 0)
wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
kfree(ext_radio_parms);
return ret;
}
int wl1271_cmd_general_parms(struct wl1271 *wl)
{
struct wl1271_general_parms_cmd *gen_parms;
struct wl1271_ini_general_params *gp =
&((struct wl1271_nvs_file *)wl->nvs)->general_params;
bool answer = false;
int ret;
if (!wl->nvs)
return -ENODEV;
if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
wl1271_warning("FEM index from INI out of bounds");
return -EINVAL;
}
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
memcpy(&gen_parms->general_params, gp, sizeof(*gp));
if (gp->tx_bip_fem_auto_detect)
answer = true;
/* Override the REF CLK from the NVS with the one from platform data */
gen_parms->general_params.ref_clock = wl->ref_clock;
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
if (ret < 0) {
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
goto out;
}
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
wl1271_warning("FEM index from FW out of bounds");
ret = -EINVAL;
goto out;
}
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
out:
kfree(gen_parms);
return ret;
}
int wl128x_cmd_general_parms(struct wl1271 *wl)
{
struct wl128x_general_parms_cmd *gen_parms;
struct wl128x_ini_general_params *gp =
&((struct wl128x_nvs_file *)wl->nvs)->general_params;
bool answer = false;
int ret;
if (!wl->nvs)
return -ENODEV;
if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
wl1271_warning("FEM index from ini out of bounds");
return -EINVAL;
}
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
memcpy(&gen_parms->general_params, gp, sizeof(*gp));
if (gp->tx_bip_fem_auto_detect)
answer = true;
/* Replace REF and TCXO CLKs with the ones from platform data */
gen_parms->general_params.ref_clock = wl->ref_clock;
gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock;
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
if (ret < 0) {
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
goto out;
}
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
wl1271_warning("FEM index from FW out of bounds");
ret = -EINVAL;
goto out;
}
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
out:
kfree(gen_parms);
return ret;
}
int wl1271_cmd_radio_parms(struct wl1271 *wl)
{
struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
struct wl1271_radio_parms_cmd *radio_parms;
struct wl1271_ini_general_params *gp = &nvs->general_params;
int ret;
if (!wl->nvs)
return -ENODEV;
radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
if (!radio_parms)
return -ENOMEM;
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl1271_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
&nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl1271_ini_fem_params_2));
/* 5GHz parameters */
memcpy(&radio_parms->static_params_5,
&nvs->stat_radio_params_5,
sizeof(struct wl1271_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
&nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl1271_ini_fem_params_5));
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
radio_parms, sizeof(*radio_parms));
ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
if (ret < 0)
wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
kfree(radio_parms);
return ret;
}
int wl128x_cmd_radio_parms(struct wl1271 *wl)
{
struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
struct wl128x_radio_parms_cmd *radio_parms;
struct wl128x_ini_general_params *gp = &nvs->general_params;
int ret;
if (!wl->nvs)
return -ENODEV;
radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
if (!radio_parms)
return -ENOMEM;
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl128x_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
&nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl128x_ini_fem_params_2));
/* 5GHz parameters */
memcpy(&radio_parms->static_params_5,
&nvs->stat_radio_params_5,
sizeof(struct wl128x_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
&nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl128x_ini_fem_params_5));
radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options;
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
radio_parms, sizeof(*radio_parms));
ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
if (ret < 0)
wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
kfree(radio_parms);
return ret;
}
/*
* This file is part of wl12xx
*
* Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved.
* Copyright (C) 2009 Nokia Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_CMD_H__
#define __WL12XX_CMD_H__
#include "conf.h"
#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
struct wl1271_general_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
struct wl1271_ini_general_params general_params;
u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 sr_sen_n_p;
u8 sr_sen_n_p_gain;
u8 sr_sen_nrn;
u8 sr_sen_prn;
u8 padding[3];
} __packed;
struct wl128x_general_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
struct wl128x_ini_general_params general_params;
u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 sr_sen_n_p;
u8 sr_sen_n_p_gain;
u8 sr_sen_nrn;
u8 sr_sen_prn;
u8 padding[3];
} __packed;
struct wl1271_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
/* Static radio parameters */
struct wl1271_ini_band_params_2 static_params_2;
struct wl1271_ini_band_params_5 static_params_5;
/* Dynamic radio parameters */
struct wl1271_ini_fem_params_2 dyn_params_2;
u8 padding2;
struct wl1271_ini_fem_params_5 dyn_params_5;
u8 padding3[2];
} __packed;
struct wl128x_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
/* Static radio parameters */
struct wl128x_ini_band_params_2 static_params_2;
struct wl128x_ini_band_params_5 static_params_5;
u8 fem_vendor_and_options;
/* Dynamic radio parameters */
struct wl128x_ini_fem_params_2 dyn_params_2;
u8 padding2;
struct wl128x_ini_fem_params_5 dyn_params_5;
} __packed;
#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
struct wl1271_ext_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
u8 padding[3];
} __packed;
int wl1271_cmd_general_parms(struct wl1271 *wl);
int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
#endif /* __WL12XX_CMD_H__ */
/*
* This file is part of wl12xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_CONF_H__
#define __WL12XX_CONF_H__
/* these are number of channels on the band divided by two, rounded up */
#define CONF_TX_PWR_COMPENSATION_LEN_2 7
#define CONF_TX_PWR_COMPENSATION_LEN_5 18
struct wl12xx_conf_rf {
/*
* Per channel power compensation for 2.4GHz
*
* Range: s8
*/
u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
/*
* Per channel power compensation for 5GHz
*
* Range: s8
*/
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
};
struct wl12xx_priv_conf {
struct wl12xx_conf_rf rf;
struct conf_memory_settings mem_wl127x;
};
#endif /* __WL12XX_CONF_H__ */
This diff is collapsed.
/*
* This file is part of wl12xx
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_PRIV_H__
#define __WL12XX_PRIV_H__
#include "conf.h"
struct wl12xx_priv {
struct wl12xx_priv_conf conf;
};
#endif /* __WL12XX_PRIV_H__ */
config WLCORE
tristate "TI wlcore support"
depends on WL_TI && GENERIC_HARDIRQS
depends on INET
select FW_LOADER
---help---
This module contains the main code for TI WLAN chips. It abstracts
hardware-specific differences among different chipset families.
Each chipset family needs to implement its own lower-level module
that will depend on this module for the common code.
If you choose to build a module, it will be called wlcore. Say N if
unsure.
config WLCORE_SPI
tristate "TI wlcore SPI support"
depends on WLCORE && SPI_MASTER
select CRC7
---help---
This module adds support for the SPI interface of adapters using
TI WLAN chipsets. Select this if your platform is using
the SPI bus.
If you choose to build a module, it'll be called wlcore_spi.
Say N if unsure.
config WLCORE_SDIO
tristate "TI wlcore SDIO support"
depends on WLCORE && MMC
---help---
This module adds support for the SDIO interface of adapters using
TI WLAN chipsets. Select this if your platform is using
the SDIO bus.
If you choose to build a module, it'll be called wlcore_sdio.
Say N if unsure.
config WL12XX_PLATFORM_DATA
bool
depends on WLCORE_SDIO != n || WL1251_SDIO != n
default y
wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
boot.o init.o debugfs.o scan.o
wl12xx_spi-objs = spi.o
wl12xx_sdio-objs = sdio.o
wlcore_spi-objs = spi.o
wlcore_sdio-objs = sdio.o
wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_WL12XX) += wl12xx.o
obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o
obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
wlcore-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_WLCORE) += wlcore.o
obj-$(CONFIG_WLCORE_SPI) += wlcore_spi.o
obj-$(CONFIG_WLCORE_SDIO) += wlcore_sdio.o
# small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
......
......@@ -28,11 +28,11 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include "wl12xx.h"
#include "wlcore.h"
#include "debug.h"
#include "wl12xx_80211.h"
#include "reg.h"
#include "ps.h"
#include "hw_ops.h"
int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 wake_up_event, u8 listen_interval)
......@@ -757,7 +757,10 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
/* configure one AP supported rate class */
acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx);
acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set);
/* the AP policy is HW specific */
acx->rate_policy.enabled_rates =
cpu_to_le32(wlcore_hw_sta_get_ap_rate_mask(wl, wlvif));
acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_policy.long_retry_limit = c->long_retry_limit;
acx->rate_policy.aflags = c->aflags;
......@@ -969,17 +972,14 @@ int wl12xx_acx_mem_cfg(struct wl1271 *wl)
goto out;
}
if (wl->chip.id == CHIP_ID_1283_PG20)
mem = &wl->conf.mem_wl128x;
else
mem = &wl->conf.mem_wl127x;
mem = &wl->conf.mem;
/* memory config */
mem_conf->num_stations = mem->num_stations;
mem_conf->rx_mem_block_num = mem->rx_block_num;
mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
mem_conf->num_ssid_profiles = mem->ssid_profiles;
mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
mem_conf->total_tx_descriptors = cpu_to_le32(wl->num_tx_desc);
mem_conf->dyn_mem_enable = mem->dynamic_memory;
mem_conf->tx_free_req = mem->min_req_tx_blocks;
mem_conf->rx_free_req = mem->min_req_rx_blocks;
......@@ -998,32 +998,6 @@ int wl12xx_acx_mem_cfg(struct wl1271 *wl)
return ret;
}
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
{
struct wl1271_acx_host_config_bitmap *bitmap_conf;
int ret;
bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
if (!bitmap_conf) {
ret = -ENOMEM;
goto out;
}
bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap);
ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP,
bitmap_conf, sizeof(*bitmap_conf));
if (ret < 0) {
wl1271_warning("wl1271 bitmap config opt failed: %d", ret);
goto out;
}
out:
kfree(bitmap_conf);
return ret;
}
int wl1271_acx_init_mem_config(struct wl1271 *wl)
{
int ret;
......
......@@ -25,7 +25,7 @@
#ifndef __ACX_H__
#define __ACX_H__
#include "wl12xx.h"
#include "wlcore.h"
#include "cmd.h"
/*************************************************************************
......@@ -824,16 +824,11 @@ struct wl1271_acx_keep_alive_config {
__le32 period;
} __packed;
/* TODO: maybe this needs to be moved somewhere else? */
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
struct wl1271_acx_host_config_bitmap {
struct acx_header header;
__le32 host_cfg_bitmap;
} __packed;
enum {
WL1271_ACX_TRIG_TYPE_LEVEL = 0,
WL1271_ACX_TRIG_TYPE_EDGE,
......@@ -1274,7 +1269,6 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
int wl1271_acx_tx_config_options(struct wl1271 *wl);
int wl12xx_acx_mem_cfg(struct wl1271 *wl);
int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif,
......
/*
* This file is part of wl1271
*
* Copyright (C) 2008-2009 Nokia Corporation
*
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __BOOT_H__
#define __BOOT_H__
#include "wlcore.h"
int wlcore_boot_upload_firmware(struct wl1271 *wl);
int wlcore_boot_upload_nvs(struct wl1271 *wl);
int wlcore_boot_run_firmware(struct wl1271 *wl);
#define WL1271_NO_SUBBANDS 8
#define WL1271_NO_POWER_LEVELS 4
#define WL1271_FW_VERSION_MAX_LEN 20
struct wl1271_static_data {
u8 mac_address[ETH_ALEN];
u8 padding[2];
u8 fw_version[WL1271_FW_VERSION_MAX_LEN];
u32 hw_version;
u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS];
};
/* number of times we try to read the INIT interrupt */
#define INIT_LOOP 20000
/* delay between retries */
#define INIT_LOOP_DELAY 50
#define WU_COUNTER_PAUSE_VAL 0x3FF
#define WELP_ARM_COMMAND_VAL 0x4
#endif
......@@ -25,17 +25,12 @@
#ifndef __CMD_H__
#define __CMD_H__
#include "wl12xx.h"
#include "wlcore.h"
struct acx_header;
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t res_len);
int wl1271_cmd_general_parms(struct wl1271 *wl);
int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
u8 *role_id);
int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
......@@ -262,13 +257,13 @@ struct wl12xx_cmd_role_disable {
u8 padding[3];
} __packed;
enum wl12xx_band {
WL12XX_BAND_2_4GHZ = 0,
WL12XX_BAND_5GHZ = 1,
WL12XX_BAND_JAPAN_4_9_GHZ = 2,
WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ,
WL12XX_BAND_INVALID = 0x7E,
WL12XX_BAND_MAX_RADIO = 0x7F,
enum wlcore_band {
WLCORE_BAND_2_4GHZ = 0,
WLCORE_BAND_5GHZ = 1,
WLCORE_BAND_JAPAN_4_9_GHZ = 2,
WLCORE_BAND_DEFAULT = WLCORE_BAND_2_4GHZ,
WLCORE_BAND_INVALID = 0x7E,
WLCORE_BAND_MAX_RADIO = 0x7F,
};
struct wl12xx_cmd_role_start {
......@@ -494,83 +489,6 @@ enum wl1271_channel_tune_bands {
#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
struct wl1271_general_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
struct wl1271_ini_general_params general_params;
u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 sr_sen_n_p;
u8 sr_sen_n_p_gain;
u8 sr_sen_nrn;
u8 sr_sen_prn;
u8 padding[3];
} __packed;
struct wl128x_general_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
struct wl128x_ini_general_params general_params;
u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 sr_sen_n_p;
u8 sr_sen_n_p_gain;
u8 sr_sen_nrn;
u8 sr_sen_prn;
u8 padding[3];
} __packed;
struct wl1271_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
/* Static radio parameters */
struct wl1271_ini_band_params_2 static_params_2;
struct wl1271_ini_band_params_5 static_params_5;
/* Dynamic radio parameters */
struct wl1271_ini_fem_params_2 dyn_params_2;
u8 padding2;
struct wl1271_ini_fem_params_5 dyn_params_5;
u8 padding3[2];
} __packed;
struct wl128x_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
/* Static radio parameters */
struct wl128x_ini_band_params_2 static_params_2;
struct wl128x_ini_band_params_5 static_params_5;
u8 fem_vendor_and_options;
/* Dynamic radio parameters */
struct wl128x_ini_fem_params_2 dyn_params_2;
u8 padding2;
struct wl128x_ini_fem_params_5 dyn_params_5;
} __packed;
struct wl1271_ext_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
u8 padding[3];
} __packed;
/*
* There are three types of disconnections:
*
......
......@@ -65,36 +65,7 @@ enum {
CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS,
};
enum {
CONF_HW_RXTX_RATE_MCS7_SGI = 0,
CONF_HW_RXTX_RATE_MCS7,
CONF_HW_RXTX_RATE_MCS6,
CONF_HW_RXTX_RATE_MCS5,
CONF_HW_RXTX_RATE_MCS4,
CONF_HW_RXTX_RATE_MCS3,
CONF_HW_RXTX_RATE_MCS2,
CONF_HW_RXTX_RATE_MCS1,
CONF_HW_RXTX_RATE_MCS0,
CONF_HW_RXTX_RATE_54,
CONF_HW_RXTX_RATE_48,
CONF_HW_RXTX_RATE_36,
CONF_HW_RXTX_RATE_24,
CONF_HW_RXTX_RATE_22,
CONF_HW_RXTX_RATE_18,
CONF_HW_RXTX_RATE_12,
CONF_HW_RXTX_RATE_11,
CONF_HW_RXTX_RATE_9,
CONF_HW_RXTX_RATE_6,
CONF_HW_RXTX_RATE_5_5,
CONF_HW_RXTX_RATE_2,
CONF_HW_RXTX_RATE_1,
CONF_HW_RXTX_RATE_MAX,
CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff
};
/* Rates between and including these are MCS rates */
#define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI
#define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0
#define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff
enum {
CONF_SG_DISABLE = 0,
......@@ -1096,16 +1067,31 @@ struct conf_scan_settings {
};
struct conf_sched_scan_settings {
/* minimum time to wait on the channel for active scans (in TUs) */
u16 min_dwell_time_active;
/*
* The base time to wait on the channel for active scans (in TU/1000).
* The minimum dwell time is calculated according to this:
* min_dwell_time = base + num_of_probes_to_be_sent * delta_per_probe
* The maximum dwell time is calculated according to this:
* max_dwell_time = min_dwell_time + max_dwell_time_delta
*/
u32 base_dwell_time;
/* maximum time to wait on the channel for active scans (in TUs) */
u16 max_dwell_time_active;
/* The delta between the min dwell time and max dwell time for
* active scans (in TU/1000s). The max dwell time is used by the FW once
* traffic is detected on the channel.
*/
u32 max_dwell_time_delta;
/* Delta added to min dwell time per each probe in 2.4 GHz (TU/1000) */
u32 dwell_time_delta_per_probe;
/* time to wait on the channel for passive scans (in TUs) */
/* Delta added to min dwell time per each probe in 5 GHz (TU/1000) */
u32 dwell_time_delta_per_probe_5;
/* time to wait on the channel for passive scans (in TU/1000) */
u32 dwell_time_passive;
/* time to wait on the channel for DFS scans (in TUs) */
/* time to wait on the channel for DFS scans (in TU/1000) */
u32 dwell_time_dfs;
/* number of probe requests to send on each channel in active scans */
......@@ -1118,26 +1104,6 @@ struct conf_sched_scan_settings {
s8 snr_threshold;
};
/* these are number of channels on the band divided by two, rounded up */
#define CONF_TX_PWR_COMPENSATION_LEN_2 7
#define CONF_TX_PWR_COMPENSATION_LEN_5 18
struct conf_rf_settings {
/*
* Per channel power compensation for 2.4GHz
*
* Range: s8
*/
u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
/*
* Per channel power compensation for 5GHz
*
* Range: s8
*/
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
};
struct conf_ht_setting {
u8 rx_ba_win_size;
u8 tx_ba_win_size;
......@@ -1286,7 +1252,7 @@ struct conf_hangover_settings {
u8 window_size;
};
struct conf_drv_settings {
struct wlcore_conf {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
struct conf_tx_settings tx;
......@@ -1296,16 +1262,13 @@ struct conf_drv_settings {
struct conf_roam_trigger_settings roam_trigger;
struct conf_scan_settings scan;
struct conf_sched_scan_settings sched_scan;
struct conf_rf_settings rf;
struct conf_ht_setting ht;
struct conf_memory_settings mem_wl127x;
struct conf_memory_settings mem_wl128x;
struct conf_memory_settings mem;
struct conf_fm_coex fm_coex;
struct conf_rx_streaming_settings rx_streaming;
struct conf_fwlog fwlog;
struct conf_rate_policy_settings rate;
struct conf_hangover_settings hangover;
u8 hci_io_ds;
};
#endif
......@@ -52,6 +52,7 @@ enum {
DEBUG_ADHOC = BIT(16),
DEBUG_AP = BIT(17),
DEBUG_PROBE = BIT(18),
DEBUG_IO = BIT(19),
DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP),
DEBUG_ALL = ~0,
};
......
......@@ -26,7 +26,7 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
#include "wl12xx.h"
#include "wlcore.h"
#include "debug.h"
#include "acx.h"
#include "ps.h"
......@@ -647,6 +647,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
VIF_STATE_PRINT_INT(last_rssi_event);
VIF_STATE_PRINT_INT(ba_support);
VIF_STATE_PRINT_INT(ba_allowed);
VIF_STATE_PRINT_INT(is_gem);
VIF_STATE_PRINT_LLHEX(tx_security_seq);
VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
}
......
......@@ -24,7 +24,7 @@
#ifndef __DEBUGFS_H__
#define __DEBUGFS_H__
#include "wl12xx.h"
#include "wlcore.h"
int wl1271_debugfs_init(struct wl1271 *wl);
void wl1271_debugfs_exit(struct wl1271 *wl);
......
......@@ -21,9 +21,8 @@
*
*/
#include "wl12xx.h"
#include "wlcore.h"
#include "debug.h"
#include "reg.h"
#include "io.h"
#include "event.h"
#include "ps.h"
......@@ -98,8 +97,9 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
}
static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
static int wl1271_event_process(struct wl1271 *wl)
{
struct event_mailbox *mbox = wl->mbox;
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
u32 vector;
......@@ -196,7 +196,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
bool success;
if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
&wl->flags))
&wlvif->flags))
continue;
success = mbox->channel_switch_status ? false : true;
......@@ -278,18 +278,8 @@ int wl1271_event_unmask(struct wl1271 *wl)
return 0;
}
void wl1271_event_mbox_config(struct wl1271 *wl)
{
wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
wl->mbox_ptr[0], wl->mbox_ptr[1]);
}
int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
{
struct event_mailbox mbox;
int ret;
wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
......@@ -298,16 +288,19 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return -EINVAL;
/* first we read the mbox descriptor */
wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
sizeof(struct event_mailbox), false);
wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
sizeof(*wl->mbox), false);
/* process the descriptor */
ret = wl1271_event_process(wl, &mbox);
ret = wl1271_event_process(wl);
if (ret < 0)
return ret;
/* then we let the firmware know it can go on...*/
wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
/*
* TODO: we just need this because one bit is in a different
* place. Is there any better way?
*/
wl->ops->ack_event(wl);
return 0;
}
......@@ -132,8 +132,9 @@ struct event_mailbox {
u8 reserved_8[9];
} __packed;
struct wl1271;
int wl1271_event_unmask(struct wl1271 *wl);
void wl1271_event_mbox_config(struct wl1271 *wl);
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
#endif
/*
* This file is part of wlcore
*
* Copyright (C) 2011 Texas Instruments Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WLCORE_HW_OPS_H__
#define __WLCORE_HW_OPS_H__
#include "wlcore.h"
#include "rx.h"
static inline u32
wlcore_hw_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
{
if (!wl->ops->calc_tx_blocks)
BUG_ON(1);
return wl->ops->calc_tx_blocks(wl, len, spare_blks);
}
static inline void
wlcore_hw_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
u32 blks, u32 spare_blks)
{
if (!wl->ops->set_tx_desc_blocks)
BUG_ON(1);
return wl->ops->set_tx_desc_blocks(wl, desc, blks, spare_blks);
}
static inline void
wlcore_hw_set_tx_desc_data_len(struct wl1271 *wl,
struct wl1271_tx_hw_descr *desc,
struct sk_buff *skb)
{
if (!wl->ops->set_tx_desc_data_len)
BUG_ON(1);
wl->ops->set_tx_desc_data_len(wl, desc, skb);
}
static inline enum wl_rx_buf_align
wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
{
if (!wl->ops->get_rx_buf_align)
BUG_ON(1);
return wl->ops->get_rx_buf_align(wl, rx_desc);
}
static inline void
wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
if (wl->ops->prepare_read)
wl->ops->prepare_read(wl, rx_desc, len);
}
static inline u32
wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len)
{
if (!wl->ops->get_rx_packet_len)
BUG_ON(1);
return wl->ops->get_rx_packet_len(wl, rx_data, data_len);
}
static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl)
{
if (wl->ops->tx_delayed_compl)
wl->ops->tx_delayed_compl(wl);
}
static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl)
{
if (wl->ops->tx_immediate_compl)
wl->ops->tx_immediate_compl(wl);
}
static inline int
wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
if (wl->ops->init_vif)
return wl->ops->init_vif(wl, wlvif);
return 0;
}
static inline u32
wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
if (!wl->ops->sta_get_ap_rate_mask)
BUG_ON(1);
return wl->ops->sta_get_ap_rate_mask(wl, wlvif);
}
static inline int wlcore_identify_fw(struct wl1271 *wl)
{
if (wl->ops->identify_fw)
return wl->ops->identify_fw(wl);
return 0;
}
#endif
......@@ -30,9 +30,9 @@
#include "wl12xx_80211.h"
#include "acx.h"
#include "cmd.h"
#include "reg.h"
#include "tx.h"
#include "io.h"
#include "hw_ops.h"
int wl1271_init_templates_config(struct wl1271 *wl)
{
......@@ -319,7 +319,7 @@ static int wl12xx_init_fwlog(struct wl1271 *wl)
{
int ret;
if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
if (wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED)
return 0;
ret = wl12xx_cmd_config_fwlog(wl);
......@@ -494,26 +494,6 @@ static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return wl12xx_acx_set_ba_initiator_policy(wl, wlvif);
}
int wl1271_chip_specific_init(struct wl1271 *wl)
{
int ret = 0;
if (wl->chip.id == CHIP_ID_1283_PG20) {
u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
if (!(wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT))
/* Enable SDIO padding */
host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
/* Must be before wl1271_acx_init_mem_config() */
ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
if (ret < 0)
goto out;
}
out:
return ret;
}
/* vif-specifc initialization */
static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
......@@ -582,12 +562,19 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
if (ret < 0)
return ret;
} else if (!wl->sta_count) {
if (wl->quirks & WLCORE_QUIRK_NO_ELP) {
/* Configure for power always on */
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
if (ret < 0)
return ret;
} else {
/* Configure for ELP power saving */
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
if (ret < 0)
return ret;
}
}
}
/* Mode specific init */
if (is_ap) {
......@@ -652,6 +639,10 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
if (ret < 0)
return ret;
ret = wlcore_hw_init_vif(wl, wlvif);
if (ret < 0)
return ret;
return 0;
}
......@@ -659,27 +650,8 @@ int wl1271_hw_init(struct wl1271 *wl)
{
int ret;
if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl128x_cmd_general_parms(wl);
if (ret < 0)
return ret;
ret = wl128x_cmd_radio_parms(wl);
if (ret < 0)
return ret;
} else {
ret = wl1271_cmd_general_parms(wl);
if (ret < 0)
return ret;
ret = wl1271_cmd_radio_parms(wl);
if (ret < 0)
return ret;
ret = wl1271_cmd_ext_radio_parms(wl);
if (ret < 0)
return ret;
}
/* Chip-specific init */
ret = wl1271_chip_specific_init(wl);
/* Chip-specific hw init */
ret = wl->ops->hw_init(wl);
if (ret < 0)
return ret;
......
......@@ -24,7 +24,7 @@
#ifndef __INIT_H__
#define __INIT_H__
#include "wl12xx.h"
#include "wlcore.h"
int wl1271_hw_init_power_auth(struct wl1271 *wl);
int wl1271_init_templates_config(struct wl1271 *wl);
......
......@@ -26,84 +26,12 @@
#include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include "wl12xx.h"
#include "wlcore.h"
#include "debug.h"
#include "wl12xx_80211.h"
#include "io.h"
#include "tx.h"
#define OCP_CMD_LOOP 32
#define OCP_CMD_WRITE 0x1
#define OCP_CMD_READ 0x2
#define OCP_READY_MASK BIT(18)
#define OCP_STATUS_MASK (BIT(16) | BIT(17))
#define OCP_STATUS_NO_RESP 0x00000
#define OCP_STATUS_OK 0x10000
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000
struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = {
[PART_DOWN] = {
.mem = {
.start = 0x00000000,
.size = 0x000177c0
},
.reg = {
.start = REGISTERS_BASE,
.size = 0x00008800
},
.mem2 = {
.start = 0x00000000,
.size = 0x00000000
},
.mem3 = {
.start = 0x00000000,
.size = 0x00000000
},
},
[PART_WORK] = {
.mem = {
.start = 0x00040000,
.size = 0x00014fc0
},
.reg = {
.start = REGISTERS_BASE,
.size = 0x0000a000
},
.mem2 = {
.start = 0x003004f8,
.size = 0x00000004
},
.mem3 = {
.start = 0x00040404,
.size = 0x00000000
},
},
[PART_DRPW] = {
.mem = {
.start = 0x00040000,
.size = 0x00014fc0
},
.reg = {
.start = DRPW_BASE,
.size = 0x00006000
},
.mem2 = {
.start = 0x00000000,
.size = 0x00000000
},
.mem3 = {
.start = 0x00000000,
.size = 0x00000000
}
}
};
bool wl1271_set_block_size(struct wl1271 *wl)
{
if (wl->if_ops->set_block_size) {
......@@ -114,17 +42,53 @@ bool wl1271_set_block_size(struct wl1271 *wl)
return false;
}
void wl1271_disable_interrupts(struct wl1271 *wl)
void wlcore_disable_interrupts(struct wl1271 *wl)
{
disable_irq(wl->irq);
}
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts);
void wl1271_enable_interrupts(struct wl1271 *wl)
void wlcore_enable_interrupts(struct wl1271 *wl)
{
enable_irq(wl->irq);
}
EXPORT_SYMBOL_GPL(wlcore_enable_interrupts);
int wlcore_translate_addr(struct wl1271 *wl, int addr)
{
struct wlcore_partition_set *part = &wl->curr_part;
/*
* To translate, first check to which window of addresses the
* particular address belongs. Then subtract the starting address
* of that window from the address. Then, add offset of the
* translated region.
*
* The translated regions occur next to each other in physical device
* memory, so just add the sizes of the preceding address regions to
* get the offset to the new region.
*/
if ((addr >= part->mem.start) &&
(addr < part->mem.start + part->mem.size))
return addr - part->mem.start;
else if ((addr >= part->reg.start) &&
(addr < part->reg.start + part->reg.size))
return addr - part->reg.start + part->mem.size;
else if ((addr >= part->mem2.start) &&
(addr < part->mem2.start + part->mem2.size))
return addr - part->mem2.start + part->mem.size +
part->reg.size;
else if ((addr >= part->mem3.start) &&
(addr < part->mem3.start + part->mem3.size))
return addr - part->mem3.start + part->mem.size +
part->reg.size + part->mem2.size;
WARN(1, "HW address 0x%x out of range", addr);
return 0;
}
EXPORT_SYMBOL_GPL(wlcore_translate_addr);
/* Set the SPI partitions to access the chip addresses
/* Set the partitions to access the chip addresses
*
* To simplify driver code, a fixed (virtual) memory map is defined for
* register and memory addresses. Because in the chipset, in different stages
......@@ -158,33 +122,43 @@ void wl1271_enable_interrupts(struct wl1271 *wl)
* | |
*
*/
int wl1271_set_partition(struct wl1271 *wl,
struct wl1271_partition_set *p)
void wlcore_set_partition(struct wl1271 *wl,
const struct wlcore_partition_set *p)
{
/* copy partition info */
memcpy(&wl->part, p, sizeof(*p));
memcpy(&wl->curr_part, p, sizeof(*p));
wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
wl1271_debug(DEBUG_IO, "mem_start %08X mem_size %08X",
p->mem.start, p->mem.size);
wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
wl1271_debug(DEBUG_IO, "reg_start %08X reg_size %08X",
p->reg.start, p->reg.size);
wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
wl1271_debug(DEBUG_IO, "mem2_start %08X mem2_size %08X",
p->mem2.start, p->mem2.size);
wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X",
p->mem3.start, p->mem3.size);
/* write partition info to the chipset */
wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
/*
* We don't need the size of the last partition, as it is
* automatically calculated based on the total memory size and
* the sizes of the previous partitions.
*/
wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
}
EXPORT_SYMBOL_GPL(wlcore_set_partition);
return 0;
void wlcore_select_partition(struct wl1271 *wl, u8 part)
{
wl1271_debug(DEBUG_IO, "setting partition %d", part);
wlcore_set_partition(wl, &wl->ptable[part]);
}
EXPORT_SYMBOL_GPL(wl1271_set_partition);
EXPORT_SYMBOL_GPL(wlcore_select_partition);
void wl1271_io_reset(struct wl1271 *wl)
{
......@@ -197,48 +171,3 @@ void wl1271_io_init(struct wl1271 *wl)
if (wl->if_ops->init)
wl->if_ops->init(wl->dev);
}
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
{
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
wl1271_write32(wl, OCP_POR_CTR, addr);
/* write value to OCP_POR_WDATA */
wl1271_write32(wl, OCP_DATA_WRITE, val);
/* write 1 to OCP_CMD */
wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE);
}
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
{
u32 val;
int timeout = OCP_CMD_LOOP;
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
wl1271_write32(wl, OCP_POR_CTR, addr);
/* write 2 to OCP_CMD */
wl1271_write32(wl, OCP_CMD, OCP_CMD_READ);
/* poll for data ready */
do {
val = wl1271_read32(wl, OCP_DATA_READ);
} while (!(val & OCP_READY_MASK) && --timeout);
if (!timeout) {
wl1271_warning("Top register access timed out.");
return 0xffff;
}
/* check data status and return if OK */
if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
return val & 0xffff;
else {
wl1271_warning("Top register access returned error.");
return 0xffff;
}
}
......@@ -26,7 +26,6 @@
#define __IO_H__
#include <linux/irqreturn.h>
#include "reg.h"
#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
......@@ -43,15 +42,14 @@
#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN];
struct wl1271;
void wl1271_disable_interrupts(struct wl1271 *wl);
void wl1271_enable_interrupts(struct wl1271 *wl);
void wlcore_disable_interrupts(struct wl1271 *wl);
void wlcore_enable_interrupts(struct wl1271 *wl);
void wl1271_io_reset(struct wl1271 *wl);
void wl1271_io_init(struct wl1271 *wl);
int wlcore_translate_addr(struct wl1271 *wl, int addr);
/* Raw target IO, address is not translated */
static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
......@@ -66,6 +64,18 @@ static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
wl->if_ops->read(wl->dev, addr, buf, len, fixed);
}
static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
{
wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed);
}
static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
{
wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed);
}
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
{
wl1271_raw_read(wl, addr, &wl->buffer_32,
......@@ -81,36 +91,12 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
sizeof(wl->buffer_32), false);
}
/* Translated target IO */
static inline int wl1271_translate_addr(struct wl1271 *wl, int addr)
{
/*
* To translate, first check to which window of addresses the
* particular address belongs. Then subtract the starting address
* of that window from the address. Then, add offset of the
* translated region.
*
* The translated regions occur next to each other in physical device
* memory, so just add the sizes of the preceding address regions to
* get the offset to the new region.
*
* Currently, only the two first regions are addressed, and the
* assumption is that all addresses will fall into either of those
* two.
*/
if ((addr >= wl->part.reg.start) &&
(addr < wl->part.reg.start + wl->part.reg.size))
return addr - wl->part.reg.start + wl->part.mem.size;
else
return addr - wl->part.mem.start;
}
static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
int physical;
physical = wl1271_translate_addr(wl, addr);
physical = wlcore_translate_addr(wl, addr);
wl1271_raw_read(wl, physical, buf, len, fixed);
}
......@@ -120,11 +106,23 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
{
int physical;
physical = wl1271_translate_addr(wl, addr);
physical = wlcore_translate_addr(wl, addr);
wl1271_raw_write(wl, physical, buf, len, fixed);
}
static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
{
wl1271_write(wl, wl->rtable[reg], buf, len, fixed);
}
static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
{
wl1271_read(wl, wl->rtable[reg], buf, len, fixed);
}
static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
void *buf, size_t len, bool fixed)
{
......@@ -134,19 +132,30 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
/* Addresses are stored internally as addresses to 32 bytes blocks */
addr = hwaddr << 5;
physical = wl1271_translate_addr(wl, addr);
physical = wlcore_translate_addr(wl, addr);
wl1271_raw_read(wl, physical, buf, len, fixed);
}
static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
{
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr));
}
static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
{
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
}
static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg)
{
return wl1271_raw_read32(wl,
wlcore_translate_addr(wl, wl->rtable[reg]));
}
static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val)
{
wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val);
}
static inline void wl1271_power_off(struct wl1271 *wl)
......@@ -164,13 +173,8 @@ static inline int wl1271_power_on(struct wl1271 *wl)
return ret;
}
/* Top Register IO */
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
int wl1271_set_partition(struct wl1271 *wl,
struct wl1271_partition_set *p);
void wlcore_set_partition(struct wl1271 *wl,
const struct wlcore_partition_set *p);
bool wl1271_set_block_size(struct wl1271 *wl);
......@@ -178,4 +182,6 @@ bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);
void wlcore_select_partition(struct wl1271 *wl, u8 part);
#endif
......@@ -21,7 +21,6 @@
*
*/
#include "reg.h"
#include "ps.h"
#include "io.h"
#include "tx.h"
......@@ -62,7 +61,7 @@ void wl1271_elp_work(struct work_struct *work)
}
wl1271_debug(DEBUG_PSM, "chip to elp");
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
out:
......@@ -74,6 +73,9 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif;
if (wl->quirks & WLCORE_QUIRK_NO_ELP)
return;
/* we shouldn't get consecutive sleep requests */
if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
return;
......@@ -125,7 +127,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl->elp_compl = &compl;
spin_unlock_irqrestore(&wl->wl_lock, flags);
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
if (!pending) {
ret = wait_for_completion_timeout(
......
......@@ -24,7 +24,7 @@
#ifndef __PS_H__
#define __PS_H__
#include "wl12xx.h"
#include "wlcore.h"
#include "acx.h"
int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
......
......@@ -24,34 +24,36 @@
#include <linux/gfp.h>
#include <linux/sched.h>
#include "wl12xx.h"
#include "wlcore.h"
#include "debug.h"
#include "acx.h"
#include "reg.h"
#include "rx.h"
#include "tx.h"
#include "io.h"
#include "hw_ops.h"
static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
{
return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_MEM_BLOCK_MASK;
}
/*
* TODO: this is here just for now, it must be removed when the data
* operations are in place.
*/
#include "../wl12xx/reg.h"
static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
static u32 wlcore_rx_get_buf_size(struct wl1271 *wl,
u32 rx_pkt_desc)
{
return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN)
return (rx_pkt_desc & ALIGNED_RX_BUF_SIZE_MASK) >>
ALIGNED_RX_BUF_SIZE_SHIFT;
return (rx_pkt_desc & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
}
static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, u32 pkt_len)
{
/* Convert the value to bool */
return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_BUF_UNALIGNED_PAYLOAD);
if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN)
return ALIGN(pkt_len, WL12XX_BUS_BLOCK_SIZE);
return pkt_len;
}
static void wl1271_rx_status(struct wl1271 *wl,
......@@ -66,10 +68,10 @@ static void wl1271_rx_status(struct wl1271 *wl,
else
status->band = IEEE80211_BAND_5GHZ;
status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
status->rate_idx = wlcore_rate_to_idx(wl, desc->rate, status->band);
/* 11n support */
if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
if (desc->rate <= wl->hw_min_ht_rate)
status->flag |= RX_FLAG_HT;
status->signal = desc->rssi;
......@@ -98,7 +100,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
bool unaligned, u8 *hlid)
enum wl_rx_buf_align rx_align, u8 *hlid)
{
struct wl1271_rx_descriptor *desc;
struct sk_buff *skb;
......@@ -106,8 +108,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
u8 *buf;
u8 beacon = 0;
u8 is_data = 0;
u8 reserved = unaligned ? NET_IP_ALIGN : 0;
u8 reserved = 0;
u16 seq_num;
u32 pkt_data_len;
/*
* In PLT mode we seem to get frames and mac80211 warns about them,
......@@ -116,6 +119,16 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
if (unlikely(wl->plt))
return -EINVAL;
pkt_data_len = wlcore_hw_get_rx_packet_len(wl, data, length);
if (!pkt_data_len) {
wl1271_error("Invalid packet arrived from HW. length %d",
length);
return -EINVAL;
}
if (rx_align == WLCORE_RX_BUF_UNALIGNED)
reserved = NET_IP_ALIGN;
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) data;
......@@ -142,8 +155,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return -EINVAL;
}
/* skb length not included rx descriptor */
skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL);
/* skb length not including rx descriptor */
skb = __dev_alloc_skb(pkt_data_len + reserved, GFP_KERNEL);
if (!skb) {
wl1271_error("Couldn't allocate RX frame");
return -ENOMEM;
......@@ -152,7 +165,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
/* reserve the unaligned payload(if any) */
skb_reserve(skb, reserved);
buf = skb_put(skb, length - sizeof(*desc));
buf = skb_put(skb, pkt_data_len);
/*
* Copy packets from aggregation buffer to the skbs without rx
......@@ -160,7 +173,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
* packets copy the packets in offset of 2 bytes guarantee IP header
* payload aligned to 4 bytes.
*/
memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
memcpy(buf, data + sizeof(*desc), pkt_data_len);
if (rx_align == WLCORE_RX_BUF_PADDED)
skb_pull(skb, NET_IP_ALIGN);
*hlid = desc->hlid;
hdr = (struct ieee80211_hdr *)skb->data;
......@@ -177,36 +193,35 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
beacon ? "beacon" : "",
seq_num, *hlid);
skb_trim(skb, skb->len - desc->pad_len);
skb_queue_tail(&wl->deferred_rx_queue, skb);
queue_work(wl->freezable_wq, &wl->netstack_work);
return is_data;
}
void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)
{
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
u32 buf_size;
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
u32 rx_counter;
u32 mem_block;
u32 pkt_length;
u32 pkt_offset;
u32 pkt_len, align_pkt_len;
u32 pkt_offset, des;
u8 hlid;
bool unaligned = false;
enum wl_rx_buf_align rx_align;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
rx_counter = drv_rx_counter;
while (rx_counter != fw_rx_counter) {
pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
des = le32_to_cpu(status->rx_pkt_descs[rx_counter]);
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)
break;
buf_size += pkt_length;
buf_size += align_pkt_len;
rx_counter++;
rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
}
......@@ -216,38 +231,18 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
break;
}
if (wl->chip.id != CHIP_ID_1283_PG20) {
/*
* Choose the block we want to read
* For aggregated packets, only the first memory block
* should be retrieved. The FW takes care of the rest.
*/
mem_block = wl12xx_rx_get_mem_block(status,
drv_rx_counter);
wl->rx_mem_pool_addr.addr = (mem_block << 8) +
le32_to_cpu(wl_mem_map->packet_memory_pool_start);
wl->rx_mem_pool_addr.addr_extra =
wl->rx_mem_pool_addr.addr + 4;
wl1271_write(wl, WL1271_SLV_REG_DATA,
&wl->rx_mem_pool_addr,
sizeof(wl->rx_mem_pool_addr), false);
}
/* Read all available packets at once */
wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
wlcore_hw_prepare_read(wl, des, buf_size);
wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
buf_size, true);
/* Split data into separate packets */
pkt_offset = 0;
while (pkt_offset < buf_size) {
pkt_length = wl12xx_rx_get_buf_size(status,
drv_rx_counter);
unaligned = wl12xx_rx_get_unaligned(status,
drv_rx_counter);
des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
pkt_len = wlcore_rx_get_buf_size(wl, des);
rx_align = wlcore_hw_get_rx_buf_align(wl, des);
/*
* the handle data call can only fail in memory-outage
......@@ -256,7 +251,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
*/
if (wl1271_rx_handle_data(wl,
wl->aggr_buf + pkt_offset,
pkt_length, unaligned,
pkt_len, rx_align,
&hlid) == 1) {
if (hlid < WL12XX_MAX_LINKS)
__set_bit(hlid, active_hlids);
......@@ -269,7 +264,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
wl->rx_counter++;
drv_rx_counter++;
drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
pkt_offset += pkt_length;
pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len);
}
}
......@@ -277,8 +272,9 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
* Write the driver's packet counter to the FW. This is only required
* for older hardware revisions
*/
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER,
wl->rx_counter);
wl12xx_rearm_rx_streaming(wl, active_hlids);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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