mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
This commit is contained in:
commit
890641b251
|
@ -325,12 +325,19 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
|
||||
int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
|
||||
{
|
||||
struct acx_rts_threshold *rts;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx rts threshold");
|
||||
/*
|
||||
* If the RTS threshold is not configured or out of range, use the
|
||||
* default value.
|
||||
*/
|
||||
if (rts_threshold > IEEE80211_MAX_RTS_THRESHOLD)
|
||||
rts_threshold = wl->conf.rx.rts_threshold;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx rts threshold: %d", rts_threshold);
|
||||
|
||||
rts = kzalloc(sizeof(*rts), GFP_KERNEL);
|
||||
if (!rts) {
|
||||
|
@ -338,7 +345,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
|
|||
goto out;
|
||||
}
|
||||
|
||||
rts->threshold = cpu_to_le16(rts_threshold);
|
||||
rts->threshold = cpu_to_le16((u16)rts_threshold);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
|
||||
if (ret < 0) {
|
||||
|
@ -540,13 +547,13 @@ int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_sg_cfg(struct wl1271 *wl)
|
||||
int wl1271_acx_sta_sg_cfg(struct wl1271 *wl)
|
||||
{
|
||||
struct acx_bt_wlan_coex_param *param;
|
||||
struct acx_sta_bt_wlan_coex_param *param;
|
||||
struct conf_sg_settings *c = &wl->conf.sg;
|
||||
int i, ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx sg cfg");
|
||||
wl1271_debug(DEBUG_ACX, "acx sg sta cfg");
|
||||
|
||||
param = kzalloc(sizeof(*param), GFP_KERNEL);
|
||||
if (!param) {
|
||||
|
@ -555,8 +562,38 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
|
|||
}
|
||||
|
||||
/* BT-WLAN coext parameters */
|
||||
for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
|
||||
param->params[i] = cpu_to_le32(c->params[i]);
|
||||
for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++)
|
||||
param->params[i] = cpu_to_le32(c->sta_params[i]);
|
||||
param->param_idx = CONF_SG_PARAMS_ALL;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("failed to set sg config: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(param);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
|
||||
{
|
||||
struct acx_ap_bt_wlan_coex_param *param;
|
||||
struct conf_sg_settings *c = &wl->conf.sg;
|
||||
int i, ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx sg ap cfg");
|
||||
|
||||
param = kzalloc(sizeof(*param), GFP_KERNEL);
|
||||
if (!param) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* BT-WLAN coext parameters */
|
||||
for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++)
|
||||
param->params[i] = cpu_to_le32(c->ap_params[i]);
|
||||
param->param_idx = CONF_SG_PARAMS_ALL;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
|
||||
|
@ -804,7 +841,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
|
|||
struct acx_ap_rate_policy *acx;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ap rate policy");
|
||||
wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x",
|
||||
idx, c->enabled_rates);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
|
@ -898,12 +936,19 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold)
|
||||
int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold)
|
||||
{
|
||||
struct acx_frag_threshold *acx;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx frag threshold");
|
||||
/*
|
||||
* If the fragmentation is not configured or out of range, use the
|
||||
* default value.
|
||||
*/
|
||||
if (frag_threshold > IEEE80211_MAX_FRAG_THRESHOLD)
|
||||
frag_threshold = wl->conf.tx.frag_threshold;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx frag threshold: %d", frag_threshold);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
|
||||
|
@ -912,7 +957,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold)
|
|||
goto out;
|
||||
}
|
||||
|
||||
acx->frag_threshold = cpu_to_le16(frag_threshold);
|
||||
acx->frag_threshold = cpu_to_le16((u16)frag_threshold);
|
||||
ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Setting of frag threshold failed: %d", ret);
|
||||
|
@ -954,6 +999,7 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl)
|
|||
int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_ap_config_memory *mem_conf;
|
||||
struct conf_memory_settings *mem;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
|
||||
|
@ -964,14 +1010,21 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (wl->chip.id == CHIP_ID_1283_PG20)
|
||||
/*
|
||||
* FIXME: The 128x AP FW does not yet support dynamic memory.
|
||||
* Use the base memory configuration for 128x for now. This
|
||||
* should be fine tuned in the future.
|
||||
*/
|
||||
mem = &wl->conf.mem_wl128x;
|
||||
else
|
||||
mem = &wl->conf.mem_wl127x;
|
||||
|
||||
/* memory config */
|
||||
/* FIXME: for now we always use mem_wl127x for AP, because it
|
||||
* doesn't support dynamic memory and we don't have the
|
||||
* optimal values for wl128x without dynamic memory yet */
|
||||
mem_conf->num_stations = wl->conf.mem_wl127x.num_stations;
|
||||
mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num;
|
||||
mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num;
|
||||
mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles;
|
||||
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);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
|
||||
|
@ -1524,46 +1577,22 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
|
||||
int wl1271_acx_max_tx_retry(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_ap_max_tx_retry *acx = NULL;
|
||||
struct wl1271_acx_max_tx_retry *acx = NULL;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx ap max tx retry");
|
||||
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.max_tx_retries);
|
||||
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 ap max tx retry failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_sta_max_tx_retry *acx = NULL;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx sta max tx retry");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx)
|
||||
return -ENOMEM;
|
||||
|
||||
acx->max_tx_retry = wl->conf.tx.max_tx_retries;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx sta max tx retry failed: %d", ret);
|
||||
wl1271_warning("acx max tx retry failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1626,3 +1655,68 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr)
|
|||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable)
|
||||
{
|
||||
struct acx_ap_beacon_filter *acx = NULL;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx)
|
||||
return -ENOMEM;
|
||||
|
||||
acx->enable = enable ? 1 : 0;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT,
|
||||
acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx set ap beacon filter failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_fm_coex(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_fm_coex *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx fm coex setting");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->enable = wl->conf.fm_coex.enable;
|
||||
acx->swallow_period = wl->conf.fm_coex.swallow_period;
|
||||
acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1;
|
||||
acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2;
|
||||
acx->m_divider_fref_set_1 =
|
||||
cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1);
|
||||
acx->m_divider_fref_set_2 =
|
||||
cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2);
|
||||
acx->coex_pll_stabilization_time =
|
||||
cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time);
|
||||
acx->ldo_stabilization_time =
|
||||
cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time);
|
||||
acx->fm_disturbed_band_margin =
|
||||
wl->conf.fm_coex.fm_disturbed_band_margin;
|
||||
acx->swallow_clk_diff = wl->conf.fm_coex.swallow_clk_diff;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_FM_COEX_CFG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx fm coex setting failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -303,7 +303,6 @@ struct acx_beacon_filter_option {
|
|||
struct acx_header header;
|
||||
|
||||
u8 enable;
|
||||
|
||||
/*
|
||||
* The number of beacons without the unicast TIM
|
||||
* bit set that the firmware buffers before
|
||||
|
@ -370,14 +369,23 @@ struct acx_bt_wlan_coex {
|
|||
u8 pad[3];
|
||||
} __packed;
|
||||
|
||||
struct acx_bt_wlan_coex_param {
|
||||
struct acx_sta_bt_wlan_coex_param {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 params[CONF_SG_PARAMS_MAX];
|
||||
__le32 params[CONF_SG_STA_PARAMS_MAX];
|
||||
u8 param_idx;
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
struct acx_ap_bt_wlan_coex_param {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 params[CONF_SG_AP_PARAMS_MAX];
|
||||
u8 param_idx;
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
|
||||
struct acx_dco_itrim_params {
|
||||
struct acx_header header;
|
||||
|
||||
|
@ -1145,7 +1153,7 @@ struct wl1271_acx_fw_tsf_information {
|
|||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_ap_max_tx_retry {
|
||||
struct wl1271_acx_max_tx_retry {
|
||||
struct acx_header header;
|
||||
|
||||
/*
|
||||
|
@ -1156,13 +1164,6 @@ struct wl1271_acx_ap_max_tx_retry {
|
|||
u8 padding_1[2];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_sta_max_tx_retry {
|
||||
struct acx_header header;
|
||||
|
||||
u8 max_tx_retry;
|
||||
u8 padding_1[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_config_ps {
|
||||
struct acx_header header;
|
||||
|
||||
|
@ -1179,6 +1180,72 @@ struct wl1271_acx_inconnection_sta {
|
|||
u8 padding1[2];
|
||||
} __packed;
|
||||
|
||||
struct acx_ap_beacon_filter {
|
||||
struct acx_header header;
|
||||
|
||||
u8 enable;
|
||||
u8 pad[3];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* ACX_FM_COEX_CFG
|
||||
* set the FM co-existence parameters.
|
||||
*/
|
||||
struct wl1271_acx_fm_coex {
|
||||
struct acx_header header;
|
||||
/* enable(1) / disable(0) the FM Coex feature */
|
||||
u8 enable;
|
||||
/*
|
||||
* Swallow period used in COEX PLL swallowing mechanism.
|
||||
* 0xFF = use FW default
|
||||
*/
|
||||
u8 swallow_period;
|
||||
/*
|
||||
* The N divider used in COEX PLL swallowing mechanism for Fref of
|
||||
* 38.4/19.2 Mhz. 0xFF = use FW default
|
||||
*/
|
||||
u8 n_divider_fref_set_1;
|
||||
/*
|
||||
* The N divider used in COEX PLL swallowing mechanism for Fref of
|
||||
* 26/52 Mhz. 0xFF = use FW default
|
||||
*/
|
||||
u8 n_divider_fref_set_2;
|
||||
/*
|
||||
* The M divider used in COEX PLL swallowing mechanism for Fref of
|
||||
* 38.4/19.2 Mhz. 0xFFFF = use FW default
|
||||
*/
|
||||
__le16 m_divider_fref_set_1;
|
||||
/*
|
||||
* The M divider used in COEX PLL swallowing mechanism for Fref of
|
||||
* 26/52 Mhz. 0xFFFF = use FW default
|
||||
*/
|
||||
__le16 m_divider_fref_set_2;
|
||||
/*
|
||||
* The time duration in uSec required for COEX PLL to stabilize.
|
||||
* 0xFFFFFFFF = use FW default
|
||||
*/
|
||||
__le32 coex_pll_stabilization_time;
|
||||
/*
|
||||
* The time duration in uSec required for LDO to stabilize.
|
||||
* 0xFFFFFFFF = use FW default
|
||||
*/
|
||||
__le16 ldo_stabilization_time;
|
||||
/*
|
||||
* The disturbed frequency band margin around the disturbed frequency
|
||||
* center (single sided).
|
||||
* For example, if 2 is configured, the following channels will be
|
||||
* considered disturbed channel:
|
||||
* 80 +- 0.1 MHz, 91 +- 0.1 MHz, 98 +- 0.1 MHz, 102 +- 0.1 MH
|
||||
* 0xFF = use FW default
|
||||
*/
|
||||
u8 fm_disturbed_band_margin;
|
||||
/*
|
||||
* The swallow clock difference of the swallowing mechanism.
|
||||
* 0xFF = use FW default
|
||||
*/
|
||||
u8 swallow_clk_diff;
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
||||
ACX_MEM_CFG = 0x0003,
|
||||
|
@ -1197,6 +1264,7 @@ enum {
|
|||
ACX_TID_CFG = 0x001A,
|
||||
ACX_PS_RX_STREAMING = 0x001B,
|
||||
ACX_BEACON_FILTER_OPT = 0x001F,
|
||||
ACX_AP_BEACON_FILTER_OPT = 0x0020,
|
||||
ACX_NOISE_HIST = 0x0021,
|
||||
ACX_HDK_VERSION = 0x0022, /* ??? */
|
||||
ACX_PD_THRESHOLD = 0x0023,
|
||||
|
@ -1208,6 +1276,7 @@ enum {
|
|||
ACX_BCN_DTIM_OPTIONS = 0x0031,
|
||||
ACX_SG_ENABLE = 0x0032,
|
||||
ACX_SG_CFG = 0x0033,
|
||||
ACX_FM_COEX_CFG = 0x0034,
|
||||
ACX_BEACON_FILTER_TABLE = 0x0038,
|
||||
ACX_ARP_IP_FILTER = 0x0039,
|
||||
ACX_ROAMING_STATISTICS_TBL = 0x003B,
|
||||
|
@ -1264,13 +1333,14 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
|
|||
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
|
||||
void *mc_list, u32 mc_list_len);
|
||||
int wl1271_acx_service_period_timeout(struct wl1271 *wl);
|
||||
int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
|
||||
int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold);
|
||||
int wl1271_acx_dco_itrim_params(struct wl1271 *wl);
|
||||
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
|
||||
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
|
||||
int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable);
|
||||
int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
|
||||
int wl1271_acx_sg_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_sta_sg_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_ap_sg_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_cca_threshold(struct wl1271 *wl);
|
||||
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
|
||||
int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
|
||||
|
@ -1287,7 +1357,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
|
|||
int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
|
||||
u8 tsid, u8 ps_scheme, u8 ack_policy,
|
||||
u32 apsd_conf0, u32 apsd_conf1);
|
||||
int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold);
|
||||
int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
|
||||
int wl1271_acx_tx_config_options(struct wl1271 *wl);
|
||||
int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
|
||||
|
@ -1314,9 +1384,10 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
|
|||
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_ap_max_tx_retry(struct wl1271 *wl);
|
||||
int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl);
|
||||
int wl1271_acx_max_tx_retry(struct wl1271 *wl);
|
||||
int wl1271_acx_config_ps(struct wl1271 *wl);
|
||||
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
|
||||
int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
|
||||
int wl1271_acx_fm_coex(struct wl1271 *wl);
|
||||
|
||||
#endif /* __WL1271_ACX_H__ */
|
||||
|
|
|
@ -478,12 +478,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
|||
DISCONNECT_EVENT_COMPLETE_ID |
|
||||
RSSI_SNR_TRIGGER_0_EVENT_ID |
|
||||
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
|
||||
SOFT_GEMINI_SENSE_EVENT_ID |
|
||||
MAX_TX_RETRY_EVENT_ID;
|
||||
SOFT_GEMINI_SENSE_EVENT_ID;
|
||||
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
|
||||
INACTIVE_STA_EVENT_ID;
|
||||
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
|
||||
else
|
||||
wl->event_mask |= DUMMY_PACKET_EVENT_ID;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
|||
if (time_after(jiffies, timeout)) {
|
||||
wl1271_error("command complete timeout");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
poll_count++;
|
||||
|
@ -96,14 +96,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
|||
status = le16_to_cpu(cmd->status);
|
||||
if (status != CMD_STATUS_SUCCESS) {
|
||||
wl1271_error("command execute failure %d", status);
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
|
||||
WL1271_ACX_INTR_CMD_COMPLETE);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
fail:
|
||||
WARN_ON(1);
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -129,6 +132,9 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
|
|||
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");
|
||||
|
@ -168,6 +174,10 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
|
|||
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");
|
||||
|
@ -1070,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)
|
|||
|
||||
memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
|
||||
cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
|
||||
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;
|
||||
|
|
|
@ -396,12 +396,43 @@ enum {
|
|||
CONF_SG_TEMP_PARAM_3,
|
||||
CONF_SG_TEMP_PARAM_4,
|
||||
CONF_SG_TEMP_PARAM_5,
|
||||
CONF_SG_PARAMS_MAX,
|
||||
|
||||
/*
|
||||
* AP beacon miss
|
||||
*
|
||||
* Range: 0 - 255
|
||||
*/
|
||||
CONF_SG_AP_BEACON_MISS_TX,
|
||||
|
||||
/*
|
||||
* AP RX window length
|
||||
*
|
||||
* Range: 0 - 50
|
||||
*/
|
||||
CONF_SG_RX_WINDOW_LENGTH,
|
||||
|
||||
/*
|
||||
* AP connection protection time
|
||||
*
|
||||
* Range: 0 - 5000
|
||||
*/
|
||||
CONF_SG_AP_CONNECTION_PROTECTION_TIME,
|
||||
|
||||
CONF_SG_TEMP_PARAM_6,
|
||||
CONF_SG_TEMP_PARAM_7,
|
||||
CONF_SG_TEMP_PARAM_8,
|
||||
CONF_SG_TEMP_PARAM_9,
|
||||
CONF_SG_TEMP_PARAM_10,
|
||||
|
||||
CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1,
|
||||
CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1,
|
||||
|
||||
CONF_SG_PARAMS_ALL = 0xff
|
||||
};
|
||||
|
||||
struct conf_sg_settings {
|
||||
u32 params[CONF_SG_PARAMS_MAX];
|
||||
u32 sta_params[CONF_SG_STA_PARAMS_MAX];
|
||||
u32 ap_params[CONF_SG_AP_PARAMS_MAX];
|
||||
u8 state;
|
||||
};
|
||||
|
||||
|
@ -509,6 +540,12 @@ struct conf_rx_settings {
|
|||
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
|
||||
CONF_HW_BIT_RATE_54MBPS)
|
||||
|
||||
#define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \
|
||||
CONF_HW_BIT_RATE_12MBPS | 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
|
||||
|
@ -516,6 +553,13 @@ struct conf_rx_settings {
|
|||
#define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
|
||||
|
||||
/*
|
||||
* Default rates for working as IBSS. use 11b rates
|
||||
*/
|
||||
#define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
|
||||
CONF_HW_BIT_RATE_11MBPS);
|
||||
|
||||
struct conf_tx_rate_class {
|
||||
|
||||
/*
|
||||
|
@ -667,34 +711,10 @@ struct conf_tx_settings {
|
|||
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;
|
||||
|
||||
/*
|
||||
* Allow this number of TX retries to a connected station/AP before an
|
||||
* AP-mode - allow this number of TX retries to a station before an
|
||||
* event is triggered from FW.
|
||||
* In AP-mode the hlids of unreachable stations are given in the
|
||||
* "sta_tx_retry_exceeded" member in the event mailbox.
|
||||
*/
|
||||
u8 max_tx_retries;
|
||||
|
||||
/*
|
||||
* AP-mode - after this number of seconds a connected station is
|
||||
* considered inactive.
|
||||
*/
|
||||
u16 ap_aging_period;
|
||||
u16 ap_max_tx_retries;
|
||||
|
||||
/*
|
||||
* Configuration for TID parameters.
|
||||
|
@ -1192,6 +1212,19 @@ struct conf_memory_settings {
|
|||
u8 tx_min;
|
||||
};
|
||||
|
||||
struct conf_fm_coex {
|
||||
u8 enable;
|
||||
u8 swallow_period;
|
||||
u8 n_divider_fref_set_1;
|
||||
u8 n_divider_fref_set_2;
|
||||
u16 m_divider_fref_set_1;
|
||||
u16 m_divider_fref_set_2;
|
||||
u32 coex_pll_stabilization_time;
|
||||
u16 ldo_stabilization_time;
|
||||
u8 fm_disturbed_band_margin;
|
||||
u8 swallow_clk_diff;
|
||||
};
|
||||
|
||||
struct conf_drv_settings {
|
||||
struct conf_sg_settings sg;
|
||||
struct conf_rx_settings rx;
|
||||
|
@ -1205,6 +1238,7 @@ struct conf_drv_settings {
|
|||
struct conf_ht_setting ht;
|
||||
struct conf_memory_settings mem_wl127x;
|
||||
struct conf_memory_settings mem_wl128x;
|
||||
struct conf_fm_coex fm_coex;
|
||||
u8 hci_io_ds;
|
||||
};
|
||||
|
||||
|
|
|
@ -291,6 +291,241 @@ static const struct file_operations gpio_power_ops = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t start_recovery_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations start_recovery_ops = {
|
||||
.write = start_recovery_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t driver_state_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
int res = 0;
|
||||
char buf[1024];
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
#define DRIVER_STATE_PRINT(x, fmt) \
|
||||
(res += scnprintf(buf + res, sizeof(buf) - res,\
|
||||
#x " = " fmt "\n", wl->x))
|
||||
|
||||
#define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld")
|
||||
#define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d")
|
||||
#define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s")
|
||||
#define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
|
||||
#define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x")
|
||||
|
||||
DRIVER_STATE_PRINT_INT(tx_blocks_available);
|
||||
DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
|
||||
DRIVER_STATE_PRINT_INT(tx_frames_cnt);
|
||||
DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
|
||||
DRIVER_STATE_PRINT_INT(tx_queue_count);
|
||||
DRIVER_STATE_PRINT_INT(tx_packets_count);
|
||||
DRIVER_STATE_PRINT_INT(tx_results_count);
|
||||
DRIVER_STATE_PRINT_LHEX(flags);
|
||||
DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]);
|
||||
DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);
|
||||
DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);
|
||||
DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]);
|
||||
DRIVER_STATE_PRINT_INT(tx_security_last_seq);
|
||||
DRIVER_STATE_PRINT_INT(rx_counter);
|
||||
DRIVER_STATE_PRINT_INT(session_counter);
|
||||
DRIVER_STATE_PRINT_INT(state);
|
||||
DRIVER_STATE_PRINT_INT(bss_type);
|
||||
DRIVER_STATE_PRINT_INT(channel);
|
||||
DRIVER_STATE_PRINT_HEX(rate_set);
|
||||
DRIVER_STATE_PRINT_HEX(basic_rate_set);
|
||||
DRIVER_STATE_PRINT_HEX(basic_rate);
|
||||
DRIVER_STATE_PRINT_INT(band);
|
||||
DRIVER_STATE_PRINT_INT(beacon_int);
|
||||
DRIVER_STATE_PRINT_INT(psm_entry_retry);
|
||||
DRIVER_STATE_PRINT_INT(ps_poll_failures);
|
||||
DRIVER_STATE_PRINT_HEX(filters);
|
||||
DRIVER_STATE_PRINT_HEX(rx_config);
|
||||
DRIVER_STATE_PRINT_HEX(rx_filter);
|
||||
DRIVER_STATE_PRINT_INT(power_level);
|
||||
DRIVER_STATE_PRINT_INT(rssi_thold);
|
||||
DRIVER_STATE_PRINT_INT(last_rssi_event);
|
||||
DRIVER_STATE_PRINT_INT(sg_enabled);
|
||||
DRIVER_STATE_PRINT_INT(enable_11a);
|
||||
DRIVER_STATE_PRINT_INT(noise);
|
||||
DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]);
|
||||
DRIVER_STATE_PRINT_INT(last_tx_hlid);
|
||||
DRIVER_STATE_PRINT_INT(ba_support);
|
||||
DRIVER_STATE_PRINT_HEX(ba_rx_bitmap);
|
||||
DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
|
||||
DRIVER_STATE_PRINT_LHEX(ap_ps_map);
|
||||
DRIVER_STATE_PRINT_HEX(quirks);
|
||||
DRIVER_STATE_PRINT_HEX(irq);
|
||||
DRIVER_STATE_PRINT_HEX(ref_clock);
|
||||
DRIVER_STATE_PRINT_HEX(tcxo_clock);
|
||||
DRIVER_STATE_PRINT_HEX(hw_pg_ver);
|
||||
DRIVER_STATE_PRINT_HEX(platform_quirks);
|
||||
DRIVER_STATE_PRINT_HEX(chip.id);
|
||||
DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
|
||||
|
||||
#undef DRIVER_STATE_PRINT_INT
|
||||
#undef DRIVER_STATE_PRINT_LONG
|
||||
#undef DRIVER_STATE_PRINT_HEX
|
||||
#undef DRIVER_STATE_PRINT_LHEX
|
||||
#undef DRIVER_STATE_PRINT_STR
|
||||
#undef DRIVER_STATE_PRINT
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, res);
|
||||
}
|
||||
|
||||
static const struct file_operations driver_state_ops = {
|
||||
.read = driver_state_read,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t dtim_interval_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
u8 value;
|
||||
|
||||
if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
|
||||
wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
|
||||
value = wl->conf.conn.listen_interval;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
|
||||
}
|
||||
|
||||
static ssize_t dtim_interval_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
char buf[10];
|
||||
size_t len;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
buf[len] = '\0';
|
||||
|
||||
ret = kstrtoul(buf, 0, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value for dtim_interval");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value < 1 || value > 10) {
|
||||
wl1271_warning("dtim value is not in valid range");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
wl->conf.conn.listen_interval = value;
|
||||
/* for some reason there are different event types for 1 and >1 */
|
||||
if (value == 1)
|
||||
wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
|
||||
else
|
||||
wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
|
||||
|
||||
/*
|
||||
* we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
|
||||
* take effect on the next time we enter psm.
|
||||
*/
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations dtim_interval_ops = {
|
||||
.read = dtim_interval_read,
|
||||
.write = dtim_interval_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t beacon_interval_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
u8 value;
|
||||
|
||||
if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON ||
|
||||
wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS)
|
||||
value = wl->conf.conn.listen_interval;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
|
||||
}
|
||||
|
||||
static ssize_t beacon_interval_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
char buf[10];
|
||||
size_t len;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
buf[len] = '\0';
|
||||
|
||||
ret = kstrtoul(buf, 0, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value for beacon_interval");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value < 1 || value > 255) {
|
||||
wl1271_warning("beacon interval value is not in valid range");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
wl->conf.conn.listen_interval = value;
|
||||
/* for some reason there are different event types for 1 and >1 */
|
||||
if (value == 1)
|
||||
wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON;
|
||||
else
|
||||
wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS;
|
||||
|
||||
/*
|
||||
* we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
|
||||
* take effect on the next time we enter psm.
|
||||
*/
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations beacon_interval_ops = {
|
||||
.read = beacon_interval_read,
|
||||
.write = beacon_interval_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int wl1271_debugfs_add_files(struct wl1271 *wl,
|
||||
struct dentry *rootdir)
|
||||
{
|
||||
|
@ -399,6 +634,10 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
|
|||
DEBUGFS_ADD(excessive_retries, rootdir);
|
||||
|
||||
DEBUGFS_ADD(gpio_power, rootdir);
|
||||
DEBUGFS_ADD(start_recovery, rootdir);
|
||||
DEBUGFS_ADD(driver_state, rootdir);
|
||||
DEBUGFS_ADD(dtim_interval, rootdir);
|
||||
DEBUGFS_ADD(beacon_interval, rootdir);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -174,8 +174,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
|||
u32 vector;
|
||||
bool beacon_loss = false;
|
||||
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
|
||||
bool disconnect_sta = false;
|
||||
unsigned long sta_bitmap = 0;
|
||||
|
||||
wl1271_event_mbox_dump(mbox);
|
||||
|
||||
|
@ -237,54 +235,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
|||
wl1271_tx_dummy_packet(wl);
|
||||
}
|
||||
|
||||
/*
|
||||
* "TX retries exceeded" has a different meaning according to mode.
|
||||
* In AP mode the offending station is disconnected. In STA mode we
|
||||
* report connection loss.
|
||||
*/
|
||||
if (vector & MAX_TX_RETRY_EVENT_ID) {
|
||||
wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
|
||||
if (is_ap) {
|
||||
sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
|
||||
disconnect_sta = true;
|
||||
} else {
|
||||
beacon_loss = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
|
||||
wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
|
||||
sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
|
||||
disconnect_sta = true;
|
||||
}
|
||||
|
||||
if (wl->vif && beacon_loss)
|
||||
ieee80211_connection_loss(wl->vif);
|
||||
|
||||
if (is_ap && disconnect_sta) {
|
||||
u32 num_packets = wl->conf.tx.max_tx_retries;
|
||||
struct ieee80211_sta *sta;
|
||||
const u8 *addr;
|
||||
int h;
|
||||
|
||||
for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
|
||||
h < AP_MAX_LINKS;
|
||||
h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
|
||||
if (!wl1271_is_active_sta(wl, h))
|
||||
continue;
|
||||
|
||||
addr = wl->links[h].addr;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(wl->vif, addr);
|
||||
if (sta) {
|
||||
wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
|
||||
ieee80211_report_low_ack(sta, num_packets);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,16 +58,13 @@ enum {
|
|||
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
|
||||
BSS_LOSE_EVENT_ID = BIT(18),
|
||||
REGAINED_BSS_EVENT_ID = BIT(19),
|
||||
MAX_TX_RETRY_EVENT_ID = BIT(20),
|
||||
ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
|
||||
/* STA: dummy paket for dynamic mem blocks */
|
||||
DUMMY_PACKET_EVENT_ID = BIT(21),
|
||||
/* AP: STA remove complete */
|
||||
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
|
||||
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
|
||||
/* STA: SG prediction */
|
||||
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
|
||||
/* AP: Inactive STA */
|
||||
INACTIVE_STA_EVENT_ID = BIT(23),
|
||||
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
|
||||
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
|
||||
DBG_EVENT_ID = BIT(26),
|
||||
|
@ -122,11 +119,7 @@ struct event_mailbox {
|
|||
|
||||
/* AP FW only */
|
||||
u8 hlid_removed;
|
||||
|
||||
/* a bitmap of hlids for stations that have been inactive too long */
|
||||
__le16 sta_aging_status;
|
||||
|
||||
/* a bitmap of hlids for stations which didn't respond to TX */
|
||||
__le16 sta_tx_retry_exceeded;
|
||||
|
||||
u8 reserved_5[24];
|
||||
|
@ -137,7 +130,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
|
|||
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
|
||||
void wl1271_pspoll_work(struct work_struct *work);
|
||||
|
||||
/* Functions from main.c */
|
||||
bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -258,7 +258,7 @@ int wl1271_init_phy_config(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
|
||||
ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -285,7 +285,10 @@ int wl1271_init_pta(struct wl1271 *wl)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = wl1271_acx_sg_cfg(wl);
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||
ret = wl1271_acx_ap_sg_cfg(wl);
|
||||
else
|
||||
ret = wl1271_acx_sta_sg_cfg(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -351,8 +354,8 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Bluetooth WLAN coexistence */
|
||||
ret = wl1271_init_pta(wl);
|
||||
/* FM WLAN coexistence */
|
||||
ret = wl1271_acx_fm_coex(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -375,10 +378,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_sta_max_tx_retry(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_sta_mem_cfg(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -414,7 +413,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
|
|||
|
||||
static int wl1271_ap_hw_init(struct wl1271 *wl)
|
||||
{
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
ret = wl1271_ap_init_templates_config(wl);
|
||||
if (ret < 0)
|
||||
|
@ -425,27 +424,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
|
|||
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);
|
||||
ret = wl1271_init_ap_rates(wl);
|
||||
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_ap_max_tx_retry(wl);
|
||||
ret = wl1271_acx_max_tx_retry(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -456,7 +439,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
|
||||
int wl1271_ap_init_templates(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -472,6 +455,70 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* when operating as AP we want to receive external beacons for
|
||||
* configuring ERP protection.
|
||||
*/
|
||||
ret = wl1271_acx_set_ap_beacon_filter(wl, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
|
||||
{
|
||||
return wl1271_ap_init_templates(wl);
|
||||
}
|
||||
|
||||
int wl1271_init_ap_rates(struct wl1271 *wl)
|
||||
{
|
||||
int i, ret;
|
||||
struct conf_tx_rate_class rc;
|
||||
u32 supported_rates;
|
||||
|
||||
wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set);
|
||||
|
||||
if (wl->basic_rate_set == 0)
|
||||
return -EINVAL;
|
||||
|
||||
rc.enabled_rates = wl->basic_rate_set;
|
||||
rc.long_retry_limit = 10;
|
||||
rc.short_retry_limit = 10;
|
||||
rc.aflags = 0;
|
||||
ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* use the min basic rate for AP broadcast/multicast */
|
||||
rc.enabled_rates = wl1271_tx_min_rate_get(wl);
|
||||
rc.short_retry_limit = 10;
|
||||
rc.long_retry_limit = 10;
|
||||
rc.aflags = 0;
|
||||
ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If the basic rates contain OFDM rates, use OFDM only
|
||||
* rates for unicast TX as well. Else use all supported rates.
|
||||
*/
|
||||
if ((wl->basic_rate_set & CONF_TX_OFDM_RATES))
|
||||
supported_rates = CONF_TX_OFDM_RATES;
|
||||
else
|
||||
supported_rates = CONF_TX_AP_ENABLED_RATES;
|
||||
|
||||
/* configure unicast TX rate classes */
|
||||
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
|
||||
rc.enabled_rates = supported_rates;
|
||||
rc.short_retry_limit = 10;
|
||||
rc.long_retry_limit = 10;
|
||||
rc.aflags = 0;
|
||||
ret = wl1271_acx_ap_rate_policy(wl, &rc, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -567,6 +614,11 @@ int wl1271_hw_init(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Bluetooth WLAN coexistence */
|
||||
ret = wl1271_init_pta(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Default memory configuration */
|
||||
ret = wl1271_acx_init_mem_config(wl);
|
||||
if (ret < 0)
|
||||
|
@ -606,7 +658,7 @@ int wl1271_hw_init(struct wl1271 *wl)
|
|||
goto out_free_memmap;
|
||||
|
||||
/* Default fragmentation threshold */
|
||||
ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
|
||||
ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
|
|
|
@ -33,5 +33,7 @@ int wl1271_init_pta(struct wl1271 *wl);
|
|||
int wl1271_init_energy_detection(struct wl1271 *wl);
|
||||
int wl1271_chip_specific_init(struct wl1271 *wl);
|
||||
int wl1271_hw_init(struct wl1271 *wl);
|
||||
int wl1271_init_ap_rates(struct wl1271 *wl);
|
||||
int wl1271_ap_init_templates(struct wl1271 *wl);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
static struct conf_drv_settings default_conf = {
|
||||
.sg = {
|
||||
.params = {
|
||||
.sta_params = {
|
||||
[CONF_SG_BT_PER_THRESHOLD] = 7500,
|
||||
[CONF_SG_HV3_MAX_OVERRIDE] = 0,
|
||||
[CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
|
||||
|
@ -101,6 +101,61 @@ static struct conf_drv_settings default_conf = {
|
|||
[CONF_SG_DHCP_TIME] = 5000,
|
||||
[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
|
||||
},
|
||||
.ap_params = {
|
||||
[CONF_SG_BT_PER_THRESHOLD] = 7500,
|
||||
[CONF_SG_HV3_MAX_OVERRIDE] = 0,
|
||||
[CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
|
||||
[CONF_SG_BT_LOAD_RATIO] = 50,
|
||||
[CONF_SG_AUTO_PS_MODE] = 1,
|
||||
[CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
|
||||
[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
|
||||
[CONF_SG_ANTENNA_CONFIGURATION] = 0,
|
||||
[CONF_SG_BEACON_MISS_PERCENT] = 60,
|
||||
[CONF_SG_RATE_ADAPT_THRESH] = 64,
|
||||
[CONF_SG_RATE_ADAPT_SNR] = 1,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25,
|
||||
[CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25,
|
||||
[CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25,
|
||||
[CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8,
|
||||
[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25,
|
||||
[CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25,
|
||||
[CONF_SG_RXT] = 1200,
|
||||
[CONF_SG_TXT] = 1000,
|
||||
[CONF_SG_ADAPTIVE_RXT_TXT] = 1,
|
||||
[CONF_SG_PS_POLL_TIMEOUT] = 10,
|
||||
[CONF_SG_UPSD_TIMEOUT] = 10,
|
||||
[CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
|
||||
[CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
|
||||
[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
|
||||
[CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8,
|
||||
[CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20,
|
||||
[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15,
|
||||
[CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20,
|
||||
[CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50,
|
||||
[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10,
|
||||
[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
|
||||
[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
|
||||
[CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75,
|
||||
[CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15,
|
||||
[CONF_SG_HV3_MAX_SERVED] = 6,
|
||||
[CONF_SG_DHCP_TIME] = 5000,
|
||||
[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
|
||||
[CONF_SG_TEMP_PARAM_1] = 0,
|
||||
[CONF_SG_TEMP_PARAM_2] = 0,
|
||||
[CONF_SG_TEMP_PARAM_3] = 0,
|
||||
[CONF_SG_TEMP_PARAM_4] = 0,
|
||||
[CONF_SG_TEMP_PARAM_5] = 0,
|
||||
[CONF_SG_AP_BEACON_MISS_TX] = 3,
|
||||
[CONF_SG_RX_WINDOW_LENGTH] = 6,
|
||||
[CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50,
|
||||
[CONF_SG_TEMP_PARAM_6] = 1,
|
||||
},
|
||||
.state = CONF_SG_PROTECTIVE,
|
||||
},
|
||||
.rx = {
|
||||
|
@ -108,7 +163,7 @@ static struct conf_drv_settings default_conf = {
|
|||
.packet_detection_threshold = 0,
|
||||
.ps_poll_timeout = 15,
|
||||
.upsd_timeout = 15,
|
||||
.rts_threshold = 2347,
|
||||
.rts_threshold = IEEE80211_MAX_RTS_THRESHOLD,
|
||||
.rx_cca_threshold = 0,
|
||||
.irq_blk_threshold = 0xFFFF,
|
||||
.irq_pkt_threshold = 0,
|
||||
|
@ -154,46 +209,7 @@ static struct conf_drv_settings default_conf = {
|
|||
.tx_op_limit = 1504,
|
||||
},
|
||||
},
|
||||
.ap_rc_conf = {
|
||||
[0] = {
|
||||
.enabled_rates = CONF_TX_AP_ENABLED_RATES,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0,
|
||||
},
|
||||
[1] = {
|
||||
.enabled_rates = CONF_TX_AP_ENABLED_RATES,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0,
|
||||
},
|
||||
[2] = {
|
||||
.enabled_rates = CONF_TX_AP_ENABLED_RATES,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0,
|
||||
},
|
||||
[3] = {
|
||||
.enabled_rates = CONF_TX_AP_ENABLED_RATES,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0,
|
||||
},
|
||||
},
|
||||
.ap_mgmt_conf = {
|
||||
.enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0,
|
||||
},
|
||||
.ap_bcst_conf = {
|
||||
.enabled_rates = CONF_HW_BIT_RATE_1MBPS,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0,
|
||||
},
|
||||
.max_tx_retries = 100,
|
||||
.ap_aging_period = 300,
|
||||
.ap_max_tx_retries = 100,
|
||||
.tid_conf_count = 4,
|
||||
.tid_conf = {
|
||||
[CONF_TX_AC_BE] = {
|
||||
|
@ -258,7 +274,7 @@ static struct conf_drv_settings default_conf = {
|
|||
.bet_enable = CONF_BET_MODE_ENABLE,
|
||||
.bet_max_consecutive = 50,
|
||||
.psm_entry_retries = 5,
|
||||
.psm_exit_retries = 255,
|
||||
.psm_exit_retries = 16,
|
||||
.psm_entry_nullfunc_retries = 3,
|
||||
.psm_entry_hangover_period = 1,
|
||||
.keep_alive_interval = 55000,
|
||||
|
@ -305,7 +321,7 @@ static struct conf_drv_settings default_conf = {
|
|||
.ssid_profiles = 1,
|
||||
.rx_block_num = 70,
|
||||
.tx_min_block_num = 40,
|
||||
.dynamic_memory = 0,
|
||||
.dynamic_memory = 1,
|
||||
.min_req_tx_blocks = 100,
|
||||
.min_req_rx_blocks = 22,
|
||||
.tx_min = 27,
|
||||
|
@ -320,10 +336,23 @@ static struct conf_drv_settings default_conf = {
|
|||
.min_req_rx_blocks = 22,
|
||||
.tx_min = 27,
|
||||
},
|
||||
.fm_coex = {
|
||||
.enable = true,
|
||||
.swallow_period = 5,
|
||||
.n_divider_fref_set_1 = 0xff, /* default */
|
||||
.n_divider_fref_set_2 = 12,
|
||||
.m_divider_fref_set_1 = 148,
|
||||
.m_divider_fref_set_2 = 0xffff, /* default */
|
||||
.coex_pll_stabilization_time = 0xffffffff, /* default */
|
||||
.ldo_stabilization_time = 0xffff, /* default */
|
||||
.fm_disturbed_band_margin = 0xff, /* default */
|
||||
.swallow_clk_diff = 0xff, /* default */
|
||||
},
|
||||
.hci_io_ds = HCI_IO_DS_6MA,
|
||||
};
|
||||
|
||||
static void __wl1271_op_remove_interface(struct wl1271 *wl);
|
||||
static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
||||
bool reset_tx_queues);
|
||||
static void wl1271_free_ap_keys(struct wl1271 *wl);
|
||||
|
||||
|
||||
|
@ -508,6 +537,11 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* FM WLAN coexistence */
|
||||
ret = wl1271_acx_fm_coex(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Energy detection */
|
||||
ret = wl1271_init_energy_detection(wl);
|
||||
if (ret < 0)
|
||||
|
@ -932,15 +966,25 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||
if (wl->state != WL1271_STATE_ON)
|
||||
goto out;
|
||||
|
||||
wl1271_info("Hardware recovery in progress.");
|
||||
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
|
||||
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
|
||||
|
||||
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
|
||||
ieee80211_connection_loss(wl->vif);
|
||||
|
||||
/* Prevent spurious TX during FW restart */
|
||||
ieee80211_stop_queues(wl->hw);
|
||||
|
||||
/* reboot the chipset */
|
||||
__wl1271_op_remove_interface(wl);
|
||||
__wl1271_op_remove_interface(wl, false);
|
||||
ieee80211_restart_hw(wl->hw);
|
||||
|
||||
/*
|
||||
* Its safe to enable TX now - the queues are stopped after a request
|
||||
* to restart the HW.
|
||||
*/
|
||||
ieee80211_wake_queues(wl->hw);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
@ -1011,6 +1055,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
|||
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
|
||||
wl->chip.id);
|
||||
|
||||
/* end-of-transaction flag should be set in wl127x AP mode */
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
|
||||
|
||||
ret = wl1271_setup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -1273,7 +1321,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
|
|||
skb->priority = WL1271_TID_MGMT;
|
||||
|
||||
/* Initialize all fields that might be used */
|
||||
skb->queue_mapping = 0;
|
||||
skb_set_queue_mapping(skb, 0);
|
||||
memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info));
|
||||
|
||||
return skb;
|
||||
|
@ -1440,7 +1488,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void __wl1271_op_remove_interface(struct wl1271 *wl)
|
||||
static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
||||
bool reset_tx_queues)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1486,7 +1535,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
|
|||
mutex_lock(&wl->mutex);
|
||||
|
||||
/* let's notify MAC80211 about the remaining pending TX frames */
|
||||
wl1271_tx_reset(wl);
|
||||
wl1271_tx_reset(wl, reset_tx_queues);
|
||||
wl1271_power_off(wl);
|
||||
|
||||
memset(wl->bssid, 0, ETH_ALEN);
|
||||
|
@ -1547,7 +1596,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
|||
*/
|
||||
if (wl->vif) {
|
||||
WARN_ON(wl->vif != vif);
|
||||
__wl1271_op_remove_interface(wl);
|
||||
__wl1271_op_remove_interface(wl, true);
|
||||
}
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
@ -2284,7 +2333,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_acx_frag_threshold(wl, (u16)value);
|
||||
ret = wl1271_acx_frag_threshold(wl, value);
|
||||
if (ret < 0)
|
||||
wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret);
|
||||
|
||||
|
@ -2312,7 +2361,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_acx_rts_threshold(wl, (u16) value);
|
||||
ret = wl1271_acx_rts_threshold(wl, value);
|
||||
if (ret < 0)
|
||||
wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
|
||||
|
||||
|
@ -2455,24 +2504,19 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
|
|||
|
||||
if ((changed & BSS_CHANGED_BASIC_RATES)) {
|
||||
u32 rates = bss_conf->basic_rates;
|
||||
struct conf_tx_rate_class mgmt_rc;
|
||||
|
||||
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
|
||||
wl->basic_rate = wl1271_tx_min_rate_get(wl);
|
||||
wl1271_debug(DEBUG_AP, "basic rates: 0x%x",
|
||||
wl->basic_rate_set);
|
||||
|
||||
/* update the AP management rate policy with the new rates */
|
||||
mgmt_rc.enabled_rates = wl->basic_rate_set;
|
||||
mgmt_rc.long_retry_limit = 10;
|
||||
mgmt_rc.short_retry_limit = 10;
|
||||
mgmt_rc.aflags = 0;
|
||||
ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc,
|
||||
ACX_TX_AP_MODE_MGMT_RATE);
|
||||
ret = wl1271_init_ap_rates(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("AP mgmt policy change failed %d", ret);
|
||||
wl1271_error("AP rate policy change failed %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_ap_init_templates(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed);
|
||||
|
@ -2505,6 +2549,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
|
|||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_IBSS) {
|
||||
wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
|
||||
bss_conf->ibss_joined);
|
||||
|
||||
if (bss_conf->ibss_joined) {
|
||||
u32 rates = bss_conf->basic_rates;
|
||||
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
|
||||
rates);
|
||||
wl->basic_rate = wl1271_tx_min_rate_get(wl);
|
||||
|
||||
/* by default, use 11b rates */
|
||||
wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
|
||||
ret = wl1271_acx_sta_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -2694,8 +2756,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
}
|
||||
} else {
|
||||
/* use defaults when not associated */
|
||||
bool was_assoc =
|
||||
!!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED,
|
||||
&wl->flags);
|
||||
clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
|
||||
clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
|
||||
wl->aid = 0;
|
||||
|
||||
/* free probe-request template */
|
||||
|
@ -2721,8 +2785,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
goto out;
|
||||
|
||||
/* restore the bssid filter and go to dummy bssid */
|
||||
wl1271_unjoin(wl);
|
||||
wl1271_dummy_join(wl);
|
||||
if (was_assoc) {
|
||||
wl1271_unjoin(wl);
|
||||
wl1271_dummy_join(wl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2954,12 +3020,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
|
|||
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
}
|
||||
|
||||
bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
|
||||
{
|
||||
int id = hlid - WL1271_AP_STA_HLID_START;
|
||||
return test_bit(id, wl->ap_hlid_map);
|
||||
}
|
||||
|
||||
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
|
@ -3104,6 +3164,28 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
bool ret = false;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
/* packets are considered pending if in the TX queue or the FW */
|
||||
ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0);
|
||||
|
||||
/* the above is appropriate for STA mode for PS purposes */
|
||||
WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* can't be const, mac80211 writes to this */
|
||||
static struct ieee80211_rate wl1271_rates[] = {
|
||||
{ .bitrate = 10,
|
||||
|
@ -3355,6 +3437,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
|||
.sta_add = wl1271_op_sta_add,
|
||||
.sta_remove = wl1271_op_sta_remove,
|
||||
.ampdu_action = wl1271_op_ampdu_action,
|
||||
.tx_frames_pending = wl1271_tx_frames_pending,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
|
@ -3542,6 +3625,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
IEEE80211_HW_HAS_RATE_CONTROL |
|
||||
IEEE80211_HW_CONNECTION_MONITOR |
|
||||
IEEE80211_HW_SUPPORTS_CQM_RSSI |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_AP_LINK_PS;
|
||||
|
||||
wl->hw->wiphy->cipher_suites = cipher_suites;
|
||||
|
|
|
@ -43,6 +43,10 @@ void wl1271_elp_work(struct work_struct *work)
|
|||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
/* our work might have been already cancelled */
|
||||
if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
|
||||
goto out;
|
||||
|
||||
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
|
||||
(!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
|
||||
!test_bit(WL1271_FLAG_IDLE, &wl->flags)))
|
||||
|
@ -61,12 +65,16 @@ void wl1271_elp_work(struct work_struct *work)
|
|||
/* Routines to toggle sleep mode while in ELP */
|
||||
void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
||||
{
|
||||
if (test_bit(WL1271_FLAG_PSM, &wl->flags) ||
|
||||
test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
|
||||
cancel_delayed_work(&wl->elp_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
}
|
||||
/* we shouldn't get consecutive sleep requests */
|
||||
if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
|
||||
return;
|
||||
|
||||
if (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
|
||||
!test_bit(WL1271_FLAG_IDLE, &wl->flags))
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
}
|
||||
|
||||
int wl1271_ps_elp_wakeup(struct wl1271 *wl)
|
||||
|
@ -77,6 +85,16 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
|
|||
u32 start_time = jiffies;
|
||||
bool pending = false;
|
||||
|
||||
/*
|
||||
* we might try to wake up even if we didn't go to sleep
|
||||
* before (e.g. on boot)
|
||||
*/
|
||||
if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))
|
||||
return 0;
|
||||
|
||||
/* don't cancel_sync as it might contend for a mutex and deadlock */
|
||||
cancel_delayed_work(&wl->elp_work);
|
||||
|
||||
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -76,12 +76,15 @@ static void wl1271_rx_status(struct wl1271 *wl,
|
|||
status->band);
|
||||
|
||||
if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
|
||||
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
|
||||
u8 desc_err_code = desc->status & WL1271_RX_DESC_STATUS_MASK;
|
||||
|
||||
if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL)))
|
||||
status->flag |= RX_FLAG_DECRYPTED;
|
||||
if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL))
|
||||
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED |
|
||||
RX_FLAG_DECRYPTED;
|
||||
|
||||
if (unlikely(desc_err_code == WL1271_RX_DESC_MIC_FAIL)) {
|
||||
status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
wl1271_warning("Michael MIC error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +103,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
|
|||
if (unlikely(wl->state == WL1271_STATE_PLT))
|
||||
return -EINVAL;
|
||||
|
||||
/* the data read starts with the descriptor */
|
||||
desc = (struct wl1271_rx_descriptor *) data;
|
||||
|
||||
switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {
|
||||
/* discard corrupted packets */
|
||||
case WL1271_RX_DESC_DRIVER_RX_Q_FAIL:
|
||||
case WL1271_RX_DESC_DECRYPT_FAIL:
|
||||
wl1271_warning("corrupted packet in RX with status: 0x%x",
|
||||
desc->status & WL1271_RX_DESC_STATUS_MASK);
|
||||
return -EINVAL;
|
||||
case WL1271_RX_DESC_SUCCESS:
|
||||
case WL1271_RX_DESC_MIC_FAIL:
|
||||
break;
|
||||
default:
|
||||
wl1271_error("invalid RX descriptor status: 0x%x",
|
||||
desc->status & WL1271_RX_DESC_STATUS_MASK);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skb = __dev_alloc_skb(length, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
wl1271_error("Couldn't allocate RX frame");
|
||||
|
@ -109,9 +131,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
|
|||
buf = skb_put(skb, length);
|
||||
memcpy(buf, data, length);
|
||||
|
||||
/* the data read starts with the descriptor */
|
||||
desc = (struct wl1271_rx_descriptor *) buf;
|
||||
|
||||
/* now we pull the descriptor out of the buffer */
|
||||
skb_pull(skb, sizeof(*desc));
|
||||
|
||||
|
@ -121,7 +140,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
|
|||
|
||||
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
|
||||
|
||||
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
|
||||
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb,
|
||||
skb->len - desc->pad_len,
|
||||
beacon ? "beacon" : "");
|
||||
|
||||
skb_trim(skb, skb->len - desc->pad_len);
|
||||
|
|
|
@ -65,6 +65,9 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
|
|||
static void wl1271_free_tx_id(struct wl1271 *wl, int id)
|
||||
{
|
||||
if (__test_and_clear_bit(id, wl->tx_frames_map)) {
|
||||
if (unlikely(wl->tx_frames_cnt == ACX_TX_DESCRIPTORS))
|
||||
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
|
||||
|
||||
wl->tx_frames[id] = NULL;
|
||||
wl->tx_frames_cnt--;
|
||||
}
|
||||
|
@ -630,7 +633,7 @@ void wl1271_tx_work(struct work_struct *work)
|
|||
|
||||
wl1271_tx_work_locked(wl);
|
||||
|
||||
wl1271_ps_elp_wakeup(wl);
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
@ -766,8 +769,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
|
|||
wl1271_handle_tx_low_watermark(wl);
|
||||
}
|
||||
|
||||
/* caller must hold wl->mutex */
|
||||
void wl1271_tx_reset(struct wl1271 *wl)
|
||||
/* caller must hold wl->mutex and TX must be stopped */
|
||||
void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
|
||||
{
|
||||
int i;
|
||||
struct sk_buff *skb;
|
||||
|
@ -803,8 +806,10 @@ void wl1271_tx_reset(struct wl1271 *wl)
|
|||
/*
|
||||
* Make sure the driver is at a consistent state, in case this
|
||||
* function is called from a context other than interface removal.
|
||||
* This call will always wake the TX queues.
|
||||
*/
|
||||
wl1271_handle_tx_low_watermark(wl);
|
||||
if (reset_tx_queues)
|
||||
wl1271_handle_tx_low_watermark(wl);
|
||||
|
||||
for (i = 0; i < ACX_TX_DESCRIPTORS; i++) {
|
||||
if (wl->tx_frames[i] == NULL)
|
||||
|
|
|
@ -185,7 +185,7 @@ static inline int wl1271_tx_get_queue(int queue)
|
|||
void wl1271_tx_work(struct work_struct *work);
|
||||
void wl1271_tx_work_locked(struct wl1271 *wl);
|
||||
void wl1271_tx_complete(struct wl1271 *wl);
|
||||
void wl1271_tx_reset(struct wl1271 *wl);
|
||||
void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
|
||||
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);
|
||||
|
|
|
@ -172,6 +172,7 @@ extern u32 wl12xx_debug_level;
|
|||
#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)
|
||||
|
||||
#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
|
||||
|
@ -345,6 +346,7 @@ enum wl12xx_flags {
|
|||
WL1271_FLAG_TX_QUEUE_STOPPED,
|
||||
WL1271_FLAG_TX_PENDING,
|
||||
WL1271_FLAG_IN_ELP,
|
||||
WL1271_FLAG_ELP_REQUESTED,
|
||||
WL1271_FLAG_PSM,
|
||||
WL1271_FLAG_PSM_REQUESTED,
|
||||
WL1271_FLAG_IRQ_RUNNING,
|
||||
|
|
Loading…
Reference in New Issue