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: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:

zatwierdzone przez
John W. Linville

rodzic
fe21bb02ca
commit
56771e5054
@@ -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;
|
||||
/* cold reset BB/ADDA */
|
||||
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET,
|
||||
AR9170_PWR_RESET_BB_COLD_RESET);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (rfi != CARL9170_RFI_NONE || warm_reset) {
|
||||
u32 val;
|
||||
err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (rfi == CARL9170_RFI_COLD)
|
||||
val = AR9170_PWR_RESET_BB_COLD_RESET;
|
||||
else
|
||||
val = AR9170_PWR_RESET_BB_WARM_RESET;
|
||||
err = carl9170_init_phy(ar, channel->band);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* 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;
|
||||
|
||||
err = carl9170_init_phy(ar, channel->band);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = carl9170_init_rf_banks_0_7(ar,
|
||||
channel->band == IEEE80211_BAND_5GHZ);
|
||||
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 {
|
||||
|
Reference in New Issue
Block a user