Skip to content

Commit

Permalink
iwlwifi: mvm: Add Smart FIFO support
Browse files Browse the repository at this point in the history
Send firmware a Smart FIFO Configuration host command to allow
interrupt coalescing. The smart FIFO is enabled when there is
only one bound interface (other than  p2p devices which are
ignored) and it is of type station, and activated while the
station is associated.

Smart Fifo allows aggragations of DMA transactions and by that
causes processor and memory controller to stay for a longer time
on lower c-states, thus saving platform power.
Firmware relies on driver to activate and disable it.

Signed-off-by: Lilach Edelstein <lilach.edelstein@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
  • Loading branch information
Lilach Edelstein authored and Emmanuel Grumbach committed Dec 17, 2013
1 parent 710e4d0 commit 1f3b0ff
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 2 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/mvm/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
obj-$(CONFIG_IWLMVM) += iwlmvm.o
iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += scan.o time-event.o rs.o
iwlmvm-y += power.o power_legacy.o bt-coex.o
iwlmvm-y += led.o tt.o
Expand Down
16 changes: 15 additions & 1 deletion drivers/net/wireless/iwlwifi/mvm/binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,29 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
return -EINVAL;

/*
* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
*/
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;

return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
}

int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;

if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
return -EINVAL;

return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);

if (!ret)
if (iwl_mvm_sf_update(mvm, vif, true))
IWL_ERR(mvm, "Failed to update SF state\n");

return ret;
}
62 changes: 62 additions & 0 deletions drivers/net/wireless/iwlwifi/mvm/fw-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ enum {
BT_PROFILE_NOTIFICATION = 0xce,
BT_COEX_CI = 0x5d,

REPLY_SF_CFG_CMD = 0xd1,
REPLY_BEACON_FILTERING_CMD = 0xd2,

REPLY_DEBUG_CMD = 0xf0,
Expand Down Expand Up @@ -1363,4 +1364,65 @@ struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */
struct mvm_statistics_general general;
} __packed;

/***********************************
* Smart Fifo API
***********************************/
/* Smart Fifo state */
enum iwl_sf_state {
SF_LONG_DELAY_ON = 0, /* should never be called by driver */
SF_FULL_ON,
SF_UNINIT,
SF_INIT_OFF,
SF_HW_NUM_STATES
};

/* Smart Fifo possible scenario */
enum iwl_sf_scenario {
SF_SCENARIO_SINGLE_UNICAST,
SF_SCENARIO_AGG_UNICAST,
SF_SCENARIO_MULTICAST,
SF_SCENARIO_BA_RESP,
SF_SCENARIO_TX_RESP,
SF_NUM_SCENARIO
};

#define SF_TRANSIENT_STATES_NUMBER 2 /* SF_LONG_DELAY_ON and SF_FULL_ON */
#define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */

/* smart FIFO default values */
#define SF_W_MARK_SISO 4096
#define SF_W_MARK_MIMO2 8192
#define SF_W_MARK_MIMO3 6144
#define SF_W_MARK_LEGACY 4096
#define SF_W_MARK_SCAN 4096

/* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */
#define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */
#define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */
#define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */
#define SF_AGG_UNICAST_AGING_TIMER 2016 /* 2 mSec */
#define SF_MCAST_IDLE_TIMER 2016 /* 2 mSec */
#define SF_MCAST_AGING_TIMER 10016 /* 10 mSec */
#define SF_BA_IDLE_TIMER 320 /* 300 uSec */
#define SF_BA_AGING_TIMER 2016 /* 2 mSec */
#define SF_TX_RE_IDLE_TIMER 320 /* 300 uSec */
#define SF_TX_RE_AGING_TIMER 2016 /* 2 mSec */

#define SF_LONG_DELAY_AGING_TIMER 1000000 /* 1 Sec */

/**
* Smart Fifo configuration command.
* @state: smart fifo state, types listed in iwl_sf_sate.
* @watermark: Minimum allowed availabe free space in RXF for transient state.
* @long_delay_timeouts: aging and idle timer values for each scenario
* in long delay state.
* @full_on_timeouts: timer values for each scenario in full on state.
*/
struct iwl_sf_cfg_cmd {
enum iwl_sf_state state;
__le32 watermark[SF_TRANSIENT_STATES_NUMBER];
__le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
__le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
} __packed; /* SF_CFG_API_S_VER_2 */

#endif /* __fw_api_h__ */
4 changes: 4 additions & 0 deletions drivers/net/wireless/iwlwifi/mvm/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}

ret = iwl_mvm_sf_update(mvm, NULL, false);
if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");

ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
if (ret)
goto error;
Expand Down
21 changes: 21 additions & 0 deletions drivers/net/wireless/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,16 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_protect_session(mvm, vif, dur, dur,
5 * dur);
}

iwl_mvm_sf_update(mvm, vif, false);
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
/*
* If update fails - SF might be running in associated
* mode while disassociated - which is forbidden.
*/
WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false),
"Failed to update SF upon disassociation\n");

/* remove AP station now that the MAC is unassoc */
ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
if (ret)
Expand Down Expand Up @@ -1200,6 +1209,17 @@ static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return 0;
}

static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u32 changed)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

if (vif->type == NL80211_IFTYPE_STATION &&
changed & IEEE80211_RC_NSS_CHANGED)
iwl_mvm_sf_update(mvm, vif, false);
}

static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 ac,
const struct ieee80211_tx_queue_params *params)
Expand Down Expand Up @@ -1765,6 +1785,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.sta_notify = iwl_mvm_mac_sta_notify,
.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
.sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/wireless/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ struct iwl_mvm {
u8 scan_last_antenna_idx; /* to toggle TX between antennas */
u8 mgmt_last_antenna_idx;

/* last smart fifo state that was successfully sent to firmware */
enum iwl_sf_state sf_state;

#ifdef CONFIG_IWLWIFI_DEBUGFS
struct dentry *debugfs_dir;
u32 dbgfs_sram_offset, dbgfs_sram_len;
Expand Down Expand Up @@ -869,4 +872,8 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm);
void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);

/* smart fifo */
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool added_vif);

#endif /* __IWL_MVM_H__ */
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/mvm/ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->aux_queue = 11;
mvm->first_agg_queue = 12;
}
mvm->sf_state = SF_UNINIT;

mutex_init(&mvm->mutex);
spin_lock_init(&mvm->async_handlers_lock);
Expand Down
Loading

0 comments on commit 1f3b0ff

Please sign in to comment.