Commit 56771e50 authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

carl9170: remove fast channel change feature

Marco Fonseca reported a issue with his carl9170 device:
"I'm seeing a problem with the carl driver. If I change channels
repeatedly on the 2.4ghz band, monitoring (e.g. tcpdump) will
eventually halt.  I've seen this on various versions of the carl
driver/firmware (both from 1.9.4 to 1.9.7)"
<http://marc.info/?l=linux-wireless&m=136381302428113>

The culprit was identified as "fast channel change feature" which
according to Adrian Chadd is: "... notoriously unreliable and
really only fully debugged on some very later chips."
<http://marc.info/?l=linux-wireless&m=136416984531380>

Therefore, this patch removes the fast channel change feature.
The phy will now always have to go through a cold reset when
changing channels, but it should no longer become deaf.

Cc: Marco Fonseca <marco@tampabay.rr.com>
Signed-off-by: default avatarChristian Lamparter <chunkeey@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent fe21bb02
......@@ -70,12 +70,6 @@
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
enum carl9170_rf_init_mode {
CARL9170_RFI_NONE,
CARL9170_RFI_WARM,
CARL9170_RFI_COLD,
};
#define CARL9170_MAX_RX_BUFFER_SIZE 8192
enum carl9170_device_state {
......@@ -599,7 +593,7 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
/* PHY / RF */
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
enum nl80211_channel_type bw);
int carl9170_get_noisefloor(struct ar9170 *ar);
/* FW */
......
......@@ -655,7 +655,7 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
case 'P':
err = carl9170_set_channel(ar, ar->hw->conf.channel,
ar->hw->conf.channel_type, CARL9170_RFI_COLD);
ar->hw->conf.channel_type);
if (err < 0)
count = err;
......
......@@ -939,7 +939,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
goto out;
err = carl9170_set_channel(ar, hw->conf.channel,
hw->conf.channel_type, CARL9170_RFI_NONE);
hw->conf.channel_type);
if (err)
goto out;
......
......@@ -1569,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type)
}
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
enum nl80211_channel_type _bw,
enum carl9170_rf_init_mode rfi)
enum nl80211_channel_type _bw)
{
const struct carl9170_phy_freq_params *freqpar;
struct carl9170_rf_init_result rf_res;
struct carl9170_rf_init rf;
u32 cmd, tmp, offs = 0, new_ht = 0;
u32 tmp, offs = 0, new_ht = 0;
int err;
enum carl9170_bw bw;
bool warm_reset;
struct ieee80211_channel *old_channel = NULL;
bw = nl80211_to_carl(_bw);
......@@ -1592,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
/* may be NULL at first setup */
if (ar->channel) {
old_channel = ar->channel;
warm_reset = (old_channel->band != channel->band) ||
(old_channel->center_freq ==
channel->center_freq) ||
(ar->ht_settings != new_ht);
ar->channel = NULL;
} else {
warm_reset = true;
}
/* HW workaround */
if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
channel->center_freq <= 2417)
warm_reset = true;
if (rfi != CARL9170_RFI_NONE || warm_reset) {
u32 val;
if (rfi == CARL9170_RFI_COLD)
val = AR9170_PWR_RESET_BB_COLD_RESET;
else
val = AR9170_PWR_RESET_BB_WARM_RESET;
/* warm/cold reset BB/ADDA */
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
if (err)
return err;
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
if (err)
return err;
/* cold reset BB/ADDA */
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET,
AR9170_PWR_RESET_BB_COLD_RESET);
if (err)
return err;
err = carl9170_init_phy(ar, channel->band);
if (err)
return err;
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
if (err)
return err;
err = carl9170_init_rf_banks_0_7(ar,
channel->band == IEEE80211_BAND_5GHZ);
if (err)
return err;
err = carl9170_init_phy(ar, channel->band);
if (err)
return err;
cmd = CARL9170_CMD_RF_INIT;
} else {
cmd = CARL9170_CMD_FREQUENCY;
}
err = carl9170_init_rf_banks_0_7(ar,
channel->band == IEEE80211_BAND_5GHZ);
if (err)
return err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
if (err)
......@@ -1648,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return err;
err = carl9170_init_rf_bank4_pwr(ar,
channel->band == IEEE80211_BAND_5GHZ,
channel->center_freq, bw);
channel->band == IEEE80211_BAND_5GHZ,
channel->center_freq, bw);
if (err)
return err;
......@@ -1703,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man);
rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
if (rfi != CARL9170_RFI_NONE)
rf.finiteLoopCount = cpu_to_le32(2000);
else
rf.finiteLoopCount = cpu_to_le32(1000);
err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
rf.finiteLoopCount = cpu_to_le32(2000);
err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf,
sizeof(rf_res), &rf_res);
if (err)
return err;
......@@ -1724,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
old_channel->center_freq : -1, channel->center_freq,
err);
if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
/*
* We have tried very hard to change to _another_
if (ar->chan_fail > 3) {
/* We have tried very hard to change to _another_
* channel and we've failed to do so!
* Chances are that the PHY/RF is no longer
* operable (due to corruptions/fatal events/bugs?)
......@@ -1736,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return 0;
}
err = carl9170_set_channel(ar, channel, _bw,
CARL9170_RFI_COLD);
err = carl9170_set_channel(ar, channel, _bw);
if (err)
return err;
} else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment