mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 08:31:55 +00:00
Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx
This commit is contained in:
commit
5dde8e1749
@ -777,7 +777,23 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
|
||||
acx->rate_policy.long_retry_limit = c->long_retry_limit;
|
||||
acx->rate_policy.aflags = c->aflags;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Setting of rate policies failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* configure one rate class for basic p2p operations.
|
||||
* (p2p packets should always go out with OFDM rates, even
|
||||
* if we are currently connected to 11b AP)
|
||||
*/
|
||||
acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P);
|
||||
acx->rate_policy.enabled_rates =
|
||||
cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P);
|
||||
acx->rate_policy.short_retry_limit = c->short_retry_limit;
|
||||
acx->rate_policy.long_retry_limit = c->long_retry_limit;
|
||||
acx->rate_policy.aflags = c->aflags;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
|
@ -656,6 +656,7 @@ struct acx_rate_class {
|
||||
|
||||
#define ACX_TX_BASIC_RATE 0
|
||||
#define ACX_TX_AP_FULL_RATE 1
|
||||
#define ACX_TX_BASIC_RATE_P2P 2
|
||||
#define ACX_TX_AP_MODE_MGMT_RATE 4
|
||||
#define ACX_TX_AP_MODE_BCST_RATE 5
|
||||
struct acx_rate_policy {
|
||||
|
@ -503,7 +503,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
BA_SESSION_RX_CONSTRAINT_EVENT_ID |
|
||||
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
|
||||
INACTIVE_STA_EVENT_ID |
|
||||
MAX_TX_RETRY_EVENT_ID;
|
||||
MAX_TX_RETRY_EVENT_ID |
|
||||
CHANNEL_SWITCH_COMPLETE_EVENT_ID;
|
||||
|
||||
ret = wl1271_event_unmask(wl);
|
||||
if (ret < 0) {
|
||||
@ -769,9 +770,6 @@ int wl1271_load_firmware(struct wl1271 *wl)
|
||||
clk |= (wl->ref_clock << 1) << 4;
|
||||
}
|
||||
|
||||
if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
|
||||
clk |= SCRATCH_ENABLE_LPD;
|
||||
|
||||
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
|
||||
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
|
@ -134,11 +134,6 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
|
||||
/* Override the REF CLK from the NVS with the one from platform data */
|
||||
gen_parms->general_params.ref_clock = wl->ref_clock;
|
||||
|
||||
/* LPD mode enable (bits 6-7) in WL1271 AP mode only */
|
||||
if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
|
||||
gen_parms->general_params.general_settings |=
|
||||
GENERAL_SETTINGS_DRPW_LPD;
|
||||
|
||||
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
|
||||
@ -1700,3 +1695,61 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id)
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct wl12xx_cmd_channel_switch *cmd;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "cmd channel switch");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->channel = ch_switch->channel->hw_value;
|
||||
cmd->switch_time = ch_switch->count;
|
||||
cmd->tx_suspend = ch_switch->block_tx;
|
||||
cmd->flush = 0; /* this value is ignored by the FW */
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send channel switch command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
|
||||
{
|
||||
struct wl12xx_cmd_stop_channel_switch *cmd;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "cmd stop channel switch");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to stop channel switch command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -79,6 +79,9 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
|
||||
int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
|
||||
int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
|
||||
int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
|
||||
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
|
||||
|
||||
enum wl1271_commands {
|
||||
CMD_INTERROGATE = 1, /*use this to read information elements*/
|
||||
@ -677,4 +680,21 @@ struct wl12xx_cmd_stop_fwlog {
|
||||
struct wl1271_cmd_header header;
|
||||
} __packed;
|
||||
|
||||
struct wl12xx_cmd_channel_switch {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
/* The new serving channel */
|
||||
u8 channel;
|
||||
/* Relative time of the serving channel switch in TBTT units */
|
||||
u8 switch_time;
|
||||
/* 1: Suspend TX till switch time; 0: Do not suspend TX */
|
||||
u8 tx_suspend;
|
||||
/* 1: Flush TX at switch time; 0: Do not flush */
|
||||
u8 flush;
|
||||
} __packed;
|
||||
|
||||
struct wl12xx_cmd_stop_channel_switch {
|
||||
struct wl1271_cmd_header header;
|
||||
} __packed;
|
||||
|
||||
#endif /* __WL1271_CMD_H__ */
|
||||
|
@ -416,13 +416,17 @@ struct conf_rx_settings {
|
||||
u8 queue_type;
|
||||
};
|
||||
|
||||
#define CONF_TX_MAX_RATE_CLASSES 8
|
||||
#define CONF_TX_MAX_RATE_CLASSES 10
|
||||
|
||||
#define CONF_TX_RATE_MASK_UNSPECIFIED 0
|
||||
#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS)
|
||||
#define CONF_TX_RATE_RETRY_LIMIT 10
|
||||
|
||||
/* basic rates for p2p operations (probe req/resp, etc.) */
|
||||
#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \
|
||||
CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS)
|
||||
|
||||
/*
|
||||
* Rates supported for data packets when operating as AP. Note the absence
|
||||
* of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
|
||||
|
@ -300,6 +300,21 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
wl1271_stop_ba_event(wl);
|
||||
}
|
||||
|
||||
if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) {
|
||||
wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
|
||||
"status = 0x%x",
|
||||
mbox->channel_switch_status);
|
||||
/*
|
||||
* That event uses for two cases:
|
||||
* 1) channel switch complete with status=0
|
||||
* 2) channel switch failed status=1
|
||||
*/
|
||||
if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) &&
|
||||
(wl->vif))
|
||||
ieee80211_chswitch_done(wl->vif,
|
||||
mbox->channel_switch_status ? false : true);
|
||||
}
|
||||
|
||||
if ((vector & DUMMY_PACKET_EVENT_ID)) {
|
||||
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
|
||||
if (wl->vif)
|
||||
|
@ -1333,14 +1333,6 @@ 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' and 'LPD mode flag'
|
||||
* should be set in wl127x AP mode only
|
||||
*/
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||
wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION |
|
||||
WL12XX_QUIRK_LPD_MODE);
|
||||
|
||||
ret = wl1271_setup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@ -2222,6 +2214,11 @@ static int wl1271_unjoin(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
|
||||
wl12xx_cmd_stop_channel_switch(wl);
|
||||
ieee80211_chswitch_done(wl->vif, false);
|
||||
}
|
||||
|
||||
/* to stop listening to a channel, we disconnect */
|
||||
ret = wl12xx_cmd_role_stop_sta(wl);
|
||||
if (ret < 0)
|
||||
@ -4130,6 +4127,37 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
ieee80211_chswitch_done(wl->vif, false);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl12xx_cmd_channel_switch(wl, ch_switch);
|
||||
|
||||
if (!ret)
|
||||
set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags);
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
@ -4406,6 +4434,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
||||
.ampdu_action = wl1271_op_ampdu_action,
|
||||
.tx_frames_pending = wl1271_tx_frames_pending,
|
||||
.set_bitrate_mask = wl12xx_set_bitrate_mask,
|
||||
.channel_switch = wl12xx_op_channel_switch,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
@ -4679,6 +4708,9 @@ 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->max_sched_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 */
|
||||
|
@ -348,6 +348,7 @@ enum wl12xx_flags {
|
||||
WL1271_FLAG_SOFT_GEMINI,
|
||||
WL1271_FLAG_RX_STREAMING_STARTED,
|
||||
WL1271_FLAG_RECOVERY_IN_PROGRESS,
|
||||
WL1271_FLAG_CS_PROGRESS,
|
||||
};
|
||||
|
||||
struct wl1271_link {
|
||||
@ -671,12 +672,6 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
|
||||
/* WL128X requires aggregated packets to be aligned to the SDIO block size */
|
||||
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
|
||||
|
||||
/*
|
||||
* WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power
|
||||
* consumption
|
||||
*/
|
||||
#define WL12XX_QUIRK_LPD_MODE BIT(3)
|
||||
|
||||
/* Older firmwares did not implement the FW logger over bus feature */
|
||||
#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user