mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-05 18:26:39 +07:00
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
This commit is contained in:
commit
cbdbc5eb54
@ -6742,12 +6742,12 @@ S: Maintained
|
||||
F: drivers/net/wireless/wl1251/*
|
||||
|
||||
WL1271 WIRELESS DRIVER
|
||||
M: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
M: Luciano Coelho <coelho@ti.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.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/wl1271*
|
||||
F: drivers/net/wireless/wl12xx/
|
||||
F: include/linux/wl12xx.h
|
||||
|
||||
WL3501 WIRELESS PCMCIA CARD DRIVER
|
||||
|
@ -751,10 +751,10 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl)
|
||||
int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
|
||||
{
|
||||
struct acx_rate_policy *acx;
|
||||
struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
|
||||
struct acx_sta_rate_policy *acx;
|
||||
struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
|
||||
int idx = 0;
|
||||
int ret = 0;
|
||||
|
||||
@ -794,6 +794,38 @@ int wl1271_acx_rate_policies(struct wl1271 *wl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
|
||||
u8 idx)
|
||||
{
|
||||
struct acx_ap_rate_policy *acx;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ap rate policy");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->rate_policy.enabled_rates = cpu_to_le32(c->enabled_rates);
|
||||
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;
|
||||
|
||||
acx->rate_policy_idx = cpu_to_le32(idx);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Setting of ap rate policy failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
|
||||
u8 aifsn, u16 txop)
|
||||
{
|
||||
@ -1233,6 +1265,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
|
||||
struct wl1271_acx_ht_capabilities *acx;
|
||||
u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
int ret = 0;
|
||||
u32 ht_capabilites = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
|
||||
|
||||
@ -1244,16 +1277,16 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
|
||||
|
||||
/* Allow HT Operation ? */
|
||||
if (allow_ht_operation) {
|
||||
acx->ht_capabilites =
|
||||
ht_capabilites =
|
||||
WL1271_ACX_FW_CAP_HT_OPERATION;
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
|
||||
acx->ht_capabilites |=
|
||||
ht_capabilites |=
|
||||
WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
|
||||
acx->ht_capabilites |=
|
||||
ht_capabilites |=
|
||||
WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
|
||||
acx->ht_capabilites |=
|
||||
ht_capabilites |=
|
||||
WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
|
||||
|
||||
/* get data from A-MPDU parameters field */
|
||||
@ -1261,10 +1294,10 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
|
||||
acx->ampdu_min_spacing = ht_cap->ampdu_density;
|
||||
|
||||
memcpy(acx->mac_address, mac_address, ETH_ALEN);
|
||||
} else { /* HT operations are not allowed */
|
||||
acx->ht_capabilites = 0;
|
||||
}
|
||||
|
||||
acx->ht_capabilites = cpu_to_le32(ht_capabilites);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx ht capabilities setting failed: %d", ret);
|
||||
@ -1309,6 +1342,91 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure BA session initiator/receiver parameters setting in the FW. */
|
||||
int wl1271_acx_set_ba_session(struct wl1271 *wl,
|
||||
enum ieee80211_back_parties direction,
|
||||
u8 tid_index, u8 policy)
|
||||
{
|
||||
struct wl1271_acx_ba_session_policy *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ba session setting");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* ANY role */
|
||||
acx->role_id = 0xff;
|
||||
acx->tid = tid_index;
|
||||
acx->enable = policy;
|
||||
acx->ba_direction = direction;
|
||||
|
||||
switch (direction) {
|
||||
case WLAN_BACK_INITIATOR:
|
||||
acx->win_size = wl->conf.ht.tx_ba_win_size;
|
||||
acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
|
||||
break;
|
||||
case WLAN_BACK_RECIPIENT:
|
||||
acx->win_size = RX_BA_WIN_SIZE;
|
||||
acx->inactivity_timeout = 0;
|
||||
break;
|
||||
default:
|
||||
wl1271_error("Incorrect acx command id=%x\n", direction);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_configure(wl,
|
||||
ACX_BA_SESSION_POLICY_CFG,
|
||||
acx,
|
||||
sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx ba session setting failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* setup BA session receiver setting in the FW. */
|
||||
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
|
||||
bool enable)
|
||||
{
|
||||
struct wl1271_acx_ba_receiver_setup *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ba receiver session setting");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Single link for now */
|
||||
acx->link_id = 1;
|
||||
acx->tid = tid_index;
|
||||
acx->enable = enable;
|
||||
acx->win_size = 0;
|
||||
acx->ssn = ssn;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
|
||||
sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx ba receiver session failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
|
||||
{
|
||||
struct wl1271_acx_fw_tsf_information *tsf_info;
|
||||
@ -1334,3 +1452,27 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
|
||||
kfree(tsf_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_max_tx_retry(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_max_tx_retry *acx = NULL;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx max tx retry");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx)
|
||||
return -ENOMEM;
|
||||
|
||||
acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx max tx retry failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
@ -747,13 +747,23 @@ struct acx_rate_class {
|
||||
#define ACX_TX_BASIC_RATE 0
|
||||
#define ACX_TX_AP_FULL_RATE 1
|
||||
#define ACX_TX_RATE_POLICY_CNT 2
|
||||
struct acx_rate_policy {
|
||||
struct acx_sta_rate_policy {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 rate_class_cnt;
|
||||
struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
|
||||
} __packed;
|
||||
|
||||
|
||||
#define ACX_TX_AP_MODE_MGMT_RATE 4
|
||||
#define ACX_TX_AP_MODE_BCST_RATE 5
|
||||
struct acx_ap_rate_policy {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 rate_policy_idx;
|
||||
struct acx_rate_class rate_policy;
|
||||
} __packed;
|
||||
|
||||
struct acx_ac_cfg {
|
||||
struct acx_header header;
|
||||
u8 ac;
|
||||
@ -1051,6 +1061,59 @@ struct wl1271_acx_ht_information {
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
#define RX_BA_WIN_SIZE 8
|
||||
|
||||
struct wl1271_acx_ba_session_policy {
|
||||
struct acx_header header;
|
||||
/*
|
||||
* Specifies role Id, Range 0-7, 0xFF means ANY role.
|
||||
* Future use. For now this field is irrelevant
|
||||
*/
|
||||
u8 role_id;
|
||||
/*
|
||||
* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id.
|
||||
* Not applicable if Role Id is set to ANY.
|
||||
*/
|
||||
u8 link_id;
|
||||
|
||||
u8 tid;
|
||||
|
||||
u8 enable;
|
||||
|
||||
/* Windows size in number of packets */
|
||||
u16 win_size;
|
||||
|
||||
/*
|
||||
* As initiator inactivity timeout in time units(TU) of 1024us.
|
||||
* As receiver reserved
|
||||
*/
|
||||
u16 inactivity_timeout;
|
||||
|
||||
/* Initiator = 1/Receiver = 0 */
|
||||
u8 ba_direction;
|
||||
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_ba_receiver_setup {
|
||||
struct acx_header header;
|
||||
|
||||
/* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */
|
||||
u8 link_id;
|
||||
|
||||
u8 tid;
|
||||
|
||||
u8 enable;
|
||||
|
||||
u8 padding[1];
|
||||
|
||||
/* Windows size in number of packets */
|
||||
u16 win_size;
|
||||
|
||||
/* BA session starting sequence number. RANGE 0-FFF */
|
||||
u16 ssn;
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_fw_tsf_information {
|
||||
struct acx_header header;
|
||||
|
||||
@ -1062,6 +1125,17 @@ struct wl1271_acx_fw_tsf_information {
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_max_tx_retry {
|
||||
struct acx_header header;
|
||||
|
||||
/*
|
||||
* the number of frames transmission failures before
|
||||
* issuing the aging event.
|
||||
*/
|
||||
__le16 max_tx_retry;
|
||||
u8 padding_1[2];
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
||||
ACX_MEM_CFG = 0x0003,
|
||||
@ -1113,12 +1187,13 @@ enum {
|
||||
ACX_RSSI_SNR_WEIGHTS = 0x0052,
|
||||
ACX_KEEP_ALIVE_MODE = 0x0053,
|
||||
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
|
||||
ACX_BA_SESSION_RESPONDER_POLICY = 0x0055,
|
||||
ACX_BA_SESSION_INITIATOR_POLICY = 0x0056,
|
||||
ACX_BA_SESSION_POLICY_CFG = 0x0055,
|
||||
ACX_BA_SESSION_RX_SETUP = 0x0056,
|
||||
ACX_PEER_HT_CAP = 0x0057,
|
||||
ACX_HT_BSS_OPERATION = 0x0058,
|
||||
ACX_COEX_ACTIVITY = 0x0059,
|
||||
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
|
||||
ACX_MAX_TX_FAILURE = 0x0072,
|
||||
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
|
||||
DOT11_CUR_TX_PWR = 0x100D,
|
||||
DOT11_RX_DOT11_MODE = 0x1012,
|
||||
@ -1160,7 +1235,9 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
|
||||
int wl1271_acx_cts_protect(struct wl1271 *wl,
|
||||
enum acx_ctsprotect_type ctsprotect);
|
||||
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl);
|
||||
int wl1271_acx_sta_rate_policies(struct wl1271 *wl);
|
||||
int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
|
||||
u8 idx);
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
|
||||
u8 aifsn, u16 txop);
|
||||
int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
|
||||
@ -1185,6 +1262,12 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
|
||||
bool allow_ht_operation);
|
||||
int wl1271_acx_set_ht_information(struct wl1271 *wl,
|
||||
u16 ht_operation_mode);
|
||||
int wl1271_acx_set_ba_session(struct wl1271 *wl,
|
||||
enum ieee80211_back_parties direction,
|
||||
u8 tid_index, u8 policy);
|
||||
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
|
||||
bool enable);
|
||||
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
|
||||
int wl1271_acx_max_tx_retry(struct wl1271 *wl);
|
||||
|
||||
#endif /* __WL1271_ACX_H__ */
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "boot.h"
|
||||
#include "io.h"
|
||||
#include "event.h"
|
||||
#include "rx.h"
|
||||
|
||||
static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
|
||||
[PART_DOWN] = {
|
||||
@ -100,6 +101,22 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
|
||||
wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
|
||||
}
|
||||
|
||||
static void wl1271_parse_fw_ver(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
|
||||
&wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
|
||||
&wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
|
||||
&wl->chip.fw_ver[4]);
|
||||
|
||||
if (ret != 5) {
|
||||
wl1271_warning("fw version incorrect value");
|
||||
memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void wl1271_boot_fw_version(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_static_data static_data;
|
||||
@ -107,11 +124,13 @@ static void wl1271_boot_fw_version(struct wl1271 *wl)
|
||||
wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
|
||||
false);
|
||||
|
||||
strncpy(wl->chip.fw_ver, static_data.fw_version,
|
||||
sizeof(wl->chip.fw_ver));
|
||||
strncpy(wl->chip.fw_ver_str, static_data.fw_version,
|
||||
sizeof(wl->chip.fw_ver_str));
|
||||
|
||||
/* make sure the string is NULL-terminated */
|
||||
wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
|
||||
wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';
|
||||
|
||||
wl1271_parse_fw_ver(wl);
|
||||
}
|
||||
|
||||
static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
||||
@ -231,7 +250,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
*/
|
||||
if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
|
||||
wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
|
||||
if (wl->nvs->general_params.dual_mode_select)
|
||||
/* for now 11a is unsupported in AP mode */
|
||||
if (wl->bss_type != BSS_TYPE_AP_BSS &&
|
||||
wl->nvs->general_params.dual_mode_select)
|
||||
wl->enable_11a = true;
|
||||
}
|
||||
|
||||
@ -431,6 +452,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
|
||||
SOFT_GEMINI_SENSE_EVENT_ID;
|
||||
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
|
||||
|
||||
ret = wl1271_event_unmask(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("EVENT mask setting failed");
|
||||
@ -595,8 +619,7 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
wl1271_boot_enable_interrupts(wl);
|
||||
|
||||
/* set the wl1271 default filters */
|
||||
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
|
||||
wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
|
||||
wl1271_set_default_filters(wl);
|
||||
|
||||
wl1271_event_mbox_config(wl);
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "wl12xx_80211.h"
|
||||
#include "cmd.h"
|
||||
#include "event.h"
|
||||
#include "tx.h"
|
||||
|
||||
#define WL1271_CMD_FAST_POLL_COUNT 50
|
||||
|
||||
@ -221,7 +222,7 @@ int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
|
||||
* Poll the mailbox event field until any of the bits in the mask is set or a
|
||||
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
|
||||
*/
|
||||
static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
|
||||
static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
|
||||
{
|
||||
u32 events_vector, event;
|
||||
unsigned long timeout;
|
||||
@ -230,7 +231,8 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
|
||||
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
|
||||
(int)mask);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -248,6 +250,19 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
|
||||
if (ret != 0) {
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
|
||||
{
|
||||
struct wl1271_cmd_join *join;
|
||||
@ -490,8 +505,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
|
||||
cmd->len = cpu_to_le16(buf_len);
|
||||
cmd->template_type = template_id;
|
||||
cmd->enabled_rates = cpu_to_le32(rates);
|
||||
cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit;
|
||||
cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit;
|
||||
cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit;
|
||||
cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit;
|
||||
cmd->index = index;
|
||||
|
||||
if (buf)
|
||||
@ -659,15 +674,15 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
|
||||
|
||||
/* llc layer */
|
||||
memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header));
|
||||
tmpl.llc_type = htons(ETH_P_ARP);
|
||||
tmpl.llc_type = cpu_to_be16(ETH_P_ARP);
|
||||
|
||||
/* arp header */
|
||||
arp_hdr = &tmpl.arp_hdr;
|
||||
arp_hdr->ar_hrd = htons(ARPHRD_ETHER);
|
||||
arp_hdr->ar_pro = htons(ETH_P_IP);
|
||||
arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER);
|
||||
arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP);
|
||||
arp_hdr->ar_hln = ETH_ALEN;
|
||||
arp_hdr->ar_pln = 4;
|
||||
arp_hdr->ar_op = htons(ARPOP_REPLY);
|
||||
arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
|
||||
|
||||
/* arp payload */
|
||||
memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN);
|
||||
@ -702,9 +717,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
|
||||
wl->basic_rate);
|
||||
}
|
||||
|
||||
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
{
|
||||
struct wl1271_cmd_set_keys *cmd;
|
||||
struct wl1271_cmd_set_sta_keys *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
|
||||
@ -731,11 +746,42 @@ int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
{
|
||||
struct wl1271_cmd_set_ap_keys *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->hlid = WL1271_AP_BROADCAST_HLID;
|
||||
cmd->key_id = id;
|
||||
cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
|
||||
cmd->key_action = cpu_to_le16(KEY_SET_ID);
|
||||
cmd->key_type = KEY_WEP;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
u8 key_size, const u8 *key, const u8 *addr,
|
||||
u32 tx_seq_32, u16 tx_seq_16)
|
||||
{
|
||||
struct wl1271_cmd_set_keys *cmd;
|
||||
struct wl1271_cmd_set_sta_keys *cmd;
|
||||
int ret = 0;
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
@ -788,6 +834,67 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
|
||||
u16 tx_seq_16)
|
||||
{
|
||||
struct wl1271_cmd_set_ap_keys *cmd;
|
||||
int ret = 0;
|
||||
u8 lid_type;
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
if (hlid == WL1271_AP_BROADCAST_HLID) {
|
||||
if (key_type == KEY_WEP)
|
||||
lid_type = WEP_DEFAULT_LID_TYPE;
|
||||
else
|
||||
lid_type = BROADCAST_LID_TYPE;
|
||||
} else {
|
||||
lid_type = UNICAST_LID_TYPE;
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d"
|
||||
" hlid: %d", (int)action, (int)id, (int)lid_type,
|
||||
(int)key_type, (int)hlid);
|
||||
|
||||
cmd->lid_key_type = lid_type;
|
||||
cmd->hlid = hlid;
|
||||
cmd->key_action = cpu_to_le16(action);
|
||||
cmd->key_size = key_size;
|
||||
cmd->key_type = key_type;
|
||||
cmd->key_id = id;
|
||||
cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
|
||||
cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
|
||||
|
||||
if (key_type == KEY_TKIP) {
|
||||
/*
|
||||
* We get the key in the following form:
|
||||
* TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
|
||||
* but the target is expecting:
|
||||
* TKIP - RX MIC - TX MIC
|
||||
*/
|
||||
memcpy(cmd->key, key, 16);
|
||||
memcpy(cmd->key + 16, key + 24, 8);
|
||||
memcpy(cmd->key + 24, key + 16, 8);
|
||||
} else {
|
||||
memcpy(cmd->key, key, key_size);
|
||||
}
|
||||
|
||||
wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd));
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("could not set ap keys");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_disconnect(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_cmd_disconnect *cmd;
|
||||
@ -850,3 +957,180 @@ int wl1271_cmd_set_sta_state(struct wl1271 *wl)
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_start_bss(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_cmd_bss_start *cmd;
|
||||
struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd start bss");
|
||||
|
||||
/*
|
||||
* FIXME: We currently do not support hidden SSID. The real SSID
|
||||
* should be fetched from mac80211 first.
|
||||
*/
|
||||
if (wl->ssid_len == 0) {
|
||||
wl1271_warning("Hidden SSID currently not supported for AP");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
|
||||
cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
|
||||
cmd->bss_index = WL1271_AP_BSS_INDEX;
|
||||
cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
|
||||
cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
|
||||
cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
|
||||
cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
|
||||
cmd->dtim_interval = bss_conf->dtim_period;
|
||||
cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
|
||||
cmd->channel = wl->channel;
|
||||
cmd->ssid_len = wl->ssid_len;
|
||||
cmd->ssid_type = SSID_TYPE_PUBLIC;
|
||||
memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
|
||||
|
||||
switch (wl->band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
cmd->band = RADIO_BAND_2_4GHZ;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
cmd->band = RADIO_BAND_5GHZ;
|
||||
break;
|
||||
default:
|
||||
wl1271_warning("bss start - unknown band: %d", (int)wl->band);
|
||||
cmd->band = RADIO_BAND_2_4GHZ;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to initiate cmd start bss");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_stop_bss(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_cmd_bss_start *cmd;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd stop bss");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->bss_index = WL1271_AP_BSS_INDEX;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to initiate cmd stop bss");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
|
||||
{
|
||||
struct wl1271_cmd_add_sta *cmd;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* currently we don't support UAPSD */
|
||||
cmd->sp_len = 0;
|
||||
|
||||
memcpy(cmd->addr, sta->addr, ETH_ALEN);
|
||||
cmd->bss_index = WL1271_AP_BSS_INDEX;
|
||||
cmd->aid = sta->aid;
|
||||
cmd->hlid = hlid;
|
||||
|
||||
/*
|
||||
* FIXME: Does STA support QOS? We need to propagate this info from
|
||||
* hostapd. Currently not that important since this is only used for
|
||||
* sending the correct flavor of null-data packet in response to a
|
||||
* trigger.
|
||||
*/
|
||||
cmd->wmm = 0;
|
||||
|
||||
cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
|
||||
sta->supp_rates[wl->band]));
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to initiate cmd add sta");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
|
||||
{
|
||||
struct wl1271_cmd_remove_sta *cmd;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->hlid = hlid;
|
||||
/* We never send a deauth, mac80211 is in charge of this */
|
||||
cmd->reason_opcode = 0;
|
||||
cmd->send_deauth_flag = 0;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to initiate cmd remove sta");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are ok with a timeout here. The event is sometimes not sent
|
||||
* due to a firmware bug.
|
||||
*/
|
||||
wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID);
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -54,12 +54,20 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
|
||||
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
|
||||
int wl1271_build_qos_null_data(struct wl1271 *wl);
|
||||
int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
|
||||
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
|
||||
int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
u8 key_size, const u8 *key, const u8 *addr,
|
||||
u32 tx_seq_32, u16 tx_seq_16);
|
||||
int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id);
|
||||
int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
|
||||
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
u8 key_size, const u8 *key, const u8 *addr,
|
||||
u32 tx_seq_32, u16 tx_seq_16);
|
||||
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
|
||||
u16 tx_seq_16);
|
||||
int wl1271_cmd_disconnect(struct wl1271 *wl);
|
||||
int wl1271_cmd_set_sta_state(struct wl1271 *wl);
|
||||
int wl1271_cmd_start_bss(struct wl1271 *wl);
|
||||
int wl1271_cmd_stop_bss(struct wl1271 *wl);
|
||||
int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
|
||||
int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
|
||||
|
||||
enum wl1271_commands {
|
||||
CMD_INTERROGATE = 1, /*use this to read information elements*/
|
||||
@ -98,6 +106,12 @@ enum wl1271_commands {
|
||||
CMD_STOP_PERIODIC_SCAN = 51,
|
||||
CMD_SET_STA_STATE = 52,
|
||||
|
||||
/* AP mode commands */
|
||||
CMD_BSS_START = 60,
|
||||
CMD_BSS_STOP = 61,
|
||||
CMD_ADD_STA = 62,
|
||||
CMD_REMOVE_STA = 63,
|
||||
|
||||
NUM_COMMANDS,
|
||||
MAX_COMMAND_ID = 0xFFFF,
|
||||
};
|
||||
@ -126,6 +140,13 @@ enum cmd_templ {
|
||||
* For CTS-to-self (FastCTS) mechanism
|
||||
* for BT/WLAN coexistence (SoftGemini). */
|
||||
CMD_TEMPL_ARP_RSP,
|
||||
|
||||
/* AP-mode specific */
|
||||
CMD_TEMPL_AP_BEACON = 13,
|
||||
CMD_TEMPL_AP_PROBE_RESPONSE,
|
||||
CMD_TEMPL_AP_ARP_RSP,
|
||||
CMD_TEMPL_DEAUTH_AP,
|
||||
|
||||
CMD_TEMPL_MAX = 0xff
|
||||
};
|
||||
|
||||
@ -270,7 +291,6 @@ struct wl1271_cmd_ps_params {
|
||||
|
||||
/* HW encryption keys */
|
||||
#define NUM_ACCESS_CATEGORIES_COPY 4
|
||||
#define MAX_KEY_SIZE 32
|
||||
|
||||
enum wl1271_cmd_key_action {
|
||||
KEY_ADD_OR_REPLACE = 1,
|
||||
@ -289,7 +309,7 @@ enum wl1271_cmd_key_type {
|
||||
|
||||
/* FIXME: Add description for key-types */
|
||||
|
||||
struct wl1271_cmd_set_keys {
|
||||
struct wl1271_cmd_set_sta_keys {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
/* Ignored for default WEP key */
|
||||
@ -318,6 +338,57 @@ struct wl1271_cmd_set_keys {
|
||||
__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
|
||||
} __packed;
|
||||
|
||||
enum wl1271_cmd_lid_key_type {
|
||||
UNICAST_LID_TYPE = 0,
|
||||
BROADCAST_LID_TYPE = 1,
|
||||
WEP_DEFAULT_LID_TYPE = 2
|
||||
};
|
||||
|
||||
struct wl1271_cmd_set_ap_keys {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
/*
|
||||
* Indicates whether the HLID is a unicast key set
|
||||
* or broadcast key set. A special value 0xFF is
|
||||
* used to indicate that the HLID is on WEP-default
|
||||
* (multi-hlids). of type wl1271_cmd_lid_key_type.
|
||||
*/
|
||||
u8 hlid;
|
||||
|
||||
/*
|
||||
* In WEP-default network (hlid == 0xFF) used to
|
||||
* indicate which network STA/IBSS/AP role should be
|
||||
* changed
|
||||
*/
|
||||
u8 lid_key_type;
|
||||
|
||||
/*
|
||||
* Key ID - For TKIP and AES key types, this field
|
||||
* indicates the value that should be inserted into
|
||||
* the KeyID field of frames transmitted using this
|
||||
* key entry. For broadcast keys the index use as a
|
||||
* marker for TX/RX key.
|
||||
* For WEP default network (HLID=0xFF), this field
|
||||
* indicates the ID of the key to add or remove.
|
||||
*/
|
||||
u8 key_id;
|
||||
u8 reserved_1;
|
||||
|
||||
/* key_action_e */
|
||||
__le16 key_action;
|
||||
|
||||
/* key size in bytes */
|
||||
u8 key_size;
|
||||
|
||||
/* key_type_e */
|
||||
u8 key_type;
|
||||
|
||||
/* This field holds the security key data to add to the STA table */
|
||||
u8 key[MAX_KEY_SIZE];
|
||||
__le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
|
||||
__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_cmd_test_header {
|
||||
u8 id;
|
||||
u8 padding[3];
|
||||
@ -412,4 +483,68 @@ struct wl1271_cmd_set_sta_state {
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
enum wl1271_ssid_type {
|
||||
SSID_TYPE_PUBLIC = 0,
|
||||
SSID_TYPE_HIDDEN = 1
|
||||
};
|
||||
|
||||
struct wl1271_cmd_bss_start {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
/* wl1271_ssid_type */
|
||||
u8 ssid_type;
|
||||
u8 ssid_len;
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
u8 padding_1[2];
|
||||
|
||||
/* Basic rate set */
|
||||
__le32 basic_rate_set;
|
||||
/* Aging period in seconds*/
|
||||
__le16 aging_period;
|
||||
|
||||
/*
|
||||
* This field specifies the time between target beacon
|
||||
* transmission times (TBTTs), in time units (TUs).
|
||||
* Valid values are 1 to 1024.
|
||||
*/
|
||||
__le16 beacon_interval;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 bss_index;
|
||||
/* Radio band */
|
||||
u8 band;
|
||||
u8 channel;
|
||||
/* The host link id for the AP's global queue */
|
||||
u8 global_hlid;
|
||||
/* The host link id for the AP's broadcast queue */
|
||||
u8 broadcast_hlid;
|
||||
/* DTIM count */
|
||||
u8 dtim_interval;
|
||||
/* Beacon expiry time in ms */
|
||||
u8 beacon_expiry;
|
||||
u8 padding_2[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_cmd_add_sta {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 hlid;
|
||||
u8 aid;
|
||||
u8 psd_type[NUM_ACCESS_CATEGORIES_COPY];
|
||||
__le32 supported_rates;
|
||||
u8 bss_index;
|
||||
u8 sp_len;
|
||||
u8 wmm;
|
||||
u8 padding1;
|
||||
} __packed;
|
||||
|
||||
struct wl1271_cmd_remove_sta {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 hlid;
|
||||
u8 reason_opcode;
|
||||
u8 send_deauth_flag;
|
||||
u8 padding1;
|
||||
} __packed;
|
||||
|
||||
#endif /* __WL1271_CMD_H__ */
|
||||
|
@ -496,6 +496,26 @@ struct conf_rx_settings {
|
||||
CONF_HW_BIT_RATE_2MBPS)
|
||||
#define CONF_TX_RATE_RETRY_LIMIT 10
|
||||
|
||||
/*
|
||||
* Rates supported for data packets when operating as AP. Note the absense
|
||||
* of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
|
||||
* one. The rate dropped is not mandatory under any operating mode.
|
||||
*/
|
||||
#define CONF_TX_AP_ENABLED_RATES (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
|
||||
CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \
|
||||
CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \
|
||||
CONF_HW_BIT_RATE_18MBPS | CONF_HW_BIT_RATE_24MBPS | \
|
||||
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
|
||||
CONF_HW_BIT_RATE_54MBPS)
|
||||
|
||||
/*
|
||||
* Default rates for management traffic when operating in AP mode. This
|
||||
* should be configured according to the basic rate set of the AP
|
||||
*/
|
||||
#define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
|
||||
|
||||
struct conf_tx_rate_class {
|
||||
|
||||
/*
|
||||
@ -636,9 +656,9 @@ struct conf_tx_settings {
|
||||
|
||||
/*
|
||||
* Configuration for rate classes for TX (currently only one
|
||||
* rate class supported.)
|
||||
* rate class supported). Used in non-AP mode.
|
||||
*/
|
||||
struct conf_tx_rate_class rc_conf;
|
||||
struct conf_tx_rate_class sta_rc_conf;
|
||||
|
||||
/*
|
||||
* Configuration for access categories for TX rate control.
|
||||
@ -646,6 +666,28 @@ struct conf_tx_settings {
|
||||
u8 ac_conf_count;
|
||||
struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT];
|
||||
|
||||
/*
|
||||
* Configuration for rate classes in AP-mode. These rate classes
|
||||
* are for the AC TX queues
|
||||
*/
|
||||
struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT];
|
||||
|
||||
/*
|
||||
* Management TX rate class for AP-mode.
|
||||
*/
|
||||
struct conf_tx_rate_class ap_mgmt_conf;
|
||||
|
||||
/*
|
||||
* Broadcast TX rate class for AP-mode.
|
||||
*/
|
||||
struct conf_tx_rate_class ap_bcst_conf;
|
||||
|
||||
/*
|
||||
* AP-mode - allow this number of TX retries to a station before an
|
||||
* event is triggered from FW.
|
||||
*/
|
||||
u16 ap_max_tx_retries;
|
||||
|
||||
/*
|
||||
* Configuration for TID parameters.
|
||||
*/
|
||||
@ -687,6 +729,12 @@ struct conf_tx_settings {
|
||||
* Range: CONF_HW_BIT_RATE_* bit mask
|
||||
*/
|
||||
u32 basic_rate_5;
|
||||
|
||||
/*
|
||||
* TX retry limits for templates
|
||||
*/
|
||||
u8 tmpl_short_retry_limit;
|
||||
u8 tmpl_long_retry_limit;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -1036,30 +1084,30 @@ struct conf_scan_settings {
|
||||
/*
|
||||
* The minimum time to wait on each channel for active scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
* Range: u32 tu/1000
|
||||
*/
|
||||
u16 min_dwell_time_active;
|
||||
u32 min_dwell_time_active;
|
||||
|
||||
/*
|
||||
* The maximum time to wait on each channel for active scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
* Range: u32 tu/1000
|
||||
*/
|
||||
u16 max_dwell_time_active;
|
||||
u32 max_dwell_time_active;
|
||||
|
||||
/*
|
||||
* The minimum time to wait on each channel for passive scans
|
||||
*
|
||||
* Range: u32 tu/1000
|
||||
*/
|
||||
u32 min_dwell_time_passive;
|
||||
|
||||
/*
|
||||
* The maximum time to wait on each channel for passive scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
* Range: u32 tu/1000
|
||||
*/
|
||||
u16 min_dwell_time_passive;
|
||||
|
||||
/*
|
||||
* The maximum time to wait on each channel for passive scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
*/
|
||||
u16 max_dwell_time_passive;
|
||||
u32 max_dwell_time_passive;
|
||||
|
||||
/*
|
||||
* Number of probe requests to transmit on each active scan channel
|
||||
@ -1090,6 +1138,11 @@ struct conf_rf_settings {
|
||||
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
|
||||
};
|
||||
|
||||
struct conf_ht_setting {
|
||||
u16 tx_ba_win_size;
|
||||
u16 inactivity_timeout;
|
||||
};
|
||||
|
||||
struct conf_drv_settings {
|
||||
struct conf_sg_settings sg;
|
||||
struct conf_rx_settings rx;
|
||||
@ -1100,6 +1153,7 @@ struct conf_drv_settings {
|
||||
struct conf_roam_trigger_settings roam_trigger;
|
||||
struct conf_scan_settings scan;
|
||||
struct conf_rf_settings rf;
|
||||
struct conf_ht_setting ht;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -261,27 +261,25 @@ static ssize_t gpio_power_write(struct file *file,
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
return -EFAULT;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
|
||||
ret = strict_strtoul(buf, 0, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in gpio_power");
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (value)
|
||||
wl1271_power_on(wl);
|
||||
else
|
||||
wl1271_power_off(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
@ -293,12 +291,13 @@ static const struct file_operations gpio_power_ops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int wl1271_debugfs_add_files(struct wl1271 *wl)
|
||||
static int wl1271_debugfs_add_files(struct wl1271 *wl,
|
||||
struct dentry *rootdir)
|
||||
{
|
||||
int ret = 0;
|
||||
struct dentry *entry, *stats;
|
||||
|
||||
stats = debugfs_create_dir("fw-statistics", wl->rootdir);
|
||||
stats = debugfs_create_dir("fw-statistics", rootdir);
|
||||
if (!stats || IS_ERR(stats)) {
|
||||
entry = stats;
|
||||
goto err;
|
||||
@ -395,16 +394,11 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl)
|
||||
DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
|
||||
DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
|
||||
|
||||
DEBUGFS_ADD(tx_queue_len, wl->rootdir);
|
||||
DEBUGFS_ADD(retry_count, wl->rootdir);
|
||||
DEBUGFS_ADD(excessive_retries, wl->rootdir);
|
||||
DEBUGFS_ADD(tx_queue_len, rootdir);
|
||||
DEBUGFS_ADD(retry_count, rootdir);
|
||||
DEBUGFS_ADD(excessive_retries, rootdir);
|
||||
|
||||
DEBUGFS_ADD(gpio_power, wl->rootdir);
|
||||
|
||||
entry = debugfs_create_x32("debug_level", 0600, wl->rootdir,
|
||||
&wl12xx_debug_level);
|
||||
if (!entry || IS_ERR(entry))
|
||||
goto err;
|
||||
DEBUGFS_ADD(gpio_power, rootdir);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -419,7 +413,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl)
|
||||
|
||||
void wl1271_debugfs_reset(struct wl1271 *wl)
|
||||
{
|
||||
if (!wl->rootdir)
|
||||
if (!wl->stats.fw_stats)
|
||||
return;
|
||||
|
||||
memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
|
||||
@ -430,13 +424,13 @@ void wl1271_debugfs_reset(struct wl1271 *wl)
|
||||
int wl1271_debugfs_init(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
struct dentry *rootdir;
|
||||
|
||||
wl->rootdir = debugfs_create_dir(KBUILD_MODNAME,
|
||||
wl->hw->wiphy->debugfsdir);
|
||||
rootdir = debugfs_create_dir(KBUILD_MODNAME,
|
||||
wl->hw->wiphy->debugfsdir);
|
||||
|
||||
if (IS_ERR(wl->rootdir)) {
|
||||
ret = PTR_ERR(wl->rootdir);
|
||||
wl->rootdir = NULL;
|
||||
if (IS_ERR(rootdir)) {
|
||||
ret = PTR_ERR(rootdir);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -450,7 +444,7 @@ int wl1271_debugfs_init(struct wl1271 *wl)
|
||||
|
||||
wl->stats.fw_stats_update = jiffies;
|
||||
|
||||
ret = wl1271_debugfs_add_files(wl);
|
||||
ret = wl1271_debugfs_add_files(wl, rootdir);
|
||||
|
||||
if (ret < 0)
|
||||
goto err_file;
|
||||
@ -462,8 +456,7 @@ int wl1271_debugfs_init(struct wl1271 *wl)
|
||||
wl->stats.fw_stats = NULL;
|
||||
|
||||
err_fw:
|
||||
debugfs_remove_recursive(wl->rootdir);
|
||||
wl->rootdir = NULL;
|
||||
debugfs_remove_recursive(rootdir);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
@ -473,8 +466,4 @@ void wl1271_debugfs_exit(struct wl1271 *wl)
|
||||
{
|
||||
kfree(wl->stats.fw_stats);
|
||||
wl->stats.fw_stats = NULL;
|
||||
|
||||
debugfs_remove_recursive(wl->rootdir);
|
||||
wl->rootdir = NULL;
|
||||
|
||||
}
|
||||
|
@ -186,6 +186,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
int ret;
|
||||
u32 vector;
|
||||
bool beacon_loss = false;
|
||||
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
|
||||
|
||||
wl1271_event_mbox_dump(mbox);
|
||||
|
||||
@ -218,21 +219,21 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
* BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
|
||||
*
|
||||
*/
|
||||
if (vector & BSS_LOSE_EVENT_ID) {
|
||||
if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) {
|
||||
wl1271_info("Beacon loss detected.");
|
||||
|
||||
/* indicate to the stack, that beacons have been lost */
|
||||
beacon_loss = true;
|
||||
}
|
||||
|
||||
if (vector & PS_REPORT_EVENT_ID) {
|
||||
if ((vector & PS_REPORT_EVENT_ID) && !is_ap) {
|
||||
wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
|
||||
ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
|
||||
if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap)
|
||||
wl1271_event_pspoll_delivery_fail(wl);
|
||||
|
||||
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
|
||||
|
@ -59,6 +59,7 @@ enum {
|
||||
BSS_LOSE_EVENT_ID = BIT(18),
|
||||
REGAINED_BSS_EVENT_ID = BIT(19),
|
||||
ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
|
||||
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */
|
||||
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
|
||||
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
|
||||
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
|
||||
@ -115,7 +116,12 @@ struct event_mailbox {
|
||||
u8 scheduled_scan_status;
|
||||
u8 ps_status;
|
||||
|
||||
u8 reserved_5[29];
|
||||
/* AP FW only */
|
||||
u8 hlid_removed;
|
||||
__le16 sta_aging_status;
|
||||
__le16 sta_tx_retry_exceeded;
|
||||
|
||||
u8 reserved_5[24];
|
||||
} __packed;
|
||||
|
||||
int wl1271_event_unmask(struct wl1271 *wl);
|
||||
|
@ -30,27 +30,9 @@
|
||||
#include "acx.h"
|
||||
#include "cmd.h"
|
||||
#include "reg.h"
|
||||
#include "tx.h"
|
||||
|
||||
static int wl1271_init_hwenc_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wl1271_acx_feature_cfg(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("couldn't set feature config");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("couldn't set default key");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
int wl1271_sta_init_templates_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
@ -118,6 +100,132 @@ int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
|
||||
{
|
||||
struct wl12xx_disconn_template *tmpl;
|
||||
int ret;
|
||||
|
||||
tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||
if (!tmpl) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_DEAUTH);
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
|
||||
tmpl, sizeof(*tmpl), 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
|
||||
out:
|
||||
kfree(tmpl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_ap_init_null_template(struct wl1271 *wl)
|
||||
{
|
||||
struct ieee80211_hdr_3addr *nullfunc;
|
||||
int ret;
|
||||
|
||||
nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
|
||||
if (!nullfunc) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
|
||||
IEEE80211_STYPE_NULLFUNC |
|
||||
IEEE80211_FCTL_FROMDS);
|
||||
|
||||
/* nullfunc->addr1 is filled by FW */
|
||||
|
||||
memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
|
||||
memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
|
||||
sizeof(*nullfunc), 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
|
||||
out:
|
||||
kfree(nullfunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
|
||||
{
|
||||
struct ieee80211_qos_hdr *qosnull;
|
||||
int ret;
|
||||
|
||||
qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
|
||||
if (!qosnull) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
|
||||
IEEE80211_STYPE_QOS_NULLFUNC |
|
||||
IEEE80211_FCTL_FROMDS);
|
||||
|
||||
/* qosnull->addr1 is filled by FW */
|
||||
|
||||
memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
|
||||
memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
|
||||
sizeof(*qosnull), 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
|
||||
out:
|
||||
kfree(qosnull);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_ap_init_templates_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Put very large empty placeholders for all templates. These
|
||||
* reserve memory for later.
|
||||
*/
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
|
||||
sizeof
|
||||
(struct wl12xx_probe_resp_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
|
||||
sizeof
|
||||
(struct wl12xx_beacon_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
|
||||
sizeof
|
||||
(struct wl12xx_disconn_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
|
||||
sizeof(struct wl12xx_null_data_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
|
||||
sizeof
|
||||
(struct wl12xx_qos_null_data_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
|
||||
{
|
||||
int ret;
|
||||
@ -145,10 +253,6 @@ int wl1271_init_phy_config(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_service_period_timeout(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -213,11 +317,186 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_sta_hw_init(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wl1271_cmd_ext_radio_parms(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_sta_init_templates_config(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Initialize connection monitoring thresholds */
|
||||
ret = wl1271_acx_conn_monit_params(wl, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Beacon filtering */
|
||||
ret = wl1271_init_beacon_filter(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Bluetooth WLAN coexistence */
|
||||
ret = wl1271_init_pta(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Beacons and broadcast settings */
|
||||
ret = wl1271_init_beacon_broadcast(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure for ELP power saving */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure rssi/snr averaging weights */
|
||||
ret = wl1271_acx_rssi_snr_avg_weights(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_sta_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("couldn't set default key");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* disable all keep-alive templates */
|
||||
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
|
||||
ret = wl1271_acx_keep_alive_config(wl, i,
|
||||
ACX_KEEP_ALIVE_TPL_INVALID);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* disable the keep-alive feature */
|
||||
ret = wl1271_acx_keep_alive_mode(wl, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_ap_hw_init(struct wl1271 *wl)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
ret = wl1271_ap_init_templates_config(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure for power always on */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure initial TX rate classes */
|
||||
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
|
||||
ret = wl1271_acx_ap_rate_policy(wl,
|
||||
&wl->conf.tx.ap_rc_conf[i], i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wl1271_acx_ap_rate_policy(wl,
|
||||
&wl->conf.tx.ap_mgmt_conf,
|
||||
ACX_TX_AP_MODE_MGMT_RATE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_ap_rate_policy(wl,
|
||||
&wl->conf.tx.ap_bcst_conf,
|
||||
ACX_TX_AP_MODE_BCST_RATE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_max_tx_retry(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wl1271_ap_init_deauth_template(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_ap_init_null_template(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_ap_init_qos_null_template(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl1271_check_ba_support(struct wl1271 *wl)
|
||||
{
|
||||
/* validate FW cose ver x.x.x.50-60.x */
|
||||
if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
|
||||
(wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
|
||||
wl->ba_support = true;
|
||||
return;
|
||||
}
|
||||
|
||||
wl->ba_support = false;
|
||||
}
|
||||
|
||||
static int wl1271_set_ba_policies(struct wl1271 *wl)
|
||||
{
|
||||
u8 tid_index;
|
||||
u8 ret = 0;
|
||||
|
||||
/* Reset the BA RX indicators */
|
||||
wl->ba_rx_bitmap = 0;
|
||||
|
||||
/* validate that FW support BA */
|
||||
wl1271_check_ba_support(wl);
|
||||
|
||||
if (wl->ba_support)
|
||||
/* 802.11n initiator BA session setting */
|
||||
for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
|
||||
++tid_index) {
|
||||
ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
|
||||
tid_index, true);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_hw_init(struct wl1271 *wl)
|
||||
{
|
||||
struct conf_tx_ac_category *conf_ac;
|
||||
struct conf_tx_tid *conf_tid;
|
||||
int ret, i;
|
||||
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
|
||||
|
||||
ret = wl1271_cmd_general_parms(wl);
|
||||
if (ret < 0)
|
||||
@ -227,12 +506,12 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_ext_radio_parms(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Mode specific init */
|
||||
if (is_ap)
|
||||
ret = wl1271_ap_hw_init(wl);
|
||||
else
|
||||
ret = wl1271_sta_hw_init(wl);
|
||||
|
||||
/* Template settings */
|
||||
ret = wl1271_init_templates_config(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -259,16 +538,6 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Initialize connection monitoring thresholds */
|
||||
ret = wl1271_acx_conn_monit_params(wl, false);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Beacon filtering */
|
||||
ret = wl1271_init_beacon_filter(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure TX patch complete interrupt behavior */
|
||||
ret = wl1271_acx_tx_config_options(wl);
|
||||
if (ret < 0)
|
||||
@ -279,21 +548,11 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Bluetooth WLAN coexistence */
|
||||
ret = wl1271_init_pta(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Energy detection */
|
||||
ret = wl1271_init_energy_detection(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Beacons and boradcast settings */
|
||||
ret = wl1271_init_beacon_broadcast(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Default fragmentation threshold */
|
||||
ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
|
||||
if (ret < 0)
|
||||
@ -321,23 +580,13 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Configure TX rate classes */
|
||||
ret = wl1271_acx_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Enable data path */
|
||||
ret = wl1271_cmd_data_path(wl, 1);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure for ELP power saving */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure HW encryption */
|
||||
ret = wl1271_init_hwenc_config(wl);
|
||||
ret = wl1271_acx_feature_cfg(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
@ -346,21 +595,17 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* disable all keep-alive templates */
|
||||
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
|
||||
ret = wl1271_acx_keep_alive_config(wl, i,
|
||||
ACX_KEEP_ALIVE_TPL_INVALID);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
/* Mode specific init - post mem init */
|
||||
if (is_ap)
|
||||
ret = wl1271_ap_hw_init_post_mem(wl);
|
||||
else
|
||||
ret = wl1271_sta_hw_init_post_mem(wl);
|
||||
|
||||
/* disable the keep-alive feature */
|
||||
ret = wl1271_acx_keep_alive_mode(wl, false);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure rssi/snr averaging weights */
|
||||
ret = wl1271_acx_rssi_snr_avg_weights(wl);
|
||||
/* Configure initiator BA sessions policies */
|
||||
ret = wl1271_set_ba_policies(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "wl12xx.h"
|
||||
|
||||
int wl1271_hw_init_power_auth(struct wl1271 *wl);
|
||||
int wl1271_init_templates_config(struct wl1271 *wl);
|
||||
int wl1271_sta_init_templates_config(struct wl1271 *wl);
|
||||
int wl1271_init_phy_config(struct wl1271 *wl);
|
||||
int wl1271_init_pta(struct wl1271 *wl);
|
||||
int wl1271_init_energy_detection(struct wl1271 *wl);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -198,6 +198,16 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
|
||||
pkt_offset += pkt_length;
|
||||
}
|
||||
}
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
|
||||
cpu_to_le32(wl->rx_counter));
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||
}
|
||||
|
||||
void wl1271_set_default_filters(struct wl1271 *wl)
|
||||
{
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS) {
|
||||
wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
|
||||
wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
|
||||
} else {
|
||||
wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
|
||||
wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,9 @@
|
||||
/*
|
||||
* RX Descriptor status
|
||||
*
|
||||
* Bits 0-2 - status
|
||||
* Bits 3-7 - reserved
|
||||
* Bits 0-2 - error code
|
||||
* Bits 3-5 - process_id tag (AP mode FW)
|
||||
* Bits 6-7 - reserved
|
||||
*/
|
||||
#define WL1271_RX_DESC_STATUS_MASK 0x07
|
||||
|
||||
@ -110,12 +111,16 @@ struct wl1271_rx_descriptor {
|
||||
u8 snr;
|
||||
__le32 timestamp;
|
||||
u8 packet_class;
|
||||
u8 process_id;
|
||||
union {
|
||||
u8 process_id; /* STA FW */
|
||||
u8 hlid; /* AP FW */
|
||||
} __packed;
|
||||
u8 pad_len;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
|
||||
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
|
||||
void wl1271_set_default_filters(struct wl1271 *wl);
|
||||
|
||||
#endif
|
||||
|
@ -345,3 +345,4 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL1271_FW_NAME);
|
||||
MODULE_FIRMWARE(WL1271_AP_FW_NAME);
|
||||
|
@ -110,9 +110,9 @@ static void wl1271_spi_reset(struct wl1271 *wl)
|
||||
spi_message_add_tail(&t, &m);
|
||||
|
||||
spi_sync(wl_to_spi(wl), &m);
|
||||
kfree(cmd);
|
||||
|
||||
wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
|
||||
kfree(cmd);
|
||||
}
|
||||
|
||||
static void wl1271_spi_init(struct wl1271 *wl)
|
||||
@ -495,4 +495,5 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL1271_FW_NAME);
|
||||
MODULE_FIRMWARE(WL1271_AP_FW_NAME);
|
||||
MODULE_ALIAS("spi:wl1271");
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "wl12xx.h"
|
||||
#include "io.h"
|
||||
@ -30,6 +31,23 @@
|
||||
#include "ps.h"
|
||||
#include "tx.h"
|
||||
|
||||
static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
{
|
||||
int ret;
|
||||
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
|
||||
|
||||
if (is_ap)
|
||||
ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
|
||||
else
|
||||
ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
|
||||
{
|
||||
int id;
|
||||
@ -99,7 +117,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
{
|
||||
struct timespec ts;
|
||||
struct wl1271_tx_hw_descr *desc;
|
||||
int pad, ac;
|
||||
int pad, ac, rate_idx;
|
||||
s64 hosttime;
|
||||
u16 tx_attr;
|
||||
|
||||
@ -117,7 +135,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
getnstimeofday(&ts);
|
||||
hosttime = (timespec_to_ns(&ts) >> 10);
|
||||
desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
|
||||
desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
|
||||
|
||||
if (wl->bss_type != BSS_TYPE_AP_BSS)
|
||||
desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
|
||||
else
|
||||
desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
|
||||
|
||||
/* configure the tx attributes */
|
||||
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
|
||||
@ -125,7 +147,41 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
/* queue (we use same identifiers for tid's and ac's */
|
||||
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
|
||||
desc->tid = ac;
|
||||
desc->aid = TX_HW_DEFAULT_AID;
|
||||
|
||||
if (wl->bss_type != BSS_TYPE_AP_BSS) {
|
||||
desc->aid = TX_HW_DEFAULT_AID;
|
||||
|
||||
/* if the packets are destined for AP (have a STA entry)
|
||||
send them with AP rate policies, otherwise use default
|
||||
basic rates */
|
||||
if (control->control.sta)
|
||||
rate_idx = ACX_TX_AP_FULL_RATE;
|
||||
else
|
||||
rate_idx = ACX_TX_BASIC_RATE;
|
||||
} else {
|
||||
if (control->control.sta) {
|
||||
struct wl1271_station *wl_sta;
|
||||
|
||||
wl_sta = (struct wl1271_station *)
|
||||
control->control.sta->drv_priv;
|
||||
desc->hlid = wl_sta->hlid;
|
||||
rate_idx = ac;
|
||||
} else {
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)
|
||||
(skb->data + sizeof(*desc));
|
||||
if (ieee80211_is_mgmt(hdr->frame_control)) {
|
||||
desc->hlid = WL1271_AP_GLOBAL_HLID;
|
||||
rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
|
||||
} else {
|
||||
desc->hlid = WL1271_AP_BROADCAST_HLID;
|
||||
rate_idx = ACX_TX_AP_MODE_BCST_RATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
|
||||
desc->reserved = 0;
|
||||
|
||||
/* align the length (and store in terms of words) */
|
||||
@ -136,14 +192,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
pad = pad - skb->len;
|
||||
tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
|
||||
|
||||
/* if the packets are destined for AP (have a STA entry) send them
|
||||
with AP rate policies, otherwise use default basic rates */
|
||||
if (control->control.sta)
|
||||
tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
|
||||
|
||||
desc->tx_attr = cpu_to_le16(tx_attr);
|
||||
|
||||
wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
|
||||
wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
|
||||
"tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
|
||||
le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
|
||||
le16_to_cpu(desc->life_time), desc->total_mem_blocks);
|
||||
}
|
||||
|
||||
/* caller must hold wl->mutex */
|
||||
@ -153,7 +207,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 extra = 0;
|
||||
int ret = 0;
|
||||
u8 idx;
|
||||
u32 total_len;
|
||||
|
||||
if (!skb)
|
||||
@ -166,11 +219,15 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
|
||||
extra = WL1271_TKIP_IV_SPACE;
|
||||
|
||||
if (info->control.hw_key) {
|
||||
idx = info->control.hw_key->hw_key_idx;
|
||||
bool is_wep;
|
||||
u8 idx = info->control.hw_key->hw_key_idx;
|
||||
u32 cipher = info->control.hw_key->cipher;
|
||||
|
||||
/* FIXME: do we have to do this if we're not using WEP? */
|
||||
if (unlikely(wl->default_key != idx)) {
|
||||
ret = wl1271_cmd_set_default_wep_key(wl, idx);
|
||||
is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
|
||||
(cipher == WLAN_CIPHER_SUITE_WEP104);
|
||||
|
||||
if (unlikely(is_wep && wl->default_key != idx)) {
|
||||
ret = wl1271_set_default_wep_key(wl, idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wl->default_key = idx;
|
||||
@ -303,7 +360,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
||||
woken_up = true;
|
||||
|
||||
wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
|
||||
wl1271_acx_rate_policies(wl);
|
||||
wl1271_acx_sta_rate_policies(wl);
|
||||
}
|
||||
|
||||
while ((skb = wl1271_skb_dequeue(wl))) {
|
||||
@ -521,3 +578,21 @@ void wl1271_tx_flush(struct wl1271 *wl)
|
||||
|
||||
wl1271_warning("Unable to flush all TX buffers, timed out.");
|
||||
}
|
||||
|
||||
u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
|
||||
{
|
||||
int i;
|
||||
u32 rate = 0;
|
||||
|
||||
if (!wl->basic_rate_set) {
|
||||
WARN_ON(1);
|
||||
wl->basic_rate_set = wl->conf.tx.basic_rate;
|
||||
}
|
||||
|
||||
for (i = 0; !rate; i++) {
|
||||
if ((wl->basic_rate_set >> i) & 0x1)
|
||||
rate = 1 << i;
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define TX_HW_BLOCK_SIZE 252
|
||||
|
||||
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
|
||||
#define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000
|
||||
/* The chipset reference driver states, that the "aid" value 1
|
||||
* is for infra-BSS, but is still always used */
|
||||
#define TX_HW_DEFAULT_AID 1
|
||||
@ -77,8 +78,12 @@ struct wl1271_tx_hw_descr {
|
||||
u8 id;
|
||||
/* The packet TID value (as User-Priority) */
|
||||
u8 tid;
|
||||
/* Identifier of the remote STA in IBSS, 1 in infra-BSS */
|
||||
u8 aid;
|
||||
union {
|
||||
/* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
|
||||
u8 aid;
|
||||
/* AP - host link ID (HLID) */
|
||||
u8 hlid;
|
||||
} __packed;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
@ -146,5 +151,6 @@ void wl1271_tx_reset(struct wl1271 *wl);
|
||||
void wl1271_tx_flush(struct wl1271 *wl);
|
||||
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
|
||||
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
|
||||
u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
|
||||
|
||||
#endif
|
||||
|
@ -38,6 +38,13 @@
|
||||
#define DRIVER_NAME "wl1271"
|
||||
#define DRIVER_PREFIX DRIVER_NAME ": "
|
||||
|
||||
/*
|
||||
* FW versions support BA 11n
|
||||
* versions marks x.x.x.50-60.x
|
||||
*/
|
||||
#define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50
|
||||
#define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60
|
||||
|
||||
enum {
|
||||
DEBUG_NONE = 0,
|
||||
DEBUG_IRQ = BIT(0),
|
||||
@ -57,6 +64,8 @@ enum {
|
||||
DEBUG_SDIO = BIT(14),
|
||||
DEBUG_FILTERS = BIT(15),
|
||||
DEBUG_ADHOC = BIT(16),
|
||||
DEBUG_AP = BIT(17),
|
||||
DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP),
|
||||
DEBUG_ALL = ~0,
|
||||
};
|
||||
|
||||
@ -103,16 +112,27 @@ extern u32 wl12xx_debug_level;
|
||||
true); \
|
||||
} while (0)
|
||||
|
||||
#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
|
||||
#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \
|
||||
CFG_BSSID_FILTER_EN | \
|
||||
CFG_MC_FILTER_EN)
|
||||
|
||||
#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
|
||||
#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
|
||||
CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
|
||||
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
|
||||
CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
|
||||
|
||||
#define WL1271_DEFAULT_AP_RX_CONFIG 0
|
||||
|
||||
#define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
|
||||
CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
|
||||
CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
|
||||
CFG_RX_ASSOC_EN)
|
||||
|
||||
|
||||
|
||||
#define WL1271_FW_NAME "wl1271-fw.bin"
|
||||
#define WL1271_AP_FW_NAME "wl1271-fw-ap.bin"
|
||||
|
||||
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
||||
|
||||
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
|
||||
@ -129,6 +149,14 @@ extern u32 wl12xx_debug_level;
|
||||
#define WL1271_DEFAULT_BEACON_INT 100
|
||||
#define WL1271_DEFAULT_DTIM_PERIOD 1
|
||||
|
||||
#define WL1271_AP_GLOBAL_HLID 0
|
||||
#define WL1271_AP_BROADCAST_HLID 1
|
||||
#define WL1271_AP_STA_HLID_START 2
|
||||
|
||||
#define WL1271_AP_BSS_INDEX 0
|
||||
#define WL1271_AP_DEF_INACTIV_SEC 300
|
||||
#define WL1271_AP_DEF_BEACON_EXP 20
|
||||
|
||||
#define ACX_TX_DESCRIPTORS 32
|
||||
|
||||
#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
|
||||
@ -161,10 +189,13 @@ struct wl1271_partition_set {
|
||||
|
||||
struct wl1271;
|
||||
|
||||
#define WL12XX_NUM_FW_VER 5
|
||||
|
||||
/* FIXME: I'm not sure about this structure name */
|
||||
struct wl1271_chip {
|
||||
u32 id;
|
||||
char fw_ver[21];
|
||||
char fw_ver_str[ETHTOOL_BUSINFO_LEN];
|
||||
unsigned int fw_ver[WL12XX_NUM_FW_VER];
|
||||
};
|
||||
|
||||
struct wl1271_stats {
|
||||
@ -178,6 +209,11 @@ struct wl1271_stats {
|
||||
#define NUM_TX_QUEUES 4
|
||||
#define NUM_RX_PKT_DESC 8
|
||||
|
||||
#define AP_MAX_STATIONS 5
|
||||
|
||||
/* Broadcast and Global links + links to stations */
|
||||
#define AP_MAX_LINKS (AP_MAX_STATIONS + 2)
|
||||
|
||||
/* FW status registers */
|
||||
struct wl1271_fw_status {
|
||||
__le32 intr;
|
||||
@ -188,7 +224,18 @@ struct wl1271_fw_status {
|
||||
__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
|
||||
__le32 tx_released_blks[NUM_TX_QUEUES];
|
||||
__le32 fw_localtime;
|
||||
__le32 padding[2];
|
||||
|
||||
/* Next fields valid only in AP FW */
|
||||
|
||||
/*
|
||||
* A bitmap (where each bit represents a single HLID)
|
||||
* to indicate if the station is in PS mode.
|
||||
*/
|
||||
__le32 link_ps_bitmap;
|
||||
|
||||
/* Number of freed MBs per HLID */
|
||||
u8 tx_lnk_free_blks[AP_MAX_LINKS];
|
||||
u8 padding_1[1];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_rx_mem_pool_addr {
|
||||
@ -218,6 +265,19 @@ struct wl1271_if_operations {
|
||||
void (*disable_irq)(struct wl1271 *wl);
|
||||
};
|
||||
|
||||
#define MAX_NUM_KEYS 14
|
||||
#define MAX_KEY_SIZE 32
|
||||
|
||||
struct wl1271_ap_key {
|
||||
u8 id;
|
||||
u8 key_type;
|
||||
u8 key_size;
|
||||
u8 key[MAX_KEY_SIZE];
|
||||
u8 hlid;
|
||||
u32 tx_seq_32;
|
||||
u16 tx_seq_16;
|
||||
};
|
||||
|
||||
struct wl1271 {
|
||||
struct platform_device *plat_dev;
|
||||
struct ieee80211_hw *hw;
|
||||
@ -251,6 +311,7 @@ struct wl1271 {
|
||||
#define WL1271_FLAG_PSPOLL_FAILURE (12)
|
||||
#define WL1271_FLAG_STA_STATE_SENT (13)
|
||||
#define WL1271_FLAG_FW_TX_BUSY (14)
|
||||
#define WL1271_FLAG_AP_STARTED (15)
|
||||
unsigned long flags;
|
||||
|
||||
struct wl1271_partition_set part;
|
||||
@ -262,6 +323,7 @@ struct wl1271 {
|
||||
|
||||
u8 *fw;
|
||||
size_t fw_len;
|
||||
u8 fw_bss_type;
|
||||
struct wl1271_nvs_file *nvs;
|
||||
size_t nvs_len;
|
||||
|
||||
@ -378,7 +440,6 @@ struct wl1271 {
|
||||
int last_rssi_event;
|
||||
|
||||
struct wl1271_stats stats;
|
||||
struct dentry *rootdir;
|
||||
|
||||
__le32 buffer_32;
|
||||
u32 buffer_cmd;
|
||||
@ -400,6 +461,23 @@ struct wl1271 {
|
||||
|
||||
/* Most recently reported noise in dBm */
|
||||
s8 noise;
|
||||
|
||||
/* map for HLIDs of associated stations - when operating in AP mode */
|
||||
unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)];
|
||||
|
||||
/* recoreded keys for AP-mode - set here before AP startup */
|
||||
struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS];
|
||||
|
||||
/* bands supported by this instance of wl12xx */
|
||||
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
|
||||
|
||||
/* RX BA constraint value */
|
||||
bool ba_support;
|
||||
u8 ba_rx_bitmap;
|
||||
};
|
||||
|
||||
struct wl1271_station {
|
||||
u8 hlid;
|
||||
};
|
||||
|
||||
int wl1271_plt_start(struct wl1271 *wl);
|
||||
|
@ -138,13 +138,13 @@ struct wl12xx_arp_rsp_template {
|
||||
struct ieee80211_hdr_3addr hdr;
|
||||
|
||||
u8 llc_hdr[sizeof(rfc1042_header)];
|
||||
u16 llc_type;
|
||||
__be16 llc_type;
|
||||
|
||||
struct arphdr arp_hdr;
|
||||
u8 sender_hw[ETH_ALEN];
|
||||
u32 sender_ip;
|
||||
__be32 sender_ip;
|
||||
u8 target_hw[ETH_ALEN];
|
||||
u32 target_ip;
|
||||
__be32 target_ip;
|
||||
} __packed;
|
||||
|
||||
|
||||
@ -160,4 +160,9 @@ struct wl12xx_probe_resp_template {
|
||||
struct wl12xx_ie_country country;
|
||||
} __packed;
|
||||
|
||||
struct wl12xx_disconn_template {
|
||||
struct ieee80211_header header;
|
||||
__le16 disconn_reason;
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user