* [PATCH 2.6.30 v2] iwl3945: fix rfkill switch
From: Stanislaw Gruszka @ 2009-08-13 12:29 UTC (permalink / raw)
To: stable
Cc: linux-wireless, Zhu Yi, Reinette Chatre, John W. Linville,
Stanislaw Gruszka
Due to rfkill and iwlwifi mishmash of SW / HW killswitch representation,
we have race conditions which make unable turn wifi radio on, after enable
and disable again killswitch. I can observe this problem on my laptop
with iwl3945 device.
In rfkill core HW switch and SW switch are separate 'states'. Device can
be only in one of 3 states: RFKILL_STATE_SOFT_BLOCKED, RFKILL_STATE_UNBLOCKED,
RFKILL_STATE_HARD_BLOCKED. Whereas in iwlwifi driver we have separate bits
STATUS_RF_KILL_HW and STATUS_RF_KILL_SW for HW and SW switches - radio can be
turned on, only if both bits are cleared.
In this particular race conditions, radio can not be turned on if in driver
STATUS_RF_KILL_SW bit is set, and rfkill core is in state
RFKILL_STATE_HARD_BLOCKED, because rfkill core is unable to call
rfkill->toggle_radio(). This situation can be entered in case:
- killswitch is turned on
- rfkill core 'see' button change first and move to RFKILL_STATE_SOFT_BLOCKED
also call ->toggle_radio() and STATE_RF_KILL_SW in driver is set
- iwl3945 get info about button from hardware to set STATUS_RF_KILL_HW bit and
force rfkill to move to RFKILL_STATE_HARD_BLOCKED
- killsiwtch is turend off
- driver clear STATUS_RF_KILL_HW
- rfkill core is unable to clear STATUS_RF_KILL_SW in driver
Additionally call to rfkill_epo() when STATUS_RF_KILL_HW in driver is set
cause move to the same situation.
In 2.6.31 this problem is fixed due to _total_ rewrite of rfkill subsystem.
This is a quite small fix for 2.6.30.x in iwlwifi driver. We are changing
internal rfkill state to always have below relations true:
STATUS_RF_KILL_HW=1 STATUS_RF_KILL_SW=1 <-> RFKILL_STATUS_SOFT_BLOCKED
STATUS_RF_KILL_HW=0 STATUS_RF_KILL_SW=1 <-> RFKILL_STATUS_SOFT_BLOCKED
STATUS_RF_KILL_HW=1 STATUS_RF_KILL_SW=0 <-> RFKILL_STATUS_HARD_BLOCKED
STATUS_RF_KILL_HW=0 STATUS_RF_KILL_SW=0 <-> RFKILL_STATUS_UNBLOCKED
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
Patch was tested by me only with iwl3945 device.
drivers/net/wireless/iwlwifi/iwl-rfkill.c | 26 ++++++++++++++++----------
1 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index 2ad9faf..fc3a95f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -53,22 +53,31 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
switch (state) {
case RFKILL_STATE_UNBLOCKED:
if (iwl_is_rfkill_hw(priv)) {
+ /* pass error to rfkill core, make it state HARD
+ * BLOCKED (rfkill->mutex taken) and disable
+ * software kill switch */
err = -EBUSY;
- goto out_unlock;
+ priv->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
}
iwl_radio_kill_sw_enable_radio(priv);
break;
case RFKILL_STATE_SOFT_BLOCKED:
iwl_radio_kill_sw_disable_radio(priv);
+ /* rfkill->mutex is taken */
+ if (priv->rfkill->state == RFKILL_STATE_HARD_BLOCKED) {
+ /* force rfkill core state to be SOFT BLOCKED,
+ * otherwise core will be unable to disable software
+ * kill switch */
+ priv->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
+ }
break;
default:
IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
state);
break;
}
-out_unlock:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->mutex);
return err;
}
@@ -132,14 +141,11 @@ void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
if (!priv->rfkill)
return;
- if (iwl_is_rfkill_hw(priv)) {
+ if (iwl_is_rfkill_sw(priv))
+ rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
+ else if (iwl_is_rfkill_hw(priv))
rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
- return;
- }
-
- if (!iwl_is_rfkill_sw(priv))
- rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
else
- rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
+ rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
--
1.6.2.5
^ permalink raw reply related
* [PATCH v3] b43: Implement RC calibration for rev.0/1 LP-PHYs
From: Gábor Stefanik @ 2009-08-13 12:19 UTC (permalink / raw)
To: John Linville, Michael Buesch, Larry Finger
Cc: Broadcom Wireless, linux-wireless
Also implement get/set BB mult, get/set TX gain, set RX gain,
disable/restore CRS, run/stop DDFS, RX IQ est and QDIV roundup
in the process.
Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
Changes from v2->v3:
-Two small spec updates/typo fixes, as suggested by Larry.
Changes from v1->v2:
-Coding style fixes as suggested by Michael.
-Added missing static to lpphy_qdiv_roundup.
-Moved set_tx_power_control & related functions before rev0/1 RC calibration,
and removed forward declaration
-Reordered variable declarations at the start of rev0_1_rc_calib.
-The ideal power table is now static const.
Interdiff v1->v2 available @ http://b43.pastebin.com/f5fe6ba3c for easier review.
drivers/net/wireless/b43/phy_lp.c | 507 +++++++++++++++++++++++++++++++++----
1 files changed, 460 insertions(+), 47 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 689c932..2441a8d 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -605,6 +605,8 @@ static void lpphy_radio_init(struct b43_wldev *dev)
}
}
+struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
+
static void lpphy_set_rc_cap(struct b43_wldev *dev)
{
u8 rc_cap = dev->phy.lp->rc_cap;
@@ -614,79 +616,326 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev)
b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80);
}
-static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
+static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
{
- //TODO and SPEC FIXME
+ return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
}
-static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
+static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
{
- struct ssb_bus *bus = dev->dev->bus;
- u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
- u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
- int i;
+ b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
+}
- b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
- b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
- b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
- b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
- b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
- b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
- b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
- b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
- b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
+static void lpphy_disable_crs(struct b43_wldev *dev)
+{
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
+ b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
+}
- for (i = 0; i < 10000; i++) {
- if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
- break;
- msleep(1);
+static void lpphy_restore_crs(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60);
+ else
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
+}
+
+struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
+
+static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
+{
+ struct lpphy_tx_gains gains;
+ u16 tmp;
+
+ gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
+ if (dev->phy.rev < 2) {
+ tmp = b43_phy_read(dev,
+ B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
+ gains.gm = tmp & 0x0007;
+ gains.pga = (tmp & 0x0078) >> 3;
+ gains.pad = (tmp & 0x780) >> 7;
+ } else {
+ tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
+ gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
+ gains.gm = tmp & 0xFF;
+ gains.pga = (tmp >> 8) & 0xFF;
}
- if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
- b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
+ return gains;
+}
- tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
+static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
+{
+ u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
+ ctl |= dac << 7;
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
+}
- b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
- b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
- b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
- b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
- b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
+static void lpphy_set_tx_gains(struct b43_wldev *dev,
+ struct lpphy_tx_gains gains)
+{
+ u16 rf_gain, pa_gain;
- if (crystal_freq == 24000000) {
- b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
- b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
+ if (dev->phy.rev < 2) {
+ rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
+ b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ 0xF800, rf_gain);
} else {
- b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
- b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+ pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00;
+ b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ (gains.pga << 8) | gains.gm);
+ b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ 0x8000, gains.pad | pa_gain);
+ b43_phy_write(dev, B43_PHY_OFDM(0xFC),
+ (gains.pga << 8) | gains.gm);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
+ 0x8000, gains.pad | pa_gain);
}
+ lpphy_set_dac_gain(dev, gains.dac);
+ if (dev->phy.rev < 2) {
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
+ } else {
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
+ }
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4);
+}
- b43_radio_write(dev, B2063_PA_SP7, 0x7D);
+static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ u16 trsw = gain & 0x1;
+ u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
+ u16 ext_lna = (gain & 2) >> 1;
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFBFF, ext_lna << 10);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xF7FF, ext_lna << 11);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
+}
- for (i = 0; i < 10000; i++) {
- if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ u16 low_gain = gain & 0xFFFF;
+ u16 high_gain = (gain >> 16) & 0xF;
+ u16 ext_lna = (gain >> 21) & 0x1;
+ u16 trsw = ~(gain >> 20) & 0x1;
+ u16 tmp;
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFDFF, ext_lna << 9);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFBFF, ext_lna << 10);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ tmp = (gain >> 2) & 0x3;
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xE7FF, tmp<<11);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
+ }
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+ if (dev->phy.rev >= 2) {
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+ if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+ return;
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7);
+ } else {
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
+ }
+}
+
+static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
+{
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+ if (dev->phy.rev >= 2) {
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+ if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+ return;
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8);
+ } else {
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
+ }
+}
+
+static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ if (dev->phy.rev < 2)
+ lpphy_rev0_1_set_rx_gain(dev, gain);
+ else
+ lpphy_rev2plus_set_rx_gain(dev, gain);
+ lpphy_enable_rx_gain_override(dev);
+}
+
+static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
+{
+ u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
+ lpphy_set_rx_gain(dev, gain);
+}
+
+static void lpphy_stop_ddfs(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
+ b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
+}
+
+static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
+ int incr1, int incr2, int scale_idx)
+{
+ lpphy_stop_ddfs(dev);
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
+ b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
+ b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20);
+}
+
+static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
+ struct lpphy_iq_est *iq_est)
+{
+ int i;
+
+ b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
+ b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
+ b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
+ b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
+ b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF);
+
+ for (i = 0; i < 500; i++) {
+ if (!(b43_phy_read(dev,
+ B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
break;
msleep(1);
}
- if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
- b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
+ if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
+ b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+ return false;
+ }
- b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+ iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
+ iq_est->iq_prod <<= 16;
+ iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
+
+ iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
+ iq_est->i_pwr <<= 16;
+ iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
+
+ iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
+ iq_est->q_pwr <<= 16;
+ iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
+
+ b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+ return true;
}
-static void lpphy_calibrate_rc(struct b43_wldev *dev)
+static int lpphy_loopback(struct b43_wldev *dev)
{
- struct b43_phy_lp *lpphy = dev->phy.lp;
+ struct lpphy_iq_est iq_est;
+ int i, index = -1;
+ u32 tmp;
+
+ memset(&iq_est, 0, sizeof(iq_est));
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+ b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
+ b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
+ for (i = 0; i < 32; i++) {
+ lpphy_set_rx_gain_by_index(dev, i);
+ lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
+ if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+ continue;
+ tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
+ if ((tmp > 4000) && (tmp < 10000)) {
+ index = i;
+ break;
+ }
+ }
+ lpphy_stop_ddfs(dev);
+ return index;
+}
- if (dev->phy.rev >= 2) {
- lpphy_rev2plus_rc_calib(dev);
- } else if (!lpphy->rc_cap) {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- lpphy_rev0_1_rc_calib(dev);
+static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+ u32 quotient, remainder, rbit, roundup, tmp;
+
+ if (divisor == 0) {
+ quotient = 0;
+ remainder = 0;
} else {
- lpphy_set_rc_cap(dev);
+ quotient = dividend / divisor;
+ remainder = dividend % divisor;
}
+
+ rbit = divisor & 0x1;
+ roundup = (divisor >> 1) + rbit;
+ precision--;
+
+ while (precision != 0xFF) {
+ tmp = remainder - roundup;
+ quotient <<= 1;
+ remainder <<= 1;
+ if (remainder >= roundup) {
+ remainder = (tmp << 1) + rbit;
+ quotient--;
+ }
+ precision--;
+ }
+
+ if (remainder >= roundup)
+ quotient++;
+
+ return quotient;
}
/* Read the TX power control mode from hardware. */
@@ -773,6 +1022,170 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
lpphy_write_tx_pctl_mode_to_hardware(dev);
}
+static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+ struct lpphy_iq_est iq_est;
+ struct lpphy_tx_gains tx_gains;
+ static const u32 ideal_pwr_table[22] = {
+ 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
+ 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
+ 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
+ 0x0004c, 0x0002c, 0x0001a, 0xc0006,
+ };
+ bool old_txg_ovr;
+ u8 old_bbmult;
+ u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
+ old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl;
+ u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
+ int loopback, i, j, inner_sum;
+
+ memset(&iq_est, 0, sizeof(iq_est));
+
+ b43_switch_channel(dev, 7);
+ old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1;
+ old_bbmult = lpphy_get_bb_mult(dev);
+ if (old_txg_ovr)
+ tx_gains = lpphy_get_tx_gains(dev);
+ old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
+ old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
+ old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
+ old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
+ old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
+ old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
+ old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
+ old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) &
+ B43_LPPHY_TX_PWR_CTL_CMD_MODE;
+
+ lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
+ lpphy_disable_crs(dev);
+ loopback = lpphy_loopback(dev);
+ if (loopback == -1)
+ goto finish;
+ lpphy_set_rx_gain_by_index(dev, loopback);
+ b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
+ for (i = 128; i <= 159; i++) {
+ b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
+ inner_sum = 0;
+ for (j = 5; j <= 25; j++) {
+ lpphy_run_ddfs(dev, 1, 1, j, j, 0);
+ if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+ goto finish;
+ mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
+ if (j == 5)
+ tmp = mean_sq_pwr;
+ ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
+ normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
+ mean_sq_pwr = ideal_pwr - normal_pwr;
+ mean_sq_pwr *= mean_sq_pwr;
+ inner_sum += mean_sq_pwr;
+ if ((i = 128) || (inner_sum < mean_sq_pwr_min)) {
+ lpphy->rc_cap = i;
+ mean_sq_pwr_min = inner_sum;
+ }
+ }
+ }
+ lpphy_stop_ddfs(dev);
+
+finish:
+ lpphy_restore_crs(dev);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
+ b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
+ b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
+ b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
+
+ lpphy_set_bb_mult(dev, old_bbmult);
+ if (old_txg_ovr) {
+ /*
+ * SPEC FIXME: The specs say "get_tx_gains" here, which is
+ * illogical. According to lwfinger, vendor driver v4.150.10.5
+ * has a Set here, while v4.174.64.19 has a Get - regression in
+ * the vendor driver? This should be tested this once the code
+ * is testable.
+ */
+ lpphy_set_tx_gains(dev, tx_gains);
+ }
+ lpphy_set_tx_power_control(dev, old_txpctl);
+ if (lpphy->rc_cap)
+ lpphy_set_rc_cap(dev);
+}
+
+static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
+ u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
+ int i;
+
+ b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+ b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+ break;
+ msleep(1);
+ }
+
+ if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+ b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
+
+ tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
+
+ b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
+
+ if (crystal_freq == 24000000) {
+ b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
+ } else {
+ b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+ }
+
+ b43_radio_write(dev, B2063_PA_SP7, 0x7D);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+ break;
+ msleep(1);
+ }
+
+ if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+ b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
+
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+}
+
+static void lpphy_calibrate_rc(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+
+ if (dev->phy.rev >= 2) {
+ lpphy_rev2plus_rc_calib(dev);
+ } else if (!lpphy->rc_cap) {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ lpphy_rev0_1_rc_calib(dev);
+ } else {
+ lpphy_set_rc_cap(dev);
+ }
+}
+
static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
--
1.6.2.4
^ permalink raw reply related
* Re: [PATCH] nl80211 connect API support
From: Jouni Malinen @ 2009-08-13 10:46 UTC (permalink / raw)
To: Zhu Yi
Cc: hostap@lists.shmoo.com, linux-wireless@vger.kernel.org,
Johannes Berg, Samuel Ortiz
In-Reply-To: <1250155777.4972.9.camel@debian>
On Thu, Aug 13, 2009 at 05:29:37PM +0800, Zhu Yi wrote:
> The connect API wraps auth/assoc commands in cfg80211 SME. For example,
> when cfg80211 receives NL80211_CMD_CONNECT (cfg80211_connect), it checks
> if connect API is supported or not. If it is not supported (for all
> mac80211 based drivers), it uses the common cfg80211_conn_do_work() to
> do auth/assoc the same way as it handles NL80211_CMD_AUTHENTICATE. So
> from user space point of view, if connect API is supported, it can use
> it directly and let cfg80211 to maintain the state of auth and assoc.
It is not about whether it would be possible to use connect or not; it
is about whether the additional features provided by separate auth/assoc
commands are of use--and they are. wpa_supplicant will provide more
functionality, e.g., FT, when using these commands. Any change to add
support for the new NL80211_CMD_CONNECT must not break this existing
mechanism; it is only to add support for drivers that cannot support the
auth/assoc interface that provides more control to user space.
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply
* Re: [PATCH] cfg80211: set SME state machine correctly for roam event
From: Johannes Berg @ 2009-08-13 9:54 UTC (permalink / raw)
To: Zhu Yi; +Cc: linville, linux-wireless
In-Reply-To: <1250155399-17847-1-git-send-email-yi.zhu@intel.com>
[-- Attachment #1: Type: text/plain, Size: 1083 bytes --]
On Thu, 2009-08-13 at 17:23 +0800, Zhu Yi wrote:
> When we receive a successful status in CFG80211_SME_CONNECTED state,
> it is a roam event. We should mark it as a success result.
But there's a cfg80211_roamed() call for that? Can the driver not tell
the difference? It also sends a different event (ROAMED rather than
CONNECTED) to userspace.
johannes
> Cc: Johannes Berg <johannes@sipsolutions.net>
> Signed-off-by: Zhu Yi <yi.zhu@intel.com>
> ---
> net/wireless/sme.c | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/net/wireless/sme.c b/net/wireless/sme.c
> index 8e2ef54..1aa1190 100644
> --- a/net/wireless/sme.c
> +++ b/net/wireless/sme.c
> @@ -393,7 +393,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
> }
>
> if (status == WLAN_STATUS_SUCCESS &&
> - wdev->sme_state == CFG80211_SME_IDLE)
> + (wdev->sme_state == CFG80211_SME_IDLE ||
> + wdev->sme_state == CFG80211_SME_CONNECTED))
> goto success;
>
> if (wdev->sme_state != CFG80211_SME_CONNECTING)
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: Roaming behavior
From: David Seira @ 2009-08-13 9:44 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1250061248.13529.94.camel@johannes.local>
But I haven't installed wpa_supplicant, I don't need it. In which files is
roaming behavior implemented?
Regards,
David
^ permalink raw reply
* Re: [PATCH] nl80211 connect API support
From: Zhu Yi @ 2009-08-13 9:29 UTC (permalink / raw)
To: Jouni Malinen
Cc: hostap@lists.shmoo.com, linux-wireless@vger.kernel.org,
Johannes Berg, Samuel Ortiz
In-Reply-To: <20090813091103.GA1826@jm.kir.nu>
Hi Jouni,
On Thu, 2009-08-13 at 17:11 +0800, Jouni Malinen wrote:
> On Thu, Aug 13, 2009 at 04:55:31PM +0800, Zhu Yi wrote:
>
> > - * authenticate - Request driver to authenticate
> > + * authenticate - Request driver to authenticate (deprecated)
>
> > + * This is an optional function that to make compatibility for wireless
> > + * stack that doesn't support connect API when driver SME is used
> > + * (WPA_DRIVER_FLAGS_SME).
>
> Thanks for the patch. If I understood this correctly, wpa_supplicant
> would be converted to use the new connect command whenever it is
> supported. While it is nice to get support for connect added, this is
> not how it should be done as it breaks all the new work we have been
> enabling with mac80211. The separate auth/assoc commands should be the
> default operation and only if the driver does not support this, should
> the connect command be used.
The connect API wraps auth/assoc commands in cfg80211 SME. For example,
when cfg80211 receives NL80211_CMD_CONNECT (cfg80211_connect), it checks
if connect API is supported or not. If it is not supported (for all
mac80211 based drivers), it uses the common cfg80211_conn_do_work() to
do auth/assoc the same way as it handles NL80211_CMD_AUTHENTICATE. So
from user space point of view, if connect API is supported, it can use
it directly and let cfg80211 to maintain the state of auth and assoc.
Thanks,
-yi
^ permalink raw reply
* [PATCH] cfg80211: set SME state machine correctly for roam event
From: Zhu Yi @ 2009-08-13 9:23 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Zhu Yi, Johannes Berg
When we receive a successful status in CFG80211_SME_CONNECTED state,
it is a roam event. We should mark it as a success result.
Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
net/wireless/sme.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8e2ef54..1aa1190 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -393,7 +393,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
}
if (status == WLAN_STATUS_SUCCESS &&
- wdev->sme_state == CFG80211_SME_IDLE)
+ (wdev->sme_state == CFG80211_SME_IDLE ||
+ wdev->sme_state == CFG80211_SME_CONNECTED))
goto success;
if (wdev->sme_state != CFG80211_SME_CONNECTING)
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH] nl80211 connect API support
From: Jouni Malinen @ 2009-08-13 9:11 UTC (permalink / raw)
To: Zhu Yi; +Cc: hostap, linux-wireless, Johannes Berg, Samuel Ortiz
In-Reply-To: <1250153731-17208-2-git-send-email-yi.zhu@intel.com>
On Thu, Aug 13, 2009 at 04:55:31PM +0800, Zhu Yi wrote:
> - * authenticate - Request driver to authenticate
> + * authenticate - Request driver to authenticate (deprecated)
> + * This is an optional function that to make compatibility for wireless
> + * stack that doesn't support connect API when driver SME is used
> + * (WPA_DRIVER_FLAGS_SME).
Thanks for the patch. If I understood this correctly, wpa_supplicant
would be converted to use the new connect command whenever it is
supported. While it is nice to get support for connect added, this is
not how it should be done as it breaks all the new work we have been
enabling with mac80211. The separate auth/assoc commands should be the
default operation and only if the driver does not support this, should
the connect command be used.
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply
* [PATCH] nl80211 connect API support
From: Zhu Yi @ 2009-08-13 8:55 UTC (permalink / raw)
To: j; +Cc: hostap, linux-wireless, Zhu Yi, Johannes Berg, Samuel Ortiz
In-Reply-To: <1250153731-17208-1-git-send-email-yi.zhu@intel.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
src/common/ieee802_11_defs.h | 15 ++
src/common/nl80211_copy.h | 65 +++++++++
src/drivers/driver.h | 28 +++-
src/drivers/driver_nl80211.c | 289 ++++++++++++++++++++++++++++++++++++-
wpa_supplicant/driver_i.h | 18 +++
wpa_supplicant/sme.c | 43 +++++--
wpa_supplicant/sme.h | 15 ++-
wpa_supplicant/wpa_supplicant.c | 9 +-
wpa_supplicant/wpa_supplicant_i.h | 2 +
9 files changed, 455 insertions(+), 29 deletions(-)
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index b4c804e..e1bd487 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -679,4 +679,19 @@ enum {
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
+/* reserved: 0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
+#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X 0x000FAC01
+#define WLAN_AKM_SUITE_PSK 0x000FAC02
+
+#define WLAN_MAX_KEY_LEN 32
+
#endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/nl80211_copy.h b/src/common/nl80211_copy.h
index dbea93b..c019a16 100644
--- a/src/common/nl80211_copy.h
+++ b/src/common/nl80211_copy.h
@@ -310,6 +310,14 @@ enum nl80211_commands {
NL80211_CMD_JOIN_IBSS,
NL80211_CMD_LEAVE_IBSS,
+ NL80211_CMD_TESTMODE,
+
+ NL80211_CMD_CONNECT,
+ NL80211_CMD_ROAM,
+ NL80211_CMD_DISCONNECT,
+
+ NL80211_CMD_SET_WIPHY_NETNS,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -619,6 +627,28 @@ enum nl80211_attrs {
NL80211_ATTR_CONTROL_PORT,
+ NL80211_ATTR_TESTDATA,
+
+ NL80211_ATTR_PRIVACY,
+
+ NL80211_ATTR_DISCONNECTED_BY_AP,
+ NL80211_ATTR_STATUS_CODE,
+
+ NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ NL80211_ATTR_CIPHER_SUITE_GROUP,
+ NL80211_ATTR_WPA_VERSIONS,
+ NL80211_ATTR_AKM_SUITES,
+
+ NL80211_ATTR_REQ_IE,
+ NL80211_ATTR_RESP_IE,
+
+ NL80211_ATTR_PREV_BSSID,
+
+ NL80211_ATTR_KEY,
+ NL80211_ATTR_KEYS,
+
+ NL80211_ATTR_PID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1224,4 +1254,39 @@ enum nl80211_mfp {
NL80211_MFP_REQUIRED,
};
+enum nl80211_wpa_versions {
+ NL80211_WPA_VERSION_1 = 1 << 0,
+ NL80211_WPA_VERSION_2 = 1 << 1,
+};
+
+/**
+ * enum nl80211_key_attributes - key attributes
+ * @__NL80211_KEY_INVALID: invalid
+ * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ * @NL80211_KEY_DEFAULT: flag indicating default key
+ * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
+ * @__NL80211_KEY_AFTER_LAST: internal
+ * @NL80211_KEY_MAX: highest key attribute
+ */
+enum nl80211_key_attributes {
+ __NL80211_KEY_INVALID,
+ NL80211_KEY_DATA,
+ NL80211_KEY_IDX,
+ NL80211_KEY_CIPHER,
+ NL80211_KEY_SEQ,
+ NL80211_KEY_DEFAULT,
+ NL80211_KEY_DEFAULT_MGMT,
+
+ /* keep last */
+ __NL80211_KEY_AFTER_LAST,
+ NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2ae5b1a..cc56124 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -444,6 +444,8 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS_SME 0x00000020
/* Driver supports AP mode */
#define WPA_DRIVER_FLAGS_AP 0x00000040
+/* Driver supports connect API */
+#define WPA_DRIVER_FLAGS_CONNECT 0x00000080
unsigned int flags;
int max_scan_ssids;
@@ -1184,16 +1186,14 @@ struct wpa_driver_ops {
int (*scan2)(void *priv, struct wpa_driver_scan_params *params);
/**
- * authenticate - Request driver to authenticate
+ * authenticate - Request driver to authenticate (deprecated)
* @priv: private driver interface data
* @params: authentication parameters
* Returns: 0 on success, -1 on failure
*
- * This is an optional function that can be used with drivers that
- * support separate authentication and association steps, i.e., when
- * wpa_supplicant can act as the SME. If not implemented, associate()
- * function is expected to take care of IEEE 802.11 authentication,
- * too.
+ * This is an optional function that to make compatibility for wireless
+ * stack that doesn't support connect API when driver SME is used
+ * (WPA_DRIVER_FLAGS_SME).
*/
int (*authenticate)(void *priv,
struct wpa_driver_auth_params *params);
@@ -1333,6 +1333,22 @@ struct wpa_driver_ops {
* Returns: 0 on success, -1 on failure
*/
int (*set_supp_port)(void *priv, int authorized);
+
+ /**
+ * connect - Request driver to connect
+ * @priv: private driver interface data
+ * @params: connect parameters
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is an optional function that can be used with drivers that
+ * support connect (both authentication and association) step, i.e.,
+ * when wpa_supplicant can act as the SME. If driver SME is not
+ * supported (both connect and authenticate are not implemented),
+ * associate() function is expected to take care of IEEE 802.11
+ * authentication, too.
+ */
+ int (*connect)(void *priv, struct wpa_driver_associate_params *params);
+ int (*disconnect)(void *priv, u8 *addr, int reason_code);
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 9b2bf7c..ca3670c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -739,6 +739,40 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
}
+static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
+ enum nl80211_commands cmd, struct nlattr *status,
+ struct nlattr *addr, struct nlattr *req_ie,
+ struct nlattr *resp_ie)
+{
+ union wpa_event_data event;
+
+ os_memset(&event, 0, sizeof(event));
+ if (cmd == NL80211_CMD_CONNECT &&
+ nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
+ if (resp_ie) {
+ event.assoc_reject.resp_ies = nla_data(resp_ie);
+ event.assoc_reject.resp_ies_len = nla_len(resp_ie);
+ }
+ event.assoc_reject.status_code = nla_get_u16(status);
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
+ return;
+ }
+
+ drv->associated = 1;
+ if (addr)
+ os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
+
+ if (req_ie) {
+ event.assoc_info.req_ies = nla_data(req_ie);
+ event.assoc_info.req_ies_len = nla_len(req_ie);
+ }
+ if (resp_ie) {
+ event.assoc_info.resp_ies = nla_data(resp_ie);
+ event.assoc_info.resp_ies_len = nla_len(resp_ie);
+ }
+
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
+}
static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
enum nl80211_commands cmd, struct nlattr *addr)
@@ -895,6 +929,17 @@ static int process_event(struct nl_msg *msg, void *arg)
mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT]);
break;
+ case NL80211_CMD_CONNECT:
+ case NL80211_CMD_ROAM:
+ mlme_event_connect(drv, gnlh->cmd, tb[NL80211_ATTR_STATUS_CODE],
+ tb[NL80211_ATTR_MAC],
+ tb[NL80211_ATTR_REQ_IE],
+ tb[NL80211_ATTR_RESP_IE]);
+ break;
+ case NL80211_CMD_DISCONNECT:
+ drv->associated = 0;
+ wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
+ break;
#endif /* HOSTAPD */
case NL80211_CMD_MICHAEL_MIC_FAILURE:
mlme_event_michael_mic_failure(drv, tb);
@@ -1003,6 +1048,7 @@ nla_put_failure:
struct wiphy_info_data {
int max_scan_ssids;
int ap_supported;
+ int connect_supported;
};
@@ -1031,6 +1077,19 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
}
}
+ info->connect_supported = 0;
+ if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
+ struct nlattr *nl_cmd;
+ int i;
+
+ nla_for_each_nested(nl_cmd,
+ tb[NL80211_ATTR_SUPPORTED_COMMANDS], i)
+ if (nla_get_u32(nl_cmd) == NL80211_CMD_CONNECT) {
+ info->connect_supported = 1;
+ break;
+ }
+ }
+
return NL_SKIP;
}
@@ -1078,6 +1137,9 @@ static void wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
drv->capa.max_scan_ssids = info.max_scan_ssids;
if (info.ap_supported)
drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
+
+ if (info.connect_supported)
+ drv->capa.flags |= WPA_DRIVER_FLAGS_CONNECT;
}
#endif /* HOSTAPD */
@@ -1658,19 +1720,22 @@ static int nl_set_encr(int ifindex, struct wpa_driver_nl80211_data *drv,
case WPA_ALG_WEP:
if (key_len == 5)
NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- 0x000FAC01);
+ WLAN_CIPHER_SUITE_WEP40);
else
NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- 0x000FAC05);
+ WLAN_CIPHER_SUITE_WEP104);
break;
case WPA_ALG_TKIP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02);
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_TKIP);
break;
case WPA_ALG_CCMP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04);
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_CCMP);
break;
case WPA_ALG_IGTK:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC06);
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_AES_CMAC);
break;
default:
wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
@@ -1737,6 +1802,60 @@ nla_put_failure:
#ifndef HOSTAPD
+static int nl80211_set_conn_keys(void *priv,
+ struct wpa_driver_associate_params *params,
+ struct nl_msg *msg)
+{
+ int i, privacy = 0;
+ struct nlattr *nl_keys, *nl_key;
+
+ for (i = 0; i < 4; i++) {
+ if (!params->wep_key[i])
+ continue;
+ privacy = 1;
+ break;
+ }
+ if (!privacy)
+ return 0;
+
+ NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
+
+ nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
+ if (!nl_keys)
+ goto nla_put_failure;
+
+ for (i = 0; i < 4; i++) {
+ if (!params->wep_key[i])
+ continue;
+
+ nl_key = nla_nest_start(msg, i);
+ if (!nl_key)
+ goto nla_put_failure;
+
+ NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],
+ params->wep_key[i]);
+ if (params->wep_key_len[i] == 5)
+ NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_WEP40);
+ else
+ NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_WEP104);
+
+ NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
+
+ if (i == params->wep_tx_keyidx)
+ NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
+
+ nla_nest_end(msg, nl_key);
+ }
+ nla_nest_end(msg, nl_keys);
+
+ return 0;
+
+nla_put_failure:
+ return -ENOBUFS;
+}
+
static int wpa_driver_nl80211_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx,
int set_tx, const u8 *seq,
@@ -1883,6 +2002,164 @@ nla_put_failure:
return ret;
}
+static int wpa_driver_nl80211_connect(
+ void *priv, struct wpa_driver_associate_params *params)
+{
+ struct wpa_driver_nl80211_data *drv = priv;
+ struct nl_msg *msg;
+ enum nl80211_auth_type type;
+ int ret = 0;
+
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_CONNECT))
+ return -EOPNOTSUPP;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
+ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
+ NL80211_CMD_CONNECT, 0);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (params->bssid) {
+ wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
+ MAC2STR(params->bssid));
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
+ }
+ if (params->freq) {
+ wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
+ }
+ if (params->ssid) {
+ wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
+ params->ssid, params->ssid_len);
+ NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
+ params->ssid);
+ if (params->ssid_len > sizeof(drv->ssid))
+ goto nla_put_failure;
+ os_memcpy(drv->ssid, params->ssid, params->ssid_len);
+ drv->ssid_len = params->ssid_len;
+ }
+ wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
+ if (params->wpa_ie)
+ NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
+ params->wpa_ie);
+
+ if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
+ type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+ else if (params->auth_alg & AUTH_ALG_SHARED_KEY)
+ type = NL80211_AUTHTYPE_SHARED_KEY;
+ else if (params->auth_alg & AUTH_ALG_LEAP)
+ type = NL80211_AUTHTYPE_NETWORK_EAP;
+ else if (params->auth_alg & AUTH_ALG_FT)
+ type = NL80211_AUTHTYPE_FT;
+ else
+ goto nla_put_failure;
+
+ wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
+ NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
+
+ if (params->wpa_ie && params->wpa_ie_len) {
+ enum nl80211_wpa_versions ver;
+
+ if (params->wpa_ie[0] == WLAN_EID_RSN)
+ ver = NL80211_WPA_VERSION_2;
+ else
+ ver = NL80211_WPA_VERSION_1;
+
+ wpa_printf(MSG_DEBUG, " * WPA Version %d", ver);
+ NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
+ }
+
+ if (params->pairwise_suite != CIPHER_NONE) {
+ int cipher = IW_AUTH_CIPHER_NONE;
+
+ switch (params->pairwise_suite) {
+ case CIPHER_WEP40:
+ cipher = WLAN_CIPHER_SUITE_WEP40;
+ break;
+ case CIPHER_WEP104:
+ cipher = WLAN_CIPHER_SUITE_WEP104;
+ break;
+ case CIPHER_CCMP:
+ cipher = WLAN_CIPHER_SUITE_CCMP;
+ break;
+ case CIPHER_TKIP:
+ default:
+ cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
+ }
+
+ if (params->group_suite != CIPHER_NONE) {
+ int cipher = IW_AUTH_CIPHER_NONE;
+
+ switch (params->group_suite) {
+ case CIPHER_WEP40:
+ cipher = WLAN_CIPHER_SUITE_WEP40;
+ break;
+ case CIPHER_WEP104:
+ cipher = WLAN_CIPHER_SUITE_WEP104;
+ break;
+ case CIPHER_CCMP:
+ cipher = WLAN_CIPHER_SUITE_CCMP;
+ break;
+ case CIPHER_TKIP:
+ default:
+ cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
+ }
+
+ if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
+ params->key_mgmt_suite == KEY_MGMT_PSK) {
+ int mgmt = WLAN_AKM_SUITE_PSK;
+
+ switch (params->key_mgmt_suite) {
+ case KEY_MGMT_802_1X:
+ mgmt = WLAN_AKM_SUITE_8021X;
+ break;
+ case KEY_MGMT_PSK:
+ default:
+ mgmt = WLAN_AKM_SUITE_PSK;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
+ }
+
+ ret = nl80211_set_conn_keys(drv, params, msg);
+ if (ret)
+ goto nla_put_failure;
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
+ "(%s)", ret, strerror(-ret));
+ goto nla_put_failure;
+ }
+ ret = 0;
+ wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+
+}
+
+static int wpa_driver_nl80211_disconnect(void *priv, u8 *addr, int reason_code)
+{
+ struct wpa_driver_nl80211_data *drv = priv;
+
+ wpa_printf(MSG_DEBUG, "%s", __func__);
+ drv->associated = 0;
+ return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISCONNECT,
+ reason_code);
+}
+
#endif /* HOSTAPD */
@@ -4060,6 +4337,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.get_capa = wpa_driver_nl80211_get_capa,
.set_operstate = wpa_driver_nl80211_set_operstate,
.set_supp_port = wpa_driver_nl80211_set_supp_port,
+ .connect = wpa_driver_nl80211_connect,
+ .disconnect = wpa_driver_nl80211_disconnect,
#endif /* HOSTAPD */
.set_country = wpa_driver_nl80211_set_country,
.set_mode = wpa_driver_nl80211_set_mode,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 4cb5372..8e59de2 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -448,4 +448,22 @@ static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline int wpa_drv_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_associate_params *params)
+{
+ if (wpa_s->driver->connect)
+ return wpa_s->driver->connect(wpa_s->drv_priv, params);
+
+ return -EOPNOTSUPP;
+}
+
+static inline int wpa_drv_disconnect(struct wpa_supplicant *wpa_s, u8 *addr,
+ int reason_code)
+{
+ if (wpa_s->driver->disconnect)
+ return wpa_s->driver->disconnect(wpa_s->drv_priv, addr,
+ reason_code);
+ return -EOPNOTSUPP;
+}
+
#endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 0d729ef..3582c20 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -27,10 +27,10 @@
#include "wps_supplicant.h"
#include "sme.h"
-void sme_authenticate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *bss, struct wpa_ssid *ssid)
+void sme_connect(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss,
+ struct wpa_ssid *ssid)
{
- struct wpa_driver_auth_params params;
+ struct wpa_driver_associate_params params;
const u8 *ie;
#ifdef CONFIG_IEEE80211R
const u8 *md = NULL;
@@ -181,8 +181,6 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "SME: Trying to use FT "
"over-the-air");
params.auth_alg = AUTH_ALG_FT;
- params.ie = wpa_s->sme.ft_ies;
- params.ie_len = wpa_s->sme.ft_ies_len;
}
}
#endif /* CONFIG_IEEE80211R */
@@ -224,10 +222,37 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
- if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) {
- wpa_msg(wpa_s, MSG_INFO, "Authentication request to the "
- "driver failed");
- return;
+ params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
+ params.wpa_ie = wpa_s->sme.assoc_req_ie;
+ params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
+ params.group_suite = cipher_suite2driver(wpa_s->group_cipher);
+
+ if (wpa_drv_connect(wpa_s, ¶ms) == -EOPNOTSUPP) {
+ struct wpa_driver_auth_params auth;
+
+ os_memset(&auth, 0, sizeof(auth));
+ auth.freq = params.freq;
+ auth.bssid = params.bssid;
+ auth.ssid = params.ssid;
+ auth.ssid_len = params.ssid_len;
+ auth.auth_alg = params.auth_alg;
+ if (auth.auth_alg == AUTH_ALG_FT) {
+ auth.ie = wpa_s->sme.ft_ies;
+ auth.ie_len = wpa_s->sme.ft_ies_len;
+ }
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (params.wep_key_len[i])
+ auth.wep_key[i] = params.wep_key[i];
+ auth.wep_key_len[i] = params.wep_key_len[i];
+ }
+ auth.wep_tx_keyidx = params.wep_tx_keyidx;
+
+ if (wpa_drv_authenticate(wpa_s, &auth) < 0) {
+ wpa_msg(wpa_s, MSG_INFO, "Authentication request to "
+ "the driver failed");
+ return;
+ }
}
/* TODO: add timeout on authentication */
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index 2780041..87804e3 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -17,8 +17,8 @@
#ifdef CONFIG_SME
-void sme_authenticate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *bss, struct wpa_ssid *ssid);
+void sme_connect(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss,
+ struct wpa_ssid *ssid);
void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data);
int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
const u8 *ies, size_t ies_len);
@@ -31,9 +31,9 @@ void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
#else /* CONFIG_SME */
-static inline void sme_authenticate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *bss,
- struct wpa_ssid *ssid)
+static inline void sme_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *bss,
+ struct wpa_ssid *ssid)
{
}
@@ -64,6 +64,11 @@ static inline void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
{
}
+void sme_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *bss, struct wpa_ssid *ssid);
+{
+}
+
#endif /* CONFIG_SME */
#endif /* SME_H */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f1f929a..3797955 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -640,7 +640,7 @@ static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
}
-static wpa_cipher cipher_suite2driver(int cipher)
+wpa_cipher cipher_suite2driver(int cipher)
{
switch (cipher) {
case WPA_CIPHER_NONE:
@@ -658,7 +658,7 @@ static wpa_cipher cipher_suite2driver(int cipher)
}
-static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
+wpa_key_mgmt key_mgmt2driver(int key_mgmt)
{
switch (key_mgmt) {
case WPA_KEY_MGMT_NONE:
@@ -966,7 +966,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
}
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
- sme_authenticate(wpa_s, bss, ssid);
+ sme_connect(wpa_s, bss, ssid);
return;
}
@@ -1303,7 +1303,8 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
if (!is_zero_ether_addr(wpa_s->bssid)) {
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
ieee80211_sta_deauthenticate(wpa_s, reason_code);
- else
+ else if (wpa_drv_disconnect(wpa_s, wpa_s->bssid, reason_code)
+ == -EOPNOTSUPP)
wpa_drv_deauthenticate(wpa_s, wpa_s->bssid,
reason_code);
addr = wpa_s->bssid;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 63984d8..13896d9 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -392,6 +392,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
const char * wpa_supplicant_state_txt(int state);
int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s);
+wpa_cipher cipher_suite2driver(int cipher);
+wpa_key_mgmt key_mgmt2driver(int key_mgmt);
int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *bss,
struct wpa_ssid *ssid,
--
1.6.0.4
^ permalink raw reply related
* [PATCH] Fix cipher overwide problem for 802.1X WEP
From: Zhu Yi @ 2009-08-13 8:55 UTC (permalink / raw)
To: j; +Cc: hostap, linux-wireless, Zhu Yi
We set the cipher_pairwise and cipher_group to WEP104 only if they
are not set already. Otherwise WEP40 has no way to be configured.
This problem is found on 802.1X with static WEP.
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
wpa_supplicant/wpa_supplicant.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index d03e9da..f1f929a 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1116,7 +1116,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
!wep_keys_set) {
use_crypt = 0;
- } else {
+ } else if (cipher_pairwise == WPA_CIPHER_NONE &&
+ cipher_group == WPA_CIPHER_NONE) {
/* Assume that dynamic WEP-104 keys will be used and
* set cipher suites in order for drivers to expect
* encryption. */
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH 2.6.30] iwl3945: fix rfkill switch
From: Stanislaw Gruszka @ 2009-08-13 7:31 UTC (permalink / raw)
To: reinette chatre
Cc: linux-wireless@vger.kernel.org, Zhu, Yi, John W. Linville,
stable@kernel.org
In-Reply-To: <20090811140908.GA3235@dhcp-lab-161.englab.brq.redhat.com>
On Tue, Aug 11, 2009 at 04:09:08PM +0200, Stanislaw Gruszka wrote:
> diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
> index d6b6098..636c04a 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
> @@ -35,6 +35,19 @@
> #include "iwl-dev.h"
> #include "iwl-core.h"
>
> +static void iwl_force_rfkill_state(struct iwl_priv *priv,
> + enum rfkill_state state)
> +{
> + enum rfkill_state oldstate;
> +
> + oldstate = priv->rfkill->state;
> + priv->rfkill->state = state;
> +
> + /* rfkill_uevent() */
> + if (oldstate != state)
> + kobject_uevent(&priv->rfkill->dev.kobj, KOBJ_CHANGE);
This is not needed because rfkill_toggle_radio() will send
rfkill_uevent().
> +}
> +
> /* software rf-kill from user */
> static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
> {
> @@ -54,8 +67,9 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
> case RFKILL_STATE_UNBLOCKED:
> if (iwl_is_rfkill_hw(priv)) {
> err = -EBUSY;
> - /* pass error to rfkill core to make it state HARD
> + /* pass error to rfkill core, make it state HARD
> * BLOCKED and disable software kill switch */
> + iwl_force_rfkill_state(priv, RFKILL_STATE_HARD_BLOCKED);
> }
> iwl_radio_kill_sw_enable_radio(priv);
> break;
> @@ -63,10 +77,10 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
> iwl_radio_kill_sw_disable_radio(priv);
> /* rfkill->mutex lock is taken */
> if (priv->rfkill->state == RFKILL_STATE_HARD_BLOCKED) {
> - /* force rfkill core state to be SOFT BLOCKED,
> + /* force rfkill core state to be in SOFT BLOCKED,
> * otherwise core will be unable to disable software
> * kill switch */
> - priv->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
> + iwl_force_rfkill_state(priv, RFKILL_STATE_SOFT_BLOCKED);
> }
> break;
Stanislaw
^ permalink raw reply
* Re: [PATCH 2.6.30] iwl3945: fix rfkill switch
From: Stanislaw Gruszka @ 2009-08-13 7:28 UTC (permalink / raw)
To: reinette chatre
Cc: linux-wireless@vger.kernel.org, Zhu, Yi, John W. Linville,
stable@kernel.org
In-Reply-To: <1250095502.30019.5951.camel@rc-desk>
On Wed, Aug 12, 2009 at 09:45:02AM -0700, reinette chatre wrote:
> > > I also do not understand the need to modify rfkill's internal state.
> >
> > It's needed for Case1. Additional change of internal rfkill state, which
> > I proposed in previous e-mail is against situation when we have:
> > STATUS_RF_KILL_HW = 1, STATUS_RF_KILL_SW = 0, RFKILL_STATE_SOFT_BLOCKED
> > To make it:
> > STATUS_RF_KILL_HW = 1, STATUS_RF_KILL_SW = 0, RFKILL_STATE_HARD_BLOCKED
>
> ok - this makes sense now. In your previous email you also mentioned
> that that delta patch was untested. Is it possible for you or anybody
> else on that redhat bugzilla to give the new patch a try?
Yes, I'm going to rewrite patch, test and resend it.
> I think I now understand what is going on. Having worked through all the
> possible scenarios makes me more comfortable about his patch considering
> the awkward way in which it is forced to solve the problem. I am really
> glad we do not need to do this moving forward.
I'm happy too.
Thanks
Stanislaw
^ permalink raw reply
* [PATCH 4/4] ath9k: Set HW state properly
From: Sujith @ 2009-08-13 4:04 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
This patch fixes a bug in ath9k_stop() where the HW
was not put into FULL_SLEEP state. Not doing so will
cause issues in suspend-resume and the HW will not respond
to chip resets.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/main.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 4a6f2d2..f452c20 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2140,6 +2140,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah);
ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
sc->sc_flags |= SC_OP_INVALID;
--
1.6.4
^ permalink raw reply related
* [PATCH 3/4] ath9k: Fix bug in PCI resume
From: Sujith @ 2009-08-13 4:04 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
This patch fixes a bug where the device was enabled
before restoring the PCI state.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/pci.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 3546504..616bdff 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -253,10 +253,12 @@ static int ath_pci_resume(struct pci_dev *pdev)
u32 val;
int err;
+ pci_restore_state(pdev);
+
err = pci_enable_device(pdev);
if (err)
return err;
- pci_restore_state(pdev);
+
/*
* Suspend/Resume resets the PCI configuration space, so we have to
* re-disable the RETRY_TIMEOUT register (0x41) to keep
--
1.6.4
^ permalink raw reply related
* [PATCH 2/4] ath9k: Remove duplicate variables
From: Sujith @ 2009-08-13 4:04 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
diversity_control and antenna_switch_swap are already
present in ath9k_ops_config. Remove duplicate occurrences
in ath_hw.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/hw.c | 7 ++-----
drivers/net/wireless/ath/ath9k/hw.h | 16 +++++++---------
drivers/net/wireless/ath/ath9k/phy.c | 12 +++++-------
3 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 0e83e98..6eef7b4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -407,7 +407,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.cck_trig_high = 200;
ah->config.cck_trig_low = 100;
ah->config.enable_ani = 1;
- ah->config.diversity_control = 0;
+ ah->config.diversity_control = ATH9K_ANT_VARIABLE;
ah->config.antenna_switch_swap = 0;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
@@ -452,9 +452,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->regulatory.power_limit = MAX_RATE_POWER;
ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
ah->atim_window = 0;
- ah->diversity_control = ah->config.diversity_control;
- ah->antenna_switch_swap =
- ah->config.antenna_switch_swap;
ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
ah->beacon_interval = 100;
ah->enable_32kHz_clock = DONT_USE_32KHZ;
@@ -3891,7 +3888,7 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
break;
}
} else {
- ah->diversity_control = settings;
+ ah->config.diversity_control = settings;
}
return true;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 0e65873..0336981 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -127,6 +127,12 @@ enum wireless_mode {
ATH9K_MODE_MAX,
};
+enum ath9k_ant_setting {
+ ATH9K_ANT_VARIABLE = 0,
+ ATH9K_ANT_FIXED_A,
+ ATH9K_ANT_FIXED_B
+};
+
enum ath9k_hw_caps {
ATH9K_HW_CAP_MIC_AESCCM = BIT(0),
ATH9K_HW_CAP_MIC_CKIP = BIT(1),
@@ -191,7 +197,7 @@ struct ath9k_ops_config {
u32 cck_trig_high;
u32 cck_trig_low;
u32 enable_ani;
- u16 diversity_control;
+ enum ath9k_ant_setting diversity_control;
u16 antenna_switch_swap;
int serialize_regmode;
bool intr_mitigation;
@@ -330,12 +336,6 @@ enum ath9k_power_mode {
ATH9K_PM_UNDEFINED
};
-enum ath9k_ant_setting {
- ATH9K_ANT_VARIABLE = 0,
- ATH9K_ANT_FIXED_A,
- ATH9K_ANT_FIXED_B
-};
-
enum ath9k_tp_scale {
ATH9K_TP_SCALE_MAX = 0,
ATH9K_TP_SCALE_50,
@@ -437,8 +437,6 @@ struct ath_hw {
u32 txurn_interrupt_mask;
bool chip_fullsleep;
u32 atim_window;
- u16 antenna_switch_swap;
- enum ath9k_ant_setting diversity_control;
/* Calibration */
enum ath9k_cal_types supp_cals;
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c
index 59bb3ce..63bf9a3 100644
--- a/drivers/net/wireless/ath/ath9k/phy.c
+++ b/drivers/net/wireless/ath/ath9k/phy.c
@@ -353,18 +353,16 @@ ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
u32 bank6SelMask;
u32 *bank6Temp = ah->bank6Temp;
- switch (ah->diversity_control) {
+ switch (ah->config.diversity_control) {
case ATH9K_ANT_FIXED_A:
bank6SelMask =
- (ah->
- antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
- REDUCE_CHAIN_1;
+ (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
+ REDUCE_CHAIN_0 : REDUCE_CHAIN_1;
break;
case ATH9K_ANT_FIXED_B:
bank6SelMask =
- (ah->
- antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
- REDUCE_CHAIN_0;
+ (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
+ REDUCE_CHAIN_1 : REDUCE_CHAIN_0;
break;
case ATH9K_ANT_VARIABLE:
return;
--
1.6.4
^ permalink raw reply related
* [PATCH 1/4] ath9k: Remove has_hw_phycounters
From: Sujith @ 2009-08-13 4:04 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
PHY counters are available in all chipsets supported
by ath9k. Remove the check.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/ani.c | 195 +++++++++++++++------------------
drivers/net/wireless/ath/ath9k/ani.h | 1 -
drivers/net/wireless/ath/ath9k/hw.h | 1 -
drivers/net/wireless/ath/ath9k/main.c | 3 +-
4 files changed, 88 insertions(+), 112 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index b709312..f264097 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -236,36 +236,35 @@ static void ath9k_ani_restart(struct ath_hw *ah)
return;
aniState = ah->curani;
-
aniState->listenTime = 0;
- if (ah->has_hw_phycounters) {
- if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
- aniState->ofdmPhyErrBase = 0;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "OFDM Trigger is too high for hw counters\n");
- } else {
- aniState->ofdmPhyErrBase =
- AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
- }
- if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
- aniState->cckPhyErrBase = 0;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "CCK Trigger is too high for hw counters\n");
- } else {
- aniState->cckPhyErrBase =
- AR_PHY_COUNTMAX - aniState->cckTrigHigh;
- }
+
+ if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->ofdmPhyErrBase = 0;
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Writing ofdmbase=%u cckbase=%u\n",
- aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+ "OFDM Trigger is too high for hw counters\n");
+ } else {
+ aniState->ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+ }
+ if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->cckPhyErrBase = 0;
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "CCK Trigger is too high for hw counters\n");
+ } else {
+ aniState->cckPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->cckTrigHigh;
}
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Writing ofdmbase=%u cckbase=%u\n",
+ aniState->ofdmPhyErrBase,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
aniState->ofdmPhyErrCount = 0;
aniState->cckPhyErrCount = 0;
}
@@ -530,18 +529,12 @@ void ath9k_ani_reset(struct ath_hw *ah)
if (aniState->firstepLevel != 0)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel);
- if (ah->has_hw_phycounters) {
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
- ~ATH9K_RX_FILTER_PHYERR);
- ath9k_ani_restart(ah);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
- } else {
- ath9k_ani_restart(ah);
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
- ATH9K_RX_FILTER_PHYERR);
- }
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+ ~ATH9K_RX_FILTER_PHYERR);
+ ath9k_ani_restart(ah);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
}
void ath9k_hw_ani_monitor(struct ath_hw *ah,
@@ -550,6 +543,8 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
{
struct ar5416AniState *aniState;
int32_t listenTime;
+ u32 phyCnt1, phyCnt2;
+ u32 ofdmPhyErrCnt, cckPhyErrCnt;
if (!DO_ANI(ah))
return;
@@ -566,50 +561,45 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
aniState->listenTime += listenTime;
- if (ah->has_hw_phycounters) {
- u32 phyCnt1, phyCnt2;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
+ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "phyCnt1 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1,
- AR_PHY_ERR_OFDM_TIMING);
- }
- if (phyCnt2 < aniState->cckPhyErrBase) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "phyCnt2 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2,
- AR_PHY_ERR_CCK_TIMING);
- }
- return;
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+ if (phyCnt1 < aniState->ofdmPhyErrBase ||
+ phyCnt2 < aniState->cckPhyErrBase) {
+ if (phyCnt1 < aniState->ofdmPhyErrBase) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "phyCnt1 0x%x, resetting "
+ "counter value to 0x%x\n",
+ phyCnt1, aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1,
+ aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+ AR_PHY_ERR_OFDM_TIMING);
+ }
+ if (phyCnt2 < aniState->cckPhyErrBase) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "phyCnt2 0x%x, resetting "
+ "counter value to 0x%x\n",
+ phyCnt2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+ AR_PHY_ERR_CCK_TIMING);
}
+ return;
+ }
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ah->stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ah->stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
- }
+ cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ ah->stats.ast_ani_cckerrs +=
+ cckPhyErrCnt - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = cckPhyErrCnt;
if (aniState->listenTime > 5 * ah->aniperiod) {
if (aniState->ofdmPhyErrCount <= aniState->listenTime *
@@ -632,11 +622,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
}
}
-bool ath9k_hw_phycounters(struct ath_hw *ah)
-{
- return ah->has_hw_phycounters ? true : false;
-}
-
void ath9k_enable_mib_counters(struct ath_hw *ah)
{
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
@@ -781,9 +766,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
{
int i;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
-
- ah->has_hw_phycounters = 1;
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n");
memset(ah->ani, 0, sizeof(ah->ani));
for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
@@ -799,24 +782,22 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ATH9K_ANI_CCK_WEAK_SIG_THR;
ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
- if (ah->has_hw_phycounters) {
- ah->ani[i].ofdmPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
- ah->ani[i].cckPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
- }
- }
- if (ah->has_hw_phycounters) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Setting OfdmErrBase = 0x%08x\n",
- ah->ani[0].ofdmPhyErrBase);
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
- ah->ani[0].cckPhyErrBase);
-
- REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
- ath9k_enable_mib_counters(ah);
+ ah->ani[i].ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
+ ah->ani[i].cckPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
}
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Setting OfdmErrBase = 0x%08x\n",
+ ah->ani[0].ofdmPhyErrBase);
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
+ ah->ani[0].cckPhyErrBase);
+
+ REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
+ ath9k_enable_mib_counters(ah);
+
ah->aniperiod = ATH9K_ANI_PERIOD;
if (ah->config.enable_ani)
ah->proc_phyerr |= HAL_PROCESS_ANI;
@@ -826,9 +807,7 @@ void ath9k_hw_ani_disable(struct ath_hw *ah)
{
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n");
- if (ah->has_hw_phycounters) {
- ath9k_hw_disable_mib_counters(ah);
- REG_WRITE(ah, AR_PHY_ERR_1, 0);
- REG_WRITE(ah, AR_PHY_ERR_2, 0);
- }
+ ath9k_hw_disable_mib_counters(ah);
+ REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ REG_WRITE(ah, AR_PHY_ERR_2, 0);
}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index a36b7bb..1199245 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -124,7 +124,6 @@ void ath9k_ani_reset(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah,
const struct ath9k_node_stats *stats,
struct ath9k_channel *chan);
-bool ath9k_hw_phycounters(struct ath_hw *ah);
void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index e83e900..0e65873 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -507,7 +507,6 @@ struct ath_hw {
/* ANI */
u32 proc_phyerr;
- bool has_hw_phycounters;
u32 aniperiod;
struct ar5416AniState *curani;
struct ar5416AniState ani[255];
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index efe2e85..4a6f2d2 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2214,8 +2214,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
if ((conf->type == NL80211_IFTYPE_STATION) ||
(conf->type == NL80211_IFTYPE_ADHOC) ||
(conf->type == NL80211_IFTYPE_MESH_POINT)) {
- if (ath9k_hw_phycounters(sc->sc_ah))
- sc->imask |= ATH9K_INT_MIB;
+ sc->imask |= ATH9K_INT_MIB;
sc->imask |= ATH9K_INT_TSFOOR;
}
--
1.6.4
^ permalink raw reply related
* Re: [ath9k-devel] [PATCH] ath5k: fix requested allocated RX skb size for DMA
From: Luis R. Rodriguez @ 2009-08-13 3:33 UTC (permalink / raw)
To: Bob Copeland
Cc: Jiri Slaby, linux-wireless, ath5k-devel, linville, ath9k-devel,
Nick Kossifidis
In-Reply-To: <b6c5339f0908121408q4f3382e3rabd4def2de14c56c@mail.gmail.com>
John please ignore this patch, its busted, as Bob noted on IRC.
Luis
^ permalink raw reply
* Re: [ath5k-devel] [PATCH 0/3] ath: advance ath.ko with one more helper
From: Luis R. Rodriguez @ 2009-08-13 3:07 UTC (permalink / raw)
To: Nick Kossifidis
Cc: Bob Copeland, ath5k-devel, ath9k-devel, linux-wireless, linville
In-Reply-To: <40f31dec0908121913y1dc39032p26556135f22c3f48@mail.gmail.com>
On Wed, Aug 12, 2009 at 7:13 PM, Nick Kossifidis<mickflemm@gmail.com> wrote:
> 2009/8/12 Luis R. Rodriguez <lrodriguez@atheros.com>:
>> On Wed, Aug 12, 2009 at 10:21 AM, Bob Copeland<me@bobcopeland.com> wrote:
>>> On Wed, Aug 12, 2009 at 12:56 PM, Luis R.
>>> Rodriguez<lrodriguez@atheros.com> wrote:
>>>> This adds a common structure where we can start stuffing shared items
>>>> and introduces a helper for both ath5k and ath9k's use.
>>>>
>>>> Luis R. Rodriguez (3):
>>>> ath: add common ath_rxbuf_alloc() and make ath9k use it
>>>> ath5k: use common ath.ko ath_rxbuf_alloc()
>>>> ath5k: use bit shift operators for cache line size
>>>
>>> Series looks OK to me but I think we can add a 4/4 that would:
>>>
>>> - include ath/reg.h [don't remember if that's the name right now]
>>> in ath.h
>>> - move reg structs into ath_common (although, this could be a
>>> bad call for ar9170, haven't really checked).
>>>
>>> Then we only have to deal with one header and one composite struct
>>> (for now) as the interface between the modules.
>>
>> Sure, I was thinking of doing this after this. Is that acceptable?
>>
>> Luis
>
> You mean have a common reg.h for both ath5k and ath9k ? Works for me
> but we have to deal with some new register ranges and some registers
> have moved on ath9k + reg.h on ath9k has no descriptions, comments, it doesn't
> include macros for accessing queue registers or tables, mixes eeprom offsets
> with register addresses and other macros.
Sorry no I meant ath/reg.h as in regulatory, as that is already party of ath.ko.
> My plan was to start merging ath9k hw code on ath5k (not the driver part,
> pcu.c, qcu.c, phy.c, eeprom.c etc + registers/eeprom offsets/descriptor formats)
> and then move all that on ath and have both ath5k/ath9k use it. I
> believe ath5k hw
> code is much cleaner than ath9k and it's a better place to start, i've
> seen most hw
> code on ath9k and i'm ready to move on if it's O.K. with you.
When we update ath9k for new hw support it is easiest if that code
matches what we have internally at Atheros. Granted we diverge from
that every now and then but I believe those changes can be brought
back in that we do and yet keep the internal code working. I believe
the changes so far bring clarity and readability. Unfortunately we
haven't yet gotten any the changes we've made on ath9k hw access stuff
or regulatory merged back in so we keep diverging more and more from
our internal codebase.
Because of this for now I would not welcome bringing ath9k code to
ath5k in any way whatsoever. What I think is reasonable though is to
start merging into ath.ko common code which doesn't change much or
would mean diverging a lot from ath9k's current style for the hw
related stuff. Don't get me wrong, changes are welcomed but the less
intrusive the better. "start merging ath9k hw code on ath5k" sounds
very intrusive by all means.
Lets do this slowly and take it on, on a patch by patch basis.
Luis
^ permalink raw reply
* Re: [ath5k-devel] [PATCH 0/3] ath: advance ath.ko with one more helper
From: Bob Copeland @ 2009-08-13 2:59 UTC (permalink / raw)
To: Nick Kossifidis
Cc: Luis R. Rodriguez, ath5k-devel, ath9k-devel, linux-wireless,
linville
In-Reply-To: <40f31dec0908121913y1dc39032p26556135f22c3f48@mail.gmail.com>
On Thu, Aug 13, 2009 at 05:13:50AM +0300, Nick Kossifidis wrote:
> You mean have a common reg.h for both ath5k and ath9k ?
I meant the existing regulatory, not register, headers -- but if
there is stuff to be shared in reg[ister].h we can do that too.
> code is much cleaner than ath9k and it's a better place to start, i've
> seen most hw
> code on ath9k and i'm ready to move on if it's O.K. with you.
I guess we should coordinate a bit. I don't have much in the way
of unsent patches but perhaps we should pick a specific time to
start moving stuff around so we don't all have a pile of rejects.
Maybe after 2.6.32 merge window?
(This particular patch series, though, is fine enough now I think.)
--
Bob Copeland %% www.bobcopeland.com
^ permalink raw reply
* Re: [PATCH v2] b43: Implement RC calibration for rev.0/1 LP-PHYs
From: Larry Finger @ 2009-08-13 2:28 UTC (permalink / raw)
To: Gábor Stefanik
Cc: John Linville, Michael Buesch, Broadcom Wireless, linux-wireless
In-Reply-To: <4A830CF1.3020907@gmail.com>
Gábor Stefanik wrote:
> Also implement get/set BB mult, get/set TX gain, set RX gain,
> disable/restore CRS, run/stop DDFS, RX IQ est and QDIV roundup
> in the process.
>
> Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
> ---
> Changes from v1->v2:
> -Coding style fixes as suggested by Michael.
> -Added missing static to lpphy_qdiv_roundup.
> -Moved set_tx_power_control & related functions before rev0/1 RC
> calibration,
> and removed forward declaration
> -Reordered variable declarations at the start of rev0_1_rc_calib.
> -The ideal power table is now static const.
>
> Interdiff v1->v2 available @ http://b43.pastebin.com/f5fe6ba3c for
> easier review.
>
> drivers/net/wireless/b43/phy_lp.c | 508
> +++++++++++++++++++++++++++++++++----
> 1 files changed, 461 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/net/wireless/b43/phy_lp.c
> b/drivers/net/wireless/b43/phy_lp.c
> index 689c932..e05981b 100644
> --- a/drivers/net/wireless/b43/phy_lp.c
> +++ b/drivers/net/wireless/b43/phy_lp.c
> @@ -605,6 +605,8 @@ static void lpphy_radio_init(struct b43_wldev *dev)
> }
> }
>
> +struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
> +
> static void lpphy_set_rc_cap(struct b43_wldev *dev)
> {
> u8 rc_cap = dev->phy.lp->rc_cap;
> @@ -614,79 +616,327 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev)
> b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80);
> }
>
> -static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
> +static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
> {
> - //TODO and SPEC FIXME
> + return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
> }
>
> -static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
> +static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
> {
> - struct ssb_bus *bus = dev->dev->bus;
> - u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
> - u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
> - int i;
> + b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
> +}
>
> - b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
> - b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
> +static void lpphy_disable_crs(struct b43_wldev *dev)
> +{
> + b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
> + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
> + b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
> + b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
> + b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
> + b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
> + b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
> + b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
> +}
>
> - for (i = 0; i < 10000; i++) {
> - if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
> - break;
> - msleep(1);
> +static void lpphy_restore_crs(struct b43_wldev *dev)
> +{
> + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
> + b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60);
> + else
> + b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
> + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
> +}
> +
> +struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
> +
> +static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
> +{
> + struct lpphy_tx_gains gains;
> + u16 tmp;
> +
> + gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
> + if (dev->phy.rev < 2) {
> + tmp = b43_phy_read(dev,
> + B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
> + gains.gm = tmp & 0x0007;
> + gains.pga = (tmp & 0x0078) >> 3;
> + gains.pad = (tmp & 0x780) >> 7;
> + } else {
> + tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
> + gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
> + gains.gm = tmp & 0xFF;
> + gains.pga = (tmp >> 8) & 0xFF;
> }
>
> - if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
> - b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
> + return gains;
> +}
>
> - tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
> +static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
> +{
> + u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
> + ctl |= dac << 7;
> + b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
> +}
>
> - b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
> +static void lpphy_set_tx_gains(struct b43_wldev *dev,
> + struct lpphy_tx_gains gains)
> +{
> + u16 rf_gain, pa_gain;
>
> - if (crystal_freq == 24000000) {
> - b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
> + if (dev->phy.rev < 2) {
> + rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
> + b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
> + 0xF800, rf_gain);
> } else {
> - b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
> - b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
> + pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00;
> + b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
> + (gains.pga << 8) | gains.gm);
> + b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
> + 0x8000, gains.pad | pa_gain);
> + b43_phy_write(dev, B43_PHY_OFDM(0xFC),
> + (gains.pga << 8) | gains.gm);
> + b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
> + 0x8000, gains.pad | pa_gain);
> + }
> + lpphy_set_dac_gain(dev, gains.dac);
> + if (dev->phy.rev < 2) {
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
> + } else {
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
> }
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4);
> +}
>
> - b43_radio_write(dev, B2063_PA_SP7, 0x7D);
> +static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
> +{
> + u16 trsw = gain & 0x1;
> + u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
> + u16 ext_lna = (gain & 2) >> 1;
> +
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
> + 0xFBFF, ext_lna << 10);
> + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
> + 0xF7FF, ext_lna << 11);
> + b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
> +}
>
> - for (i = 0; i < 10000; i++) {
> - if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
> +static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
> +{
> + u16 low_gain = gain & 0xFFFF;
> + u16 high_gain = (gain >> 16) & 0xF;
> + u16 ext_lna = (gain >> 21) & 0x1;
> + u16 trsw = ~(gain >> 21) & 0x1;
==
Should be 20, not 21.
> + u16 tmp;
> + //SPEC FIXME is trsw really just ~(bool)ext_lna for rev2+?
No.
Larry
^ permalink raw reply
* Re: [PATCH] b43: Implement RC calibration for rev.0/1 LP-PHYs
From: Larry Finger @ 2009-08-13 2:19 UTC (permalink / raw)
To: Michael Buesch
Cc: bcm43xx-dev, Gábor Stefanik, John Linville, linux-wireless
In-Reply-To: <200908122008.29582.mb@bu3sch.de>
Michael Buesch wrote:
> On Wednesday 12 August 2009 19:56:25 Gábor Stefanik wrote:
>> + b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
>> + b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
>> + b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 3);
>
> 3bit shift smells fishy. Did you want 8?
There was a typo in the specs. It now is changed to 8.
>> + for (j = 5; j <= 25; j++) {
>> + lpphy_run_ddfs(dev, 1, 1, j, j, 0);
>
> (Just by guess) Did you really want j,j instead of i,j or something like that?
No, it definitely is j,j.
Larry
^ permalink raw reply
* Re: [ath5k-devel] [PATCH 0/3] ath: advance ath.ko with one more helper
From: Nick Kossifidis @ 2009-08-13 2:13 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Bob Copeland, ath5k-devel, ath9k-devel, linux-wireless, linville
In-Reply-To: <43e72e890908121027x5211c7cja3185861bc9c02f1@mail.gmail.com>
2009/8/12 Luis R. Rodriguez <lrodriguez@atheros.com>:
> On Wed, Aug 12, 2009 at 10:21 AM, Bob Copeland<me@bobcopeland.com> wrote:
>> On Wed, Aug 12, 2009 at 12:56 PM, Luis R.
>> Rodriguez<lrodriguez@atheros.com> wrote:
>>> This adds a common structure where we can start stuffing shared items
>>> and introduces a helper for both ath5k and ath9k's use.
>>>
>>> Luis R. Rodriguez (3):
>>> ath: add common ath_rxbuf_alloc() and make ath9k use it
>>> ath5k: use common ath.ko ath_rxbuf_alloc()
>>> ath5k: use bit shift operators for cache line size
>>
>> Series looks OK to me but I think we can add a 4/4 that would:
>>
>> - include ath/reg.h [don't remember if that's the name right now]
>> in ath.h
>> - move reg structs into ath_common (although, this could be a
>> bad call for ar9170, haven't really checked).
>>
>> Then we only have to deal with one header and one composite struct
>> (for now) as the interface between the modules.
>
> Sure, I was thinking of doing this after this. Is that acceptable?
>
> Luis
You mean have a common reg.h for both ath5k and ath9k ? Works for me
but we have to deal with some new register ranges and some registers
have moved on ath9k + reg.h on ath9k has no descriptions, comments, it doesn't
include macros for accessing queue registers or tables, mixes eeprom offsets
with register addresses and other macros.
My plan was to start merging ath9k hw code on ath5k (not the driver part,
pcu.c, qcu.c, phy.c, eeprom.c etc + registers/eeprom offsets/descriptor formats)
and then move all that on ath and have both ath5k/ath9k use it. I
believe ath5k hw
code is much cleaner than ath9k and it's a better place to start, i've
seen most hw
code on ath9k and i'm ready to move on if it's O.K. with you.
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick
^ permalink raw reply
* Re: [PATCH 3/7] [compat-2.6] pcmcia_parse_tuple was redefined in pcmcia/cistpl.h
From: Luis R. Rodriguez @ 2009-08-13 2:03 UTC (permalink / raw)
To: Hauke Mehrtens; +Cc: linux-wireless
In-Reply-To: <43e72e890908111404k780a3a8ehd8745142e9c01f56@mail.gmail.com>
On Tue, Aug 11, 2009 at 2:04 PM, Luis R.
Rodriguez<lrodriguez@atheros.com> wrote:
> On Tue, Aug 11, 2009 at 1:53 PM, Hauke Mehrtens<hauke@hauke-m.de> wrote:
>> Hi Luis,
>>
>> Thank you for applying the rest of the patches. Next time I will use
>> --cover-letter when generating the patches.
>>
>> Luis R. Rodriguez wrote:
>>> On Sat, Aug 8, 2009 at 5:38 AM, Hauke Mehrtens<hauke@hauke-m.de> wrote:
>>>> fix build:
>>>> undef pcmcia_parse_tuple before redefine it again.
>>>>
>>>> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
>>>> ---
>>>> compat/compat-2.6.28.h | 8 +++++++-
>>>> 1 files changed, 7 insertions(+), 1 deletions(-)
>>>>
>>>> diff --git a/compat/compat-2.6.28.h b/compat/compat-2.6.28.h
>>>> index fdc021a..e25259f 100644
>>>> --- a/compat/compat-2.6.28.h
>>>> +++ b/compat/compat-2.6.28.h
>>>> @@ -29,7 +29,13 @@
>>>> })
>>>> #endif /* From include/asm-generic/bug.h */
>>>>
>>>> -#define pcmcia_parse_tuple(tuple, parse) pcmcia_parse_tuple(NULL, tuple, parse)
>>>> +#include <pcmcia/cs_types.h>
>>>> +#include <pcmcia/cs.h>
>>>> +#include <pcmcia/cistpl.h>
>>>> +#ifdef pcmcia_parse_tuple
>>>> +#undef pcmcia_parse_tuple
>>>> +#define pcmcia_parse_tuple(tuple, parse) pccard_parse_tuple(tuple, parse)
>>>> +#endif
>>>
>>> Where did pccard_parse_tuple() come from?
>> In include/pcmcia/cistpl.h pcmcia_parse_tuple(p_dev, tuple, parse) is
>> defined as pccard_parse_tuple(tuple, parse)
>>
>>> Did you see the commit 0df8084caf53774113c8f118e9dd43e660cf9e15 by any
>>> chance? That fixed compilation for me against older kernels.
>> I still get a compile error with recent compat-wireless including commit
>> 0df8084caf53774113c8f118e9dd43e660cf9e15 with kernel <= 2.6.27 in Ubuntu:
>>
>> In file included from
>> /compat-wireless-git/drivers/net/wireless/b43/pcmcia.c:30:
>> include/pcmcia/cistpl.h:610:1: warning: "pcmcia_parse_tuple" redefined
>> In file included from /compat-wireless-git/include/net/compat.h:19,
>> from <command-line>:0:
>> /compat-wireless-git/include/net/compat-2.6.28.h:32:1: warning: this is
>> the location of the previous definition
>>
>> The above patch fixes it for me. The patch does not look relay nice, do
>> you have a better idea how to solve this problem?
>
> Hm odd, compilation worked for me against 2.6.27 using KLIB and
> KLIB_BUILD. I'll try to do that again today see if I still can compile
> ok or not.
OK thanks for the patch, applied!
Luis
^ permalink raw reply
* Re: compile error: compat-wireless-2009-08-12
From: Luis R. Rodriguez @ 2009-08-13 2:02 UTC (permalink / raw)
To: Bringfried Stecklum; +Cc: linux-wireless
In-Reply-To: <4A829D90.2080208@tls-tautenburg.de>
On Wed, Aug 12, 2009 at 3:46 AM, Bringfried
Stecklum<stecklum@tls-tautenburg.de> wrote:
> When trying to compile the latest compat-wireless package on an Ubuntu 8.10
> 64bit system running linux kernel 2.6.27-12 I get the following error
>
> stecklum@extragalactix:~/System/src/compat-wireless-2009-08-12$ make
> ./scripts/gen-compat-autoconf.sh config.mk > include/linux/compat_autoconf.h
> make -C /lib/modules/2.6.27-12-mygeneric/build
> M=/home/stecklum/System/src/compat-wireless-2009-08-12 modules
> make[1]: Entering directory `/usr/src/linux-headers-2.6.27-12-mygeneric'
> ...
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/main.c:
> In function ‘b43_request_firmware’:
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/main.c:2103:
> warning: format not a string literal and no format arguments
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/tables.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/phy_common.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/phy_g.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/phy_a.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/sysfs.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/xmit.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/lo.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/wa.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/dma.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pio.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/rfkill.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/leds.o
> CC [M]
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.o
> In file included from
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.c:30:
> include/pcmcia/cistpl.h:610:1: warning: "pcmcia_parse_tuple" redefined
> In file included from
> /home/stecklum/System/src/compat-wireless-2009-08-12/include/net/compat.h:19,
> from <command-line>:0:
> /home/stecklum/System/src/compat-wireless-2009-08-12/include/net/compat-2.6.28.h:32:1:
> warning: this is the location of the previous definition
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.c:91:41:
> error: macro "pcmcia_parse_tuple" requires 3 arguments, but only 2 given
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.c:
> In function ‘b43_pcmcia_probe’:
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.c:91:
> error: ‘pcmcia_parse_tuple’ undeclared (first use in this function)
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.c:91:
> error: (Each undeclared identifier is reported only once
> /home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.c:91:
> error: for each function it appears in.)
> make[4]: ***
> [/home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43/pcmcia.o]
> Error 1
> make[3]: ***
> [/home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless/b43]
> Error 2
> make[2]: ***
> [/home/stecklum/System/src/compat-wireless-2009-08-12/drivers/net/wireless]
> Error 2
> make[1]: *** [_module_/home/stecklum/System/src/compat-wireless-2009-08-12]
> Error 2
> make[1]: Leaving directory `/usr/src/linux-headers-2.6.27-12-mygeneric'
> make: *** [modules] Error 2
Try today's release.
Luis
^ permalink raw reply
* Minimal cross-compilation fix for CRDA
From: Philip A. Prindeville @ 2009-08-13 1:45 UTC (permalink / raw)
To: wireless
[-- Attachment #1: Type: text/plain, Size: 547 bytes --]
Reposting.
I think I've addresses all of the comments, and this fix is as short as
possible.
I considered passing in all of the variables from outside, but (a) this
doesn't scale well, and (b) things like $(NLLIBNAME) are "scratch"
variables used by the make process when doing discovery about the host
it's running on... they shouldn't be externally visible, much less
overridden by some encompassing make.
Putting the auto-discovery into its own path with a gating variable
seems like the cleanest, most robust, most maintainable approach.
[-- Attachment #2: crda-cross-compile.patch --]
[-- Type: text/plain, Size: 1543 bytes --]
Changes:
1. Move invariant definitions to before any cross-compilation conditional sections for clarity (and to avoid having to duplicate them).
2. Bracket any host (native) compilation sections with conditional based on $(CROSS_COMPILE) being empty.
4. Add 'else' section for cross-compilation using openssl and libnl-1 (or libnl-2 if explicitly selected).
--- crda-1.1.0/Makefile 2009-08-10 13:37:36.000000000 -0700
+++ crda-1.1.0/Makefile.new 2009-08-10 17:29:22.000000000 -0700
@@ -22,12 +22,17 @@
# with make PUBKEY_DIR=/usr/lib/crda/pubkeys
PUBKEY_DIR?=pubkeys
+MKDIR ?= mkdir -p
+INSTALL ?= install
+
CFLAGS += -Wall -g
all: all_noverify verify
all_noverify: crda intersect regdbdump
+ifeq ($(CROSS_COMPILE),)
+
ifeq ($(USE_OPENSSL),1)
CFLAGS += -DUSE_OPENSSL `pkg-config --cflags openssl`
LDLIBS += `pkg-config --libs openssl`
@@ -41,8 +46,6 @@
reglib.o: keys-gcrypt.c
endif
-MKDIR ?= mkdir -p
-INSTALL ?= install
NL1FOUND := $(shell pkg-config --atleast-version=1 libnl-1 && echo Y)
NL2FOUND := $(shell pkg-config --atleast-version=2 libnl-2.0 && echo Y)
@@ -64,6 +67,31 @@
NLLIBS += `pkg-config --libs $(NLLIBNAME)`
CFLAGS += `pkg-config --cflags $(NLLIBNAME)`
+else
+
+ifeq ($(USE_OPENSSL),1)
+CFLAGS += -DUSE_OPENSSL
+LDLIBS += -lssl
+
+reglib.o: keys-ssl.c
+
+else
+CFLAGS += -DUSE_GCRYPT
+LDLIBS += -lgcrypt
+
+reglib.o: keys-gcrypt.c
+
+endif
+
+ifeq ($(USE_LIBNL20),1)
+CFLAGS += -DCONFIG_LIBNL20
+NLLIBS = -lnl-genl -lnl-2.0
+else
+NLLIBS = -lnl
+endif
+
+endif
+
ifeq ($(V),1)
Q=
NQ=@true
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox