Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx
This commit is contained in:
commit
376cf5d3fd
|
@ -19,16 +19,6 @@ config WL12XX
|
|||
If you choose to build a module, it will be called wl12xx. Say N if
|
||||
unsure.
|
||||
|
||||
config WL12XX_HT
|
||||
bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)"
|
||||
depends on WL12XX && EXPERIMENTAL
|
||||
default n
|
||||
---help---
|
||||
This will enable 802.11 HT support in the wl12xx module.
|
||||
|
||||
That configuration is temporary due to the code incomplete and
|
||||
still in testing process.
|
||||
|
||||
config WL12XX_SPI
|
||||
tristate "TI wl12xx SPI support"
|
||||
depends on WL12XX && SPI_MASTER
|
||||
|
|
|
@ -1691,3 +1691,43 @@ out:
|
|||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl12xx_acx_config_hangover(struct wl1271 *wl)
|
||||
{
|
||||
struct wl12xx_acx_config_hangover *acx;
|
||||
struct conf_hangover_settings *conf = &wl->conf.hangover;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx config hangover");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->recover_time = cpu_to_le32(conf->recover_time);
|
||||
acx->hangover_period = conf->hangover_period;
|
||||
acx->dynamic_mode = conf->dynamic_mode;
|
||||
acx->early_termination_mode = conf->early_termination_mode;
|
||||
acx->max_period = conf->max_period;
|
||||
acx->min_period = conf->min_period;
|
||||
acx->increase_delta = conf->increase_delta;
|
||||
acx->decrease_delta = conf->decrease_delta;
|
||||
acx->quiet_time = conf->quiet_time;
|
||||
acx->increase_time = conf->increase_time;
|
||||
acx->window_size = acx->window_size;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx,
|
||||
sizeof(*acx));
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx config hangover failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -1144,6 +1144,23 @@ struct wl12xx_acx_set_rate_mgmt_params {
|
|||
u8 padding2[2];
|
||||
} __packed;
|
||||
|
||||
struct wl12xx_acx_config_hangover {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 recover_time;
|
||||
u8 hangover_period;
|
||||
u8 dynamic_mode;
|
||||
u8 early_termination_mode;
|
||||
u8 max_period;
|
||||
u8 min_period;
|
||||
u8 increase_delta;
|
||||
u8 decrease_delta;
|
||||
u8 quiet_time;
|
||||
u8 increase_time;
|
||||
u8 window_size;
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
||||
ACX_MEM_CFG = 0x0003,
|
||||
|
@ -1281,5 +1298,6 @@ int wl1271_acx_config_ps(struct wl1271 *wl);
|
|||
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
|
||||
int wl1271_acx_fm_coex(struct wl1271 *wl);
|
||||
int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
|
||||
int wl12xx_acx_config_hangover(struct wl1271 *wl);
|
||||
|
||||
#endif /* __WL1271_ACX_H__ */
|
||||
|
|
|
@ -895,7 +895,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
|
|||
struct acx_header *acx = buf;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd configure");
|
||||
wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id);
|
||||
|
||||
acx->id = cpu_to_le16(id);
|
||||
|
||||
|
@ -1413,7 +1413,7 @@ out:
|
|||
int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
|
||||
{
|
||||
struct wl12xx_cmd_add_peer *cmd;
|
||||
int ret;
|
||||
int i, ret;
|
||||
u32 sta_rates;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
|
||||
|
@ -1424,15 +1424,19 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
|
|||
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;
|
||||
cmd->sp_len = sta->max_sp;
|
||||
cmd->wmm = sta->wme ? 1 : 0;
|
||||
|
||||
for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++)
|
||||
if (sta->wme && (sta->uapsd_queues & BIT(i)))
|
||||
cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER;
|
||||
else
|
||||
cmd->psd_type[i] = WL1271_PSD_LEGACY;
|
||||
|
||||
sta_rates = sta->supp_rates[wl->band];
|
||||
if (sta->ht_cap.ht_supported)
|
||||
sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
|
||||
|
@ -1440,7 +1444,8 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
|
|||
cmd->supported_rates =
|
||||
cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates));
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates);
|
||||
wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
|
||||
cmd->supported_rates, sta->uapsd_queues);
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -591,6 +591,13 @@ enum wl12xx_ssid_type {
|
|||
WL12XX_SSID_TYPE_ANY = 2,
|
||||
};
|
||||
|
||||
enum wl1271_psd_type {
|
||||
WL1271_PSD_LEGACY = 0,
|
||||
WL1271_PSD_UPSD_TRIGGER = 1,
|
||||
WL1271_PSD_LEGACY_PSPOLL = 2,
|
||||
WL1271_PSD_SAPSD = 3
|
||||
};
|
||||
|
||||
struct wl12xx_cmd_add_peer {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
|
|
|
@ -915,14 +915,6 @@ struct conf_conn_settings {
|
|||
*/
|
||||
u8 psm_entry_nullfunc_retries;
|
||||
|
||||
/*
|
||||
* Specifies the time to linger in active mode after successfully
|
||||
* transmitting the PSM entry null-func frame.
|
||||
*
|
||||
* Range 0 - 255 TU's
|
||||
*/
|
||||
u8 psm_entry_hangover_period;
|
||||
|
||||
/*
|
||||
*
|
||||
* Specifies the interval of the connection keep-alive null-func
|
||||
|
@ -1236,6 +1228,20 @@ struct conf_rate_policy_settings {
|
|||
u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
|
||||
};
|
||||
|
||||
struct conf_hangover_settings {
|
||||
u32 recover_time;
|
||||
u8 hangover_period;
|
||||
u8 dynamic_mode;
|
||||
u8 early_termination_mode;
|
||||
u8 max_period;
|
||||
u8 min_period;
|
||||
u8 increase_delta;
|
||||
u8 decrease_delta;
|
||||
u8 quiet_time;
|
||||
u8 increase_time;
|
||||
u8 window_size;
|
||||
};
|
||||
|
||||
struct conf_drv_settings {
|
||||
struct conf_sg_settings sg;
|
||||
struct conf_rx_settings rx;
|
||||
|
@ -1254,6 +1260,7 @@ struct conf_drv_settings {
|
|||
struct conf_rx_streaming_settings rx_streaming;
|
||||
struct conf_fwlog fwlog;
|
||||
struct conf_rate_policy_settings rate;
|
||||
struct conf_hangover_settings hangover;
|
||||
u8 hci_io_ds;
|
||||
};
|
||||
|
||||
|
|
|
@ -265,18 +265,10 @@ static ssize_t gpio_power_write(struct file *file,
|
|||
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);
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in gpio_power");
|
||||
return -EINVAL;
|
||||
|
@ -427,17 +419,10 @@ static ssize_t dtim_interval_write(struct file *file,
|
|||
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);
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value for dtim_interval");
|
||||
return -EINVAL;
|
||||
|
@ -492,17 +477,10 @@ static ssize_t beacon_interval_write(struct file *file,
|
|||
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);
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value for beacon_interval");
|
||||
return -EINVAL;
|
||||
|
@ -542,17 +520,10 @@ static ssize_t rx_streaming_interval_write(struct file *file,
|
|||
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);
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in rx_streaming_interval!");
|
||||
return -EINVAL;
|
||||
|
@ -601,17 +572,10 @@ static ssize_t rx_streaming_always_write(struct file *file,
|
|||
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);
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in rx_streaming_write!");
|
||||
return -EINVAL;
|
||||
|
@ -655,6 +619,47 @@ static const struct file_operations rx_streaming_always_ops = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t beacon_filtering_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_filtering!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_acx_beacon_filter_opt(wl, !!value);
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations beacon_filtering_ops = {
|
||||
.write = beacon_filtering_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int wl1271_debugfs_add_files(struct wl1271 *wl,
|
||||
struct dentry *rootdir)
|
||||
{
|
||||
|
@ -767,6 +772,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
|
|||
DEBUGFS_ADD(driver_state, rootdir);
|
||||
DEBUGFS_ADD(dtim_interval, rootdir);
|
||||
DEBUGFS_ADD(beacon_interval, rootdir);
|
||||
DEBUGFS_ADD(beacon_filtering, rootdir);
|
||||
|
||||
streaming = debugfs_create_dir("rx_streaming", rootdir);
|
||||
if (!streaming || IS_ERR(streaming))
|
||||
|
|
|
@ -171,19 +171,26 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
|
|||
wl->last_rssi_event = event;
|
||||
}
|
||||
|
||||
static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
|
||||
static void wl1271_stop_ba_event(struct wl1271 *wl)
|
||||
{
|
||||
/* Convert the value to bool */
|
||||
wl->ba_allowed = !!ba_allowed;
|
||||
if (wl->bss_type != BSS_TYPE_AP_BSS) {
|
||||
if (!wl->ba_rx_bitmap)
|
||||
return;
|
||||
ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap,
|
||||
wl->bssid);
|
||||
} else {
|
||||
int i;
|
||||
struct wl1271_link *lnk;
|
||||
for (i = WL1271_AP_STA_HLID_START; i < WL12XX_MAX_LINKS; i++) {
|
||||
lnk = &wl->links[i];
|
||||
if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Return in case:
|
||||
* there are not BA open or the event indication is to allowed BA
|
||||
*/
|
||||
if ((!wl->ba_rx_bitmap) || (wl->ba_allowed))
|
||||
return;
|
||||
|
||||
ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
|
||||
ieee80211_stop_rx_ba_session(wl->vif,
|
||||
lnk->ba_bitmap,
|
||||
lnk->addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
|
||||
|
@ -283,12 +290,14 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
|||
wl1271_event_rssi_trigger(wl, mbox);
|
||||
}
|
||||
|
||||
if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
|
||||
if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) {
|
||||
wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
|
||||
"ba_allowed = 0x%x", mbox->rx_ba_allowed);
|
||||
|
||||
if (wl->vif)
|
||||
wl1271_stop_ba_event(wl, mbox->rx_ba_allowed);
|
||||
wl->ba_allowed = !!mbox->rx_ba_allowed;
|
||||
|
||||
if (wl->vif && !wl->ba_allowed)
|
||||
wl1271_stop_ba_event(wl);
|
||||
}
|
||||
|
||||
if ((vector & DUMMY_PACKET_EVENT_ID)) {
|
||||
|
|
|
@ -707,6 +707,11 @@ int wl1271_hw_init(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* configure hangover */
|
||||
ret = wl12xx_acx_config_hangover(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_memmap:
|
||||
|
|
|
@ -239,7 +239,6 @@ static struct conf_drv_settings default_conf = {
|
|||
.psm_entry_retries = 8,
|
||||
.psm_exit_retries = 16,
|
||||
.psm_entry_nullfunc_retries = 3,
|
||||
.psm_entry_hangover_period = 1,
|
||||
.keep_alive_interval = 55000,
|
||||
.max_listen_interval = 20,
|
||||
},
|
||||
|
@ -267,8 +266,8 @@ static struct conf_drv_settings default_conf = {
|
|||
},
|
||||
.sched_scan = {
|
||||
/* sched_scan requires dwell times in TU instead of TU/1000 */
|
||||
.min_dwell_time_active = 8,
|
||||
.max_dwell_time_active = 30,
|
||||
.min_dwell_time_active = 30,
|
||||
.max_dwell_time_active = 60,
|
||||
.dwell_time_passive = 100,
|
||||
.dwell_time_dfs = 150,
|
||||
.num_probe_reqs = 2,
|
||||
|
@ -359,9 +358,23 @@ static struct conf_drv_settings default_conf = {
|
|||
0x00, 0x00, 0x00,
|
||||
},
|
||||
},
|
||||
.hangover = {
|
||||
.recover_time = 0,
|
||||
.hangover_period = 20,
|
||||
.dynamic_mode = 1,
|
||||
.early_termination_mode = 1,
|
||||
.max_period = 20,
|
||||
.min_period = 1,
|
||||
.increase_delta = 1,
|
||||
.decrease_delta = 2,
|
||||
.quiet_time = 4,
|
||||
.increase_time = 1,
|
||||
.window_size = 16,
|
||||
},
|
||||
};
|
||||
|
||||
static char *fwlog_param;
|
||||
static bool bug_on_recovery;
|
||||
|
||||
static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
||||
bool reset_tx_queues);
|
||||
|
@ -757,13 +770,14 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
|||
|
||||
static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
|
||||
{
|
||||
bool fw_ps;
|
||||
bool fw_ps, single_sta;
|
||||
|
||||
/* only regulate station links */
|
||||
if (hlid < WL1271_AP_STA_HLID_START)
|
||||
return;
|
||||
|
||||
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
single_sta = (wl->active_sta_count == 1);
|
||||
|
||||
/*
|
||||
* Wake up from high level PS if the STA is asleep with too little
|
||||
|
@ -772,8 +786,12 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
|
|||
if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
|
||||
wl1271_ps_link_end(wl, hlid);
|
||||
|
||||
/* Start high-level PS if the STA is asleep with enough blocks in FW */
|
||||
else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
/*
|
||||
* Start high-level PS if the STA is asleep with enough blocks in FW.
|
||||
* Make an exception if this is the only connected station. In this
|
||||
* case FW-memory congestion is not a problem.
|
||||
*/
|
||||
else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
wl1271_ps_link_start(wl, hlid, true);
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1231,8 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
|
||||
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
|
||||
|
||||
BUG_ON(bug_on_recovery);
|
||||
|
||||
/*
|
||||
* Advance security sequence number to overcome potential progress
|
||||
* in the firmware during recovery. This doens't hurt if the network is
|
||||
|
@ -1222,9 +1242,6 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||
test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
|
||||
wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1528,7 +1545,13 @@ out:
|
|||
int wl1271_tx_dummy_packet(struct wl1271 *wl)
|
||||
{
|
||||
unsigned long flags;
|
||||
int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
|
||||
int q;
|
||||
|
||||
/* no need to queue a new dummy packet if one is already pending */
|
||||
if (test_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags))
|
||||
return 0;
|
||||
|
||||
q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
|
||||
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
|
||||
|
@ -1802,10 +1825,16 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl)
|
|||
{
|
||||
switch (wl->bss_type) {
|
||||
case BSS_TYPE_AP_BSS:
|
||||
return WL1271_ROLE_AP;
|
||||
if (wl->p2p)
|
||||
return WL1271_ROLE_P2P_GO;
|
||||
else
|
||||
return WL1271_ROLE_AP;
|
||||
|
||||
case BSS_TYPE_STA_BSS:
|
||||
return WL1271_ROLE_STA;
|
||||
if (wl->p2p)
|
||||
return WL1271_ROLE_P2P_CL;
|
||||
else
|
||||
return WL1271_ROLE_STA;
|
||||
|
||||
case BSS_TYPE_IBSS:
|
||||
return WL1271_ROLE_IBSS;
|
||||
|
@ -1827,7 +1856,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
bool booted = false;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||
vif->type, vif->addr);
|
||||
ieee80211_vif_type_p2p(vif), vif->addr);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (wl->vif) {
|
||||
|
@ -1847,7 +1876,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
goto out;
|
||||
}
|
||||
|
||||
switch (vif->type) {
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
wl->p2p = 1;
|
||||
/* fall-through */
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wl->bss_type = BSS_TYPE_STA_BSS;
|
||||
wl->set_bss_type = BSS_TYPE_STA_BSS;
|
||||
|
@ -1856,6 +1888,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
wl->bss_type = BSS_TYPE_IBSS;
|
||||
wl->set_bss_type = BSS_TYPE_STA_BSS;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
wl->p2p = 1;
|
||||
/* fall-through */
|
||||
case NL80211_IFTYPE_AP:
|
||||
wl->bss_type = BSS_TYPE_AP_BSS;
|
||||
break;
|
||||
|
@ -2051,6 +2086,7 @@ deinit:
|
|||
wl->ssid_len = 0;
|
||||
wl->bss_type = MAX_BSS_TYPE;
|
||||
wl->set_bss_type = MAX_BSS_TYPE;
|
||||
wl->p2p = 0;
|
||||
wl->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
wl->rx_counter = 0;
|
||||
|
@ -2075,6 +2111,7 @@ deinit:
|
|||
memset(wl->roles_map, 0, sizeof(wl->roles_map));
|
||||
memset(wl->links_map, 0, sizeof(wl->links_map));
|
||||
memset(wl->roc_map, 0, sizeof(wl->roc_map));
|
||||
wl->active_sta_count = 0;
|
||||
|
||||
/* The system link is always allocated */
|
||||
__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
|
||||
|
@ -3729,14 +3766,18 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
|
|||
wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
|
||||
*hlid = wl_sta->hlid;
|
||||
memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
|
||||
wl->active_sta_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
|
||||
void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
|
||||
{
|
||||
int id = hlid - WL1271_AP_STA_HLID_START;
|
||||
|
||||
if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
|
||||
if (hlid < WL1271_AP_STA_HLID_START)
|
||||
return;
|
||||
|
||||
if (!test_bit(id, wl->ap_hlid_map))
|
||||
return;
|
||||
|
||||
clear_bit(id, wl->ap_hlid_map);
|
||||
|
@ -3745,6 +3786,7 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
|
|||
wl1271_tx_reset_link_queues(wl, hlid);
|
||||
__clear_bit(hlid, &wl->ap_ps_map);
|
||||
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
wl->active_sta_count--;
|
||||
}
|
||||
|
||||
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
|
||||
|
@ -4066,7 +4108,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
|
|||
/* 11n STA capabilities */
|
||||
#define HW_RX_HIGHEST_RATE 72
|
||||
|
||||
#ifdef CONFIG_WL12XX_HT
|
||||
#define WL12XX_HT_CAP { \
|
||||
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
|
||||
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
|
||||
|
@ -4079,11 +4120,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
|
|||
.tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
|
||||
}, \
|
||||
}
|
||||
#else
|
||||
#define WL12XX_HT_CAP { \
|
||||
.ht_supported = false, \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* can't be const, mac80211 writes to this */
|
||||
static struct ieee80211_supported_band wl1271_band_2ghz = {
|
||||
|
@ -4483,15 +4519,19 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
IEEE80211_HW_SUPPORTS_CQM_RSSI |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_AP_LINK_PS;
|
||||
IEEE80211_HW_AP_LINK_PS |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW;
|
||||
|
||||
wl->hw->wiphy->cipher_suites = cipher_suites;
|
||||
wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
|
||||
|
||||
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
|
||||
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
|
||||
wl->hw->wiphy->max_scan_ssids = 1;
|
||||
wl->hw->wiphy->max_sched_scan_ssids = 8;
|
||||
wl->hw->wiphy->max_sched_scan_ssids = 16;
|
||||
wl->hw->wiphy->max_match_sets = 16;
|
||||
/*
|
||||
* Maximum length of elements in scanning probe request templates
|
||||
* should be the maximum length possible for a template, without
|
||||
|
@ -4500,6 +4540,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
|
||||
sizeof(struct ieee80211_header);
|
||||
|
||||
wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
|
||||
|
||||
/* make sure all our channels fit in the scanned_ch bitmask */
|
||||
BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
|
||||
ARRAY_SIZE(wl1271_channels_5ghz) >
|
||||
|
@ -4625,6 +4667,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
|
|||
wl->session_counter = 0;
|
||||
wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
|
||||
wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
|
||||
wl->active_sta_count = 0;
|
||||
setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
|
||||
(unsigned long) wl);
|
||||
wl->fwlog_size = 0;
|
||||
|
@ -4776,6 +4819,9 @@ module_param_named(fwlog, fwlog_param, charp, 0);
|
|||
MODULE_PARM_DESC(keymap,
|
||||
"FW logger options: continuous, ondemand, dbgpins or disable");
|
||||
|
||||
module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
|
|
|
@ -199,15 +199,19 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
|
|||
unsigned long flags;
|
||||
int filtered[NUM_TX_QUEUES];
|
||||
|
||||
/* filter all frames currently the low level queus for this hlid */
|
||||
/* filter all frames currently in the low level queues for this hlid */
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++) {
|
||||
filtered[i] = 0;
|
||||
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
|
||||
filtered[i]++;
|
||||
|
||||
if (WARN_ON(wl12xx_is_dummy_packet(wl, skb)))
|
||||
continue;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
info->status.rates[0].idx = -1;
|
||||
ieee80211_tx_status_ni(wl->hw, skb);
|
||||
filtered[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,11 +66,9 @@ static void wl1271_rx_status(struct wl1271 *wl,
|
|||
|
||||
status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
|
||||
|
||||
#ifdef CONFIG_WL12XX_HT
|
||||
/* 11n support */
|
||||
if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
|
||||
status->flag |= RX_FLAG_HT;
|
||||
#endif
|
||||
|
||||
status->signal = desc->rssi;
|
||||
|
||||
|
@ -107,6 +105,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
|||
u8 beacon = 0;
|
||||
u8 is_data = 0;
|
||||
u8 reserved = unaligned ? NET_IP_ALIGN : 0;
|
||||
u16 seq_num;
|
||||
|
||||
/*
|
||||
* In PLT mode we seem to get frames and mac80211 warns about them,
|
||||
|
@ -169,9 +168,11 @@ 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,
|
||||
seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
||||
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb,
|
||||
skb->len - desc->pad_len,
|
||||
beacon ? "beacon" : "");
|
||||
beacon ? "beacon" : "",
|
||||
seq_num);
|
||||
|
||||
skb_trim(skb, skb->len - desc->pad_len);
|
||||
|
||||
|
|
|
@ -65,8 +65,9 @@ void wl1271_scan_complete_work(struct work_struct *work)
|
|||
/* return to ROC if needed */
|
||||
is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
|
||||
is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
|
||||
if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
|
||||
(is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) {
|
||||
if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
|
||||
(is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
|
||||
!test_bit(wl->dev_role_id, wl->roc_map)) {
|
||||
/* restore remain on channel */
|
||||
wl12xx_cmd_role_start_dev(wl);
|
||||
wl12xx_roc(wl, wl->dev_role_id);
|
||||
|
@ -164,9 +165,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* We always use high priority scans */
|
||||
scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
|
||||
|
||||
/* No SSIDs means that we have a forced passive scan */
|
||||
if (passive || wl->scan.req->n_ssids == 0)
|
||||
scan_options |= WL1271_SCAN_OPT_PASSIVE;
|
||||
|
@ -473,34 +471,86 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
|
|||
cfg->passive[2] || cfg->active[2];
|
||||
}
|
||||
|
||||
/* Returns 0 if no wildcard is used, 1 if wildcard is used or a
|
||||
* negative value on error */
|
||||
/* Returns the scan type to be used or a negative value on error */
|
||||
static int
|
||||
wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
|
||||
struct cfg80211_sched_scan_request *req)
|
||||
{
|
||||
struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
|
||||
struct cfg80211_ssid *ssid = req->ssids;
|
||||
int ret, wildcard = 0;
|
||||
struct cfg80211_match_set *sets = req->match_sets;
|
||||
struct cfg80211_ssid *ssids = req->ssids;
|
||||
int ret = 0, type, i, j, n_match_ssids = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
/* count the match sets that contain SSIDs */
|
||||
for (i = 0; i < req->n_match_sets; i++)
|
||||
if (sets[i].ssid.ssid_len > 0)
|
||||
n_match_ssids++;
|
||||
|
||||
while ((cmd->n_ssids < req->n_ssids) && ssid) {
|
||||
if (ssid->ssid_len == 0) {
|
||||
wildcard = 1;
|
||||
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
|
||||
} else {
|
||||
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN;
|
||||
/* No filter, no ssids or only bcast ssid */
|
||||
if (!n_match_ssids &&
|
||||
(!req->n_ssids ||
|
||||
(req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
|
||||
type = SCAN_SSID_FILTER_ANY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!n_match_ssids) {
|
||||
/* No filter, with ssids */
|
||||
type = SCAN_SSID_FILTER_DISABLED;
|
||||
|
||||
for (i = 0; i < req->n_ssids; i++) {
|
||||
cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
|
||||
SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
|
||||
cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
|
||||
memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
|
||||
ssids[i].ssid_len);
|
||||
cmd->n_ssids++;
|
||||
}
|
||||
} else {
|
||||
type = SCAN_SSID_FILTER_LIST;
|
||||
|
||||
/* Add all SSIDs from the filters */
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
/* ignore sets without SSIDs */
|
||||
if (!sets[i].ssid.ssid_len)
|
||||
continue;
|
||||
|
||||
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
|
||||
cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
|
||||
memcpy(cmd->ssids[cmd->n_ssids].ssid,
|
||||
sets[i].ssid.ssid, sets[i].ssid.ssid_len);
|
||||
cmd->n_ssids++;
|
||||
}
|
||||
if ((req->n_ssids > 1) ||
|
||||
(req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
|
||||
/*
|
||||
* Mark all the SSIDs passed in the SSID list as HIDDEN,
|
||||
* so they're used in probe requests.
|
||||
*/
|
||||
for (i = 0; i < req->n_ssids; i++) {
|
||||
for (j = 0; j < cmd->n_ssids; j++)
|
||||
if (!memcmp(req->ssids[i].ssid,
|
||||
cmd->ssids[j].ssid,
|
||||
req->ssids[i].ssid_len)) {
|
||||
cmd->ssids[j].type =
|
||||
SCAN_SSID_TYPE_HIDDEN;
|
||||
break;
|
||||
}
|
||||
/* Fail if SSID isn't present in the filters */
|
||||
if (j == req->n_ssids) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
}
|
||||
cmd->ssids[cmd->n_ssids].len = ssid->ssid_len;
|
||||
memcpy(cmd->ssids[cmd->n_ssids].ssid, ssid->ssid,
|
||||
ssid->ssid_len);
|
||||
ssid++;
|
||||
cmd->n_ssids++;
|
||||
}
|
||||
|
||||
wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
|
||||
|
@ -509,13 +559,15 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
|
|||
sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("cmd sched scan ssid list failed");
|
||||
goto out;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = wildcard;
|
||||
out:
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
out:
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return type;
|
||||
}
|
||||
|
||||
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
||||
|
@ -550,21 +602,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
|||
cfg->intervals[i] = cpu_to_le32(req->interval);
|
||||
|
||||
cfg->ssid_len = 0;
|
||||
if (req->n_ssids == 0) {
|
||||
wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY");
|
||||
cfg->filter_type = SCAN_SSID_FILTER_ANY;
|
||||
} else {
|
||||
ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret) {
|
||||
wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_DISABLED");
|
||||
cfg->filter_type = SCAN_SSID_FILTER_DISABLED;
|
||||
} else {
|
||||
wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_LIST");
|
||||
cfg->filter_type = SCAN_SSID_FILTER_LIST;
|
||||
}
|
||||
}
|
||||
ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
cfg->filter_type = ret;
|
||||
|
||||
wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
|
||||
|
||||
if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
|
||||
wl1271_error("scan channel list is empty");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "reg.h"
|
||||
#include "ps.h"
|
||||
#include "tx.h"
|
||||
#include "event.h"
|
||||
|
||||
static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
{
|
||||
|
@ -125,25 +126,31 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
|
|||
|
||||
static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
|
||||
{
|
||||
bool fw_ps;
|
||||
bool fw_ps, single_sta;
|
||||
u8 tx_pkts;
|
||||
|
||||
/* only regulate station links */
|
||||
if (hlid < WL1271_AP_STA_HLID_START)
|
||||
return;
|
||||
|
||||
if (WARN_ON(!wl1271_is_active_sta(wl, hlid)))
|
||||
return;
|
||||
|
||||
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
tx_pkts = wl->links[hlid].allocated_pkts;
|
||||
single_sta = (wl->active_sta_count == 1);
|
||||
|
||||
/*
|
||||
* if in FW PS and there is enough data in FW we can put the link
|
||||
* into high-level PS and clean out its TX queues.
|
||||
* Make an exception if this is the only connected station. In this
|
||||
* case FW-memory congestion is not a problem.
|
||||
*/
|
||||
if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
wl1271_ps_link_start(wl, hlid, true);
|
||||
}
|
||||
|
||||
static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
|
||||
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
|
||||
{
|
||||
return wl->dummy_packet == skb;
|
||||
}
|
||||
|
@ -453,7 +460,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
|
|||
rate_set >>= 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WL12XX_HT
|
||||
/* MCS rates indication are on bits 16 - 23 */
|
||||
rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;
|
||||
|
||||
|
@ -462,7 +468,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
|
|||
enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
|
||||
rate_set >>= 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return enabled_rates;
|
||||
}
|
||||
|
@ -886,6 +891,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
|
|||
/* TX failure */
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS) {
|
||||
for (i = 0; i < AP_MAX_LINKS; i++) {
|
||||
wl1271_free_sta(wl, i);
|
||||
wl1271_tx_reset_link_queues(wl, i);
|
||||
wl->links[i].allocated_pkts = 0;
|
||||
wl->links[i].prev_freed_pkts = 0;
|
||||
|
@ -905,10 +911,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
|
|||
ieee80211_tx_status_ni(wl->hw, skb);
|
||||
}
|
||||
}
|
||||
wl->tx_queue_count[i] = 0;
|
||||
}
|
||||
|
||||
wl->ba_rx_bitmap = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||
wl->tx_queue_count[i] = 0;
|
||||
|
||||
wl->stopped_queues_map = 0;
|
||||
|
||||
/*
|
||||
|
|
|
@ -214,5 +214,9 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
|
|||
u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
|
||||
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
|
||||
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
|
||||
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
|
||||
|
||||
/* from main.c */
|
||||
void wl1271_free_sta(struct wl1271 *wl, u8 hlid);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -234,14 +234,14 @@ struct wl1271_stats {
|
|||
#define NUM_TX_QUEUES 4
|
||||
#define NUM_RX_PKT_DESC 8
|
||||
|
||||
#define AP_MAX_STATIONS 5
|
||||
#define AP_MAX_STATIONS 8
|
||||
|
||||
/* Broadcast and Global links + system link + links to stations */
|
||||
/*
|
||||
* TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
|
||||
* the places that use this.
|
||||
*/
|
||||
#define AP_MAX_LINKS (AP_MAX_STATIONS + 3)
|
||||
#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START)
|
||||
|
||||
/* FW status registers */
|
||||
struct wl12xx_fw_status {
|
||||
|
@ -402,6 +402,7 @@ struct wl1271 {
|
|||
u8 mac_addr[ETH_ALEN];
|
||||
u8 bss_type;
|
||||
u8 set_bss_type;
|
||||
u8 p2p; /* we are using p2p role */
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 ssid_len;
|
||||
int channel;
|
||||
|
@ -626,6 +627,9 @@ struct wl1271 {
|
|||
|
||||
/* number of currently active RX BA sessions */
|
||||
int ba_rx_session_count;
|
||||
|
||||
/* AP-mode - number of currently connected stations */
|
||||
int active_sta_count;
|
||||
};
|
||||
|
||||
struct wl1271_station {
|
||||
|
|
Loading…
Reference in New Issue