mirror of https://gitee.com/openkylin/linux.git
iwlwifi: support channel switch offload in driver
Support channel switch in driver as a separated mac80211 callback function instead of part of mac_config callback; by moving to this approach, uCode can have more control of channel switch timing. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
This commit is contained in:
parent
a0ee74cf08
commit
79d0732550
|
@ -1445,7 +1445,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
|
||||||
|
struct ieee80211_channel_switch *ch_switch)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
u8 band = 0;
|
u8 band = 0;
|
||||||
|
@ -1453,11 +1454,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||||
u8 ctrl_chan_high = 0;
|
u8 ctrl_chan_high = 0;
|
||||||
struct iwl4965_channel_switch_cmd cmd;
|
struct iwl4965_channel_switch_cmd cmd;
|
||||||
const struct iwl_channel_info *ch_info;
|
const struct iwl_channel_info *ch_info;
|
||||||
|
u32 switch_time_in_usec, ucode_switch_time;
|
||||||
|
u16 ch;
|
||||||
|
u32 tsf_low;
|
||||||
|
u8 switch_count;
|
||||||
|
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||||
|
struct ieee80211_vif *vif = priv->vif;
|
||||||
band = priv->band == IEEE80211_BAND_2GHZ;
|
band = priv->band == IEEE80211_BAND_2GHZ;
|
||||||
|
|
||||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
|
||||||
|
|
||||||
is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
|
is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
|
||||||
|
|
||||||
if (is_ht40 &&
|
if (is_ht40 &&
|
||||||
|
@ -1466,26 +1470,56 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||||
|
|
||||||
cmd.band = band;
|
cmd.band = band;
|
||||||
cmd.expect_beacon = 0;
|
cmd.expect_beacon = 0;
|
||||||
cmd.channel = cpu_to_le16(channel);
|
ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
|
||||||
|
cmd.channel = cpu_to_le16(ch);
|
||||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||||
|
switch_count = ch_switch->count;
|
||||||
|
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||||
|
/*
|
||||||
|
* calculate the ucode channel switch time
|
||||||
|
* adding TSF as one of the factor for when to switch
|
||||||
|
*/
|
||||||
|
if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
|
||||||
|
if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
|
||||||
|
beacon_interval)) {
|
||||||
|
switch_count -= (priv->ucode_beacon_time -
|
||||||
|
tsf_low) / beacon_interval;
|
||||||
|
} else
|
||||||
|
switch_count = 0;
|
||||||
|
}
|
||||||
|
if (switch_count <= 1)
|
||||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||||
|
else {
|
||||||
|
switch_time_in_usec =
|
||||||
|
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||||
|
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||||
|
switch_time_in_usec,
|
||||||
|
beacon_interval);
|
||||||
|
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||||
|
priv->ucode_beacon_time,
|
||||||
|
ucode_switch_time,
|
||||||
|
beacon_interval);
|
||||||
|
}
|
||||||
|
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||||
|
cmd.switch_time);
|
||||||
|
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||||
if (ch_info)
|
if (ch_info)
|
||||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||||
else {
|
else {
|
||||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||||
priv->active_rxon.channel, channel);
|
priv->active_rxon.channel, ch);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
|
rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
|
||||||
ctrl_chan_high, &cmd.tx_power);
|
ctrl_chan_high, &cmd.tx_power);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc);
|
IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
priv->switch_rxon.channel = cmd.channel;
|
||||||
priv->switch_rxon.switch_in_progress = true;
|
priv->switch_rxon.switch_in_progress = true;
|
||||||
|
|
||||||
return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
|
return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
|
||||||
|
|
|
@ -271,10 +271,17 @@ static void iwl5150_temperature(struct iwl_priv *priv)
|
||||||
iwl_tt_handler(priv);
|
iwl_tt_handler(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
||||||
|
struct ieee80211_channel_switch *ch_switch)
|
||||||
{
|
{
|
||||||
struct iwl5000_channel_switch_cmd cmd;
|
struct iwl5000_channel_switch_cmd cmd;
|
||||||
const struct iwl_channel_info *ch_info;
|
const struct iwl_channel_info *ch_info;
|
||||||
|
u32 switch_time_in_usec, ucode_switch_time;
|
||||||
|
u16 ch;
|
||||||
|
u32 tsf_low;
|
||||||
|
u8 switch_count;
|
||||||
|
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||||
|
struct ieee80211_vif *vif = priv->vif;
|
||||||
struct iwl_host_cmd hcmd = {
|
struct iwl_host_cmd hcmd = {
|
||||||
.id = REPLY_CHANNEL_SWITCH,
|
.id = REPLY_CHANNEL_SWITCH,
|
||||||
.len = sizeof(cmd),
|
.len = sizeof(cmd),
|
||||||
|
@ -282,22 +289,51 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||||
.data = &cmd,
|
.data = &cmd,
|
||||||
};
|
};
|
||||||
|
|
||||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
|
||||||
priv->active_rxon.channel, channel);
|
|
||||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||||
cmd.channel = cpu_to_le16(channel);
|
ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
|
||||||
|
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||||
|
priv->active_rxon.channel, ch);
|
||||||
|
cmd.channel = cpu_to_le16(ch);
|
||||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||||
|
switch_count = ch_switch->count;
|
||||||
|
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||||
|
/*
|
||||||
|
* calculate the ucode channel switch time
|
||||||
|
* adding TSF as one of the factor for when to switch
|
||||||
|
*/
|
||||||
|
if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
|
||||||
|
if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
|
||||||
|
beacon_interval)) {
|
||||||
|
switch_count -= (priv->ucode_beacon_time -
|
||||||
|
tsf_low) / beacon_interval;
|
||||||
|
} else
|
||||||
|
switch_count = 0;
|
||||||
|
}
|
||||||
|
if (switch_count <= 1)
|
||||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
else {
|
||||||
|
switch_time_in_usec =
|
||||||
|
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||||
|
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||||
|
switch_time_in_usec,
|
||||||
|
beacon_interval);
|
||||||
|
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||||
|
priv->ucode_beacon_time,
|
||||||
|
ucode_switch_time,
|
||||||
|
beacon_interval);
|
||||||
|
}
|
||||||
|
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||||
|
cmd.switch_time);
|
||||||
|
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||||
if (ch_info)
|
if (ch_info)
|
||||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||||
else {
|
else {
|
||||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||||
priv->active_rxon.channel, channel);
|
priv->active_rxon.channel, ch);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
priv->switch_rxon.channel = cmd.channel;
|
||||||
priv->switch_rxon.switch_in_progress = true;
|
priv->switch_rxon.switch_in_progress = true;
|
||||||
|
|
||||||
return iwl_send_cmd_sync(priv, &hcmd);
|
return iwl_send_cmd_sync(priv, &hcmd);
|
||||||
|
|
|
@ -239,10 +239,17 @@ static int iwl6050_hw_set_hw_params(struct iwl_priv *priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||||
|
struct ieee80211_channel_switch *ch_switch)
|
||||||
{
|
{
|
||||||
struct iwl6000_channel_switch_cmd cmd;
|
struct iwl6000_channel_switch_cmd cmd;
|
||||||
const struct iwl_channel_info *ch_info;
|
const struct iwl_channel_info *ch_info;
|
||||||
|
u32 switch_time_in_usec, ucode_switch_time;
|
||||||
|
u16 ch;
|
||||||
|
u32 tsf_low;
|
||||||
|
u8 switch_count;
|
||||||
|
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||||
|
struct ieee80211_vif *vif = priv->vif;
|
||||||
struct iwl_host_cmd hcmd = {
|
struct iwl_host_cmd hcmd = {
|
||||||
.id = REPLY_CHANNEL_SWITCH,
|
.id = REPLY_CHANNEL_SWITCH,
|
||||||
.len = sizeof(cmd),
|
.len = sizeof(cmd),
|
||||||
|
@ -250,23 +257,51 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||||
.data = &cmd,
|
.data = &cmd,
|
||||||
};
|
};
|
||||||
|
|
||||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
|
||||||
priv->active_rxon.channel, channel);
|
|
||||||
|
|
||||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||||
cmd.channel = cpu_to_le16(channel);
|
ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
|
||||||
|
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
|
||||||
|
priv->active_rxon.channel, ch);
|
||||||
|
cmd.channel = cpu_to_le16(ch);
|
||||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||||
|
switch_count = ch_switch->count;
|
||||||
|
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||||
|
/*
|
||||||
|
* calculate the ucode channel switch time
|
||||||
|
* adding TSF as one of the factor for when to switch
|
||||||
|
*/
|
||||||
|
if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
|
||||||
|
if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
|
||||||
|
beacon_interval)) {
|
||||||
|
switch_count -= (priv->ucode_beacon_time -
|
||||||
|
tsf_low) / beacon_interval;
|
||||||
|
} else
|
||||||
|
switch_count = 0;
|
||||||
|
}
|
||||||
|
if (switch_count <= 1)
|
||||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
else {
|
||||||
|
switch_time_in_usec =
|
||||||
|
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||||
|
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||||
|
switch_time_in_usec,
|
||||||
|
beacon_interval);
|
||||||
|
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||||
|
priv->ucode_beacon_time,
|
||||||
|
ucode_switch_time,
|
||||||
|
beacon_interval);
|
||||||
|
}
|
||||||
|
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||||
|
cmd.switch_time);
|
||||||
|
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||||
if (ch_info)
|
if (ch_info)
|
||||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||||
else {
|
else {
|
||||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||||
priv->active_rxon.channel, channel);
|
priv->active_rxon.channel, ch);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
priv->switch_rxon.channel = cmd.channel;
|
||||||
priv->switch_rxon.switch_in_progress = true;
|
priv->switch_rxon.switch_in_progress = true;
|
||||||
|
|
||||||
return iwl_send_cmd_sync(priv, &hcmd);
|
return iwl_send_cmd_sync(priv, &hcmd);
|
||||||
|
|
|
@ -120,7 +120,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||||
(priv->switch_rxon.channel != priv->staging_rxon.channel)) {
|
(priv->switch_rxon.channel != priv->staging_rxon.channel)) {
|
||||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||||
le16_to_cpu(priv->switch_rxon.channel));
|
le16_to_cpu(priv->switch_rxon.channel));
|
||||||
priv->switch_rxon.switch_in_progress = false;
|
iwl_chswitch_done(priv, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't need to send a full RXON, we can use
|
/* If we don't need to send a full RXON, we can use
|
||||||
|
@ -3325,6 +3325,98 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_channel_switch *ch_switch)
|
||||||
|
{
|
||||||
|
struct iwl_priv *priv = hw->priv;
|
||||||
|
const struct iwl_channel_info *ch_info;
|
||||||
|
struct ieee80211_conf *conf = &hw->conf;
|
||||||
|
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||||
|
u16 ch;
|
||||||
|
unsigned long flags = 0;
|
||||||
|
|
||||||
|
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||||
|
|
||||||
|
if (iwl_is_rfkill(priv))
|
||||||
|
goto out_exit;
|
||||||
|
|
||||||
|
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
|
||||||
|
test_bit(STATUS_SCANNING, &priv->status))
|
||||||
|
goto out_exit;
|
||||||
|
|
||||||
|
if (!iwl_is_associated(priv))
|
||||||
|
goto out_exit;
|
||||||
|
|
||||||
|
/* channel switch in progress */
|
||||||
|
if (priv->switch_rxon.switch_in_progress == true)
|
||||||
|
goto out_exit;
|
||||||
|
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
if (priv->cfg->ops->lib->set_channel_switch) {
|
||||||
|
|
||||||
|
ch = ieee80211_frequency_to_channel(
|
||||||
|
ch_switch->channel->center_freq);
|
||||||
|
if (le16_to_cpu(priv->active_rxon.channel) != ch) {
|
||||||
|
ch_info = iwl_get_channel_info(priv,
|
||||||
|
conf->channel->band,
|
||||||
|
ch);
|
||||||
|
if (!is_channel_valid(ch_info)) {
|
||||||
|
IWL_DEBUG_MAC80211(priv, "invalid channel\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
|
|
||||||
|
priv->current_ht_config.smps = conf->smps_mode;
|
||||||
|
|
||||||
|
/* Configure HT40 channels */
|
||||||
|
ht_conf->is_ht = conf_is_ht(conf);
|
||||||
|
if (ht_conf->is_ht) {
|
||||||
|
if (conf_is_ht40_minus(conf)) {
|
||||||
|
ht_conf->extension_chan_offset =
|
||||||
|
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||||
|
ht_conf->is_40mhz = true;
|
||||||
|
} else if (conf_is_ht40_plus(conf)) {
|
||||||
|
ht_conf->extension_chan_offset =
|
||||||
|
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||||
|
ht_conf->is_40mhz = true;
|
||||||
|
} else {
|
||||||
|
ht_conf->extension_chan_offset =
|
||||||
|
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||||
|
ht_conf->is_40mhz = false;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ht_conf->is_40mhz = false;
|
||||||
|
|
||||||
|
/* if we are switching from ht to 2.4 clear flags
|
||||||
|
* from any ht related info since 2.4 does not
|
||||||
|
* support ht */
|
||||||
|
if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
|
||||||
|
priv->staging_rxon.flags = 0;
|
||||||
|
|
||||||
|
iwl_set_rxon_channel(priv, conf->channel);
|
||||||
|
iwl_set_rxon_ht(priv, ht_conf);
|
||||||
|
iwl_set_flags_for_band(priv, conf->channel->band,
|
||||||
|
priv->vif);
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
|
iwl_set_rate(priv);
|
||||||
|
/*
|
||||||
|
* at this point, staging_rxon has the
|
||||||
|
* configuration for channel switch
|
||||||
|
*/
|
||||||
|
if (priv->cfg->ops->lib->set_channel_switch(priv,
|
||||||
|
ch_switch))
|
||||||
|
priv->switch_rxon.switch_in_progress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
out_exit:
|
||||||
|
if (!priv->switch_rxon.switch_in_progress)
|
||||||
|
ieee80211_chswitch_done(priv->vif, false);
|
||||||
|
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* sysfs attributes
|
* sysfs attributes
|
||||||
|
@ -3646,6 +3738,7 @@ static struct ieee80211_ops iwl_hw_ops = {
|
||||||
.sta_notify = iwl_mac_sta_notify,
|
.sta_notify = iwl_mac_sta_notify,
|
||||||
.sta_add = iwlagn_mac_sta_add,
|
.sta_add = iwlagn_mac_sta_add,
|
||||||
.sta_remove = iwl_mac_sta_remove,
|
.sta_remove = iwl_mac_sta_remove,
|
||||||
|
.channel_switch = iwl_mac_channel_switch,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
|
|
|
@ -893,7 +893,7 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iwl_set_rxon_channel);
|
EXPORT_SYMBOL(iwl_set_rxon_channel);
|
||||||
|
|
||||||
static void iwl_set_flags_for_band(struct iwl_priv *priv,
|
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||||
enum ieee80211_band band,
|
enum ieee80211_band band,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
|
@ -914,6 +914,7 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||||
priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
|
priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(iwl_set_flags_for_band);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize rxon structure with default values from eeprom
|
* initialize rxon structure with default values from eeprom
|
||||||
|
@ -989,7 +990,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iwl_connection_init_rx_config);
|
EXPORT_SYMBOL(iwl_connection_init_rx_config);
|
||||||
|
|
||||||
static void iwl_set_rate(struct iwl_priv *priv)
|
void iwl_set_rate(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
const struct ieee80211_supported_band *hw = NULL;
|
const struct ieee80211_supported_band *hw = NULL;
|
||||||
struct ieee80211_rate *rate;
|
struct ieee80211_rate *rate;
|
||||||
|
@ -1017,6 +1018,21 @@ static void iwl_set_rate(struct iwl_priv *priv)
|
||||||
priv->staging_rxon.ofdm_basic_rates =
|
priv->staging_rxon.ofdm_basic_rates =
|
||||||
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(iwl_set_rate);
|
||||||
|
|
||||||
|
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
|
||||||
|
{
|
||||||
|
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->switch_rxon.switch_in_progress) {
|
||||||
|
ieee80211_chswitch_done(priv->vif, is_success);
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
priv->switch_rxon.switch_in_progress = false;
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iwl_chswitch_done);
|
||||||
|
|
||||||
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||||
{
|
{
|
||||||
|
@ -1031,11 +1047,12 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||||
priv->staging_rxon.channel = csa->channel;
|
priv->staging_rxon.channel = csa->channel;
|
||||||
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
|
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
|
||||||
le16_to_cpu(csa->channel));
|
le16_to_cpu(csa->channel));
|
||||||
} else
|
iwl_chswitch_done(priv, true);
|
||||||
|
} else {
|
||||||
IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
|
IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
|
||||||
le16_to_cpu(csa->channel));
|
le16_to_cpu(csa->channel));
|
||||||
|
iwl_chswitch_done(priv, false);
|
||||||
priv->switch_rxon.switch_in_progress = false;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iwl_rx_csa);
|
EXPORT_SYMBOL(iwl_rx_csa);
|
||||||
|
@ -2044,22 +2061,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
|
|
||||||
iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
|
iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
if (iwl_is_associated(priv) &&
|
|
||||||
(le16_to_cpu(priv->active_rxon.channel) != ch) &&
|
|
||||||
priv->cfg->ops->lib->set_channel_switch) {
|
|
||||||
iwl_set_rate(priv);
|
|
||||||
/*
|
|
||||||
* at this point, staging_rxon has the
|
|
||||||
* configuration for channel switch
|
|
||||||
*/
|
|
||||||
ret = priv->cfg->ops->lib->set_channel_switch(priv,
|
|
||||||
ch);
|
|
||||||
if (!ret) {
|
|
||||||
iwl_print_rx_config_cmd(priv);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
priv->switch_rxon.switch_in_progress = false;
|
|
||||||
}
|
|
||||||
set_ch_out:
|
set_ch_out:
|
||||||
/* The list of supported rates and rate mask can be different
|
/* The list of supported rates and rate mask can be different
|
||||||
* for each band; since the band may have changed, reset
|
* for each band; since the band may have changed, reset
|
||||||
|
|
|
@ -175,7 +175,8 @@ struct iwl_lib_ops {
|
||||||
void (*dump_nic_error_log)(struct iwl_priv *priv);
|
void (*dump_nic_error_log)(struct iwl_priv *priv);
|
||||||
void (*dump_csr)(struct iwl_priv *priv);
|
void (*dump_csr)(struct iwl_priv *priv);
|
||||||
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
|
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
|
||||||
int (*set_channel_switch)(struct iwl_priv *priv, u16 channel);
|
int (*set_channel_switch)(struct iwl_priv *priv,
|
||||||
|
struct ieee80211_channel_switch *ch_switch);
|
||||||
/* power management */
|
/* power management */
|
||||||
struct iwl_apm_ops apm_ops;
|
struct iwl_apm_ops apm_ops;
|
||||||
|
|
||||||
|
@ -345,11 +346,15 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
|
||||||
int iwl_full_rxon_required(struct iwl_priv *priv);
|
int iwl_full_rxon_required(struct iwl_priv *priv);
|
||||||
void iwl_set_rxon_chain(struct iwl_priv *priv);
|
void iwl_set_rxon_chain(struct iwl_priv *priv);
|
||||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
||||||
|
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||||
|
enum ieee80211_band band,
|
||||||
|
struct ieee80211_vif *vif);
|
||||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
||||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||||
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
||||||
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||||
struct ieee80211_vif *vif);
|
struct ieee80211_vif *vif);
|
||||||
|
void iwl_set_rate(struct iwl_priv *priv);
|
||||||
int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
||||||
struct ieee80211_hdr *hdr,
|
struct ieee80211_hdr *hdr,
|
||||||
u32 decrypt_res,
|
u32 decrypt_res,
|
||||||
|
@ -461,6 +466,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
||||||
struct iwl_rx_mem_buffer *rxb);
|
struct iwl_rx_mem_buffer *rxb);
|
||||||
void iwl_reply_statistics(struct iwl_priv *priv,
|
void iwl_reply_statistics(struct iwl_priv *priv,
|
||||||
struct iwl_rx_mem_buffer *rxb);
|
struct iwl_rx_mem_buffer *rxb);
|
||||||
|
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
|
||||||
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||||
|
|
||||||
/* TX helpers */
|
/* TX helpers */
|
||||||
|
|
Loading…
Reference in New Issue