From 2f19c287fecb958eb68b1c2199b4dd6e00ba4276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Thu, 13 Aug 2009 16:51:51 +0200 Subject: b43: Update dummy transmission to match V4 specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The V4 dummy transmission has two extra bools in its prototype, so update all callers with the 2 bools. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/lo.c | 2 +- drivers/net/wireless/b43/main.c | 42 ++++++++++++++++++++++++---------------- drivers/net/wireless/b43/main.h | 2 +- drivers/net/wireless/b43/phy_g.c | 6 +++--- drivers/net/wireless/b43/wa.c | 2 +- 5 files changed, 31 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 22d0fbd83a6..976104f634a 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -477,7 +477,7 @@ static void lo_measure_setup(struct b43_wldev *dev, } else b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); if (phy->rev >= 2) - b43_dummy_transmission(dev); + b43_dummy_transmission(dev, false, true); b43_gphy_channel_switch(dev, 6, 0); b43_radio_read16(dev, 0x51); /* dummy read */ if (phy->type == B43_PHYTYPE_G) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 950beefbeae..f6d039e303f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -691,9 +691,9 @@ static void b43_synchronize_irq(struct b43_wldev *dev) } /* DummyTransmission function, as documented on - * http://bcm-specs.sipsolutions.net/DummyTransmission + * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission */ -void b43_dummy_transmission(struct b43_wldev *dev) +void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) { struct b43_wl *wl = dev->wl; struct b43_phy *phy = &dev->phy; @@ -707,19 +707,12 @@ void b43_dummy_transmission(struct b43_wldev *dev) 0x00000000, }; - switch (phy->type) { - case B43_PHYTYPE_A: + if (ofdm) { max_loop = 0x1E; buffer[0] = 0x000201CC; - break; - case B43_PHYTYPE_B: - case B43_PHYTYPE_G: + } else { max_loop = 0xFA; buffer[0] = 0x000B846E; - break; - default: - B43_WARN_ON(1); - return; } spin_lock_irq(&wl->irq_lock); @@ -728,20 +721,35 @@ void b43_dummy_transmission(struct b43_wldev *dev) for (i = 0; i < 5; i++) b43_ram_write(dev, i * 4, buffer[i]); - /* Commit writes */ - b43_read32(dev, B43_MMIO_MACCTL); - b43_write16(dev, 0x0568, 0x0000); - b43_write16(dev, 0x07C0, 0x0000); - value = ((phy->type == B43_PHYTYPE_A) ? 1 : 0); + if (dev->dev->id.revision < 11) + b43_write16(dev, 0x07C0, 0x0000); + else + b43_write16(dev, 0x07C0, 0x0100); + value = (ofdm ? 0x41 : 0x40); b43_write16(dev, 0x050C, value); + if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP)) + b43_write16(dev, 0x0514, 0x1A02); b43_write16(dev, 0x0508, 0x0000); b43_write16(dev, 0x050A, 0x0000); b43_write16(dev, 0x054C, 0x0000); b43_write16(dev, 0x056A, 0x0014); b43_write16(dev, 0x0568, 0x0826); b43_write16(dev, 0x0500, 0x0000); - b43_write16(dev, 0x0502, 0x0030); + if (!pa_on && (phy->type == B43_PHYTYPE_N)) { + //SPEC TODO + } + + switch (phy->type) { + case B43_PHYTYPE_N: + b43_write16(dev, 0x0502, 0x00D0); + break; + case B43_PHYTYPE_LP: + b43_write16(dev, 0x0502, 0x0050); + break; + default: + b43_write16(dev, 0x0502, 0x0030); + } if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) b43_radio_write16(dev, 0x0051, 0x0017); diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 950fb1b0546..0406e06781d 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -123,7 +123,7 @@ void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value u64 b43_hf_read(struct b43_wldev *dev); void b43_hf_write(struct b43_wldev *dev, u64 value); -void b43_dummy_transmission(struct b43_wldev *dev); +void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on); void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags); diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 5300232449f..e47131216a6 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -333,7 +333,7 @@ static void b43_set_all_gains(struct b43_wldev *dev, b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp); b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp); } - b43_dummy_transmission(dev); + b43_dummy_transmission(dev, false, true); } static void b43_set_original_gains(struct b43_wldev *dev) @@ -365,7 +365,7 @@ static void b43_set_original_gains(struct b43_wldev *dev) b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040); b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040); b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000); - b43_dummy_transmission(dev); + b43_dummy_transmission(dev, false, true); } /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ @@ -1964,7 +1964,7 @@ static void b43_phy_init_pctl(struct b43_wldev *dev) } b43_set_txpower_g(dev, &bbatt, &rfatt, 0); } - b43_dummy_transmission(dev); + b43_dummy_transmission(dev, false, true); gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); if (B43_DEBUG) { /* Current-Idle-TSSI sanity check. */ diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index e1e20f69f6d..73e97fa4ddf 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -37,7 +37,7 @@ static void b43_wa_papd(struct b43_wldev *dev) backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0); b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7); b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0); - b43_dummy_transmission(dev); + b43_dummy_transmission(dev, true, true); b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup); } -- cgit v1.2.3 From 7021f62a46d4866fecd7b31cbc359d742876bb61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Thu, 13 Aug 2009 17:27:31 +0200 Subject: b43: LP-PHY: Initialize TX power control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HW TX power control init still needs work. The SW init is complete according to the specs. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 105 +++++++++++++++++++++++++++++++++++--- drivers/net/wireless/b43/phy_lp.h | 5 ++ 2 files changed, 103 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index cfb8337d385..996b7eccfaf 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1257,18 +1257,109 @@ static void lpphy_calibration(struct b43_wldev *dev) b43_mac_enable(dev); } +static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode) +{ + if (mode != TSSI_MUX_EXT) { + b43_radio_set(dev, B2063_PA_SP1, 0x2); + b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000); + b43_radio_write(dev, B2063_PA_CTL10, 0x51); + if (mode == TSSI_MUX_POSTPA) { + b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE); + b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7); + } else { + b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1); + b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL, + 0xFFC7, 0x20); + } + } else { + B43_WARN_ON(1); + } +} + +static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev) +{ + u16 tmp; + int i; + + //SPEC TODO Call LP PHY Clear TX Power offsets + for (i = 0; i < 64; i++) { + if (dev->phy.rev >= 2) + b43_lptab_write(dev, B43_LPTAB32(7, i + 1), i); + else + b43_lptab_write(dev, B43_LPTAB32(10, i + 1), i); + } + + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF); + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000); + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F); + if (dev->phy.rev < 2) { + b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF); + b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000); + } else { + b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE); + b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4); + b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10); + b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1); + lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA); + } + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000); + b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF); + b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA); + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, + (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, + B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); + b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF); + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, + (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, + B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW); + + if (dev->phy.rev < 2) { + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000); + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF); + } else { + lpphy_set_tx_power_by_index(dev, 0x7F); + } + + b43_dummy_transmission(dev, true, true); + + tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT); + if (tmp & 0x8000) { + b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, + 0xFFC0, (tmp & 0xFF) - 32); + } + + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF); + + // (SPEC?) TODO Set "Target TX frequency" variable to 0 + // SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8! +} + +static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev) +{ + struct lpphy_tx_gains gains; + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + gains.gm = 4; + gains.pad = 12; + gains.pga = 12; + gains.dac = 0; + } else { + gains.gm = 7; + gains.pad = 14; + gains.pga = 15; + gains.dac = 0; + } + lpphy_set_tx_gains(dev, gains); + lpphy_set_bb_mult(dev, 150); +} + /* Initialize TX power control */ static void lpphy_tx_pctl_init(struct b43_wldev *dev) { if (0/*FIXME HWPCTL capable */) { - //TODO + lpphy_tx_pctl_init_hw(dev); } else { /* This device is only software TX power control capable. */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - //TODO - } else { - //TODO - } - //TODO set BB multiplier to 0x0096 + lpphy_tx_pctl_init_sw(dev); } } diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 0461d5b3144..4eab760ac61 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h @@ -886,6 +886,11 @@ struct b43_phy_lp { u16 dig_flt_state[9]; }; +enum tssi_mux_mode { + TSSI_MUX_PREPA, + TSSI_MUX_POSTPA, + TSSI_MUX_EXT, +}; struct b43_phy_operations; extern const struct b43_phy_operations b43_phyops_lp; -- cgit v1.2.3 From e6a6cf4c42e0dc3541a63b5f0f88299f982d6704 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 13 Aug 2009 13:30:50 -0700 Subject: iwlwifi: prevent read outside array bounds With EDCA and HCCA we have 16 potential tid values. This is accommodated by mac80211, but iwlwifi only supports EDCA. With this implementation it is thus possible for mac80211 to request a tid that will cause iwlwifi to read outside array bounds. A similar problem exists if traffic is received in an unsupported category. We add error checking to catch these situations. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-tx.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 ++ 3 files changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 21331552ff2..1bd7cd4dd80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -332,6 +332,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, } else return MAX_TID_COUNT; + if (unlikely(tid >= TID_MAX_LOAD_COUNT)) + return MAX_TID_COUNT; + tl = &lq_data->load[tid]; curr_time -= curr_time % TID_ROUND_VALUE; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 9b76bd41f21..7686fc72eb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -745,6 +745,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + if (unlikely(tid >= MAX_TID_COUNT)) + goto drop_unlock; seq_number = priv->stations[sta_id].tid[tid].seq_number; seq_number &= IEEE80211_SCTL_SEQ; hdr->seq_ctrl = hdr->seq_ctrl & @@ -1238,6 +1240,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) return -EINVAL; } + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) tx_fifo_id = default_tid_to_tx_fifo[tid]; else diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e617411d0c5..f339c5bd1fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -544,6 +544,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + if (unlikely(tid >= MAX_TID_COUNT)) + goto drop; seq_number = priv->stations[sta_id].tid[tid].seq_number & IEEE80211_SCTL_SEQ; hdr->seq_ctrl = cpu_to_le16(seq_number) | -- cgit v1.2.3 From be2527654fab254beda8612cbd6bc927dc98fbee Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:30:51 -0700 Subject: iwlwifi: remove unused HT configuration entry tx_chan_width The tx_chan_width entry is never used, supported_chan_width is used instead. Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index af735128333..479b7e165b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2423,7 +2423,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); - iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; iwl_conf->ht_protection = bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; iwl_conf->non_GF_STA_present = diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b96c3c9e92a..c34f9d73306 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -515,7 +515,6 @@ struct iwl_ht_info { struct ieee80211_mcs_info mcs; /* BSS related data */ u8 extension_chan_offset; - u8 tx_chan_width; u8 ht_protection; u8 non_GF_STA_present; }; -- cgit v1.2.3 From 7869b0eaed0447a989d8672eed27a358aa5dde0c Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:30:52 -0700 Subject: iwlwifi: include HT configuration when adding stations through rs_rate_init Driver's first notification of a new station from mac80211 can be through rate selection API. This patch fixes a bug where, in this code path, the HT capabilities of the new station were ignored. Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 1bd7cd4dd80..551c4ba3f17 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2522,6 +2522,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_supported_band *sband = txrc->sband; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_conf *conf = &priv->hw->conf; + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; @@ -2554,7 +2555,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", hdr->addr1); sta_id = iwl_add_station(priv, hdr->addr1, - false, CMD_ASYNC, NULL); + false, CMD_ASYNC, ht_cap); } if ((sta_id != IWL_INVALID_STATION)) { lq_sta->lq.sta_id = sta_id; @@ -2623,6 +2624,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, int i, j; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_conf *conf = &priv->hw->conf; + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct iwl_lq_sta *lq_sta = priv_sta; u16 mask_bit = 0; int count; @@ -2651,7 +2653,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); sta_id = iwl_add_station(priv, sta->addr, false, - CMD_ASYNC, NULL); + CMD_ASYNC, ht_cap); } if ((sta_id != IWL_INVALID_STATION)) { lq_sta->lq.sta_id = sta_id; @@ -2672,19 +2674,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), * supp_rates[] does not; shift to convert format, force 9 MBits off. */ - lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1; - lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1; + lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; + lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; lq_sta->active_siso_rate &= ~((u16)0x2); lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; /* Same here */ - lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1; - lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1; + lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; + lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; lq_sta->active_mimo2_rate &= ~((u16)0x2); lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; - lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1; - lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1; + lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1; + lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1; lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; -- cgit v1.2.3 From 3b24716fc978db9c27c4a069e5201460479340a4 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 13 Aug 2009 13:30:53 -0700 Subject: iwlwifi: cleanup HT40 extension channels setup The patch cleans up the HT40 extension channels setup for EEPROM band 6 and 7 to make it more readable. Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 37 ++++++++++--------------------- 1 file changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 78c4a324a3b..ded63320a46 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -484,14 +484,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, ? # x " " : "") /** - * iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv. + * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. * * Does not set up a command, or touch hardware. */ -static int iwl_set_ht40_chan_info(struct iwl_priv *priv, +static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, const struct iwl_eeprom_channel *eeprom_ch, - u8 ht40_extension_channel) + u8 clear_ht40_extension_channel) { struct iwl_channel_info *ch_info; @@ -523,7 +523,7 @@ static int iwl_set_ht40_chan_info(struct iwl_priv *priv, ch_info->ht40_min_power = 0; ch_info->ht40_scan_power = eeprom_ch->max_power_avg; ch_info->ht40_flags = eeprom_ch->flags; - ch_info->ht40_extension_channel = ht40_extension_channel; + ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; return 0; } @@ -592,8 +592,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* First write that ht40 is not enabled, and then enable * one by one */ ch_info->ht40_extension_channel = - (IEEE80211_CHAN_NO_HT40PLUS | - IEEE80211_CHAN_NO_HT40MINUS); + IEEE80211_CHAN_NO_HT40; if (!(is_channel_valid(ch_info))) { IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " @@ -652,7 +651,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ for (band = 6; band <= 7; band++) { enum ieee80211_band ieeeband; - u8 ht40_extension_chan; iwl_init_band_reference(priv, band, &eeprom_ch_count, &eeprom_ch_info, &eeprom_ch_index); @@ -663,28 +661,17 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { - - if ((band == 6) && - ((eeprom_ch_index[ch] == 5) || - (eeprom_ch_index[ch] == 6) || - (eeprom_ch_index[ch] == 7))) - /* both are allowed: above and below */ - ht40_extension_chan = 0; - else - ht40_extension_chan = - IEEE80211_CHAN_NO_HT40MINUS; - /* Set up driver's info for lower half */ - iwl_set_ht40_chan_info(priv, ieeeband, + iwl_mod_ht40_chan_info(priv, ieeeband, eeprom_ch_index[ch], - &(eeprom_ch_info[ch]), - ht40_extension_chan); + &eeprom_ch_info[ch], + IEEE80211_CHAN_NO_HT40PLUS); /* Set up driver's info for upper half */ - iwl_set_ht40_chan_info(priv, ieeeband, - (eeprom_ch_index[ch] + 4), - &(eeprom_ch_info[ch]), - IEEE80211_CHAN_NO_HT40PLUS); + iwl_mod_ht40_chan_info(priv, ieeeband, + eeprom_ch_index[ch] + 4, + &eeprom_ch_info[ch], + IEEE80211_CHAN_NO_HT40MINUS); } } -- cgit v1.2.3 From 415e49936b4b29b34c2fb561eeab867d41fc43a6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 13 Aug 2009 13:30:54 -0700 Subject: iwlwifi: traverse linklist to find the valid OTP block For devices using OTP memory, EEPROM image can start from any one of the OTP blocks. If shadow RAM is disabled, we need to traverse link list to find the last valid block, then start the EEPROM image reading. If OTP is not full, the valid block is the block _before_ the last block on the link list; the last block on the link list is the empty block ready for next OTP refresh/update. If OTP is full, then the last block is the valid block to be used for configure the device. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 20 +++- drivers/net/wireless/iwlwifi/iwl-core.h | 4 + drivers/net/wireless/iwlwifi/iwl-dev.h | 11 ++ drivers/net/wireless/iwlwifi/iwl-eeprom.c | 185 ++++++++++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-eeprom.h | 10 +- 6 files changed, 191 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 191718a0c54..9bb6a287eae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -149,12 +149,14 @@ struct iwl_cfg iwl1000_bgn_cfg = { .ucode_api_min = IWL1000_UCODE_API_MIN, .sku = IWL_SKU_G|IWL_SKU_N, .ops = &iwl1000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .need_pll_cfg = true, + .max_ll_items = OTP_MAX_LL_ITEMS_1000, + .shadow_ram_support = false, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c3ec6c20cc9..0b731fd5ad1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -161,7 +161,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = { .ucode_api_min = IWL6000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl6000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, @@ -169,6 +169,8 @@ struct iwl_cfg iwl6000h_2agn_cfg = { .valid_rx_ant = ANT_AB, .need_pll_cfg = false, .pa_type = IWL_PA_HYBRID, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, }; /* @@ -181,7 +183,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .ucode_api_min = IWL6000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl6000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, @@ -189,6 +191,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .valid_rx_ant = ANT_BC, .need_pll_cfg = false, .pa_type = IWL_PA_INTERNAL, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -198,7 +202,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl6000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, @@ -206,6 +210,8 @@ struct iwl_cfg iwl6050_2agn_cfg = { .valid_rx_ant = ANT_AB, .need_pll_cfg = false, .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -215,7 +221,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .ucode_api_min = IWL6000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl6000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, @@ -223,6 +229,8 @@ struct iwl_cfg iwl6000_3agn_cfg = { .valid_rx_ant = ANT_ABC, .need_pll_cfg = false, .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, }; struct iwl_cfg iwl6050_3agn_cfg = { @@ -232,7 +240,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl6000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, @@ -240,6 +248,8 @@ struct iwl_cfg iwl6050_3agn_cfg = { .valid_rx_ant = ANT_ABC, .need_pll_cfg = false, .pa_type = IWL_PA_SYSTEM, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 32750f4f1ce..509683487e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -209,6 +209,8 @@ struct iwl_mod_params { * @ucode_api_max: Highest version of uCode API supported by driver. * @ucode_api_min: Lowest version of uCode API supported by driver. * @pa_type: used by 6000 series only to identify the type of Power Amplifier + * @max_ll_items: max number of OTP blocks + * @shadow_ram_support: shadow support for OTP memory * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -247,6 +249,8 @@ struct iwl_cfg { bool need_pll_cfg; bool use_isr_legacy; enum iwl_pa_type pa_type; + const u16 max_ll_items; + const bool shadow_ram_support; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c34f9d73306..0b19a6f93c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -887,6 +887,17 @@ enum iwl_nvm_type { NVM_DEVICE_TYPE_OTP, }; +/* + * Two types of OTP memory access modes + * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, + * based on physical memory addressing + * IWL_OTP_ACCESS_RELATIVE - relative address mode, + * based on logical memory addressing + */ +enum iwl_access_mode { + IWL_OTP_ACCESS_ABSOLUTE, + IWL_OTP_ACCESS_RELATIVE, +}; /** * enum iwl_pa_type - Power Amplifier type diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index ded63320a46..01b95e89009 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) } EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); +static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) +{ + u32 otpgp; + + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); + if (mode == IWL_OTP_ACCESS_ABSOLUTE) + iwl_clear_bit(priv, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_OTP_ACCESS_MODE); + else + iwl_set_bit(priv, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_OTP_ACCESS_MODE); +} + static int iwlcore_get_nvm_type(struct iwl_priv *priv) { u32 otpgp; @@ -252,6 +265,124 @@ static int iwl_init_otp_access(struct iwl_priv *priv) return ret; } +static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) +{ + int ret = 0; + u32 r; + u32 otpgp; + + _iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); + if (ret < 0) { + IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); + return ret; + } + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + /* check for ECC errors: */ + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); + if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { + /* stop in this case */ + /* set the uncorrectable OTP ECC bit for acknowledgement */ + iwl_set_bit(priv, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); + IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); + return -EINVAL; + } + if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { + /* continue in this case */ + /* set the correctable OTP ECC bit for acknowledgement */ + iwl_set_bit(priv, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); + IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); + } + *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); + return 0; +} + +/* + * iwl_is_otp_empty: check for empty OTP + */ +static bool iwl_is_otp_empty(struct iwl_priv *priv) +{ + u16 next_link_addr = 0, link_value; + bool is_empty = false; + + /* locate the beginning of OTP link list */ + if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) { + if (!link_value) { + IWL_ERR(priv, "OTP is empty\n"); + is_empty = true; + } + } else { + IWL_ERR(priv, "Unable to read first block of OTP list.\n"); + is_empty = true; + } + + return is_empty; +} + + +/* + * iwl_find_otp_image: find EEPROM image in OTP + * finding the OTP block that contains the EEPROM image. + * the last valid block on the link list (the block _before_ the last block) + * is the block we should read and used to configure the device. + * If all the available OTP blocks are full, the last block will be the block + * we should read and used to configure the device. + * only perform this operation if shadow RAM is disabled + */ +static int iwl_find_otp_image(struct iwl_priv *priv, + u16 *validblockaddr) +{ + u16 next_link_addr = 0, link_value = 0, valid_addr; + int ret = 0; + int usedblocks = 0; + + /* set addressing mode to absolute to traverse the link list */ + iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE); + + /* checking for empty OTP or error */ + if (iwl_is_otp_empty(priv)) + return -EINVAL; + + /* + * start traverse link list + * until reach the max number of OTP blocks + * different devices have different number of OTP blocks + */ + do { + /* save current valid block address + * check for more block on the link list + */ + valid_addr = next_link_addr; + next_link_addr = link_value; + IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", + usedblocks, next_link_addr); + if (iwl_read_otp_word(priv, next_link_addr, &link_value)) + return -EINVAL; + if (!link_value) { + /* + * reach the end of link list, + * set address point to the starting address + * of the image + */ + goto done; + } + /* more in the link list, continue */ + usedblocks++; + } while (usedblocks < priv->cfg->max_ll_items); + /* OTP full, use last block */ + IWL_DEBUG_INFO(priv, "OTP is full, use last block\n"); +done: + *validblockaddr = valid_addr; + /* skip first 2 bytes (link list pointer) */ + *validblockaddr += 2; + return ret; +} + /** * iwl_eeprom_init - read EEPROM contents * @@ -266,15 +397,14 @@ int iwl_eeprom_init(struct iwl_priv *priv) int sz; int ret; u16 addr; - u32 otpgp; + u16 validblockaddr = 0; + u16 cache_addr = 0; priv->nvm_device_type = iwlcore_get_nvm_type(priv); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ - if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) - priv->cfg->eeprom_size = - OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL; + IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size); sz = priv->cfg->eeprom_size; priv->eeprom = kzalloc(sz, GFP_KERNEL); if (!priv->eeprom) { @@ -302,46 +432,31 @@ int iwl_eeprom_init(struct iwl_priv *priv) if (ret) { IWL_ERR(priv, "Failed to initialize OTP access.\n"); ret = -ENOENT; - goto err; + goto done; } _iwl_write32(priv, CSR_EEPROM_GP, iwl_read32(priv, CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); - /* clear */ - _iwl_write32(priv, CSR_OTP_GP_REG, - iwl_read32(priv, CSR_OTP_GP_REG) | + + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); - - for (addr = 0; addr < sz; addr += sizeof(u16)) { - u32 r; - - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - - ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { - IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); + /* traversing the linked list if no shadow ram supported */ + if (!priv->cfg->shadow_ram_support) { + if (iwl_find_otp_image(priv, &validblockaddr)) { + ret = -ENOENT; goto done; } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - /* check for ECC errors: */ - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); - if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { - /* stop in this case */ - IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n"); + } + for (addr = validblockaddr; addr < validblockaddr + sz; + addr += sizeof(u16)) { + u16 eeprom_data; + + ret = iwl_read_otp_word(priv, addr, &eeprom_data); + if (ret) goto done; - } - if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { - /* continue in this case */ - _iwl_write32(priv, CSR_OTP_GP_REG, - iwl_read32(priv, CSR_OTP_GP_REG) | - CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); - IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); - } - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); + e[cache_addr / 2] = eeprom_data; + cache_addr += sizeof(u16); } } else { /* eeprom is an array of 16bit values */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 05d4fc4451d..ca7920a8f52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -180,8 +180,14 @@ struct iwl_eeprom_channel { #define EEPROM_5050_EEPROM_VERSION (0x21E) /* OTP */ -#define OTP_LOWER_BLOCKS_TOTAL (3) -#define OTP_BLOCK_SIZE (0x400) +/* lower blocks contain EEPROM image and calibration data */ +#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ +/* high blocks contain PAPD data */ +#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */ +#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */ +#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ +#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ +#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ /* 2.4 GHz */ extern const u8 iwl_eeprom_band_1[14]; -- cgit v1.2.3 From 367ca28da433ed9639468be851e1f33468e3485e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 13 Aug 2009 13:30:55 -0700 Subject: iwlwifi: remove unused members of iwl_ht_info Some members of iwl_ht_info are unused, and one of them is write-only, so we can remove these three: max_amsdu_size, ampdu_factor and mpdu_density. Signed-off-by: Johannes Berg Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 -- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 --- 2 files changed, 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 479b7e165b0..08345b97cb4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2397,8 +2397,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, iwl_conf->sgf |= HT_SHORT_GI_40MHZ; iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); - iwl_conf->max_amsdu_size = - !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); iwl_conf->supported_chan_width = !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0b19a6f93c8..db745343d36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -509,9 +509,6 @@ struct iwl_ht_info { u8 sm_ps; u8 is_green_field; u8 sgf; /* HT_SHORT_GI_* short guard interval */ - u8 max_amsdu_size; - u8 ampdu_factor; - u8 mpdu_density; struct ieee80211_mcs_info mcs; /* BSS related data */ u8 extension_chan_offset; -- cgit v1.2.3 From 9f30e04e041cf9943940f71fd76094dd5a237018 Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:30:56 -0700 Subject: iwlwifi: refactor packet reception code This patch fixes a number of issues in iwl_rx_reply_rx and iwl_pass_packet_to_mac80211. These issues stem from the complexities of managing two different types of packet commands for different hardware. - Unify code handling rx_phy_res in SKB or cached to eliminate redundancy and remove potential NULL pointer accesses - Replace magic number with proper constant - Optimize functions by moving early exit conditions before computation - Comment code and improve some variable names - Remove redundant computation in iwl_pass_packet_to_mac80211 by passing in the correct, already-computed arguments. Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-rx.c | 204 +++++++++++----------------- 2 files changed, 78 insertions(+), 127 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 68d7719071f..9398ad7e42b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1156,6 +1156,7 @@ struct iwl_wep_cmd { #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) #define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0) +#define RX_RES_PHY_FLAGS_ANTENNA_POS 4 #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 43b2fce4cbf..092d3276175 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -853,61 +853,12 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) } static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, - int include_phy, - struct iwl_rx_mem_buffer *rxb, - struct ieee80211_rx_status *stats) + struct ieee80211_hdr *hdr, + u16 len, + u32 ampdu_status, + struct iwl_rx_mem_buffer *rxb, + struct ieee80211_rx_status *stats) { - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_rx_phy_res *rx_start = (include_phy) ? - (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL; - struct ieee80211_hdr *hdr; - u16 len; - __le32 *rx_end; - unsigned int skblen; - u32 ampdu_status; - u32 ampdu_status_legacy; - - if (!include_phy && priv->last_phy_res[0]) - rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; - - if (!rx_start) { - IWL_ERR(priv, "MPDU frame without a PHY data\n"); - return; - } - if (include_phy) { - hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] + - rx_start->cfg_phy_cnt); - - len = le16_to_cpu(rx_start->byte_count); - - rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] + - sizeof(struct iwl_rx_phy_res) + - rx_start->cfg_phy_cnt + len); - - } else { - struct iwl4965_rx_mpdu_res_start *amsdu = - (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; - - hdr = (struct ieee80211_hdr *)(pkt->u.raw + - sizeof(struct iwl4965_rx_mpdu_res_start)); - len = le16_to_cpu(amsdu->byte_count); - rx_start->byte_count = amsdu->byte_count; - rx_end = (__le32 *) (((u8 *) hdr) + len); - } - - ampdu_status = le32_to_cpu(*rx_end); - skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32); - - if (!include_phy) { - /* New status scheme, need to translate */ - ampdu_status_legacy = ampdu_status; - ampdu_status = iwl_translate_rx_status(priv, ampdu_status); - } - - /* start from MAC */ - skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); - skb_put(rxb->skb, len); /* end where data ends */ - /* We only process data packets if the interface is open */ if (unlikely(!priv->is_open)) { IWL_DEBUG_DROP_LIMIT(priv, @@ -915,13 +866,15 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, return; } - hdr = (struct ieee80211_hdr *)rxb->skb->data; - - /* in case of HW accelerated crypto and bad decryption, drop */ + /* In case of HW accelerated crypto and bad decryption, drop */ if (!priv->cfg->mod_params->sw_crypto && iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) return; + /* Resize SKB from mac header to end of packet */ + skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data); + skb_put(rxb->skb, len); + iwl_update_stats(priv, false, hdr->frame_control, len); memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); ieee80211_rx_irqsafe(priv->hw, rxb->skb); @@ -955,25 +908,66 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, struct ieee80211_hdr *header; struct ieee80211_rx_status rx_status; struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - /* Use phy data (Rx signal strength, etc.) contained within - * this rx packet for legacy frames, - * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ - int include_phy = (pkt->hdr.cmd == REPLY_RX); - struct iwl_rx_phy_res *rx_start = (include_phy) ? - (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : - (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; - __le32 *rx_end; - unsigned int len = 0; + struct iwl_rx_phy_res *phy_res; + __le32 rx_pkt_status; + struct iwl4965_rx_mpdu_res_start *amsdu; + u32 len; + u32 ampdu_status; u16 fc; - u8 network_packet; - rx_status.mactime = le64_to_cpu(rx_start->timestamp); + /** + * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. + * REPLY_RX: physical layer info is in this buffer + * REPLY_RX_MPDU_CMD: physical layer info was sent in separate + * command and cached in priv->last_phy_res + * + * Here we set up local variables depending on which command is + * received. + */ + if (pkt->hdr.cmd == REPLY_RX) { + phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; + header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) + + phy_res->cfg_phy_cnt); + + len = le16_to_cpu(phy_res->byte_count); + rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + + phy_res->cfg_phy_cnt + len); + ampdu_status = le32_to_cpu(rx_pkt_status); + } else { + if (!priv->last_phy_res[0]) { + IWL_ERR(priv, "MPDU frame without cached PHY data\n"); + return; + } + phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; + amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; + header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); + len = le16_to_cpu(amsdu->byte_count); + rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); + ampdu_status = iwl_translate_rx_status(priv, + le32_to_cpu(rx_pkt_status)); + } + + if ((unlikely(phy_res->cfg_phy_cnt > 20))) { + IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", + phy_res->cfg_phy_cnt); + return; + } + + if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || + !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { + IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", + le32_to_cpu(rx_pkt_status)); + return; + } + + /* rx_status carries information about the packet to mac80211 */ + rx_status.mactime = le64_to_cpu(phy_res->timestamp); rx_status.freq = - ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); - rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? + ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); + rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; rx_status.rate_idx = - iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); + iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags)); if (rx_status.band == IEEE80211_BAND_5GHZ) rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; @@ -983,54 +977,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, * this W/A doesn't propagate it to the mac80211 */ /*rx_status.flag |= RX_FLAG_TSFT;*/ - if ((unlikely(rx_start->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", - rx_start->cfg_phy_cnt); - return; - } - - if (!include_phy) { - if (priv->last_phy_res[0]) - rx_start = (struct iwl_rx_phy_res *) - &priv->last_phy_res[1]; - else - rx_start = NULL; - } - - if (!rx_start) { - IWL_ERR(priv, "MPDU frame without a PHY data\n"); - return; - } - - if (include_phy) { - header = (struct ieee80211_hdr *)((u8 *) &rx_start[1] - + rx_start->cfg_phy_cnt); - - len = le16_to_cpu(rx_start->byte_count); - rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + - sizeof(struct iwl_rx_phy_res) + len); - } else { - struct iwl4965_rx_mpdu_res_start *amsdu = - (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; - - header = (void *)(pkt->u.raw + - sizeof(struct iwl4965_rx_mpdu_res_start)); - len = le16_to_cpu(amsdu->byte_count); - rx_end = (__le32 *) (pkt->u.raw + - sizeof(struct iwl4965_rx_mpdu_res_start) + len); - } - - if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) || - !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) { - IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", - le32_to_cpu(*rx_end)); - return; - } - - priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); + priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); /* Find max signal strength (dBm) among 3 antenna/receiver chains */ - rx_status.signal = iwl_calc_rssi(priv, rx_start); + rx_status.signal = iwl_calc_rssi(priv, phy_res); /* Meaningful noise values are available only from beacon statistics, * which are gathered only when associated, and indicate noise @@ -1050,10 +1000,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (!iwl_is_associated(priv)) priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - /* Set "1" to report good data frames in groups of 100 */ #ifdef CONFIG_IWLWIFI_DEBUG + /* Set "1" to report good data frames in groups of 100 */ if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) - iwl_dbg_report_frame(priv, rx_start, len, header, 1); + iwl_dbg_report_frame(priv, phy_res, len, header, 1); #endif iwl_dbg_log_rx_data_frame(priv, len, header); IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", @@ -1073,18 +1023,18 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, * new 802.11n radiotap field "RX chains" that is defined * as a bitmask. */ - rx_status.antenna = le16_to_cpu(rx_start->phy_flags & - RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; + rx_status.antenna = + le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK) + >> RX_RES_PHY_FLAGS_ANTENNA_POS; /* set the preamble flag if appropriate */ - if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) + if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) rx_status.flag |= RX_FLAG_SHORTPRE; - network_packet = iwl_is_network_packet(priv, header); - if (network_packet) { + if (iwl_is_network_packet(priv, header)) { priv->last_rx_rssi = rx_status.signal; priv->last_beacon_time = priv->ucode_beacon_time; - priv->last_tsf = le64_to_cpu(rx_start->timestamp); + priv->last_tsf = le64_to_cpu(phy_res->timestamp); } fc = le16_to_cpu(header->frame_control); @@ -1096,8 +1046,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, header->addr2); /* fall through */ default: - iwl_pass_packet_to_mac80211(priv, include_phy, rxb, - &rx_status); + iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, + rxb, &rx_status); break; } -- cgit v1.2.3 From 28bd723bbaddba4e145d25117649bb6da5fafad7 Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:30:57 -0700 Subject: iwlwifi: configure HT40 channels in iwl_mac_config As indicated by note in iwl_ht_conf, some HT parameters are set on association (e.g., channel width) and some vary over time (HT protection mode) and per station (e.g., short GI support). The global parameters should be set in iwl_mac_config and the local/varying parameters in iwl_ht_conf. This patch moves the channel width configuration from iwl_ht_conf to iwl_mac_config, and defers further cleanup of the local/global conflation for a later patch. This fixes a bug in using HT40 channels in some modes. Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 46 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 08345b97cb4..104fd95dfad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2398,25 +2398,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); - iwl_conf->supported_chan_width = - !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); - - /* - * XXX: The HT configuration needs to be moved into iwl_mac_config() - * to be done there correctly. - */ - - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - if (conf_is_ht40_minus(&priv->hw->conf)) - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - else if (conf_is_ht40_plus(&priv->hw->conf)) - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - - /* If no above or below channel supplied disable HT40 channel */ - if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && - iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) - iwl_conf->supported_chan_width = 0; - iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); @@ -2733,6 +2714,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; struct ieee80211_conf *conf = &hw->conf; + struct iwl_ht_info *ht_conf = &priv->current_ht_config; unsigned long flags = 0; int ret = 0; u16 ch; @@ -2774,10 +2756,32 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) goto set_ch_out; } - priv->current_ht_config.is_ht = conf_is_ht(conf); - spin_lock_irqsave(&priv->lock, flags); + /* Configure HT40 channels */ + ht_conf->is_ht = conf_is_ht(conf); + if (ht_conf->is_ht) { + if (conf_is_ht40_minus(conf)) { + ht_conf->extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ht_conf->supported_chan_width = + IWL_CHANNEL_WIDTH_40MHZ; + } else if (conf_is_ht40_plus(conf)) { + ht_conf->extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ht_conf->supported_chan_width = + IWL_CHANNEL_WIDTH_40MHZ; + } else { + ht_conf->extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ht_conf->supported_chan_width = + IWL_CHANNEL_WIDTH_20MHZ; + } + } else + ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ; + /* Default to no protection. Protection mode will later be set + * from BSS config in iwl_ht_conf */ + ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not -- cgit v1.2.3 From 28e6f48953f44f7eb615383efe6e7f17624a11bb Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:30:58 -0700 Subject: iwlwifi: check short GI support per-station rather than globally Short guard interval support is a local per-station parameter not a global per-NIC parameter. (mac80211 will correctly remove SGI support from station capabilities if the BSS does not permit it). This patch removes the short GI support bitfield from the global iwl_ht_info struct and properly uses per-station HT capabilities during rate selection. Signed-off-by: Daniel C Halperin Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 69 +++++++------------------------ drivers/net/wireless/iwlwifi/iwl-core.c | 5 --- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 -- 3 files changed, 15 insertions(+), 63 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 551c4ba3f17..3b1bbc394a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1225,18 +1225,6 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, else tbl->is_ht40 = 0; - /* FIXME: - don't toggle SGI here - if (tbl->is_ht40) { - if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) - tbl->is_SGI = 1; - else - tbl->is_SGI = 0; - } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) - tbl->is_SGI = 1; - else - tbl->is_SGI = 0; - */ - rs_set_expected_tpt_table(lq_sta, tbl); rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); @@ -1291,18 +1279,6 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, else tbl->is_ht40 = 0; - /* FIXME: - don't toggle SGI here - if (tbl->is_ht40) { - if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) - tbl->is_SGI = 1; - else - tbl->is_SGI = 0; - } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) - tbl->is_SGI = 1; - else - tbl->is_SGI = 0; - */ - rs_set_expected_tpt_table(lq_sta, tbl); rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); @@ -1350,18 +1326,6 @@ static int rs_switch_to_siso(struct iwl_priv *priv, else tbl->is_ht40 = 0; - /* FIXME: - don't toggle SGI here - if (tbl->is_ht40) { - if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) - tbl->is_SGI = 1; - else - tbl->is_SGI = 0; - } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) - tbl->is_SGI = 1; - else - tbl->is_SGI = 0; - */ - if (is_green) tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ @@ -1530,6 +1494,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, struct iwl_scale_tbl_info *search_tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); struct iwl_rate_scale_data *window = &(tbl->win[index]); + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; @@ -1589,13 +1554,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, goto out; break; case IWL_SISO_SWITCH_GI: - if (!tbl->is_ht40 && - !(priv->current_ht_config.sgf & - HT_SHORT_GI_20MHZ)) + if (!tbl->is_ht40 && !(ht_cap->cap & + IEEE80211_HT_CAP_SGI_20)) break; - if (tbl->is_ht40 && - !(priv->current_ht_config.sgf & - HT_SHORT_GI_40MHZ)) + if (tbl->is_ht40 && !(ht_cap->cap & + IEEE80211_HT_CAP_SGI_40)) break; IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n"); @@ -1669,6 +1632,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, struct iwl_scale_tbl_info *search_tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); struct iwl_rate_scale_data *window = &(tbl->win[index]); + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; @@ -1729,13 +1693,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, break; case IWL_MIMO2_SWITCH_GI: - if (!tbl->is_ht40 && - !(priv->current_ht_config.sgf & - HT_SHORT_GI_20MHZ)) + if (!tbl->is_ht40 && !(ht_cap->cap & + IEEE80211_HT_CAP_SGI_20)) break; - if (tbl->is_ht40 && - !(priv->current_ht_config.sgf & - HT_SHORT_GI_40MHZ)) + if (tbl->is_ht40 && !(ht_cap->cap & + IEEE80211_HT_CAP_SGI_40)) break; IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); @@ -1811,6 +1773,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, struct iwl_scale_tbl_info *search_tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); struct iwl_rate_scale_data *window = &(tbl->win[index]); + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; @@ -1893,13 +1856,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, break; case IWL_MIMO3_SWITCH_GI: - if (!tbl->is_ht40 && - !(priv->current_ht_config.sgf & - HT_SHORT_GI_20MHZ)) + if (!tbl->is_ht40 && !(ht_cap->cap & + IEEE80211_HT_CAP_SGI_20)) break; - if (tbl->is_ht40 && - !(priv->current_ht_config.sgf & - HT_SHORT_GI_40MHZ)) + if (tbl->is_ht40 && !(ht_cap->cap & + IEEE80211_HT_CAP_SGI_40)) break; IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 104fd95dfad..b845cf30e1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2391,11 +2391,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, } ht_conf = &sta->ht_cap; - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) - iwl_conf->sgf |= HT_SHORT_GI_20MHZ; - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) - iwl_conf->sgf |= HT_SHORT_GI_40MHZ; - iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index db745343d36..e6a1c6ff44d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -508,7 +508,6 @@ struct iwl_ht_info { u8 supported_chan_width; u8 sm_ps; u8 is_green_field; - u8 sgf; /* HT_SHORT_GI_* short guard interval */ struct ieee80211_mcs_info mcs; /* BSS related data */ u8 extension_chan_offset; @@ -728,9 +727,6 @@ struct iwl_dma_ptr { size_t size; }; -#define HT_SHORT_GI_20MHZ (1 << 0) -#define HT_SHORT_GI_40MHZ (1 << 1) - #define IWL_CHANNEL_WIDTH_20MHZ 0 #define IWL_CHANNEL_WIDTH_40MHZ 1 -- cgit v1.2.3 From b261793da587160d12ce6d63db60493342ddce20 Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:30:59 -0700 Subject: iwlwifi: use station HT capabilities and BSS operating mode for Green-field Green-field mode should be configured in the HT station table. This patch uses both the per-station GF support flag as well as the current BSS HT operation mode (non-GF stations present flag). Added the "ht_greenfield_support" field to struct iwl_cfg to replace the device-specific check in rs_use_green(). That check has been moved to iwlcore_init_ht_hw_capab(). Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.c | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 26 +++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-core.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 9 files changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9bb6a287eae..a95caa01414 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -158,5 +158,6 @@ struct iwl_cfg iwl1000_bgn_cfg = { .need_pll_cfg = true, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, + .ht_greenfield_support = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ba5ef832d77..b5a4d2ecdd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2889,7 +2889,8 @@ static struct iwl_cfg iwl3945_bg_cfg = { .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params, - .use_isr_legacy = true + .use_isr_legacy = true, + .ht_greenfield_support = false, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2902,7 +2903,8 @@ static struct iwl_cfg iwl3945_abg_cfg = { .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params, - .use_isr_legacy = true + .use_isr_legacy = true, + .ht_greenfield_support = false, }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e427a8937ed..6a13bfbc9d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2344,7 +2344,8 @@ struct iwl_cfg iwl4965_agn_cfg = { .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, .ops = &iwl4965_ops, .mod_params = &iwl4965_mod_params, - .use_isr_legacy = true + .use_isr_legacy = true, + .ht_greenfield_support = false, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 755c184b3ec..e1e862eb5ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1652,6 +1652,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .need_pll_cfg = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl5100_bg_cfg = { @@ -1668,6 +1669,7 @@ struct iwl_cfg iwl5100_bg_cfg = { .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, .need_pll_cfg = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -1684,6 +1686,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, .need_pll_cfg = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -1700,6 +1703,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, .need_pll_cfg = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1716,6 +1720,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .need_pll_cfg = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1732,6 +1737,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .need_pll_cfg = true, + .ht_greenfield_support = true, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 0b731fd5ad1..383177db7de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -171,6 +171,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = { .pa_type = IWL_PA_HYBRID, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, + .ht_greenfield_support = true, }; /* @@ -193,6 +194,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .pa_type = IWL_PA_INTERNAL, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -212,6 +214,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -231,6 +234,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, + .ht_greenfield_support = true, }; struct iwl_cfg iwl6050_3agn_cfg = { @@ -250,6 +254,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, + .ht_greenfield_support = true, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3b1bbc394a4..fee110de5c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -657,19 +657,15 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, return 1; } -/* in 4965 we don't use greenfield at all */ -static inline u8 rs_use_green(struct iwl_priv *priv, - struct ieee80211_conf *conf) +/** + * Green-field mode is valid if the station supports it and + * there are no non-GF stations present in the BSS. + */ +static inline u8 rs_use_green(struct ieee80211_sta *sta, + struct iwl_ht_info *ht_conf) { - u8 is_green; - - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) - is_green = 0; - else - is_green = (conf_is_ht(conf) && - priv->current_ht_config.is_green_field && - !priv->current_ht_config.non_GF_STA_present); - return is_green; + return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && + !(ht_conf->non_GF_STA_present); } /** @@ -2072,7 +2068,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (is_legacy(tbl->lq_type)) lq_sta->is_green = 0; else - lq_sta->is_green = rs_use_green(priv, conf); + lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); is_green = lq_sta->is_green; /* current tx rate */ @@ -2430,7 +2426,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, int rate_idx; int i; u32 rate; - u8 use_green = rs_use_green(priv, conf); + u8 use_green = rs_use_green(sta, &priv->current_ht_config); u8 active_tbl = 0; u8 valid_tx_ant; @@ -2627,7 +2623,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->is_dup = 0; lq_sta->max_rate_idx = -1; lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; - lq_sta->is_green = rs_use_green(priv, conf); + lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); lq_sta->active_rate_basic = priv->active_rate_basic; lq_sta->band = priv->band; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b845cf30e1b..62aa87b4358 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -394,7 +394,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->ht_supported = true; - ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; + if (priv->cfg->ht_greenfield_support) + ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_SGI_20; ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & (WLAN_HT_CAP_SM_PS_DISABLED << 2)); @@ -2391,8 +2392,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, } ht_conf = &sta->ht_cap; - iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); - iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 509683487e0..4ca025a34da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -251,6 +251,7 @@ struct iwl_cfg { enum iwl_pa_type pa_type; const u16 max_ll_items; const bool shadow_ram_support; + const bool ht_greenfield_support; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e6a1c6ff44d..0178734499f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -507,7 +507,6 @@ struct iwl_ht_info { u8 is_ht; u8 supported_chan_width; u8 sm_ps; - u8 is_green_field; struct ieee80211_mcs_info mcs; /* BSS related data */ u8 extension_chan_offset; -- cgit v1.2.3 From 15993e08ac027b64b6f3400d32754966b4cac7b0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 13 Aug 2009 13:31:00 -0700 Subject: iwlwifi: add thermal throttling support to 5150 Adding legacy thermal throttling management support to 5150 NIC Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e1e862eb5ac..720d234c973 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1411,6 +1411,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; /* now vt hold the temperature in Kelvin */ priv->temperature = KELVIN_TO_CELSIUS(vt); + iwl_tt_handler(priv); } /* Calc max signal level (dBm) among 3 possible receivers */ -- cgit v1.2.3 From 396887a2b2ad1ef5e5526fec34dec582baf39b81 Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Thu, 13 Aug 2009 13:31:01 -0700 Subject: iwlwifi: fix erroneous use of iwl_rx_packet.len as a length The field called 'len' in struct iwl_rx_packet is in fact not just a length field but also includes some flags from the flow handler. In several places throughout the driver, this causes incorrect values to be interpreted as lengths when the field is improperly masked. In most situations the improper use is for debugging output, and simply results in an erroneous message, such as: [551933.070224] ieee80211 phy0: I iwl_rx_statistics Statistics notification received (480 vs -1367342620). which should read '(480 vs 484)'. In at least one case this could case bad things to happen: void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len) ); } EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); Given the rampant misuse of this field without proper masking throughout the driver (every use but one), this patch renames the field from 'len' to 'len_n_flags' to reduce confusion. It also adds the proper masking when this field is used as a length value. Signed-off-by: Daniel C Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-rx.c | 3 ++- 5 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b5a4d2ecdd2..e9a685d8e3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -349,12 +349,13 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, * *****************************************************************************/ -void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +void iwl3945_hw_rx_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(struct iwl3945_notif_statistics), - le32_to_cpu(pkt->len)); + le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 720d234c973..1d539e3b8db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -494,7 +494,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; - int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK; + int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; int index; /* reduce the size of the length field itself */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 9398ad7e42b..f4303843ff9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3482,7 +3482,7 @@ struct iwl_wimax_coex_cmd { *****************************************************************************/ struct iwl_rx_packet { - __le32 len; + __le32 len_n_flags; struct iwl_cmd_header hdr; union { struct iwl3945_rx_frame rx_frame; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 62aa87b4358..f4c2431017e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2294,10 +2294,11 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; + u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " - "notification for %s:\n", - le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); - iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); + "notification for %s:\n", len, + get_cmd_string(pkt->hdr.cmd)); + iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); } EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 092d3276175..353d9a2ddbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -539,7 +539,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", - (int)sizeof(priv->statistics), pkt->len); + (int)sizeof(priv->statistics), + le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); change = ((priv->statistics.general.temperature != pkt->u.stats.general.temperature) || -- cgit v1.2.3 From b23da49e6db341f4721476394dd8b95e0be2d179 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 13 Aug 2009 13:31:02 -0700 Subject: iwlwifi: disable PS by default Unfortunately, PS currently affects RX performance significantly enough to warrant disabling it by default, but give the user the choice to enable it again with iwconfig. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f4c2431017e..c0efa6623c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1580,6 +1580,12 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Firmware does not support this */ hw->wiphy->disable_beacon_hints = true; + /* + * For now, disable PS by default because it affects + * RX performance significantly. + */ + hw->wiphy->ps_default = false; + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; /* we create the 802.11 header and a zero-length SSID element */ hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; -- cgit v1.2.3 From 6f632d57f35303118685b88c139f3da73df077e2 Mon Sep 17 00:00:00 2001 From: Andrey Yurovsky Date: Thu, 13 Aug 2009 17:34:40 -0700 Subject: libertas: don't use dynamic-sized array sparse complains about a bad constant expression due to the use of a dynamic-sized array in get_common_rates(). Allocate and free the array instead. Signed-off-by: Andrey Yurovsky Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 385b50f4b10..81f86ef2699 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -45,9 +45,14 @@ static int get_common_rates(struct lbs_private *priv, u8 *card_rates = lbs_bg_rates; size_t num_card_rates = sizeof(lbs_bg_rates); int ret = 0, i, j; - u8 tmp[30]; + u8 *tmp; size_t tmp_size = 0; + tmp = kzalloc((ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1), + GFP_KERNEL); + if (!tmp) + return -1; + /* For each rate in card_rates that exists in rate1, copy to tmp */ for (i = 0; card_rates[i] && (i < num_card_rates); i++) { for (j = 0; rates[j] && (j < *rates_size); j++) { @@ -77,6 +82,7 @@ done: memset(rates, 0, *rates_size); *rates_size = min_t(int, tmp_size, *rates_size); memcpy(rates, tmp, *rates_size); + kfree(tmp); return ret; } -- cgit v1.2.3 From 588f8377c5470fab611c14ead768f7f9af87da94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Thu, 13 Aug 2009 22:46:30 +0200 Subject: b43: LP-PHY: Implement channel switching for rev2+/B2063 radio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev.2+/B2063 will now hopefully show some signs of life, though it won't work at full performance, as calibration is still missing. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 424 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 402 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 996b7eccfaf..86da8281d92 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -29,6 +29,25 @@ #include "tables_lpphy.h" +static inline u16 channel2freq_lp(u8 channel) +{ + if (channel < 14) + return (2407 + 5 * channel); + else if (channel == 14) + return 2484; + else if (channel < 184) + return (5000 + 5 * channel); + else + return (4000 + 5 * channel); +} + +static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) +{ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + return 1; + return 36; +} + static int b43_lpphy_op_allocate(struct b43_wldev *dev) { struct b43_phy_lp *lpphy; @@ -142,10 +161,9 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) } } -static void lpphy_adjust_gain_table(struct b43_wldev *dev) +static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq) { struct b43_phy_lp *lpphy = dev->phy.lp; - u32 freq = dev->wl->hw->conf.channel->center_freq; u16 temp[3]; u16 isolation; @@ -170,6 +188,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev) static void lpphy_table_init(struct b43_wldev *dev) { + u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev)); + if (dev->phy.rev < 2) lpphy_rev0_1_table_init(dev); else @@ -178,7 +198,7 @@ static void lpphy_table_init(struct b43_wldev *dev) lpphy_init_tx_gain_table(dev); if (dev->phy.rev < 2) - lpphy_adjust_gain_table(dev); + lpphy_adjust_gain_table(dev, freq); } static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) @@ -1363,20 +1383,6 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev) } } -static int b43_lpphy_op_init(struct b43_wldev *dev) -{ - lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? - lpphy_baseband_init(dev); - lpphy_radio_init(dev); - lpphy_calibrate_rc(dev); - //TODO set channel - lpphy_tx_pctl_init(dev); - lpphy_calibration(dev); - //TODO ACI init - - return 0; -} - static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) { b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); @@ -1419,18 +1425,392 @@ static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, //TODO } +struct b206x_channel { + u8 channel; + u16 freq; + u8 data[12]; +}; + +static const struct b206x_channel b2063_chantbl[] = { + { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C, + .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C, + .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C, + .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C, + .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C, + .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C, + .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C, + .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C, + .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C, + .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C, + .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C, + .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C, + .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C, + .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, + .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x80, .data[11] = 0x70, }, + { .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05, + .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05, + .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, + .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, + .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, + .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04, + .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03, + .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03, + .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02, + .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60, + .data[10] = 0x20, .data[11] = 0x00, }, + { .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01, + .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, + .data[10] = 0x10, .data[11] = 0x00, }, + { .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01, + .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, + .data[10] = 0x10, .data[11] = 0x00, }, + { .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, + .data[10] = 0x10, .data[11] = 0x00, }, + { .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, + .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, + .data[10] = 0x00, .data[11] = 0x00, }, + { .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0, + .data[10] = 0x50, .data[11] = 0x00, }, + { .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0, + .data[10] = 0x50, .data[11] = 0x00, }, + { .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0, + .data[10] = 0x50, .data[11] = 0x00, }, + { .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, + .data[10] = 0x40, .data[11] = 0x00, }, + { .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, + .data[10] = 0x40, .data[11] = 0x00, }, + { .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, + .data[10] = 0x40, .data[11] = 0x00, }, + { .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, + .data[10] = 0x40, .data[11] = 0x00, }, + { .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, + .data[10] = 0x40, .data[11] = 0x00, }, + { .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C, + .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08, + .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, + .data[10] = 0x40, .data[11] = 0x00, }, +}; + +static void lpphy_b2062_tune(struct b43_wldev *dev, + unsigned int channel) +{ + //TODO +} + +static void lpphy_b2063_vco_calib(struct b43_wldev *dev) +{ + u16 tmp; + + b43_phy_mask(dev, B2063_PLL_SP1, ~0x40); + tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8; + b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp); + udelay(1); + b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4); + udelay(1); + b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6); + udelay(1); + b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7); + udelay(300); + b43_phy_set(dev, B2063_PLL_SP1, 0x40); +} + +static void lpphy_b2063_tune(struct b43_wldev *dev, + unsigned int channel) +{ + struct ssb_bus *bus = dev->dev->bus; + + static const struct b206x_channel *chandata = NULL; + u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; + u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count; + u16 old_comm15, scale; + u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + int i, div = (crystal_freq <= 26000000 ? 1 : 2); + + for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) { + if (b2063_chantbl[i].channel == channel) { + chandata = &b2063_chantbl[i]; + break; + } + } + + if (B43_WARN_ON(!chandata)) + return; + + b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]); + b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]); + b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]); + b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]); + b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]); + b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]); + b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]); + b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]); + b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]); + b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]); + b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]); + b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]); + + old_comm15 = b43_radio_read(dev, B2063_COMM15); + b43_radio_set(dev, B2063_COMM15, 0x1E); + + if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */ + vco_freq = chandata->freq << 1; + else + vco_freq = chandata->freq << 2; + + freqref = crystal_freq * 3; + val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16); + val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16); + val3 = lpphy_qdiv_roundup(vco_freq, 3, 16); + timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1; + b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2); + b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6, + 0xFFF8, timeout >> 2); + b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7, + 0xFF9F,timeout << 5); + + timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) + + 999999) / 1000000) + 1; + b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref); + + count = lpphy_qdiv_roundup(val3, val2 + 16, 16); + count *= (timeout + 1) * (timeoutref + 1); + count--; + b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7, + 0xF0, count >> 8); + b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF); + + tmp1 = ((val3 * 62500) / freqref) << 4; + tmp2 = ((val3 * 62500) % freqref) << 4; + while (tmp2 >= freqref) { + tmp1++; + tmp2 -= freqref; + } + b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4); + b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4); + b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16); + b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF); + b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF); + + b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9); + b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88); + b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28); + b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63); + + tmp3 = ((41 * (val3 - 3000)) /1200) + 27; + tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16); + + if ((tmp4 + tmp3 - 1) / tmp3 > 60) { + scale = 1; + tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8; + } else { + scale = 0; + tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8; + } + b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5); + b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6); + + tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16); + tmp6 *= (tmp5 * 8) * (scale + 1); + if (tmp6 > 150) + tmp6 = 0; + + b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6); + b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5); + + b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4); + if (crystal_freq > 26000000) + b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2); + else + b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD); + + if (val1 == 45) + b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2); + else + b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD); + + b43_phy_set(dev, B2063_PLL_SP2, 0x3); + udelay(1); + b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC); + lpphy_b2063_vco_calib(dev); + b43_radio_write(dev, B2063_COMM15, old_comm15); +} + static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, unsigned int new_channel) { - //TODO + b43_write16(dev, B43_MMIO_CHANNEL, new_channel); + + if (dev->phy.radio_ver == 0x2063) { + lpphy_b2063_tune(dev, new_channel); + } else { + lpphy_b2062_tune(dev, new_channel); + //TODO Japan filter + } + + lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); + return 0; } -static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) +static int b43_lpphy_op_init(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - return 1; - return 36; + lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? + lpphy_baseband_init(dev); + lpphy_radio_init(dev); + lpphy_calibrate_rc(dev); + b43_lpphy_op_switch_channel(dev, b43_lpphy_op_get_default_chan(dev)); + lpphy_tx_pctl_init(dev); + lpphy_calibration(dev); + //TODO ACI init + + return 0; } static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) -- cgit v1.2.3 From 1e711bee566e26f03e51d5a754e7c8a57e489f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 00:15:17 +0200 Subject: b43: LP-PHY: Implement channel switching for rev0/1/B2062 radio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Move pdiv from lpphy_2062_init to struct b43_phy_lp. -Add channel table for the B2062 radio. -Add code for tuning the B2062 radio to channel. -Add error handling to op_switch_channel, and use it for both radios. Rev0/1/B2062 will now hopefully show some signs of life, though it won't work at full performance, as calibration is still missing. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 297 ++++++++++++++++++++++++++++++++++++-- drivers/net/wireless/b43/phy_lp.h | 2 + 2 files changed, 284 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 86da8281d92..e010268b987 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -455,8 +455,9 @@ struct b2062_freqdata { /* Initialize the 2062 radio. */ static void lpphy_2062_init(struct b43_wldev *dev) { + struct b43_phy_lp *lpphy = dev->phy.lp; struct ssb_bus *bus = dev->dev->bus; - u32 crystalfreq, pdiv, tmp, ref; + u32 crystalfreq, tmp, ref; unsigned int i; const struct b2062_freqdata *fd = NULL; @@ -496,22 +497,24 @@ static void lpphy_2062_init(struct b43_wldev *dev) B43_WARN_ON(crystalfreq == 0); if (crystalfreq >= 30000000) { - pdiv = 1; + lpphy->pdiv = 1; b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); } else { - pdiv = 2; + lpphy->pdiv = 2; b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); } - tmp = (800000000 * pdiv + crystalfreq) / (32000000 * pdiv); + tmp = (800000000 * lpphy->pdiv + crystalfreq) / + (32000000 * lpphy->pdiv); tmp = (tmp - 1) & 0xFF; b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); - tmp = (2 * crystalfreq + 1000000 * pdiv) / (2000000 * pdiv); + tmp = (2 * crystalfreq + 1000000 * lpphy->pdiv) / + (2000000 * lpphy->pdiv); tmp = ((tmp & 0xFF) - 1) & 0xFFFF; b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); - ref = (1000 * pdiv + 2 * crystalfreq) / (2000 * pdiv); + ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv); ref &= 0xFFFF; for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { if (ref < freqdata_tab[i].freq) { @@ -1431,6 +1434,162 @@ struct b206x_channel { u8 data[12]; }; +static const struct b206x_channel b2062_chantbl[] = { + { .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF, + .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, + .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, + { .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22, + .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11, + .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11, + .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11, + .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11, + .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11, + .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00, + .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77, + .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77, + .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66, + .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66, + .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55, + .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55, + .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44, + .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, + { .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44, + .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, + { .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44, + .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77, + .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, +}; + static const struct b206x_channel b2063_chantbl[] = { { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C, .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, @@ -1638,10 +1797,110 @@ static const struct b206x_channel b2063_chantbl[] = { .data[10] = 0x40, .data[11] = 0x00, }, }; -static void lpphy_b2062_tune(struct b43_wldev *dev, - unsigned int channel) +static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) { - //TODO + struct ssb_bus *bus = dev->dev->bus; + + b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF); + udelay(20); + if (bus->chip_id == 0x5354) { + b43_radio_write(dev, B2062_N_COMM1, 4); + b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4); + } else { + b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0); + } + udelay(5); +} + +static void lpphy_b2062_vco_calib(struct b43_wldev *dev) +{ + b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42); + b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62); + udelay(200); +} + +static int lpphy_b2062_tune(struct b43_wldev *dev, + unsigned int channel) +{ + struct b43_phy_lp *lpphy = dev->phy.lp; + struct ssb_bus *bus = dev->dev->bus; + static const struct b206x_channel *chandata = NULL; + u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; + u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; + int i, err = 0; + + for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) { + if (b2063_chantbl[i].channel == channel) { + chandata = &b2063_chantbl[i]; + break; + } + } + + if (B43_WARN_ON(!chandata)) + return -EINVAL; + + b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04); + b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]); + b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]); + b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]); + b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]); + b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]); + b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]); + b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]); + b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]); + b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]); + + tmp1 = crystal_freq / 1000; + tmp2 = lpphy->pdiv * 1000; + b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC); + b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07); + lpphy_b2062_reset_pll_bias(dev); + tmp3 = tmp2 * channel2freq_lp(channel); + if (channel2freq_lp(channel) < 4000) + tmp3 *= 2; + tmp4 = 48 * tmp1; + tmp6 = tmp3 / tmp4; + tmp7 = tmp3 % tmp4; + b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6); + tmp5 = tmp7 * 0x100; + tmp6 = tmp5 / tmp4; + tmp7 = tmp5 % tmp4; + b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6); + tmp5 = tmp7 * 0x100; + tmp6 = tmp5 / tmp4; + tmp7 = tmp5 % tmp4; + b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4)); + tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19); + tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1); + b43_radio_write(dev, B2062_S_RFPLL_CTL23, tmp9 >> 8); + b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF); + + lpphy_b2062_vco_calib(dev); + if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) { + b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC); + b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0); + lpphy_b2062_reset_pll_bias(dev); + lpphy_b2062_vco_calib(dev); + if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) + err = -EINVAL; + } + + b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04); + return err; +} + +static void lpphy_japan_filter(struct b43_wldev *dev, int channel) +{ + struct b43_phy_lp *lpphy = dev->phy.lp; + u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! + + if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific? + b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9); + if ((dev->phy.rev == 1) && (lpphy->rc_cap)) + lpphy_set_rc_cap(dev); + } else { + b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F); + } } static void lpphy_b2063_vco_calib(struct b43_wldev *dev) @@ -1661,8 +1920,8 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev) b43_phy_set(dev, B2063_PLL_SP1, 0x40); } -static void lpphy_b2063_tune(struct b43_wldev *dev, - unsigned int channel) +static int lpphy_b2063_tune(struct b43_wldev *dev, + unsigned int channel) { struct ssb_bus *bus = dev->dev->bus; @@ -1681,7 +1940,7 @@ static void lpphy_b2063_tune(struct b43_wldev *dev, } if (B43_WARN_ON(!chandata)) - return; + return -EINVAL; b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]); b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]); @@ -1780,18 +2039,26 @@ static void lpphy_b2063_tune(struct b43_wldev *dev, b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC); lpphy_b2063_vco_calib(dev); b43_radio_write(dev, B2063_COMM15, old_comm15); + + return 0; } static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, unsigned int new_channel) { + int err; + b43_write16(dev, B43_MMIO_CHANNEL, new_channel); if (dev->phy.radio_ver == 0x2063) { - lpphy_b2063_tune(dev, new_channel); + err = lpphy_b2063_tune(dev, new_channel); + if (err) + return err; } else { - lpphy_b2062_tune(dev, new_channel); - //TODO Japan filter + err = lpphy_b2062_tune(dev, new_channel); + if (err) + return err; + lpphy_japan_filter(dev, new_channel); } lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 4eab760ac61..99cb0386e34 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h @@ -884,6 +884,8 @@ struct b43_phy_lp { /* Used for "Save/Restore Dig Filt State" */ u16 dig_flt_state[9]; + + unsigned int pdiv; }; enum tssi_mux_mode { -- cgit v1.2.3 From db91f2e4d410bf3011b3649b9257e5b3c60b25ff Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Fri, 14 Aug 2009 11:27:16 +0530 Subject: ath9k: Add open loop power control support for AR9287. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 44 +++++++++++++++++++++++----------- drivers/net/wireless/ath/ath9k/hw.c | 20 ++++++++++++---- drivers/net/wireless/ath/ath9k/phy.h | 7 ++++++ 3 files changed, 52 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 26d87527acb..20f74b5b570 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -729,26 +729,42 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) static void ath9k_olc_temp_compensation(struct ath_hw *ah) { u32 rddata, i; - int delta, currPDADC, regval; + int delta, currPDADC, regval, slope; rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); - currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) - delta = (currPDADC - ah->initPDADC + 4) / 8; - else - delta = (currPDADC - ah->initPDADC + 5) / 10; - if (delta != ah->PDADCdelta) { - ah->PDADCdelta = delta; - for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { - regval = ah->originalGain[i] - delta; - if (regval < 0) - regval = 0; + if (OLC_FOR_AR9287_10_LATER) { + if (ah->initPDADC == 0 || currPDADC == 0) { + return; + } else { + slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); + if (slope == 0) + delta = 0; + else + delta = ((currPDADC - ah->initPDADC)*4) / slope; + REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, + AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); + } + } else { + if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) + delta = (currPDADC - ah->initPDADC + 4) / 8; + else + delta = (currPDADC - ah->initPDADC + 5) / 10; + + if (delta != ah->PDADCdelta) { + ah->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = ah->originalGain[i] - delta; + if (regval < 0) + regval = 0; - REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, - AR_PHY_TX_GAIN, regval); + REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); + } } } } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9f1b34d9861..125e689f7c5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1332,11 +1332,21 @@ static void ath9k_olc_init(struct ath_hw *ah) { u32 i; - for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) - ah->originalGain[i] = - MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), - AR_PHY_TX_GAIN); - ah->PDADCdelta = 0; + if (OLC_FOR_AR9287_10_LATER) { + REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, + AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); + ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, + AR9287_AN_TXPC0_TXPCMODE, + AR9287_AN_TXPC0_TXPCMODE_S, + AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); + udelay(100); + } else { + for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) + ah->originalGain[i] = + MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), + AR_PHY_TX_GAIN); + ah->PDADCdelta = 0; + } } static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index e83cd4ab87f..dfda6f44464 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -490,11 +490,18 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, #define AR_PHY_TX_PWRCTRL9 0xa27C #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 #define AR_PHY_TX_GAIN_TBL1 0xa300 #define AR_PHY_TX_GAIN 0x0007F000 #define AR_PHY_TX_GAIN_S 12 +#define AR_PHY_CH0_TX_PWRCTRL11 0xa398 +#define AR_PHY_CH1_TX_PWRCTRL11 0xb398 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 + #define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 #define AR_PHY_MASK2_M_31_45 0xa3a4 #define AR_PHY_MASK2_M_16_30 0xa3a8 -- cgit v1.2.3 From d340b1f0e5e374fc902a020cb6ef9ebd7fb9f368 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Fri, 14 Aug 2009 11:29:27 +0530 Subject: ath9k: Set AR_WA for AR9287 as it improves consistency in throughput. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 125e689f7c5..9a139dcc69b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3073,7 +3073,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) if (ah->config.pcie_waen) { REG_WRITE(ah, AR_WA, ah->config.pcie_waen); } else { - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); /* * On AR9280 chips bit 22 of 0x4004 needs to be set to -- cgit v1.2.3 From 08fc5c1ba026de0904aeeba9785f95f6603d58f7 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Fri, 14 Aug 2009 11:30:52 +0530 Subject: ath9k: Enable LEDs for AR9287 chipsets. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 ++- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 27 ++++++++++++++++----------- drivers/net/wireless/ath/ath9k/pci.c | 6 +++--- 4 files changed, 22 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2fd663c01b8..2c9f6628a8e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -454,7 +454,8 @@ struct ath_ani { /* LED Control */ /********************/ -#define ATH_LED_PIN 1 +#define ATH_LED_PIN_DEF 1 +#define ATH_LED_PIN_9287 8 #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0336981a70e..de31a1595f1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -522,6 +522,7 @@ struct ath_hw { u32 originalGain[22]; int initPDADC; int PDADCdelta; + u8 led_pin; struct ar5416IniArray iniModes; struct ar5416IniArray iniCommon; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index fa4c6e74f97..3e09b9ac165 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -968,9 +968,9 @@ static void ath_led_blink_work(struct work_struct *work) if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); else - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); ieee80211_queue_delayed_work(sc->hw, @@ -1002,7 +1002,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev, case LED_OFF: if (led->led_type == ATH_LED_ASSOC || led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (led->led_type == ATH_LED_RADIO)); sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; if (led->led_type == ATH_LED_RADIO) @@ -1017,7 +1017,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev, ieee80211_queue_delayed_work(sc->hw, &sc->ath_led_blink_work, 0); } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); sc->sc_flags |= SC_OP_LED_ON; } else { sc->led_on_cnt++; @@ -1062,7 +1062,7 @@ static void ath_deinit_leds(struct ath_softc *sc) ath_unregister_led(&sc->tx_led); ath_unregister_led(&sc->rx_led); ath_unregister_led(&sc->radio_led); - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); } static void ath_init_leds(struct ath_softc *sc) @@ -1070,11 +1070,16 @@ static void ath_init_leds(struct ath_softc *sc) char *trigger; int ret; + if (AR_SREV_9287(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9287; + else + sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); @@ -1153,9 +1158,9 @@ void ath_radio_enable(struct ath_softc *sc) ath9k_hw_set_interrupts(ah, sc->imask); /* Enable LED */ - ath9k_hw_cfg_output(ah, ATH_LED_PIN, + ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); + ath9k_hw_set_gpio(ah, ah->led_pin, 0); ieee80211_wake_queues(sc->hw); ath9k_ps_restore(sc); @@ -1171,8 +1176,8 @@ void ath_radio_disable(struct ath_softc *sc) ieee80211_stop_queues(sc->hw); /* Disable LED */ - ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1); - ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN); + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); /* Disable interrupts */ ath9k_hw_set_interrupts(ah, 0); diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 616bdff2b6a..685a8cebb46 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -236,7 +236,7 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); pci_save_state(pdev); pci_disable_device(pdev); @@ -269,9 +269,9 @@ static int ath_pci_resume(struct pci_dev *pdev) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); /* Enable LED */ - ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); return 0; } -- cgit v1.2.3 From d4fe5afa006bf308962877c4768c4e60d37a3da2 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Fri, 14 Aug 2009 11:32:04 +0530 Subject: ath9k: Fix ref power interpolation logic for AR9287 chipsets. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index aeb7f484b6e..959097927ee 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -374,7 +374,6 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, u8 *pCalChans, u16 availPiers, int8_t *pPwr) { - u8 pcdac, i = 0; u16 idxL = 0, idxR = 0, numPiers; bool match; struct chan_centers centers; @@ -392,17 +391,12 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, &idxL, &idxR); if (match) { - pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0]; - *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0]; + *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; } else { - pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0]; - *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] + - pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + + (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; } - while ((pcdac > ah->originalGain[i]) && - (i < (AR9280_TX_GAIN_TABLE_SIZE - 1))) - i++; } static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, -- cgit v1.2.3 From 326bebbcb51d3ce9761f616b8b9a35827fd9c697 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Fri, 14 Aug 2009 11:33:36 +0530 Subject: ath9k: Updates for AR9287_12 version of chipset. Enable AsyncFIFO and AGGWEP for AR9287_12 and later revisions only. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 6 +++--- drivers/net/wireless/ath/ath9k/reg.h | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9a139dcc69b..df62113d89d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2392,7 +2392,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9280_10_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); - if (AR_SREV_9287_10_OR_LATER(ah)) { + if (AR_SREV_9287_12_OR_LATER(ah)) { /* Enable ASYNC FIFO */ REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); @@ -2478,7 +2478,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_user_settings(ah); - if (AR_SREV_9287_10_OR_LATER(ah)) { + if (AR_SREV_9287_12_OR_LATER(ah)) { REG_WRITE(ah, AR_D_GBL_IFS_SIFS, AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); REG_WRITE(ah, AR_D_GBL_IFS_SLOT, @@ -2494,7 +2494,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); } - if (AR_SREV_9287_10_OR_LATER(ah)) { + if (AR_SREV_9287_12_OR_LATER(ah)) { REG_SET_BIT(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_ENABLE_AGGWEP); } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 13fd658b5d3..c9e1ac92d0e 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -744,6 +744,7 @@ #define AR_SREV_VERSION_9287 0x180 #define AR_SREV_REVISION_9287_10 0 #define AR_SREV_REVISION_9287_11 1 +#define AR_SREV_REVISION_9287_12 2 #define AR_SREV_VERSION_9271 0x140 #define AR_SREV_REVISION_9271_10 0 #define AR_SREV_REVISION_9271_11 1 @@ -817,7 +818,13 @@ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) - +#define AR_SREV_9287_12(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12)) +#define AR_SREV_9287_12_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12))) #define AR_SREV_9271(_ah) \ (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) #define AR_SREV_9271_10(_ah) \ -- cgit v1.2.3 From c46aaba74f37448f0a1a3e911230834b7ebe514f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 14 Aug 2009 13:23:05 +0200 Subject: p54: disable PS by default Johannes kindly pointed out that I completely missed a hunk in his patch: "[PATCH] cfg80211: allow driver to override PS default". The driver must explicitly set ps_default to false, as the setting is pre-filled with the kconfig default. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 4a741df9c08..77203e346cd 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -575,6 +575,12 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 + sizeof(struct p54_tx_data); + /* + * For now, disable PS by default because it affects + * link stability significantly. + */ + dev->wiphy->ps_default = false; + mutex_init(&priv->conf_mutex); mutex_init(&priv->eeprom_mutex); init_completion(&priv->eeprom_comp); -- cgit v1.2.3 From 759b973bb2d24adecaa526957435eabb00f02725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 14:39:53 +0200 Subject: b43: Add LP-PHY firmware loading support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for loading LP-PHY firmware to b43_try_request_fw. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index f6d039e303f..2a75bebd329 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1955,8 +1955,12 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) filename = "ucode5"; else if ((rev >= 11) && (rev <= 12)) filename = "ucode11"; - else if (rev >= 13) + else if (rev == 13) filename = "ucode13"; + else if (rev == 14) + filename = "ucode14"; + else if (rev >= 15) + filename = "ucode15"; else goto err_no_ucode; err = b43_do_request_fw(ctx, filename, &fw->ucode); @@ -2004,6 +2008,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) else goto err_no_initvals; break; + case B43_PHYTYPE_LP: + if (rev == 13) + filename = "lp0initvals13"; + else if (rev == 14) + filename = "lp0initvals14"; + else if (rev >= 15) + filename = "lp0initvals15"; + else + goto err_no_initvals; + break; default: goto err_no_initvals; } @@ -2038,6 +2052,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) else goto err_no_initvals; break; + case B43_PHYTYPE_LP: + if (rev == 13) + filename = "lp0bsinitvals13"; + else if (rev == 14) + filename = "lp0bsinitvals14"; + else if (rev >= 15) + filename = "lp0bsinitvals15"; + else + goto err_no_initvals; + break; default: goto err_no_initvals; } -- cgit v1.2.3 From 9d86a2d531c722feb0046e5a0b81809efb10422a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 14:54:46 +0200 Subject: b43: Make LP-PHY testable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Enable rate memory init for LP-PHY (same as G and N-PHY). -Mark rev.2 LP-PHYs with the B2063 radio as supported. -Allow using the 5GHz band on LP-PHYs. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 2a75bebd329..99b41ce6848 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2589,6 +2589,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev) case B43_PHYTYPE_A: case B43_PHYTYPE_G: case B43_PHYTYPE_N: + case B43_PHYTYPE_LP: b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); @@ -3817,7 +3818,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) #endif #ifdef CONFIG_B43_PHY_LP case B43_PHYTYPE_LP: - if (phy_rev > 1) + if (phy_rev > 2) unsupported = 1; break; #endif @@ -3874,7 +3875,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) unsupported = 1; break; case B43_PHYTYPE_LP: - if (radio_ver != 0x2062) + if (radio_ver != 0x2062 && radio_ver != 0x2063) unsupported = 1; break; default: @@ -4512,9 +4513,10 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) case B43_PHYTYPE_A: have_5ghz_phy = 1; break; + case B43_PHYTYPE_LP: //FIXME not always! + have_5ghz_phy = 1; case B43_PHYTYPE_G: case B43_PHYTYPE_N: - case B43_PHYTYPE_LP: have_2ghz_phy = 1; break; default: @@ -4529,7 +4531,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) } if (1 /* disable A-PHY */) { /* FIXME: For now we disable the A-PHY on multi-PHY devices. */ - if (dev->phy.type != B43_PHYTYPE_N) { + if (dev->phy.type != B43_PHYTYPE_N && + dev->phy.type != B43_PHYTYPE_LP) { have_2ghz_phy = 1; have_5ghz_phy = 0; } -- cgit v1.2.3 From 0c61bb9a410de6ef36b4a473ced34f983a87db35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 21:11:59 +0200 Subject: b43: LP-PHY: Don't adjust gain table for rev2+ when setting channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rev2+ never needs to have gain tables adjusted according to the spec. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index e010268b987..ce81920d26d 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -2059,10 +2059,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, if (err) return err; lpphy_japan_filter(dev, new_channel); + lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); } - lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); - return 0; } -- cgit v1.2.3 From 16373f652523705aa07bf78b4f388d96feb8f9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 22:10:34 +0200 Subject: b43: LP-PHY: Update TX gain override for a spec typo fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index ce81920d26d..18d517cc292 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -747,7 +747,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev, 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_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 6); } static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) -- cgit v1.2.3 From 1245684c631844d52079fb3fa1fcb57cc1213e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 23:00:32 +0200 Subject: b43: LP-PHY: Fix another TX power control abuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should fix the remaining WARN_ON. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 18d517cc292..038a59d63a4 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1059,7 +1059,8 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) 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; + old_rf2_ovr, old_rf2_ovrval, old_phy_ctl; + enum b43_lpphy_txpctl_mode old_txpctl; u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; int loopback, i, j, inner_sum; @@ -1077,8 +1078,8 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) 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_read_tx_pctl_mode_from_hardware(dev); + old_txpctl = lpphy->txpctl_mode; lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); lpphy_disable_crs(dev); -- cgit v1.2.3 From 826ee70664c658a022d999f7eb4d3cd9448895dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sat, 15 Aug 2009 00:52:02 +0200 Subject: b43: Handle B43_PHYTYPE_LP in RX path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't drop all packets received from an LP-PHY with WARN_ON. Also update a comment with LP-specific information. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/wa.c | 2 +- drivers/net/wireless/b43/xmit.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index 73e97fa4ddf..97c79161c20 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -628,7 +628,7 @@ void b43_wa_all(struct b43_wldev *dev) B43_WARN_ON(1); } b43_wa_boards_g(dev); - } else { /* No N PHY support so far */ + } else { /* No N PHY support so far, LP PHY is in phy_lp.c */ B43_WARN_ON(1); } diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5280ebc8c6e..be1c53ecdb0 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -655,6 +655,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) status.freq = chanid + 2400; break; case B43_PHYTYPE_N: + case B43_PHYTYPE_LP: /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ) { -- cgit v1.2.3 From 96909e97716de1d86e6e24d6aabce09980372771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sun, 16 Aug 2009 01:15:49 +0200 Subject: b43: LP-PHY: Update baseband init for recent spec changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec had some nasty typos, and a large part of the rev0/1 BB init procedure was also missing. Fix these. Also make the init-time channel switch debuggable. (The change from -EINVAL to -EIO is simply to make it possible to distinguish the PLL charge pump error from a channel-not-found error.) Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 73 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 038a59d63a4..85af82a7f94 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -204,8 +204,62 @@ static void lpphy_table_init(struct b43_wldev *dev) static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) { struct ssb_bus *bus = dev->dev->bus; + struct b43_phy_lp *lpphy = dev->phy.lp; u16 tmp, tmp2; + b43_phy_mask(dev, B43_LPPHY_AFE_DAC_CTL, 0xF7FF); + b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0); + b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0); + b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0); + b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0); + b43_phy_set(dev, B43_LPPHY_AFE_DAC_CTL, 0x0004); + b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x0078); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800); + b43_phy_write(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x0016); + b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_0, 0xFFF8, 0x0004); + b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5400); + b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2400); + b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100); + b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006); + b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC10, 0x0180); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3800); + b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005); + b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A); + b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3); + b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00); + b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, + 0xFF00, lpphy->rx_pwr_offset); + if ((bus->sprom.boardflags_lo & B43_BFL_FEM) && + ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || + (bus->sprom.boardflags_hi & B43_BFH_PAREF))) { + /* TODO: + * Set the LDO voltage to 0x0028 - FIXME: What is this? + * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage + * as arguments + * Call sb_pmu_paref_ldo_enable with argument TRUE + */ + if (dev->phy.rev == 0) { + b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, + 0xFFCF, 0x0010); + } + b43_lptab_write(dev, B43_LPTAB16(11, 7), 60); + } else { + //TODO: Call ssb_pmu_paref_ldo_enable with argument FALSE + b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, + 0xFFCF, 0x0020); + b43_lptab_write(dev, B43_LPTAB16(11, 7), 100); + } + tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000; + b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp); + if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV) + b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA); + else + b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA); + b43_lptab_write(dev, B43_LPTAB16(11, 1), 24); + b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL, + 0xFFF9, (lpphy->bx_arch << 1)); if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) { b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); @@ -255,7 +309,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006); b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700); } - if (dev->phy.rev == 1) { + if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) { b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1); b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2); b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3); @@ -267,6 +321,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); + //FIXME the Broadcom driver caches & delays this HF write! b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W); } if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { @@ -384,7 +439,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9); b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF); b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xF81F, 0xA0); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0); b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300); b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { @@ -405,7 +460,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); - if ((bus->chip_id == 0x4325) && (bus->chip_rev == 1)) { + if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); } @@ -416,6 +471,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6); b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00); b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1); + b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF); } else /* 5GHz */ b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40); @@ -1883,7 +1939,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, lpphy_b2062_reset_pll_bias(dev); lpphy_b2062_vco_calib(dev); if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) - err = -EINVAL; + err = -EIO; } b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04); @@ -2068,11 +2124,18 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, static int b43_lpphy_op_init(struct b43_wldev *dev) { + int err; + lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? lpphy_baseband_init(dev); lpphy_radio_init(dev); lpphy_calibrate_rc(dev); - b43_lpphy_op_switch_channel(dev, b43_lpphy_op_get_default_chan(dev)); + err = b43_lpphy_op_switch_channel(dev, + b43_lpphy_op_get_default_chan(dev)); + if (err) { + b43dbg(dev->wl, "Switch to init channel failed, error = %d.\n", + err); + } lpphy_tx_pctl_init(dev); lpphy_calibration(dev); //TODO ACI init -- cgit v1.2.3 From 055114a38804947554065194d50ded4bc7d7c4c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sun, 16 Aug 2009 15:32:40 +0200 Subject: b43: LP-PHY: Fix a spec error in the B2062 channel switch routine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The channel switch routine had a whole instruction missing. Add it. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 85af82a7f94..cb6c18d2cdb 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1922,6 +1922,10 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, tmp5 = tmp7 * 0x100; tmp6 = tmp5 / tmp4; tmp7 = tmp5 % tmp4; + b43_radio_write(dev, B2062_S_RFPLL_CTL27, tmp6); + tmp5 = tmp7 * 0x100; + tmp6 = tmp5 / tmp4; + tmp7 = tmp5 % tmp4; b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6); tmp5 = tmp7 * 0x100; tmp6 = tmp5 / tmp4; -- cgit v1.2.3 From 5269102ec9c1584ccfab71affd1d7600d59f9096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sun, 16 Aug 2009 18:05:09 +0200 Subject: b43: LP-PHY: Update code for spec fixes, and fix a few typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A few typos have been discovered in both the specs and the code. This patch fixes them. Also use lpphy_op_switch_channel consistently, and make all users of it print its return value for easier debugging. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 53 ++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index cb6c18d2cdb..4d14102821c 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -552,7 +552,7 @@ static void lpphy_2062_init(struct b43_wldev *dev) B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)); B43_WARN_ON(crystalfreq == 0); - if (crystalfreq >= 30000000) { + if (crystalfreq <= 30000000) { lpphy->pdiv = 1; b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); } else { @@ -560,14 +560,16 @@ static void lpphy_2062_init(struct b43_wldev *dev) b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); } - tmp = (800000000 * lpphy->pdiv + crystalfreq) / - (32000000 * lpphy->pdiv); - tmp = (tmp - 1) & 0xFF; + tmp = (((800000000 * lpphy->pdiv + crystalfreq) / + (2 * crystalfreq)) - 8) & 0xFF; + b43_radio_write(dev, B2062_S_RFPLL_CTL7, tmp); + + tmp = (((100 * crystalfreq + 16000000 * lpphy->pdiv) / + (32000000 * lpphy->pdiv)) - 1) & 0xFF; b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); - tmp = (2 * crystalfreq + 1000000 * lpphy->pdiv) / - (2000000 * lpphy->pdiv); - tmp = ((tmp & 0xFF) - 1) & 0xFFFF; + tmp = (((2 * crystalfreq + 1000000 * lpphy->pdiv) / + (2000000 * lpphy->pdiv)) - 1) & 0xFF; b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv); @@ -671,7 +673,7 @@ static void lpphy_radio_init(struct b43_wldev *dev) b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD); udelay(1); - if (dev->phy.rev < 2) { + if (dev->phy.radio_ver == 0x2062) { lpphy_2062_init(dev); } else { lpphy_2063_init(dev); @@ -688,11 +690,18 @@ 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; + struct b43_phy_lp *lpphy = dev->phy.lp; + + u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1; - b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80)); - b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80); - b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80); + if (dev->phy.rev == 1) //FIXME check channel 14! + rc_cap = max_t(u8, rc_cap + 5, 15); + + b43_radio_write(dev, B2062_N_RXBB_CALIB2, + max_t(u8, lpphy->rc_cap - 4, 0x80)); + b43_radio_write(dev, B2062_N_TX_CTL_A, rc_cap | 0x80); + b43_radio_write(dev, B2062_S_RXG_CNT16, + ((lpphy->rc_cap & 0x1F) >> 2) | 0x80); } static u8 lpphy_get_bb_mult(struct b43_wldev *dev) @@ -1101,6 +1110,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, lpphy_write_tx_pctl_mode_to_hardware(dev); } +static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, + unsigned int new_channel); + static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; @@ -1118,11 +1130,16 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) old_rf2_ovr, old_rf2_ovrval, old_phy_ctl; enum b43_lpphy_txpctl_mode old_txpctl; u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; - int loopback, i, j, inner_sum; + int loopback, i, j, inner_sum, err; memset(&iq_est, 0, sizeof(iq_est)); - b43_switch_channel(dev, 7); + err = b43_lpphy_op_switch_channel(dev, 7); + if (err) { + b43dbg(dev->wl, + "RC calib: Failed to switch to channel 7, error = %d", + err); + } 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) @@ -1881,14 +1898,14 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, { struct b43_phy_lp *lpphy = dev->phy.lp; struct ssb_bus *bus = dev->dev->bus; - static const struct b206x_channel *chandata = NULL; + const struct b206x_channel *chandata = NULL; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; int i, err = 0; - for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) { - if (b2063_chantbl[i].channel == channel) { - chandata = &b2063_chantbl[i]; + for (i = 0; i < ARRAY_SIZE(b2062_chantbl); i++) { + if (b2062_chantbl[i].channel == channel) { + chandata = &b2062_chantbl[i]; break; } } -- cgit v1.2.3 From ed07c4b3af341bad3fa29558f08b166220014ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sun, 16 Aug 2009 18:40:09 +0200 Subject: b43: LP-PHY: Fix a bug in the B2062 channel tune path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I missed the "+16" part of the instruction in the specs. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 4d14102821c..4553e407395 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1950,7 +1950,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4)); tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19); tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1); - b43_radio_write(dev, B2062_S_RFPLL_CTL23, tmp9 >> 8); + b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16); b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF); lpphy_b2062_vco_calib(dev); -- cgit v1.2.3 From 7e4d8529921004014bef21a2031b6c3478339a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sun, 16 Aug 2009 20:08:13 +0200 Subject: b43: LP-PHY: Update B2062 radio init with recent spec changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec for initializing the B2062 radio have changed recently, update the code to match the changes. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 4553e407395..faca56f908e 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -537,10 +537,15 @@ static void lpphy_2062_init(struct b43_wldev *dev) b43_radio_write(dev, B2062_N_TX_CTL3, 0); b43_radio_write(dev, B2062_N_TX_CTL4, 0); b43_radio_write(dev, B2062_N_TX_CTL5, 0); + b43_radio_write(dev, B2062_N_TX_CTL6, 0); b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40); b43_radio_write(dev, B2062_N_PDN_CTL0, 0); b43_radio_write(dev, B2062_N_CALIB_TS, 0x10); b43_radio_write(dev, B2062_N_CALIB_TS, 0); + if (dev->phy.rev > 0) { + b43_radio_write(dev, B2062_S_BG_CTL1, + (b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80); + } if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1); else -- cgit v1.2.3 From 86b2892a22a433e56e39e33bf353adc6cc4eabb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Sun, 16 Aug 2009 20:22:41 +0200 Subject: b43: LP-PHY: Remove BROKEN from B43_PHY_LP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Larry has reported success getting scan data with an LP-PHY device, so it's probably time to release LP-PHY support for testing. Also disable 802.11a support for now, as 802.11a currently causes the driver to panic on startup (NULL pointer dereference). Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 14 +++++++------- drivers/net/wireless/b43/main.c | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 67f564e3722..237b1aadf9b 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -80,16 +80,16 @@ config B43_NPHY SAY N. config B43_PHY_LP - bool "IEEE 802.11g LP-PHY support (BROKEN)" - depends on B43 && EXPERIMENTAL && BROKEN + bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)" + depends on B43 && EXPERIMENTAL ---help--- Support for the LP-PHY. - The LP-PHY is an IEEE 802.11g based PHY built into some notebooks - and embedded devices. - - THIS IS BROKEN AND DOES NOT WORK YET. + The LP-PHY is a low-power PHY built into some notebooks + and embedded devices. It supports 802.11a/g + (802.11a support is optional, and currently disabled). - SAY N. + This is heavily experimental, and probably will not work for you. + Say N unless you want to help debug the driver. # This config option automatically enables b43 LEDS support, # if it's possible. diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 99b41ce6848..c5bece09042 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4514,7 +4514,9 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) have_5ghz_phy = 1; break; case B43_PHYTYPE_LP: //FIXME not always! +#if 0 //FIXME enabling 5GHz causes a NULL pointer dereference have_5ghz_phy = 1; +#endif case B43_PHYTYPE_G: case B43_PHYTYPE_N: have_2ghz_phy = 1; -- cgit v1.2.3 From 3ac64beecd27400d12cc7afb4108eef26c499f6a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Aug 2009 16:16:53 +0200 Subject: mac80211: allow configure_filter callback to sleep Over time, a whole bunch of drivers have come up with their own scheme to delay the configure_filter operation to a workqueue. To be able to simplify things, allow configure_filter to sleep, and add a new prepare_multicast callback that drivers that need the multicast address list implement. This new callback must be atomic, but most drivers either don't care or just calculate a hash which can be done atomically and then uploaded to the hardware non-atomically. A cursory look suggests that at76c50x-usb, ar9170, mwl8k (which is actually very broken now), rt2x00, wl1251, wl1271 and zd1211 should make use of this new capability. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 42 +++++++++++++------- drivers/net/wireless/at76c50x-usb.c | 7 ++-- drivers/net/wireless/ath/ar9170/main.c | 43 +++++++++++--------- drivers/net/wireless/ath/ath5k/base.c | 64 ++++++++++++++++++------------ drivers/net/wireless/ath/ath9k/main.c | 3 +- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43legacy/main.c | 4 +- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 3 +- drivers/net/wireless/libertas_tf/main.c | 37 +++++++++++------ drivers/net/wireless/mac80211_hwsim.c | 4 +- drivers/net/wireless/mwl8k.c | 34 ++++++++++++---- drivers/net/wireless/p54/main.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- drivers/net/wireless/rtl818x/rtl8180_dev.c | 11 ++++- drivers/net/wireless/rtl818x/rtl8187_dev.c | 11 ++++- drivers/net/wireless/wl12xx/wl1251_main.c | 4 +- drivers/net/wireless/wl12xx/wl1271_main.c | 4 +- drivers/net/wireless/zd1211rw/zd_mac.c | 44 +++++++++++++------- 20 files changed, 205 insertions(+), 120 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 5695911bc60..b80f514877d 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1328,16 +1328,39 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev, } } +static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + unsigned int bit_nr, i; + u32 mc_filter[2]; + + mc_filter[1] = mc_filter[0] = 0; + + for (i = 0; i < mc_count; i++) { + if (!mclist) + break; + bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + + bit_nr &= 0x3F; + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + mclist = mclist->next; + } + + return mc_filter[0] | ((u64)(mc_filter[1]) << 32); +} + static void adm8211_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; struct adm8211_priv *priv = dev->priv; - unsigned int bit_nr, new_flags; + unsigned int new_flags; u32 mc_filter[2]; - int i; + + mc_filter[0] = multicast; + mc_filter[1] = multicast >> 32; new_flags = 0; @@ -1346,23 +1369,13 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, priv->nar |= ADM8211_NAR_PR; priv->nar &= ~ADM8211_NAR_MM; mc_filter[1] = mc_filter[0] = ~0; - } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) { + } else if (*total_flags & FIF_ALLMULTI || multicast == ~(0ULL)) { new_flags |= FIF_ALLMULTI; priv->nar &= ~ADM8211_NAR_PR; priv->nar |= ADM8211_NAR_MM; mc_filter[1] = mc_filter[0] = ~0; } else { priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); - mc_filter[1] = mc_filter[0] = 0; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - bit_nr &= 0x3F; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - mclist = mclist->next; - } } ADM8211_IDLE_RX(); @@ -1757,6 +1770,7 @@ static const struct ieee80211_ops adm8211_ops = { .remove_interface = adm8211_remove_interface, .config = adm8211_config, .bss_info_changed = adm8211_bss_info_changed, + .prepare_multicast = adm8211_prepare_multicast, .configure_filter = adm8211_configure_filter, .get_stats = adm8211_get_stats, .get_tx_stats = adm8211_get_tx_stats, diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 7218dbabad3..a6e19545ac6 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1997,15 +1997,14 @@ static void at76_bss_info_changed(struct ieee80211_hw *hw, /* must be atomic */ static void at76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, int mc_count, - struct dev_addr_list *mc_list) + unsigned int *total_flags, u64 multicast) { struct at76_priv *priv = hw->priv; int flags; at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " - "total_flags=0x%08x mc_count=%d", - __func__, changed_flags, *total_flags, mc_count); + "total_flags=0x%08x", + __func__, changed_flags, *total_flags); flags = changed_flags & AT76_SUPPORTED_FILTERS; *total_flags = AT76_SUPPORTED_FILTERS; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index ea8c9419336..6a9462e4fd8 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2100,10 +2100,29 @@ unlock: mutex_unlock(&ar->mutex); } +static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, + struct dev_addr_list *mclist) +{ + u64 mchash; + int i; + + /* always get broadcast frames */ + mchash = 1ULL << (0xff >> 2); + + for (i = 0; i < mc_count; i++) { + if (WARN_ON(!mclist)) + break; + mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); + mclist = mclist->next; + } + + return mchash; +} + static void ar9170_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { struct ar9170 *ar = hw->priv; @@ -2116,24 +2135,11 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, * then checking the error flags, later. */ - if (changed_flags & FIF_ALLMULTI) { - if (*new_flags & FIF_ALLMULTI) { - ar->want_mc_hash = ~0ULL; - } else { - u64 mchash; - int i; - - /* always get broadcast frames */ - mchash = 1ULL << (0xff >> 2); + if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) + multicast = ~0ULL; - for (i = 0; i < mc_count; i++) { - if (WARN_ON(!mclist)) - break; - mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); - mclist = mclist->next; - } - ar->want_mc_hash = mchash; - } + if (multicast != ar->want_mc_hash) { + ar->want_mc_hash = multicast; set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed); } @@ -2543,6 +2549,7 @@ static const struct ieee80211_ops ar9170_ops = { .add_interface = ar9170_op_add_interface, .remove_interface = ar9170_op_remove_interface, .config = ar9170_op_config, + .prepare_multicast = ar9170_op_prepare_multicast, .configure_filter = ar9170_op_configure_filter, .conf_tx = ar9170_conf_tx, .bss_info_changed = ar9170_op_bss_info_changed, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2b3cf39dd4b..3951b5b1342 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -229,10 +229,12 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); +static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mc_list); static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist); + u64 multicast); static int ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -260,6 +262,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { .add_interface = ath5k_add_interface, .remove_interface = ath5k_remove_interface, .config = ath5k_config, + .prepare_multicast = ath5k_prepare_multicast, .configure_filter = ath5k_configure_filter, .set_key = ath5k_set_key, .get_stats = ath5k_get_stats, @@ -2853,6 +2856,37 @@ unlock: return ret; } +static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + u32 mfilt[2], val; + int i; + u8 pos; + + mfilt[0] = 0; + mfilt[1] = 1; + + for (i = 0; i < mc_count; i++) { + if (!mclist) + break; + /* calculate XOR of eight 6-bit values */ + val = get_unaligned_le32(mclist->dmi_addr + 0); + pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + val = get_unaligned_le32(mclist->dmi_addr + 3); + pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + pos &= 0x3f; + mfilt[pos / 32] |= (1 << (pos % 32)); + /* XXX: we might be able to just do this instead, + * but not sure, needs testing, if we do use this we'd + * neet to inform below to not reset the mcast */ + /* ath5k_hw_set_mcast_filterindex(ah, + * mclist->dmi_addr[5]); */ + mclist = mclist->next; + } + + return ((u64)(mfilt[1]) << 32) | mfilt[0]; +} + #define SUPPORTED_FIF_FLAGS \ FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ @@ -2878,16 +2912,14 @@ unlock: static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; - u32 mfilt[2], val, rfilt; - u8 pos; - int i; + u32 mfilt[2], rfilt; - mfilt[0] = 0; - mfilt[1] = 0; + mfilt[0] = multicast; + mfilt[1] = multicast >> 32; /* Only deal with supported flags */ changed_flags &= SUPPORTED_FIF_FLAGS; @@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, if (*new_flags & FIF_ALLMULTI) { mfilt[0] = ~0; mfilt[1] = ~0; - } else { - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(mclist->dmi_addr + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(mclist->dmi_addr + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); - /* XXX: we might be able to just do this instead, - * but not sure, needs testing, if we do use this we'd - * neet to inform below to not reset the mcast */ - /* ath5k_hw_set_mcast_filterindex(ah, - * mclist->dmi_addr[5]); */ - mclist = mclist->next; - } } /* This is the best we can do */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3e09b9ac165..2f9c149fd48 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2394,8 +2394,7 @@ skip_chan_change: static void ath9k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, - struct dev_mc_list *mclist) + u64 multicast) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c5bece09042..78ddbc7f836 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3679,7 +3679,7 @@ out_unlock: static void b43_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *fflags, - int mc_count, struct dev_addr_list *mc_list) + u64 multicast) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index b1435594921..b166a6f9f05 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2836,9 +2836,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, - unsigned int *fflags, - int mc_count, - struct dev_addr_list *mc_list) + unsigned int *fflags,u64 multicast) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c0efa6623c0..f1f6dabd8fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1514,7 +1514,7 @@ EXPORT_SYMBOL(iwl_irq_handle_error); void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list) + u64 multicast) { struct iwl_priv *priv = hw->priv; __le32 *filter_flags = &priv->staging_rxon.filter_flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ca025a34da..62d90364b61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -282,8 +282,7 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, void iwl_irq_handle_error(struct iwl_priv *priv); void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list); + unsigned int *total_flags, u64 multicast); int iwl_hw_nic_init(struct iwl_priv *priv); int iwl_setup_mac(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 4872345a2f6..019431d2f8a 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -366,15 +366,35 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) return 0; } +static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + struct lbtf_private *priv = hw->priv; + int i; + + if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) + return mc_count; + + priv->nr_of_multicastmacaddr = mc_count; + for (i = 0; i < mc_count; i++) { + if (!mclist) + break; + memcpy(&priv->multicastlist[i], mclist->da_addr, + ETH_ALEN); + mclist = mclist->next; + } + + return mc_count; +} + #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) static void lbtf_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { struct lbtf_private *priv = hw->priv; int old_mac_control = priv->mac_control; - int i; changed_flags &= SUPPORTED_FIF_FLAGS; *new_flags &= SUPPORTED_FIF_FLAGS; @@ -386,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw, else priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; if (*new_flags & (FIF_ALLMULTI) || - mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { + multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) { priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; - } else if (mc_count) { + } else if (multicast) { priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; - priv->nr_of_multicastmacaddr = mc_count; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - memcpy(&priv->multicastlist[i], mclist->da_addr, - ETH_ALEN); - mclist = mclist->next; - } lbtf_cmd_set_mac_multicast_addr(priv); } else { priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | @@ -461,6 +473,7 @@ static const struct ieee80211_ops lbtf_ops = { .add_interface = lbtf_op_add_interface, .remove_interface = lbtf_op_remove_interface, .config = lbtf_op_config, + .prepare_multicast = lbtf_op_prepare_multicast, .configure_filter = lbtf_op_configure_filter, .bss_info_changed = lbtf_op_bss_info_changed, }; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 930f5c7da4a..6f6cd43592c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -582,9 +582,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) + unsigned int *total_flags,u64 multicast) { struct mac80211_hwsim_data *data = hw->priv; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8a6d3afe412..f84387083e7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3251,31 +3251,50 @@ mwl8k_configure_filter_exit: return rc; } +static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + struct mwl8k_configure_filter_worker *worker; + + worker = kzalloc(sizeof(*worker), GFP_ATOMIC); + + if (!worker) + return 0; + + /* + * XXX: This is _HORRIBLY_ broken!! + * + * No locking, the mclist pointer might be invalid as soon as this + * function returns, something in the list might be invalidated + * once we get to the worker, etc... + */ + worker->mc_count = mc_count; + worker->mclist = mclist; + + return (u64)worker; +} + static void mwl8k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mclist) + u64 multicast) { - struct mwl8k_configure_filter_worker *worker; + struct mwl8k_configure_filter_worker *worker = (void *)multicast; struct mwl8k_priv *priv = hw->priv; /* Clear unsupported feature flags */ *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; - if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS) && !mc_count) + if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS)) return; - worker = kzalloc(sizeof(*worker), GFP_ATOMIC); if (worker == NULL) return; worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; worker->changed_flags = changed_flags; worker->total_flags = total_flags; - worker->mc_count = mc_count; - worker->mclist = mclist; mwl8k_queue_work(hw, &worker->header, priv->config_wq, mwl8k_configure_filter_wt); @@ -3441,6 +3460,7 @@ static const struct ieee80211_ops mwl8k_ops = { .remove_interface = mwl8k_remove_interface, .config = mwl8k_config, .bss_info_changed = mwl8k_bss_info_changed, + .prepare_multicast = mwl8k_prepare_multicast, .configure_filter = mwl8k_configure_filter, .set_rts_threshold = mwl8k_set_rts_threshold, .conf_tx = mwl8k_conf_tx, diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 77203e346cd..4d486bf9f72 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -302,7 +302,7 @@ out: static void p54_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { struct p54_common *priv = dev->priv; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 99e89596cef..39d7d9baafd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -978,7 +978,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list); + u64 multicast); int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); #ifdef CONFIG_RT2X00_LIB_CRYPTO diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index cb7b6d45933..602f1269971 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -379,7 +379,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_config); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list) + u64 multicast) { struct rt2x00_dev *rt2x00dev = hw->priv; diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 09f46abc730..16429c49139 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -728,10 +728,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, priv->rf->conf_erp(dev, info); } +static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, + struct dev_addr_list *mc_list) +{ + return mc_count; +} + static void rtl8180_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mclist) + u64 multicast) { struct rtl8180_priv *priv = dev->priv; @@ -741,7 +747,7 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, priv->rx_conf ^= RTL818X_RX_CONF_CTRL; if (changed_flags & FIF_OTHER_BSS) priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - if (*total_flags & FIF_ALLMULTI || mc_count > 0) + if (*total_flags & FIF_ALLMULTI || multicast > 0) priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; else priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; @@ -768,6 +774,7 @@ static const struct ieee80211_ops rtl8180_ops = { .remove_interface = rtl8180_remove_interface, .config = rtl8180_config, .bss_info_changed = rtl8180_bss_info_changed, + .prepare_multicast = rtl8180_prepare_multicast, .configure_filter = rtl8180_configure_filter, }; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 53f57dc5222..90f38357393 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1192,10 +1192,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, info->use_short_preamble); } +static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, + int mc_count, struct dev_addr_list *mc_list) +{ + return mc_count; +} + static void rtl8187_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mclist) + u64 multicast) { struct rtl8187_priv *priv = dev->priv; @@ -1205,7 +1211,7 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, priv->rx_conf ^= RTL818X_RX_CONF_CTRL; if (changed_flags & FIF_OTHER_BSS) priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - if (*total_flags & FIF_ALLMULTI || mc_count > 0) + if (*total_flags & FIF_ALLMULTI || multicast > 0) priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; else priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; @@ -1268,6 +1274,7 @@ static const struct ieee80211_ops rtl8187_ops = { .remove_interface = rtl8187_remove_interface, .config = rtl8187_config, .bss_info_changed = rtl8187_bss_info_changed, + .prepare_multicast = rtl8187_prepare_multicast, .configure_filter = rtl8187_configure_filter, .conf_tx = rtl8187_conf_tx }; diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 7148934e464..5809ef5b18f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -652,9 +652,7 @@ out: static void wl1251_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, - unsigned int *total, - int mc_count, - struct dev_addr_list *mc_list) + unsigned int *total,u64 multicast) { struct wl1251 *wl = hw->priv; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4102d590b79..754be817930 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -793,9 +793,7 @@ out: static void wl1271_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, - unsigned int *total, - int mc_count, - struct dev_addr_list *mc_list) + unsigned int *total,u64 multicast) { struct wl1271 *wl = hw->priv; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 55b7fbdc85d..6d666359a42 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -796,18 +796,40 @@ static void set_rx_filter_handler(struct work_struct *work) dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); } +static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + struct zd_mac *mac = zd_hw_mac(hw); + struct zd_mc_hash hash; + int i; + + zd_mc_clear(&hash); + + for (i = 0; i < mc_count; i++) { + if (!mclist) + break; + dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr); + zd_mc_add_addr(&hash, mclist->dmi_addr); + mclist = mclist->next; + } + + return hash.low | ((u64)hash.high << 32); +} + #define SUPPORTED_FIF_FLAGS \ (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) static void zd_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) + u64 multicast) { - struct zd_mc_hash hash; + struct zd_mc_hash hash = { + .low = multicast, + .high = multicast >> 32, + }; struct zd_mac *mac = zd_hw_mac(hw); unsigned long flags; - int i; /* Only deal with supported flags */ changed_flags &= SUPPORTED_FIF_FLAGS; @@ -819,25 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, if (!changed_flags) return; - if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) { + if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) zd_mc_add_all(&hash); - } else { - zd_mc_clear(&hash); - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", - mclist->dmi_addr); - zd_mc_add_addr(&hash, mclist->dmi_addr); - mclist = mclist->next; - } - } spin_lock_irqsave(&mac->lock, flags); mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); mac->multicast_hash = hash; spin_unlock_irqrestore(&mac->lock, flags); + + /* XXX: these can be called here now, can sleep now! */ queue_work(zd_workqueue, &mac->set_multicast_hash_work); if (changed_flags & FIF_CONTROL) @@ -940,6 +953,7 @@ static const struct ieee80211_ops zd_ops = { .add_interface = zd_op_add_interface, .remove_interface = zd_op_remove_interface, .config = zd_op_config, + .prepare_multicast = zd_op_prepare_multicast, .configure_filter = zd_op_configure_filter, .bss_info_changed = zd_op_bss_info_changed, .get_tsf = zd_op_get_tsf, -- cgit v1.2.3 From f424afa17899408cbd267a4c4534ca6fc9d8f71c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Aug 2009 16:18:07 +0200 Subject: mac80211: remove deprecated API All but two drivers have now stopped using the two deprecated members radio_enabled and beacon_int, so it's about time to remove them for good. Signed-off-by: Johannes Berg Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 5 ++--- drivers/net/wireless/mwl8k.c | 7 ------- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index a6e19545ac6..8e1a55dec35 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1950,9 +1950,8 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed) { struct at76_priv *priv = hw->priv; - at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d", - __func__, hw->conf.channel->hw_value, - hw->conf.radio_enabled); + at76_dbg(DBG_MAC80211, "%s(): channel %d", + __func__, hw->conf.channel->hw_value); at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:"); mutex_lock(&priv->mtx); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f84387083e7..c32e93c8c41 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3031,13 +3031,6 @@ static int mwl8k_config_wt(struct work_struct *wt) struct mwl8k_priv *priv = hw->priv; int rc = 0; - if (!conf->radio_enabled) { - mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); - priv->current_channel = NULL; - rc = 0; - goto mwl8k_config_exit; - } - if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { rc = -EINVAL; goto mwl8k_config_exit; -- cgit v1.2.3 From 1de6f73c34fb9a74454a5b519cefd635b5e8ceb6 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 17 Aug 2009 11:18:14 -0400 Subject: wl1251: correct definitions for 0th bit defines ACX_SLV_SOFT_RESET_BIT and ACX_REG_EEPROM_START_BIT are both defined as "1" in the vendor driver code, but they were defined to be BIT(1) ("2") here. The SOFT_RESET typo ensures that wl1251_boot_soft_reset() doesn't; as a result the device hangs when trying to reprogram the PLL registers while running. Signed-off-by: Bob Copeland Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index bdd561001dc..06e1bd94a73 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h @@ -245,8 +245,8 @@ enum wl12xx_acx_int_reg { ACX_REG_TABLE_LEN }; -#define ACX_SLV_SOFT_RESET_BIT BIT(1) -#define ACX_REG_EEPROM_START_BIT BIT(1) +#define ACX_SLV_SOFT_RESET_BIT BIT(0) +#define ACX_REG_EEPROM_START_BIT BIT(0) /* Command/Information Mailbox Pointers */ -- cgit v1.2.3 From 12d4bba0fd7ac50ca20d9ac1247a0de851850bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 20:29:47 +0200 Subject: b43: LP-PHY: Fix reading old mode in the set TX power control routine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the mode the hardware is in, not the mode we used the last time. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index faca56f908e..ca52fd5f38c 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1085,9 +1085,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, struct b43_phy_lp *lpphy = dev->phy.lp; enum b43_lpphy_txpctl_mode oldmode; - oldmode = lpphy->txpctl_mode; lpphy_read_tx_pctl_mode_from_hardware(dev); - if (lpphy->txpctl_mode == mode) + oldmode = lpphy->txpctl_mode; + if (oldmode == mode) return; lpphy->txpctl_mode = mode; -- cgit v1.2.3 From 5f1c07d924d3e670044911487aca057bb39b4e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Fri, 14 Aug 2009 21:19:58 +0200 Subject: b43: LP-PHY: Fix setting TX power control mode during RC calibration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call set_tx_power_control with a LPPHY_TXPCTL rather than an LPPHY_TX_PWR_CTL_CMD_MODE. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index ca52fd5f38c..94023838568 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1159,7 +1159,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) lpphy_read_tx_pctl_mode_from_hardware(dev); old_txpctl = lpphy->txpctl_mode; - lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); + lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); lpphy_disable_crs(dev); loopback = lpphy_loopback(dev); if (loopback == -1) -- cgit v1.2.3 From 73077c85458739169cdaf893a375b8bb3939d35a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 17 Aug 2009 18:53:24 +0200 Subject: rt2x00: Fix RFKILL polling The rfkill_poll callback function in the drivers check a bit to see if the RFKILL key has been pressed. However when the bit is set it means the radio is active and the device can be used. The wiphy_rfkill_set_hw_state() function expects the inversed, so '1' must be send when the radio must be disabled. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 602f1269971..3011aea4fea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -704,8 +704,8 @@ EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; - bool blocked = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + bool active = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); + wiphy_rfkill_set_hw_state(hw->wiphy, !active); } EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); -- cgit v1.2.3 From 1738c9e42a9bb3705a3b03dde854f3db269e7bdd Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 17 Aug 2009 18:53:57 +0200 Subject: rt2x00: Fix for rt2800usb for SHARED_KEY_TABLE initializations Fixed comments about SHARED_KEY_TABLE_BASE and SHARED_KEY_MODE_BASE. Fixed initialization loop for SHARED_KEY_MODE_ENTRY. Based on a patch for rt2800pci from Benoit. Signed-off-by: Benoit PAPILLAULT Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++++---- drivers/net/wireless/rt2x00/rt2800usb.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 3856f06fdca..c82474ebba3 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1463,6 +1463,10 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) /* * ASIC will keep garbage value after boot, clear encryption keys. */ + for (i = 0; i < 4; i++) + rt2x00usb_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); + for (i = 0; i < 256; i++) { u32 wcid[2] = { 0xffffffff, 0x00ffffff }; rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), @@ -1472,10 +1476,6 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); } - for (i = 0; i < 16; i++) - rt2x00usb_register_write(rt2x00dev, - SHARED_KEY_MODE_ENTRY(i), 0); - /* * Clear all beacons * For the Beacon base registers we only need to clear diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 2d9dc378336..a79a6d90eea 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -1300,8 +1300,8 @@ * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry - * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry - * SHARED_KEY_MODE_BASE: 4-byte * 16-entry + * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry + * SHARED_KEY_MODE_BASE: 4 bits * 32-entry */ #define MAC_WCID_BASE 0x1800 #define PAIRWISE_KEY_TABLE_BASE 0x4000 -- cgit v1.2.3 From 05a32730f16e7b91e9fd2d11f26db152e5c9a68d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 17 Aug 2009 18:54:47 +0200 Subject: rt2x00: Add new RF chip defines Add new defines for RF chipsets which can be found by the driver. We don't have to check for these chips specifically yet, but it is better to have the defines in now. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index a79a6d90eea..4d9991c9a51 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -36,6 +36,9 @@ * RF2750 2.4G/5G 1T2R * RF3020 2.4G 1T1R * RF2020 2.4G B/G + * RF3021 2.4G 1T2R + * RF3022 2.4G 2T2R + * RF3052 2.4G 2T2R */ #define RF2820 0x0001 #define RF2850 0x0002 @@ -43,6 +46,9 @@ #define RF2750 0x0004 #define RF3020 0x0005 #define RF2020 0x0006 +#define RF3021 0x0007 +#define RF3022 0x0008 +#define RF3052 0x0009 /* * RT2870 version -- cgit v1.2.3 From 0fefe0fda4376eff97be965a41714da38fe4a36d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 17 Aug 2009 18:54:50 +0200 Subject: rt2x00: Set SKBDESC_L2_PADDED in RX path When the RX descriptor indicates the frame was L2 padded, the SKBDESC_L2_PADDED flag should be set to make sure the L2 padding is removed before it is send to mac80211. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c82474ebba3..6de2edab51e 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -2163,8 +2163,10 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; - if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) + if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) { rxdesc->dev_flags |= RXDONE_L2PAD; + skbdesc->flags |= SKBDESC_L2_PADDED; + } if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) rxdesc->flags |= RX_FLAG_SHORT_GI; -- cgit v1.2.3 From 534aff0288f49a2366b7e6fbb67ff035dea814d3 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 17 Aug 2009 18:55:15 +0200 Subject: rt2x00: wireless CLI ID and packet ID must not be 0 In the TX descriptor the Packet ID must not be 0, so add 1 to the ID. The wireless CLI ID is not allowed to be 0 either, but also must be initialized with the wcid value rather then keyid. Based on a patch for rt2800pci from Benoit Signed-off-by: Benoit PAPILLAULT Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6de2edab51e..3633e5878ee 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1995,11 +1995,11 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - txdesc->key_idx : 0xff); + (skbdesc->entry->entry_idx + 1) : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len - txdesc->l2pad); rt2x00_set_field32(&word, TXWI_W1_PACKETID, - skbdesc->entry->entry_idx); + skbdesc->entry->queue->qid + 1); rt2x00_desc_write(txwi, 1, word); /* -- cgit v1.2.3 From cd80b684a08655e7dcc7a1c96d4b7e7ffa753017 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 17 Aug 2009 18:55:40 +0200 Subject: rt2x00: Fix MCS register intialization According to the original Ralink driver, LG_FBK_CFG0_OFDMMCS2FBK should be initialized to 9 rather then 3. Based on a patch for rt2800pci from Benoit Signed-off-by: Benoit PAPILLAULT Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 3633e5878ee..45e02f16d75 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1520,7 +1520,7 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 3); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); -- cgit v1.2.3 From 92ed48e5230e8f5906dda0cc31715b3b7e3fe303 Mon Sep 17 00:00:00 2001 From: Benoit PAPILLAULT Date: Mon, 17 Aug 2009 18:56:10 +0200 Subject: rt2x00: Add support for retry rates rt2800pci can handle different retry rates, it will always step 1 rate down after a failed transmission so creating the retry rate list for mac80211 is quite simple. Signed-off-by: Benoit PAPILLAULT Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 22 +++++++++++++++++----- drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b6676c6722f..9ab70e435b5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -220,7 +220,8 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - u8 rate_idx, rate_flags; + u8 rate_idx, rate_flags, retry_rates; + unsigned int i; /* * Unmap the skb. @@ -259,16 +260,27 @@ void rt2x00lib_txdone(struct queue_entry *entry, rate_idx = skbdesc->tx_rate_idx; rate_flags = skbdesc->tx_rate_flags; + retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ? + (txdesc->retry + 1) : 1; /* * Initialize TX status */ memset(&tx_info->status, 0, sizeof(tx_info->status)); tx_info->status.ack_signal = 0; - tx_info->status.rates[0].idx = rate_idx; - tx_info->status.rates[0].flags = rate_flags; - tx_info->status.rates[0].count = txdesc->retry + 1; - tx_info->status.rates[1].idx = -1; /* terminate */ + + /* + * Frame was send with retries, hardware tried + * different rates to send out the frame, at each + * retry it lowered the rate 1 step. + */ + for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { + tx_info->status.rates[i].idx = rate_idx - i; + tx_info->status.rates[i].flags = rate_flags; + tx_info->status.rates[i].count = 1; + } + if (i < (IEEE80211_TX_MAX_RATES -1)) + tx_info->status.rates[i].idx = -1; /* terminate */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (test_bit(TXDONE_SUCCESS, &txdesc->flags) || diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 47d175a1379..a5591fb2b19 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -214,6 +214,7 @@ struct rxdone_entry_desc { * * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. * @TXDONE_SUCCESS: Frame was successfully send + * @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. * @TXDONE_FAILURE: Frame was not successfully send * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the * frame transmission failed due to excessive retries. @@ -221,6 +222,7 @@ struct rxdone_entry_desc { enum txdone_entry_desc_flags { TXDONE_UNKNOWN, TXDONE_SUCCESS, + TXDONE_FALLBACK, TXDONE_FAILURE, TXDONE_EXCESSIVE_RETRY, }; -- cgit v1.2.3 From bcd64e0c20eafe6a3976c248833d5d8bcccdf0d9 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 17 Aug 2009 23:33:56 -0400 Subject: wl1251: halt the embedded CPU before loading firmware After initial power-up, the embedded cpu is usually halted. However, if we down the interface and only do a soft reset before bringing the interface back up, it will still be running and the firmware loading code will bail out. This change halts the CPU before loading the firmware, enabling a second call to wl1251_boot() to succeed without a hard reset. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_boot.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 592c3b5cc8f..452d748e42c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c @@ -465,6 +465,9 @@ int wl1251_boot(struct wl1251 *wl) int ret = 0, minor_minor_e2_ver; u32 tmp, boot_data; + /* halt embedded ARM CPU while loading firmware */ + wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT); + ret = wl1251_boot_soft_reset(wl); if (ret < 0) goto out; -- cgit v1.2.3 From 4c48381786159ba3f3d8a33d967aeb049341a220 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 18 Aug 2009 10:51:52 +0530 Subject: ath9k: Fix TX poll cancelling In ath9k_stop(), tx_complete_work was being cancelled twice. This patch fixes it. Also, locking sc->mutex should be done at the beginning. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2f9c149fd48..fddda206def 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2105,6 +2105,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + mutex_lock(&sc->mutex); + aphy->state = ATH_WIPHY_INACTIVE; cancel_delayed_work_sync(&sc->ath_led_blink_work); @@ -2117,13 +2119,10 @@ static void ath9k_stop(struct ieee80211_hw *hw) if (sc->sc_flags & SC_OP_INVALID) { DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); + mutex_unlock(&sc->mutex); return; } - mutex_lock(&sc->mutex); - - cancel_delayed_work_sync(&sc->tx_complete_work); - if (ath9k_wiphy_started(sc)) { mutex_unlock(&sc->mutex); return; /* another wiphy still in use */ -- cgit v1.2.3 From 608b88cb34b0e70a538ee1fc334cc833ef691836 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 17 Aug 2009 18:07:23 -0700 Subject: ath: move regulatory info into shared common structure This moves the shared regulatory structure into the common structure. We will use this ongoing for common data. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 2 +- drivers/net/wireless/ath/ar9170/main.c | 14 ++++---- drivers/net/wireless/ath/ath.h | 18 ++++++++++ drivers/net/wireless/ath/ath5k/ath5k.h | 3 -- drivers/net/wireless/ath/ath5k/base.c | 14 ++++---- drivers/net/wireless/ath/ath5k/base.h | 13 +++++++ drivers/net/wireless/ath/ath5k/phy.c | 3 +- drivers/net/wireless/ath/ath9k/ath9k.h | 10 ++++++ drivers/net/wireless/ath/ath9k/eeprom_4k.c | 8 +++-- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 16 ++++----- drivers/net/wireless/ath/ath9k/eeprom_def.c | 14 ++++---- drivers/net/wireless/ath/ath9k/hw.c | 53 ++++++++++++++++------------ drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/main.c | 6 ++-- drivers/net/wireless/ath/regd.h | 20 ++--------- 15 files changed, 116 insertions(+), 79 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index e6c3ee3e058..95f8256c202 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -157,6 +157,7 @@ struct ar9170_sta_tid { struct ar9170 { struct ieee80211_hw *hw; + struct ath_common common; struct mutex mutex; enum ar9170_device_state state; unsigned long bad_hw_nagger; @@ -222,7 +223,6 @@ struct ar9170 { /* EEPROM */ struct ar9170_eeprom eeprom; - struct ath_regulatory regulatory; /* tx queues - as seen by hw - */ struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 6a9462e4fd8..d30f33d4d41 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2641,6 +2641,7 @@ static int ar9170_read_eeprom(struct ar9170 *ar) { #define RW 8 /* number of words to read at once */ #define RB (sizeof(u32) * RW) + struct ath_regulatory *regulatory = &ar->common.regulatory; u8 *eeprom = (void *)&ar->eeprom; u8 *addr = ar->eeprom.mac_address; __le32 offsets[RW]; @@ -2707,8 +2708,8 @@ static int ar9170_read_eeprom(struct ar9170 *ar) else ar->hw->channel_change_time = 80 * 1000; - ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); - ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); + regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); + regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); /* second part of wiphy init */ SET_IEEE80211_PERM_ADDR(ar->hw, addr); @@ -2722,11 +2723,12 @@ static int ar9170_reg_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ar9170 *ar = hw->priv; - return ath_reg_notifier_apply(wiphy, request, &ar->regulatory); + return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); } int ar9170_register(struct ar9170 *ar, struct device *pdev) { + struct ath_regulatory *regulatory = &ar->common.regulatory; int err; /* try to read EEPROM, init MAC addr */ @@ -2734,7 +2736,7 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) if (err) goto err_out; - err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, + err = ath_regd_init(regulatory, ar->hw->wiphy, ar9170_reg_notifier); if (err) goto err_out; @@ -2743,8 +2745,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) if (err) goto err_out; - if (!ath_is_world_regd(&ar->regulatory)) - regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); + if (!ath_is_world_regd(regulatory)) + regulatory_hint(ar->hw->wiphy, regulatory->alpha2); err = ar9170_init_leds(ar); if (err) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index e284cd3ac6d..a63e90cbf9e 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -19,8 +19,26 @@ #include +struct reg_dmn_pair_mapping { + u16 regDmnEnum; + u16 reg_5ghz_ctl; + u16 reg_2ghz_ctl; +}; + +struct ath_regulatory { + char alpha2[2]; + u16 country_code; + u16 max_power_level; + u32 tp_scale; + u16 current_rd; + u16 current_rd_ext; + int16_t power_limit; + struct reg_dmn_pair_mapping *regpair; +}; + struct ath_common { u16 cachelsz; + struct ath_regulatory regulatory; }; struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index c09402eea7f..862762cea54 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -27,8 +27,6 @@ #include #include -#include "../regd.h" - /* RX/TX descriptor hw structs * TODO: Driver part should only see sw structs */ #include "desc.h" @@ -1077,7 +1075,6 @@ struct ath5k_hw { int ah_gpio_npins; - struct ath_regulatory ah_regulatory; struct ath5k_capabilities ah_capabilities; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3951b5b1342..5056410d788 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -718,9 +718,9 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ath5k_softc *sc = hw->priv; - struct ath_regulatory *reg = &sc->ah->ah_regulatory; + struct ath_regulatory *regulatory = &sc->common.regulatory; - return ath_reg_notifier_apply(wiphy, request, reg); + return ath_reg_notifier_apply(wiphy, request, regulatory); } static int @@ -728,6 +728,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) { struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; + struct ath_regulatory *regulatory = &sc->common.regulatory; u8 mac[ETH_ALEN] = {}; int ret; @@ -817,9 +818,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) memset(sc->bssidmask, 0xff, ETH_ALEN); ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); - ah->ah_regulatory.current_rd = - ah->ah_capabilities.cap_eeprom.ee_regdomain; - ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); + regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; + ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); if (ret) { ATH5K_ERR(sc, "can't initialize regulatory system\n"); goto err_queues; @@ -831,8 +831,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) goto err_queues; } - if (!ath_is_world_regd(&sc->ah->ah_regulatory)) - regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); + if (!ath_is_world_regd(regulatory)) + regulatory_hint(hw->wiphy, regulatory->alpha2); ath5k_init_leds(sc); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 25a72a85aaa..a28c42f32c9 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -50,6 +50,8 @@ #include "ath5k.h" #include "debug.h" + +#include "../regd.h" #include "../ath.h" #define ATH_RXBUF 40 /* number of RX buffers */ @@ -200,4 +202,15 @@ struct ath5k_softc { #define ath5k_hw_hasveol(_ah) \ (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) +static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) +{ + return &ah->ah_sc->common; +} + +static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) +{ + return &(ath5k_hw_common(ah)->regulatory); + +} + #endif diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 298fcf01522..1a039f2bd73 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2198,6 +2198,7 @@ static void ath5k_get_max_ctl_power(struct ath5k_hw *ah, struct ieee80211_channel *channel) { + struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_edge_power *rep = ee->ee_ctl_pwr; u8 *ctl_val = ee->ee_ctl; @@ -2208,7 +2209,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, u8 ctl_idx = 0xFF; u32 target = channel->center_freq; - ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band); + ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band); switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2c9f6628a8e..0e444a62904 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -631,6 +631,16 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); +static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) +{ + return &ah->ah_sc->common; +} + +static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) +{ + return &(ath9k_hw_common(ah)->regulatory); +} + static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) { sc->bus_ops->read_cachesize(sc, csz); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index d34dd23e806..b8eca7be5f3 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -508,6 +508,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); int i; int16_t twiceLargestAntenna; u16 twiceMinEdgePower; @@ -541,9 +542,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, twiceLargestAntenna, 0); maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { + if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { maxRegAllowedPower -= - (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); + (tpScaleReductionTable[(regulatory->tp_scale)] * 2); } scaledPower = min(powerLimit, maxRegAllowedPower); @@ -707,6 +708,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, u8 twiceMaxRegulatoryPower, u8 powerLimit) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; struct modal_eep_4k_header *pModal = &pEepData->modalHeader; int16_t ratesArray[Ar5416RateSize]; @@ -744,7 +746,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, else if (IS_CHAN_HT20(chan)) i = rateHt20_0; - ah->regulatory.max_power_level = ratesArray[i]; + regulatory->max_power_level = ratesArray[i]; if (AR_SREV_9280_10_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 959097927ee..c20c21a79b2 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -599,7 +599,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, { #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 - + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; static const u16 tpScaleReductionTable[5] = { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; @@ -632,9 +632,9 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, twiceLargestAntenna, 0); maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) + if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) maxRegAllowedPower -= - (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); + (tpScaleReductionTable[(regulatory->tp_scale)] * 2); scaledPower = min(powerLimit, maxRegAllowedPower); @@ -831,7 +831,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, { #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 - + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; int16_t ratesArray[Ar5416RateSize]; @@ -949,20 +949,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, i = rate6mb; if (AR_SREV_9280_10_OR_LATER(ah)) - ah->regulatory.max_power_level = + regulatory->max_power_level = ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; else - ah->regulatory.max_power_level = ratesArray[i]; + regulatory->max_power_level = ratesArray[i]; switch (ar5416_get_ntxchains(ah->txchainmask)) { case 1: break; case 2: - ah->regulatory.max_power_level += + regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; break; case 3: - ah->regulatory.max_power_level += + regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; break; default: diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 5211ad94c8f..ae7fb5dcb26 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -904,6 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; static const u16 tpScaleReductionTable[5] = @@ -953,9 +954,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { + if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { maxRegAllowedPower -= - (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); + (tpScaleReductionTable[(regulatory->tp_scale)] * 2); } scaledPower = min(powerLimit, maxRegAllowedPower); @@ -1163,6 +1164,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, u8 powerLimit) { #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; struct modal_eep_header *pModal = &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); @@ -1292,19 +1294,19 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, i = rateHt20_0; if (AR_SREV_9280_10_OR_LATER(ah)) - ah->regulatory.max_power_level = + regulatory->max_power_level = ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; else - ah->regulatory.max_power_level = ratesArray[i]; + regulatory->max_power_level = ratesArray[i]; switch(ar5416_get_ntxchains(ah->txchainmask)) { case 1: break; case 2: - ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; + regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; break; case 3: - ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; + regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; break; default: DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index df62113d89d..4f3d5ea3481 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -439,8 +439,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah) static void ath9k_hw_init_defaults(struct ath_hw *ah) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + + regulatory->country_code = CTRY_DEFAULT; + regulatory->power_limit = MAX_RATE_POWER; + regulatory->tp_scale = ATH9K_TP_SCALE_MAX; + ah->hw_version.magic = AR5416_MAGIC; - ah->regulatory.country_code = CTRY_DEFAULT; ah->hw_version.subvendorid = 0; ah->ah_flags = 0; @@ -449,8 +454,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) if (!AR_SREV_9100(ah)) ah->ah_flags = AH_USE_EEPROM; - ah->regulatory.power_limit = MAX_RATE_POWER; - ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; ah->atim_window = 0; ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; ah->beacon_interval = 100; @@ -1368,6 +1371,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); int i, regWrites = 0; struct ieee80211_channel *channel = chan->chan; u32 modesIndex, freqIndex; @@ -1474,11 +1478,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, ath9k_olc_init(ah); ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(&ah->regulatory, chan), + ath9k_regd_get_ctl(regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)); + (u32) regulatory->power_limit)); if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { DPRINTF(ah->ah_sc, ATH_DBG_FATAL, @@ -1796,6 +1800,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ieee80211_channel *channel = chan->chan; u32 synthDelay, qnum; @@ -1828,11 +1833,11 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, } ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(&ah->regulatory, chan), + ath9k_regd_get_ctl(regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)); + (u32) regulatory->power_limit)); synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; if (IS_CHAN_B(chan)) @@ -3480,27 +3485,29 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, void ath9k_hw_fill_cap_info(struct ath_hw *ah) { struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + u16 capField = 0, eeval; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); - ah->regulatory.current_rd = eeval; + regulatory->current_rd = eeval; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); if (AR_SREV_9285_10_OR_LATER(ah)) eeval |= AR9285_RDEXT_DEFAULT; - ah->regulatory.current_rd_ext = eeval; + regulatory->current_rd_ext = eeval; capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); if (ah->opmode != NL80211_IFTYPE_AP && ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { - if (ah->regulatory.current_rd == 0x64 || - ah->regulatory.current_rd == 0x65) - ah->regulatory.current_rd += 5; - else if (ah->regulatory.current_rd == 0x41) - ah->regulatory.current_rd = 0x43; + if (regulatory->current_rd == 0x64 || + regulatory->current_rd == 0x65) + regulatory->current_rd += 5; + else if (regulatory->current_rd == 0x41) + regulatory->current_rd = 0x43; DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "regdomain mapped to 0x%x\n", ah->regulatory.current_rd); + "regdomain mapped to 0x%x\n", regulatory->current_rd); } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); @@ -3635,7 +3642,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { + if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { pCap->reg_cap = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | @@ -3664,6 +3671,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 *result) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); switch (type) { case ATH9K_CAP_CIPHER: switch (capability) { @@ -3712,13 +3720,13 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, case 0: return 0; case 1: - *result = ah->regulatory.power_limit; + *result = regulatory->power_limit; return 0; case 2: - *result = ah->regulatory.max_power_level; + *result = regulatory->max_power_level; return 0; case 3: - *result = ah->regulatory.tp_scale; + *result = regulatory->tp_scale; return 0; } return false; @@ -3956,17 +3964,18 @@ bool ath9k_hw_disable(struct ath_hw *ah) void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath9k_channel *chan = ah->curchan; struct ieee80211_channel *channel = chan->chan; - ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); + regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(&ah->regulatory, chan), + ath9k_regd_get_ctl(regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)); + (u32) regulatory->power_limit)); } void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index de31a1595f1..24b30631d93 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -396,7 +396,6 @@ struct ath_hw { struct ath9k_hw_version hw_version; struct ath9k_ops_config config; struct ath9k_hw_capabilities caps; - struct ath_regulatory regulatory; struct ath9k_channel channels[38]; struct ath9k_channel *curchan; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index fddda206def..de197117fdc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1293,7 +1293,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_regulatory *reg = &sc->sc_ah->regulatory; + struct ath_regulatory *reg = &sc->common.regulatory; return ath_reg_notifier_apply(wiphy, request, reg); } @@ -1586,12 +1586,12 @@ int ath_init_device(u16 devid, struct ath_softc *sc) ath_set_hw_capab(sc, hw); - error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, + error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy, ath9k_reg_notifier); if (error) return error; - reg = &sc->sc_ah->regulatory; + reg = &sc->common.regulatory; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 07291ccb23f..4d3c53674e5 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -18,9 +18,10 @@ #define REGD_H #include - #include +#include "ath.h" + #define NO_CTL 0xff #define SD_NO_CTL 0xE0 #define NO_CTL 0xff @@ -47,29 +48,12 @@ #define CHANNEL_HALF_BW 10 #define CHANNEL_QUARTER_BW 5 -struct reg_dmn_pair_mapping { - u16 regDmnEnum; - u16 reg_5ghz_ctl; - u16 reg_2ghz_ctl; -}; - struct country_code_to_enum_rd { u16 countryCode; u16 regDmnEnum; const char *isoName; }; -struct ath_regulatory { - char alpha2[2]; - u16 country_code; - u16 max_power_level; - u32 tp_scale; - u16 current_rd; - u16 current_rd_ext; - int16_t power_limit; - struct reg_dmn_pair_mapping *regpair; -}; - enum CountryCode { CTRY_ALBANIA = 8, CTRY_ALGERIA = 12, -- cgit v1.2.3 From e5539bcbf64fdb16af73b5c8caff9255307490b5 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 18 Aug 2009 10:50:34 -0400 Subject: wl1271: remove print_mac usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/wl12xx/wl1271_main.o drivers/net/wireless/wl12xx/wl1271_main.c: In function ‘wl1271_op_add_interface’: drivers/net/wireless/wl12xx/wl1271_main.c:611: warning: ‘print_mac’ is deprecated (declared at include/linux/if_ether.h:142) Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 754be817930..d9169b47ac4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -605,11 +605,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct wl1271 *wl = hw->priv; - DECLARE_MAC_BUF(mac); int ret = 0; - wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s", - conf->type, print_mac(mac, conf->mac_addr)); + wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", + conf->type, conf->mac_addr); mutex_lock(&wl->mutex); -- cgit v1.2.3 From 21f8a73f829797eb7ebc12202b4c68e10e751ddb Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 18 Aug 2009 10:25:05 -0700 Subject: ipw2x00: fix sparse warnings This fixes: CHECK drivers/net/wireless/ipw2x00/ipw2100.c drivers/net/wireless/ipw2x00/ipw2100.c:7888:22: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2100.c:188:12: originally declared here drivers/net/wireless/ipw2x00/ipw2100.c:7952:18: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2100.c:188:12: originally declared here drivers/net/wireless/ipw2x00/ipw2100.c:8000:18: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2100.c:188:12: originally declared here drivers/net/wireless/ipw2x00/ipw2100.c:8268:27: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2100.c:8268:27: originally declared here drivers/net/wireless/ipw2x00/ipw2100.c:8268:27: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2100.c:8268:27: originally declared here drivers/net/wireless/ipw2x00/ipw2100.c:8268:27: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2100.c:8268:27: originally declared here CC [M] drivers/net/wireless/ipw2x00/ipw2100.o CHECK drivers/net/wireless/ipw2x00/ipw2200.c drivers/net/wireless/ipw2x00/ipw2200.c:847:13: warning: symbol 'led' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:92:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:891:13: warning: symbol 'led' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:92:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:935:13: warning: symbol 'led' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:92:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:980:13: warning: symbol 'led' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:92:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:1016:13: warning: symbol 'led' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:92:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:1051:13: warning: symbol 'led' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:92:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:1823:13: warning: symbol 'channel' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:86:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min1' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: warning: symbol '_min2' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:4268:19: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:6228:28: warning: symbol 'channel' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:86:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:6369:20: warning: symbol 'channel' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:86:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:6857:12: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:87:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:7964:13: warning: symbol 'channel' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:86:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:8720:12: warning: symbol 'channel' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:86:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:9662:13: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:87:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:9720:13: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:87:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:9826:13: warning: symbol 'mode' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:87:12: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:10318:21: warning: symbol 'remaining_bytes' shadows an earlier one drivers/net/wireless/ipw2x00/ipw2200.c:10184:13: originally declared here drivers/net/wireless/ipw2x00/ipw2200.c:8338:45: warning: cast to restricted __le16 drivers/net/wireless/ipw2x00/ipw2200.c:4414:21: warning: incorrect type in assignment (different base types) drivers/net/wireless/ipw2x00/ipw2200.c:4414:21: expected restricted __le16 [usertype] size drivers/net/wireless/ipw2x00/ipw2200.c:4414:21: got unsigned short [unsigned] [usertype] drivers/net/wireless/ipw2x00/ipw2200.c:6105:33: warning: incorrect type in initializer (different base types) drivers/net/wireless/ipw2x00/ipw2200.c:6105:33: expected restricted __le16 [usertype] tx_rates drivers/net/wireless/ipw2x00/ipw2200.c:6105:33: got unsigned short [unsigned] [usertype] rates_mask drivers/net/wireless/ipw2x00/ipw2200.c:6124:29: warning: bad assignment (>>=) to restricted __le16 drivers/net/wireless/ipw2x00/ipw2200.c:6130:31: warning: restricted __le16 degrades to integer drivers/net/wireless/ipw2x00/ipw2200.c:6140:23: warning: restricted __le16 degrades to integer drivers/net/wireless/ipw2x00/ipw2200.c:6149:54: warning: restricted __le16 degrades to integer drivers/net/wireless/ipw2x00/ipw2200.c:6151:37: warning: invalid assignment: &= drivers/net/wireless/ipw2x00/ipw2200.c:6151:37: left side has type restricted __le16 drivers/net/wireless/ipw2x00/ipw2200.c:6151:37: right side has type int drivers/net/wireless/ipw2x00/ipw2200.c:6154:54: warning: restricted __le16 degrades to integer drivers/net/wireless/ipw2x00/ipw2200.c:6156:37: warning: invalid assignment: &= drivers/net/wireless/ipw2x00/ipw2200.c:6156:37: left side has type restricted __le16 drivers/net/wireless/ipw2x00/ipw2200.c:6156:37: right side has type int drivers/net/wireless/ipw2x00/ipw2200.c:6159:55: warning: restricted __le16 degrades to integer drivers/net/wireless/ipw2x00/ipw2200.c:6161:37: warning: invalid assignment: &= drivers/net/wireless/ipw2x00/ipw2200.c:6161:37: left side has type restricted __le16 drivers/net/wireless/ipw2x00/ipw2200.c:6161:37: right side has type int drivers/net/wireless/ipw2x00/ipw2200.c:6164:29: warning: invalid assignment: |= drivers/net/wireless/ipw2x00/ipw2200.c:6164:29: left side has type restricted __le16 drivers/net/wireless/ipw2x00/ipw2200.c:6164:29: right side has type unsigned short drivers/net/wireless/ipw2x00/ipw2200.c:7853:29: warning: incorrect type in assignment (different base types) drivers/net/wireless/ipw2x00/ipw2200.c:7853:29: expected signed char [signed] [usertype] [explicitly-signed] rt_dbmnoise drivers/net/wireless/ipw2x00/ipw2200.c:7853:29: got restricted __le16 [usertype] noise drivers/net/wireless/ipw2x00/ipw2200.c:7967:25: warning: incorrect type in initializer (different base types) drivers/net/wireless/ipw2x00/ipw2200.c:7967:25: expected signed char [signed] [usertype] [explicitly-signed] noise drivers/net/wireless/ipw2x00/ipw2200.c:7967:25: got restricted __le16 [usertype] noise Signed-off-by: Reinette Chatre Cc: Zhu Yi Acked-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 14 ++++--- drivers/net/wireless/ipw2x00/ipw2200.c | 73 +++++++++++++++++----------------- 2 files changed, 44 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 742432388ca..dee50ed0897 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -185,7 +185,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); static int debug = 0; -static int mode = 0; +static int network_mode = 0; static int channel = 0; static int associate = 0; static int disable = 0; @@ -195,7 +195,7 @@ static struct ipw2100_fw ipw2100_firmware; #include module_param(debug, int, 0444); -module_param(mode, int, 0444); +module_param_named(mode, network_mode, int, 0444); module_param(channel, int, 0444); module_param(associate, int, 0444); module_param(disable, int, 0444); @@ -2844,7 +2844,7 @@ static int __ipw2100_tx_process(struct ipw2100_priv *priv) #ifdef CONFIG_IPW2100_DEBUG { - int i = txq->oldest; + i = txq->oldest; IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, &txq->drv[i], (u32) (txq->nic + i * sizeof(struct ipw2100_bd)), @@ -6076,7 +6076,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->ieee->ieee802_1x = 1; /* Set module parameters */ - switch (mode) { + switch (network_mode) { case 1: priv->ieee->iw_mode = IW_MODE_ADHOC; break; @@ -8179,10 +8179,11 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) int rssi_qual; int tx_qual; int beacon_qual; + int quality; struct ipw2100_priv *priv = ieee80211_priv(dev); struct iw_statistics *wstats; - u32 rssi, quality, tx_retries, missed_beacons, tx_failures; + u32 rssi, tx_retries, missed_beacons, tx_failures; u32 ord_len = sizeof(u32); if (!priv) @@ -8265,7 +8266,8 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) beacon_qual = (20 - missed_beacons) * (PERFECT - VERY_GOOD) / 20 + VERY_GOOD; - quality = min(beacon_qual, min(tx_qual, rssi_qual)); + quality = min(tx_qual, rssi_qual); + quality = min(beacon_qual, quality); #ifdef CONFIG_IPW2100_DEBUG if (beacon_qual == quality) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 07f171c4d30..8e18d534835 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -83,13 +83,13 @@ MODULE_LICENSE("GPL"); static int cmdlog = 0; static int debug = 0; -static int channel = 0; -static int mode = 0; +static int default_channel = 0; +static int network_mode = 0; static u32 ipw_debug_level; static int associate; static int auto_create = 1; -static int led = 0; +static int led_support = 0; static int disable = 0; static int bt_coexist = 0; static int hwcrypto = 0; @@ -4265,9 +4265,10 @@ static void ipw_gather_stats(struct ipw_priv *priv) IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", signal_quality, rssi); - quality = min(beacon_quality, - min(rate_quality, - min(tx_quality, min(rx_quality, signal_quality)))); + quality = min(rx_quality, signal_quality); + quality = min(tx_quality, quality); + quality = min(rate_quality, quality); + quality = min(beacon_quality, quality); if (quality == beacon_quality) IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n", quality); @@ -4411,7 +4412,6 @@ static void ipw_rx_notification(struct ipw_priv *priv, { DECLARE_SSID_BUF(ssid); u16 size = le16_to_cpu(notif->size); - notif->size = le16_to_cpu(notif->size); IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); @@ -6101,11 +6101,10 @@ static void ipw_debug_config(struct ipw_priv *priv) static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) { /* TODO: Verify that this works... */ - struct ipw_fixed_rate fr = { - .tx_rates = priv->rates_mask - }; + struct ipw_fixed_rate fr; u32 reg; u16 mask = 0; + u16 new_tx_rates = priv->rates_mask; /* Identify 'current FW band' and match it with the fixed * Tx rates */ @@ -6117,54 +6116,56 @@ static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) /* Invalid fixed rate mask */ IPW_DEBUG_WX ("invalid fixed rate mask in ipw_set_fixed_rate\n"); - fr.tx_rates = 0; + new_tx_rates = 0; break; } - fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A; + new_tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A; break; default: /* 2.4Ghz or Mixed */ /* IEEE_B */ if (mode == IEEE_B) { - if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { + if (new_tx_rates & ~IEEE80211_CCK_RATES_MASK) { /* Invalid fixed rate mask */ IPW_DEBUG_WX ("invalid fixed rate mask in ipw_set_fixed_rate\n"); - fr.tx_rates = 0; + new_tx_rates = 0; } break; } /* IEEE_G */ - if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK | + if (new_tx_rates & ~(IEEE80211_CCK_RATES_MASK | IEEE80211_OFDM_RATES_MASK)) { /* Invalid fixed rate mask */ IPW_DEBUG_WX ("invalid fixed rate mask in ipw_set_fixed_rate\n"); - fr.tx_rates = 0; + new_tx_rates = 0; break; } - if (IEEE80211_OFDM_RATE_6MB_MASK & fr.tx_rates) { + if (IEEE80211_OFDM_RATE_6MB_MASK & new_tx_rates) { mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1); - fr.tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK; + new_tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK; } - if (IEEE80211_OFDM_RATE_9MB_MASK & fr.tx_rates) { + if (IEEE80211_OFDM_RATE_9MB_MASK & new_tx_rates) { mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1); - fr.tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK; + new_tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK; } - if (IEEE80211_OFDM_RATE_12MB_MASK & fr.tx_rates) { + if (IEEE80211_OFDM_RATE_12MB_MASK & new_tx_rates) { mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1); - fr.tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK; + new_tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK; } - fr.tx_rates |= mask; + new_tx_rates |= mask; break; } + fr.tx_rates = cpu_to_le16(new_tx_rates); + reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE); ipw_write_reg32(priv, reg, *(u32 *) & fr); } @@ -7850,7 +7851,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, /* Convert signal to DBM */ ipw_rt->rt_dbmsignal = antsignal; - ipw_rt->rt_dbmnoise = frame->noise; + ipw_rt->rt_dbmnoise = (s8) le16_to_cpu(frame->noise); /* Convert the channel data and set the flags */ ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); @@ -7964,7 +7965,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, u16 channel = frame->received_channel; u8 phy_flags = frame->antennaAndPhy; s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; - s8 noise = frame->noise; + s8 noise = (s8) le16_to_cpu(frame->noise); u8 rate = frame->rate; short len = le16_to_cpu(pkt->u.frame.length); struct sk_buff *skb; @@ -8335,7 +8336,7 @@ static void ipw_rx(struct ipw_priv *priv) .rssi = pkt->u.frame.rssi_dbm - IPW_RSSI_TO_DBM, .signal = - le16_to_cpu(pkt->u.frame.rssi_dbm) - + pkt->u.frame.rssi_dbm - IPW_RSSI_TO_DBM + 0x100, .noise = le16_to_cpu(pkt->u.frame.noise), @@ -8517,7 +8518,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) /* We default to disabling the LED code as right now it causes * too many systems to lock up... */ - if (!led) + if (!led_support) priv->config |= CFG_NO_LED; if (associate) @@ -8539,10 +8540,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) IPW_DEBUG_INFO("Radio disabled.\n"); } - if (channel != 0) { + if (default_channel != 0) { priv->config |= CFG_STATIC_CHANNEL; - priv->channel = channel; - IPW_DEBUG_INFO("Bind to static channel %d\n", channel); + priv->channel = default_channel; + IPW_DEBUG_INFO("Bind to static channel %d\n", default_channel); /* TODO: Validate that provided channel is in range */ } #ifdef CONFIG_IPW2200_QOS @@ -8550,7 +8551,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) burst_duration_CCK, burst_duration_OFDM); #endif /* CONFIG_IPW2200_QOS */ - switch (mode) { + switch (network_mode) { case 1: priv->ieee->iw_mode = IW_MODE_ADHOC; priv->net_dev->type = ARPHRD_ETHER; @@ -10181,7 +10182,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, #endif struct clx2_queue *q = &txq->q; u8 id, hdr_len, unicast; - u16 remaining_bytes; int fc; if (!(priv->status & STATUS_ASSOCIATED)) @@ -10220,7 +10220,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, tfd->u.data.cmd_id = DINO_CMD_TX; tfd->u.data.len = cpu_to_le16(txb->payload_size); - remaining_bytes = txb->payload_size; if (priv->assoc_request.ieee_mode == IPW_B_MODE) tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; @@ -11946,13 +11945,13 @@ MODULE_PARM_DESC(associate, "auto associate when scanning (default off)"); module_param(auto_create, int, 0444); MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); -module_param(led, int, 0444); +module_param_named(led, led_support, int, 0444); MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); -module_param(channel, int, 0444); +module_param_named(channel, default_channel, int, 0444); MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); #ifdef CONFIG_IPW2200_PROMISCUOUS @@ -11978,10 +11977,10 @@ MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); #endif /* CONFIG_IPW2200_QOS */ #ifdef CONFIG_IPW2200_MONITOR -module_param(mode, int, 0444); +module_param_named(mode, network_mode, int, 0444); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); #else -module_param(mode, int, 0444); +module_param_named(mode, network_mode, int, 0444); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); #endif -- cgit v1.2.3 From afa620429ac6a636246f85d97cf205d6533e7fcb Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 18 Aug 2009 19:54:23 +0200 Subject: rt2x00: configure_filter() callback is allowed to sleep The configure_filter() callback function no longer needs to be atomic. Remove the scheduled work structure and call into the driver configure_filter() directly. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 - drivers/net/wireless/rt2x00/rt2x00dev.c | 10 ---------- drivers/net/wireless/rt2x00/rt2x00mac.c | 5 +---- 3 files changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 39d7d9baafd..ad70946c3b5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -826,7 +826,6 @@ struct rt2x00_dev { * due to RTNL locking requirements. */ struct work_struct intf_work; - struct work_struct filter_work; /* * Data queue arrays for RX, TX and Beacon. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9ab70e435b5..16b560a661e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -118,14 +118,6 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) rt2x00link_start_tuner(rt2x00dev); } -static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, filter_work); - - rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter); -} - static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { @@ -859,7 +851,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) * Initialize configuration work. */ INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); - INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); /* * Allocate queue array. @@ -907,7 +898,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) /* * Stop all work. */ - cancel_work_sync(&rt2x00dev->filter_work); cancel_work_sync(&rt2x00dev->intf_work); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3011aea4fea..967d3b55c89 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -430,10 +430,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, return; rt2x00dev->packet_filter = *total_flags; - if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) - rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); - else - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work); + rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); } EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); -- cgit v1.2.3 From d904dc17495581254442b7fd054e267f2605c8ec Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 18 Aug 2009 20:33:12 +0200 Subject: rt2x00: bss_info_changed() callback is allowed to sleep The bss_info_changed() callback function no longer needs to be atomic. Remove the scheduled work structure and call into the driver directly. Additionaly this makes the DRIVER_REQUIRE_SCHEDULED flag redundant so it can be removed. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 1 - drivers/net/wireless/rt2x00/rt2800usb.c | 1 - drivers/net/wireless/rt2x00/rt2x00.h | 3 --- drivers/net/wireless/rt2x00/rt2x00dev.c | 8 -------- drivers/net/wireless/rt2x00/rt2x00mac.c | 14 +++----------- drivers/net/wireless/rt2x00/rt73usb.c | 1 - 6 files changed, 3 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 09a589432da..b04f59bab3b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1874,7 +1874,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) */ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); if (!modparam_nohwcrypt) { __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 45e02f16d75..639dc6cc04b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -2634,7 +2634,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); if (!modparam_nohwcrypt) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ad70946c3b5..555a777db6d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -350,8 +350,6 @@ struct rt2x00_intf { */ unsigned int delayed_flags; #define DELAYED_UPDATE_BEACON 0x00000001 -#define DELAYED_CONFIG_ERP 0x00000002 -#define DELAYED_LED_ASSOC 0x00000004 /* * Software sequence counter, this is only required @@ -614,7 +612,6 @@ enum rt2x00_flags { DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_ATIM_QUEUE, - DRIVER_REQUIRE_SCHEDULED, DRIVER_REQUIRE_DMA, DRIVER_REQUIRE_COPY_IV, DRIVER_REQUIRE_L2PAD, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 16b560a661e..3f8c70ebe9a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -123,7 +123,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); - struct ieee80211_bss_conf conf; int delayed_flags; /* @@ -133,7 +132,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, */ spin_lock(&intf->lock); - memcpy(&conf, &vif->bss_conf, sizeof(conf)); delayed_flags = intf->delayed_flags; intf->delayed_flags = 0; @@ -150,12 +148,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (delayed_flags & DELAYED_UPDATE_BEACON) rt2x00queue_update_beacon(rt2x00dev, vif, true); - - if (delayed_flags & DELAYED_CONFIG_ERP) - rt2x00lib_config_erp(rt2x00dev, intf, &conf); - - if (delayed_flags & DELAYED_LED_ASSOC) - rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); } static void rt2x00lib_intf_scheduled(struct work_struct *work) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 967d3b55c89..a91f316cd45 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -636,23 +636,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, else rt2x00dev->intf_associated--; - if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) - rt2x00leds_led_assoc(rt2x00dev, - !!rt2x00dev->intf_associated); - else - delayed |= DELAYED_LED_ASSOC; + rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); } /* * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ - if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { - if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) - rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); - else - delayed |= DELAYED_CONFIG_ERP; - } + if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) + rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); spin_lock(&intf->lock); if (delayed) { diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4d94b65943f..90e11726305 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2151,7 +2151,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); if (!modparam_nohwcrypt) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -- cgit v1.2.3 From 5791ce18aa660df7d1dafebf6bd89d5aa05bd742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Tue, 18 Aug 2009 22:08:31 +0200 Subject: b43: LP-PHY: Two small spec updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The specs are beginning to support rev3 LP-PHYs - implement one of the changes needed for rev3 support. Also, in the new MIPS driver, the "Japan TX filter" was renamed to "analog TX filter init" - however, calling it "init" is confusing, so name it "set analog filter", with a comment for easier future identification. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 94023838568..37ba1777667 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -609,9 +609,14 @@ static void lpphy_2063_init(struct b43_wldev *dev) b43_radio_write(dev, B2063_PA_SP7, 0); b43_radio_write(dev, B2063_TX_RF_SP6, 0x20); b43_radio_write(dev, B2063_TX_RF_SP9, 0x40); - b43_radio_write(dev, B2063_PA_SP3, 0xa0); - b43_radio_write(dev, B2063_PA_SP4, 0xa0); - b43_radio_write(dev, B2063_PA_SP2, 0x18); + if (dev->phy.rev == 2) { + b43_radio_write(dev, B2063_PA_SP3, 0xa0); + b43_radio_write(dev, B2063_PA_SP4, 0xa0); + b43_radio_write(dev, B2063_PA_SP2, 0x18); + } else { + b43_radio_write(dev, B2063_PA_SP3, 0x20); + b43_radio_write(dev, B2063_PA_SP2, 0x20); + } } struct lpphy_stx_table_entry { @@ -1972,7 +1977,9 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, return err; } -static void lpphy_japan_filter(struct b43_wldev *dev, int channel) + +/* This was previously called lpphy_japan_filter */ +static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel) { struct b43_phy_lp *lpphy = dev->phy.lp; u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! @@ -2141,7 +2148,7 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, err = lpphy_b2062_tune(dev, new_channel); if (err) return err; - lpphy_japan_filter(dev, new_channel); + lpphy_set_analog_filter(dev, new_channel); lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); } -- cgit v1.2.3 From eeef41854deae30ea304544f18684df70ae3f87b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 19 Aug 2009 12:43:47 +0200 Subject: ar9170: refactor configure_filter Thanks to "mac80211: allow configure_filter callback to sleep", we no longer have to defer the work to the workqueue. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 14 ++---- drivers/net/wireless/ath/ar9170/mac.c | 22 +++------- drivers/net/wireless/ath/ar9170/main.c | 75 +++++++------------------------- 3 files changed, 27 insertions(+), 84 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 95f8256c202..ce407248d7d 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -185,10 +185,8 @@ struct ar9170 { bool disable_offload; /* filter settings */ - struct work_struct filter_config_work; - u64 cur_mc_hash, want_mc_hash; - u32 cur_filter, want_filter; - unsigned long filter_changed; + u64 cur_mc_hash; + u32 cur_filter; unsigned int filter_state; bool sniffer_enabled; @@ -261,10 +259,6 @@ struct ar9170_tx_info { #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) #define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) -#define AR9170_FILTER_CHANGED_MODE BIT(0) -#define AR9170_FILTER_CHANGED_MULTICAST BIT(1) -#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2) - /* exported interface */ void *ar9170_alloc(size_t priv_size); int ar9170_register(struct ar9170 *ar, struct device *pdev); @@ -278,8 +272,8 @@ int ar9170_nag_limiter(struct ar9170 *ar); int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); int ar9170_init_mac(struct ar9170 *ar); int ar9170_set_qos(struct ar9170 *ar); -int ar9170_update_multicast(struct ar9170 *ar); -int ar9170_update_frame_filter(struct ar9170 *ar); +int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); +int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); int ar9170_set_operating_mode(struct ar9170 *ar); int ar9170_set_beacon_timers(struct ar9170 *ar); int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index d9f1f46de18..60049366e86 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -238,39 +238,31 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) return ar9170_regwrite_result(); } -int ar9170_update_multicast(struct ar9170 *ar) +int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) { int err; ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, - ar->want_mc_hash >> 32); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, - ar->want_mc_hash); - + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); ar9170_regwrite_finish(); err = ar9170_regwrite_result(); - if (err) return err; - ar->cur_mc_hash = ar->want_mc_hash; - + ar->cur_mc_hash = mc_hash; return 0; } -int ar9170_update_frame_filter(struct ar9170 *ar) +int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) { int err; - err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, - ar->want_filter); - + err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); if (err) return err; - ar->cur_filter = ar->want_filter; - + ar->cur_filter = filter; return 0; } diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index d30f33d4d41..658b32312ca 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1232,8 +1232,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw) mutex_lock(&ar->mutex); - ar->filter_changed = 0; - /* reinitialize queues statistics */ memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); for (i = 0; i < __AR9170_NUM_TXQ; i++) @@ -1296,7 +1294,6 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) #ifdef CONFIG_AR9170_LEDS cancel_delayed_work_sync(&ar->led_work); #endif - cancel_work_sync(&ar->filter_config_work); cancel_work_sync(&ar->beacon_work); mutex_lock(&ar->mutex); @@ -1973,8 +1970,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, } ar->cur_filter = 0; - ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS; - err = ar9170_update_frame_filter(ar); + err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); if (err) goto unlock; @@ -1992,8 +1988,7 @@ static void ar9170_op_remove_interface(struct ieee80211_hw *hw, mutex_lock(&ar->mutex); ar->vif = NULL; - ar->want_filter = 0; - ar9170_update_frame_filter(ar); + ar9170_update_frame_filter(ar, 0); ar9170_set_beacon_timers(ar); dev_kfree_skb(ar->beacon); ar->beacon = NULL; @@ -2065,41 +2060,6 @@ out: return err; } -static void ar9170_set_filters(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - filter_config_work); - int err; - - if (unlikely(!IS_STARTED(ar))) - return ; - - mutex_lock(&ar->mutex); - if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE, - &ar->filter_changed)) { - err = ar9170_set_operating_mode(ar); - if (err) - goto unlock; - } - - if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST, - &ar->filter_changed)) { - err = ar9170_update_multicast(ar); - if (err) - goto unlock; - } - - if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, - &ar->filter_changed)) { - err = ar9170_update_frame_filter(ar); - if (err) - goto unlock; - } - -unlock: - mutex_unlock(&ar->mutex); -} - static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mclist) { @@ -2126,6 +2086,11 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, { struct ar9170 *ar = hw->priv; + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return ; + + mutex_lock(&ar->mutex); + /* mask supported flags */ *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; @@ -2136,12 +2101,10 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, */ if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) - multicast = ~0ULL; + multicast = ~0ULL; - if (multicast != ar->want_mc_hash) { - ar->want_mc_hash = multicast; - set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed); - } + if (multicast != ar->cur_mc_hash) + ar9170_update_multicast(ar, multicast); if (changed_flags & FIF_CONTROL) { u32 filter = AR9170_MAC_REG_FTF_PSPOLL | @@ -2152,24 +2115,22 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, AR9170_MAC_REG_FTF_CFE_ACK; if (*new_flags & FIF_CONTROL) - ar->want_filter = ar->cur_filter | filter; + filter |= ar->cur_filter; else - ar->want_filter = ar->cur_filter & ~filter; + filter &= (~ar->cur_filter); - set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, - &ar->filter_changed); + ar9170_update_frame_filter(ar, filter); } if (changed_flags & FIF_PROMISC_IN_BSS) { ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; - set_bit(AR9170_FILTER_CHANGED_MODE, - &ar->filter_changed); + ar9170_set_operating_mode(ar); } - if (likely(IS_STARTED(ar))) - ieee80211_queue_work(ar->hw, &ar->filter_config_work); + mutex_unlock(&ar->mutex); } + static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -2423,9 +2384,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, default: break; } - - if (IS_STARTED(ar) && ar->filter_changed) - ieee80211_queue_work(ar->hw, &ar->filter_config_work); } static int ar9170_get_stats(struct ieee80211_hw *hw, @@ -2596,7 +2554,6 @@ void *ar9170_alloc(size_t priv_size) skb_queue_head_init(&ar->tx_pending[i]); } ar9170_rx_reset_rx_mpdu(ar); - INIT_WORK(&ar->filter_config_work, ar9170_set_filters); INIT_WORK(&ar->beacon_work, ar9170_new_beacon); INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); INIT_LIST_HEAD(&ar->tx_ampdu_list); -- cgit v1.2.3 From 30fab9e0aecf15ca79bb194bb603203f5e1fde66 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Wed, 19 Aug 2009 00:44:43 +0100 Subject: orinoco: remove spare whitespace Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 3e56f7643df..7698fdd6a3a 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -1291,7 +1291,7 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - priv->ibss_port = val ; + priv->ibss_port = val; /* Actually update the mode we are using */ set_port_type(priv); -- cgit v1.2.3 From 5904d2067680e9bb73a4816fa6b9eec49355c9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Stefanik?= Date: Tue, 18 Aug 2009 19:18:13 +0200 Subject: b43: LP-PHY: Implement spec updates and remove resolved FIXMEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Larry has started re-checking all current routines against a new version of the Broadcom MIPS driver. This patch implements the first round of changes he documented on the specs wiki. Also remove a few FIXMEs regarding missing initial values for variables with dynamic initial values where reading the values has been implemented. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 98 ++++++++++++++++++++------------- drivers/net/wireless/b43/phy_lp.h | 18 +++--- drivers/net/wireless/b43/tables_lpphy.c | 12 +++- 3 files changed, 82 insertions(+), 46 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 37ba1777667..2d3a5d812c4 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -724,9 +724,39 @@ static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult) b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8); } -static void lpphy_disable_crs(struct b43_wldev *dev) +static void lpphy_set_deaf(struct b43_wldev *dev, bool user) { + struct b43_phy_lp *lpphy = dev->phy.lp; + + if (user) + lpphy->crs_usr_disable = 1; + else + lpphy->crs_sys_disable = 1; b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80); +} + +static void lpphy_clear_deaf(struct b43_wldev *dev, bool user) +{ + struct b43_phy_lp *lpphy = dev->phy.lp; + + if (user) + lpphy->crs_usr_disable = 0; + else + lpphy->crs_sys_disable = 0; + + if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) { + 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); + } +} + +static void lpphy_disable_crs(struct b43_wldev *dev, bool user) +{ + lpphy_set_deaf(dev, user); 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); @@ -754,12 +784,9 @@ static void lpphy_disable_crs(struct b43_wldev *dev) b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF); } -static void lpphy_restore_crs(struct b43_wldev *dev) +static void lpphy_restore_crs(struct b43_wldev *dev, bool user) { - 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); + lpphy_clear_deaf(dev, user); b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80); b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00); } @@ -805,10 +832,11 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev, b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xF800, rf_gain); } else { - pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00; + pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0; + pa_gain <<= 2; 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, + b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0x8000, gains.pad | pa_gain); b43_phy_write(dev, B43_PHY_OFDM(0xFC), (gains.pga << 8) | gains.gm); @@ -822,7 +850,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev, 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 << 6); + b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6); } static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) @@ -862,33 +890,33 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) } } -static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) +static void lpphy_disable_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); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); + b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7); + } } else { b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); } } -static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) +static void lpphy_enable_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); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); + b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8); + } } else { b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); } @@ -1007,26 +1035,22 @@ 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 { - quotient = dividend / divisor; - remainder = dividend % divisor; - } + if (divisor == 0) + return 0; + + quotient = dividend / divisor; + remainder = dividend % divisor; rbit = divisor & 0x1; roundup = (divisor >> 1) + rbit; - precision--; - while (precision != 0xFF) { + while (precision != 0) { tmp = remainder - roundup; quotient <<= 1; - remainder <<= 1; - if (remainder >= roundup) { + if (remainder >= roundup) remainder = (tmp << 1) + rbit; - quotient--; - } + else + remainder <<= 1; precision--; } @@ -1128,11 +1152,11 @@ 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] = { + static const u32 ideal_pwr_table[21] = { 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64, 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35, 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088, - 0x0004c, 0x0002c, 0x0001a, 0xc0006, + 0x0004c, 0x0002c, 0x0001a, }; bool old_txg_ovr; u8 old_bbmult; @@ -1150,7 +1174,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) "RC calib: Failed to switch to channel 7, error = %d", err); } - old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1; + old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40); old_bbmult = lpphy_get_bb_mult(dev); if (old_txg_ovr) tx_gains = lpphy_get_tx_gains(dev); @@ -1165,7 +1189,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) old_txpctl = lpphy->txpctl_mode; lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - lpphy_disable_crs(dev); + lpphy_disable_crs(dev, true); loopback = lpphy_loopback(dev); if (loopback == -1) goto finish; @@ -1198,7 +1222,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) lpphy_stop_ddfs(dev); finish: - lpphy_restore_crs(dev); + lpphy_restore_crs(dev, true); 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); diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 99cb0386e34..e158d1f66c0 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h @@ -825,11 +825,11 @@ struct b43_phy_lp { enum b43_lpphy_txpctl_mode txpctl_mode; /* Transmit isolation medium band */ - u8 tx_isolation_med_band; /* FIXME initial value? */ + u8 tx_isolation_med_band; /* Transmit isolation low band */ - u8 tx_isolation_low_band; /* FIXME initial value? */ + u8 tx_isolation_low_band; /* Transmit isolation high band */ - u8 tx_isolation_hi_band; /* FIXME initial value? */ + u8 tx_isolation_hi_band; /* Max transmit power medium band */ u16 max_tx_pwr_med_band; @@ -848,7 +848,7 @@ struct b43_phy_lp { s16 txpa[3], txpal[3], txpah[3]; /* Receive power offset */ - u8 rx_pwr_offset; /* FIXME initial value? */ + u8 rx_pwr_offset; /* TSSI transmit count */ u16 tssi_tx_count; @@ -864,16 +864,16 @@ struct b43_phy_lp { s8 tx_pwr_idx_over; /* FIXME initial value? */ /* RSSI vf */ - u8 rssi_vf; /* FIXME initial value? */ + u8 rssi_vf; /* RSSI vc */ - u8 rssi_vc; /* FIXME initial value? */ + u8 rssi_vc; /* RSSI gs */ - u8 rssi_gs; /* FIXME initial value? */ + u8 rssi_gs; /* RC cap */ u8 rc_cap; /* FIXME initial value? */ /* BX arch */ - u8 bx_arch; /* FIXME initial value? */ + u8 bx_arch; /* Full calibration channel */ u8 full_calib_chan; /* FIXME initial value? */ @@ -885,6 +885,8 @@ struct b43_phy_lp { /* Used for "Save/Restore Dig Filt State" */ u16 dig_flt_state[9]; + bool crs_usr_disable, crs_sys_disable; + unsigned int pdiv; }; diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c index 2721310acb2..60d472f285a 100644 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ b/drivers/net/wireless/b43/tables_lpphy.c @@ -2367,7 +2367,17 @@ static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset, tmp = data.pad << 16; tmp |= data.pga << 8; tmp |= data.gm; - tmp |= 0x7f000000; + if (dev->phy.rev >= 3) { + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + tmp |= 0x10 << 24; + else + tmp |= 0x70 << 24; + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + tmp |= 0x14 << 24; + else + tmp |= 0x7F << 24; + } b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp); tmp = data.bb_mult << 20; tmp |= data.dac << 28; -- cgit v1.2.3 From 035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9 Mon Sep 17 00:00:00 2001 From: gregor kowski Date: Wed, 19 Aug 2009 22:35:45 +0200 Subject: b43: add hardware tkip This add hardware tkip for b43. Signed-off-by: Gregor Kowski Acked-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 2 +- drivers/net/wireless/b43/main.c | 122 +++++++++++++++++++++++++++++++++++++++- drivers/net/wireless/b43/pio.c | 4 +- drivers/net/wireless/b43/xmit.c | 28 +++++++-- drivers/net/wireless/b43/xmit.h | 3 +- 5 files changed, 147 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 41a0e9c2b33..289aaf6dfe7 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1188,7 +1188,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]); cookie = generate_cookie(ring, slot); err = b43_generate_txhdr(ring->dev, header, - skb->data, skb->len, info, cookie); + skb, info, cookie); if (unlikely(err)) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 78ddbc7f836..f5bdf1cae1d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -80,6 +80,10 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static int modparam_hwtkip; +module_param_named(hwtkip, modparam_hwtkip, int, 0444); +MODULE_PARM_DESC(hwtkip, "Enable hardware tkip."); + static int modparam_qos = 1; module_param_named(qos, modparam_qos, int, 0444); MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); @@ -834,6 +838,85 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) (index * 2) + 1, addrtmp[1]); } +/* The ucode will use phase1 key with TEK key to decrypt rx packets. + * When a packet is received, the iv32 is checked. + * - if it doesn't the packet is returned without modification (and software + * decryption can be done). That's what happen when iv16 wrap. + * - if it does, the rc4 key is computed, and decryption is tried. + * Either it will success and B43_RX_MAC_DEC is returned, + * either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned + * and the packet is not usable (it got modified by the ucode). + * So in order to never have B43_RX_MAC_DECERR, we should provide + * a iv32 and phase1key that match. Because we drop packets in case of + * B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all + * packets will be lost without higher layer knowing (ie no resync possible + * until next wrap). + * + * NOTE : this should support 50 key like RCMTA because + * (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50 + */ +static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32, + u16 *phase1key) +{ + unsigned int i; + u32 offset; + u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; + + if (!modparam_hwtkip) + return; + + if (b43_new_kidx_api(dev)) + pairwise_keys_start = B43_NR_GROUP_KEYS; + + B43_WARN_ON(index < pairwise_keys_start); + /* We have four default TX keys and possibly four default RX keys. + * Physical mac 0 is mapped to physical key 4 or 8, depending + * on the firmware version. + * So we must adjust the index here. + */ + index -= pairwise_keys_start; + B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS); + + if (b43_debug(dev, B43_DBG_KEYS)) { + b43dbg(dev->wl, "rx_tkip_phase1_write : idx 0x%x, iv32 0x%x\n", + index, iv32); + } + /* Write the key to the RX tkip shared mem */ + offset = B43_SHM_SH_TKIPTSCTTAK + index * (10 + 4); + for (i = 0; i < 10; i += 2) { + b43_shm_write16(dev, B43_SHM_SHARED, offset + i, + phase1key ? phase1key[i / 2] : 0); + } + b43_shm_write16(dev, B43_SHM_SHARED, offset + i, iv32); + b43_shm_write16(dev, B43_SHM_SHARED, offset + i + 2, iv32 >> 16); +} + +static void b43_op_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_key_conf *keyconf, const u8 *addr, + u32 iv32, u16 *phase1key) +{ + struct b43_wl *wl = hw_to_b43_wl(hw); + struct b43_wldev *dev; + int index = keyconf->hw_key_idx; + + if (B43_WARN_ON(!modparam_hwtkip)) + return; + + mutex_lock(&wl->mutex); + + dev = wl->current_dev; + if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) + goto out_unlock; + + keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ + + rx_tkip_phase1_write(dev, index, iv32, phase1key); + keymac_write(dev, index, addr); + +out_unlock: + mutex_unlock(&wl->mutex); +} + static void do_key_write(struct b43_wldev *dev, u8 index, u8 algorithm, const u8 *key, size_t key_len, const u8 *mac_addr) @@ -849,6 +932,19 @@ static void do_key_write(struct b43_wldev *dev, if (index >= pairwise_keys_start) keymac_write(dev, index, NULL); /* First zero out mac. */ + if (algorithm == B43_SEC_ALGO_TKIP) { + /* + * We should provide an initial iv32, phase1key pair. + * We could start with iv32=0 and compute the corresponding + * phase1key, but this means calling ieee80211_get_tkip_key + * with a fake skb (or export other tkip function). + * Because we are lazy we hope iv32 won't start with + * 0xffffffff and let's b43_op_update_tkip_key provide a + * correct pair. + */ + rx_tkip_phase1_write(dev, index, 0xffffffff, (u16*)buf); + } else if (index >= pairwise_keys_start) /* clear it */ + rx_tkip_phase1_write(dev, index, 0, NULL); if (key) memcpy(buf, key, key_len); key_write(dev, index, algorithm, buf); @@ -867,6 +963,15 @@ static int b43_key_write(struct b43_wldev *dev, int i; int pairwise_keys_start; + /* For ALG_TKIP the key is encoded as a 256-bit (32 byte) data block: + * - Temporal Encryption Key (128 bits) + * - Temporal Authenticator Tx MIC Key (64 bits) + * - Temporal Authenticator Rx MIC Key (64 bits) + * + * Hardware only store TEK + */ + if (algorithm == B43_SEC_ALGO_TKIP && key_len == 32) + key_len = 16; if (key_len > B43_SEC_KEYSIZE) return -EINVAL; for (i = 0; i < ARRAY_SIZE(dev->key); i++) { @@ -973,6 +1078,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev) printk(" Algo: %04X/%02X", algo, key->algorithm); if (index >= pairwise_keys_start) { + if (key->algorithm == B43_SEC_ALGO_TKIP) { + printk(" TKIP: "); + offset = B43_SHM_SH_TKIPTSCTTAK + (index - 4) * (10 + 4); + for (i = 0; i < 14; i += 2) { + u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i); + printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF)); + } + } rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, ((index - pairwise_keys_start) * 2) + 0); rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, @@ -3620,8 +3733,10 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: - if (algorithm == B43_SEC_ALGO_TKIP) { - /* FIXME: No TKIP hardware encryption for now. */ + if (algorithm == B43_SEC_ALGO_TKIP && + (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) || + !modparam_hwtkip)) { + /* We support only pairwise key */ err = -EOPNOTSUPP; goto out_unlock; } @@ -3651,6 +3766,8 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, b43_hf_read(dev) & ~B43_HF_USEDEFKEYS); } key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + if (algorithm == B43_SEC_ALGO_TKIP) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; break; case DISABLE_KEY: { err = b43_key_clear(dev, key->hw_key_idx); @@ -4378,6 +4495,7 @@ static const struct ieee80211_ops b43_hw_ops = { .bss_info_changed = b43_op_bss_info_changed, .configure_filter = b43_op_configure_filter, .set_key = b43_op_set_key, + .update_tkip_key = b43_op_update_tkip_key, .get_stats = b43_op_get_stats, .get_tx_stats = b43_op_get_tx_stats, .get_tsf = b43_op_get_tsf, diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 73c047d8de4..3fd653c78b1 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -461,8 +461,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q, cookie = generate_cookie(q, pack); hdrlen = b43_txhdr_size(q->dev); - err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data, - skb->len, info, cookie); + err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb, + info, cookie); if (err) return err; diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index be1c53ecdb0..e7075d2c775 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -180,11 +180,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate) /* Generate a TX data header. */ int b43_generate_txhdr(struct b43_wldev *dev, u8 *_txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, + struct sk_buff *skb_frag, struct ieee80211_tx_info *info, u16 cookie) { + const unsigned char *fragment_data = skb_frag->data; + unsigned int fragment_len = skb_frag->len; struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; const struct b43_phy *phy = &dev->phy; const struct ieee80211_hdr *wlhdr = @@ -258,9 +259,26 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & B43_TXH_MAC_KEYALG; wlhdr_len = ieee80211_hdrlen(fctl); - iv_len = min((size_t) info->control.hw_key->iv_len, - ARRAY_SIZE(txhdr->iv)); - memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); + if (key->algorithm == B43_SEC_ALGO_TKIP) { + u16 phase1key[5]; + int i; + /* we give the phase1key and iv16 here, the key is stored in + * shm. With that the hardware can do phase 2 and encryption. + */ + ieee80211_get_tkip_key(info->control.hw_key, skb_frag, + IEEE80211_TKIP_P1_KEY, (u8*)phase1key); + /* phase1key is in host endian */ + for (i = 0; i < 5; i++) + phase1key[i] = cpu_to_le16(phase1key[i]); + + memcpy(txhdr->iv, phase1key, 10); + /* iv16 */ + memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3); + } else { + iv_len = min((size_t) info->control.hw_key->iv_len, + ARRAY_SIZE(txhdr->iv)); + memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); + } } if (b43_is_old_txhdr_format(dev)) { b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 4fb2a190f7a..3530de87187 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -176,8 +176,7 @@ size_t b43_txhdr_size(struct b43_wldev *dev) int b43_generate_txhdr(struct b43_wldev *dev, u8 * txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, + struct sk_buff *skb_frag, struct ieee80211_tx_info *txctl, u16 cookie); /* Transmit Status */ -- cgit v1.2.3 From ff36041652fcb9f5c17bdbeb081414f69521f1af Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 20 Aug 2009 13:41:14 +0530 Subject: ath9k: Fix bug in retrieving average beacon rssi Currently the beacon rssi that LPF gives is divided and rounded up by ATH_RSSI_EP_MULTIPLIER twice. This will leave the incorrect rssi in ANI. Having correct rssi in ANI fixes the connection stability at < 30dB rssi range. This patch removes the unncessary computation of average rssi over already valid average rssi. Also removes the redundant macros to find average rssi. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 119924511f8..6273fd056c2 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -18,15 +18,10 @@ #define ANI_H #define HAL_PROCESS_ANI 0x00000001 -#define ATH9K_RSSI_EP_MULTIPLIER (1<<7) #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) -#define HAL_EP_RND(x, mul) \ - ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) -#define BEACON_RSSI(ahp) \ - HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi, \ - ATH9K_RSSI_EP_MULTIPLIER) +#define BEACON_RSSI(ahp) (ahp->stats.ast_nodestats.ns_avgbrssi) #define ATH9K_ANI_OFDM_TRIG_HIGH 500 #define ATH9K_ANI_OFDM_TRIG_LOW 200 -- cgit v1.2.3 From 22e66a4c15b063aee5d03991c4b9629a3b0c4556 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 19 Aug 2009 16:23:40 +0530 Subject: ath9k: Nuke struct ath9k_node_stats Other than ns_avgbrssi (Average beacon rssi) no data of ath9k_node_stats is being used anywhere. Nuke this structure and move its only useful member to ar5416Anistate. Also cleanup this redundant data in ath_softc. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 6 +----- drivers/net/wireless/ath/ath9k/ani.h | 15 +++------------ drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/main.c | 9 +++------ drivers/net/wireless/ath/ath9k/recv.c | 2 +- 5 files changed, 8 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index f264097a2f4..a7cbb07988c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -538,7 +538,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) { struct ar5416AniState *aniState; @@ -550,7 +549,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, return; aniState = ah->curani; - ah->stats.ast_nodestats = *stats; listenTime = ath9k_hw_ani_get_listen_time(ah); if (listenTime < 0) { @@ -693,8 +691,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, * any of the MIB counters overflow/trigger so don't assume we're * here because a PHY error counter triggered. */ -void ath9k_hw_procmibevent(struct ath_hw *ah, - const struct ath9k_node_stats *stats) +void ath9k_hw_procmibevent(struct ath_hw *ah) { u32 phyCnt1, phyCnt2; @@ -706,7 +703,6 @@ void ath9k_hw_procmibevent(struct ath_hw *ah, /* Clear the mib counters and save them in the stats */ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - ah->stats.ast_nodestats = *stats; if (!DO_ANI(ah)) return; diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 6273fd056c2..4e1ab94a515 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -21,7 +21,7 @@ #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) -#define BEACON_RSSI(ahp) (ahp->stats.ast_nodestats.ns_avgbrssi) +#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) #define ATH9K_ANI_OFDM_TRIG_HIGH 500 #define ATH9K_ANI_OFDM_TRIG_LOW 200 @@ -60,13 +60,6 @@ struct ath9k_mib_stats { u32 beacons; }; -struct ath9k_node_stats { - u32 ns_avgbrssi; - u32 ns_avgrssi; - u32 ns_avgtxrssi; - u32 ns_avgtxrate; -}; - struct ar5416AniState { struct ath9k_channel *c; u8 noiseImmunityLevel; @@ -110,21 +103,19 @@ struct ar5416Stats { u32 ast_ani_reset; u32 ast_ani_lzero; u32 ast_ani_lneg; + u32 avgbrssi; struct ath9k_mib_stats ast_mibstats; - struct ath9k_node_stats ast_nodestats; }; #define ah_mibStats stats.ast_mibstats 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); 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, u32 *rxf_pcnt, u32 *txf_pcnt); -void ath9k_hw_procmibevent(struct ath_hw *ah, - const struct ath9k_node_stats *stats); +void ath9k_hw_procmibevent(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); void ath9k_hw_ani_disable(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0e444a62904..7705da1103f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -603,7 +603,6 @@ struct ath_softc { int beacon_interval; struct ath_ani ani; - struct ath9k_node_stats nodestats; #ifdef CONFIG_ATH9K_DEBUG struct ath9k_debug debug; #endif diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index de197117fdc..9b9b4e8ee1e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -384,7 +384,7 @@ static void ath_ani_calibrate(unsigned long data) if (longcal || shortcal || aniflag) { /* Call ANI routine if necessary */ if (aniflag) - ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan); + ath9k_hw_ani_monitor(ah, ah->curchan); /* Perform calibration if necessary */ if (longcal || shortcal) { @@ -589,7 +589,7 @@ irqreturn_t ath_isr(int irq, void *dev) * it will clear whatever condition caused * the interrupt. */ - ath9k_hw_procmibevent(ah, &sc->nodestats); + ath9k_hw_procmibevent(ah); ath9k_hw_set_interrupts(ah, sc->imask); } @@ -940,10 +940,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ath_beacon_config(sc, vif); /* Reset rssi stats */ - sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; - sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; - sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; - sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; + sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; ath_start_ani(sc); } else { diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 61dbdd22744..7b62c220d5f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -222,7 +222,7 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, /* Update Beacon RSSI, this is used by ANI. */ if (ieee80211_is_beacon(fc)) - sc->nodestats.ns_avgbrssi = ds->ds_rxstat.rs_rssi; + sc->sc_ah->stats.avgbrssi = ds->ds_rxstat.rs_rssi; rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); rx_status->band = hw->conf.channel->band; -- cgit v1.2.3 From c23b5a699471ea2ef9d146eae80e64836cfbf001 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 13:49:55 +0200 Subject: mwl8k: remove various unused struct members and defines Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 73 +++++--------------------------------------- 1 file changed, 8 insertions(+), 65 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index c32e93c8c41..91b7062711e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table); #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 #define MWL8K_H2A_INT_DUMMY (1 << 20) #define MWL8K_H2A_INT_RESET (1 << 15) -#define MWL8K_H2A_INT_PS (1 << 2) #define MWL8K_H2A_INT_DOORBELL (1 << 1) #define MWL8K_H2A_INT_PPA_READY (1 << 0) @@ -161,10 +160,8 @@ struct mwl8k_priv { /* lock held over TX and TX reap */ spinlock_t tx_lock; - u32 int_mask; struct ieee80211_vif *vif; - struct list_head vif_list; struct ieee80211_channel *current_channel; @@ -173,10 +170,8 @@ struct mwl8k_priv { dma_addr_t cookie_dma; u16 num_mcaddrs; - u16 region_code; u8 hw_rev; __le32 fw_rev; - u32 wep_enabled; /* * Running count of TX packets in flight, to avoid @@ -226,8 +221,6 @@ struct mwl8k_priv { /* Per interface specific private data */ struct mwl8k_vif { - struct list_head node; - /* backpointer to parent config block */ struct mwl8k_priv *priv; @@ -247,18 +240,11 @@ struct mwl8k_vif { /* number of supported legacy rates */ u8 legacy_nrates; - /* Number of supported MCS rates. Work in progress */ - u8 mcs_nrates; - /* Index into station database.Returned by update_sta_db call */ u8 peer_id; /* Non AMPDU sequence number assigned by driver */ u16 seqno; - - /* Note:There is no channel info, - * refer to the master channel info in priv - */ }; #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) @@ -681,11 +667,9 @@ struct ewc_ht_info { /* Peer Entry flags - used to define the type of the peer node */ #define MWL8K_PEER_TYPE_ACCESSPOINT 2 -#define MWL8K_PEER_TYPE_ADHOC_STATION 4 #define MWL8K_IEEE_LEGACY_DATA_RATES 12 #define MWL8K_MCS_BITMAP_SIZE 16 -#define pad_size 16 struct peer_capability_info { /* Peer type - AP vs. STA. */ @@ -707,7 +691,7 @@ struct peer_capability_info { /* HT rate table. Intersection of our rates and peer rates. */ __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; - __u8 pad[pad_size]; + __u8 pad[16]; /* If set, interoperability mode, no proprietary extensions. */ __u8 interop; @@ -717,15 +701,6 @@ struct peer_capability_info { } __attribute__((packed)); /* Inline functions to manipulate QoS field in data descriptor. */ -static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid) -{ - u16 val_mask = 0x000f; - u16 qos_mask = ~val_mask; - - /* TID bits 0-3 */ - return (qos & qos_mask) | (tid & val_mask); -} - static inline u16 mwl8k_qos_setbit_eosp(u16 qos) { u16 val_mask = 1 << 4; @@ -826,9 +801,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) /* * Packet reception. */ -#define MWL8K_RX_CTRL_KEY_INDEX_MASK 0x30 #define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 -#define MWL8K_RX_CTRL_AMPDU 0x01 struct mwl8k_rx_desc { __le16 pkt_len; @@ -1073,8 +1046,6 @@ enum { /* Transmit packet ACK policy */ #define MWL8K_TXD_ACK_POLICY_NORMAL 0 -#define MWL8K_TXD_ACK_POLICY_NONE 1 -#define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT 2 #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 #define GET_TXQ(_ac) (\ @@ -1083,20 +1054,11 @@ enum { ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ MWL8K_WME_AC_BE) -#define MWL8K_TXD_STATUS_IDLE 0x00000000 -#define MWL8K_TXD_STATUS_USED 0x00000001 #define MWL8K_TXD_STATUS_OK 0x00000001 #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 -#define MWL8K_TXD_STATUS_BROADCAST_TX 0x00000010 -#define MWL8K_TXD_STATUS_FAILED_LINK_ERROR 0x00000020 -#define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040 -#define MWL8K_TXD_STATUS_FAILED_AGING 0x00000080 -#define MWL8K_TXD_STATUS_HOST_CMD 0x40000000 #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 -#define MWL8K_TXD_SOFTSTALE 0x80 -#define MWL8K_TXD_SOFTSTALE_MGMT_RETRY 0x01 struct mwl8k_tx_desc { __le32 status; @@ -1279,12 +1241,10 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) return 0; } -#define MWL8K_TXD_OK (MWL8K_TXD_STATUS_OK | \ - MWL8K_TXD_STATUS_OK_RETRY | \ - MWL8K_TXD_STATUS_OK_MORE_RETRY) -#define MWL8K_TXD_SUCCESS(stat) ((stat) & MWL8K_TXD_OK) -#define MWL8K_TXD_FAIL_RETRY(stat) \ - ((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT)) +#define MWL8K_TXD_SUCCESS(status) \ + ((status) & (MWL8K_TXD_STATUS_OK | \ + MWL8K_TXD_STATUS_OK_RETRY | \ + MWL8K_TXD_STATUS_OK_MORE_RETRY)) static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) { @@ -1671,7 +1631,6 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; - priv->region_code = le16_to_cpu(cmd->region_code); } kfree(cmd); @@ -2150,7 +2109,6 @@ struct mwl8k_cmd_set_edca_params { __u8 txq; } __attribute__((packed)); -#define MWL8K_GET_EDCA_ALL 0 #define MWL8K_SET_EDCA_CW 0x01 #define MWL8K_SET_EDCA_TXOP 0x02 #define MWL8K_SET_EDCA_AIFS 0x04 @@ -2323,18 +2281,12 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, /* * CMD_SET_AID. */ -#define IEEE80211_OPMODE_DISABLED 0x00 -#define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE 0x01 -#define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE 0x02 -#define IEEE80211_OPMODE_HTMIXED_PROT_MODE 0x03 - #define MWL8K_RATE_INDEX_MAX_ARRAY 14 #define MWL8K_FRAME_PROT_DISABLED 0x00 #define MWL8K_FRAME_PROT_11G 0x07 #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 -#define MWL8K_FRAME_PROT_MASK 0x07 struct mwl8k_cmd_update_set_aid { struct mwl8k_cmd_pkt header; @@ -2439,10 +2391,6 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw, */ #define MWL8K_RATE_TABLE_SIZE 8 #define MWL8K_UCAST_RATE 0 -#define MWL8K_MCAST_RATE 1 -#define MWL8K_BCAST_RATE 2 - -#define MWL8K_USE_FIXED_RATE 0x0001 #define MWL8K_USE_AUTO_RATE 0x0002 struct mwl8k_rate_entry { @@ -2535,7 +2483,6 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - status &= priv->int_mask; if (!status) return IRQ_NONE; @@ -2873,7 +2820,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) } /* Enable interrupts */ - iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); worker = kzalloc(sizeof(*worker), GFP_KERNEL); if (worker == NULL) { @@ -3532,7 +3479,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->hostcmd_wait = NULL; priv->tx_wait = NULL; priv->inconfig = false; - priv->wep_enabled = 0; priv->wmm_mode = false; priv->pending_tx_pkts = 0; strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); @@ -3614,8 +3560,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, } iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - priv->int_mask = 0; - iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); @@ -3652,9 +3597,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, * commands use interrupts and avoids polling. Disable * interrupts when done. */ - priv->int_mask |= MWL8K_A2H_EVENTS; - - iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); /* Get config data, mac addrs etc */ rc = mwl8k_cmd_get_hw_spec(hw); -- cgit v1.2.3 From d89173f25228b8795af2d4b53e985cc44c729332 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 09:54:27 +0200 Subject: mwl8k: s/IEEE80211_ADDR_LEN/ETH_ALEN/g Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 47 +++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 91b7062711e..e8febab6135 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -38,8 +38,6 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = { }; MODULE_DEVICE_TABLE(pci, mwl8k_table); -#define IEEE80211_ADDR_LEN ETH_ALEN - /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 #define MWL8K_MODE_STA 0x0000005a @@ -199,7 +197,7 @@ struct mwl8k_priv { /* XXX need to convert this to handle multiple interfaces */ bool capture_beacon; - u8 capture_bssid[IEEE80211_ADDR_LEN]; + u8 capture_bssid[ETH_ALEN]; struct sk_buff *beacon_skb; /* @@ -228,8 +226,8 @@ struct mwl8k_vif { struct ieee80211_bss_conf bss_info; /* BSSID of AP or IBSS */ - u8 bssid[IEEE80211_ADDR_LEN]; - u8 mac_addr[IEEE80211_ADDR_LEN]; + u8 bssid[ETH_ALEN]; + u8 mac_addr[ETH_ALEN]; /* * Subset of supported legacy rates. @@ -785,7 +783,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) memmove(&tr->wh, wh, hdrlen); /* Clear addr4 */ - memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN); + memset(tr->wh.addr4, 0, ETH_ALEN); /* * Firmware length is the length of the fully formed "802.11 @@ -952,7 +950,7 @@ static inline void mwl8k_save_beacon(struct mwl8k_priv *priv, struct sk_buff *skb) { priv->capture_beacon = false; - memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN); + memset(priv->capture_bssid, 0, ETH_ALEN); /* * Use GFP_ATOMIC as rxq_process is called from @@ -1067,7 +1065,7 @@ struct mwl8k_tx_desc { __le16 qos_control; __le32 pkt_phys_addr; __le16 pkt_len; - __u8 dest_MAC_addr[IEEE80211_ADDR_LEN]; + __u8 dest_MAC_addr[ETH_ALEN]; __le32 next_tx_desc_phys_addr; __le32 reserved; __le16 rate_info; @@ -1587,7 +1585,7 @@ struct mwl8k_cmd_get_hw_spec { __u8 hw_rev; __u8 host_interface; __le16 num_mcaddrs; - __u8 perm_addr[IEEE80211_ADDR_LEN]; + __u8 perm_addr[ETH_ALEN]; __le16 region_code; __le32 fw_rev; __le32 ps_cookie; @@ -1644,7 +1642,7 @@ struct mwl8k_cmd_mac_multicast_adr { struct mwl8k_cmd_pkt header; __le16 action; __le16 numaddr; - __u8 addr[1][IEEE80211_ADDR_LEN]; + __u8 addr[1][ETH_ALEN]; }; #define MWL8K_ENABLE_RX_MULTICAST 0x000F @@ -1655,7 +1653,7 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, struct mwl8k_cmd_mac_multicast_adr *cmd; int index = 0; int rc; - int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN); + int size = sizeof(*cmd) + ((mc_count - 1) * ETH_ALEN); cmd = kzalloc(size, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -1665,11 +1663,11 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); cmd->numaddr = cpu_to_le16(mc_count); while ((index < mc_count) && mclist) { - if (mclist->da_addrlen != IEEE80211_ADDR_LEN) { + if (mclist->da_addrlen != ETH_ALEN) { rc = -EINVAL; goto mwl8k_cmd_mac_multicast_adr_exit; } - memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN); + memcpy(cmd->addr[index], mclist->da_addr, ETH_ALEN); index++; mclist = mclist->next; } @@ -1848,11 +1846,11 @@ static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) struct mwl8k_cmd_set_post_scan { struct mwl8k_cmd_pkt header; __le32 isibss; - __u8 bssid[IEEE80211_ADDR_LEN]; + __u8 bssid[ETH_ALEN]; } __attribute__((packed)); static int -mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN]) +mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[ETH_ALEN]) { struct mwl8k_cmd_set_post_scan *cmd; int rc; @@ -1864,7 +1862,7 @@ mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN]) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->isibss = 0; - memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN); + memcpy(cmd->bssid, mac, ETH_ALEN); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2216,7 +2214,7 @@ struct mwl8k_cmd_update_sta_db { __le32 action; /* Peer MAC address */ - __u8 peer_addr[IEEE80211_ADDR_LEN]; + __u8 peer_addr[ETH_ALEN]; __le32 reserved; @@ -2244,7 +2242,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, cmd->action = cpu_to_le32(action); peer_info = &cmd->peer_info; - memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN); + memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); switch (action) { case MWL8K_STA_DB_ADD_ENTRY: @@ -2293,7 +2291,7 @@ struct mwl8k_cmd_update_set_aid { __le16 aid; /* AP's MAC address (BSSID) */ - __u8 bssid[IEEE80211_ADDR_LEN]; + __u8 bssid[ETH_ALEN]; __le16 protection_mode; __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; } __attribute__((packed)); @@ -2317,7 +2315,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->aid = cpu_to_le16(info->aid); - memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN); + memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); prot_mode = MWL8K_FRAME_PROT_DISABLED; @@ -2934,7 +2932,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); /* Save the mac address */ - memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN); + memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); /* Back pointer to parent config block */ mwl8k_vif->priv = priv; @@ -3091,14 +3089,13 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt) * Finalize the join. Tell rx handler to process * next beacon from our BSSID. */ - memcpy(priv->capture_bssid, - mwl8k_vif->bssid, IEEE80211_ADDR_LEN); + memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); priv->capture_beacon = true; } else { mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); memset(&mwl8k_vif->bss_info, 0, sizeof(struct ieee80211_bss_conf)); - memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN); + memset(mwl8k_vif->bssid, 0, ETH_ALEN); } mwl8k_bss_info_changed_exit: @@ -3117,7 +3114,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, int rc; if (changed & BSS_CHANGED_BSSID) - memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN); + memcpy(mv_vif->bssid, info->bssid, ETH_ALEN); if ((changed & BSS_CHANGED_ASSOC) == 0) return; -- cgit v1.2.3 From ff45fc60ad583f45ecf10a41f7dbecf78519bcc1 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 11:50:36 +0200 Subject: mwl8k: sort firmware command list by opcode, and trim unused commands Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index e8febab6135..682b82071a0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -307,25 +307,23 @@ static const struct ieee80211_rate mwl8k_rates[] = { #define MWL8K_CMD_GET_HW_SPEC 0x0003 #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 #define MWL8K_CMD_GET_STAT 0x0014 -#define MWL8K_CMD_RADIO_CONTROL 0x001C -#define MWL8K_CMD_RF_TX_POWER 0x001E +#define MWL8K_CMD_RADIO_CONTROL 0x001c +#define MWL8K_CMD_RF_TX_POWER 0x001e #define MWL8K_CMD_SET_PRE_SCAN 0x0107 #define MWL8K_CMD_SET_POST_SCAN 0x0108 -#define MWL8K_CMD_SET_RF_CHANNEL 0x010A +#define MWL8K_CMD_SET_RF_CHANNEL 0x010a +#define MWL8K_CMD_SET_AID 0x010d +#define MWL8K_CMD_SET_RATE 0x0110 +#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 +#define MWL8K_CMD_RTS_THRESHOLD 0x0113 #define MWL8K_CMD_SET_SLOT 0x0114 +#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 +#define MWL8K_CMD_SET_WMM_MODE 0x0123 #define MWL8K_CMD_MIMO_CONFIG 0x0125 +#define MWL8K_CMD_USE_FIXED_RATE 0x0126 #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 -#define MWL8K_CMD_SET_WMM_MODE 0x0123 -#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 -#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 -#define MWL8K_CMD_UPDATE_STADB 0x1123 #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 -#define MWL8K_CMD_SET_LINKADAPT_MODE 0x0129 -#define MWL8K_CMD_SET_AID 0x010d -#define MWL8K_CMD_SET_RATE 0x0110 -#define MWL8K_CMD_USE_FIXED_RATE 0x0126 -#define MWL8K_CMD_RTS_THRESHOLD 0x0113 -#define MWL8K_CMD_ENCRYPTION 0x1122 +#define MWL8K_CMD_UPDATE_STADB 0x1123 static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) { @@ -343,20 +341,18 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(SET_PRE_SCAN); MWL8K_CMDNAME(SET_POST_SCAN); MWL8K_CMDNAME(SET_RF_CHANNEL); + MWL8K_CMDNAME(SET_AID); + MWL8K_CMDNAME(SET_RATE); + MWL8K_CMDNAME(SET_FINALIZE_JOIN); + MWL8K_CMDNAME(RTS_THRESHOLD); MWL8K_CMDNAME(SET_SLOT); + MWL8K_CMDNAME(SET_EDCA_PARAMS); + MWL8K_CMDNAME(SET_WMM_MODE); MWL8K_CMDNAME(MIMO_CONFIG); + MWL8K_CMDNAME(USE_FIXED_RATE); MWL8K_CMDNAME(ENABLE_SNIFFER); - MWL8K_CMDNAME(SET_WMM_MODE); - MWL8K_CMDNAME(SET_EDCA_PARAMS); - MWL8K_CMDNAME(SET_FINALIZE_JOIN); - MWL8K_CMDNAME(UPDATE_STADB); MWL8K_CMDNAME(SET_RATEADAPT_MODE); - MWL8K_CMDNAME(SET_LINKADAPT_MODE); - MWL8K_CMDNAME(SET_AID); - MWL8K_CMDNAME(SET_RATE); - MWL8K_CMDNAME(USE_FIXED_RATE); - MWL8K_CMDNAME(RTS_THRESHOLD); - MWL8K_CMDNAME(ENCRYPTION); + MWL8K_CMDNAME(UPDATE_STADB); default: snprintf(buf, bufsize, "0x%x", cmd); } -- cgit v1.2.3 From ce9e2e1b8433c8795459a259ee87bc4e424e7c50 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 14:00:45 +0200 Subject: mwl8k: various coding style cleanups Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 130 +++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 73 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 682b82071a0..a2eeba17d37 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1,5 +1,6 @@ /* - * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards + * drivers/net/wireless/mwl8k.c + * Driver for Marvell TOPDOG 802.11 Wireless cards * * Copyright (C) 2008 Marvell Semiconductor Inc. * @@ -40,12 +41,12 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table); /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 -#define MWL8K_MODE_STA 0x0000005a -#define MWL8K_MODE_AP 0x000000a5 +#define MWL8K_MODE_STA 0x0000005a +#define MWL8K_MODE_AP 0x000000a5 #define MWL8K_HIU_INT_CODE 0x00000c14 -#define MWL8K_FWSTA_READY 0xf0f1f2f4 -#define MWL8K_FWAP_READY 0xf1f2f4a5 -#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 +#define MWL8K_FWSTA_READY 0xf0f1f2f4 +#define MWL8K_FWAP_READY 0xf1f2f4a5 +#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 #define MWL8K_HIU_SCRATCH 0x00000c40 /* Host->device communications */ @@ -54,10 +55,10 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table); #define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 #define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 -#define MWL8K_H2A_INT_DUMMY (1 << 20) -#define MWL8K_H2A_INT_RESET (1 << 15) -#define MWL8K_H2A_INT_DOORBELL (1 << 1) -#define MWL8K_H2A_INT_PPA_READY (1 << 0) +#define MWL8K_H2A_INT_DUMMY (1 << 20) +#define MWL8K_H2A_INT_RESET (1 << 15) +#define MWL8K_H2A_INT_DOORBELL (1 << 1) +#define MWL8K_H2A_INT_PPA_READY (1 << 0) /* Device->host communications */ #define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c @@ -65,16 +66,16 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table); #define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c -#define MWL8K_A2H_INT_DUMMY (1 << 20) -#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) -#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) -#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) -#define MWL8K_A2H_INT_RADIO_ON (1 << 6) -#define MWL8K_A2H_INT_RADIO_OFF (1 << 5) -#define MWL8K_A2H_INT_MAC_EVENT (1 << 3) -#define MWL8K_A2H_INT_OPC_DONE (1 << 2) -#define MWL8K_A2H_INT_RX_READY (1 << 1) -#define MWL8K_A2H_INT_TX_DONE (1 << 0) +#define MWL8K_A2H_INT_DUMMY (1 << 20) +#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) +#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) +#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) +#define MWL8K_A2H_INT_RADIO_ON (1 << 6) +#define MWL8K_A2H_INT_RADIO_OFF (1 << 5) +#define MWL8K_A2H_INT_MAC_EVENT (1 << 3) +#define MWL8K_A2H_INT_OPC_DONE (1 << 2) +#define MWL8K_A2H_INT_RX_READY (1 << 1) +#define MWL8K_A2H_INT_TX_DONE (1 << 0) #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ MWL8K_A2H_INT_CHNL_SWITCHED | \ @@ -331,7 +332,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) snprintf(buf, bufsize, "%s", #x);\ return buf;\ } while (0) - switch (cmd & (~0x8000)) { + switch (cmd & ~0x8000) { MWL8K_CMDNAME(CODE_DNLD); MWL8K_CMDNAME(GET_HW_SPEC); MWL8K_CMDNAME(MAC_MULTICAST_ADR); @@ -1078,8 +1079,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) int size; int i; - memset(&txq->tx_stats, 0, - sizeof(struct ieee80211_tx_queue_stats)); + memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats)); txq->tx_stats.limit = MWL8K_TX_DESCS; txq->tx_head = 0; txq->tx_tail = 0; @@ -1181,10 +1181,10 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) { - u32 count = 0; - unsigned long timeout = 0; struct mwl8k_priv *priv = hw->priv; DECLARE_COMPLETION_ONSTACK(cmd_wait); + u32 count; + unsigned long timeout; might_sleep(); @@ -1219,7 +1219,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) __func__, __LINE__, delay_ms, count, newcount); mwl8k_scan_tx_ring(priv, txinfo, 4); - for (index = 0 ; index < 4; index++) + for (index = 0; index < 4; index++) printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", index, @@ -1229,6 +1229,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) txinfo[index].fw_owned, txinfo[index].drv_owned, txinfo[index].unused); + return -ETIMEDOUT; } @@ -1251,7 +1252,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) int rc; struct mwl8k_tx_desc *tx_desc; unsigned long addr; - size_t size; + int size; struct sk_buff *skb; struct ieee80211_tx_info *info; u32 status; @@ -1275,7 +1276,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) priv->pending_tx_pkts--; addr = le32_to_cpu(tx_desc->pkt_phys_addr); - size = (u32)(le16_to_cpu(tx_desc->pkt_len)); + size = le16_to_cpu(tx_desc->pkt_len); skb = txq->tx_skb[tx].skb; txq->tx_skb[tx].skb = NULL; @@ -1312,12 +1313,8 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); - - /* Convert firmware status stuff into tx_status */ - if (MWL8K_TXD_SUCCESS(status)) { - /* Transmit OK */ + if (MWL8K_TXD_SUCCESS(status)) info->flags |= IEEE80211_TX_STAT_ACK; - } ieee80211_tx_status_irqsafe(hw, skb); @@ -1522,7 +1519,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) dma_addr_t dma_addr; unsigned int dma_size; int rc; - u16 __iomem *result; unsigned long timeout = 0; u8 buf[32]; @@ -1551,7 +1547,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) pci_unmap_single(priv->pdev, dma_addr, dma_size, PCI_DMA_BIDIRECTIONAL); - result = &cmd->result; if (!timeout) { spin_lock_irq(&priv->fw_lock); priv->hostcmd_wait = NULL; @@ -1562,12 +1557,12 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) MWL8K_CMD_TIMEOUT_MS); rc = -ETIMEDOUT; } else { - rc = *result ? -EINVAL : 0; + rc = cmd->result ? -EINVAL : 0; if (rc) printk(KERN_ERR "%s: Command %s error 0x%x\n", priv->name, mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), - *result); + cmd->result); } return rc; @@ -1638,10 +1633,11 @@ struct mwl8k_cmd_mac_multicast_adr { struct mwl8k_cmd_pkt header; __le16 action; __le16 numaddr; - __u8 addr[1][ETH_ALEN]; + __u8 addr[0][ETH_ALEN]; }; #define MWL8K_ENABLE_RX_MULTICAST 0x000F + static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mclist) @@ -1649,7 +1645,8 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, struct mwl8k_cmd_mac_multicast_adr *cmd; int index = 0; int rc; - int size = sizeof(*cmd) + ((mc_count - 1) * ETH_ALEN); + int size = sizeof(*cmd) + mc_count * ETH_ALEN; + cmd = kzalloc(size, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -1658,13 +1655,13 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, cmd->header.length = cpu_to_le16(size); cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); cmd->numaddr = cpu_to_le16(mc_count); - while ((index < mc_count) && mclist) { + + while (index < mc_count && mclist) { if (mclist->da_addrlen != ETH_ALEN) { rc = -EINVAL; goto mwl8k_cmd_mac_multicast_adr_exit; } - memcpy(cmd->addr[index], mclist->da_addr, ETH_ALEN); - index++; + memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN); mclist = mclist->next; } @@ -1846,7 +1843,7 @@ struct mwl8k_cmd_set_post_scan { } __attribute__((packed)); static int -mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[ETH_ALEN]) +mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac) { struct mwl8k_cmd_set_post_scan *cmd; int rc; @@ -1980,7 +1977,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0; + cmd->action = cpu_to_le32(!!enable); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -1989,7 +1986,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) } /* - * CMD_SET_RATE_ADAPT_MODE. + * CMD_SET_RATEADAPT_MODE. */ struct mwl8k_cmd_set_rate_adapt_mode { struct mwl8k_cmd_pkt header; @@ -2117,22 +2114,18 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, __u8 aifs, __u16 txop) { struct mwl8k_cmd_set_edca_params *cmd; - u32 log_cw_min, log_cw_max; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - log_cw_min = ilog2(cw_min+1); - log_cw_max = ilog2(cw_max+1); cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); cmd->txop = cpu_to_le16(txop); - cmd->log_cw_max = (u8)log_cw_max; - cmd->log_cw_min = (u8)log_cw_min; + cmd->log_cw_max = (u8)ilog2(cw_max + 1); + cmd->log_cw_min = (u8)ilog2(cw_min + 1); cmd->aifs = aifs; cmd->txq = qnum; @@ -2173,11 +2166,7 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - if (dtim) - cmd->sleep_interval = cpu_to_le32(dtim); - else - cmd->sleep_interval = cpu_to_le32(1); + cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); hdrlen = ieee80211_hdrlen(payload->frame_control); @@ -2189,8 +2178,8 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, "sent to firmware. Sz=%u MAX=%u\n", __func__, payload_len, MWL8K_FJ_BEACON_MAXLEN); - payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ? - MWL8K_FJ_BEACON_MAXLEN : payload_len; + if (payload_len > MWL8K_FJ_BEACON_MAXLEN) + payload_len = MWL8K_FJ_BEACON_MAXLEN; if (payload && payload_len) memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); @@ -2250,7 +2239,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, peer_info->amsdu_enabled = 0; rates = peer_info->legacy_rates; - for (count = 0 ; count < mv_vif->legacy_nrates; count++) + for (count = 0; count < mv_vif->legacy_nrates; count++) rates[count] = bitrates[count].hw_value; rc = mwl8k_post_cmd(hw, &cmd->header); @@ -2313,8 +2302,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); - prot_mode = MWL8K_FRAME_PROT_DISABLED; - if (info->use_cts_prot) { prot_mode = MWL8K_FRAME_PROT_11G; } else { @@ -2331,7 +2318,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, break; } } - cmd->protection_mode = cpu_to_le16(prot_mode); for (count = 0; count < mv_vif->legacy_nrates; count++) @@ -2934,7 +2920,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, mwl8k_vif->priv = priv; /* Setup initial PHY parameters */ - memcpy(mwl8k_vif->legacy_rates , + memcpy(mwl8k_vif->legacy_rates, priv->rates, sizeof(mwl8k_vif->legacy_rates)); mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); @@ -3171,8 +3157,9 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) if (rc) goto mwl8k_configure_filter_exit; if (mc_count) { - mc_count = mc_count < priv->num_mcaddrs ? - mc_count : priv->num_mcaddrs; + if (mc_count > priv->num_mcaddrs) + mc_count = priv->num_mcaddrs; + rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); if (rc) printk(KERN_ERR @@ -3411,12 +3398,9 @@ static void mwl8k_tx_reclaim_handler(unsigned long data) for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, 0); - if (priv->tx_wait != NULL) { - int count = mwl8k_txq_busy(priv); - if (count == 0) { - complete(priv->tx_wait); - priv->tx_wait = NULL; - } + if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) { + complete(priv->tx_wait); + priv->tx_wait = NULL; } spin_unlock_bh(&priv->tx_lock); } @@ -3426,7 +3410,7 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) struct mwl8k_priv *priv = container_of(work, struct mwl8k_priv, finalize_join_worker); struct sk_buff *skb = priv->beacon_skb; - u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period; + u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); dev_kfree_skb(skb); @@ -3513,7 +3497,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR); /* Set rssi and noise values to dBm */ - hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM); + hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; hw->vif_data_size = sizeof(struct mwl8k_vif); priv->vif = NULL; -- cgit v1.2.3 From c46563b714b09d44eec4d1fd8a0f53e79ddaa3aa Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 12:14:58 +0200 Subject: mwl8k: remove MWL8K_RADIO_* defines Instead of passing a flag bitmask to mwl8k_cmd_802_11_radio_control, pass the 'enable' and 'force' arguments as separate parameters, and introduce wrappers for the common cases of enabling and disabling without forcing. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 50 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a2eeba17d37..78183c8b5f0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -186,9 +186,10 @@ struct mwl8k_priv { struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; + bool radio_on; + /* RF preamble: Short, Long or Auto */ u8 radio_preamble; - u8 radio_state; /* WMM MODE 1 for enabled; 0 for disabled */ bool wmm_mode; @@ -278,9 +279,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { }; /* Radio settings */ -#define MWL8K_RADIO_FORCE 0x2 -#define MWL8K_RADIO_ENABLE 0x1 -#define MWL8K_RADIO_DISABLE 0x0 #define MWL8K_RADIO_AUTO_PREAMBLE 0x0005 #define MWL8K_RADIO_SHORT_PREAMBLE 0x0003 #define MWL8K_RADIO_LONG_PREAMBLE 0x0001 @@ -1195,7 +1193,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) count = mwl8k_txq_busy(priv); if (count) { priv->tx_wait = &cmd_wait; - if (priv->radio_state) + if (priv->radio_on) mwl8k_tx_start(priv); } spin_unlock_bh(&priv->tx_lock); @@ -1318,7 +1316,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) ieee80211_tx_status_irqsafe(hw, skb); - wake = !priv->inconfig && priv->radio_state; + wake = !priv->inconfig && priv->radio_on; } if (wake) @@ -1726,18 +1724,16 @@ struct mwl8k_cmd_802_11_radio_control { __le16 radio_on; } __attribute__((packed)); -static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable) +static int +mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_802_11_radio_control *cmd; int rc; - if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) && - !(enable & MWL8K_RADIO_FORCE)) + if (enable == priv->radio_on && !force) return 0; - enable &= MWL8K_RADIO_ENABLE; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -1752,11 +1748,21 @@ static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable) kfree(cmd); if (!rc) - priv->radio_state = enable; + priv->radio_on = enable; return rc; } +static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) +{ + return mwl8k_cmd_802_11_radio_control(hw, 0, 0); +} + +static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) +{ + return mwl8k_cmd_802_11_radio_control(hw, 1, 0); +} + static int mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) { @@ -1770,8 +1776,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) MWL8K_RADIO_SHORT_PREAMBLE : MWL8K_RADIO_LONG_PREAMBLE); - return mwl8k_cmd_802_11_radio_control(hw, - MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE); + return mwl8k_cmd_802_11_radio_control(hw, 1, 1); } /* @@ -2483,7 +2488,7 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { if (!priv->inconfig && - priv->radio_state && + priv->radio_on && mwl8k_txq_busy(priv)) mwl8k_tx_start(priv); } @@ -2661,7 +2666,7 @@ static void mwl8k_config_thread(struct work_struct *wt) spin_lock_irq(&priv->tx_lock); priv->inconfig = false; - if (priv->pending_tx_pkts && priv->radio_state) + if (priv->pending_tx_pkts && priv->radio_on) mwl8k_tx_start(priv); spin_unlock_irq(&priv->tx_lock); ieee80211_wake_queues(hw); @@ -2745,7 +2750,7 @@ static int mwl8k_start_wt(struct work_struct *wt) } /* Turn on radio */ - if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { + if (mwl8k_cmd_802_11_radio_enable(hw)) { rc = -EIO; goto mwl8k_start_exit; } @@ -2839,11 +2844,8 @@ static int mwl8k_stop_wt(struct work_struct *wt) { struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt; struct ieee80211_hw *hw = worker->header.hw; - int rc; - - rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); - return rc; + return mwl8k_cmd_802_11_radio_disable(hw); } static void mwl8k_stop(struct ieee80211_hw *hw) @@ -2958,7 +2960,7 @@ static int mwl8k_config_wt(struct work_struct *wt) struct mwl8k_priv *priv = hw->priv; int rc = 0; - if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { + if (mwl8k_cmd_802_11_radio_enable(hw)) { rc = -EINVAL; goto mwl8k_config_exit; } @@ -3503,7 +3505,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Set default radio state and preamble */ priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE; - priv->radio_state = MWL8K_RADIO_DISABLE; + priv->radio_on = 0; /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); @@ -3584,7 +3586,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, } /* Turn radio off */ - rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); + rc = mwl8k_cmd_802_11_radio_disable(hw); if (rc) { printk(KERN_ERR "%s: Cannot disable\n", priv->name); goto err_stop_firmware; -- cgit v1.2.3 From 68ce38845c23443b15e374fb7362916c1231278e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 12:26:57 +0200 Subject: mwl8k: remove MWL8K_RADIO_*_PREAMBLE defines Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 78183c8b5f0..22500bf59d1 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -187,9 +187,7 @@ struct mwl8k_priv { struct ieee80211_rate rates[12]; bool radio_on; - - /* RF preamble: Short, Long or Auto */ - u8 radio_preamble; + bool radio_short_preamble; /* WMM MODE 1 for enabled; 0 for disabled */ bool wmm_mode; @@ -278,17 +276,10 @@ static const struct ieee80211_rate mwl8k_rates[] = { { .bitrate = 540, .hw_value = 108, }, }; -/* Radio settings */ -#define MWL8K_RADIO_AUTO_PREAMBLE 0x0005 -#define MWL8K_RADIO_SHORT_PREAMBLE 0x0003 -#define MWL8K_RADIO_LONG_PREAMBLE 0x0001 - /* WMM */ #define MWL8K_WMM_ENABLE 1 #define MWL8K_WMM_DISABLE 0 -#define MWL8K_RADIO_DEFAULT_PREAMBLE MWL8K_RADIO_LONG_PREAMBLE - /* Slot time */ /* Short Slot: 9us slot time */ @@ -1741,7 +1732,7 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->control = cpu_to_le16(priv->radio_preamble); + cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1); cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); rc = mwl8k_post_cmd(hw, &cmd->header); @@ -1772,9 +1763,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) return -EINVAL; priv = hw->priv; - priv->radio_preamble = (short_preamble ? - MWL8K_RADIO_SHORT_PREAMBLE : - MWL8K_RADIO_LONG_PREAMBLE); + priv->radio_short_preamble = short_preamble; return mwl8k_cmd_802_11_radio_control(hw, 1, 1); } @@ -3051,8 +3040,7 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt) goto mwl8k_bss_info_changed_exit; /* Set radio preamble */ - if (mwl8k_set_radio_preamble(hw, - info->use_short_preamble)) + if (mwl8k_set_radio_preamble(hw, info->use_short_preamble)) goto mwl8k_bss_info_changed_exit; /* Set slot time */ @@ -3504,8 +3492,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->vif = NULL; /* Set default radio state and preamble */ - priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE; priv->radio_on = 0; + priv->radio_short_preamble = 0; /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); -- cgit v1.2.3 From 0439b1f55646ea944b0d58337f5065b79a1c1be0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 12:34:02 +0200 Subject: mwl8k: remove MWL8K_WMM_* defines Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 22500bf59d1..33d7ab517b3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -188,9 +188,7 @@ struct mwl8k_priv { bool radio_on; bool radio_short_preamble; - - /* WMM MODE 1 for enabled; 0 for disabled */ - bool wmm_mode; + bool wmm_enabled; /* Set if PHY config is in progress */ bool inconfig; @@ -276,10 +274,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { { .bitrate = 540, .hw_value = 108, }, }; -/* WMM */ -#define MWL8K_WMM_ENABLE 1 -#define MWL8K_WMM_DISABLE 0 - /* Slot time */ /* Short Slot: 9us slot time */ @@ -2028,13 +2022,13 @@ static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0; + cmd->action = cpu_to_le16(!!enable); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); if (!rc) - priv->wmm_mode = enable; + priv->wmm_enabled = enable; return rc; } @@ -2762,7 +2756,7 @@ static int mwl8k_start_wt(struct work_struct *wt) } /* Disable WMM. WMM gets enabled when stack sends WMM parms */ - if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) { + if (mwl8k_set_wmm(hw, 0)) { rc = -EIO; goto mwl8k_start_exit; } @@ -3272,10 +3266,11 @@ static int mwl8k_conf_tx_wt(struct work_struct *wt) struct mwl8k_priv *priv = hw->priv; int rc = 0; - if (priv->wmm_mode == MWL8K_WMM_DISABLE) - if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) { + if (!priv->wmm_enabled) { + if (mwl8k_set_wmm(hw, 1)) { rc = -EINVAL; goto mwl8k_conf_tx_exit; + } } if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min, @@ -3446,7 +3441,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->hostcmd_wait = NULL; priv->tx_wait = NULL; priv->inconfig = false; - priv->wmm_mode = false; + priv->wmm_enabled = false; priv->pending_tx_pkts = 0; strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); -- cgit v1.2.3 From 5539bb51295f2c9300a6e467a29bb62bcfe9f4bc Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 16:06:53 +0200 Subject: mwl8k: remove MWL8K_*_SLOTTIME defines Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 33d7ab517b3..a40434b5572 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -274,14 +274,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { { .bitrate = 540, .hw_value = 108, }, }; -/* Slot time */ - -/* Short Slot: 9us slot time */ -#define MWL8K_SHORT_SLOTTIME 1 - -/* Long slot: 20us slot time */ -#define MWL8K_LONG_SLOTTIME 0 - /* Set or get info from Firmware */ #define MWL8K_CMD_SET 0x0001 #define MWL8K_CMD_GET 0x0000 @@ -1895,7 +1887,7 @@ struct mwl8k_cmd_set_slot { __u8 short_slot; } __attribute__((packed)); -static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time) +static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) { struct mwl8k_cmd_set_slot *cmd; int rc; @@ -1907,7 +1899,7 @@ static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0; + cmd->short_slot = short_slot_time; rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -3038,8 +3030,7 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt) goto mwl8k_bss_info_changed_exit; /* Set slot time */ - if (mwl8k_cmd_set_slot(hw, info->use_short_slot ? - MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME)) + if (mwl8k_cmd_set_slot(hw, info->use_short_slot)) goto mwl8k_bss_info_changed_exit; /* Update peer rate info */ -- cgit v1.2.3 From e81cd2d664fe5b75a0db9bb24b43c0dfbde32319 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 03:55:42 +0200 Subject: mwl8k: fix mwl8k_configure_filter() parameter lifetime issue mwl8k_configure_filter() passes pointers to total_flags and the multicast address list to a workqueue function, while there is no guarantee that those pointers will still be valid by the time the workqueue function runs. Solve this by passing total_flags by value, and by passing an already built multicast address setup command packet to the workqueue function so that we don't have to look at the multicast address list itself outside of mwl8k_configure_filter(). Also, since ->configure_filter() can sleep now, wait synchronously for the worker to finish. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 107 ++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 68 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a40434b5572..a961b698c69 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1613,38 +1613,39 @@ struct mwl8k_cmd_mac_multicast_adr { #define MWL8K_ENABLE_RX_MULTICAST 0x000F -static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, - int mc_count, - struct dev_addr_list *mclist) +static struct mwl8k_cmd_pkt * +__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) { + struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_mac_multicast_adr *cmd; - int index = 0; - int rc; - int size = sizeof(*cmd) + mc_count * ETH_ALEN; + int size; + int i; + + if (mc_count > priv->num_mcaddrs) + mc_count = priv->num_mcaddrs; + + size = sizeof(*cmd) + mc_count * ETH_ALEN; - cmd = kzalloc(size, GFP_KERNEL); + cmd = kzalloc(size, GFP_ATOMIC); if (cmd == NULL) - return -ENOMEM; + return NULL; cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); cmd->header.length = cpu_to_le16(size); cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); cmd->numaddr = cpu_to_le16(mc_count); - while (index < mc_count && mclist) { + for (i = 0; i < mc_count && mclist; i++) { if (mclist->da_addrlen != ETH_ALEN) { - rc = -EINVAL; - goto mwl8k_cmd_mac_multicast_adr_exit; + kfree(cmd); + return NULL; } - memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN); + memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); mclist = mclist->next; } - rc = mwl8k_post_cmd(hw, &cmd->header); - -mwl8k_cmd_mac_multicast_adr_exit: - kfree(cmd); - return rc; + return &cmd->header; } /* @@ -3091,12 +3092,21 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, printk(KERN_ERR "%s() timed out\n", __func__); } +static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, + int mc_count, struct dev_addr_list *mclist) +{ + struct mwl8k_cmd_pkt *cmd; + + cmd = __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); + + return (unsigned long)cmd; +} + struct mwl8k_configure_filter_worker { struct mwl8k_work_struct header; unsigned int changed_flags; - unsigned int *total_flags; - int mc_count; - struct dev_addr_list *mclist; + unsigned int total_flags; + struct mwl8k_cmd_pkt *multicast_adr_cmd; }; #define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC @@ -3105,18 +3115,12 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) { struct mwl8k_configure_filter_worker *worker = (struct mwl8k_configure_filter_worker *)wt; - struct ieee80211_hw *hw = worker->header.hw; - unsigned int changed_flags = worker->changed_flags; - unsigned int *total_flags = worker->total_flags; - int mc_count = worker->mc_count; - struct dev_addr_list *mclist = worker->mclist; - struct mwl8k_priv *priv = hw->priv; int rc = 0; - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + if (worker->changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (worker->total_flags & FIF_BCN_PRBRESP_PROMISC) rc = mwl8k_cmd_set_pre_scan(hw); else { u8 *bssid; @@ -3129,54 +3133,20 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) } } - if (rc) - goto mwl8k_configure_filter_exit; - if (mc_count) { - if (mc_count > priv->num_mcaddrs) - mc_count = priv->num_mcaddrs; - - rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); - if (rc) - printk(KERN_ERR - "%s()Error setting multicast addresses\n", - __func__); - } + if (!rc && worker->multicast_adr_cmd != NULL) + rc = mwl8k_post_cmd(hw, worker->multicast_adr_cmd); + kfree(worker->multicast_adr_cmd); -mwl8k_configure_filter_exit: return rc; } -static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - struct mwl8k_configure_filter_worker *worker; - - worker = kzalloc(sizeof(*worker), GFP_ATOMIC); - - if (!worker) - return 0; - - /* - * XXX: This is _HORRIBLY_ broken!! - * - * No locking, the mclist pointer might be invalid as soon as this - * function returns, something in the list might be invalidated - * once we get to the worker, etc... - */ - worker->mc_count = mc_count; - worker->mclist = mclist; - - return (u64)worker; -} - static void mwl8k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast) { - - struct mwl8k_configure_filter_worker *worker = (void *)multicast; struct mwl8k_priv *priv = hw->priv; + struct mwl8k_configure_filter_worker *worker; /* Clear unsupported feature flags */ *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; @@ -3184,12 +3154,13 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS)) return; + worker = kzalloc(sizeof(*worker), GFP_ATOMIC); if (worker == NULL) return; - worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; worker->changed_flags = changed_flags; - worker->total_flags = total_flags; + worker->total_flags = *total_flags; + worker->multicast_adr_cmd = (void *)(unsigned long)multicast; mwl8k_queue_work(hw, &worker->header, priv->config_wq, mwl8k_configure_filter_wt); -- cgit v1.2.3 From 240e86efd60e6bc232a072273a7f7794bcb035e0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 14:15:44 +0200 Subject: mwl8k: ->add_interface() is not called for monitor interfaces There is no need to check for NL80211_IFTYPE_MONITOR in ->add_interface(), as this function is never called for monitor interfaces. Also, there is no need to advertise this bit in our wiphy's ->interface_modes. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a961b698c69..301d2a20d42 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2883,8 +2883,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, /* * We only support managed interfaces for now. */ - if (conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_MONITOR) + if (conf->type != NL80211_IFTYPE_STATION) return -EINVAL; /* Clean out driver private area */ @@ -3440,8 +3439,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->queues = MWL8K_TX_QUEUES; - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR); + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); /* Set rssi and noise values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; -- cgit v1.2.3 From 76266b2ad38c33fb2c1475cfeb35ed070adaba2b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 11:07:09 +0200 Subject: mwl8k: dma header manipulations can't fail Adding and removing the DMA header that the mwl8k hardware requires on tx and provides on rx can never fail, since we are guaranteed to have enough headroom on the tx path to expand the packet, and we only ever shrink the packet on the rx path. (And on both paths we are guaranteed to be the only user of the skb we are handling.) This allows removing all of the skb clone handling in the tx and tx reclaim paths, and eliminates error checks in both the tx and rx paths, simplifying the code a bit more. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 83 +++++++------------------------------------- 1 file changed, 13 insertions(+), 70 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 301d2a20d42..5aa80420c0d 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -111,17 +111,6 @@ struct mwl8k_rx_queue { struct sk_buff **rx_skb; }; -struct mwl8k_skb { - /* - * The DMA engine requires a modification to the payload. - * If the skbuff is shared/cloned, it needs to be unshared. - * This method is used to ensure the stack always gets back - * the skbuff it sent for transmission. - */ - struct sk_buff *clone; - struct sk_buff *skb; -}; - struct mwl8k_tx_queue { /* hw transmits here */ int tx_head; @@ -132,7 +121,7 @@ struct mwl8k_tx_queue { struct ieee80211_tx_queue_stats tx_stats; struct mwl8k_tx_desc *tx_desc_area; dma_addr_t tx_desc_dma; - struct mwl8k_skb *tx_skb; + struct sk_buff **tx_skb; }; /* Pointers to the firmware data and meta information about it. */ @@ -714,12 +703,11 @@ struct mwl8k_dma_data { } __attribute__((packed)); /* Routines to add/remove DMA header from skb. */ -static inline int mwl8k_remove_dma_header(struct sk_buff *skb) +static inline void mwl8k_remove_dma_header(struct sk_buff *skb) { - struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data); + struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data; void *dst, *src = &tr->wh; - __le16 fc = tr->wh.frame_control; - int hdrlen = ieee80211_hdrlen(fc); + int hdrlen = ieee80211_hdrlen(tr->wh.frame_control); u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; dst = (void *)tr + space; @@ -727,11 +715,9 @@ static inline int mwl8k_remove_dma_header(struct sk_buff *skb) memmove(dst, src, hdrlen); skb_pull(skb, space); } - - return 0; } -static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) +static inline void mwl8k_add_dma_header(struct sk_buff *skb) { struct ieee80211_hdr *wh; u32 hdrlen, pktlen; @@ -763,8 +749,6 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) * This includes all crypto material including the MIC. */ tr->fwlen = cpu_to_le16(pktlen - hdrlen); - - return skb; } @@ -967,10 +951,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); - if (mwl8k_remove_dma_header(skb)) { - dev_kfree_skb(skb); - continue; - } + mwl8k_remove_dma_header(skb); wh = (struct ieee80211_hdr *)skb->data; @@ -1224,7 +1205,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) while (txq->tx_stats.len > 0) { int tx; - int rc; struct mwl8k_tx_desc *tx_desc; unsigned long addr; int size; @@ -1232,7 +1212,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) struct ieee80211_tx_info *info; u32 status; - rc = 0; tx = txq->tx_head; tx_desc = txq->tx_desc_area + tx; @@ -1252,40 +1231,18 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) addr = le32_to_cpu(tx_desc->pkt_phys_addr); size = le16_to_cpu(tx_desc->pkt_len); - skb = txq->tx_skb[tx].skb; - txq->tx_skb[tx].skb = NULL; + skb = txq->tx_skb[tx]; + txq->tx_skb[tx] = NULL; BUG_ON(skb == NULL); pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); - rc = mwl8k_remove_dma_header(skb); + mwl8k_remove_dma_header(skb); /* Mark descriptor as unused */ tx_desc->pkt_phys_addr = 0; tx_desc->pkt_len = 0; - if (txq->tx_skb[tx].clone) { - /* Replace with original skb - * before returning to stack - * as buffer has been cloned - */ - dev_kfree_skb(skb); - skb = txq->tx_skb[tx].clone; - txq->tx_skb[tx].clone = NULL; - } - - if (rc) { - /* Something has gone wrong here. - * Failed to remove DMA header. - * Print error message and drop packet. - */ - printk(KERN_ERR "%s: Error removing DMA header from " - "tx skb 0x%p.\n", priv->name, skb); - - dev_kfree_skb(skb); - continue; - } - info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); if (MWL8K_TXD_SUCCESS(status)) @@ -1327,7 +1284,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) struct mwl8k_tx_desc *tx; struct mwl8k_dma_data *tr; struct mwl8k_vif *mwl8k_vif; - struct sk_buff *org_skb = skb; dma_addr_t dma; u16 qos = 0; bool qosframe = false, ampduframe = false; @@ -1338,21 +1294,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txq = priv->txq + index; tx = txq->tx_desc_area + txq->tx_tail; - BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL); + BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); /* - * Append HW DMA header to start of packet. Drop packet if - * there is not enough space or a failure to unshare/unclone - * the skb. + * Append HW DMA header to start of packet. */ - skb = mwl8k_add_dma_header(skb); - - if (skb == NULL) { - printk(KERN_DEBUG "%s: failed to prepend HW DMA " - "header, dropping TX frame.\n", priv->name); - dev_kfree_skb(org_skb); - return NETDEV_TX_OK; - } + mwl8k_add_dma_header(skb); tx_info = IEEE80211_SKB_CB(skb); mwl8k_vif = MWL8K_VIF(tx_info->control.vif); @@ -1380,8 +1327,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) printk(KERN_DEBUG "%s: failed to dma map skb, " "dropping TX frame.\n", priv->name); - if (org_skb != NULL) - dev_kfree_skb(org_skb); if (skb != NULL) dev_kfree_skb(skb); return NETDEV_TX_OK; @@ -1437,9 +1382,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) tx->pkt_phys_addr = cpu_to_le32(dma); tx->pkt_len = cpu_to_le16(skb->len); - txq->tx_skb[txq->tx_tail].skb = skb; - txq->tx_skb[txq->tx_tail].clone = - skb == org_skb ? NULL : org_skb; + txq->tx_skb[txq->tx_tail] = skb; spin_lock_bh(&priv->tx_lock); -- cgit v1.2.3 From d4b7057052236e81ab0788cc8df306dc02b0e7be Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 16 Jul 2009 12:44:45 +0200 Subject: mwl8k: don't touch 'command done' interrupt during firmware load Since firmware load commands don't generate 'command done' interrupts like normal commands do, polling for command done interrupts just unnecessarily slows down the firmware load process. Removing this bit of code speeds up loading a typical firmware image from 840 msec to 180 msec. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 5aa80420c0d..cc0aa80ca87 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -411,7 +411,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) { void __iomem *regs = priv->regs; dma_addr_t dma_addr; - int rc; int loops; dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); @@ -425,7 +424,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) iowrite32(MWL8K_H2A_INT_DUMMY, regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - rc = -ETIMEDOUT; loops = 1000; do { u32 int_code; @@ -433,7 +431,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) int_code = ioread32(regs + MWL8K_HIU_INT_CODE); if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { iowrite32(0, regs + MWL8K_HIU_INT_CODE); - rc = 0; break; } @@ -442,26 +439,7 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); - /* - * Clear 'command done' interrupt bit. - */ - loops = 1000; - do { - u32 status; - - status = ioread32(priv->regs + - MWL8K_HIU_A2H_INTERRUPT_STATUS); - if (status & MWL8K_A2H_INT_OPC_DONE) { - iowrite32(~MWL8K_A2H_INT_OPC_DONE, - priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - break; - } - - udelay(1); - } while (--loops); - - return rc; + return loops ? 0 : -ETIMEDOUT; } static int mwl8k_load_fw_image(struct mwl8k_priv *priv, -- cgit v1.2.3 From c3f967d301a76b7053d16817c34191964c457566 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 04:15:22 +0200 Subject: mwl8k: don't hardcode the number of transmit queues Use MWL8K_TX_QUEUES instead of a hardcoded "4" in a couple of places. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index cc0aa80ca87..0281e70cec8 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1080,17 +1080,17 @@ struct mwl8k_txq_info { }; static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, - struct mwl8k_txq_info txinfo[], - u32 num_queues) + struct mwl8k_txq_info *txinfo) { int count, desc, status; struct mwl8k_tx_queue *txq; struct mwl8k_tx_desc *tx_desc; int ndescs = 0; - memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info)); + memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info)); + spin_lock_bh(&priv->tx_lock); - for (count = 0; count < num_queues; count++) { + for (count = 0; count < MWL8K_TX_QUEUES; count++) { txq = priv->txq + count; txinfo[count].len = txq->tx_stats.len; txinfo[count].head = txq->tx_head; @@ -1135,7 +1135,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) spin_unlock_bh(&priv->tx_lock); if (count) { - struct mwl8k_txq_info txinfo[4]; + struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES]; int index; int newcount; @@ -1152,8 +1152,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n", __func__, __LINE__, delay_ms, count, newcount); - mwl8k_scan_tx_ring(priv, txinfo, 4); - for (index = 0; index < 4; index++) + mwl8k_scan_tx_ring(priv, txinfo); + for (index = 0; index < MWL8K_TX_QUEUES; index++) printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", index, -- cgit v1.2.3 From 361c55cfaddaa36f0997c5a96948ba5888bfb992 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 04:19:00 +0200 Subject: mwl8k: no need to hold ->tx_lock while setting the hardware interrupt mask Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0281e70cec8..177d92f0b87 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2768,9 +2768,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) printk(KERN_ERR "%s() timed out\n", __func__); /* Disable interrupts */ - spin_lock_irq(&priv->tx_lock); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - spin_unlock_irq(&priv->tx_lock); free_irq(priv->pdev->irq, hw); /* Stop finalize join worker */ @@ -3457,9 +3455,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, } /* Disable interrupts */ - spin_lock_irq(&priv->tx_lock); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - spin_unlock_irq(&priv->tx_lock); free_irq(priv->pdev->irq, hw); rc = ieee80211_register_hw(hw); @@ -3483,9 +3479,7 @@ err_stop_firmware: mwl8k_release_firmware(priv); err_free_irq: - spin_lock_irq(&priv->tx_lock); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - spin_unlock_irq(&priv->tx_lock); free_irq(priv->pdev->irq, hw); err_free_queues: -- cgit v1.2.3 From 7595d67a06466cc00e3aae1b86544278b57481ee Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 17 Aug 2009 23:59:40 +0200 Subject: mwl8k: implement idle mode Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 177d92f0b87..65eefe83502 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2854,6 +2854,12 @@ static int mwl8k_config_wt(struct work_struct *wt) struct mwl8k_priv *priv = hw->priv; int rc = 0; + if (conf->flags & IEEE80211_CONF_IDLE) { + mwl8k_cmd_802_11_radio_disable(hw); + priv->current_channel = NULL; + goto mwl8k_config_exit; + } + if (mwl8k_cmd_802_11_radio_enable(hw)) { rc = -EINVAL; goto mwl8k_config_exit; -- cgit v1.2.3 From 23b339062f247e0be84eaabb15e17b403c4388b6 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 05:21:04 +0200 Subject: mwl8k: mwl8k_txq_xmit() rework Various mwl8k_txq_xmit changes: - Extract the QoS field before adding the DMA header. - Only write to tx->status once, and only after all the other descriptor fields have been set. - Do all tx state manipulation under the tx spinlock. - Remove the priv->inconfig check, as all transmit queues will be frozen during config cycles, so we won't ever be asked to transmit if a config cycle is running. - Remove some more dead code. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 145 ++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 93 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 65eefe83502..88ba52e13af 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1257,46 +1257,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) { struct mwl8k_priv *priv = hw->priv; struct ieee80211_tx_info *tx_info; + struct mwl8k_vif *mwl8k_vif; struct ieee80211_hdr *wh; struct mwl8k_tx_queue *txq; struct mwl8k_tx_desc *tx; - struct mwl8k_dma_data *tr; - struct mwl8k_vif *mwl8k_vif; dma_addr_t dma; - u16 qos = 0; - bool qosframe = false, ampduframe = false; - bool mcframe = false, eapolframe = false; - bool amsduframe = false; - __le16 fc; + u32 txstatus; + u8 txdatarate; + u16 qos; - txq = priv->txq + index; - tx = txq->tx_desc_area + txq->tx_tail; - - BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); + wh = (struct ieee80211_hdr *)skb->data; + if (ieee80211_is_data_qos(wh->frame_control)) + qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); + else + qos = 0; - /* - * Append HW DMA header to start of packet. - */ mwl8k_add_dma_header(skb); + wh = &((struct mwl8k_dma_data *)skb->data)->wh; tx_info = IEEE80211_SKB_CB(skb); mwl8k_vif = MWL8K_VIF(tx_info->control.vif); - tr = (struct mwl8k_dma_data *)skb->data; - wh = &tr->wh; - fc = wh->frame_control; - qosframe = ieee80211_is_data_qos(fc); - mcframe = is_multicast_ether_addr(wh->addr1); - ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { u16 seqno = mwl8k_vif->seqno; + wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); wh->seq_ctrl |= cpu_to_le16(seqno << 4); mwl8k_vif->seqno = seqno++ % 4096; } - if (qosframe) - qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); + /* Setup firmware control bit fields for each frame type. */ + txstatus = 0; + txdatarate = 0; + if (ieee80211_is_mgmt(wh->frame_control) || + ieee80211_is_ctl(wh->frame_control)) { + txdatarate = 0; + qos = mwl8k_qos_setbit_eosp(qos); + /* Set Queue size to unspecified */ + qos = mwl8k_qos_setbit_qlen(qos, 0xff); + } else if (ieee80211_is_data(wh->frame_control)) { + txdatarate = 1; + if (is_multicast_ether_addr(wh->addr1)) + txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; + + /* Send pkt in an aggregate if AMPDU frame. */ + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) + qos = mwl8k_qos_setbit_ack(qos, + MWL8K_TXD_ACK_POLICY_BLOCKACK); + else + qos = mwl8k_qos_setbit_ack(qos, + MWL8K_TXD_ACK_POLICY_NORMAL); + + if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) + qos = mwl8k_qos_setbit_amsdu(qos); + } dma = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); @@ -1304,95 +1318,40 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) if (pci_dma_mapping_error(priv->pdev, dma)) { printk(KERN_DEBUG "%s: failed to dma map skb, " "dropping TX frame.\n", priv->name); - - if (skb != NULL) - dev_kfree_skb(skb); + dev_kfree_skb(skb); return NETDEV_TX_OK; } - /* Set desc header, cpu bit order. */ - tx->status = 0; - tx->data_rate = 0; - tx->tx_priority = index; - tx->qos_control = 0; - tx->rate_info = 0; - tx->peer_id = mwl8k_vif->peer_id; - - amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); - - /* Setup firmware control bit fields for each frame type. */ - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { - tx->data_rate = 0; - qos = mwl8k_qos_setbit_eosp(qos); - /* Set Queue size to unspecified */ - qos = mwl8k_qos_setbit_qlen(qos, 0xff); - } else if (ieee80211_is_data(fc)) { - tx->data_rate = 1; - if (mcframe) - tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX; + spin_lock_bh(&priv->tx_lock); - /* - * Tell firmware to not send EAPOL pkts in an - * aggregate. Verify against mac80211 tx path. If - * stack turns off AMPDU for an EAPOL frame this - * check will be removed. - */ - if (eapolframe) { - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_NORMAL); - } else { - /* Send pkt in an aggregate if AMPDU frame. */ - if (ampduframe) - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_BLOCKACK); - else - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_NORMAL); + txq = priv->txq + index; - if (amsduframe) - qos = mwl8k_qos_setbit_amsdu(qos); - } - } + BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); + txq->tx_skb[txq->tx_tail] = skb; - /* Convert to little endian */ + tx = txq->tx_desc_area + txq->tx_tail; + tx->data_rate = txdatarate; + tx->tx_priority = index; tx->qos_control = cpu_to_le16(qos); - tx->status = cpu_to_le32(tx->status); tx->pkt_phys_addr = cpu_to_le32(dma); tx->pkt_len = cpu_to_le16(skb->len); - - txq->tx_skb[txq->tx_tail] = skb; - - spin_lock_bh(&priv->tx_lock); - - tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK | - MWL8K_TXD_STATUS_FW_OWNED); + tx->rate_info = 0; + tx->peer_id = mwl8k_vif->peer_id; wmb(); + tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); + + txq->tx_stats.count++; txq->tx_stats.len++; priv->pending_tx_pkts++; - txq->tx_stats.count++; - txq->tx_tail++; + txq->tx_tail++; if (txq->tx_tail == MWL8K_TX_DESCS) txq->tx_tail = 0; + if (txq->tx_head == txq->tx_tail) ieee80211_stop_queue(hw, index); - if (priv->inconfig) { - /* - * Silently queue packet when we are in the middle of - * a config cycle. Notify firmware only if we are - * waiting for TXQs to empty. If a packet is sent - * before .config() is complete, perhaps it is better - * to drop the packet, as the channel is being changed - * and the packet will end up on the wrong channel. - */ - printk(KERN_ERR "%s(): WARNING TX activity while " - "in config\n", __func__); - - if (priv->tx_wait != NULL) - mwl8k_tx_start(priv); - } else - mwl8k_tx_start(priv); + mwl8k_tx_start(priv); spin_unlock_bh(&priv->tx_lock); -- cgit v1.2.3 From 950d5b0191dc3e71017f336017f75f6189f39f08 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 01:48:41 +0200 Subject: mwl8k: mwl8k_queue_work() cleanup Delete most of the mwl8k_work_struct fields and options, since most of them are unused or never changed from their defaults: - We always use priv->config_wq, so delete the wqueue argument from mwl8k_queue_work(). - MWL8K_WQ_SPIN and MWL8K_WQ_POST_REQUEST are never used, as all callers sleep for request completion, so sleep unconditionally. - MWL8K_WQ_FREE_WORKSTRUCT is never used. - MWL8K_WQ_TX_WAIT_EMPTY is always set, so assume it unconditionally. - timeout_ms/txwait_attempts/tx_timeout_ms are never changed from their defaults, so just hardcode these in the workqueue worker. - step is never used. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 204 +++++++------------------------------------ 1 file changed, 33 insertions(+), 171 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 88ba52e13af..7bbdca41831 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1113,7 +1113,7 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, return ndescs; } -static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) +static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; DECLARE_COMPLETION_ONSTACK(cmd_wait); @@ -1140,7 +1140,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) int newcount; timeout = wait_for_completion_timeout(&cmd_wait, - msecs_to_jiffies(delay_ms)); + msecs_to_jiffies(1000)); if (timeout) return 0; @@ -1149,8 +1149,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) newcount = mwl8k_txq_busy(priv); spin_unlock_bh(&priv->tx_lock); - printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n", - __func__, __LINE__, delay_ms, count, newcount); + printk(KERN_ERR "%s(%u) TIMEDOUT:1000ms Pend:%u-->%u\n", + __func__, __LINE__, count, newcount); mwl8k_scan_tx_ring(priv, txinfo); for (index = 0; index < MWL8K_TX_QUEUES; index++) @@ -2389,84 +2389,15 @@ struct mwl8k_work_struct { /* Result code. */ int rc; - - /* - * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX - * flags for explanation. Defaults to MWL8K_WQ_DEFAULT_OPTIONS. - */ - u32 options; - - /* Optional field. Defaults to MWL8K_CONFIG_TIMEOUT_MS. */ - unsigned long timeout_ms; - - /* Optional field. Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS. */ - u32 txwait_attempts; - - /* Optional field. Defaults to MWL8K_TXWAIT_MS. */ - u32 tx_timeout_ms; - u32 step; }; -/* Flags controlling behavior of config queue requests */ - -/* Caller spins while waiting for completion. */ -#define MWL8K_WQ_SPIN 0x00000001 - -/* Wait for TX queues to empty before proceeding with configuration. */ -#define MWL8K_WQ_TX_WAIT_EMPTY 0x00000002 - -/* Queue request and return immediately. */ -#define MWL8K_WQ_POST_REQUEST 0x00000004 - -/* - * Caller sleeps and waits for task complete notification. - * Do not use in atomic context. - */ -#define MWL8K_WQ_SLEEP 0x00000008 - -/* Free work struct when task is done. */ -#define MWL8K_WQ_FREE_WORKSTRUCT 0x00000010 - -/* - * Config request is queued and returns to caller imediately. Use - * this in atomic context. Work struct is freed by mwl8k_queue_work() - * when this flag is set. - */ -#define MWL8K_WQ_QUEUE_ONLY (MWL8K_WQ_POST_REQUEST | \ - MWL8K_WQ_FREE_WORKSTRUCT) - -/* Default work queue behavior is to sleep and wait for tx completion. */ -#define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY) - -/* - * Default config request timeout. Add adjustments to make sure the - * config thread waits long enough for both tx wait and cmd wait before - * timing out. - */ - -/* Time to wait for all TXQs to drain. TX Doorbell is pressed each time. */ -#define MWL8K_TXWAIT_TIMEOUT_MS 1000 - -/* Default number of TX wait attempts. */ -#define MWL8K_WQ_TXWAIT_ATTEMPTS 4 - -/* Total time to wait for TXQ to drain. */ -#define MWL8K_TXWAIT_MS (MWL8K_TXWAIT_TIMEOUT_MS * \ - MWL8K_WQ_TXWAIT_ATTEMPTS) - -/* Scheduling slop. */ -#define MWL8K_OS_SCHEDULE_OVERHEAD_MS 200 - -#define MWL8K_CONFIG_TIMEOUT_MS (MWL8K_CMD_TIMEOUT_MS + \ - MWL8K_TXWAIT_MS + \ - MWL8K_OS_SCHEDULE_OVERHEAD_MS) - static void mwl8k_config_thread(struct work_struct *wt) { struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt; struct ieee80211_hw *hw = worker->hw; struct mwl8k_priv *priv = hw->priv; int rc = 0; + int iter; spin_lock_irq(&priv->tx_lock); priv->inconfig = true; @@ -2479,44 +2410,16 @@ static void mwl8k_config_thread(struct work_struct *wt) * reconfiguration. This avoids interrupting any in-flight * DMA transfers to the hardware. */ - if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) { - u32 timeout; - u32 time_remaining; - u32 iter; - u32 tx_wait_attempts = worker->txwait_attempts; - - time_remaining = worker->tx_timeout_ms; - if (!tx_wait_attempts) - tx_wait_attempts = 1; - - timeout = worker->tx_timeout_ms/tx_wait_attempts; - if (!timeout) - timeout = 1; - - iter = tx_wait_attempts; - do { - int wait_time; - - if (time_remaining > timeout) { - time_remaining -= timeout; - wait_time = timeout; - } else - wait_time = time_remaining; - - if (!wait_time) - wait_time = 1; - - rc = mwl8k_tx_wait_empty(hw, wait_time); - if (rc) - printk(KERN_ERR "%s() txwait timeout=%ums " - "Retry:%u/%u\n", __func__, timeout, - tx_wait_attempts - iter + 1, - tx_wait_attempts); + iter = 4; + do { + rc = mwl8k_tx_wait_empty(hw); + if (rc) + printk(KERN_ERR "%s() txwait timeout=1000ms " + "Retry:%u/%u\n", __func__, 4 - iter + 1, 4); + } while (rc && --iter); - } while (rc && --iter); + rc = iter ? 0 : -ETIMEDOUT; - rc = iter ? 0 : -ETIMEDOUT; - } if (!rc) rc = worker->wfunc(wt); @@ -2525,65 +2428,39 @@ static void mwl8k_config_thread(struct work_struct *wt) if (priv->pending_tx_pkts && priv->radio_on) mwl8k_tx_start(priv); spin_unlock_irq(&priv->tx_lock); + ieee80211_wake_queues(hw); worker->rc = rc; - if (worker->options & MWL8K_WQ_SLEEP) - complete(worker->cmd_wait); - - if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT) - kfree(wt); + complete(worker->cmd_wait); } static int mwl8k_queue_work(struct ieee80211_hw *hw, struct mwl8k_work_struct *worker, - struct workqueue_struct *wqueue, int (*wfunc)(struct work_struct *w)) { + struct mwl8k_priv *priv = hw->priv; unsigned long timeout = 0; int rc = 0; DECLARE_COMPLETION_ONSTACK(cmd_wait); - if (!worker->timeout_ms) - worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS; - - if (!worker->options) - worker->options = MWL8K_WQ_DEFAULT_OPTIONS; - - if (!worker->txwait_attempts) - worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS; - - if (!worker->tx_timeout_ms) - worker->tx_timeout_ms = MWL8K_TXWAIT_MS; - worker->hw = hw; worker->cmd_wait = &cmd_wait; worker->rc = 1; worker->wfunc = wfunc; INIT_WORK(&worker->wt, mwl8k_config_thread); - queue_work(wqueue, &worker->wt); + queue_work(priv->config_wq, &worker->wt); - if (worker->options & MWL8K_WQ_POST_REQUEST) { - rc = 0; - } else { - if (worker->options & MWL8K_WQ_SPIN) { - timeout = worker->timeout_ms; - while (timeout && (worker->rc > 0)) { - mdelay(1); - timeout--; - } - } else if (worker->options & MWL8K_WQ_SLEEP) - timeout = wait_for_completion_timeout(&cmd_wait, - msecs_to_jiffies(worker->timeout_ms)); + timeout = wait_for_completion_timeout(&cmd_wait, + msecs_to_jiffies(10000)); - if (timeout) - rc = worker->rc; - else { - cancel_work_sync(&worker->wt); - rc = -ETIMEDOUT; - } + if (timeout) + rc = worker->rc; + else { + cancel_work_sync(&worker->wt); + rc = -ETIMEDOUT; } return rc; @@ -2669,8 +2546,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) goto mwl8k_start_disable_irq; } - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, mwl8k_start_wt); + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_start_wt); kfree(worker); if (!rc) return rc; @@ -2720,8 +2596,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) if (worker == NULL) return; - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, mwl8k_stop_wt); + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_stop_wt); kfree(worker); if (rc == -ETIMEDOUT) printk(KERN_ERR "%s() timed out\n", __func__); @@ -2849,15 +2724,14 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) { int rc = 0; struct mwl8k_config_worker *worker; - struct mwl8k_priv *priv = hw->priv; worker = kzalloc(sizeof(*worker), GFP_KERNEL); if (worker == NULL) return -ENOMEM; worker->changed = changed; - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, mwl8k_config_wt); + + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_config_wt); if (rc == -ETIMEDOUT) { printk(KERN_ERR "%s() timed out.\n", __func__); rc = -EINVAL; @@ -2950,7 +2824,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct mwl8k_bss_info_changed_worker *worker; - struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); int rc; @@ -2967,9 +2840,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, worker->vif = vif; worker->info = info; worker->changed = changed; - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, - mwl8k_bss_info_changed_wt); + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_bss_info_changed_wt); kfree(worker); if (rc == -ETIMEDOUT) printk(KERN_ERR "%s() timed out\n", __func__); @@ -3028,7 +2899,6 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { - struct mwl8k_priv *priv = hw->priv; struct mwl8k_configure_filter_worker *worker; /* Clear unsupported feature flags */ @@ -3045,8 +2915,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, worker->total_flags = *total_flags; worker->multicast_adr_cmd = (void *)(unsigned long)multicast; - mwl8k_queue_work(hw, &worker->header, priv->config_wq, - mwl8k_configure_filter_wt); + mwl8k_queue_work(hw, &worker->header, mwl8k_configure_filter_wt); } struct mwl8k_set_rts_threshold_worker { @@ -3072,7 +2941,6 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { int rc; struct mwl8k_set_rts_threshold_worker *worker; - struct mwl8k_priv *priv = hw->priv; worker = kzalloc(sizeof(*worker), GFP_KERNEL); if (worker == NULL) @@ -3080,9 +2948,7 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) worker->value = value; - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, - mwl8k_set_rts_threshold_wt); + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_set_rts_threshold_wt); kfree(worker); if (rc == -ETIMEDOUT) { @@ -3130,7 +2996,6 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, { int rc; struct mwl8k_conf_tx_worker *worker; - struct mwl8k_priv *priv = hw->priv; worker = kzalloc(sizeof(*worker), GFP_KERNEL); if (worker == NULL) @@ -3138,8 +3003,7 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, worker->queue = queue; worker->params = params; - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, mwl8k_conf_tx_wt); + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_conf_tx_wt); kfree(worker); if (rc == -ETIMEDOUT) { printk(KERN_ERR "%s() timed out\n", __func__); @@ -3183,15 +3047,13 @@ static int mwl8k_get_stats(struct ieee80211_hw *hw, { int rc; struct mwl8k_get_stats_worker *worker; - struct mwl8k_priv *priv = hw->priv; worker = kzalloc(sizeof(*worker), GFP_KERNEL); if (worker == NULL) return -ENOMEM; worker->stats = stats; - rc = mwl8k_queue_work(hw, &worker->header, - priv->config_wq, mwl8k_get_stats_wt); + rc = mwl8k_queue_work(hw, &worker->header, mwl8k_get_stats_wt); kfree(worker); if (rc == -ETIMEDOUT) { -- cgit v1.2.3 From 618952a7b19b796fce98364fb26551cbe3e16a75 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 03:18:01 +0200 Subject: mwl8k: fix firmware command serialisation The current mwl8k_priv->fw_lock spinlock doesn't actually protect against multiple commands being submitted at once, as it is not kept held over the entire firmware command submission. And since waiting for command completion sleeps, we can't use a spinlock anyway. To fix mwl8k firmware command serialisation properly, we have the following requirements: - Some commands require that the packet transmit path is idle when the command is issued. (For simplicity, we'll just quiesce the transmit path for every command.) - There are certain sequences of commands that need to be issued to the hardware sequentially, with no other intervening commands. This leads to an implementation of a "firmware lock" as a mutex that can be taken recursively, and which is taken by both the low-level command submission function (mwl8k_post_cmd) as well as any users of that function that require issuing of an atomic sequence of commands, and quiesces the transmit path whenever it's taken. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 154 +++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 65 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 7bbdca41831..93b92680d07 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -139,13 +139,18 @@ struct mwl8k_priv { struct pci_dev *pdev; u8 name[16]; - /* firmware access lock */ - spinlock_t fw_lock; /* firmware files and meta data */ struct mwl8k_firmware fw; u32 part_num; + /* firmware access */ + struct mutex fw_mutex; + struct task_struct *fw_mutex_owner; + int fw_mutex_depth; + struct completion *tx_wait; + struct completion *hostcmd_wait; + /* lock held over TX and TX reap */ spinlock_t tx_lock; @@ -179,9 +184,6 @@ struct mwl8k_priv { bool radio_short_preamble; bool wmm_enabled; - /* Set if PHY config is in progress */ - bool inconfig; - /* XXX need to convert this to handle multiple interfaces */ bool capture_beacon; u8 capture_bssid[ETH_ALEN]; @@ -200,8 +202,6 @@ struct mwl8k_priv { /* Work thread to serialize configuration requests */ struct workqueue_struct *config_wq; - struct completion *hostcmd_wait; - struct completion *tx_wait; }; /* Per interface specific private data */ @@ -1113,6 +1113,9 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, return ndescs; } +/* + * Must be called with hw->fw_mutex held and tx queues stopped. + */ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; @@ -1122,9 +1125,6 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) might_sleep(); - if (priv->tx_wait != NULL) - printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n"); - spin_lock_bh(&priv->tx_lock); count = mwl8k_txq_busy(priv); if (count) { @@ -1140,7 +1140,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) int newcount; timeout = wait_for_completion_timeout(&cmd_wait, - msecs_to_jiffies(1000)); + msecs_to_jiffies(5000)); if (timeout) return 0; @@ -1149,7 +1149,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) newcount = mwl8k_txq_busy(priv); spin_unlock_bh(&priv->tx_lock); - printk(KERN_ERR "%s(%u) TIMEDOUT:1000ms Pend:%u-->%u\n", + printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n", __func__, __LINE__, count, newcount); mwl8k_scan_tx_ring(priv, txinfo); @@ -1228,10 +1228,10 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) ieee80211_tx_status_irqsafe(hw, skb); - wake = !priv->inconfig && priv->radio_on; + wake = 1; } - if (wake) + if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) ieee80211_wake_queue(hw, index); } @@ -1359,6 +1359,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) } +/* + * Firmware access. + * + * We have the following requirements for issuing firmware commands: + * - Some commands require that the packet transmit path is idle when + * the command is issued. (For simplicity, we'll just quiesce the + * transmit path for every command.) + * - There are certain sequences of commands that need to be issued to + * the hardware sequentially, with no other intervening commands. + * + * This leads to an implementation of a "firmware lock" as a mutex that + * can be taken recursively, and which is taken by both the low-level + * command submission function (mwl8k_post_cmd) as well as any users of + * that function that require issuing of an atomic sequence of commands, + * and quiesces the transmit path whenever it's taken. + */ +static int mwl8k_fw_lock(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + + if (priv->fw_mutex_owner != current) { + int rc; + + mutex_lock(&priv->fw_mutex); + ieee80211_stop_queues(hw); + + rc = mwl8k_tx_wait_empty(hw); + if (rc) { + ieee80211_wake_queues(hw); + mutex_unlock(&priv->fw_mutex); + + return rc; + } + + priv->fw_mutex_owner = current; + } + + priv->fw_mutex_depth++; + + return 0; +} + +static void mwl8k_fw_unlock(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + + if (!--priv->fw_mutex_depth) { + ieee80211_wake_queues(hw); + priv->fw_mutex_owner = NULL; + mutex_unlock(&priv->fw_mutex); + } +} + + /* * Command processing. */ @@ -1384,28 +1438,28 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) if (pci_dma_mapping_error(priv->pdev, dma_addr)) return -ENOMEM; - if (priv->hostcmd_wait != NULL) - printk(KERN_ERR "WARNING host command in progress\n"); + rc = mwl8k_fw_lock(hw); + if (rc) + return rc; - spin_lock_irq(&priv->fw_lock); priv->hostcmd_wait = &cmd_wait; iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); iowrite32(MWL8K_H2A_INT_DOORBELL, regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); iowrite32(MWL8K_H2A_INT_DUMMY, regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - spin_unlock_irq(&priv->fw_lock); timeout = wait_for_completion_timeout(&cmd_wait, msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); + priv->hostcmd_wait = NULL; + + mwl8k_fw_unlock(hw); + pci_unmap_single(priv->pdev, dma_addr, dma_size, PCI_DMA_BIDIRECTIONAL); if (!timeout) { - spin_lock_irq(&priv->fw_lock); - priv->hostcmd_wait = NULL; - spin_unlock_irq(&priv->fw_lock); printk(KERN_ERR "%s: Command %s timeout after %u ms\n", priv->name, mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), @@ -2336,17 +2390,14 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) } if (status & MWL8K_A2H_INT_OPC_DONE) { - if (priv->hostcmd_wait != NULL) { + if (priv->hostcmd_wait != NULL) complete(priv->hostcmd_wait); - priv->hostcmd_wait = NULL; - } } if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { - if (!priv->inconfig && - priv->radio_on && - mwl8k_txq_busy(priv)) - mwl8k_tx_start(priv); + if (!mutex_is_locked(&priv->fw_mutex) && + priv->radio_on && mwl8k_txq_busy(priv)) + mwl8k_tx_start(priv); } return IRQ_HANDLED; @@ -2395,41 +2446,13 @@ static void mwl8k_config_thread(struct work_struct *wt) { struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt; struct ieee80211_hw *hw = worker->hw; - struct mwl8k_priv *priv = hw->priv; int rc = 0; - int iter; - spin_lock_irq(&priv->tx_lock); - priv->inconfig = true; - spin_unlock_irq(&priv->tx_lock); - - ieee80211_stop_queues(hw); - - /* - * Wait for host queues to drain before doing PHY - * reconfiguration. This avoids interrupting any in-flight - * DMA transfers to the hardware. - */ - iter = 4; - do { - rc = mwl8k_tx_wait_empty(hw); - if (rc) - printk(KERN_ERR "%s() txwait timeout=1000ms " - "Retry:%u/%u\n", __func__, 4 - iter + 1, 4); - } while (rc && --iter); - - rc = iter ? 0 : -ETIMEDOUT; - - if (!rc) + rc = mwl8k_fw_lock(hw); + if (!rc) { rc = worker->wfunc(wt); - - spin_lock_irq(&priv->tx_lock); - priv->inconfig = false; - if (priv->pending_tx_pkts && priv->radio_on) - mwl8k_tx_start(priv); - spin_unlock_irq(&priv->tx_lock); - - ieee80211_wake_queues(hw); + mwl8k_fw_unlock(hw); + } worker->rc = rc; complete(worker->cmd_wait); @@ -3145,15 +3168,10 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv = hw->priv; priv->hw = hw; priv->pdev = pdev; - priv->hostcmd_wait = NULL; - priv->tx_wait = NULL; - priv->inconfig = false; priv->wmm_enabled = false; priv->pending_tx_pkts = 0; strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); - spin_lock_init(&priv->fw_lock); - SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); @@ -3219,6 +3237,12 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, goto err_iounmap; rxq_refill(hw, 0, INT_MAX); + mutex_init(&priv->fw_mutex); + priv->fw_mutex_owner = NULL; + priv->fw_mutex_depth = 0; + priv->tx_wait = NULL; + priv->hostcmd_wait = NULL; + spin_lock_init(&priv->tx_lock); for (i = 0; i < MWL8K_TX_QUEUES; i++) { -- cgit v1.2.3 From 2ec610cb6d57032cdab89781e37ed3e442c73367 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:11:37 +0200 Subject: mwl8k: get rid of mwl8k_start() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 105 +++++++++++-------------------------------- 1 file changed, 27 insertions(+), 78 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 93b92680d07..7b7007da873 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2489,104 +2489,53 @@ static int mwl8k_queue_work(struct ieee80211_hw *hw, return rc; } -struct mwl8k_start_worker { - struct mwl8k_work_struct header; -}; - -static int mwl8k_start_wt(struct work_struct *wt) -{ - struct mwl8k_start_worker *worker = (struct mwl8k_start_worker *)wt; - struct ieee80211_hw *hw = worker->header.hw; - struct mwl8k_priv *priv = hw->priv; - int rc = 0; - - if (priv->vif != NULL) { - rc = -EIO; - goto mwl8k_start_exit; - } - - /* Turn on radio */ - if (mwl8k_cmd_802_11_radio_enable(hw)) { - rc = -EIO; - goto mwl8k_start_exit; - } - - /* Purge TX/RX HW queues */ - if (mwl8k_cmd_set_pre_scan(hw)) { - rc = -EIO; - goto mwl8k_start_exit; - } - - if (mwl8k_cmd_set_post_scan(hw, "\x00\x00\x00\x00\x00\x00")) { - rc = -EIO; - goto mwl8k_start_exit; - } - - /* Enable firmware rate adaptation */ - if (mwl8k_cmd_setrateadaptmode(hw, 0)) { - rc = -EIO; - goto mwl8k_start_exit; - } - - /* Disable WMM. WMM gets enabled when stack sends WMM parms */ - if (mwl8k_set_wmm(hw, 0)) { - rc = -EIO; - goto mwl8k_start_exit; - } - - /* Disable sniffer mode */ - if (mwl8k_enable_sniffer(hw, 0)) - rc = -EIO; - -mwl8k_start_exit: - return rc; -} - static int mwl8k_start(struct ieee80211_hw *hw) { - struct mwl8k_start_worker *worker; struct mwl8k_priv *priv = hw->priv; int rc; - /* Enable tx reclaim tasklet */ - tasklet_enable(&priv->tx_reclaim_task); - rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { printk(KERN_ERR "%s: failed to register IRQ handler\n", priv->name); - rc = -EIO; - goto mwl8k_start_disable_tasklet; + return -EIO; } + /* Enable tx reclaim tasklet */ + tasklet_enable(&priv->tx_reclaim_task); + /* Enable interrupts */ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) { - rc = -ENOMEM; - goto mwl8k_start_disable_irq; - } + rc = mwl8k_fw_lock(hw); + if (!rc) { + rc = mwl8k_cmd_802_11_radio_enable(hw); - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_start_wt); - kfree(worker); - if (!rc) - return rc; + if (!rc) + rc = mwl8k_cmd_set_pre_scan(hw); - if (rc == -ETIMEDOUT) - printk(KERN_ERR "%s() timed out\n", __func__); + if (!rc) + rc = mwl8k_cmd_set_post_scan(hw, + "\x00\x00\x00\x00\x00\x00"); - rc = -EIO; + if (!rc) + rc = mwl8k_cmd_setrateadaptmode(hw, 0); -mwl8k_start_disable_irq: - spin_lock_irq(&priv->tx_lock); - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - spin_unlock_irq(&priv->tx_lock); - free_irq(priv->pdev->irq, hw); + if (!rc) + rc = mwl8k_set_wmm(hw, 0); -mwl8k_start_disable_tasklet: - tasklet_disable(&priv->tx_reclaim_task); + if (!rc) + rc = mwl8k_enable_sniffer(hw, 0); + + mwl8k_fw_unlock(hw); + } + + if (rc) { + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + free_irq(priv->pdev->irq, hw); + tasklet_disable(&priv->tx_reclaim_task); + } return rc; } -- cgit v1.2.3 From d3cea0b85a31a98630c6fcf7373d486db9612a10 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:15:49 +0200 Subject: mwl8k: get rid of mwl8k_stop() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 7b7007da873..b88b1e001f0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2540,39 +2540,15 @@ static int mwl8k_start(struct ieee80211_hw *hw) return rc; } -struct mwl8k_stop_worker { - struct mwl8k_work_struct header; -}; - -static int mwl8k_stop_wt(struct work_struct *wt) -{ - struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt; - struct ieee80211_hw *hw = worker->header.hw; - - return mwl8k_cmd_802_11_radio_disable(hw); -} - static void mwl8k_stop(struct ieee80211_hw *hw) { - int rc; - struct mwl8k_stop_worker *worker; struct mwl8k_priv *priv = hw->priv; int i; - if (priv->vif != NULL) - return; + mwl8k_cmd_802_11_radio_disable(hw); ieee80211_stop_queues(hw); - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) - return; - - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_stop_wt); - kfree(worker); - if (rc == -ETIMEDOUT) - printk(KERN_ERR "%s() timed out\n", __func__); - /* Disable interrupts */ iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); free_irq(priv->pdev->irq, hw); -- cgit v1.2.3 From ee03a93241eb954d669fb795b4e5c0eec92eef22 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:19:37 +0200 Subject: mwl8k: get rid of mwl8k_config() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 72 ++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 52 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b88b1e001f0..77e280a00a5 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2622,77 +2622,45 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, priv->vif = NULL; } -struct mwl8k_config_worker { - struct mwl8k_work_struct header; - u32 changed; -}; - -static int mwl8k_config_wt(struct work_struct *wt) +static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) { - struct mwl8k_config_worker *worker = - (struct mwl8k_config_worker *)wt; - struct ieee80211_hw *hw = worker->header.hw; struct ieee80211_conf *conf = &hw->conf; struct mwl8k_priv *priv = hw->priv; - int rc = 0; + int rc; if (conf->flags & IEEE80211_CONF_IDLE) { mwl8k_cmd_802_11_radio_disable(hw); priv->current_channel = NULL; - goto mwl8k_config_exit; + return 0; } - if (mwl8k_cmd_802_11_radio_enable(hw)) { - rc = -EINVAL; - goto mwl8k_config_exit; - } + rc = mwl8k_fw_lock(hw); + if (rc) + return rc; - priv->current_channel = conf->channel; + rc = mwl8k_cmd_802_11_radio_enable(hw); + if (rc) + goto out; - if (mwl8k_cmd_set_rf_channel(hw, conf->channel)) { - rc = -EINVAL; - goto mwl8k_config_exit; - } + rc = mwl8k_cmd_set_rf_channel(hw, conf->channel); + if (rc) + goto out; + + priv->current_channel = conf->channel; if (conf->power_level > 18) conf->power_level = 18; - if (mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level)) { - rc = -EINVAL; - goto mwl8k_config_exit; - } + rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); + if (rc) + goto out; if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) rc = -EINVAL; -mwl8k_config_exit: - return rc; -} - -static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) -{ - int rc = 0; - struct mwl8k_config_worker *worker; - - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) - return -ENOMEM; - - worker->changed = changed; - - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_config_wt); - if (rc == -ETIMEDOUT) { - printk(KERN_ERR "%s() timed out.\n", __func__); - rc = -EINVAL; - } - - kfree(worker); +out: + mwl8k_fw_unlock(hw); - /* - * mac80211 will crash on anything other than -EINVAL on - * error. Looks like wireless extensions which calls mac80211 - * may be the actual culprit... - */ - return rc ? -EINVAL : 0; + return rc; } struct mwl8k_bss_info_changed_worker { -- cgit v1.2.3 From 3a980d0a505161b99fc936827cb28ec8eb853284 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:21:46 +0200 Subject: mwl8k: get rid of mwl8k_bss_info_changed() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 101 ++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 63 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 77e280a00a5..d5a46a917cf 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2663,58 +2663,62 @@ out: return rc; } -struct mwl8k_bss_info_changed_worker { - struct mwl8k_work_struct header; - struct ieee80211_vif *vif; - struct ieee80211_bss_conf *info; - u32 changed; -}; - -static int mwl8k_bss_info_changed_wt(struct work_struct *wt) +static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) { - struct mwl8k_bss_info_changed_worker *worker = - (struct mwl8k_bss_info_changed_worker *)wt; - struct ieee80211_hw *hw = worker->header.hw; - struct ieee80211_vif *vif = worker->vif; - struct ieee80211_bss_conf *info = worker->info; - u32 changed; - int rc; - struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); + int rc; + + if (changed & BSS_CHANGED_BSSID) + memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); + + if ((changed & BSS_CHANGED_ASSOC) == 0) + return; - changed = worker->changed; priv->capture_beacon = false; + rc = mwl8k_fw_lock(hw); + if (!rc) + return; + if (info->assoc) { memcpy(&mwl8k_vif->bss_info, info, sizeof(struct ieee80211_bss_conf)); /* Install rates */ - if (mwl8k_update_rateset(hw, vif)) - goto mwl8k_bss_info_changed_exit; + rc = mwl8k_update_rateset(hw, vif); + if (rc) + goto out; /* Turn on rate adaptation */ - if (mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, - MWL8K_UCAST_RATE, NULL)) - goto mwl8k_bss_info_changed_exit; + rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, + MWL8K_UCAST_RATE, NULL); + if (rc) + goto out; /* Set radio preamble */ - if (mwl8k_set_radio_preamble(hw, info->use_short_preamble)) - goto mwl8k_bss_info_changed_exit; + rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); + if (rc) + goto out; /* Set slot time */ - if (mwl8k_cmd_set_slot(hw, info->use_short_slot)) - goto mwl8k_bss_info_changed_exit; + rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); + if (rc) + goto out; /* Update peer rate info */ - if (mwl8k_cmd_update_sta_db(hw, vif, - MWL8K_STA_DB_MODIFY_ENTRY)) - goto mwl8k_bss_info_changed_exit; + rc = mwl8k_cmd_update_sta_db(hw, vif, + MWL8K_STA_DB_MODIFY_ENTRY); + if (rc) + goto out; /* Set AID */ - if (mwl8k_cmd_set_aid(hw, vif)) - goto mwl8k_bss_info_changed_exit; + rc = mwl8k_cmd_set_aid(hw, vif); + if (rc) + goto out; /* * Finalize the join. Tell rx handler to process @@ -2723,43 +2727,14 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt) memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); priv->capture_beacon = true; } else { - mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); + rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); memset(&mwl8k_vif->bss_info, 0, sizeof(struct ieee80211_bss_conf)); memset(mwl8k_vif->bssid, 0, ETH_ALEN); } -mwl8k_bss_info_changed_exit: - rc = 0; - return rc; -} - -static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct mwl8k_bss_info_changed_worker *worker; - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - int rc; - - if (changed & BSS_CHANGED_BSSID) - memcpy(mv_vif->bssid, info->bssid, ETH_ALEN); - - if ((changed & BSS_CHANGED_ASSOC) == 0) - return; - - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) - return; - - worker->vif = vif; - worker->info = info; - worker->changed = changed; - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_bss_info_changed_wt); - kfree(worker); - if (rc == -ETIMEDOUT) - printk(KERN_ERR "%s() timed out\n", __func__); +out: + mwl8k_fw_unlock(hw); } static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, -- cgit v1.2.3 From 733d3067d3fb168fbbd008cb0ebf5ad2027030f3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:24:15 +0200 Subject: mwl8k: get rid of mwl8k_set_rts_threshold() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 42 +++--------------------------------------- 1 file changed, 3 insertions(+), 39 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d5a46a917cf..3129c577388 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1970,7 +1970,7 @@ struct mwl8k_cmd_rts_threshold { } __attribute__((packed)); static int mwl8k_rts_threshold(struct ieee80211_hw *hw, - u16 action, u16 *threshold) + u16 action, u16 threshold) { struct mwl8k_cmd_rts_threshold *cmd; int rc; @@ -1982,7 +1982,7 @@ static int mwl8k_rts_threshold(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(action); - cmd->threshold = cpu_to_le16(*threshold); + cmd->threshold = cpu_to_le16(threshold); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2809,45 +2809,9 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, mwl8k_queue_work(hw, &worker->header, mwl8k_configure_filter_wt); } -struct mwl8k_set_rts_threshold_worker { - struct mwl8k_work_struct header; - u32 value; -}; - -static int mwl8k_set_rts_threshold_wt(struct work_struct *wt) -{ - struct mwl8k_set_rts_threshold_worker *worker = - (struct mwl8k_set_rts_threshold_worker *)wt; - - struct ieee80211_hw *hw = worker->header.hw; - u16 threshold = (u16)(worker->value); - int rc; - - rc = mwl8k_rts_threshold(hw, MWL8K_CMD_SET, &threshold); - - return rc; -} - static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { - int rc; - struct mwl8k_set_rts_threshold_worker *worker; - - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) - return -ENOMEM; - - worker->value = value; - - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_set_rts_threshold_wt); - kfree(worker); - - if (rc == -ETIMEDOUT) { - printk(KERN_ERR "%s() timed out\n", __func__); - rc = -EINVAL; - } - - return rc; + return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); } struct mwl8k_conf_tx_worker { -- cgit v1.2.3 From 3e4f542cfbf5a60f2295b2de9a31bdd14beb7b4a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:25:59 +0200 Subject: mwl8k: get rid of mwl8k_conf_tx() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 57 +++++++++++--------------------------------- 1 file changed, 14 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 3129c577388..5ce2d362e07 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2814,56 +2814,27 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); } -struct mwl8k_conf_tx_worker { - struct mwl8k_work_struct header; - u16 queue; - const struct ieee80211_tx_queue_params *params; -}; - -static int mwl8k_conf_tx_wt(struct work_struct *wt) -{ - struct mwl8k_conf_tx_worker *worker = - (struct mwl8k_conf_tx_worker *)wt; - - struct ieee80211_hw *hw = worker->header.hw; - u16 queue = worker->queue; - const struct ieee80211_tx_queue_params *params = worker->params; - - struct mwl8k_priv *priv = hw->priv; - int rc = 0; - - if (!priv->wmm_enabled) { - if (mwl8k_set_wmm(hw, 1)) { - rc = -EINVAL; - goto mwl8k_conf_tx_exit; - } - } - - if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min, - params->cw_max, params->aifs, params->txop)) - rc = -EINVAL; -mwl8k_conf_tx_exit: - return rc; -} - static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { + struct mwl8k_priv *priv = hw->priv; int rc; - struct mwl8k_conf_tx_worker *worker; - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) - return -ENOMEM; + rc = mwl8k_fw_lock(hw); + if (!rc) { + if (!priv->wmm_enabled) + rc = mwl8k_set_wmm(hw, 1); - worker->queue = queue; - worker->params = params; - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_conf_tx_wt); - kfree(worker); - if (rc == -ETIMEDOUT) { - printk(KERN_ERR "%s() timed out\n", __func__); - rc = -EINVAL; + if (!rc) + rc = mwl8k_set_edca_params(hw, queue, + params->cw_min, + params->cw_max, + params->aifs, + params->txop); + + mwl8k_fw_unlock(hw); } + return rc; } -- cgit v1.2.3 From 954ef509cc7d795ccd69fa2e01539297e9a003a0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 17 Jul 2009 07:26:27 +0200 Subject: mwl8k: get rid of mwl8k_get_stats() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 5ce2d362e07..29712bd95af 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2852,42 +2852,14 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, sizeof(struct ieee80211_tx_queue_stats)); } spin_unlock_bh(&priv->tx_lock); - return 0; -} - -struct mwl8k_get_stats_worker { - struct mwl8k_work_struct header; - struct ieee80211_low_level_stats *stats; -}; -static int mwl8k_get_stats_wt(struct work_struct *wt) -{ - struct mwl8k_get_stats_worker *worker = - (struct mwl8k_get_stats_worker *)wt; - - return mwl8k_cmd_802_11_get_stat(worker->header.hw, worker->stats); + return 0; } static int mwl8k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - int rc; - struct mwl8k_get_stats_worker *worker; - - worker = kzalloc(sizeof(*worker), GFP_KERNEL); - if (worker == NULL) - return -ENOMEM; - - worker->stats = stats; - rc = mwl8k_queue_work(hw, &worker->header, mwl8k_get_stats_wt); - - kfree(worker); - if (rc == -ETIMEDOUT) { - printk(KERN_ERR "%s() timed out\n", __func__); - rc = -EINVAL; - } - - return rc; + return mwl8k_cmd_802_11_get_stat(hw, stats); } static const struct ieee80211_ops mwl8k_ops = { -- cgit v1.2.3 From e6935ea10485f34b82d16f8dff9aa2bdf32ab4bf Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 04:06:20 +0200 Subject: mwl8k: get rid of mwl8k_configure_filter() workqueue use Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 65 ++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 45 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 29712bd95af..43e5dd19b66 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2747,26 +2747,23 @@ static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, return (unsigned long)cmd; } -struct mwl8k_configure_filter_worker { - struct mwl8k_work_struct header; - unsigned int changed_flags; - unsigned int total_flags; +static void mwl8k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_pkt *multicast_adr_cmd; -}; -#define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC + /* Clear unsupported feature flags */ + *total_flags &= FIF_BCN_PRBRESP_PROMISC; -static int mwl8k_configure_filter_wt(struct work_struct *wt) -{ - struct mwl8k_configure_filter_worker *worker = - (struct mwl8k_configure_filter_worker *)wt; - struct ieee80211_hw *hw = worker->header.hw; - struct mwl8k_priv *priv = hw->priv; - int rc = 0; + if (mwl8k_fw_lock(hw)) + return; - if (worker->changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (worker->total_flags & FIF_BCN_PRBRESP_PROMISC) - rc = mwl8k_cmd_set_pre_scan(hw); + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + mwl8k_cmd_set_pre_scan(hw); else { u8 *bssid; @@ -2774,39 +2771,17 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) if (priv->vif != NULL) bssid = MWL8K_VIF(priv->vif)->bssid; - rc = mwl8k_cmd_set_post_scan(hw, bssid); + mwl8k_cmd_set_post_scan(hw, bssid); } } - if (!rc && worker->multicast_adr_cmd != NULL) - rc = mwl8k_post_cmd(hw, worker->multicast_adr_cmd); - kfree(worker->multicast_adr_cmd); - - return rc; -} - -static void mwl8k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct mwl8k_configure_filter_worker *worker; - - /* Clear unsupported feature flags */ - *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; - - if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS)) - return; - - worker = kzalloc(sizeof(*worker), GFP_ATOMIC); - if (worker == NULL) - return; - - worker->changed_flags = changed_flags; - worker->total_flags = *total_flags; - worker->multicast_adr_cmd = (void *)(unsigned long)multicast; + multicast_adr_cmd = (void *)(unsigned long)multicast; + if (multicast_adr_cmd != NULL) { + mwl8k_post_cmd(hw, multicast_adr_cmd); + kfree(multicast_adr_cmd); + } - mwl8k_queue_work(hw, &worker->header, mwl8k_configure_filter_wt); + mwl8k_fw_unlock(hw); } static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -- cgit v1.2.3 From ab565790cb5ca3d00db0af9c2a8eb95e16054c29 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 04:08:01 +0200 Subject: mwl8k: remove mwl8k_queue_work() Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 64 -------------------------------------------- 1 file changed, 64 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 43e5dd19b66..a634b565018 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2425,70 +2425,6 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return rc; } -struct mwl8k_work_struct { - /* Initialized by mwl8k_queue_work(). */ - struct work_struct wt; - - /* Required field passed in to mwl8k_queue_work(). */ - struct ieee80211_hw *hw; - - /* Required field passed in to mwl8k_queue_work(). */ - int (*wfunc)(struct work_struct *w); - - /* Initialized by mwl8k_queue_work(). */ - struct completion *cmd_wait; - - /* Result code. */ - int rc; -}; - -static void mwl8k_config_thread(struct work_struct *wt) -{ - struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt; - struct ieee80211_hw *hw = worker->hw; - int rc = 0; - - rc = mwl8k_fw_lock(hw); - if (!rc) { - rc = worker->wfunc(wt); - mwl8k_fw_unlock(hw); - } - - worker->rc = rc; - complete(worker->cmd_wait); -} - -static int mwl8k_queue_work(struct ieee80211_hw *hw, - struct mwl8k_work_struct *worker, - int (*wfunc)(struct work_struct *w)) -{ - struct mwl8k_priv *priv = hw->priv; - unsigned long timeout = 0; - int rc = 0; - - DECLARE_COMPLETION_ONSTACK(cmd_wait); - - worker->hw = hw; - worker->cmd_wait = &cmd_wait; - worker->rc = 1; - worker->wfunc = wfunc; - - INIT_WORK(&worker->wt, mwl8k_config_thread); - queue_work(priv->config_wq, &worker->wt); - - timeout = wait_for_completion_timeout(&cmd_wait, - msecs_to_jiffies(10000)); - - if (timeout) - rc = worker->rc; - else { - cancel_work_sync(&worker->wt); - rc = -ETIMEDOUT; - } - - return rc; -} - static int mwl8k_start(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; -- cgit v1.2.3 From a145d575833ff47330125364cb49304db7308825 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Aug 2009 04:34:26 +0200 Subject: mwl8k: update copyright and version number Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a634b565018..41a708ce873 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2,7 +2,7 @@ * drivers/net/wireless/mwl8k.c * Driver for Marvell TOPDOG 802.11 Wireless cards * - * Copyright (C) 2008 Marvell Semiconductor Inc. + * Copyright (C) 2008-2009 Marvell Semiconductor Inc. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -25,7 +25,7 @@ #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" #define MWL8K_NAME KBUILD_MODNAME -#define MWL8K_VERSION "0.9.1" +#define MWL8K_VERSION "0.10" MODULE_DESCRIPTION(MWL8K_DESC); MODULE_VERSION(MWL8K_VERSION); -- cgit v1.2.3