From 84c87dc86eaf5c3f70d6c85fac832b277b1f71c7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 5 Aug 2011 13:10:32 +0200 Subject: ath9k: remove ->config_pci_powersave() redundant argument We always call ->config_pci_powersave() with both restore and power_off arguments equal to 0 or both equal to 1, so merge them into one argument. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 44d9d8d..70a18d1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -303,8 +303,7 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) * register as the other analog registers. Hence the 9 writes. */ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, - int restore, - int power_off) + bool power_off) { u8 i; u32 val; @@ -313,7 +312,7 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, return; /* Nothing to do on restore for 11N */ - if (!restore) { + if (!power_off /* !restore */) { if (AR_SREV_9280_20_OR_LATER(ah)) { /* * AR9280 2.0 or later chips use SerDes values from the diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index ad2bb2b..e3d58bd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -516,14 +516,13 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) * register as the other analog registers. Hence the 9 writes. */ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, - int restore, - int power_off) + bool power_off) { if (ah->is_pciexpress != true || ah->aspm_enabled != true) return; /* Nothing to do on restore for 11N */ - if (!restore) { + if (!power_off /* !restore */) { /* set bit 19 to allow forcing of pcie core into L1 state */ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index cb29e88..8c12385 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -22,10 +22,9 @@ /* Hardware core and driver accessible callbacks */ static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, - int restore, - int power_off) + bool power_off) { - ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); + ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off); } static inline void ath9k_hw_rxena(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 4fbcced..2ea10f3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -606,8 +606,7 @@ struct ath_hw_private_ops { */ struct ath_hw_ops { void (*config_pci_powersave)(struct ath_hw *ah, - int restore, - int power_off); + bool power_off); void (*rx_enable)(struct ath_hw *ah); void (*set_desc_link)(void *ds, u32 link); bool (*calibrate)(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1e7fe8c..e408732 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -888,7 +888,7 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); atomic_set(&ah->intr_ref_cnt, -1); - ath9k_hw_configpcipowersave(ah, 0, 0); + ath9k_hw_configpcipowersave(ah, false); if (!ah->curchan) ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); @@ -969,7 +969,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_hw_phy_disable(ah); - ath9k_hw_configpcipowersave(ah, 1, 1); + ath9k_hw_configpcipowersave(ah, true); spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); @@ -1069,7 +1069,7 @@ static int ath9k_start(struct ieee80211_hw *hw) init_channel = ath9k_cmn_get_curchannel(hw, ah); /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(ah, 0, 0); + ath9k_hw_configpcipowersave(ah, false); /* * The basic interface to setting the hardware in a good diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 5685cf1..65cf728 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -35,6 +35,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { 0 } }; + /* return bus cachesize in 4B word units */ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) { @@ -137,7 +138,7 @@ static void ath_pci_aspm_init(struct ath_common *common) if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { ah->aspm_enabled = true; /* Initialize PCIe PM and SERDES registers. */ - ath9k_hw_configpcipowersave(ah, 0, 0); + ath9k_hw_configpcipowersave(ah, false); } } -- cgit v0.10.2 From 3b9cf1be8c4440ae0dd6809bcf3ab6e0e6c54573 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 5 Aug 2011 13:10:33 +0200 Subject: ath9k: merge common ->config_pci_powersave() checks Move common checks into wrapper function. Since ASPM can be only enabled on PCIe devices ->is_pciexpress check is unneeded. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 70a18d1..b54ab78 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -308,9 +308,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, u8 i; u32 val; - if (ah->is_pciexpress != true || ah->aspm_enabled != true) - return; - /* Nothing to do on restore for 11N */ if (!power_off /* !restore */) { if (AR_SREV_9280_20_OR_LATER(ah)) { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index e3d58bd..9cf5d13 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -518,9 +518,6 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) static void ar9003_hw_configpcipowersave(struct ath_hw *ah, bool power_off) { - if (ah->is_pciexpress != true || ah->aspm_enabled != true) - return; - /* Nothing to do on restore for 11N */ if (!power_off /* !restore */) { /* set bit 19 to allow forcing of pcie core into L1 state */ diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 8c12385..dd9003e 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -24,6 +24,9 @@ static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, bool power_off) { + if (ah->aspm_enabled != true) + return; + ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off); } -- cgit v0.10.2 From 69ce674bfa69c55cdf32710d811fa89738eafbef Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 5 Aug 2011 13:10:34 +0200 Subject: ath9k: do btcoex ASPM disabling at initialization time Disable ASPM in pci ->probe on upstream (device) and downstream (PCIe port) component. According to e1000e driver authors this is required. I did not find that requirement in PCIe spec, but it seems to be logical for me. This need to be fixed for CONFIG_PCIEASPM, that will be done later ... Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index db44e5b..875faf6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -603,10 +603,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_regs(ah); - - if (ah->is_pciexpress) - ath9k_hw_aspm_init(ah); - else + if (!ah->is_pciexpress) ath9k_hw_disablepcie(ah); if (!AR_SREV_9300_20_OR_LATER(ah)) @@ -621,6 +618,9 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (r) return r; + if (ah->is_pciexpress) + ath9k_hw_aspm_init(ah); + r = ath9k_hw_init_macaddr(ah); if (r) { ath_err(common, "Failed to initialize MAC address\n"); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 2ea10f3..ee0d944 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1036,10 +1036,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); void ath9k_hw_proc_mib_event(struct ath_hw *ah); void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); -#define ATH_PCIE_CAP_LINK_CTRL 0x70 -#define ATH_PCIE_CAP_LINK_L0S 1 -#define ATH_PCIE_CAP_LINK_L1 2 - #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e408732..781af25 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1145,8 +1145,6 @@ static int ath9k_start(struct ieee80211_hw *hw) AR_STOMP_LOW_WLAN_WGHT); ath9k_hw_btcoex_enable(ah); - if (common->bus_ops->bt_coex_prep) - common->bus_ops->bt_coex_prep(common); if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) ath9k_btcoex_timer_resume(sc); } diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 65cf728..daa26b5 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -89,23 +89,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) return true; } -/* - * Bluetooth coexistance requires disabling ASPM. - */ -static void ath_pci_bt_coex_prep(struct ath_common *common) -{ - struct ath_softc *sc = (struct ath_softc *) common->priv; - struct pci_dev *pdev = to_pci_dev(sc->dev); - u8 aspm; - - if (!pci_is_pcie(pdev)) - return; - - pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); - aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); - pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); -} - static void ath_pci_extn_synch_enable(struct ath_common *common) { struct ath_softc *sc = (struct ath_softc *) common->priv; @@ -117,6 +100,7 @@ static void ath_pci_extn_synch_enable(struct ath_common *common) pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl); } +/* Need to be called after we discover btcoex capabilities */ static void ath_pci_aspm_init(struct ath_common *common) { struct ath_softc *sc = (struct ath_softc *) common->priv; @@ -126,10 +110,33 @@ static void ath_pci_aspm_init(struct ath_common *common) int pos; u8 aspm; - if (!pci_is_pcie(pdev)) + pos = pci_pcie_cap(pdev); + if (!pos) return; parent = pdev->bus->self; + + if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) { + /* Bluetooth coexistance requires disabling ASPM. */ + pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); + aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); + pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); + + /* + * Both upstream and downstream PCIe components should + * have the same ASPM settings. + */ + if (WARN_ON(!parent)) + return; + + pos = pci_pcie_cap(parent); + pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); + aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); + pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); + + return; + } + if (WARN_ON(!parent)) return; @@ -146,7 +153,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = { .ath_bus_type = ATH_PCI, .read_cachesize = ath_pci_read_cachesize, .eeprom_read = ath_pci_eeprom_read, - .bt_coex_prep = ath_pci_bt_coex_prep, .extn_synch_en = ath_pci_extn_synch_enable, .aspm_init = ath_pci_aspm_init, }; -- cgit v0.10.2 From 2a190322d4390bbd5184a2fd4f97bbef9f1f5b4e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 10 Aug 2011 13:50:30 -0600 Subject: b43: reload phy and bss settings after core restarts b43_op_config and b43_op_bss_info_changed apply many settings by directly writing to hardware registers. These settings are lost as soon as the core is restarted and the initvals are reloaded. This was discovered because restarting hostapd led to the beacon interval getting set to ~33s (see https://dev.openwrt.org/ticket/8033 for more information). Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d2661aa..4a5cac6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -320,6 +320,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev); static int b43_wireless_core_init(struct b43_wldev *dev); static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); static int b43_wireless_core_start(struct b43_wldev *dev); +static void b43_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed); static int b43_ratelimit(struct b43_wl *wl) { @@ -3778,14 +3782,24 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_conf *conf = &hw->conf; int antenna; int err = 0; + bool reload_bss = false; mutex_lock(&wl->mutex); + dev = wl->current_dev; + /* Switch the band (if necessary). This might change the active core. */ err = b43_switch_band(wl, conf->channel); if (err) goto out_unlock_mutex; - dev = wl->current_dev; + + /* Need to reload all settings if the core changed */ + if (dev != wl->current_dev) { + dev = wl->current_dev; + changed = ~0; + reload_bss = true; + } + phy = &dev->phy; if (conf_is_ht(conf)) @@ -3846,6 +3860,9 @@ out_mac_enable: out_unlock_mutex: mutex_unlock(&wl->mutex); + if (wl->vif && reload_bss) + b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0); + return err; } @@ -3934,7 +3951,8 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BEACON_INT && (b43_is_mode(wl, NL80211_IFTYPE_AP) || b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || - b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) && + conf->beacon_int) b43_set_beacon_int(dev, conf->beacon_int); if (changed & BSS_CHANGED_BASIC_RATES) @@ -4702,6 +4720,9 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, out_mutex_unlock: mutex_unlock(&wl->mutex); + if (err == 0) + b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0); + return err; } @@ -4772,6 +4793,9 @@ static int b43_op_start(struct ieee80211_hw *hw) out_mutex_unlock: mutex_unlock(&wl->mutex); + /* reload configuration */ + b43_op_config(hw, ~0); + return err; } @@ -4928,10 +4952,18 @@ out: if (err) wl->current_dev = NULL; /* Failed to init the dev. */ mutex_unlock(&wl->mutex); - if (err) + + if (err) { b43err(wl, "Controller restart FAILED\n"); - else - b43info(wl, "Controller restarted\n"); + return; + } + + /* reload configuration */ + b43_op_config(wl->hw, ~0); + if (wl->vif) + b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0); + + b43info(wl, "Controller restarted\n"); } static int b43_setup_bands(struct b43_wldev *dev, -- cgit v0.10.2 From c1407b6cb22245ae8653cfc195530a9b8eb52879 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 11 Aug 2011 16:17:41 +0200 Subject: wireless: Introduce defines for BAR TID_INFO & MULTI_TID fields While at it also fix the indention of the other IEEE80211_BAR_CTRL_ defines. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 54c8789..5286de5 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -816,9 +816,11 @@ struct ieee80211_bar { } __attribute__((packed)); /* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_BAR_CTRL_MULTI_TID 0x0002 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 +#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000 +#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12 #define IEEE80211_HT_MCS_MASK_LEN 10 diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index b7075f3..018108d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -128,7 +128,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; - bar_control |= (u16)(tid << 12); + bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT); bar->control = cpu_to_le16(bar_control); bar->start_seq_num = cpu_to_le16(ssn); -- cgit v0.10.2 From e69deded2bc29e6dd176089252a11b1854012c76 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 11 Aug 2011 16:17:42 +0200 Subject: mac80211: Tear down BA session on BAR tx failure As described at [1] some STAs (i.e. Intel 5100 Windows) can end up correctly BlockAcking incoming frames without delivering them to user space if a AMPDU subframe got lost and we don't flush the receipients reorder buffer with a BlockAckReq. This in turn results in stuck connections. According to 802.11n-2009 it is not necessary to send a BAR to flush the recepients RX reorder buffer but we still do that to be polite. However, assume the following frame exchange: AP -> STA, AMPDU (failed) AP -> STA, BAR (failed) The client in question then ends up in the same situation and won't deliver frames to userspace anymore since we weren't able to flush its reorder buffer. This is not a hypothetical situation but I was able to observe this exact behavior during a stress test between a rt2800pci AP and a Intel 5100 Windows client. In order to work around this issue just tear down the BA session as soon as a BAR failed to be TX'ed. [1] http://comments.gmane.org/gmane.linux.kernel.wireless.general/66867 Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville diff --git a/net/mac80211/status.c b/net/mac80211/status.c index a89cca3..e51bd2a 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -187,6 +187,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) int rates_idx = -1; bool send_to_cooked; bool acked; + struct ieee80211_bar *bar; + u16 tid; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { if (info->status.rates[i].idx < 0) { @@ -243,6 +245,22 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) tid, ssn); } + if (!acked && ieee80211_is_back_req(fc)) { + /* + * BAR failed, let's tear down the BA session as a + * last resort as some STAs (Intel 5100 on Windows) + * can get stuck when the BA window isn't flushed + * correctly. + */ + bar = (struct ieee80211_bar *) skb->data; + if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) { + tid = (bar->control & + IEEE80211_BAR_CTRL_TID_INFO_MASK) >> + IEEE80211_BAR_CTRL_TID_INFO_SHIFT; + ieee80211_stop_tx_ba_session(&sta->sta, tid); + } + } + if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { ieee80211_handle_filtered_frame(local, sta, skb); rcu_read_unlock(); -- cgit v0.10.2 From 2391b7e8d40e4b3be0756396c628d2323f2d0b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 11 Aug 2011 15:07:14 +0200 Subject: b43: rename TX header formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "old" and "new" with number of the first firmware known to use the given format. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index b74f25e..36c7243 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -338,10 +338,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, } } if (b43_is_old_txhdr_format(dev)) { - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), plcp_fragment_len, rate); } else { - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp), plcp_fragment_len, rate); } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), @@ -433,10 +433,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, if (b43_is_old_txhdr_format(dev)) { cts = (struct ieee80211_cts *) - (txhdr->old_format.rts_frame); + (txhdr->format_351.rts_frame); } else { cts = (struct ieee80211_cts *) - (txhdr->new_format.rts_frame); + (txhdr->format_410.rts_frame); } ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -448,10 +448,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, if (b43_is_old_txhdr_format(dev)) { rts = (struct ieee80211_rts *) - (txhdr->old_format.rts_frame); + (txhdr->format_351.rts_frame); } else { rts = (struct ieee80211_rts *) - (txhdr->new_format.rts_frame); + (txhdr->format_410.rts_frame); } ieee80211_rts_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -463,9 +463,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* Generate the PLCP headers for the RTS/CTS frame */ if (b43_is_old_txhdr_format(dev)) - plcp = &txhdr->old_format.rts_plcp; + plcp = &txhdr->format_351.rts_plcp; else - plcp = &txhdr->new_format.rts_plcp; + plcp = &txhdr->format_410.rts_plcp; b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate); plcp = &txhdr->rts_plcp_fb; @@ -474,10 +474,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, if (b43_is_old_txhdr_format(dev)) { hdr = (struct ieee80211_hdr *) - (&txhdr->old_format.rts_frame); + (&txhdr->format_351.rts_frame); } else { hdr = (struct ieee80211_hdr *) - (&txhdr->new_format.rts_frame); + (&txhdr->format_410.rts_frame); } txhdr->rts_dur_fb = hdr->duration_id; @@ -506,9 +506,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* Magic cookie */ if (b43_is_old_txhdr_format(dev)) - txhdr->old_format.cookie = cpu_to_le16(cookie); + txhdr->format_351.cookie = cpu_to_le16(cookie); else - txhdr->new_format.cookie = cpu_to_le16(cookie); + txhdr->format_410.cookie = cpu_to_le16(cookie); if (phy->type == B43_PHYTYPE_N) { txhdr->phy_ctl1 = diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 42debb5..79fc162 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -46,7 +46,7 @@ struct b43_txhdr { __le32 timeout; /* Timeout */ union { - /* The new r410 format. */ + /* Tested with 410.2160, 478.104 and 508.* */ struct { __le16 mimo_antenna; /* MIMO antenna select */ __le16 preload_size; /* Preload size */ @@ -57,9 +57,9 @@ struct b43_txhdr { __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } new_format __packed; + } format_410 __packed; - /* The old r351 format. */ + /* Tested with 351.126 */ struct { PAD_BYTES(2); __le16 cookie; /* TX frame cookie */ @@ -68,7 +68,7 @@ struct b43_txhdr { __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } old_format __packed; + } format_351 __packed; } __packed; } __packed; -- cgit v0.10.2 From efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 11 Aug 2011 15:07:15 +0200 Subject: b43: use enum for firmware header format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index c818b0b..39baaaf 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -694,6 +694,11 @@ struct b43_firmware_file { enum b43_firmware_file_type type; }; +enum b43_firmware_hdr_format { + B43_FW_HDR_410, + B43_FW_HDR_351, +}; + /* Pointers to the firmware data and meta information about it. */ struct b43_firmware { /* Microcode */ @@ -710,6 +715,9 @@ struct b43_firmware { /* Firmware patchlevel */ u16 patch; + /* Format of header used by firmware */ + enum b43_firmware_hdr_format hdr_format; + /* Set to true, if we are using an opensource firmware. * Use this to check for proprietary vs opensource. */ bool opensource; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 4a5cac6..cc3dd80 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2514,6 +2514,10 @@ static int b43_upload_microcode(struct b43_wldev *dev) } dev->fw.rev = fwrev; dev->fw.patch = fwpatch; + if (dev->fw.rev >= 410) + dev->fw.hdr_format = B43_FW_HDR_410; + else + dev->fw.hdr_format = B43_FW_HDR_351; dev->fw.opensource = (fwdate == 0xFFFF); /* Default to use-all-queues. */ @@ -2561,7 +2565,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) dev->fw.rev, dev->fw.patch); wiphy->hw_version = dev->dev->core_id; - if (b43_is_old_txhdr_format(dev)) { + if (dev->fw.hdr_format == B43_FW_HDR_351) { /* We're over the deadline, but we keep support for old fw * until it turns out to be in major conflict with something new. */ b43warn(dev->wl, "You are using an old firmware image. " diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 36c7243..5ce17d5e 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -337,12 +337,15 @@ int b43_generate_txhdr(struct b43_wldev *dev, memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); } } - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_351: b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), plcp_fragment_len, rate); - } else { + break; + case B43_FW_HDR_410: b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp), plcp_fragment_len, rate); + break; } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), plcp_fragment_len, rate_fb); @@ -415,10 +418,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; - struct ieee80211_hdr *hdr; + struct ieee80211_hdr *uninitialized_var(hdr); int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; - struct b43_plcp_hdr6 *plcp; + struct b43_plcp_hdr6 *uninitialized_var(plcp); struct ieee80211_rate *rts_cts_rate; rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); @@ -429,14 +432,17 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - struct ieee80211_cts *cts; + struct ieee80211_cts *uninitialized_var(cts); - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_351: cts = (struct ieee80211_cts *) (txhdr->format_351.rts_frame); - } else { + break; + case B43_FW_HDR_410: cts = (struct ieee80211_cts *) (txhdr->format_410.rts_frame); + break; } ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -444,14 +450,17 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= B43_TXH_MAC_SENDCTS; len = sizeof(struct ieee80211_cts); } else { - struct ieee80211_rts *rts; + struct ieee80211_rts *uninitialized_var(rts); - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_351: rts = (struct ieee80211_rts *) (txhdr->format_351.rts_frame); - } else { + break; + case B43_FW_HDR_410: rts = (struct ieee80211_rts *) (txhdr->format_410.rts_frame); + break; } ieee80211_rts_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -462,22 +471,29 @@ int b43_generate_txhdr(struct b43_wldev *dev, len += FCS_LEN; /* Generate the PLCP headers for the RTS/CTS frame */ - if (b43_is_old_txhdr_format(dev)) + switch (dev->fw.hdr_format) { + case B43_FW_HDR_351: plcp = &txhdr->format_351.rts_plcp; - else + break; + case B43_FW_HDR_410: plcp = &txhdr->format_410.rts_plcp; + break; + } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate); plcp = &txhdr->rts_plcp_fb; b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate_fb); - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_351: hdr = (struct ieee80211_hdr *) (&txhdr->format_351.rts_frame); - } else { + break; + case B43_FW_HDR_410: hdr = (struct ieee80211_hdr *) (&txhdr->format_410.rts_frame); + break; } txhdr->rts_dur_fb = hdr->duration_id; @@ -505,10 +521,14 @@ int b43_generate_txhdr(struct b43_wldev *dev, } /* Magic cookie */ - if (b43_is_old_txhdr_format(dev)) + switch (dev->fw.hdr_format) { + case B43_FW_HDR_351: txhdr->format_351.cookie = cpu_to_le16(cookie); - else + break; + case B43_FW_HDR_410: txhdr->format_410.cookie = cpu_to_le16(cookie); + break; + } if (phy->type == B43_PHYTYPE_N) { txhdr->phy_ctl1 = diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 79fc162..a3ff727 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -166,19 +166,16 @@ struct b43_tx_legacy_rate_phy_ctl_entry { #define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */ -/* r351 firmware compatibility stuff. */ -static inline -bool b43_is_old_txhdr_format(struct b43_wldev *dev) -{ - return (dev->fw.rev <= 351); -} - static inline size_t b43_txhdr_size(struct b43_wldev *dev) { - if (b43_is_old_txhdr_format(dev)) + switch (dev->fw.hdr_format) { + case B43_FW_HDR_410: + return 104 + sizeof(struct b43_plcp_hdr6); + case B43_FW_HDR_351: return 100 + sizeof(struct b43_plcp_hdr6); - return 104 + sizeof(struct b43_plcp_hdr6); + } + return 0; } -- cgit v0.10.2 From 5d852905561a979dfb4d8a68f7313dcb8f055bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 11 Aug 2011 15:07:16 +0200 Subject: b43: support new TX header, noticed to be used by 598.314+ fw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 39baaaf..f4e9d8b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -695,6 +695,7 @@ struct b43_firmware_file { }; enum b43_firmware_hdr_format { + B43_FW_HDR_598, B43_FW_HDR_410, B43_FW_HDR_351, }; @@ -883,7 +884,7 @@ struct b43_wl { struct b43_leds leds; /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ - u8 pio_scratchspace[110] __attribute__((__aligned__(8))); + u8 pio_scratchspace[118] __attribute__((__aligned__(8))); u8 pio_tailspace[4] __attribute__((__aligned__(8))); }; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cc3dd80..aac88322 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2514,7 +2514,9 @@ static int b43_upload_microcode(struct b43_wldev *dev) } dev->fw.rev = fwrev; dev->fw.patch = fwpatch; - if (dev->fw.rev >= 410) + if (dev->fw.rev >= 598) + dev->fw.hdr_format = B43_FW_HDR_598; + else if (dev->fw.rev >= 410) dev->fw.hdr_format = B43_FW_HDR_410; else dev->fw.hdr_format = B43_FW_HDR_351; diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5ce17d5e..b02170d 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -338,6 +338,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, } } switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp), + plcp_fragment_len, rate); + break; case B43_FW_HDR_351: b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), plcp_fragment_len, rate); @@ -435,6 +439,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, struct ieee80211_cts *uninitialized_var(cts); switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + cts = (struct ieee80211_cts *) + (txhdr->format_598.rts_frame); + break; case B43_FW_HDR_351: cts = (struct ieee80211_cts *) (txhdr->format_351.rts_frame); @@ -453,6 +461,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, struct ieee80211_rts *uninitialized_var(rts); switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + rts = (struct ieee80211_rts *) + (txhdr->format_598.rts_frame); + break; case B43_FW_HDR_351: rts = (struct ieee80211_rts *) (txhdr->format_351.rts_frame); @@ -472,6 +484,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* Generate the PLCP headers for the RTS/CTS frame */ switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + plcp = &txhdr->format_598.rts_plcp; + break; case B43_FW_HDR_351: plcp = &txhdr->format_351.rts_plcp; break; @@ -486,6 +501,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, len, rts_rate_fb); switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + hdr = (struct ieee80211_hdr *) + (&txhdr->format_598.rts_frame); + break; case B43_FW_HDR_351: hdr = (struct ieee80211_hdr *) (&txhdr->format_351.rts_frame); @@ -522,6 +541,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* Magic cookie */ switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + txhdr->format_598.cookie = cpu_to_le16(cookie); + break; case B43_FW_HDR_351: txhdr->format_351.cookie = cpu_to_le16(cookie); break; diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index a3ff727..dccf7c1 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -46,6 +46,23 @@ struct b43_txhdr { __le32 timeout; /* Timeout */ union { + /* Tested with 598.314, 644.1001 and 666.2 */ + struct { + __le16 mimo_antenna; /* MIMO antenna select */ + __le16 preload_size; /* Preload size */ + PAD_BYTES(2); + __le16 cookie; /* TX frame cookie */ + __le16 tx_status; /* TX status */ + __le16 max_n_mpdus; + __le16 max_a_bytes_mrt; + __le16 max_a_bytes_fbr; + __le16 min_m_bytes; + struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ + __u8 rts_frame[16]; /* The RTS frame (if used) */ + PAD_BYTES(2); + struct b43_plcp_hdr6 plcp; /* Main PLCP header */ + } format_598 __packed; + /* Tested with 410.2160, 478.104 and 508.* */ struct { __le16 mimo_antenna; /* MIMO antenna select */ @@ -170,6 +187,8 @@ static inline size_t b43_txhdr_size(struct b43_wldev *dev) { switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + return 112 + sizeof(struct b43_plcp_hdr6); case B43_FW_HDR_410: return 104 + sizeof(struct b43_plcp_hdr6); case B43_FW_HDR_351: -- cgit v0.10.2 From 17030f48e31adde5b043741c91ba143f5f7db0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 11 Aug 2011 17:16:27 +0200 Subject: b43: support new RX header, noticed to be used in 598.314+ fw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 83cba22..d0d9aee 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -858,8 +858,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, ring->current_slot = -1; } else { if (ring->index == 0) { - ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; - ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE; + ring->frameoffset = B43_DMA0_RX_FW598_FO; + break; + case B43_FW_HDR_410: + case B43_FW_HDR_351: + ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE; + ring->frameoffset = B43_DMA0_RX_FW351_FO; + break; + } } else B43_WARN_ON(1); } diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index cdf8709..546d19c 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -162,12 +162,15 @@ struct b43_dmadesc_generic { /* Misc DMA constants */ #define B43_DMA_RINGMEMSIZE PAGE_SIZE -#define B43_DMA0_RX_FRAMEOFFSET 30 +/* Offset of frame with actual data */ +#define B43_DMA0_RX_FW598_FO 38 +#define B43_DMA0_RX_FW351_FO 30 /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 #define B43_RXRING_SLOTS 64 -#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) /* Pointer poison */ #define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM)) diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 6e4228c..ce8a4bd 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -676,7 +676,15 @@ data_ready: goto rx_error; } - macstat = le32_to_cpu(rxhdr->mac_status); + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + macstat = le32_to_cpu(rxhdr->format_598.mac_status); + break; + case B43_FW_HDR_410: + case B43_FW_HDR_351: + macstat = le32_to_cpu(rxhdr->format_351.mac_status); + break; + } if (macstat & B43_RX_MAC_FCSERR) { if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { /* Drop frames with failed FCS. */ diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index b02170d..5b82409 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -653,8 +653,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) struct ieee80211_hdr *wlhdr; const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; __le16 fctl; - u16 phystat0, phystat3, chanstat, mactime; - u32 macstat; + u16 phystat0, phystat3; + u16 uninitialized_var(chanstat), uninitialized_var(mactime); + u32 uninitialized_var(macstat); u16 chanid; u16 phytype; int padding; @@ -664,9 +665,19 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* Get metadata about the frame from the header. */ phystat0 = le16_to_cpu(rxhdr->phy_status0); phystat3 = le16_to_cpu(rxhdr->phy_status3); - macstat = le32_to_cpu(rxhdr->mac_status); - mactime = le16_to_cpu(rxhdr->mac_time); - chanstat = le16_to_cpu(rxhdr->channel); + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + macstat = le32_to_cpu(rxhdr->format_598.mac_status); + mactime = le16_to_cpu(rxhdr->format_598.mac_time); + chanstat = le16_to_cpu(rxhdr->format_598.channel); + break; + case B43_FW_HDR_410: + case B43_FW_HDR_351: + macstat = le32_to_cpu(rxhdr->format_351.mac_status); + mactime = le16_to_cpu(rxhdr->format_351.mac_time); + chanstat = le16_to_cpu(rxhdr->format_351.channel); + break; + } phytype = chanstat & B43_RX_CHAN_PHYTYPE; if (unlikely(macstat & B43_RX_MAC_FCSERR)) { diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index dccf7c1..f6e8bc4 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -250,9 +250,23 @@ struct b43_rxhdr_fw4 { } __packed; __le16 phy_status2; /* PHY RX Status 2 */ __le16 phy_status3; /* PHY RX Status 3 */ - __le32 mac_status; /* MAC RX status */ - __le16 mac_time; - __le16 channel; + union { + /* Tested with 598.314, 644.1001 and 666.2 */ + struct { + __le16 phy_status4; /* PHY RX Status 4 */ + __le16 phy_status5; /* PHY RX Status 5 */ + __le32 mac_status; /* MAC RX status */ + __le16 mac_time; + __le16 channel; + } format_598 __packed; + + /* Tested with 351.126, 410.2160, 478.104 and 508.* */ + struct { + __le32 mac_status; /* MAC RX status */ + __le16 mac_time; + __le16 channel; + } format_351 __packed; + } __packed; } __packed; /* PHY RX Status 0 */ -- cgit v0.10.2 From 984e5befbafe2799be28c2209226a82fb3a3be7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 11 Aug 2011 23:46:44 +0200 Subject: bcma: implement BCM4331 workaround for external PA lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to disable ext. PA lines for reading SPROM. It's disabled by default, but this patch allows using bcma after loading wl, which leaves workaround enabled. Cc: Arend van Spriel Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 5940c81..4bc10aa 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -90,6 +90,24 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) } } +/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ +void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) +{ + struct bcma_bus *bus = cc->core->bus; + u32 val; + + val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); + if (enable) { + val |= BCMA_CHIPCTL_4331_EXTPA_EN; + if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) + val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; + } else { + val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; + val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; + } + bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); +} + void bcma_pmu_workarounds(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; @@ -99,7 +117,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - pr_err("Enabling Ext PA lines not implemented\n"); + /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ break; case 43224: if (bus->chipinfo.rev == 0) { diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 8b5b785..166ed13 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -152,6 +152,9 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; + if (bus->chipinfo.id == 0x4331) + bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); + /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). * According to brcm80211 this applies to cards with PCIe rev >= 6 * TODO: understand this condition and use it */ @@ -159,6 +162,9 @@ int bcma_sprom_get(struct bcma_bus *bus) BCMA_CC_SPROM_PCIE6; bcma_sprom_read(bus, offset, sprom); + if (bus->chipinfo.id == 0x4331) + bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); + err = bcma_sprom_valid(sprom); if (err) goto out; diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 6083725..a7ae33d 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -283,6 +283,22 @@ #define BCMA_CC_PPL_PCHI_OFF 5 #define BCMA_CC_PPL_PCHI_MASK 0x0000003f +/* BCM4331 ChipControl numbers. */ +#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */ +#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */ +#define BCMA_CHIPCTL_4331_EXT_LNA BIT(2) /* 0 disable */ +#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15 BIT(3) /* sprom/gpio13-15 mux */ +#define BCMA_CHIPCTL_4331_EXTPA_EN BIT(4) /* 0 ext pa disable, 1 ext pa enabled */ +#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS BIT(5) /* set drive out GPIO_CLK on sprom_cs pin */ +#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS BIT(6) /* use sprom_cs pin as PCIE mdio interface */ +#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5 BIT(7) /* aband extpa will be at gpio2/5 and sprom_dout */ +#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN BIT(8) /* override core control on pipe_AuxClkEnable */ +#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */ +#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */ +#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */ +#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */ +#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */ + /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ @@ -342,6 +358,8 @@ extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); extern void bcma_chipco_resume(struct bcma_drv_cc *cc); +void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); + extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); -- cgit v0.10.2 From 6a461c23e7051d090751a2030e5febf6356c8d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 12 Aug 2011 00:03:25 +0200 Subject: b43: include HT-PHY in some common code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index aac88322..b5e8305 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2953,6 +2953,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev) case B43_PHYTYPE_G: case B43_PHYTYPE_N: case B43_PHYTYPE_LP: + case B43_PHYTYPE_HT: 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); diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5b82409..b8de62c 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -797,6 +797,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) break; case B43_PHYTYPE_N: case B43_PHYTYPE_LP: + case B43_PHYTYPE_HT: /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ) { -- cgit v0.10.2 From f6a3e99da82167e066ebde975ec604638b42d816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 12 Aug 2011 00:03:26 +0200 Subject: b43: make forcing clock common (HT-PHY also uses that) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 07f009f..3ea44bb 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -448,6 +448,38 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type) channel_type == NL80211_CHAN_HT40PLUS); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ +void b43_phy_force_clock(struct b43_wldev *dev, bool force) +{ + u32 tmp; + + WARN_ON(dev->phy.type != B43_PHYTYPE_N && + dev->phy.type != B43_PHYTYPE_HT); + + switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + if (force) + tmp |= BCMA_IOCTL_FGC; + else + tmp &= ~BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); + break; +#endif +#ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); + if (force) + tmp |= SSB_TMSLOW_FGC; + else + tmp &= ~SSB_TMSLOW_FGC; + ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); + break; +#endif + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */ struct b43_c32 b43_cordic(int theta) { diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index aa77ba6..9233b13 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -444,6 +444,8 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type); +void b43_phy_force_clock(struct b43_wldev *dev, bool force); + struct b43_c32 b43_cordic(int theta); #endif /* LINUX_B43_PHY_COMMON_H_ */ diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3b46360..2eadadf 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -600,49 +600,17 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) } } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ -static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) -{ - u32 tmp; - - if (dev->phy.type != B43_PHYTYPE_N) - return; - - switch (dev->dev->bus_type) { -#ifdef CONFIG_B43_BCMA - case B43_BUS_BCMA: - tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); - if (force) - tmp |= BCMA_IOCTL_FGC; - else - tmp &= ~BCMA_IOCTL_FGC; - bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); - break; -#endif -#ifdef CONFIG_B43_SSB - case B43_BUS_SSB: - tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); - if (force) - tmp |= SSB_TMSLOW_FGC; - else - tmp &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); - break; -#endif - } -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ static void b43_nphy_reset_cca(struct b43_wldev *dev) { u16 bbcfg; - b43_nphy_bmac_clock_fgc(dev, 1); + b43_phy_force_clock(dev, 1); bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); udelay(1); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); - b43_nphy_bmac_clock_fgc(dev, 0); + b43_phy_force_clock(dev, 0); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); } @@ -3715,11 +3683,11 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_workarounds(dev); /* Reset CCA, in init code it differs a little from standard way */ - b43_nphy_bmac_clock_fgc(dev, 1); + b43_phy_force_clock(dev, 1); tmp = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); - b43_nphy_bmac_clock_fgc(dev, 0); + b43_phy_force_clock(dev, 0); b43_mac_phy_clock_set(dev, true); -- cgit v0.10.2 From 082ebb0c258d28af7452b19df9ef8b7553f37690 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 11 Aug 2011 19:35:10 -0700 Subject: mac80211: fix mesh beacon format Correct ordering of IEs in the mesh beacon while removing unneeded IEs from mesh peering frames. Set privacy bit in capability info if security is enabled. Add utility functions to aid in construction of IEs and reduce code duplication. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 29e9980..1990869 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -204,36 +204,185 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, return 0; } -void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +int +mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u8 *pos, neighbors; + u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie); + + if (skb_tailroom(skb) < 2 + meshconf_len) + return -ENOMEM; + + pos = skb_put(skb, 2 + meshconf_len); + *pos++ = WLAN_EID_MESH_CONFIG; + *pos++ = meshconf_len; + + /* Active path selection protocol ID */ + *pos++ = ifmsh->mesh_pp_id; + /* Active path selection metric ID */ + *pos++ = ifmsh->mesh_pm_id; + /* Congestion control mode identifier */ + *pos++ = ifmsh->mesh_cc_id; + /* Synchronization protocol identifier */ + *pos++ = ifmsh->mesh_sp_id; + /* Authentication Protocol identifier */ + *pos++ = ifmsh->mesh_auth_id; + /* Mesh Formation Info - number of neighbors */ + neighbors = atomic_read(&ifmsh->mshstats.estab_plinks); + /* Number of neighbor mesh STAs or 15 whichever is smaller */ + neighbors = (neighbors > 15) ? 15 : neighbors; + *pos++ = neighbors << 1; + /* Mesh capability */ + ifmsh->accepting_plinks = mesh_plink_availables(sdata); + *pos = MESHCONF_CAPAB_FORWARDING; + *pos++ |= ifmsh->accepting_plinks ? + MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; + *pos++ = 0x00; + + return 0; +} + +int +mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u8 *pos; + + if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len) + return -ENOMEM; + + pos = skb_put(skb, 2 + ifmsh->mesh_id_len); + *pos++ = WLAN_EID_MESH_ID; + *pos++ = ifmsh->mesh_id_len; + if (ifmsh->mesh_id_len) + memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len); + + return 0; +} + +int +mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u8 offset, len; + const u8 *data; + + if (!ifmsh->ie || !ifmsh->ie_len) + return 0; + + /* fast-forward to vendor IEs */ + offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0); + + if (offset) { + len = ifmsh->ie_len - offset; + data = ifmsh->ie + offset; + if (skb_tailroom(skb) < len) + return -ENOMEM; + memcpy(skb_put(skb, len), data, len); + } + + return 0; +} + +int +mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u8 len = 0; + const u8 *data; + + if (!ifmsh->ie || !ifmsh->ie_len) + return 0; + + /* find RSN IE */ + data = ifmsh->ie; + while (data < ifmsh->ie + ifmsh->ie_len) { + if (*data == WLAN_EID_RSN) { + len = data[1] + 2; + break; + } + data++; + } + + if (len) { + if (skb_tailroom(skb) < len) + return -ENOMEM; + memcpy(skb_put(skb, len), data, len); + } + + return 0; +} + +int +mesh_add_srates_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; - u8 *pos; - int len, i, rate; - u8 neighbors; + int rate; + u8 i, rates, *pos; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - len = sband->n_bitrates; - if (len > 8) - len = 8; - pos = skb_put(skb, len + 2); + rates = sband->n_bitrates; + if (rates > 8) + rates = 8; + + if (skb_tailroom(skb) < rates + 2) + return -ENOMEM; + + pos = skb_put(skb, rates + 2); *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = len; - for (i = 0; i < len; i++) { + *pos++ = rates; + for (i = 0; i < rates; i++) { rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } - if (sband->n_bitrates > len) { - pos = skb_put(skb, sband->n_bitrates - len + 2); + return 0; +} + +int +mesh_add_ext_srates_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + int rate; + u8 i, exrates, *pos; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + exrates = sband->n_bitrates; + if (exrates > 8) + exrates -= 8; + else + exrates = 0; + + if (skb_tailroom(skb) < exrates + 2) + return -ENOMEM; + + if (exrates) { + pos = skb_put(skb, exrates + 2); *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = sband->n_bitrates - len; - for (i = len; i < sband->n_bitrates; i++) { + *pos++ = exrates; + for (i = 8; i < sband->n_bitrates; i++) { rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } } + return 0; +} + +int mesh_add_ds_params_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + u8 *pos; + + if (skb_tailroom(skb) < 3) + return -ENOMEM; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; if (sband->band == IEEE80211_BAND_2GHZ) { pos = skb_put(skb, 2 + 1); *pos++ = WLAN_EID_DS_PARAMS; @@ -241,53 +390,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); } - pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); - *pos++ = WLAN_EID_MESH_ID; - *pos++ = sdata->u.mesh.mesh_id_len; - if (sdata->u.mesh.mesh_id_len) - memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); - - pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); - *pos++ = WLAN_EID_MESH_CONFIG; - *pos++ = sizeof(struct ieee80211_meshconf_ie); - - /* Active path selection protocol ID */ - *pos++ = sdata->u.mesh.mesh_pp_id; - - /* Active path selection metric ID */ - *pos++ = sdata->u.mesh.mesh_pm_id; - - /* Congestion control mode identifier */ - *pos++ = sdata->u.mesh.mesh_cc_id; - - /* Synchronization protocol identifier */ - *pos++ = sdata->u.mesh.mesh_sp_id; - - /* Authentication Protocol identifier */ - *pos++ = sdata->u.mesh.mesh_auth_id; - - /* Mesh Formation Info - number of neighbors */ - neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks); - /* Number of neighbor mesh STAs or 15 whichever is smaller */ - neighbors = (neighbors > 15) ? 15 : neighbors; - *pos++ = neighbors << 1; - - /* Mesh capability */ - sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); - *pos = MESHCONF_CAPAB_FORWARDING; - *pos++ |= sdata->u.mesh.accepting_plinks ? - MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; - *pos++ = 0x00; - - if (sdata->u.mesh.ie) { - int len = sdata->u.mesh.ie_len; - const u8 *data = sdata->u.mesh.ie; - if (skb_tailroom(skb) > len) - memcpy(skb_put(skb, len), data, len); - } + return 0; } - static void ieee80211_mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 249e733..b794360 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -199,6 +199,20 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); +int mesh_add_meshconf_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_meshid_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_rsn_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_vendor_ies(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_srates_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_ext_srates_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_ds_params_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f4adc09..e4113f2 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -195,7 +195,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, memset(pos, 0, 2); memcpy(pos + 2, &plid, 2); } - mesh_mgmt_ies_add(skb, sdata); + if (mesh_add_srates_ie(skb, sdata) || + mesh_add_ext_srates_ie(skb, sdata) || + mesh_add_rsn_ie(skb, sdata) || + mesh_add_meshid_ie(skb, sdata) || + mesh_add_meshconf_ie(skb, sdata)) + return -1; } /* Add Peer Link Management element */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 69fd494..0107263 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2295,13 +2295,23 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(sdata->vif.bss_conf.beacon_int); - mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ + mgmt->u.beacon.capab_info |= cpu_to_le16( + sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0); pos = skb_put(skb, 2); *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - mesh_mgmt_ies_add(skb, sdata); + if (mesh_add_srates_ie(skb, sdata) || + mesh_add_ds_params_ie(skb, sdata) || + mesh_add_ext_srates_ie(skb, sdata) || + mesh_add_rsn_ie(skb, sdata) || + mesh_add_meshid_ie(skb, sdata) || + mesh_add_meshconf_ie(skb, sdata) || + mesh_add_vendor_ies(skb, sdata)) { + pr_err("o11s: couldn't add ies!\n"); + goto out; + } } else { WARN_ON(1); goto out; -- cgit v0.10.2 From 6709a6d96e0f9b05a07999f720a15389ad242a4a Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 11 Aug 2011 19:35:11 -0700 Subject: ieee80211: introduce Self Protected Action codes 802.11s introduces a new action frame category, add action codes as well as an entry in ieee80211_mgmt. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 5286de5..0750987 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -749,6 +749,10 @@ struct ieee80211_mgmt { */ u8 variable[0]; } __attribute__((packed)) plink_action; + struct { + u8 action_code; + u8 variable[0]; + } __attribute__((packed)) self_prot; struct{ u8 action_code; u8 variable[0]; @@ -1311,6 +1315,16 @@ enum ieee80211_ht_actioncode { WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, }; +/* Self Protected Action codes */ +enum ieee80211_self_protected_actioncode { + WLAN_SP_RESERVED = 0, + WLAN_SP_MESH_PEERING_OPEN = 1, + WLAN_SP_MESH_PEERING_CONFIRM = 2, + WLAN_SP_MESH_PEERING_CLOSE = 3, + WLAN_SP_MGK_INFORM = 4, + WLAN_SP_MGK_ACK = 5, +}; + /* Security key length */ enum ieee80211_key_len { WLAN_KEY_LEN_WEP40 = 5, -- cgit v0.10.2 From 54ef656b05103f700ff8fc2aaf0382cfd0e54fe4 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 11 Aug 2011 19:35:12 -0700 Subject: mac80211: update mesh peering frame codes Have the mesh peering frames use the self-protected action and reason codes specified in 802.11s and defined in ieee80211.h. Remove the local enums. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index e4113f2..2cf2212 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -25,29 +25,12 @@ #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ jiffies + HZ * t / 1000)) -/* Peer link cancel reasons, all subject to ANA approval */ -#define MESH_LINK_CANCELLED 2 -#define MESH_MAX_NEIGHBORS 3 -#define MESH_CAPABILITY_POLICY_VIOLATION 4 -#define MESH_CLOSE_RCVD 5 -#define MESH_MAX_RETRIES 6 -#define MESH_CONFIRM_TIMEOUT 7 -#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8 -#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 -#define MESH_SECURITY_FAILED_VERIFICATION 10 - #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) -enum plink_frame_type { - PLINK_OPEN = 1, - PLINK_CONFIRM, - PLINK_CLOSE -}; - enum plink_event { PLINK_UNDEFINED, OPN_ACPT, @@ -157,8 +140,8 @@ void mesh_plink_deactivate(struct sta_info *sta) } static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, - enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, - __le16 reason) { + enum ieee80211_self_protected_actioncode action, + u8 *da, __le16 llid, __le16 plid, __le16 reason) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + sdata->u.mesh.ie_len); @@ -185,11 +168,11 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; mgmt->u.action.u.plink_action.action_code = action; - if (action == PLINK_CLOSE) + if (action == WLAN_SP_MESH_PEERING_CLOSE) mgmt->u.action.u.plink_action.aux = reason; else { mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0); - if (action == PLINK_CONFIRM) { + if (action == WLAN_SP_MESH_PEERING_CONFIRM) { pos = skb_put(skb, 4); /* two-byte status code followed by two-byte AID */ memset(pos, 0, 2); @@ -205,14 +188,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, /* Add Peer Link Management element */ switch (action) { - case PLINK_OPEN: + case WLAN_SP_MESH_PEERING_OPEN: ie_len = 6; break; - case PLINK_CONFIRM: + case WLAN_SP_MESH_PEERING_CONFIRM: ie_len = 8; include_plid = true; break; - case PLINK_CLOSE: + case WLAN_SP_MESH_PEERING_CLOSE: default: if (!plid) ie_len = 8; @@ -233,7 +216,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, pos += 2; memcpy(pos, &plid, 2); } - if (action == PLINK_CLOSE) { + if (action == WLAN_SP_MESH_PEERING_CLOSE) { pos += 2; memcpy(pos, &reason, 2); } @@ -327,21 +310,21 @@ static void mesh_plink_timer(unsigned long data) ++sta->plink_retries; mod_plink_timer(sta, sta->plink_timeout); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, - 0, 0); + mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, + sta->sta.addr, llid, 0, 0); break; } - reason = cpu_to_le16(MESH_MAX_RETRIES); + reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES); /* fall through on else */ case NL80211_PLINK_CNF_RCVD: /* confirm timer */ if (!reason) - reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); + reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); sta->plink_state = NL80211_PLINK_HOLDING; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, - reason); + mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, + sta->sta.addr, llid, plid, reason); break; case NL80211_PLINK_HOLDING: /* holding timer */ @@ -401,7 +384,7 @@ int mesh_plink_open(struct sta_info *sta) mpl_dbg("Mesh plink: starting establishment with %pM\n", sta->sta.addr); - return mesh_plink_frame_tx(sdata, PLINK_OPEN, + return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, sta->sta.addr, llid, 0, 0); } @@ -427,7 +410,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m struct ieee802_11_elems elems; struct sta_info *sta; enum plink_event event; - enum plink_frame_type ftype; + enum ieee80211_self_protected_actioncode ftype; size_t baselen; bool deactivated, matches_local = true; u8 ie_len; @@ -456,7 +439,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m baseaddr = mgmt->u.action.u.plink_action.variable; baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; - if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { + if (mgmt->u.action.u.plink_action.action_code == + WLAN_SP_MESH_PEERING_CONFIRM) { baseaddr += 4; baselen += 4; } @@ -473,15 +457,17 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ftype = mgmt->u.action.u.plink_action.action_code; ie_len = elems.peer_link_len; - if ((ftype == PLINK_OPEN && ie_len != 6) || - (ftype == PLINK_CONFIRM && ie_len != 8) || - (ftype == PLINK_CLOSE && ie_len != 8 && ie_len != 10)) { + if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 6) || + (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 8) || + (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 8 + && ie_len != 10)) { mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; } - if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) { + if (ftype != WLAN_SP_MESH_PEERING_CLOSE && + (!elems.mesh_id || !elems.mesh_config)) { mpl_dbg("Mesh plink: missing necessary ie\n"); return; } @@ -489,13 +475,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m * from the point of view of this host. */ memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); - if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10)) + if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || + (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 10)) memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); - if (!sta && ftype != PLINK_OPEN) { + if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) { mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); rcu_read_unlock(); return; @@ -514,30 +501,30 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m /* Now we will figure out the appropriate event... */ event = PLINK_UNDEFINED; - if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { + if (ftype != WLAN_SP_MESH_PEERING_CLOSE && + (!mesh_matches_local(&elems, sdata))) { matches_local = false; switch (ftype) { - case PLINK_OPEN: + case WLAN_SP_MESH_PEERING_OPEN: event = OPN_RJCT; break; - case PLINK_CONFIRM: + case WLAN_SP_MESH_PEERING_CONFIRM: event = CNF_RJCT; break; - case PLINK_CLOSE: - /* avoid warning */ + default: break; } } if (!sta && !matches_local) { rcu_read_unlock(); - reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); + reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); llid = 0; - mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, - plid, reason); + mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, + mgmt->sa, llid, plid, reason); return; } else if (!sta) { - /* ftype == PLINK_OPEN */ + /* ftype == WLAN_SP_MESH_PEERING_OPEN */ u32 rates; rcu_read_unlock(); @@ -562,21 +549,21 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } else if (matches_local) { spin_lock_bh(&sta->lock); switch (ftype) { - case PLINK_OPEN: + case WLAN_SP_MESH_PEERING_OPEN: if (!mesh_plink_free_count(sdata) || (sta->plid && sta->plid != plid)) event = OPN_IGNR; else event = OPN_ACPT; break; - case PLINK_CONFIRM: + case WLAN_SP_MESH_PEERING_CONFIRM: if (!mesh_plink_free_count(sdata) || (sta->llid != llid || sta->plid != plid)) event = CNF_IGNR; else event = CNF_ACPT; break; - case PLINK_CLOSE: + case WLAN_SP_MESH_PEERING_CLOSE: if (sta->plink_state == NL80211_PLINK_ESTAB) /* Do not check for llid or plid. This does not * follow the standard but since multiple plinks @@ -625,10 +612,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->llid = llid; mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, - 0, 0); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, - llid, plid, 0); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_OPEN, + sta->sta.addr, llid, 0, 0); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CONFIRM, + sta->sta.addr, llid, plid, 0); break; default: spin_unlock_bh(&sta->lock); @@ -640,10 +629,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m switch (event) { case OPN_RJCT: case CNF_RJCT: - reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); + reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); case CLS_ACPT: if (!reason) - reason = cpu_to_le16(MESH_CLOSE_RCVD); + reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, @@ -652,8 +641,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, - plid, reason); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CLOSE, + sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: /* retry timer is left untouched */ @@ -661,8 +651,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->plid = plid; llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, - plid, 0); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CONFIRM, + sta->sta.addr, llid, plid, 0); break; case CNF_ACPT: sta->plink_state = NL80211_PLINK_CNF_RCVD; @@ -682,10 +673,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m switch (event) { case OPN_RJCT: case CNF_RJCT: - reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); + reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); case CLS_ACPT: if (!reason) - reason = cpu_to_le16(MESH_CLOSE_RCVD); + reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, @@ -694,14 +685,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, - plid, reason); + mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, + sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, - plid, 0); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CONFIRM, + sta->sta.addr, llid, plid, 0); break; case CNF_ACPT: del_timer(&sta->plink_timer); @@ -722,10 +714,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m switch (event) { case OPN_RJCT: case CNF_RJCT: - reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); + reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); case CLS_ACPT: if (!reason) - reason = cpu_to_le16(MESH_CLOSE_RCVD); + reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, @@ -734,8 +726,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, - plid, reason); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CLOSE, + sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: del_timer(&sta->plink_timer); @@ -745,8 +738,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); mpl_dbg("Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, - plid, 0); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CONFIRM, + sta->sta.addr, llid, plid, 0); break; default: spin_unlock_bh(&sta->lock); @@ -757,7 +751,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case NL80211_PLINK_ESTAB: switch (event) { case CLS_ACPT: - reason = cpu_to_le16(MESH_CLOSE_RCVD); + reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); sta->reason = reason; deactivated = __mesh_plink_deactivate(sta); sta->plink_state = NL80211_PLINK_HOLDING; @@ -766,14 +760,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_unlock_bh(&sta->lock); if (deactivated) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, - plid, reason); + mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, + sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, - plid, 0); + mesh_plink_frame_tx(sdata, + WLAN_SP_MESH_PEERING_CONFIRM, + sta->sta.addr, llid, plid, 0); break; default: spin_unlock_bh(&sta->lock); @@ -795,8 +790,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; reason = sta->reason; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, - llid, plid, reason); + mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, + sta->sta.addr, llid, plid, reason); break; default: spin_unlock_bh(&sta->lock); -- cgit v0.10.2 From 8db098507c5cbe499061d0f6aea426a36e7c72d7 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 12 Aug 2011 20:01:00 -0700 Subject: mac80211: update mesh peering frame format This patch updates the mesh peering frames to the format specified in the recently ratified 802.11s standard. Several changes took place to make this happen: - Change RX path to handle new self-protected frames - Add new Peering management IE - Remove old Peer Link IE - Remove old plink_action field in ieee80211_mgmt header These changes by themselves would either break peering, or work by coincidence, so squash them all into this patch. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 0750987..819954a 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -736,19 +736,6 @@ struct ieee80211_mgmt { __le16 params; __le16 reason_code; } __attribute__((packed)) delba; - struct{ - u8 action_code; - /* capab_info for open and confirm, - * reason for close - */ - __le16 aux; - /* Followed in plink_confirm by status - * code, AID and supported rates, - * and directly by supported rates in - * plink_open and plink_close - */ - u8 variable[0]; - } __attribute__((packed)) plink_action; struct { u8 action_code; u8 variable[0]; @@ -1200,11 +1187,6 @@ enum ieee80211_eid { WLAN_EID_MESH_ID = 114, WLAN_EID_LINK_METRIC_REPORT = 115, WLAN_EID_CONGESTION_NOTIFICATION = 116, - /* Note that the Peer Link IE has been replaced with the similar - * Peer Management IE. We will keep the former definition until mesh - * code is changed to comply with latest 802.11s drafts. - */ - WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ WLAN_EID_PEER_MGMT = 117, WLAN_EID_CHAN_SWITCH_PARAM = 118, WLAN_EID_MESH_AWAKE_WINDOW = 119, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d86a15d..d29d11a 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2291,7 +2291,7 @@ struct ieee802_11_elems { struct ieee80211_ht_info *ht_info_elem; struct ieee80211_meshconf_ie *mesh_config; u8 *mesh_id; - u8 *peer_link; + u8 *peering; u8 *preq; u8 *prep; u8 *perr; @@ -2318,7 +2318,7 @@ struct ieee802_11_elems { u8 wmm_info_len; u8 wmm_param_len; u8 mesh_id_len; - u8 peer_link_len; + u8 peering_len; u8 preq_len; u8 prep_len; u8 perr_len; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1990869..da5e981 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -662,8 +662,14 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_rx_status *rx_status) { switch (mgmt->u.action.category) { - case WLAN_CATEGORY_MESH_ACTION: - mesh_rx_plink_frame(sdata, mgmt, len, rx_status); + case WLAN_CATEGORY_SELF_PROTECTED: + switch (mgmt->u.action.u.self_prot.action_code) { + case WLAN_SP_MESH_PEERING_OPEN: + case WLAN_SP_MESH_PEERING_CLOSE: + case WLAN_SP_MESH_PEERING_CONFIRM: + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); + break; + } break; case WLAN_CATEGORY_MESH_PATH_SEL: mesh_rx_path_sel_frame(sdata, mgmt, len); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 2cf2212..1a00d0f 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -19,8 +19,8 @@ #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) #endif -#define PLINK_GET_LLID(p) (p + 4) -#define PLINK_GET_PLID(p) (p + 6) +#define PLINK_GET_LLID(p) (p + 2) +#define PLINK_GET_PLID(p) (p + 4) #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ jiffies + HZ * t / 1000)) @@ -147,9 +147,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, sdata->u.mesh.ie_len); struct ieee80211_mgmt *mgmt; bool include_plid = false; - static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; + int ie_len = 4; + u16 peering_proto = 0; u8 *pos; - int ie_len; if (!skb) return -1; @@ -158,24 +158,23 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, * common action part (1) */ mgmt = (struct ieee80211_mgmt *) - skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); - memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); + skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot)); + memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot)); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; - mgmt->u.action.u.plink_action.action_code = action; + mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED; + mgmt->u.action.u.self_prot.action_code = action; - if (action == WLAN_SP_MESH_PEERING_CLOSE) - mgmt->u.action.u.plink_action.aux = reason; - else { - mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0); + if (action != WLAN_SP_MESH_PEERING_CLOSE) { + /* capability info */ + pos = skb_put(skb, 2); + memset(pos, 0, 2); if (action == WLAN_SP_MESH_PEERING_CONFIRM) { - pos = skb_put(skb, 4); - /* two-byte status code followed by two-byte AID */ - memset(pos, 0, 2); + /* AID */ + pos = skb_put(skb, 2); memcpy(pos + 2, &plid, 2); } if (mesh_add_srates_ie(skb, sdata) || @@ -184,42 +183,50 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata)) return -1; + } else { /* WLAN_SP_MESH_PEERING_CLOSE */ + if (mesh_add_meshid_ie(skb, sdata)) + return -1; } - /* Add Peer Link Management element */ + /* Add Mesh Peering Management element */ switch (action) { case WLAN_SP_MESH_PEERING_OPEN: - ie_len = 6; break; case WLAN_SP_MESH_PEERING_CONFIRM: - ie_len = 8; + ie_len += 2; include_plid = true; break; case WLAN_SP_MESH_PEERING_CLOSE: - default: - if (!plid) - ie_len = 8; - else { - ie_len = 10; + if (plid) { + ie_len += 2; include_plid = true; } + ie_len += 2; /* reason code */ break; + default: + return -EINVAL; } + if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) + return -ENOMEM; + pos = skb_put(skb, 2 + ie_len); - *pos++ = WLAN_EID_PEER_LINK; + *pos++ = WLAN_EID_PEER_MGMT; *pos++ = ie_len; - memcpy(pos, meshpeeringproto, sizeof(meshpeeringproto)); - pos += 4; + memcpy(pos, &peering_proto, 2); + pos += 2; memcpy(pos, &llid, 2); + pos += 2; if (include_plid) { - pos += 2; memcpy(pos, &plid, 2); + pos += 2; } if (action == WLAN_SP_MESH_PEERING_CLOSE) { - pos += 2; memcpy(pos, &reason, 2); + pos += 2; } + if (mesh_add_vendor_ies(skb, sdata)) + return -1; ieee80211_tx_skb(sdata, skb); return 0; @@ -437,15 +444,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - baseaddr = mgmt->u.action.u.plink_action.variable; - baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; - if (mgmt->u.action.u.plink_action.action_code == + baseaddr = mgmt->u.action.u.self_prot.variable; + baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; + if (mgmt->u.action.u.self_prot.action_code == WLAN_SP_MESH_PEERING_CONFIRM) { baseaddr += 4; baselen += 4; } ieee802_11_parse_elems(baseaddr, len - baselen, &elems); - if (!elems.peer_link) { + if (!elems.peering) { mpl_dbg("Mesh plink: missing necessary peer link ie\n"); return; } @@ -455,12 +462,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - ftype = mgmt->u.action.u.plink_action.action_code; - ie_len = elems.peer_link_len; - if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 6) || - (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 8) || - (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 8 - && ie_len != 10)) { + ftype = mgmt->u.action.u.self_prot.action_code; + ie_len = elems.peering_len; + if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || + (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || + (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 + && ie_len != 8)) { mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; @@ -474,10 +481,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m /* Note the lines below are correct, the llid in the frame is the plid * from the point of view of this host. */ - memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); + memcpy(&plid, PLINK_GET_LLID(elems.peering), 2); if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || - (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 10)) - memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); + (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) + memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); rcu_read_lock(); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fe2c2a7..3fb6dea 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2220,6 +2220,24 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto handled; } break; + case WLAN_CATEGORY_SELF_PROTECTED: + switch (mgmt->u.action.u.self_prot.action_code) { + case WLAN_SP_MESH_PEERING_OPEN: + case WLAN_SP_MESH_PEERING_CLOSE: + case WLAN_SP_MESH_PEERING_CONFIRM: + if (!ieee80211_vif_is_mesh(&sdata->vif)) + goto invalid; + if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) + /* userspace handles this frame */ + break; + goto queue; + case WLAN_SP_MGK_INFORM: + case WLAN_SP_MGK_ACK: + if (!ieee80211_vif_is_mesh(&sdata->vif)) + goto invalid; + break; + } + break; case WLAN_CATEGORY_MESH_ACTION: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; diff --git a/net/wireless/util.c b/net/wireless/util.c index 844ddb0..eef82f7 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1158,9 +1158,9 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, if (elen >= sizeof(struct ieee80211_meshconf_ie)) elems->mesh_config = (void *)pos; break; - case WLAN_EID_PEER_LINK: - elems->peer_link = pos; - elems->peer_link_len = elen; + case WLAN_EID_PEER_MGMT: + elems->peering = pos; + elems->peering_len = elen; break; case WLAN_EID_PREQ: elems->preq = pos; -- cgit v0.10.2 From 36c704fded53ee0d6866e8ae7f7e3d29cd4315b9 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 11 Aug 2011 19:35:14 -0700 Subject: ieee80211: add mesh action codes Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 819954a..58033c1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1307,6 +1307,21 @@ enum ieee80211_self_protected_actioncode { WLAN_SP_MGK_ACK = 5, }; +/* Mesh action codes */ +enum ieee80211_mesh_actioncode { + WLAN_MESH_ACTION_LINK_METRIC_REPORT, + WLAN_MESH_ACTION_HWMP_PATH_SELECTION, + WLAN_MESH_ACTION_GATE_ANNOUNCEMENT, + WLAN_MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION, + WLAN_MESH_ACTION_MCCA_SETUP_REQUEST, + WLAN_MESH_ACTION_MCCA_SETUP_REPLY, + WLAN_MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST, + WLAN_MESH_ACTION_MCCA_ADVERTISEMENT, + WLAN_MESH_ACTION_MCCA_TEARDOWN, + WLAN_MESH_ACTION_TBTT_ADJUSTMENT_REQUEST, + WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE, +}; + /* Security key length */ enum ieee80211_key_len { WLAN_KEY_LEN_WEP40 = 5, -- cgit v0.10.2 From 25d49e4d63564c7004a4d6735d1d8c3cc41a7394 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 11 Aug 2011 19:35:15 -0700 Subject: mac80211: update mesh path selection frame format Make mesh path selection frames Mesh Action category, remove outdated Mesh Path Selection category and defines, use updated reason codes, add mesh_action_is_path_sel for readability, and update/correct path selection IEs. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 58033c1..03cfbf3 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -629,6 +629,7 @@ struct ieee80211_rann_ie { u8 rann_ttl; u8 rann_addr[6]; u32 rann_seq; + u32 rann_interval; u32 rann_metric; } __attribute__ ((packed)); @@ -1269,9 +1270,6 @@ enum ieee80211_category { WLAN_CATEGORY_MULTIHOP_ACTION = 14, WLAN_CATEGORY_SELF_PROTECTED = 15, WLAN_CATEGORY_WMM = 17, - /* TODO: remove MESH_PATH_SEL after mesh is updated - * to current 802.11s draft */ - WLAN_CATEGORY_MESH_PATH_SEL = 32, WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, WLAN_CATEGORY_VENDOR_SPECIFIC = 127, }; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index da5e981..ecdde6c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -13,10 +13,6 @@ #include "ieee80211_i.h" #include "mesh.h" -#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) -#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) -#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) - #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 #define MESHCONF_CAPAB_FORWARDING 0x08 @@ -27,6 +23,17 @@ int mesh_allocated; static struct kmem_cache *rm_cache; +#ifdef CONFIG_MAC80211_MESH +bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) +{ + return (mgmt->u.action.u.mesh_action.action_code == + WLAN_MESH_ACTION_HWMP_PATH_SELECTION); +} +#else +bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) +{ return false; } +#endif + void ieee80211s_init(void) { mesh_pathtbl_init(); @@ -671,8 +678,9 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, break; } break; - case WLAN_CATEGORY_MESH_PATH_SEL: - mesh_rx_path_sel_frame(sdata, mgmt, len); + case WLAN_CATEGORY_MESH_ACTION: + if (mesh_action_is_path_sel(mgmt)) + mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index b794360..3c7d0f8 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -166,6 +166,9 @@ struct mesh_rmc { u32 idx_mask; }; +#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) +#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) +#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ @@ -177,14 +180,6 @@ struct mesh_rmc { /* Maximum number of paths per interface */ #define MESH_MAX_MPATHS 1024 -/* Pending ANA approval */ -#define MESH_PATH_SEL_ACTION 0 - -/* PERR reason codes */ -#define PEER_RCODE_UNSPECIFIED 11 -#define PERR_RCODE_NO_ROUTE 12 -#define PERR_RCODE_DEST_UNREACH 13 - /* Public interfaces */ /* Various */ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, @@ -276,6 +271,7 @@ void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); void mesh_path_restart(struct ieee80211_sub_if_data *sdata); void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); +bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); extern int mesh_paths_generation; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 3d8e55a..9c3c0b8 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -68,12 +68,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) #define PREP_IE_TTL(x) PREQ_IE_TTL(x) -#define PREP_IE_ORIG_ADDR(x) (x + 3) -#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) +#define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) +#define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x)) #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) -#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) -#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) +#define PREP_IE_TARGET_ADDR(x) (x + 3) +#define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0) #define PERR_IE_TTL(x) (*(x)) #define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) @@ -132,8 +132,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); /* BSSID == SA */ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; - mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; + mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; + mgmt->u.action.u.mesh_action.action_code = + WLAN_MESH_ACTION_HWMP_PATH_SELECTION; switch (action) { case MPATH_PREQ: @@ -163,29 +164,37 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, *pos++ = flags; *pos++ = hop_count; *pos++ = ttl; - if (action == MPATH_PREQ) { - memcpy(pos, &preq_id, 4); + if (action == MPATH_PREP) { + memcpy(pos, target, ETH_ALEN); + pos += ETH_ALEN; + memcpy(pos, &target_sn, 4); pos += 4; - } - memcpy(pos, orig_addr, ETH_ALEN); - pos += ETH_ALEN; - memcpy(pos, &orig_sn, 4); - pos += 4; - if (action != MPATH_RANN) { - memcpy(pos, &lifetime, 4); + } else { + if (action == MPATH_PREQ) { + memcpy(pos, &preq_id, 4); + pos += 4; + } + memcpy(pos, orig_addr, ETH_ALEN); + pos += ETH_ALEN; + memcpy(pos, &orig_sn, 4); pos += 4; } + memcpy(pos, &lifetime, 4); /* interval for RANN */ + pos += 4; memcpy(pos, &metric, 4); pos += 4; if (action == MPATH_PREQ) { - /* destination count */ - *pos++ = 1; + *pos++ = 1; /* destination count */ *pos++ = target_flags; - } - if (action != MPATH_RANN) { memcpy(pos, target, ETH_ALEN); pos += ETH_ALEN; memcpy(pos, &target_sn, 4); + pos += 4; + } else if (action == MPATH_PREP) { + memcpy(pos, orig_addr, ETH_ALEN); + pos += ETH_ALEN; + memcpy(pos, &orig_sn, 4); + pos += 4; } ieee80211_tx_skb(sdata, skb); @@ -224,9 +233,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, memcpy(mgmt->da, ra, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - /* BSSID is left zeroed, wildcard value */ - mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; - mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; + /* BSSID == SA */ + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); + mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; + mgmt->u.action.u.mesh_action.action_code = + WLAN_MESH_ACTION_HWMP_PATH_SELECTION; ie_len = 15; pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_PERR; @@ -683,6 +694,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, u8 ttl, flags, hopcount; u8 *orig_addr; u32 orig_sn, metric; + u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL); ttl = rann->rann_ttl; if (ttl <= 1) { @@ -715,7 +727,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, cpu_to_le32(orig_sn), 0, NULL, 0, broadcast_addr, - hopcount, ttl, 0, + hopcount, ttl, interval, cpu_to_le32(metric + mpath->metric), 0, sdata); mpath->sn = orig_sn; @@ -1006,10 +1018,11 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL); mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, cpu_to_le32(++ifmsh->sn), 0, NULL, 0, broadcast_addr, 0, sdata->u.mesh.mshcfg.element_ttl, - 0, 0, 0, sdata); + interval, 0, 0, sdata); } diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 068ee65..6ffcd53 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -539,6 +539,7 @@ void mesh_plink_broken(struct sta_info *sta) struct hlist_node *p; struct ieee80211_sub_if_data *sdata = sta->sdata; int i; + __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE); rcu_read_lock(); tbl = rcu_dereference(mesh_paths); @@ -553,8 +554,7 @@ void mesh_plink_broken(struct sta_info *sta) spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, mpath->dst, cpu_to_le32(mpath->sn), - cpu_to_le16(PERR_RCODE_DEST_UNREACH), - bcast, sdata); + reason, bcast, sdata); } else spin_unlock_bh(&mpath->state_lock); } @@ -699,6 +699,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct mesh_path *mpath; u32 sn = 0; + __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { u8 *ra, *da; @@ -709,8 +710,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, if (mpath) sn = ++mpath->sn; mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, - cpu_to_le32(sn), - cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); + cpu_to_le32(sn), reason, ra, sdata); } kfree_skb(skb); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3fb6dea..c4453fd 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2241,9 +2241,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) case WLAN_CATEGORY_MESH_ACTION: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; - goto queue; - case WLAN_CATEGORY_MESH_PATH_SEL: - if (!mesh_path_sel_is_hwmp(sdata)) + if (mesh_action_is_path_sel(mgmt) && + (!mesh_path_sel_is_hwmp(sdata))) break; goto queue; } -- cgit v0.10.2 From a63d7e67fc259249c563878f8e296a2ed6def039 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Fri, 12 Aug 2011 12:20:21 +0530 Subject: mwl8k: Traffic to clients gets affected when one client leaves a cyrpto bss When a client disassociates from a crypto enabled bss, data traffic to other clients connected to the bss is stalled. This was due to a boolean variable used to keep track if HW crypto is enabled i.e. if set key has been called to add a key. This flag was being reset every time delete key was called e.g when a station leaves the bss. Once the flag is reset, rx status flags were not being set for connected clients which disrupts traffic to these clients. Fix this issue by not resetting the flag since we do not need to reset this flag during the life time of the bss. Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index da36dbf..771280a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -4097,9 +4097,6 @@ static int mwl8k_set_key(struct ieee80211_hw *hw, if (rc) goto out; - - mwl8k_vif->is_hw_crypto_enabled = false; - } out: return rc; -- cgit v0.10.2 From 15222b582dc761ba1eb1ed47367df43f803f3670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 12 Aug 2011 13:13:44 +0200 Subject: b43: HT-PHY: init: zero EXTG registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 7c40919..99b3035 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -152,6 +152,24 @@ static void b43_radio_2059_init(struct b43_wldev *dev) } /************************************************** + * Various PHY ops + **************************************************/ + +static void b43_phy_ht_zero_extg(struct b43_wldev *dev) +{ + u8 i, j; + u16 base[] = { 0x40, 0x60, 0x80 }; + + for (i = 0; i < ARRAY_SIZE(base); i++) { + for (j = 0; j < 4; j++) + b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0); + } + + for (i = 0; i < ARRAY_SIZE(base); i++) + b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); +} + +/************************************************** * Channel switching ops. **************************************************/ @@ -257,6 +275,10 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) { b43_phy_ht_tables_init(dev); + /* TODO: PHY ops on regs 0x0be, 0x23f 0x240 0x241 */ + + b43_phy_ht_zero_extg(dev); + return 0; } -- cgit v0.10.2 From f457f1842d3ad0f24cc0b181e60b6c59ed1d90ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 12 Aug 2011 13:13:45 +0200 Subject: b43: HT-PHY: init: implement few simple PHY writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 99b3035..93ee0e4 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -279,6 +279,28 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_phy_ht_zero_extg(dev); + /* TODO: PHY op on reg B43_PHY_EXTG(0) */ + + b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); + b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); + b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); + + b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); + b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); + b43_phy_write(dev, 0x20d, 0xb8); + b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); + b43_phy_write(dev, 0x70, 0x50); + b43_phy_write(dev, 0x1ff, 0x30); + + if (0) /* TODO: condition */ + ; /* TODO: PHY op on reg 0x217 */ + + ; /* TODO: PHY op on reg 0xb0 */ + + ; /* TODO: PHY ops on regs 0xb1, 0x32f, 0x077, 0x0b4, 0x17e */ + + b43_phy_write(dev, 0x0b9, 0x0072); + return 0; } -- cgit v0.10.2 From 19240f36cf4c4ccc9a1b0a368d0fd59c9bbbfba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 12 Aug 2011 13:13:46 +0200 Subject: b43: HT-PHY: init: copy tables and reset CCA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 93ee0e4..55cf0f2 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -273,6 +273,8 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) static int b43_phy_ht_op_init(struct b43_wldev *dev) { + u16 tmp; + b43_phy_ht_tables_init(dev); /* TODO: PHY ops on regs 0x0be, 0x23f 0x240 0x241 */ @@ -301,6 +303,25 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_phy_write(dev, 0x0b9, 0x0072); + /* TODO: Some ops here */ + + /* Copy some tables entries */ + tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); + b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); + tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); + b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); + tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); + b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); + + /* Reset CCA */ + b43_phy_force_clock(dev, true); + tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); + b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); + b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); + b43_phy_force_clock(dev, false); + + b43_mac_phy_clock_set(dev, true); + return 0; } diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h index 7ad7aff..f70af0c 100644 --- a/drivers/net/wireless/b43/phy_ht.h +++ b/drivers/net/wireless/b43/phy_ht.h @@ -4,7 +4,11 @@ #include "phy_common.h" +#define B43_PHY_HT_BBCFG 0x001 /* BB config */ +#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */ +#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */ #define B43_PHY_HT_BANDCTL 0x009 /* Band control */ +#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */ #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ -- cgit v0.10.2 From b50583484ab60ba5c3af9eff476a2cc712cf7f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 12 Aug 2011 15:27:34 +0200 Subject: b43: HT-PHY: init: init BPHY and upload 0x1a table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 55cf0f2..96b699e 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -169,6 +169,24 @@ static void b43_phy_ht_zero_extg(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); } +static void b43_phy_ht_bphy_init(struct b43_wldev *dev) +{ + unsigned int i; + u16 val; + + val = 0x1E1F; + for (i = 0; i < 16; i++) { + b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); + val -= 0x202; + } + val = 0x3E3F; + for (i = 0; i < 16; i++) { + b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); + val -= 0x202; + } + b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); +} + /************************************************** * Channel switching ops. **************************************************/ @@ -322,6 +340,14 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_mac_phy_clock_set(dev, true); + /* TODO: Some ops here */ + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_phy_ht_bphy_init(dev); + + b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), + B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); + return 0; } diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c index 6039386..2127bd2 100644 --- a/drivers/net/wireless/b43/tables_phy_ht.c +++ b/drivers/net/wireless/b43/tables_phy_ht.c @@ -574,6 +574,42 @@ static const u32 b43_httab_0x24[] = { 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c, }; +/* Some late-init table */ +const u32 b43_httab_0x1a_0xc0_late[] = { + 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, + 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, + 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, + 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, + 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, + 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, + 0x10390038, 0x10390035, 0x1031003a, 0x10310036, + 0x10310033, 0x1029003a, 0x10290037, 0x10290034, + 0x10290031, 0x10210039, 0x10210036, 0x10210033, + 0x10210030, 0x1019003c, 0x10190039, 0x10190036, + 0x10190033, 0x10190030, 0x1019002d, 0x1019002b, + 0x10190028, 0x1011003a, 0x10110036, 0x10110033, + 0x10110030, 0x1011002e, 0x1011002b, 0x10110029, + 0x10110027, 0x10110024, 0x10110022, 0x10110020, + 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, + 0x10090034, 0x10090031, 0x1009002e, 0x1009002c, + 0x10090029, 0x10090027, 0x10090025, 0x10090023, + 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, + 0x1009001a, 0x10090018, 0x10090017, 0x10090016, + 0x10090015, 0x10090013, 0x10090012, 0x10090011, + 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, + 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, + 0x1009000a, 0x1009000a, 0x10090009, 0x10090009, + 0x10090008, 0x10090008, 0x10090007, 0x10090007, + 0x10090007, 0x10090006, 0x10090006, 0x10090005, + 0x10090005, 0x10090005, 0x10090005, 0x10090004, + 0x10090004, 0x10090004, 0x10090004, 0x10090003, + 0x10090003, 0x10090003, 0x10090003, 0x10090003, + 0x10090003, 0x10090002, 0x10090002, 0x10090002, + 0x10090002, 0x10090002, 0x10090002, 0x10090002, + 0x10090002, 0x10090002, 0x10090001, 0x10090001, + 0x10090001, 0x10090001, 0x10090001, 0x10090001, +}; + /************************************************** * R/W ops. **************************************************/ @@ -723,6 +759,9 @@ void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, } while (0) void b43_phy_ht_tables_init(struct b43_wldev *dev) { + BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) != + B43_HTTAB_1A_C0_LATE_SIZE); + httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12); httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27); httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26); diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h index ea3be38..bd20e9a 100644 --- a/drivers/net/wireless/b43/tables_phy_ht.h +++ b/drivers/net/wireless/b43/tables_phy_ht.h @@ -19,4 +19,7 @@ void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, void b43_phy_ht_tables_init(struct b43_wldev *dev); +#define B43_HTTAB_1A_C0_LATE_SIZE 128 +extern const u32 b43_httab_0x1a_0xc0_late[]; + #endif /* B43_TABLES_PHY_HT_H_ */ -- cgit v0.10.2 From 357e24d2d07a2bb5bf706026d1ccf508c56b9b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 13 Aug 2011 01:41:11 +0200 Subject: b43: HT-PHY: init: add missing PHY mask/set ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MMIO hacks were used to trick ndis&wl. For example following: phy_read(0x0280) -> 0xffff phy_write(0x0280) <- 0xff3e *** phy_read(0x0280) -> 0x0000 phy_write(0x0280) <- 0x003e was translated to mask 0xff00 and set 0x3e. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 96b699e..651938e 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -291,15 +291,19 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) static int b43_phy_ht_op_init(struct b43_wldev *dev) { + u8 i; u16 tmp; b43_phy_ht_tables_init(dev); - /* TODO: PHY ops on regs 0x0be, 0x23f 0x240 0x241 */ + b43_phy_mask(dev, 0x0be, ~0x2); + b43_phy_set(dev, 0x23f, 0x7ff); + b43_phy_set(dev, 0x240, 0x7ff); + b43_phy_set(dev, 0x241, 0x7ff); b43_phy_ht_zero_extg(dev); - /* TODO: PHY op on reg B43_PHY_EXTG(0) */ + b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); @@ -315,14 +319,35 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) if (0) /* TODO: condition */ ; /* TODO: PHY op on reg 0x217 */ - ; /* TODO: PHY op on reg 0xb0 */ + b43_phy_read(dev, 0xb0); /* TODO: what for? */ + b43_phy_set(dev, 0xb0, 0x1); - ; /* TODO: PHY ops on regs 0xb1, 0x32f, 0x077, 0x0b4, 0x17e */ + b43_phy_set(dev, 0xb1, 0x91); + b43_phy_write(dev, 0x32f, 0x0003); + b43_phy_write(dev, 0x077, 0x0010); + b43_phy_write(dev, 0x0b4, 0x0258); + b43_phy_mask(dev, 0x17e, ~0x4000); b43_phy_write(dev, 0x0b9, 0x0072); /* TODO: Some ops here */ + b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); + b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); + b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); + b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); + + /* TODO: Some ops here */ + + b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); + b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); + b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); + + b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); + b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); + b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); + b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); + /* Copy some tables entries */ tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); @@ -340,7 +365,18 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_mac_phy_clock_set(dev, true); - /* TODO: Some ops here */ + for (i = 0; i < 2; i++) { + tmp = b43_phy_read(dev, B43_PHY_EXTG(0)); + b43_phy_set(dev, B43_PHY_EXTG(0), 0x3); + b43_phy_set(dev, B43_PHY_EXTG(3), i ? 0x20 : 0x1); + /* FIXME: wait for some bit to be cleared (find out which) */ + b43_phy_read(dev, B43_PHY_EXTG(4)); + b43_phy_write(dev, B43_PHY_EXTG(0), tmp); + } + + /* TODO: PHY op on reg 0xb0 */ + + /* TODO: PHY ops on regs 0x40e, 0x44e, 0x48e */ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) b43_phy_ht_bphy_init(dev); -- cgit v0.10.2 From a4042bb0932832328650fe9fb93d9afcb6699a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 13 Aug 2011 01:41:12 +0200 Subject: b43: HT-PHY: init: add some AFE (Analog Frontend) operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 651938e..8a92d6e 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -169,6 +169,28 @@ static void b43_phy_ht_zero_extg(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); } +/* Some unknown AFE (Analog Frondned) op */ +static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) +{ + u8 i; + + const u16 ctl_regs[3][2] = { + { B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 }, + { B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 }, + { B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6}, + }; + + for (i = 0; i < 3; i++) { + /* TODO: verify masks&sets */ + b43_phy_set(dev, ctl_regs[i][1], 0x4); + b43_phy_set(dev, ctl_regs[i][0], 0x4); + b43_phy_mask(dev, ctl_regs[i][1], ~0x1); + b43_phy_set(dev, ctl_regs[i][0], 0x1); + b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0); + b43_phy_mask(dev, ctl_regs[i][0], ~0x4); + } +} + static void b43_phy_ht_bphy_init(struct b43_wldev *dev) { unsigned int i; @@ -332,6 +354,10 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) /* TODO: Some ops here */ + b43_phy_ht_afe_unk1(dev); + + /* TODO: Some ops here */ + b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); -- cgit v0.10.2 From b5be7e4c8f7bc60625302979a5c445738e3b1034 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Sat, 13 Aug 2011 12:12:36 +0200 Subject: rtlwifi: add module parameter to set global debug level No need to recompile the module anymore to set the debug level. Signed-off-by: Stefan Assmann Signed-off-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c index 5fa7385..b2f897a 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/rtlwifi/debug.c @@ -28,12 +28,16 @@ #include "wifi.h" +static unsigned int debug = DBG_EMERG; +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, "Set global debug level for rtlwifi (0,2-5)"); + void rtl_dbgp_flag_init(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 i; - rtlpriv->dbg.global_debuglevel = DBG_EMERG; + rtlpriv->dbg.global_debuglevel = debug; rtlpriv->dbg.global_debugcomponents = COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND | -- cgit v0.10.2 From 98f8dc72ac50a931b982d0610d9ec08292ceafdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 13 Aug 2011 17:54:04 +0200 Subject: b43: HT-PHY: init: add missing small-tables writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 8a92d6e..62a9084 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -352,18 +352,45 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_phy_write(dev, 0x0b9, 0x0072); - /* TODO: Some ops here */ + b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); + b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); + b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); b43_phy_ht_afe_unk1(dev); - /* TODO: Some ops here */ + b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, + 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); + + b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); + b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); + + b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); + b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); + b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); + + b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, + 0x8e, 0x96, 0x96, 0x96); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, + 0x8f, 0x9f, 0x9f, 0x9f); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, + 0x8f, 0x9f, 0x9f, 0x9f); + + b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); - /* TODO: Some ops here */ + b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, + 0x09, 0x0e, 0x13, 0x18); + b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, + 0x09, 0x0e, 0x13, 0x18); + /* TODO: Did wl mean 2 instead of 40? */ + b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, + 0x09, 0x0e, 0x13, 0x18); b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); -- cgit v0.10.2 From 87a8c8cb2001a64034f1bd64980ab826402ab881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 23 Aug 2011 19:09:30 +0200 Subject: b43: HT-PHY: allow writing longer tables with a single call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes we need to write table which is 2-10 elements long. It's easier to create such a function instead of defining array every time. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c index 2127bd2..677d217 100644 --- a/drivers/net/wireless/b43/tables_phy_ht.c +++ b/drivers/net/wireless/b43/tables_phy_ht.c @@ -710,6 +710,51 @@ void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value) return; } +void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...) +{ + va_list args; + u32 type, value; + unsigned int i; + + type = offset & B43_HTTAB_TYPEMASK; + offset &= 0xFFFF; + + va_start(args, num); + switch (type) { + case B43_HTTAB_8BIT: + b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + for (i = 0; i < num; i++) { + value = va_arg(args, int); + B43_WARN_ON(value & ~0xFF); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); + } + break; + case B43_HTTAB_16BIT: + b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + for (i = 0; i < num; i++) { + value = va_arg(args, int); + B43_WARN_ON(value & ~0xFFFF); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); + } + break; + case B43_HTTAB_32BIT: + b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + for (i = 0; i < num; i++) { + value = va_arg(args, int); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, + value >> 16); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, + value & 0xFFFF); + } + break; + default: + B43_WARN_ON(1); + } + va_end(args); + + return; +} + void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data) { diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h index bd20e9a..1b5ef2b 100644 --- a/drivers/net/wireless/b43/tables_phy_ht.h +++ b/drivers/net/wireless/b43/tables_phy_ht.h @@ -14,6 +14,7 @@ u32 b43_httab_read(struct b43_wldev *dev, u32 offset); void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, void *_data); void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...); void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data); -- cgit v0.10.2 From 7646887a5390123475fdd621620b9f270b38df98 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:04 -0700 Subject: mac80211: improve mpath debugging make hwmp_dbg print the relevant sdata->name by default and improve formatting. Also add mpath_dbg macro for debugging of mesh path operations. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index f5fdfcb..d1886b5 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -199,6 +199,19 @@ config MAC80211_VERBOSE_MPL_DEBUG Do not select this option. +config MAC80211_VERBOSE_MPATH_DEBUG + bool "Verbose mesh path debugging" + depends on MAC80211_DEBUG_MENU + depends on MAC80211_MESH + ---help--- + Selecting this option causes mac80211 to print out very + verbose mesh path selection debugging messages (when mac80211 + is taking part in a mesh network). + It should not be selected on production systems as those + messages are remotely triggerable. + + Do not select this option. + config MAC80211_VERBOSE_MHWMP_DEBUG bool "Verbose mesh HWMP routing debugging" depends on MAC80211_DEBUG_MENU diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 9c3c0b8..abd0347 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -11,7 +11,8 @@ #include "mesh.h" #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG -#define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args) +#define mhwmp_dbg(fmt, args...) \ + printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) #else #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) #endif @@ -138,19 +139,19 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, switch (action) { case MPATH_PREQ: - mhwmp_dbg("sending PREQ to %pM\n", target); + mhwmp_dbg("sending PREQ to %pM", target); ie_len = 37; pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_PREQ; break; case MPATH_PREP: - mhwmp_dbg("sending PREP to %pM\n", target); + mhwmp_dbg("sending PREP to %pM", target); ie_len = 31; pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_PREP; break; case MPATH_RANN: - mhwmp_dbg("sending RANN from %pM\n", orig_addr); + mhwmp_dbg("sending RANN from %pM", orig_addr); ie_len = sizeof(struct ieee80211_rann_ie); pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_RANN; @@ -494,10 +495,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, orig_sn = PREQ_IE_ORIG_SN(preq_elem); target_flags = PREQ_IE_TARGET_F(preq_elem); - mhwmp_dbg("received PREQ from %pM\n", orig_addr); + mhwmp_dbg("received PREQ from %pM", orig_addr); if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { - mhwmp_dbg("PREQ is for us\n"); + mhwmp_dbg("PREQ is for us"); forward = false; reply = true; metric = 0; @@ -533,7 +534,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, lifetime = PREQ_IE_LIFETIME(preq_elem); ttl = ifmsh->mshcfg.element_ttl; if (ttl != 0) { - mhwmp_dbg("replying to the PREQ\n"); + mhwmp_dbg("replying to the PREQ"); mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, cpu_to_le32(target_sn), 0, orig_addr, cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, @@ -553,7 +554,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ifmsh->mshstats.dropped_frames_ttl++; return; } - mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr); + mhwmp_dbg("forwarding the PREQ from %pM", orig_addr); --ttl; flags = PREQ_IE_FLAGS(preq_elem); preq_id = PREQ_IE_PREQ_ID(preq_elem); @@ -588,7 +589,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, u8 next_hop[ETH_ALEN]; u32 target_sn, orig_sn, lifetime; - mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem)); + mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); /* Note that we divert from the draft nomenclature and denominate * destination to what the draft refers to as origininator. So in this @@ -799,7 +800,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); if (!preq_node) { - mhwmp_dbg("could not allocate PREQ node\n"); + mhwmp_dbg("could not allocate PREQ node"); return; } @@ -808,7 +809,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); kfree(preq_node); if (printk_ratelimit()) - mhwmp_dbg("PREQ node queue full\n"); + mhwmp_dbg("PREQ node queue full"); return; } diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 6ffcd53..bd6b8b3 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -17,6 +17,12 @@ #include "ieee80211_i.h" #include "mesh.h" +#ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG +#define mpath_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) +#else +#define mpath_dbg(fmt, args...) do { (void)(0); } while (0) +#endif + /* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */ #define INIT_PATHS_SIZE_ORDER 2 -- cgit v0.10.2 From 86d7f9f35dcc686d57465798201e678040916979 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:05 -0700 Subject: mac80211: fix mpath timer NULL function If we have an mpath whose timer has not been initialized, don't try to delete it. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index bd6b8b3..bfd7638 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -619,7 +619,8 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) struct mpath_node *node = container_of(rp, struct mpath_node, rcu); struct ieee80211_sub_if_data *sdata = node->mpath->sdata; - del_timer_sync(&node->mpath->timer); + if (node->mpath->timer.function) + del_timer_sync(&node->mpath->timer); atomic_dec(&sdata->u.mesh.mpaths); kfree(node->mpath); kfree(node); @@ -768,7 +769,8 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs) mpath = node->mpath; hlist_del_rcu(p); if (free_leafs) { - del_timer_sync(&mpath->timer); + if (mpath->timer.function) + del_timer_sync(&mpath->timer); kfree(mpath); } kfree(node); -- cgit v0.10.2 From a6965c44e981214c7483e020106a30a869411231 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:06 -0700 Subject: mac80211: mesh locking fixes mesh_queue_preq is invoked invoked from both user (work queue) and softirq (timer) context, so the _bh version of spinlock needs to be used. Also, the mpath->state_lock should be softirq safe as well. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index bfd7638..385f9fc 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -654,12 +654,12 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) mpath = node->mpath; if (mpath->sdata == sdata && memcmp(addr, mpath->dst, ETH_ALEN) == 0) { - spin_lock(&mpath->state_lock); + spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; hlist_del_rcu(&node->list); call_rcu(&node->rcu, mesh_path_node_reclaim); atomic_dec(&tbl->entries); - spin_unlock(&mpath->state_lock); + spin_unlock_bh(&mpath->state_lock); goto enddel; } } -- cgit v0.10.2 From 00e3f25c8556384bfec2a168c41e885fa6a7748c Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:07 -0700 Subject: mac80211: fix mesh path flushing Previously, mpaths were never flushed since the mpath is not active once we call this function. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 385f9fc..bcf7fee 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -735,8 +735,7 @@ void mesh_path_flush_pending(struct mesh_path *mpath) { struct sk_buff *skb; - while ((skb = skb_dequeue(&mpath->frame_queue)) && - (mpath->flags & MESH_PATH_ACTIVE)) + while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) mesh_path_discard_frame(skb, mpath->sdata); } -- cgit v0.10.2 From 5ee68e5b39de5cefecf147c58711f8ab01c21231 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:08 -0700 Subject: mac80211: mesh gate implementation In this implementation, a mesh gate is a root node with a certain bit set in its RANN flags. The mpath to this root node is marked as a path to a gate, and added to our list of known gates for this if_mesh. Once a path discovery process fails, we forward the unresolved frames to a known gate. Thanks to Luis Rodriguez for refactoring and bug fix help. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 03cfbf3..37f95f2 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -633,6 +633,10 @@ struct ieee80211_rann_ie { u32 rann_metric; } __attribute__ ((packed)); +enum ieee80211_rann_flags { + RANN_FLAG_IS_GATE = 1 << 0, +}; + #define WLAN_SA_QUERY_TR_ID_LEN 2 struct ieee80211_mgmt { diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ea74190..c204cee 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -514,6 +514,7 @@ struct ieee80211_if_mesh { struct mesh_config mshcfg; u32 mesh_seqnum; bool accepting_plinks; + int num_gates; const u8 *ie; u8 ie_len; enum { diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index ecdde6c..e120fef 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -545,7 +545,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - /* use atomic bitops in case both timers fire at the same time */ + /* use atomic bitops in case all timers fire at the same time */ if (del_timer_sync(&ifmsh->housekeeping_timer)) set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); @@ -752,6 +752,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ifmsh->accepting_plinks = true; ifmsh->preq_id = 0; ifmsh->sn = 0; + ifmsh->num_gates = 0; atomic_set(&ifmsh->mpaths, 0); mesh_rmc_init(sdata); ifmsh->last_preq = jiffies; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 3c7d0f8..9d9116e 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -81,6 +81,7 @@ enum mesh_deferred_task_flags { * @discovery_retries: number of discovery retries * @flags: mesh path flags, as specified on &enum mesh_path_flags * @state_lock: mesh path state lock + * @is_gate: the destination station of this path is a mesh gate * * * The combination of dst and sdata is unique in the mesh path table. Since the @@ -104,6 +105,7 @@ struct mesh_path { u8 discovery_retries; enum mesh_path_flags flags; spinlock_t state_lock; + bool is_gate; }; /** @@ -120,6 +122,9 @@ struct mesh_path { * buckets * @mean_chain_len: maximum average length for the hash buckets' list, if it is * reached, the table will grow + * @known_gates: list of known mesh gates and their mpaths by the station. The + * gate's mpath may or may not be resolved and active. + * * rcu_head: RCU head to free the table */ struct mesh_table { @@ -133,6 +138,8 @@ struct mesh_table { int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); int size_order; int mean_chain_len; + struct hlist_head *known_gates; + spinlock_t gates_lock; struct rcu_head rcu_head; }; @@ -236,6 +243,10 @@ void mesh_path_flush(struct ieee80211_sub_if_data *sdata); void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len); int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); + +int mesh_path_add_gate(struct mesh_path *mpath); +int mesh_path_send_to_gates(struct mesh_path *mpath); +int mesh_gate_num(struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index abd0347..7b517c4 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -696,6 +696,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, u8 *orig_addr; u32 orig_sn, metric; u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL); + bool root_is_gate; ttl = rann->rann_ttl; if (ttl <= 1) { @@ -704,12 +705,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, } ttl--; flags = rann->rann_flags; + root_is_gate = !!(flags & RANN_FLAG_IS_GATE); orig_addr = rann->rann_addr; orig_sn = rann->rann_seq; hopcount = rann->rann_hopcount; hopcount++; metric = rann->rann_metric; - mhwmp_dbg("received RANN from %pM\n", orig_addr); + + /* Ignore our own RANNs */ + if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) + return; + + mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr, + root_is_gate); rcu_read_lock(); mpath = mesh_path_lookup(orig_addr, sdata); @@ -721,9 +729,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, sdata->u.mesh.mshstats.dropped_frames_no_route++; return; } - mesh_queue_preq(mpath, - PREQ_Q_F_START | PREQ_Q_F_REFRESH); } + + if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) || + time_after(jiffies, mpath->exp_time - 1*HZ)) && + !(mpath->flags & MESH_PATH_FIXED)) { + mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name, + orig_addr); + mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); + } + if (mpath->sn < orig_sn) { mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, cpu_to_le32(orig_sn), @@ -733,6 +748,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, 0, sdata); mpath->sn = orig_sn; } + if (root_is_gate) + mesh_path_add_gate(mpath); + rcu_read_unlock(); } @@ -994,25 +1012,32 @@ void mesh_path_timer(unsigned long data) { struct mesh_path *mpath = (void *) data; struct ieee80211_sub_if_data *sdata = mpath->sdata; + int ret; if (sdata->local->quiescing) return; spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_RESOLVED || - (!(mpath->flags & MESH_PATH_RESOLVING))) + (!(mpath->flags & MESH_PATH_RESOLVING))) { mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); - else if (mpath->discovery_retries < max_preq_retries(sdata)) { + spin_unlock_bh(&mpath->state_lock); + } else if (mpath->discovery_retries < max_preq_retries(sdata)) { ++mpath->discovery_retries; mpath->discovery_timeout *= 2; + spin_unlock_bh(&mpath->state_lock); mesh_queue_preq(mpath, 0); } else { mpath->flags = 0; mpath->exp_time = jiffies; - mesh_path_flush_pending(mpath); + spin_unlock_bh(&mpath->state_lock); + if (!mpath->is_gate && mesh_gate_num(sdata) > 0) { + ret = mesh_path_send_to_gates(mpath); + if (ret) + mhwmp_dbg("no gate was reachable"); + } else + mesh_path_flush_pending(mpath); } - - spin_unlock_bh(&mpath->state_lock); } void diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index bcf7fee..75e4b60 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -66,6 +66,8 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void) lockdep_is_held(&pathtbl_resize_lock)); } +static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath); + /* * CAREFUL -- "tbl" must not be an expression, * in particular not an rcu_dereference(), since @@ -109,6 +111,7 @@ static struct mesh_table *mesh_table_alloc(int size_order) sizeof(newtbl->hash_rnd)); for (i = 0; i <= newtbl->hash_mask; i++) spin_lock_init(&newtbl->hashwlock[i]); + spin_lock_init(&newtbl->gates_lock); return newtbl; } @@ -124,6 +127,7 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) { struct hlist_head *mesh_hash; struct hlist_node *p, *q; + struct mpath_node *gate; int i; mesh_hash = tbl->hash_buckets; @@ -135,6 +139,17 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) } spin_unlock_bh(&tbl->hashwlock[i]); } + if (free_leafs) { + spin_lock_bh(&tbl->gates_lock); + hlist_for_each_entry_safe(gate, p, q, + tbl->known_gates, list) { + hlist_del(&gate->list); + kfree(gate); + } + kfree(tbl->known_gates); + spin_unlock_bh(&tbl->gates_lock); + } + __mesh_table_free(tbl); } @@ -152,6 +167,7 @@ static int mesh_table_grow(struct mesh_table *oldtbl, newtbl->free_node = oldtbl->free_node; newtbl->mean_chain_len = oldtbl->mean_chain_len; newtbl->copy_node = oldtbl->copy_node; + newtbl->known_gates = oldtbl->known_gates; atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); oldhash = oldtbl->hash_buckets; @@ -211,6 +227,111 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); } +static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, + struct mesh_path *gate_mpath) +{ + struct ieee80211_hdr *hdr; + struct ieee80211s_hdr *mshdr; + int mesh_hdrlen, hdrlen; + char *next_hop; + + hdr = (struct ieee80211_hdr *) skb->data; + hdrlen = ieee80211_hdrlen(hdr->frame_control); + mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + + if (!(mshdr->flags & MESH_FLAGS_AE)) { + /* size of the fixed part of the mesh header */ + mesh_hdrlen = 6; + + /* make room for the two extended addresses */ + skb_push(skb, 2 * ETH_ALEN); + memmove(skb->data, hdr, hdrlen + mesh_hdrlen); + + hdr = (struct ieee80211_hdr *) skb->data; + + /* we preserve the previous mesh header and only add + * the new addreses */ + mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + mshdr->flags = MESH_FLAGS_AE_A5_A6; + memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN); + memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN); + } + + /* update next hop */ + hdr = (struct ieee80211_hdr *) skb->data; + rcu_read_lock(); + next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; + memcpy(hdr->addr1, next_hop, ETH_ALEN); + rcu_read_unlock(); + memcpy(hdr->addr3, dst_addr, ETH_ALEN); +} + +/** + * + * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another + * + * This function is used to transfer or copy frames from an unresolved mpath to + * a gate mpath. The function also adds the Address Extension field and + * updates the next hop. + * + * If a frame already has an Address Extension field, only the next hop and + * destination addresses are updated. + * + * The gate mpath must be an active mpath with a valid mpath->next_hop. + * + * @mpath: An active mpath the frames will be sent to (i.e. the gate) + * @from_mpath: The failed mpath + * @copy: When true, copy all the frames to the new mpath queue. When false, + * move them. + */ +static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, + struct mesh_path *from_mpath, + bool copy) +{ + struct sk_buff *skb, *cp_skb; + struct sk_buff_head gateq, failq; + unsigned long flags; + int num_skbs; + + BUG_ON(gate_mpath == from_mpath); + BUG_ON(!gate_mpath->next_hop); + + __skb_queue_head_init(&gateq); + __skb_queue_head_init(&failq); + + spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); + skb_queue_splice_init(&from_mpath->frame_queue, &failq); + spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); + + num_skbs = skb_queue_len(&failq); + + while (num_skbs--) { + skb = __skb_dequeue(&failq); + if (copy) + cp_skb = skb_copy(skb, GFP_ATOMIC); + + prepare_for_gate(skb, gate_mpath->dst, gate_mpath); + __skb_queue_tail(&gateq, skb); + + if (copy && cp_skb) + __skb_queue_tail(&failq, cp_skb); + } + + spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); + skb_queue_splice(&gateq, &gate_mpath->frame_queue); + mpath_dbg("Mpath queue for gate %pM has %d frames\n", + gate_mpath->dst, + skb_queue_len(&gate_mpath->frame_queue)); + spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); + + if (!copy) + return; + + spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); + skb_queue_splice(&failq, &from_mpath->frame_queue); + spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); +} + /** * mesh_path_lookup - look up a path in the mesh path table @@ -310,6 +431,109 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data return NULL; } +static void mesh_gate_node_reclaim(struct rcu_head *rp) +{ + struct mpath_node *node = container_of(rp, struct mpath_node, rcu); + kfree(node); +} + +/** + * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates + * @mesh_tbl: table which contains known_gates list + * @mpath: mpath to known mesh gate + * + * Returns: 0 on success + * + */ +static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath) +{ + struct mpath_node *gate, *new_gate; + struct hlist_node *n; + int err; + + rcu_read_lock(); + tbl = rcu_dereference(tbl); + + hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list) + if (gate->mpath == mpath) { + err = -EEXIST; + goto err_rcu; + } + + new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC); + if (!new_gate) { + err = -ENOMEM; + goto err_rcu; + } + + mpath->is_gate = true; + mpath->sdata->u.mesh.num_gates++; + new_gate->mpath = mpath; + spin_lock_bh(&tbl->gates_lock); + hlist_add_head_rcu(&new_gate->list, tbl->known_gates); + spin_unlock_bh(&tbl->gates_lock); + rcu_read_unlock(); + mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n", + mpath->sdata->name, mpath->dst, + mpath->sdata->u.mesh.num_gates); + return 0; +err_rcu: + rcu_read_unlock(); + return err; +} + +/** + * mesh_gate_del - remove a mesh gate from the list of known gates + * @tbl: table which holds our list of known gates + * @mpath: gate mpath + * + * Returns: 0 on success + * + * Locking: must be called inside rcu_read_lock() section + */ +static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) +{ + struct mpath_node *gate; + struct hlist_node *p, *q; + + tbl = rcu_dereference(tbl); + + hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) + if (gate->mpath == mpath) { + spin_lock_bh(&tbl->gates_lock); + hlist_del_rcu(&gate->list); + call_rcu(&gate->rcu, mesh_gate_node_reclaim); + spin_unlock_bh(&tbl->gates_lock); + mpath->sdata->u.mesh.num_gates--; + mpath->is_gate = false; + mpath_dbg("Mesh path (%s): Deleted gate: %pM. " + "%d known gates\n", mpath->sdata->name, + mpath->dst, mpath->sdata->u.mesh.num_gates); + break; + } + + return 0; +} + +/** + * + * mesh_path_add_gate - add the given mpath to a mesh gate to our path table + * @mpath: gate path to add to table + */ +int mesh_path_add_gate(struct mesh_path *mpath) +{ + return mesh_gate_add(mesh_paths, mpath); +} + +/** + * mesh_gate_num - number of gates known to this interface + * @sdata: subif data + */ +int mesh_gate_num(struct ieee80211_sub_if_data *sdata) +{ + return sdata->u.mesh.num_gates; +} + /** * mesh_path_add - allocate and add a new path to the mesh path table * @addr: destination address of the path (ETH_ALEN length) @@ -655,6 +879,8 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) if (mpath->sdata == sdata && memcmp(addr, mpath->dst, ETH_ALEN) == 0) { spin_lock_bh(&mpath->state_lock); + if (mpath->is_gate) + mesh_gate_del(tbl, mpath); mpath->flags |= MESH_PATH_RESOLVING; hlist_del_rcu(&node->list); call_rcu(&node->rcu, mesh_path_node_reclaim); @@ -688,6 +914,58 @@ void mesh_path_tx_pending(struct mesh_path *mpath) } /** + * mesh_path_send_to_gates - sends pending frames to all known mesh gates + * + * @mpath: mesh path whose queue will be emptied + * + * If there is only one gate, the frames are transferred from the failed mpath + * queue to that gate's queue. If there are more than one gates, the frames + * are copied from each gate to the next. After frames are copied, the + * mpath queues are emptied onto the transmission queue. + */ +int mesh_path_send_to_gates(struct mesh_path *mpath) +{ + struct ieee80211_sub_if_data *sdata = mpath->sdata; + struct hlist_node *n; + struct mesh_table *tbl; + struct mesh_path *from_mpath = mpath; + struct mpath_node *gate = NULL; + bool copy = false; + struct hlist_head *known_gates; + + rcu_read_lock(); + tbl = rcu_dereference(mesh_paths); + known_gates = tbl->known_gates; + rcu_read_unlock(); + + if (!known_gates) + return -EHOSTUNREACH; + + hlist_for_each_entry_rcu(gate, n, known_gates, list) { + if (gate->mpath->sdata != sdata) + continue; + + if (gate->mpath->flags & MESH_PATH_ACTIVE) { + mpath_dbg("Forwarding to %pM\n", gate->mpath->dst); + mesh_path_move_to_queue(gate->mpath, from_mpath, copy); + from_mpath = gate->mpath; + copy = true; + } else { + mpath_dbg("Not forwarding %p\n", gate->mpath); + mpath_dbg("flags %x\n", gate->mpath->flags); + } + } + + hlist_for_each_entry_rcu(gate, n, known_gates, list) + if (gate->mpath->sdata == sdata) { + mpath_dbg("Sending to %pM\n", gate->mpath->dst); + mesh_path_tx_pending(gate->mpath); + } + + return (from_mpath == mpath) ? -EHOSTUNREACH : 0; +} + +/** * mesh_path_discard_frame - discard a frame whose path could not be resolved * * @skb: frame to discard @@ -804,6 +1082,9 @@ int mesh_pathtbl_init(void) tbl_path->free_node = &mesh_path_node_free; tbl_path->copy_node = &mesh_path_node_copy; tbl_path->mean_chain_len = MEAN_CHAIN_LEN; + tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); + INIT_HLIST_HEAD(tbl_path->known_gates); + tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); if (!tbl_mpp) { @@ -813,6 +1094,9 @@ int mesh_pathtbl_init(void) tbl_mpp->free_node = &mesh_path_node_free; tbl_mpp->copy_node = &mesh_path_node_copy; tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; + /* XXX: not needed */ + tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); + INIT_HLIST_HEAD(tbl_mpp->known_gates); /* Need no locking since this is during init */ RCU_INIT_POINTER(mesh_paths, tbl_path); -- cgit v0.10.2 From 699403dbd41998a56d1d92d612ac261e5085a99f Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:09 -0700 Subject: {nl,mac}80211: add missing root mode meshconf entries This fix allows userspace to mark a meshif as a root node. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9ea7c0d..75ece3d 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -485,7 +485,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); MESHPARAMS_ADD(path_refresh_time); MESHPARAMS_ADD(min_discovery_timeout); - + MESHPARAMS_ADD(dot11MeshHWMPRootMode); #undef MESHPARAMS_ADD } #endif diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2aa6a21..93ee888 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3062,6 +3062,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, }; static const struct nla_policy -- cgit v0.10.2 From 0507e159a2b590666982b53ecf6fb2843a5bb423 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:10 -0700 Subject: {nl,cfg,mac}80211: let userspace set RANN interval Allow userspace to set Root Announcement Interval for our mesh interface. Also, RANN interval is now in proper units of TUs. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 89dec16..20353bb 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1861,6 +1861,9 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a * source mesh point for path selection elements. * + * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between + * root announcements are transmitted. + * * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -1882,6 +1885,7 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, NL80211_MESHCONF_HWMP_ROOTMODE, NL80211_MESHCONF_ELEMENT_TTL, + NL80211_MESHCONF_HWMP_RANN_INTERVAL, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d29d11a..4f0d12e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -755,6 +755,7 @@ struct mesh_config { u16 dot11MeshHWMPpreqMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; + u16 dot11MeshHWMPRannInterval; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c1fa577..9995c83 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1137,6 +1137,10 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode; ieee80211_mesh_root_setup(ifmsh); } + if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { + conf->dot11MeshHWMPRannInterval = + nconf->dot11MeshHWMPRannInterval; + } return 0; } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 75ece3d..bac9443 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -372,6 +372,8 @@ IEEE80211_IF_FILE(min_discovery_timeout, u.mesh.mshcfg.min_discovery_timeout, DEC); IEEE80211_IF_FILE(dot11MeshHWMPRootMode, u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); +IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, + u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); #endif @@ -486,6 +488,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(path_refresh_time); MESHPARAMS_ADD(min_discovery_timeout); MESHPARAMS_ADD(dot11MeshHWMPRootMode); + MESHPARAMS_ADD(dot11MeshHWMPRannInterval); #undef MESHPARAMS_ADD } #endif diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e120fef..1c4f53c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -537,7 +537,8 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) mesh_path_tx_root_frame(sdata); mod_timer(&ifmsh->mesh_path_root_timer, - round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); + round_jiffies(jiffies + + usecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPRannInterval * 1024))); } #ifdef CONFIG_PM diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 9d9116e..2027207 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -175,7 +175,6 @@ struct mesh_rmc { #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) -#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 7b517c4..ae3de75 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -695,7 +695,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, u8 ttl, flags, hopcount; u8 *orig_addr; u32 orig_sn, metric; - u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL); + u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; bool root_is_gate; ttl = rann->rann_ttl; @@ -743,7 +743,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, cpu_to_le32(orig_sn), 0, NULL, 0, broadcast_addr, - hopcount, ttl, interval, + hopcount, ttl, cpu_to_le32(interval), cpu_to_le32(metric + mpath->metric), 0, sdata); mpath->sn = orig_sn; @@ -1044,11 +1044,11 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL); + u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, cpu_to_le32(++ifmsh->sn), 0, NULL, 0, broadcast_addr, 0, sdata->u.mesh.mshcfg.element_ttl, - interval, 0, 0, sdata); + cpu_to_le32(interval), 0, 0, sdata); } diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 5c11608..b5a39d4 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -12,6 +12,7 @@ #define MESH_HOLD_T 100 #define MESH_PATH_TIMEOUT 5000 +#define MESH_RANN_INTERVAL 5000 /* * Minimum interval between two consecutive PREQs originated by the same @@ -49,6 +50,7 @@ const struct mesh_config default_mesh_config = { .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES, .path_refresh_time = MESH_PATH_REFRESH_TIME, .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, + .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, }; const struct mesh_setup default_mesh_setup = { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 93ee888..bbf3d73 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3035,6 +3035,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, cur_params.dot11MeshHWMPnetDiameterTraversalTime); NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, cur_params.dot11MeshHWMPRootMode); + NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, + cur_params.dot11MeshHWMPRannInterval); nla_nest_end(msg, pinfoattr); genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); @@ -3063,6 +3065,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, + [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, }; static const struct nla_policy @@ -3141,6 +3144,10 @@ do {\ dot11MeshHWMPRootMode, mask, NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8); + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, + dot11MeshHWMPRannInterval, mask, + NL80211_MESHCONF_HWMP_RANN_INTERVAL, + nla_get_u16); if (mask_out) *mask_out = mask; -- cgit v0.10.2 From 16dd7267f460739b3e29d984e73f05c5ffe2b142 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 9 Aug 2011 16:45:11 -0700 Subject: {nl,cfg,mac}80211: let userspace make meshif mesh gate Allow userspace to set NL80211_MESHCONF_GATE_ANNOUNCEMENTS attribute, which will advertise this mesh node as being a mesh gate. NL80211_HWMP_ROOTMODE must be set or this will do nothing. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 20353bb..3769303 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1864,6 +1864,10 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between * root announcements are transmitted. * + * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has + * access to a broader network beyond the MBSS. This is done via Root + * Announcement frames. + * * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -1886,6 +1890,7 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_HWMP_ROOTMODE, NL80211_MESHCONF_ELEMENT_TTL, NL80211_MESHCONF_HWMP_RANN_INTERVAL, + NL80211_MESHCONF_GATE_ANNOUNCEMENTS, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4f0d12e..77aa777 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -756,6 +756,11 @@ struct mesh_config { u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; u16 dot11MeshHWMPRannInterval; + /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol + * set to true only means that the station will announce others it's a + * mesh gate, but not necessarily using the gate announcement protocol. + * Still keeping the same nomenclature to be in sync with the spec. */ + bool dot11MeshGateAnnouncementProtocol; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9995c83..7d17a91 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1137,6 +1137,10 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode; ieee80211_mesh_root_setup(ifmsh); } + if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) { + conf->dot11MeshGateAnnouncementProtocol = + nconf->dot11MeshGateAnnouncementProtocol; + } if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { conf->dot11MeshHWMPRannInterval = nconf->dot11MeshHWMPRannInterval; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index bac9443..6e8eab7 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -372,6 +372,8 @@ IEEE80211_IF_FILE(min_discovery_timeout, u.mesh.mshcfg.min_discovery_timeout, DEC); IEEE80211_IF_FILE(dot11MeshHWMPRootMode, u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); +IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, + u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); #endif @@ -489,6 +491,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(min_discovery_timeout); MESHPARAMS_ADD(dot11MeshHWMPRootMode); MESHPARAMS_ADD(dot11MeshHWMPRannInterval); + MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); #undef MESHPARAMS_ADD } #endif diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index ae3de75..fd4f76a 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -1045,8 +1045,11 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; + u8 flags; - mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, + flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol) + ? RANN_FLAG_IS_GATE : 0; + mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr, cpu_to_le32(++ifmsh->sn), 0, NULL, 0, broadcast_addr, 0, sdata->u.mesh.mshcfg.element_ttl, diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index b5a39d4..4423e64 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -51,6 +51,7 @@ const struct mesh_config default_mesh_config = { .path_refresh_time = MESH_PATH_REFRESH_TIME, .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, + .dot11MeshGateAnnouncementProtocol = false, }; const struct mesh_setup default_mesh_setup = { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index bbf3d73..57ecfa4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3037,6 +3037,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, cur_params.dot11MeshHWMPRootMode); NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, cur_params.dot11MeshHWMPRannInterval); + NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + cur_params.dot11MeshGateAnnouncementProtocol); nla_nest_end(msg, pinfoattr); genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); @@ -3066,6 +3068,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, + [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, }; static const struct nla_policy @@ -3148,6 +3151,10 @@ do {\ dot11MeshHWMPRannInterval, mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL, nla_get_u16); + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, + dot11MeshGateAnnouncementProtocol, mask, + NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + nla_get_u8); if (mask_out) *mask_out = mask; -- cgit v0.10.2 From 7a12dfdbf508fed2cbd1a9142c6e19341a55527b Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:08 +0530 Subject: ath9k_hw: Fix exceed transmission burst-time of 5GHz The WAR which adds extra delimiters when using RTS/CTS with aggregation and non-enterprise AR9003 chips. This extra padding is done after doing all the 4ms limit checks and hence the total aggregate sizes are exceeding the allowed duration. This patch limits the aggregate sizes appropriately after including these extra delimiters. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 1aadc47..81ccce1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -415,36 +415,12 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, u32 aggrLen) { -#define FIRST_DESC_NDELIMS 60 struct ar9003_txc *ads = (struct ar9003_txc *) ds; ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); - if (ah->ent_mode & AR_ENT_OTP_MPSD) { - u32 ctl17, ndelim; - /* - * Add delimiter when using RTS/CTS with aggregation - * and non enterprise AR9003 card - */ - ctl17 = ads->ctl17; - ndelim = MS(ctl17, AR_PadDelim); - - if (ndelim < FIRST_DESC_NDELIMS) { - aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; - ndelim = FIRST_DESC_NDELIMS; - } - - ctl17 &= ~AR_AggrLen; - ctl17 |= SM(aggrLen, AR_AggrLen); - - ctl17 &= ~AR_PadDelim; - ctl17 |= SM(ndelim, AR_PadDelim); - - ads->ctl17 = ctl17; - } else { - ads->ctl17 &= ~AR_AggrLen; - ads->ctl17 |= SM(aggrLen, AR_AggrLen); - } + ads->ctl17 &= ~AR_AggrLen; + ads->ctl17 |= SM(aggrLen, AR_AggrLen); } static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index e1d1e90..feef013 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -644,8 +644,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, * meet the minimum required mpdudensity. */ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf, u16 frmlen) + struct ath_buf *bf, u16 frmlen, + bool first_subfrm) { +#define FIRST_DESC_NDELIMS 60 struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); u32 nsymbits, nsymbols; @@ -668,6 +670,13 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ndelim += ATH_AGGR_ENCRYPTDELIM; /* + * Add delimiter when using RTS/CTS with aggregation + * and non enterprise AR9003 card + */ + if (first_subfrm) + ndelim = max(ndelim, FIRST_DESC_NDELIMS); + + /* * Convert desired mpdu density from microeconds to bytes based * on highest rate in rate series (i.e. first rate) to determine * required minimum length for subframe. Take into account @@ -756,7 +765,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, status = ATH_AGGR_LIMITED; break; } - nframes++; /* add padding for previous frame to aggregation length */ al += bpad + al_delta; @@ -765,9 +773,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, * Get the delimiters needed to meet the MPDU * density for this node. */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); + ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen, + !nframes); bpad = PADBYTES(al_delta) + (ndelim << 2); + nframes++; bf->bf_next = NULL; ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); -- cgit v0.10.2 From 0682c9b52bf51fbc67c4e79fcbdadcf70bd600f8 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:09 +0530 Subject: ath9k: Fix rx overrun interrupt storm Whenever RXEOL is received, both RXORN and RXEOL got cleared to avoid rx overrun interrupt storm. This was handled only for edma chips. The same scenario was also observered with AR9280, doing frequent channel type switch b/w HT20/40 with bidi traffic that is causing failure to stop rx dma. This patch clears the RXEOL & RXORN interrupts for all chips. ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x42000020 DMADBG_7=0x000062c0 ath: Could not stop RX, we could be confusing the DMA engine when we start RX up ------------[ cut here ]------------ WARNING: at drivers/net/wireless/ath/ath9k/recv.c:532 ath_stoprecv+0x110/0x120 [ath9k]() Call Trace: [] warn_slowpath_common+0x7a/0xb0 [] warn_slowpath_null+0x15/0x20 [] ath_stoprecv+0x110/0x120 [ath9k] [] ath_reset+0x6a/0x200 [ath9k] Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 781af25..3c5db30 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -826,11 +826,9 @@ irqreturn_t ath_isr(int irq, void *dev) if (status & ATH9K_INT_TXURN) ath9k_hw_updatetxtriglevel(ah, true); - if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { - if (status & ATH9K_INT_RXEOL) { - ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); - ath9k_hw_set_interrupts(ah, ah->imask); - } + if (status & ATH9K_INT_RXEOL) { + ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); + ath9k_hw_set_interrupts(ah, ah->imask); } if (status & ATH9K_INT_MIB) { -- cgit v0.10.2 From 29ab0b3632293b506d85adc9dcb323c79f40d428 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:10 +0530 Subject: ath9k: Re-enable RXOEL interrupt after processing rx buffers Once RXEOL was disabled, it never be enabled again. This patch re-enables rxeol at the end of rx tasklet. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 7409402..c0c66e0 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1978,5 +1978,10 @@ requeue: spin_unlock_bh(&sc->rx.rxbuflock); + if (!(ah->imask & ATH9K_INT_RXEOL)) { + ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); + ath9k_hw_set_interrupts(ah, ah->imask); + } + return 0; } -- cgit v0.10.2 From 3de2111697ffca5b9b2fba452bced812725524de Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:11 +0530 Subject: ath9k: Remove unused argument tsf from ath9k_hw_rxprocdesc Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0f90e15..7ddca67 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -564,7 +564,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) EXPORT_SYMBOL(ath9k_hw_resettxqueue); int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - struct ath_rx_status *rs, u64 tsf) + struct ath_rx_status *rs) { struct ar5416_desc ads; struct ar5416_desc *adsp = AR5416DESC(ds); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 8e848c4..153859c 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -687,7 +687,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - struct ath_rx_status *rs, u64 tsf); + struct ath_rx_status *rs); void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags); bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c0c66e0..a9d8f96b 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -761,7 +761,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, * on. All this is necessary because of our use of * a self-linked list to avoid rx overruns. */ - ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0); + ret = ath9k_hw_rxprocdesc(ah, ds, rs); if (ret == -EINPROGRESS) { struct ath_rx_status trs; struct ath_buf *tbf; @@ -787,7 +787,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, */ tds = tbf->bf_desc; - ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); + ret = ath9k_hw_rxprocdesc(ah, tds, &trs); if (ret == -EINPROGRESS) return NULL; } -- cgit v0.10.2 From 479c68927af8735597505320032c249e894f6b6c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:12 +0530 Subject: ath9k: qinfo never be NULL in setuptxqueue Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7ddca67..7ce9b32 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -345,21 +345,8 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, } memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); qi->tqi_type = type; - if (qinfo == NULL) { - qi->tqi_qflags = - TXQ_FLAG_TXOKINT_ENABLE - | TXQ_FLAG_TXERRINT_ENABLE - | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; - qi->tqi_aifs = INIT_AIFS; - qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi->tqi_cwmax = INIT_CWMAX; - qi->tqi_shretry = INIT_SH_RETRY; - qi->tqi_lgretry = INIT_LG_RETRY; - qi->tqi_physCompBuf = 0; - } else { - qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; - (void) ath9k_hw_set_txq_props(ah, q, qinfo); - } + qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; + (void) ath9k_hw_set_txq_props(ah, q, qinfo); return q; } -- cgit v0.10.2 From 56266bff6df685d9c26d08904ae1d43bad162539 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:13 +0530 Subject: ath9k_hw: Remove unnecessary chainmask configuration The chainmasks were already configured at process_ini before doing init calibration. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f48051c..fa35a02 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -839,20 +839,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_capabilities *pCap = &ah->caps; - int val; bool txiqcal_done = false; - val = REG_READ(ah, AR_ENT_OTP); - ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); - - /* Configure rx/tx chains before running AGC/TxiQ cals */ - if (val & AR_ENT_OTP_CHAIN2_DISABLE) - ar9003_hw_set_chain_masks(ah, 0x3, 0x3); - else - ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, - pCap->tx_chainmask); - /* Do Tx IQ Calibration */ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, @@ -887,9 +875,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, if (txiqcal_done) ar9003_hw_tx_iq_cal_post_proc(ah); - /* Revert chainmasks to their original values before NF cal */ - ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); - ath9k_hw_start_nfcal(ah, true); /* Initialize list pointers */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index a0aaa68..88468a0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -540,7 +540,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, udelay(synthDelay + BASE_ACTIVATE_DELAY); } -void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) { switch (rx) { case 0x5: diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 6de3f0b..3aca9fa 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -1124,6 +1124,4 @@ #define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f #define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0 -void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); - #endif /* AR9003_PHY_H */ -- cgit v0.10.2 From d77bf3eb5160c1356d7d7620b7d2fbe28e5e6257 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:14 +0530 Subject: ath9k: Remove SC_OP_ENABLE_APM Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c03949e..4b08a3d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -558,8 +558,7 @@ struct ath_ant_comb { #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) -#define SC_OP_ENABLE_APM BIT(15) -#define SC_OP_PRIM_STA_VIF BIT(16) +#define SC_OP_PRIM_STA_VIF BIT(15) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3c5db30..2af4a1c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -565,7 +565,6 @@ set_timer: static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an; - struct ath_hw *ah = sc->sc_ah; an = (struct ath_node *)sta->drv_priv; #ifdef CONFIG_ATH9K_DEBUGFS @@ -574,9 +573,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) spin_unlock(&sc->nodes_lock); an->sta = sta; #endif - if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) - sc->sc_flags |= SC_OP_ENABLE_APM; - if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index feef013..2062672 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1584,9 +1584,9 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) { struct ath_hw *ah = sc->sc_ah; struct ath9k_channel *curchan = ah->curchan; - if ((sc->sc_flags & SC_OP_ENABLE_APM) && - (curchan->channelFlags & CHANNEL_5GHZ) && - (chainmask == 0x7) && (rate < 0x90)) + if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && + (curchan->channelFlags & CHANNEL_5GHZ) && + (chainmask == 0x7) && (rate < 0x90)) return 0x3; else return chainmask; -- cgit v0.10.2 From f82b4bde17aeb6c2f8bf0540ee44811de4651cf6 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:15 +0530 Subject: ath9k: Move ath9k_init_crypto to common Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 4b08a3d..3a893e1 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -663,7 +663,6 @@ extern int led_blink; extern bool is_ath9k_unloaded; irqreturn_t ath_isr(int irq, void *dev); -void ath9k_init_crypto(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index fa6bd2d..dc705a2 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -169,6 +169,32 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, } EXPORT_SYMBOL(ath9k_cmn_update_txpow); +void ath9k_cmn_init_crypto(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + int i = 0; + + /* Get the hardware key cache size. */ + common->keymax = AR_KEYTABLE_SIZE; + + /* + * Check whether the separate key cache entries + * are required to handle both tx+rx MIC keys. + * With split mic keys the number of stations is limited + * to 27 otherwise 59. + */ + if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) + common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; + + /* + * Reset the key cache since some parts do not + * reset the contents on initial power up. + */ + for (i = 0; i < common->keymax; i++) + ath_hw_keyreset(common, (u16) i); +} +EXPORT_SYMBOL(ath9k_cmn_init_crypto); + static int __init ath9k_cmn_init(void) { return 0; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 77ec288..ad14fec 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -62,3 +62,4 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, enum ath_stomp_type stomp_type); void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, u16 new_txpow, u16 *txpower); +void ath9k_cmn_init_crypto(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 19aa5b7..9cf42f6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -572,25 +572,6 @@ err: return -EINVAL; } -static void ath9k_init_crypto(struct ath9k_htc_priv *priv) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - int i = 0; - - /* Get the hardware key cache size. */ - common->keymax = AR_KEYTABLE_SIZE; - - if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) - common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < common->keymax; i++) - ath_hw_keyreset(common, (u16) i); -} - static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) { if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { @@ -720,7 +701,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) priv->cur_beacon_conf.bslot[i] = NULL; - ath9k_init_crypto(priv); + ath9k_cmn_init_crypto(ah); ath9k_init_channels_rates(priv); ath9k_init_misc(priv); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index db38a58..d7761d1 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -404,31 +404,6 @@ fail: return error; } -void ath9k_init_crypto(struct ath_softc *sc) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - int i = 0; - - /* Get the hardware key cache size. */ - common->keymax = AR_KEYTABLE_SIZE; - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < common->keymax; i++) - ath_hw_keyreset(common, (u16) i); - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) - common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; -} - static int ath9k_init_btcoex(struct ath_softc *sc) { struct ath_txq *txq; @@ -630,7 +605,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, if (ret) goto err_btcoex; - ath9k_init_crypto(sc); + ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); return 0; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index daa26b5..8bd8e85 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -345,7 +345,7 @@ static int ath_pci_resume(struct device *device) * semi-random values after suspend/resume. */ ath9k_ps_wakeup(sc); - ath9k_init_crypto(sc); + ath9k_cmn_init_crypto(sc->sc_ah); ath9k_ps_restore(sc); sc->ps_idle = true; -- cgit v0.10.2 From 6b3d348681a153b8e4a16ba1a6f792711e389a9e Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:16 +0530 Subject: ath9k: Fix noisefloor history update for extn chains Before doing hw reset the current channel's noisefloor readings are updated into history buffer. The extension chain's readings are considered only if the current channel was configured in HT40. While moving from HT40 to HT20, the extn chain's readings are skipped though the current channel is in ht40. This patch updates extn chain reading based on channel flag. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index ac2da3c..ebaf304 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -82,7 +82,6 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, int16_t *nfarray) { struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_conf *conf = &common->hw->conf; struct ath_nf_limits *limit; struct ath9k_nfcal_hist *h; bool high_nf_mid = false; @@ -94,7 +93,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, for (i = 0; i < NUM_NF_READINGS; i++) { if (!(chainmask & (1 << i)) || - ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) + ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan))) continue; h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; -- cgit v0.10.2 From e338a85e21d89574a0160fef7a89f42960cc5d7f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:17 +0530 Subject: ath9k: Fix invalid noisefloor reading due to channel update While switching b/w HT20/40, the current channel's nf values are updated into history buffer. Since the current channel's channel type, channel flag got updated before reading nf value from hw. This channel type mismatch is causing invalid readings when hw is on ht20 but getnf tries to read on extn chains. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2af4a1c..113c1df 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1672,6 +1672,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; + struct ath9k_channel old_chan; int pos = curchan->hw_value; int old_pos = -1; unsigned long flags; @@ -1688,15 +1689,25 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) "Set channel: %d MHz type: %d\n", curchan->center_freq, conf->channel_type); - ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], - curchan, conf->channel_type); - /* update survey stats for the old channel before switching */ spin_lock_irqsave(&common->cc_lock, flags); ath_update_survey_stats(sc); spin_unlock_irqrestore(&common->cc_lock, flags); /* + * Preserve the current channel values, before updating + * the same channel + */ + if (old_pos == pos) { + memcpy(&old_chan, &sc->sc_ah->channels[pos], + sizeof(struct ath9k_channel)); + ah->curchan = &old_chan; + } + + ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], + curchan, conf->channel_type); + + /* * If the operating channel changes, change the survey in-use flags * along with it. * Reset the survey data for the new channel, unless we're switching -- cgit v0.10.2 From d069a46be8ac745c193f2acc6071d9042b347224 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 13 Aug 2011 10:28:18 +0530 Subject: ath9k: Dump modal noisefloor calibration history Debugfs file location: /ieee80211/phy#/ath9k/dump_nfcal Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 9bec3b8..da45f32 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1163,6 +1163,59 @@ static const struct file_operations fops_regdump = { .llseek = default_llseek,/* read accesses f_pos */ }; +static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_hw *ah = sc->sc_ah; + struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; + u32 len = 0, size = 1500; + u32 i, j; + ssize_t retval = 0; + char *buf; + u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; + u8 nread; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += snprintf(buf + len, size - len, + "Channel Noise Floor : %d\n", ah->noise); + len += snprintf(buf + len, size - len, + "Chain | privNF | # Readings | NF Readings\n"); + for (i = 0; i < NUM_NF_READINGS; i++) { + if (!(chainmask & (1 << i)) || + ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) + continue; + + nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount; + len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t", + i, h[i].privNF, nread); + for (j = 0; j < nread; j++) + len += snprintf(buf + len, size - len, + " %d", h[i].nfCalBuffer[j]); + len += snprintf(buf + len, size - len, "\n"); + } + + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + +static const struct file_operations fops_dump_nfcal = { + .read = read_file_dump_nfcal, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1262,6 +1315,8 @@ int ath9k_init_debug(struct ath_hw *ah) &ah->config.cwm_ignore_extcca); debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_regdump); + debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_dump_nfcal); debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_base_eeprom); debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, -- cgit v0.10.2 From 292121dce2af63dab371102097a887de7cf24233 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Aug 2011 10:13:49 -0600 Subject: ath9k: remove a bogus WARN_ON On embedded hardware it's normal to not have a PCI device for the PCI bridge that the wifi card is attached to. pdev->bus->self will be NULL in that case. In that case, simply return without emitting an useless kernel stack trace. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 8bd8e85..d704c8d 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -126,7 +126,7 @@ static void ath_pci_aspm_init(struct ath_common *common) * Both upstream and downstream PCIe components should * have the same ASPM settings. */ - if (WARN_ON(!parent)) + if (!parent) return; pos = pci_pcie_cap(parent); @@ -137,7 +137,7 @@ static void ath_pci_aspm_init(struct ath_common *common) return; } - if (WARN_ON(!parent)) + if (!parent) return; pos = pci_pcie_cap(parent); -- cgit v0.10.2 From 04023afcce2eaff4f66d19ca21b106512fffabe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 14 Aug 2011 19:39:40 +0200 Subject: ssb: fix DMA translation for some specific boards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Buesch Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 29c7d4f..d0cbdb0 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1260,16 +1260,34 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) } EXPORT_SYMBOL(ssb_device_disable); +/* Some chipsets need routing known for PCIe and 64-bit DMA */ +static bool ssb_dma_translation_special_bit(struct ssb_device *dev) +{ + u16 chip_id = dev->bus->chip_id; + + if (dev->id.coreid == SSB_DEV_80211) { + return (chip_id == 0x4322 || chip_id == 43221 || + chip_id == 43231 || chip_id == 43222); + } + + return 0; +} + u32 ssb_dma_translation(struct ssb_device *dev) { switch (dev->bus->bustype) { case SSB_BUSTYPE_SSB: return 0; case SSB_BUSTYPE_PCI: - if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) + if (pci_is_pcie(dev->bus->host_pci) && + ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) { return SSB_PCIE_DMA_H32; - else - return SSB_PCI_DMA; + } else { + if (ssb_dma_translation_special_bit(dev)) + return SSB_PCIE_DMA_H32; + else + return SSB_PCI_DMA; + } default: __ssb_dma_not_implemented(dev); } -- cgit v0.10.2 From 0cc9772a6bd8002aaf7583194098e92481d9c7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 14 Aug 2011 20:16:37 +0200 Subject: b43: fix DMA on some bugged hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some hardware with 64-bit DMA uses lower address word for setting routing (translation) bit. Add workaround for such boards. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f4e9d8b..9e5974b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -594,6 +594,7 @@ struct b43_dma { struct b43_dmaring *rx_ring; u32 translation; /* Routing bits */ + bool translation_in_low; /* Should translation bit go into low addr? */ bool parity; /* Check for parity */ }; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index d0d9aee..e76b40d 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -47,6 +47,38 @@ * into separate slots. */ #define TX_SLOTS_PER_FRAME 2 +static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr, + enum b43_addrtype addrtype) +{ + u32 uninitialized_var(addr); + + switch (addrtype) { + case B43_DMA_ADDR_LOW: + addr = lower_32_bits(dmaaddr); + if (dma->translation_in_low) { + addr &= ~SSB_DMA_TRANSLATION_MASK; + addr |= dma->translation; + } + break; + case B43_DMA_ADDR_HIGH: + addr = upper_32_bits(dmaaddr); + if (!dma->translation_in_low) { + addr &= ~SSB_DMA_TRANSLATION_MASK; + addr |= dma->translation; + } + break; + case B43_DMA_ADDR_EXT: + if (dma->translation_in_low) + addr = lower_32_bits(dmaaddr); + else + addr = upper_32_bits(dmaaddr); + addr &= SSB_DMA_TRANSLATION_MASK; + addr >>= SSB_DMA_TRANSLATION_SHIFT; + break; + } + + return addr; +} /* 32bit DMA ops. */ static @@ -77,10 +109,9 @@ static void op32_fill_descriptor(struct b43_dmaring *ring, slot = (int)(&(desc->dma32) - descbase); B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); - addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ring->dev->dma.translation; + addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW); + addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT); + ctl = bufsize & B43_DMA32_DCTL_BYTECNT; if (slot == ring->nr_slots - 1) ctl |= B43_DMA32_DCTL_DTABLEEND; @@ -170,11 +201,10 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, slot = (int)(&(desc->dma64) - descbase); B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - addrlo = (u32) (dmaaddr & 0xFFFFFFFF); - addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); - addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= ring->dev->dma.translation; + addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW); + addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH); + addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT); + if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -658,41 +688,37 @@ static int dmacontroller_setup(struct b43_dmaring *ring) int err = 0; u32 value; u32 addrext; - u32 trans = ring->dev->dma.translation; bool parity = ring->dev->dma.parity; + u32 addrlo; + u32 addrhi; if (ring->tx) { if (ring->type == B43_DMA_64BIT) { u64 ringbase = (u64) (ring->dmabase); + addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); + addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); + addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH); - addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; value = B43_DMA64_TXENABLE; value |= (addrext << B43_DMA64_TXADDREXT_SHIFT) & B43_DMA64_TXADDREXT_MASK; if (!parity) value |= B43_DMA64_TXPARITYDISABLE; b43_dma_write(ring, B43_DMA64_TXCTL, value); - b43_dma_write(ring, B43_DMA64_TXRINGLO, - (ringbase & 0xFFFFFFFF)); - b43_dma_write(ring, B43_DMA64_TXRINGHI, - ((ringbase >> 32) & - ~SSB_DMA_TRANSLATION_MASK) - | trans); + b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo); + b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi); } else { u32 ringbase = (u32) (ring->dmabase); + addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); + addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); - addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; value = B43_DMA32_TXENABLE; value |= (addrext << B43_DMA32_TXADDREXT_SHIFT) & B43_DMA32_TXADDREXT_MASK; if (!parity) value |= B43_DMA32_TXPARITYDISABLE; b43_dma_write(ring, B43_DMA32_TXCTL, value); - b43_dma_write(ring, B43_DMA32_TXRING, - (ringbase & ~SSB_DMA_TRANSLATION_MASK) - | trans); + b43_dma_write(ring, B43_DMA32_TXRING, addrlo); } } else { err = alloc_initial_descbuffers(ring); @@ -700,9 +726,10 @@ static int dmacontroller_setup(struct b43_dmaring *ring) goto out; if (ring->type == B43_DMA_64BIT) { u64 ringbase = (u64) (ring->dmabase); + addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); + addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); + addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH); - addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT); value |= B43_DMA64_RXENABLE; value |= (addrext << B43_DMA64_RXADDREXT_SHIFT) @@ -710,19 +737,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring) if (!parity) value |= B43_DMA64_RXPARITYDISABLE; b43_dma_write(ring, B43_DMA64_RXCTL, value); - b43_dma_write(ring, B43_DMA64_RXRINGLO, - (ringbase & 0xFFFFFFFF)); - b43_dma_write(ring, B43_DMA64_RXRINGHI, - ((ringbase >> 32) & - ~SSB_DMA_TRANSLATION_MASK) - | trans); + b43_dma_write(ring, B43_DMA64_RXRINGLO, addrlo); + b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi); b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots * sizeof(struct b43_dmadesc64)); } else { u32 ringbase = (u32) (ring->dmabase); + addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); + addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); - addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT); value |= B43_DMA32_RXENABLE; value |= (addrext << B43_DMA32_RXADDREXT_SHIFT) @@ -730,9 +753,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) if (!parity) value |= B43_DMA32_RXPARITYDISABLE; b43_dma_write(ring, B43_DMA32_RXCTL, value); - b43_dma_write(ring, B43_DMA32_RXRING, - (ringbase & ~SSB_DMA_TRANSLATION_MASK) - | trans); + b43_dma_write(ring, B43_DMA32_RXRING, addrlo); b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots * sizeof(struct b43_dmadesc32)); } @@ -1061,6 +1082,25 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) return 0; } +/* Some hardware with 64-bit DMA seems to be bugged and looks for translation + * bit in low address word instead of high one. + */ +static bool b43_dma_translation_in_low_word(struct b43_wldev *dev, + enum b43_dmatype type) +{ + if (type != B43_DMA_64BIT) + return 1; + +#ifdef CONFIG_B43_SSB + if (dev->dev->bus_type == B43_BUS_SSB && + dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && + !(dev->dev->sdev->bus->host_pci->is_pcie && + ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) + return 1; +#endif + return 0; +} + int b43_dma_init(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; @@ -1086,6 +1126,7 @@ int b43_dma_init(struct b43_wldev *dev) break; #endif } + dma->translation_in_low = b43_dma_translation_in_low_word(dev, type); dma->parity = true; #ifdef CONFIG_B43_BCMA diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 546d19c..7e20b04f 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -215,6 +215,12 @@ enum b43_dmatype { B43_DMA_64BIT = 64, }; +enum b43_addrtype { + B43_DMA_ADDR_LOW, + B43_DMA_ADDR_HIGH, + B43_DMA_ADDR_EXT, +}; + struct b43_dmaring { /* Lowlevel DMA ops. */ const struct b43_dma_ops *ops; -- cgit v0.10.2 From f928668f2d822ec51c0853fc92f4da2fef376958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 14 Aug 2011 23:27:28 +0200 Subject: b43: LCN-PHY: add very basic PHY ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 9f7dbbd..03944ad 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -28,14 +28,64 @@ #include "main.h" /************************************************** + * Basic PHY ops. + **************************************************/ + +static int b43_phy_lcn_op_allocate(struct b43_wldev *dev) +{ + struct b43_phy_lcn *phy_lcn; + + phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL); + if (!phy_lcn) + return -ENOMEM; + dev->phy.lcn = phy_lcn; + + return 0; +} + +static void b43_phy_lcn_op_free(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_lcn *phy_lcn = phy->lcn; + + kfree(phy_lcn); + phy->lcn = NULL; +} + +static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_lcn *phy_lcn = phy->lcn; + + memset(phy_lcn, 0, sizeof(*phy_lcn)); +} + +static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) +{ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + return 1; + return 36; +} + +static enum b43_txpwr_result +b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) +{ + return B43_TXPWR_RES_DONE; +} + +static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev) +{ +} + +/************************************************** * PHY ops struct. **************************************************/ const struct b43_phy_operations b43_phyops_lcn = { - /* .allocate = b43_phy_lcn_op_allocate, .free = b43_phy_lcn_op_free, .prepare_structs = b43_phy_lcn_op_prepare_structs, + /* .init = b43_phy_lcn_op_init, .phy_read = b43_phy_lcn_op_read, .phy_write = b43_phy_lcn_op_write, @@ -45,8 +95,8 @@ const struct b43_phy_operations b43_phyops_lcn = { .software_rfkill = b43_phy_lcn_op_software_rfkill, .switch_analog = b43_phy_lcn_op_switch_analog, .switch_channel = b43_phy_lcn_op_switch_channel, + */ .get_default_chan = b43_phy_lcn_op_get_default_chan, .recalc_txpower = b43_phy_lcn_op_recalc_txpower, .adjust_txpower = b43_phy_lcn_op_adjust_txpower, - */ }; diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h index c046c2a..9e1b291 100644 --- a/drivers/net/wireless/b43/phy_lcn.h +++ b/drivers/net/wireless/b43/phy_lcn.h @@ -11,4 +11,4 @@ struct b43_phy_lcn { struct b43_phy_operations; extern const struct b43_phy_operations b43_phyops_lcn; -#endif /* B43_PHY_LCN_H_ */ \ No newline at end of file +#endif /* B43_PHY_LCN_H_ */ -- cgit v0.10.2 From ba356b569f7c0ff5cdf6c1abb8a9b789e5eeed22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 14 Aug 2011 23:27:29 +0200 Subject: b43: LCN-PHY: implement disabling radio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wl reads radio version, then disables it. That's how we found it in MMIO dump: radio_read(0x0000) -> 0x0031 <-- RADIO READ WITHOUT 0x200 SET! radio_read(0x0001) -> 0x0064 <-- RADIO READ WITHOUT 0x200 SET! radio_read(0x0002) -> 0x0020 <-- RADIO READ WITHOUT 0x200 SET! read32 0xfaafc120 -> 0x04000400 phy_read(0x044d) -> 0x0000 phy_write(0x044d) <- 0x0000 phy_read(0x044c) -> 0x1fff phy_write(0x044c) <- 0x1fff phy_read(0x04b7) -> 0x0000 phy_write(0x04b7) <- 0x0000 phy_read(0x04b1) -> 0x0000 phy_write(0x04b1) <- 0x0000 phy_read(0x04b0) -> 0x7dff phy_write(0x04b0) <- 0x7dff phy_read(0x04fa) -> 0x0000 phy_write(0x04fa) <- 0x0000 phy_read(0x04f9) -> 0x007f phy_write(0x04f9) <- 0x007f Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 03944ad..69a93b5 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -60,6 +60,27 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev) memset(phy_lcn, 0, sizeof(*phy_lcn)); } +static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev, + bool blocked) +{ + if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) + b43err(dev->wl, "MAC not suspended\n"); + + if (blocked) { + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00); + b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00); + + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00); + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2); + b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808); + + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8); + b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8); + } else { + /* TODO */ + } +} + static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) @@ -92,7 +113,9 @@ const struct b43_phy_operations b43_phyops_lcn = { .phy_maskset = b43_phy_lcn_op_maskset, .radio_read = b43_phy_lcn_op_radio_read, .radio_write = b43_phy_lcn_op_radio_write, + */ .software_rfkill = b43_phy_lcn_op_software_rfkill, + /* .switch_analog = b43_phy_lcn_op_switch_analog, .switch_channel = b43_phy_lcn_op_switch_channel, */ diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h index 9e1b291..89f13b2 100644 --- a/drivers/net/wireless/b43/phy_lcn.h +++ b/drivers/net/wireless/b43/phy_lcn.h @@ -4,6 +4,15 @@ #include "phy_common.h" +#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C) +#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D) +#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0) +#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1) +#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7) +#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9) +#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA) + + struct b43_phy_lcn { }; -- cgit v0.10.2 From 7ed88528884bd477bddef367e8676b9e5ff99668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 14 Aug 2011 23:27:30 +0200 Subject: b43: LCN-PHY: switch analog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Analog is switched on right after reading PHY version: read16 0xfaafc3e0 -> 0xa801 phy_read(0x043b) -> 0x0000 phy_write(0x043b) <- 0x0000 Switched off after after killing radio: >>> Switch Radio(OFF) end phy_read(0x043c) -> 0x0000 phy_write(0x043c) <- 0x0007 phy_read(0x043b) -> 0x0000 phy_write(0x043b) <- 0x0007 Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 69a93b5..0fd72c1 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -81,6 +81,16 @@ static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev, } } +static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on) +{ + if (on) { + b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7); + } else { + b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7); + b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7); + } +} + static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) @@ -115,8 +125,8 @@ const struct b43_phy_operations b43_phyops_lcn = { .radio_write = b43_phy_lcn_op_radio_write, */ .software_rfkill = b43_phy_lcn_op_software_rfkill, - /* .switch_analog = b43_phy_lcn_op_switch_analog, + /* .switch_channel = b43_phy_lcn_op_switch_channel, */ .get_default_chan = b43_phy_lcn_op_get_default_chan, diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h index 89f13b2..371e07d 100644 --- a/drivers/net/wireless/b43/phy_lcn.h +++ b/drivers/net/wireless/b43/phy_lcn.h @@ -4,6 +4,8 @@ #include "phy_common.h" +#define B43_PHY_LCN_AFE_CTL1 B43_PHY_OFDM(0x03B) +#define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C) #define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C) #define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D) #define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0) -- cgit v0.10.2 From ba2d00e816a11b532e0c035e5cf7b9311e72ac00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 15 Aug 2011 01:23:09 +0200 Subject: b43: LCN-PHY: add init tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They were taken from MMIO dump with few RegExps and vim. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h index 371e07d..25f06e8 100644 --- a/drivers/net/wireless/b43/phy_lcn.h +++ b/drivers/net/wireless/b43/phy_lcn.h @@ -8,6 +8,9 @@ #define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C) #define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C) #define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D) +#define B43_PHY_LCN_TABLE_ADDR B43_PHY_OFDM(0x055) /* Table address */ +#define B43_PHY_LCN_TABLE_DATALO B43_PHY_OFDM(0x056) /* Table data low */ +#define B43_PHY_LCN_TABLE_DATAHI B43_PHY_OFDM(0x057) /* Table data high */ #define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0) #define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1) #define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7) diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c index 40c1d09..0a58428 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/drivers/net/wireless/b43/tables_phy_lcn.c @@ -25,10 +25,442 @@ #include "phy_common.h" #include "phy_lcn.h" +static const u16 b43_lcntab_0x02[] = { + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, + 0x014d, 0x014d, 0x014d, 0x014d, +}; + +static const u16 b43_lcntab_0x01[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, +}; + +static const u32 b43_lcntab_0x0b[] = { + 0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb, + 0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb, + 0x0001fea3, 0x0000024b, +}; + +static const u32 b43_lcntab_0x0c[] = { + 0x00100001, 0x00200010, 0x00300001, 0x00400010, + 0x00500022, 0x00600122, 0x00700222, 0x00800322, + 0x00900422, 0x00a00522, 0x00b00622, 0x00c00722, + 0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22, + 0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22, +}; + +static const u32 b43_lcntab_0x0d[] = { + 0x00000000, 0x00000000, 0x10000000, 0x00000000, + 0x20000000, 0x00000000, 0x30000000, 0x00000000, + 0x40000000, 0x00000000, 0x50000000, 0x00000000, + 0x60000000, 0x00000000, 0x70000000, 0x00000000, + 0x80000000, 0x00000000, 0x90000000, 0x00000008, + 0xa0000000, 0x00000008, 0xb0000000, 0x00000008, + 0xc0000000, 0x00000008, 0xd0000000, 0x00000008, + 0xe0000000, 0x00000008, 0xf0000000, 0x00000008, + 0x00000000, 0x00000009, 0x10000000, 0x00000009, + 0x20000000, 0x00000019, 0x30000000, 0x00000019, + 0x40000000, 0x00000019, 0x50000000, 0x00000019, + 0x60000000, 0x00000019, 0x70000000, 0x00000019, + 0x80000000, 0x00000019, 0x90000000, 0x00000019, + 0xa0000000, 0x00000019, 0xb0000000, 0x00000019, + 0xc0000000, 0x00000019, 0xd0000000, 0x00000019, + 0xe0000000, 0x00000019, 0xf0000000, 0x00000019, + 0x00000000, 0x0000001a, 0x10000000, 0x0000001a, + 0x20000000, 0x0000001a, 0x30000000, 0x0000001a, + 0x40000000, 0x0000001a, 0x50000000, 0x00000002, + 0x60000000, 0x00000002, 0x70000000, 0x00000002, + 0x80000000, 0x00000002, 0x90000000, 0x00000002, + 0xa0000000, 0x00000002, 0xb0000000, 0x00000002, + 0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a, + 0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a, + 0x00000000, 0x0000000b, 0x10000000, 0x0000000b, + 0x20000000, 0x0000000b, 0x30000000, 0x0000000b, + 0x40000000, 0x0000000b, 0x50000000, 0x0000001b, + 0x60000000, 0x0000001b, 0x70000000, 0x0000001b, + 0x80000000, 0x0000001b, 0x90000000, 0x0000001b, + 0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b, + 0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b, + 0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b, + 0x00000000, 0x0000001c, 0x10000000, 0x0000001c, + 0x20000000, 0x0000001c, 0x30000000, 0x0000001c, + 0x40000000, 0x0000001c, 0x50000000, 0x0000001c, + 0x60000000, 0x0000001c, 0x70000000, 0x0000001c, + 0x80000000, 0x0000001c, 0x90000000, 0x0000001c, +}; + +static const u16 b43_lcntab_0x0e[] = { + 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, + 0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c, + 0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092, + 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198, + 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, + 0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4, + 0x01a5, 0x0000, +}; + +static const u16 b43_lcntab_0x0f[] = { + 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, + 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, + 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, + 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, + 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, + 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, + 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, + 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, + 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, + 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, + 0x000a, 0x0009, 0x0006, 0x0005, +}; + +static const u16 b43_lcntab_0x10[] = { + 0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036, + 0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f, + 0x005f, 0x0036, 0x0029, 0x001f, +}; + +static const u16 b43_lcntab_0x11[] = { + 0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007, + 0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005, + 0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, + 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, + 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, + 0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000, +}; + +static const u32 b43_lcntab_0x12[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000000, 0x00000004, 0x00000008, + 0x00000001, 0x00000005, 0x00000009, 0x0000000d, + 0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d, + 0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f, + 0x000000cf, 0x000000d3, 0x00000113, 0x00000513, + 0x00000913, 0x00000953, 0x00000d53, 0x00001153, + 0x00001193, 0x00005193, 0x00009193, 0x0000d193, + 0x00011193, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000000, 0x00000004, 0x00000008, 0x00000001, + 0x00000005, 0x00000009, 0x0000000d, 0x0000004d, + 0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d, + 0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf, + 0x000000d3, 0x00000113, 0x00000513, 0x00000913, + 0x00000953, 0x00000d53, 0x00001153, 0x00005153, + 0x00009153, 0x0000d153, 0x00011153, 0x00015153, + 0x00019153, 0x0001d153, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static const u16 b43_lcntab_0x14[] = { + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003, + 0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, +}; + +static const u16 b43_lcntab_0x17[] = { + 0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0, + 0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0, + 0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c, + 0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c, + 0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340, + 0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104, + 0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104, + 0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186, + 0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104, + 0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4, + 0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186, + 0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be, + 0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036, + 0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6, + 0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288, + 0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6, + 0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8, + 0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798, + 0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6, + 0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288, + 0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a, + 0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288, + 0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360, + 0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc, + 0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510, + 0x05b2, 0x0654, 0x0654, 0x06f6, +}; + +static const u16 b43_lcntab_0x00[] = { + 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, + 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, + 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600, + 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, + 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, + 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +static const u32 b43_lcntab_0x18[] = { + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, + 0x00080000, 0x00080000, 0x00080000, 0x00080000, +}; + +/************************************************** + * R/W ops. + **************************************************/ + +u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset) +{ + u32 type, value; + + type = offset & B43_LCNTAB_TYPEMASK; + offset &= ~B43_LCNTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + switch (type) { + case B43_LCNTAB_8BIT: + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF; + break; + case B43_LCNTAB_16BIT: + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO); + break; + case B43_LCNTAB_32BIT: + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI); + value <<= 16; + value |= b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO); + break; + default: + B43_WARN_ON(1); + value = 0; + } + + return value; +} + +void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, void *_data) +{ + u32 type; + u8 *data = _data; + unsigned int i; + + type = offset & B43_LCNTAB_TYPEMASK; + offset &= ~B43_LCNTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + + for (i = 0; i < nr_elements; i++) { + switch (type) { + case B43_LCNTAB_8BIT: + *data = b43_phy_read(dev, + B43_PHY_LCN_TABLE_DATALO) & 0xFF; + data++; + break; + case B43_LCNTAB_16BIT: + *((u16 *)data) = b43_phy_read(dev, + B43_PHY_LCN_TABLE_DATALO); + data += 2; + break; + case B43_LCNTAB_32BIT: + *((u32 *)data) = b43_phy_read(dev, + B43_PHY_LCN_TABLE_DATAHI); + *((u32 *)data) <<= 16; + *((u32 *)data) |= b43_phy_read(dev, + B43_PHY_LCN_TABLE_DATALO); + data += 4; + break; + default: + B43_WARN_ON(1); + } + } +} + +void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value) +{ + u32 type; + + type = offset & B43_LCNTAB_TYPEMASK; + offset &= 0xFFFF; + + switch (type) { + case B43_LCNTAB_8BIT: + B43_WARN_ON(value & ~0xFF); + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); + break; + case B43_LCNTAB_16BIT: + B43_WARN_ON(value & ~0xFFFF); + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); + break; + case B43_LCNTAB_32BIT: + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF); + break; + default: + B43_WARN_ON(1); + } + + return; +} + +void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, const void *_data) +{ + u32 type, value; + const u8 *data = _data; + unsigned int i; + + type = offset & B43_LCNTAB_TYPEMASK; + offset &= ~B43_LCNTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + + for (i = 0; i < nr_elements; i++) { + switch (type) { + case B43_LCNTAB_8BIT: + value = *data; + data++; + B43_WARN_ON(value & ~0xFF); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); + break; + case B43_LCNTAB_16BIT: + value = *((u16 *)data); + data += 2; + B43_WARN_ON(value & ~0xFFFF); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); + break; + case B43_LCNTAB_32BIT: + value = *((u32 *)data); + data += 4; + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, + value >> 16); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, + value & 0xFFFF); + break; + default: + B43_WARN_ON(1); + } + } +} + /************************************************** * Tables ops. **************************************************/ +#define lcntab_upload(dev, offset, data) do { \ + b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \ + } while (0) void b43_phy_lcn_tables_init(struct b43_wldev *dev) { + lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02); + lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01); + lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b); + lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c); + lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d); + lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e); + lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f); + lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10); + lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11); + lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12); + lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14); + lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17); + lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00); + lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); } diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h index 5e31b15..b6471e8 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.h +++ b/drivers/net/wireless/b43/tables_phy_lcn.h @@ -1,6 +1,22 @@ #ifndef B43_TABLES_PHY_LCN_H_ #define B43_TABLES_PHY_LCN_H_ +/* The LCN-PHY tables. */ +#define B43_LCNTAB_TYPEMASK 0xF0000000 +#define B43_LCNTAB_8BIT 0x10000000 +#define B43_LCNTAB_16BIT 0x20000000 +#define B43_LCNTAB_32BIT 0x30000000 +#define B43_LCNTAB8(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_8BIT) +#define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT) +#define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT) + +u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset); +void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, void *_data); +void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, const void *_data); + void b43_phy_lcn_tables_init(struct b43_wldev *dev); #endif /* B43_TABLES_PHY_LCN_H_ */ -- cgit v0.10.2 From bfe2ed8f4df2e7b6991c4039bb624dee5f8b6583 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 15 Aug 2011 14:25:35 +0300 Subject: libertas: handle mesh networks in lbs_iface_active() There was an extra semicolon so the if condition wasn't used. We checked "priv->dev" twice instead of "priv->mesh_dev". Signed-off-by: Dan Carpenter Acked-by: Dan Williams Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 8148389..b9ff0dc 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -190,8 +190,8 @@ static inline int lbs_iface_active(struct lbs_private *priv) int r; r = netif_running(priv->dev); - if (priv->mesh_dev); - r |= netif_running(priv->dev); + if (priv->mesh_dev) + r |= netif_running(priv->mesh_dev); return r; } -- cgit v0.10.2 From 7ccc83b0fc69d5b18602aa250c10be0d3ae920c6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 15 Aug 2011 18:45:54 +0200 Subject: carl9170: fix timekeeping for HW_COUNTER firmwares AR9170_PWR_REG_PLL_ADDAC is used to set the main clock divisor which affects the AHB/CPU speed. Because this would interfere with the firmware internal timekeeping, the function has to be moved into the firmware. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index c5427a7..f7dbdaa 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -282,6 +282,7 @@ struct ar9170 { bool rx_stream; bool tx_stream; bool rx_filter; + bool hw_counters; unsigned int mem_blocks; unsigned int mem_block_size; unsigned int rx_size; diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 39ddea5..f4cae1c 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -266,6 +266,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) FIF_PROMISC_IN_BSS; } + if (SUPP(CARL9170FW_HW_COUNTERS)) + ar->fw.hw_counters = true; + if (SUPP(CARL9170FW_WOL)) device_set_wakeup_enable(&ar->udev->dev, true); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index aa147a9..8635c5c 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -578,11 +578,10 @@ static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) if (err) return err; - /* XXX: remove magic! */ - if (is_2ghz) - err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163); - else - err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143); + if (!ar->fw.hw_counters) { + err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, + is_2ghz ? 0x5163 : 0x5143); + } return err; } -- cgit v0.10.2 From f5e2289a142c714732aef67cadbb0a8843565507 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 15 Aug 2011 19:39:51 +0200 Subject: carl9170: import updated firmware headers Import new headers from our firmware branch: git://git.kernel.org/pub/scm/linux/kernel/git/chr/carl9170fw.git Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 0a6dec5..9443c80 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -55,6 +55,7 @@ enum carl9170_cmd_oids { CARL9170_CMD_READ_TSF = 0x06, CARL9170_CMD_RX_FILTER = 0x07, CARL9170_CMD_WOL = 0x08, + CARL9170_CMD_TALLY = 0x09, /* CAM */ CARL9170_CMD_EKEY = 0x10, @@ -286,6 +287,15 @@ struct carl9170_tsf_rsp { } __packed; #define CARL9170_TSF_RSP_SIZE 8 +struct carl9170_tally_rsp { + __le32 active; + __le32 cca; + __le32 tx_time; + __le32 rx_total; + __le32 rx_overrun; + __le32 tick; +} __packed; + struct carl9170_rsp { struct carl9170_cmd_head hdr; @@ -300,6 +310,7 @@ struct carl9170_rsp { struct carl9170_gpio gpio; struct carl9170_tsf_rsp tsf; struct carl9170_psm psm; + struct carl9170_tally_rsp tally; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; } __packed; } __packed __aligned(4); diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index 6470377..e651db8 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H #define CARL9170FW_VERSION_YEAR 11 -#define CARL9170FW_VERSION_MONTH 6 -#define CARL9170FW_VERSION_DAY 30 +#define CARL9170FW_VERSION_MONTH 8 +#define CARL9170FW_VERSION_DAY 15 #define CARL9170FW_VERSION_GIT "1.9.4" #endif /* __CARL9170_SHARED_VERSION_H */ -- cgit v0.10.2 From acf1771221f2877ab5d36487930cd6a2ecaa73e6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 15 Aug 2011 19:50:48 +0200 Subject: carl9170: improve site survey The firmware keeps track of channel usage. This data can be used by the automatic channel selection to find the *best* channel. Survey data from wlan22 frequency: 2412 MHz [in use] noise: -86 dBm channel active time: 3339608 ms channel busy time: 270982 ms channel transmit time: 121515 ms Survey data from wlan22 frequency: 2417 MHz noise: -86 dBm channel active time: 70 ms channel busy time: 2 ms channel transmit time: 1 ms Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index f7dbdaa..74350d6 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -151,6 +151,7 @@ struct carl9170_sta_tid { #define CARL9170_TX_TIMEOUT 2500 #define CARL9170_JANITOR_DELAY 128 #define CARL9170_QUEUE_STUCK_TIMEOUT 5500 +#define CARL9170_STAT_WORK 30000 #define CARL9170_NUM_TX_AGG_MAX 30 @@ -332,11 +333,21 @@ struct ar9170 { /* PHY */ struct ieee80211_channel *channel; + unsigned int num_channels; int noise[4]; unsigned int chan_fail; unsigned int total_chan_fail; u8 heavy_clip; u8 ht_settings; + struct { + u64 active; /* usec */ + u64 cca; /* usec */ + u64 tx_time; /* usec */ + u64 rx_total; + u64 rx_overrun; + } tally; + struct delayed_work stat_work; + struct survey_info *survey; /* power calibration data */ u8 power_5G_leg[4]; diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index cdfc94c..9970bf8 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -165,6 +165,37 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, return __carl9170_exec_cmd(ar, cmd, true); } +int carl9170_collect_tally(struct ar9170 *ar) +{ + struct carl9170_tally_rsp tally; + struct survey_info *info; + unsigned int tick; + int err; + + err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL, + sizeof(tally), (u8 *)&tally); + if (err) + return err; + + tick = le32_to_cpu(tally.tick); + if (tick) { + ar->tally.active += le32_to_cpu(tally.active) / tick; + ar->tally.cca += le32_to_cpu(tally.cca) / tick; + ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick; + ar->tally.rx_total += le32_to_cpu(tally.rx_total); + ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun); + + if (ar->channel) { + info = &ar->survey[ar->channel->hw_value]; + + info->channel_time = ar->tally.active / 1000; + info->channel_time_busy = ar->tally.cca / 1000; + info->channel_time_tx = ar->tally.tx_time / 1000; + } + } + return 0; +} + int carl9170_powersave(struct ar9170 *ar, const bool ps) { struct carl9170_cmd *cmd; diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h index d5f95bd..885c427 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.h +++ b/drivers/net/wireless/ath/carl9170/cmd.h @@ -50,6 +50,7 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v); int carl9170_reboot(struct ar9170 *ar); int carl9170_mac_reset(struct ar9170 *ar); int carl9170_powersave(struct ar9170 *ar, const bool power_on); +int carl9170_collect_tally(struct ar9170 *ar); int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, const u32 mode, const u32 addr, const u32 len); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 0122930..85cb1bd 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -413,6 +413,9 @@ static int carl9170_op_start(struct ieee80211_hw *hw) carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED); + ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, + round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK))); + ieee80211_wake_queues(ar->hw); err = 0; @@ -423,6 +426,7 @@ out: static void carl9170_cancel_worker(struct ar9170 *ar) { + cancel_delayed_work_sync(&ar->stat_work); cancel_delayed_work_sync(&ar->tx_janitor); #ifdef CONFIG_CARL9170_LEDS cancel_delayed_work_sync(&ar->led_work); @@ -794,6 +798,43 @@ static void carl9170_ps_work(struct work_struct *work) mutex_unlock(&ar->mutex); } +static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise) +{ + int err; + + if (noise) { + err = carl9170_get_noisefloor(ar); + if (err) + return err; + } + + if (ar->fw.hw_counters) { + err = carl9170_collect_tally(ar); + if (err) + return err; + } + + if (flush) + memset(&ar->tally, 0, sizeof(ar->tally)); + + return 0; +} + +static void carl9170_stat_work(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work); + int err; + + mutex_lock(&ar->mutex); + err = carl9170_update_survey(ar, false, true); + mutex_unlock(&ar->mutex); + + if (err) + return; + + ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, + round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK))); +} static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) { @@ -828,11 +869,19 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) if (err) goto out; + err = carl9170_update_survey(ar, true, false); + if (err) + goto out; + err = carl9170_set_channel(ar, hw->conf.channel, hw->conf.channel_type, CARL9170_RFI_NONE); if (err) goto out; + err = carl9170_update_survey(ar, false, true); + if (err) + goto out; + err = carl9170_set_dyn_sifs_ack(ar); if (err) goto out; @@ -1423,20 +1472,52 @@ static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { struct ar9170 *ar = hw->priv; - int err; + struct ieee80211_channel *chan; + struct ieee80211_supported_band *band; + int err, b, i; - if (idx != 0) - return -ENOENT; + chan = ar->channel; + if (!chan) + return -ENODEV; - mutex_lock(&ar->mutex); - err = carl9170_get_noisefloor(ar); - mutex_unlock(&ar->mutex); - if (err) - return err; + if (idx == chan->hw_value) { + mutex_lock(&ar->mutex); + err = carl9170_update_survey(ar, false, true); + mutex_unlock(&ar->mutex); + if (err) + return err; + } - survey->channel = ar->channel; + for (b = 0; b < IEEE80211_NUM_BANDS; b++) { + band = ar->hw->wiphy->bands[b]; + + if (!band) + continue; + + for (i = 0; i < band->n_channels; i++) { + if (band->channels[i].hw_value == idx) { + chan = &band->channels[i]; + goto found; + } + } + } + return -ENOENT; + +found: + memcpy(survey, &ar->survey[idx], sizeof(*survey)); + + survey->channel = chan; survey->filled = SURVEY_INFO_NOISE_DBM; - survey->noise = ar->noise[0]; + + if (ar->channel == chan) + survey->filled |= SURVEY_INFO_IN_USE; + + if (ar->fw.hw_counters) { + survey->filled |= SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_TX; + } + return 0; } @@ -1569,6 +1650,7 @@ void *carl9170_alloc(size_t priv_size) INIT_WORK(&ar->ping_work, carl9170_ping_work); INIT_WORK(&ar->restart_work, carl9170_restart_work); INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); + INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work); INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); INIT_LIST_HEAD(&ar->tx_ampdu_list); rcu_assign_pointer(ar->tx_ampdu_iter, @@ -1652,6 +1734,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) struct ath_regulatory *regulatory = &ar->common.regulatory; unsigned int rx_streams, tx_streams, tx_params = 0; int bands = 0; + int chans = 0; if (ar->eeprom.length == cpu_to_le16(0xffff)) return -ENODATA; @@ -1675,14 +1758,24 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &carl9170_band_2GHz; + chans += carl9170_band_2GHz.n_channels; bands++; } if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &carl9170_band_5GHz; + chans += carl9170_band_5GHz.n_channels; bands++; } + if (!bands) + return -EINVAL; + + ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL); + if (!ar->survey) + return -ENOMEM; + ar->num_channels = chans; + /* * I measured this, a bandswitch takes roughly * 135 ms and a frequency switch about 80. @@ -1701,7 +1794,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) /* second part of wiphy init */ SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address); - return bands ? 0 : -EINVAL; + return 0; } static int carl9170_reg_notifier(struct wiphy *wiphy, @@ -1834,6 +1927,9 @@ void carl9170_free(struct ar9170 *ar) kfree(ar->mem_bitmap); ar->mem_bitmap = NULL; + kfree(ar->survey); + ar->survey = NULL; + mutex_destroy(&ar->mutex); ieee80211_free_hw(ar->hw); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index 8635c5c..472efc7 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -1573,6 +1573,9 @@ int carl9170_get_noisefloor(struct ar9170 *ar) AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8); } + if (ar->channel) + ar->survey[ar->channel->hw_value].noise = ar->noise[0]; + return 0; } @@ -1765,10 +1768,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, ar->chan_fail = 0; } - err = carl9170_get_noisefloor(ar); - if (err) - return err; - if (ar->heavy_clip) { err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, 0x200 | ar->heavy_clip); -- cgit v0.10.2 From 00044f17afd36bf6397b9a2a12f242a057449e9a Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 15 Aug 2011 20:09:54 +0200 Subject: carl9170: export HW random number generator All AR9170 hardware have a 16-Bit random number generator. The documentation claims the values are suitable for "security keys". The "throughput" is around 320Kibit/s. It's slow, but it does work without introducing any special offload firmware commands. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig index 2d1b821..267d5dc 100644 --- a/drivers/net/wireless/ath/carl9170/Kconfig +++ b/drivers/net/wireless/ath/carl9170/Kconfig @@ -39,3 +39,17 @@ config CARL9170_WPC bool depends on CARL9170 && (INPUT = y || INPUT = CARL9170) default y + +config CARL9170_HWRNG + bool "Random number generator" + depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170) + default n + help + Provides a hardware random number generator to the kernel. + + SECURITY WARNING: It's relatively easy to eavesdrop all + generated random numbers from the transport stream with + usbmon [software] or special usb sniffer hardware. + + Say N, unless your setup[i.e.: embedded system] has no + other rng source and you can afford to take the risk. diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 74350d6..6cfbb41 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -449,6 +450,17 @@ struct ar9170 { unsigned int off_override; bool state; } ps; + +#ifdef CONFIG_CARL9170_HWRNG +# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN + struct { + struct hwrng rng; + bool initialized; + char name[30 + 1]; + u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)]; + unsigned int cache_idx; + } rng; +#endif /* CONFIG_CARL9170_HWRNG */ }; enum carl9170_ps_off_override_reasons { diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 85cb1bd..782b8f3 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1468,6 +1468,109 @@ static int carl9170_register_wps_button(struct ar9170 *ar) } #endif /* CONFIG_CARL9170_WPC */ +#ifdef CONFIG_CARL9170_HWRNG +static int carl9170_rng_get(struct ar9170 *ar) +{ + +#define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32)) +#define RB (CARL9170_MAX_CMD_PAYLOAD_LEN) + + static const __le32 rng_load[RW] = { + [0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)}; + + u32 buf[RW]; + + unsigned int i, off = 0, transfer, count; + int err; + + BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN); + + if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized) + return -EAGAIN; + + count = ARRAY_SIZE(ar->rng.cache); + while (count) { + err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, + RB, (u8 *) rng_load, + RB, (u8 *) buf); + if (err) + return err; + + transfer = min_t(unsigned int, count, RW); + for (i = 0; i < transfer; i++) + ar->rng.cache[off + i] = buf[i]; + + off += transfer; + count -= transfer; + } + + ar->rng.cache_idx = 0; + +#undef RW +#undef RB + return 0; +} + +static int carl9170_rng_read(struct hwrng *rng, u32 *data) +{ + struct ar9170 *ar = (struct ar9170 *)rng->priv; + int ret = -EIO; + + mutex_lock(&ar->mutex); + if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) { + ret = carl9170_rng_get(ar); + if (ret) { + mutex_unlock(&ar->mutex); + return ret; + } + } + + *data = ar->rng.cache[ar->rng.cache_idx++]; + mutex_unlock(&ar->mutex); + + return sizeof(u16); +} + +static void carl9170_unregister_hwrng(struct ar9170 *ar) +{ + if (ar->rng.initialized) { + hwrng_unregister(&ar->rng.rng); + ar->rng.initialized = false; + } +} + +static int carl9170_register_hwrng(struct ar9170 *ar) +{ + int err; + + snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name), + "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy)); + ar->rng.rng.name = ar->rng.name; + ar->rng.rng.data_read = carl9170_rng_read; + ar->rng.rng.priv = (unsigned long)ar; + + if (WARN_ON(ar->rng.initialized)) + return -EALREADY; + + err = hwrng_register(&ar->rng.rng); + if (err) { + dev_err(&ar->udev->dev, "Failed to register the random " + "number generator (%d)\n", err); + return err; + } + + ar->rng.initialized = true; + + err = carl9170_rng_get(ar); + if (err) { + carl9170_unregister_hwrng(ar); + return err; + } + + return 0; +} +#endif /* CONFIG_CARL9170_HWRNG */ + static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { @@ -1878,6 +1981,12 @@ int carl9170_register(struct ar9170 *ar) goto err_unreg; #endif /* CONFIG_CARL9170_WPC */ +#ifdef CONFIG_CARL9170_HWRNG + err = carl9170_register_hwrng(ar); + if (err) + goto err_unreg; +#endif /* CONFIG_CARL9170_HWRNG */ + dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n", wiphy_name(ar->hw->wiphy)); @@ -1910,6 +2019,10 @@ void carl9170_unregister(struct ar9170 *ar) } #endif /* CONFIG_CARL9170_WPC */ +#ifdef CONFIG_CARL9170_HWRNG + carl9170_unregister_hwrng(ar); +#endif /* CONFIG_CARL9170_HWRNG */ + carl9170_cancel_worker(ar); cancel_work_sync(&ar->restart_work); -- cgit v0.10.2 From 78bc2463af4c311a188a9db4d833acf724bbc304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 15 Aug 2011 18:50:55 +0200 Subject: b43: LCN-PHY: basic PHY init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 0fd72c1..604a3a6 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -28,6 +28,50 @@ #include "main.h" /************************************************** + * Various PHY ops + **************************************************/ + +static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev) +{ + u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2); + u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1); + + b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1); + b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1); + + b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1); + b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1); + + b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2); + b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1); +} + +static void b43_phy_lcn_clean_0x18_table(struct b43_wldev *dev) +{ + u8 i; + + for (i = 0; i < 0x80; i++) + b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000); +} + +static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev) +{ + u8 i; + + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340); + for (i = 0; i < 30; i++) { + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0); + } + + b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80); + for (i = 0; i < 64; i++) { + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0); + b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0); + } +} + +/************************************************** * Basic PHY ops. **************************************************/ @@ -60,6 +104,30 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev) memset(phy_lcn, 0, sizeof(*phy_lcn)); } +static int b43_phy_lcn_op_init(struct b43_wldev *dev) +{ + b43_phy_set(dev, 0x44a, 0x80); + b43_phy_mask(dev, 0x44a, 0x7f); + b43_phy_set(dev, 0x6d1, 0x80); + b43_phy_write(dev, 0x6d0, 0x7); + + b43_phy_lcn_afe_set_unset(dev); + + b43_phy_write(dev, 0x60a, 0xa0); + b43_phy_write(dev, 0x46a, 0x19); + b43_phy_maskset(dev, 0x663, 0xFF00, 0x64); + + b43_phy_lcn_tables_init(dev); + /* TODO: various tables ops here */ + b43_phy_lcn_clean_0x18_table(dev); + + /* TODO: some ops here */ + + b43_phy_lcn_clear_0x07_table(dev); + + return 0; +} + static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev, bool blocked) { @@ -77,7 +145,9 @@ static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev, b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8); b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8); } else { - /* TODO */ + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00); + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808); + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8); } } @@ -116,8 +186,8 @@ const struct b43_phy_operations b43_phyops_lcn = { .allocate = b43_phy_lcn_op_allocate, .free = b43_phy_lcn_op_free, .prepare_structs = b43_phy_lcn_op_prepare_structs, - /* .init = b43_phy_lcn_op_init, + /* .phy_read = b43_phy_lcn_op_read, .phy_write = b43_phy_lcn_op_write, .phy_maskset = b43_phy_lcn_op_maskset, -- cgit v0.10.2 From dc713fb2afa1be7a29f5c1d0b087c35bfbbe2815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 15 Aug 2011 18:50:56 +0200 Subject: b43: LCN-PHY: init 0x2064 radio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 604a3a6..4b2cd6d 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -28,6 +28,55 @@ #include "main.h" /************************************************** + * Radio 2064. + **************************************************/ + +static void b43_radio_2064_init(struct b43_wldev *dev) +{ + b43_radio_write(dev, 0x09c, 0x0020); + b43_radio_write(dev, 0x105, 0x0008); + b43_radio_write(dev, 0x032, 0x0062); + b43_radio_write(dev, 0x033, 0x0019); + b43_radio_write(dev, 0x090, 0x0010); + b43_radio_write(dev, 0x010, 0x0000); + b43_radio_write(dev, 0x060, 0x007f); + b43_radio_write(dev, 0x061, 0x0072); + b43_radio_write(dev, 0x062, 0x007f); + b43_radio_write(dev, 0x01d, 0x0002); + b43_radio_write(dev, 0x01e, 0x0006); + + b43_phy_write(dev, 0x4ea, 0x4688); + b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2); + b43_phy_mask(dev, 0x4eb, ~0x01c0); + b43_phy_maskset(dev, 0x4eb, 0xff00, 0x19); + + b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0); + + b43_radio_mask(dev, 0x05b, (u16) ~0xff02); + b43_radio_set(dev, 0x004, 0x40); + b43_radio_set(dev, 0x120, 0x10); + b43_radio_set(dev, 0x078, 0x80); + b43_radio_set(dev, 0x129, 0x2); + b43_radio_set(dev, 0x057, 0x1); + b43_radio_set(dev, 0x05b, 0x2); + + /* TODO: wait for some bit to be set */ + b43_radio_read(dev, 0x05c); + + b43_radio_mask(dev, 0x05b, (u16) ~0xff02); + b43_radio_mask(dev, 0x057, (u16) ~0xff01); + + b43_phy_write(dev, 0x933, 0x2d6b); + b43_phy_write(dev, 0x934, 0x2d6b); + b43_phy_write(dev, 0x935, 0x2d6b); + b43_phy_write(dev, 0x936, 0x2d6b); + b43_phy_write(dev, 0x937, 0x016b); + + b43_radio_mask(dev, 0x057, (u16) ~0xff02); + b43_radio_write(dev, 0x0c2, 0x006f); +} + +/************************************************** * Various PHY ops **************************************************/ @@ -125,6 +174,11 @@ static int b43_phy_lcn_op_init(struct b43_wldev *dev) b43_phy_lcn_clear_0x07_table(dev); + if (dev->phy.radio_ver == 0x2064) + b43_radio_2064_init(dev); + else + B43_WARN_ON(1); + return 0; } -- cgit v0.10.2 From 948990251508d8d41f5dd2c9988d415fb8fb49c7 Mon Sep 17 00:00:00 2001 From: Alex Hacker Date: Tue, 16 Aug 2011 16:41:40 +0600 Subject: ath9k_hw: fix EIFS value to microseconds The EIFS value read from AR_D_GBL_IFS_EIFS register in core clocks and then written back as microsecond value. Signed-off-by: Alex Hacker Acked-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 875faf6..88100cc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -996,7 +996,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) slottime = 21; sifstime = 64; } else { - eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS); + eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate; reg = REG_READ(ah, AR_USEC); rx_lat = MS(reg, AR_USEC_RX_LAT); tx_lat = MS(reg, AR_USEC_TX_LAT); -- cgit v0.10.2 From cbe1e82a543dae06ffdba9bc108a1a22dc55cde3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 16 Aug 2011 21:44:21 +0200 Subject: b43: warn when forcing PIO mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have resolved all the known issues with DMA mode, however some users (or distros) are still forcing PIO mode by config files. Without debugging enabled it's not noticable at all. Add the warning for them. Cc: Gregory Bellier Signed-off-by: Rafał Miłecki Acked-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b5e8305..bf17516 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4654,8 +4654,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); if (b43_bus_host_is_pcmcia(dev->dev) || - b43_bus_host_is_sdio(dev->dev) || - dev->use_pio) { + b43_bus_host_is_sdio(dev->dev)) { + dev->__using_pio_transfers = 1; + err = b43_pio_init(dev); + } else if (dev->use_pio) { + b43warn(dev->wl, "Forced PIO by use_pio module parameter. " + "This should not be needed and will result in lower " + "performance.\n"); dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { -- cgit v0.10.2 From 152e585dc9fe2c3436e87cc982f2446697778228 Mon Sep 17 00:00:00 2001 From: Bill Jordan Date: Fri, 19 Aug 2011 11:10:22 -0400 Subject: ath9k: fix MGMT packets when using TKIP Prevent 8 bytes from being truncated from MGMT packets when using TKIP. Signed-off-by: Bill Jordan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a9d8f96b..ad5f9bd 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -824,7 +824,8 @@ static bool ath9k_rx_accept(struct ath_common *common, is_mc = !!is_multicast_ether_addr(hdr->addr1); is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && test_bit(rx_stats->rs_keyix, common->tkip_keymap); - strip_mic = is_valid_tkip && !(rx_stats->rs_status & + strip_mic = is_valid_tkip && ieee80211_is_data(fc) && + !(rx_stats->rs_status & (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC)); if (!rx_stats->rs_datalen) -- cgit v0.10.2 From 4e0d8cc1006b889909a87f824943bad9a56358e8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 23 Aug 2011 22:15:35 +0300 Subject: bcma: signedness bug in bcma_get_next_core() The u32 would never be less than zero so the error handling would break. I changed it to s32 to match how bcma_erom_get_mst_port() is declared. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 0ea390f..cad9948 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -281,7 +281,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, /* get & parse master ports */ for (i = 0; i < ports[0]; i++) { - u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); + s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); if (mst_port_d < 0) return -EILSEQ; } -- cgit v0.10.2 From e8753043f9fbabffbf087c7f4b514c50ef89541e Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Aug 2011 15:47:11 +0200 Subject: NFC: Reserve tx head and tail room We can have the NFC core layer allocating the tx head and tail room for the drivers and avoid 1 or more SKBs copy on write on the Tx path. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index c77e054..f81a93e 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1246,7 +1246,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) { int payload_len = skb->len; struct pn533_frame *out_frame; - struct sk_buff *discarded; u8 tg; nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__, @@ -1260,18 +1259,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) return -ENOSYS; } - /* Reserving header space */ - if (skb_cow_head(skb, PN533_CMD_DATAEXCH_HEAD_LEN)) { - nfc_dev_err(&dev->interface->dev, "Error to add header data"); - return -ENOMEM; - } - - /* Reserving tail space, see pn533_tx_frame_finish */ - if (skb_cow_data(skb, PN533_FRAME_TAIL_SIZE, &discarded) < 0) { - nfc_dev_err(&dev->interface->dev, "Error to add tail data"); - return -ENOMEM; - } - skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); out_frame = (struct pn533_frame *) skb->data; @@ -1536,7 +1523,9 @@ static int pn533_probe(struct usb_interface *interface, | NFC_PROTO_ISO14443_MASK | NFC_PROTO_NFC_DEP_MASK; - dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols); + dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, + PN533_CMD_DATAEXCH_HEAD_LEN, + PN533_FRAME_TAIL_SIZE); if (!dev->nfc_dev) goto kill_tasklet; diff --git a/include/linux/nfc.h b/include/linux/nfc.h index 330a4c5..c525e0b 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h @@ -123,4 +123,6 @@ struct sockaddr_nfc { #define NFC_SOCKPROTO_RAW 0 #define NFC_SOCKPROTO_MAX 1 +#define NFC_HEADER_SIZE 1 + #endif /*__LINUX_NFC_H */ diff --git a/include/net/nfc.h b/include/net/nfc.h index cc01303..87b51fe 100644 --- a/include/net/nfc.h +++ b/include/net/nfc.h @@ -82,6 +82,9 @@ struct nfc_dev { struct nfc_genl_data genl_data; u32 supported_protocols; + int tx_headroom; + int tx_tailroom; + struct nfc_ops *ops; }; #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) @@ -89,7 +92,9 @@ struct nfc_dev { extern struct class nfc_class; struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - u32 supported_protocols); + u32 supported_protocols, + int tx_headroom, + int tx_tailroom); /** * nfc_free_device - free nfc device diff --git a/net/nfc/core.c b/net/nfc/core.c index b6fd4e1..284e2f6 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -322,7 +322,9 @@ struct nfc_dev *nfc_get_device(unsigned idx) * @supported_protocols: NFC protocols supported by the device */ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - u32 supported_protocols) + u32 supported_protocols, + int tx_headroom, + int tx_tailroom) { static atomic_t dev_no = ATOMIC_INIT(0); struct nfc_dev *dev; @@ -345,6 +347,8 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, dev->ops = ops; dev->supported_protocols = supported_protocols; + dev->tx_headroom = tx_headroom; + dev->tx_tailroom = tx_tailroom; spin_lock_init(&dev->targets_lock); nfc_genl_data_init(&dev->genl_data); diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 52de84a..9fd652a 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -123,11 +123,7 @@ error: static int rawsock_add_header(struct sk_buff *skb) { - - if (skb_cow_head(skb, 1)) - return -ENOMEM; - - *skb_push(skb, 1) = 0; + *skb_push(skb, NFC_HEADER_SIZE) = 0; return 0; } @@ -197,6 +193,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; + struct nfc_dev *dev = nfc_rawsock(sk)->dev; struct sk_buff *skb; int rc; @@ -208,11 +205,13 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, if (sock->state != SS_CONNECTED) return -ENOTCONN; - skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, - &rc); + skb = sock_alloc_send_skb(sk, len + dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE, + msg->msg_flags & MSG_DONTWAIT, &rc); if (!skb) return rc; + skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); + rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); if (rc < 0) { kfree_skb(skb); -- cgit v0.10.2 From 6423d30f030b560ef1b701bb1f205c3817efe380 Mon Sep 17 00:00:00 2001 From: Aloisio Almeida Jr Date: Fri, 19 Aug 2011 16:09:49 -0300 Subject: MAINTAINERS: Add NFC subsystem entry Update MAINTAINERS with NFC subsystem and drivers entry. Signed-off-by: Aloisio Almeida Jr Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 1d2e79d..4771368 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4492,6 +4492,17 @@ W: http://www.qlogic.com S: Supported F: drivers/net/netxen/ +NFC SUBSYSTEM +M: Lauro Ramos Venancio +M: Aloisio Almeida Jr +M: Samuel Ortiz +L: linux-wireless@vger.kernel.org +S: Maintained +F: net/nfc/ +F: include/linux/nfc.h +F: include/net/nfc.h +F: drivers/nfc/ + NFS, SUNRPC, AND LOCKD CLIENTS M: Trond Myklebust L: linux-nfs@vger.kernel.org -- cgit v0.10.2 From 0d78156eef1d8869ea4e56f8a257252a8f262f04 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 20 Aug 2011 01:53:59 +0200 Subject: p54: improve site survey The firmware keeps track of channel usage. This data can be used by the automatic channel selection to find the best channel. Survey data from wlan4 frequency: 5200 MHz [in use] noise: -91 dBm channel active time: 811909 ms channel busy time: 63395 ms channel transmit time: 59636 ms Survey data from wlan4 frequency: 5210 MHz noise: -91 dBm channel active time: 121 ms channel busy time: 119 ms channel transmit time: 0 ms Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 54cc0bb..8b6f363 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -145,6 +145,7 @@ static int p54_fill_band_bitrates(struct ieee80211_hw *dev, static int p54_generate_band(struct ieee80211_hw *dev, struct p54_channel_list *list, + unsigned int *chan_num, enum ieee80211_band band) { struct p54_common *priv = dev->priv; @@ -190,7 +191,14 @@ static int p54_generate_band(struct ieee80211_hw *dev, tmp->channels[j].band = chan->band; tmp->channels[j].center_freq = chan->freq; + priv->survey[*chan_num].channel = &tmp->channels[j]; + priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | + SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_TX; + tmp->channels[j].hw_value = (*chan_num); j++; + (*chan_num)++; } if (j == 0) { @@ -263,7 +271,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; struct p54_channel_list *list; - unsigned int i, j, max_channel_num; + unsigned int i, j, k, max_channel_num; int ret = 0; u16 freq; @@ -283,6 +291,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) ret = -ENOMEM; goto free; } + priv->chan_num = max_channel_num; + priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num, + GFP_KERNEL); + if (!priv->survey) { + ret = -ENOMEM; + goto free; + } list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * @@ -321,8 +336,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) sort(list->channels, list->entries, sizeof(struct p54_channel_entry), p54_compare_channels, NULL); + k = 0; for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { - if (p54_generate_band(dev, list, i) == 0) + if (p54_generate_band(dev, list, &k, i) == 0) j++; } if (j == 0) { @@ -335,6 +351,10 @@ free: kfree(list->channels); kfree(list); } + if (ret) { + kfree(priv->survey); + priv->survey = NULL; + } return ret; } @@ -853,10 +873,12 @@ err: kfree(priv->output_limit); kfree(priv->curve_data); kfree(priv->rssi_db); + kfree(priv->survey); priv->iq_autocal = NULL; priv->output_limit = NULL; priv->curve_data = NULL; priv->rssi_db = NULL; + priv->survey = NULL; wiphy_err(dev->wiphy, "eeprom parse failed!\n"); return err; diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index b6a061c..53a3408 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -385,6 +385,7 @@ int p54_setup_mac(struct p54_common *priv) setup->v2.osc_start_delay = cpu_to_le16(65535); } p54_tx(priv, skb); + priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE; return 0; } @@ -626,6 +627,7 @@ int p54_set_ps(struct p54_common *priv) psm->exclude[0] = WLAN_EID_TIM; p54_tx(priv, skb); + priv->phy_ps = mode != P54_PSM_CAM; return 0; } diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index a5a6d9e..726a934 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -204,13 +204,11 @@ static void p54_stop(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; int i; - mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->softled_state = 0; - p54_set_leds(priv); - cancel_delayed_work_sync(&priv->work); - + mutex_lock(&priv->conf_mutex); + p54_set_leds(priv); priv->stop(dev); skb_queue_purge(&priv->tx_pending); skb_queue_purge(&priv->tx_queue); @@ -278,6 +276,42 @@ static void p54_remove_interface(struct ieee80211_hw *dev, mutex_unlock(&priv->conf_mutex); } +static int p54_wait_for_stats(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + int ret; + + priv->update_stats = true; + ret = p54_fetch_statistics(priv); + if (ret) + return ret; + + ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ); + if (ret == 0) + return -ETIMEDOUT; + + return 0; +} + +static void p54_reset_stats(struct p54_common *priv) +{ + struct ieee80211_channel *chan = priv->curchan; + + if (chan) { + struct survey_info *info = &priv->survey[chan->hw_value]; + + /* only reset channel statistics, don't touch .filled, etc. */ + info->channel_time = 0; + info->channel_time_busy = 0; + info->channel_time_tx = 0; + } + + priv->update_stats = true; + priv->survey_raw.active = 0; + priv->survey_raw.cca = 0; + priv->survey_raw.tx = 0; +} + static int p54_config(struct ieee80211_hw *dev, u32 changed) { int ret = 0; @@ -288,19 +322,36 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) priv->output_power = conf->power_level << 2; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + struct ieee80211_channel *oldchan; + WARN_ON(p54_wait_for_stats(dev)); + oldchan = priv->curchan; + priv->curchan = NULL; ret = p54_scan(priv, P54_SCAN_EXIT, 0); - if (ret) + if (ret) { + priv->curchan = oldchan; goto out; + } + /* + * TODO: Use the LM_SCAN_TRAP to determine the current + * operating channel. + */ + priv->curchan = priv->hw->conf.channel; + p54_reset_stats(priv); + WARN_ON(p54_fetch_statistics(priv)); } if (changed & IEEE80211_CONF_CHANGE_PS) { + WARN_ON(p54_wait_for_stats(dev)); ret = p54_set_ps(priv); if (ret) goto out; + WARN_ON(p54_wait_for_stats(dev)); } if (changed & IEEE80211_CONF_CHANGE_IDLE) { + WARN_ON(p54_wait_for_stats(dev)); ret = p54_setup_mac(priv); if (ret) goto out; + WARN_ON(p54_wait_for_stats(dev)); } out: @@ -384,7 +435,9 @@ static void p54_work(struct work_struct *work) * 2. cancel stuck frames / reset the device if necessary. */ - p54_fetch_statistics(priv); + mutex_lock(&priv->conf_mutex); + WARN_ON_ONCE(p54_fetch_statistics(priv)); + mutex_unlock(&priv->conf_mutex); } static int p54_get_stats(struct ieee80211_hw *dev, @@ -541,16 +594,47 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx, struct survey_info *survey) { struct p54_common *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; + struct ieee80211_channel *chan; + int err, tries; + bool in_use = false; - if (idx != 0) + if (idx >= priv->chan_num) return -ENOENT; - survey->channel = conf->channel; - survey->filled = SURVEY_INFO_NOISE_DBM; - survey->noise = clamp_t(s8, priv->noise, -128, 127); +#define MAX_TRIES 1 + for (tries = 0; tries < MAX_TRIES; tries++) { + chan = priv->curchan; + if (chan && chan->hw_value == idx) { + mutex_lock(&priv->conf_mutex); + err = p54_wait_for_stats(dev); + mutex_unlock(&priv->conf_mutex); + if (err) + return err; + + in_use = true; + } - return 0; + memcpy(survey, &priv->survey[idx], sizeof(*survey)); + + if (in_use) { + /* test if the reported statistics are valid. */ + if (survey->channel_time != 0) { + survey->filled |= SURVEY_INFO_IN_USE; + } else { + /* + * hw/fw has not accumulated enough sample sets. + * Wait for 100ms, this ought to be enough to + * to get at least one non-null set of channel + * usage statistics. + */ + msleep(100); + continue; + } + } + return 0; + } + return -ETIMEDOUT; +#undef MAX_TRIES } static unsigned int p54_flush_count(struct p54_common *priv) @@ -686,11 +770,14 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) mutex_init(&priv->conf_mutex); mutex_init(&priv->eeprom_mutex); + init_completion(&priv->stat_comp); init_completion(&priv->eeprom_comp); init_completion(&priv->beacon_comp); INIT_DELAYED_WORK(&priv->work, p54_work); memset(&priv->mc_maclist[0], ~0, ETH_ALEN); + priv->curchan = NULL; + p54_reset_stats(priv); return dev; } EXPORT_SYMBOL_GPL(p54_init_common); @@ -730,11 +817,13 @@ void p54_free_common(struct ieee80211_hw *dev) kfree(priv->curve_data); kfree(priv->rssi_db); kfree(priv->used_rxkeys); + kfree(priv->survey); priv->iq_autocal = NULL; priv->output_limit = NULL; priv->curve_data = NULL; priv->rssi_db = NULL; priv->used_rxkeys = NULL; + priv->survey = NULL; ieee80211_free_hw(dev); } EXPORT_SYMBOL_GPL(p54_free_common); diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 799d05e..452fa3a 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -199,6 +199,22 @@ struct p54_common { u8 tx_diversity_mask; unsigned int output_power; struct p54_rssi_db_entry *cur_rssi; + struct ieee80211_channel *curchan; + struct survey_info *survey; + unsigned int chan_num; + struct completion stat_comp; + bool update_stats; + struct { + unsigned int timestamp; + unsigned int cached_cca; + unsigned int cached_tx; + unsigned int cached_rssi; + u64 active; + u64 cca; + u64 tx; + u64 rssi; + } survey_raw; + int noise; /* calibration, output power limit and rssi<->dBm conversation data */ struct pda_iq_autocal_entry *iq_autocal; @@ -220,6 +236,8 @@ struct p54_common { u32 basic_rate_mask; u16 aid; u8 coverage_class; + bool phy_idle; + bool phy_ps; bool powersave_override; __le32 beacon_req_id; struct completion beacon_comp; diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 042842e..44a3bd4 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -507,6 +507,8 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) struct p54_hdr *hdr = (struct p54_hdr *) skb->data; struct p54_statistics *stats = (struct p54_statistics *) hdr->data; struct sk_buff *tmp; + struct ieee80211_channel *chan; + unsigned int i, rssi, tx, cca, dtime, dtotal, dcca, dtx, drssi, unit; u32 tsf32; if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) @@ -523,8 +525,72 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise)); + /* + * STSW450X LMAC API page 26 - 3.8 Statistics + * "The exact measurement period can be derived from the + * timestamp member". + */ + dtime = tsf32 - priv->survey_raw.timestamp; + + /* + * STSW450X LMAC API page 26 - 3.8.1 Noise histogram + * The LMAC samples RSSI, CCA and transmit state at regular + * periods (typically 8 times per 1k [as in 1024] usec). + */ + cca = le32_to_cpu(stats->sample_cca); + tx = le32_to_cpu(stats->sample_tx); + rssi = 0; + for (i = 0; i < ARRAY_SIZE(stats->sample_noise); i++) + rssi += le32_to_cpu(stats->sample_noise[i]); + + dcca = cca - priv->survey_raw.cached_cca; + drssi = rssi - priv->survey_raw.cached_rssi; + dtx = tx - priv->survey_raw.cached_tx; + dtotal = dcca + drssi + dtx; + + /* + * update statistics when more than a second is over since the + * last call, or when a update is badly needed. + */ + if (dtotal && (priv->update_stats || dtime >= USEC_PER_SEC) && + dtime >= dtotal) { + priv->survey_raw.timestamp = tsf32; + priv->update_stats = false; + unit = dtime / dtotal; + + if (dcca) { + priv->survey_raw.cca += dcca * unit; + priv->survey_raw.cached_cca = cca; + } + if (dtx) { + priv->survey_raw.tx += dtx * unit; + priv->survey_raw.cached_tx = tx; + } + if (drssi) { + priv->survey_raw.rssi += drssi * unit; + priv->survey_raw.cached_rssi = rssi; + } + + /* 1024 usec / 8 times = 128 usec / time */ + if (!(priv->phy_ps || priv->phy_idle)) + priv->survey_raw.active += dtotal * unit; + else + priv->survey_raw.active += (dcca + dtx) * unit; + } + + chan = priv->curchan; + if (chan) { + struct survey_info *survey = &priv->survey[chan->hw_value]; + survey->noise = clamp_t(s8, priv->noise, -128, 127); + survey->channel_time = priv->survey_raw.active / 1024; + survey->channel_time_tx = priv->survey_raw.tx / 1024; + survey->channel_time_busy = priv->survey_raw.cca / 1024 + + survey->channel_time_tx; + } + tmp = p54_find_and_unlink_skb(priv, hdr->req_id); dev_kfree_skb_any(tmp); + complete(&priv->stat_comp); } static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) -- cgit v0.10.2 From 52c94f413fdf5011b7e54ae68e0a2cfcb1b311df Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Sat, 20 Aug 2011 17:21:42 +0530 Subject: ath9k: Add support for get_stats callback this useful for debugging and to keep track of success/failure of frames such as ACK, RTS and FCS error count in a noisy environment Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 113c1df..5ac4f3f 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2403,6 +2403,20 @@ skip: return sc->beacon.tx_last; } +static int ath9k_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; + struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; + + stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; + stats->dot11RTSFailureCount = mib_stats->rts_bad; + stats->dot11FCSErrorCount = mib_stats->fcs_bad; + stats->dot11RTSSuccessCount = mib_stats->rts_good; + return 0; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2427,5 +2441,6 @@ struct ieee80211_ops ath9k_ops = { .set_coverage_class = ath9k_set_coverage_class, .flush = ath9k_flush, .tx_frames_pending = ath9k_tx_frames_pending, - .tx_last_beacon = ath9k_tx_last_beacon, + .tx_last_beacon = ath9k_tx_last_beacon, + .get_stats = ath9k_get_stats, }; -- cgit v0.10.2 From 2a15b394f8e46dd3e2ab365ab41cfa701d92fa77 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 20 Aug 2011 17:22:09 +0530 Subject: ath9k_hw: Fix descriptor status of TxOpExceeded Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 81ccce1..8ace36e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -253,8 +253,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, return -EIO; } - if (status & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; ts->ts_rateindex = MS(status, AR_FinalTxIdx); ts->ts_seqnum = MS(status, AR_SeqNum); ts->tid = MS(status, AR_TxTid); @@ -264,6 +262,8 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_status = 0; ts->ts_flags = 0; + if (status & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; status = ACCESS_ONCE(ads->status2); ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); -- cgit v0.10.2 From a35e27802291a8119c2b12532fb5f3c1b3e565a2 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 20 Aug 2011 17:22:10 +0530 Subject: ath9k: Change rate control to use legacy rate as last MRR In congested network, having all rate reties at MCS rates is failing to transmit the frame offenly. By the time reaching the success rate set, the application gets timed out. One such scenario is that authentication time out during 4-Way handshake. This patch uses a legacy rate as last retry sequnce for unaggregated frames or if the first selected rate's PER is ~80% of max limit. And also observed from the tx status that the frame was trasmitted successfully by using legacy rates. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 9e3649a..4f13018 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -603,7 +603,8 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, static u8 ath_rc_get_highest_rix(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, const struct ath_rate_table *rate_table, - int *is_probing) + int *is_probing, + bool legacy) { u32 best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; @@ -624,6 +625,8 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, u8 per_thres; rate = ath_rc_priv->valid_rate_index[index]; + if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY)) + continue; if (rate > ath_rc_priv->rate_max_phy) continue; @@ -767,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate *rates = tx_info->control.rates; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; - u8 try_per_rate, i = 0, rix; + u8 try_per_rate, i = 0, rix, high_rix; int is_probe = 0; if (rate_control_send_low(sta, priv_sta, txrc)) @@ -786,7 +789,9 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate = 4; rate_table = ath_rc_priv->rate_table; - rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); + rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, + &is_probe, false); + high_rix = rix; /* * If we're in HT mode and both us and our peer supports LDPC. @@ -822,10 +827,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, } /* Fill in the other rates for multirate retry */ - for ( ; i < 4; i++) { - /* Use twice the number of tries for the last MRR segment. */ - if (i + 1 == 4) - try_per_rate = 8; + for ( ; i < 3; i++) { ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); /* All other rates in the series have RTS enabled */ @@ -833,6 +835,24 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate, rix, 1); } + /* Use twice the number of tries for the last MRR segment. */ + try_per_rate = 8; + + /* + * Use a legacy rate as last retry to ensure that the frame + * is tried in both MCS and legacy rates. + */ + if ((rates[2].flags & IEEE80211_TX_RC_MCS) && + (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) || + (ath_rc_priv->per[high_rix] > 45))) + rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, + &is_probe, true); + else + ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); + + /* All other rates in the series have RTS enabled */ + ath_rc_rate_set_series(rate_table, &rates[i], txrc, + try_per_rate, rix, 1); /* * NB:Change rate series to enable aggregation when operating * at lower MCS rates. When first rate in series is MCS2 -- cgit v0.10.2 From 8ad38d22dc6f6c244642ca1fbe9255d7d149870a Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 20 Aug 2011 17:34:19 +0530 Subject: ath9k_hw: Disable Walsh spatial spreading for 2 chains The Walsh bit is disabled for regulatory consideration. FCC limit for walsh enable is lower than that for walsh disable. So disabling walsh bit will not limit tx power/affect tx power even in cases where we are not FCC limited (most client cards). If the tx power is not FCC limited, then enabling/disabling walsh bit will not affect Avg. EVM/overall performance in any visible manner. Cc: Felix Fietkau Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index a0aadad..f2c6f23 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -636,7 +636,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, + {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0}, {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, {0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f}, {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 88468a0..33edb56 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -482,7 +482,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO); /* Enable 11n HT, 20 MHz */ - phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH | + phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_SHORT_GI_40 | enableDacFifo; /* Configure baseband for dynamic 20/40 operation */ -- cgit v0.10.2 From 8b0be90c4d3770b0c31489fc3ae33e5d8ba9edf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BCsch?= Date: Sun, 21 Aug 2011 17:24:47 +0200 Subject: b43/legacy: Remove firmware IDs This removes the "FWxx" ID strings from the b43 and b43legacy drivers. They were once used to match a specific driver revision to a set of firmware files. However, this is hardly useful today. Additionally, the IDs are not updated and maintained properly, so they might mislead users. Signed-off-by: Michael Buesch Acked-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 9e5974b..8a52657 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -17,11 +17,6 @@ #include "phy_common.h" -/* The unique identifier of the firmware that's officially supported by - * this driver version. */ -#define B43_SUPPORTED_FIRMWARE_ID "FW13" - - #ifdef CONFIG_B43_DEBUG # define B43_DEBUG 1 #else diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index bf17516..0628901 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -66,7 +66,6 @@ MODULE_AUTHOR("Michael Buesch"); MODULE_AUTHOR("Gábor Stefanik"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); MODULE_FIRMWARE("b43/ucode11.fw"); MODULE_FIRMWARE("b43/ucode13.fw"); MODULE_FIRMWARE("b43/ucode14.fw"); @@ -5460,8 +5459,7 @@ static void b43_print_driverinfo(void) feat_sdio = "S"; #endif printk(KERN_INFO "Broadcom 43xx driver loaded " - "[ Features: %s%s%s%s%s, Firmware-ID: " - B43_SUPPORTED_FIRMWARE_ID " ]\n", + "[ Features: %s%s%s%s%s ]\n", feat_pci, feat_pcmcia, feat_nphy, feat_leds, feat_sdio); } diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index ad4e743..12b5182 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -22,10 +22,6 @@ #include "phy.h" -/* The unique identifier of the firmware that's officially supported by this - * driver version. */ -#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10" - #define B43legacy_IRQWAIT_MAX_RETRIES 20 /* MMIO offsets */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index aae8dfc..468d183 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -60,7 +60,6 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); MODULE_FIRMWARE("b43legacy/ucode2.fw"); MODULE_FIRMWARE("b43legacy/ucode4.fw"); @@ -3947,8 +3946,7 @@ static void b43legacy_print_driverinfo(void) feat_dma = "D"; #endif printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " - "[ Features: %s%s%s%s, Firmware-ID: " - B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", + "[ Features: %s%s%s%s ]\n", feat_pci, feat_leds, feat_pio, feat_dma); } -- cgit v0.10.2 From f750323009b6540cc614304fd784300b49506797 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Aug 2011 16:16:14 +0200 Subject: drivers/net/wireless/mwifiex/scan.c: test the just-initialized value Test the just-initialized value rather than some other one. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ identifier x,y,f!={PTR_ERR,ERR_PTR,ERR_CAST}; statement S; @@ x = f(...); ( if (\(x == NULL\|IS_ERR(x)\)) S | *if (\(y == NULL\|IS_ERR(y)\)) { ... when != x return ...; } ) // Signed-off-by: Julia Lawall Acked-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index b28241c..37ca2f9 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1480,8 +1480,8 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, return -ENOMEM; } beacon_ie = kzalloc(ie_len, GFP_KERNEL); - if (!bss_desc) { - dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); + if (!beacon_ie) { + dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); return -ENOMEM; } memcpy(beacon_ie, ie_buf, ie_len); -- cgit v0.10.2 From 7ad0ce3576edb2ea65bd5c93a83c4a6afaa1dd76 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 22 Aug 2011 16:50:14 -0500 Subject: rtlwifi: Install updated rate-mapping routine In preparation for fixing the rate-mapping situation, place a driver-agnostic version in rtlwifi. This one contains the updated rate incormation. Signed-off-by: Larry Finger Cc: Chaoming Li Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 0b598db..098fc55 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -664,6 +664,167 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw) return hw_rate; } +/* mac80211's rate_idx is like this: + * + * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ + * + * B/G rate: + * (rx_status->flag & RX_FLAG_HT) = 0, + * DESC92_RATE1M-->DESC92_RATE54M ==> idx is 0-->11, + * + * N rate: + * (rx_status->flag & RX_FLAG_HT) = 1, + * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15 + * + * 5G band:rx_status->band == IEEE80211_BAND_5GHZ + * A rate: + * (rx_status->flag & RX_FLAG_HT) = 0, + * DESC92_RATE6M-->DESC92_RATE54M ==> idx is 0-->7, + * + * N rate: + * (rx_status->flag & RX_FLAG_HT) = 1, + * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15 + */ +int rtlwifi_rate_mapping(struct ieee80211_hw *hw, + bool isht, u8 desc_rate, bool first_ampdu) +{ + int rate_idx; + + if (false == isht) { + if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) { + switch (desc_rate) { + case DESC92_RATE1M: + rate_idx = 0; + break; + case DESC92_RATE2M: + rate_idx = 1; + break; + case DESC92_RATE5_5M: + rate_idx = 2; + break; + case DESC92_RATE11M: + rate_idx = 3; + break; + case DESC92_RATE6M: + rate_idx = 4; + break; + case DESC92_RATE9M: + rate_idx = 5; + break; + case DESC92_RATE12M: + rate_idx = 6; + break; + case DESC92_RATE18M: + rate_idx = 7; + break; + case DESC92_RATE24M: + rate_idx = 8; + break; + case DESC92_RATE36M: + rate_idx = 9; + break; + case DESC92_RATE48M: + rate_idx = 10; + break; + case DESC92_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + } else { + switch (desc_rate) { + case DESC92_RATE6M: + rate_idx = 0; + break; + case DESC92_RATE9M: + rate_idx = 1; + break; + case DESC92_RATE12M: + rate_idx = 2; + break; + case DESC92_RATE18M: + rate_idx = 3; + break; + case DESC92_RATE24M: + rate_idx = 4; + break; + case DESC92_RATE36M: + rate_idx = 5; + break; + case DESC92_RATE48M: + rate_idx = 6; + break; + case DESC92_RATE54M: + rate_idx = 7; + break; + default: + rate_idx = 0; + break; + } + } + + } else { + + switch (desc_rate) { + case DESC92_RATEMCS0: + rate_idx = 0; + break; + case DESC92_RATEMCS1: + rate_idx = 1; + break; + case DESC92_RATEMCS2: + rate_idx = 2; + break; + case DESC92_RATEMCS3: + rate_idx = 3; + break; + case DESC92_RATEMCS4: + rate_idx = 4; + break; + case DESC92_RATEMCS5: + rate_idx = 5; + break; + case DESC92_RATEMCS6: + rate_idx = 6; + break; + case DESC92_RATEMCS7: + rate_idx = 7; + break; + case DESC92_RATEMCS8: + rate_idx = 8; + break; + case DESC92_RATEMCS9: + rate_idx = 9; + break; + case DESC92_RATEMCS10: + rate_idx = 10; + break; + case DESC92_RATEMCS11: + rate_idx = 11; + break; + case DESC92_RATEMCS12: + rate_idx = 12; + break; + case DESC92_RATEMCS13: + rate_idx = 13; + break; + case DESC92_RATEMCS14: + rate_idx = 14; + break; + case DESC92_RATEMCS15: + rate_idx = 15; + break; + default: + rate_idx = 0; + break; + } + } + return rate_idx; +} +EXPORT_SYMBOL(rtlwifi_rate_mapping); + void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index a91f3ee..4ae9059 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h @@ -140,4 +140,6 @@ u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid); extern struct attribute_group rtl_attribute_group; +int rtlwifi_rate_mapping(struct ieee80211_hw *hw, + bool isht, u8 desc_rate, bool first_ampdu); #endif diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index d3c3ffd..8a90919 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -386,6 +386,41 @@ enum rtl_hal_state { _HAL_STATE_START = 1, }; +enum rtl_desc92_rate { + DESC92_RATE1M = 0x00, + DESC92_RATE2M = 0x01, + DESC92_RATE5_5M = 0x02, + DESC92_RATE11M = 0x03, + + DESC92_RATE6M = 0x04, + DESC92_RATE9M = 0x05, + DESC92_RATE12M = 0x06, + DESC92_RATE18M = 0x07, + DESC92_RATE24M = 0x08, + DESC92_RATE36M = 0x09, + DESC92_RATE48M = 0x0a, + DESC92_RATE54M = 0x0b, + + DESC92_RATEMCS0 = 0x0c, + DESC92_RATEMCS1 = 0x0d, + DESC92_RATEMCS2 = 0x0e, + DESC92_RATEMCS3 = 0x0f, + DESC92_RATEMCS4 = 0x10, + DESC92_RATEMCS5 = 0x11, + DESC92_RATEMCS6 = 0x12, + DESC92_RATEMCS7 = 0x13, + DESC92_RATEMCS8 = 0x14, + DESC92_RATEMCS9 = 0x15, + DESC92_RATEMCS10 = 0x16, + DESC92_RATEMCS11 = 0x17, + DESC92_RATEMCS12 = 0x18, + DESC92_RATEMCS13 = 0x19, + DESC92_RATEMCS14 = 0x1a, + DESC92_RATEMCS15 = 0x1b, + DESC92_RATEMCS15_SG = 0x1c, + DESC92_RATEMCS32 = 0x20, +}; + enum rtl_var_map { /*reg map */ SYS_ISO_CTRL = 0, -- cgit v0.10.2 From 78851b66b1f4c00fe324d53ae55dbf5bf9a02e27 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 22 Aug 2011 16:50:15 -0500 Subject: rtlwifi: rtl8192ce: Convert to use the new rate-mapping routine in rtlwifi Signed-off-by: Larry Finger Cc: Chaoming Li Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 373dc78..4c34c4c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -318,21 +318,21 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, }; DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 230bbe9..4fb5ae2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -48,104 +48,6 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) return skb->priority; } -static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -{ - int rate_idx; - - if (first_ampdu) { - if (false == isht) { - switch (desc_rate) { - case DESC92C_RATE1M: - rate_idx = 0; - break; - case DESC92C_RATE2M: - rate_idx = 1; - break; - case DESC92C_RATE5_5M: - rate_idx = 2; - break; - case DESC92C_RATE11M: - rate_idx = 3; - break; - case DESC92C_RATE6M: - rate_idx = 4; - break; - case DESC92C_RATE9M: - rate_idx = 5; - break; - case DESC92C_RATE12M: - rate_idx = 6; - break; - case DESC92C_RATE18M: - rate_idx = 7; - break; - case DESC92C_RATE24M: - rate_idx = 8; - break; - case DESC92C_RATE36M: - rate_idx = 9; - break; - case DESC92C_RATE48M: - rate_idx = 10; - break; - case DESC92C_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 0; - break; - } - } else { - rate_idx = 11; - } - - return rate_idx; - } - - switch (desc_rate) { - case DESC92C_RATE1M: - rate_idx = 0; - break; - case DESC92C_RATE2M: - rate_idx = 1; - break; - case DESC92C_RATE5_5M: - rate_idx = 2; - break; - case DESC92C_RATE11M: - rate_idx = 3; - break; - case DESC92C_RATE6M: - rate_idx = 4; - break; - case DESC92C_RATE9M: - rate_idx = 5; - break; - case DESC92C_RATE12M: - rate_idx = 6; - break; - case DESC92C_RATE18M: - rate_idx = 7; - break; - case DESC92C_RATE24M: - rate_idx = 8; - break; - case DESC92C_RATE36M: - rate_idx = 9; - break; - case DESC92C_RATE48M: - rate_idx = 10; - break; - case DESC92C_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 11; - break; - } - return rate_idx; -} - static u8 _rtl92c_query_rxpwrpercentage(char antpower) { if ((antpower <= -100) || (antpower >= 20)) @@ -336,8 +238,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; - if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 && - pdesc->rxmcs <= DESC92C_RATEMCS15) + if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && + pdesc->rxmcs <= DESC92_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -670,12 +572,10 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = _rtl92ce_rate_mapping((bool) - GET_RX_DESC_RXHT(pdesc), - (u8) - GET_RX_DESC_RXMCS(pdesc), - (bool) - GET_RX_DESC_PAGGR(pdesc)); + rx_status->rate_idx = rtlwifi_rate_mapping(hw, + (bool)GET_RX_DESC_RXHT(pdesc), + (u8)GET_RX_DESC_RXMCS(pdesc), + (bool)GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { @@ -768,7 +668,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_BW(pdesc, 0); SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? + ((tcb_desc->rts_rate <= DESC92_RATE54M) ? (tcb_desc->rts_use_shortpreamble ? 1 : 0) : (tcb_desc->rts_use_shortgi ? 1 : 0))); @@ -886,7 +786,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, if (firstseg) SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); SET_TX_DESC_SEQ(pdesc, 0); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index 0f11771..81ae642 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -538,10 +538,10 @@ do { \ } while (0); #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (_pdesc->rxmcs == DESC92C_RATE1M || \ - _pdesc->rxmcs == DESC92C_RATE2M || \ - _pdesc->rxmcs == DESC92C_RATE5_5M || \ - _pdesc->rxmcs == DESC92C_RATE11M) + (_pdesc->rxmcs == DESC92_RATE1M || \ + _pdesc->rxmcs == DESC92_RATE2M || \ + _pdesc->rxmcs == DESC92_RATE5_5M || \ + _pdesc->rxmcs == DESC92_RATE11M) struct rx_fwinfo_92c { u8 gain_trsw[4]; -- cgit v0.10.2 From 2b67e88f648f3b16783feb09178719380150e51f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 22 Aug 2011 16:50:16 -0500 Subject: rtlwifi: rtl8192cu: Convert to use the new rate-mapping routine in rtlwifi This patch also removes the now unused code from rtl8192ce/def.h. Signed-off-by: Larry Finger Cc: Chaoming Li Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 35ff7df..11f4319 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -220,41 +220,6 @@ enum rtl_desc_qsel { QSLT_CMD = 0x13, }; -enum rtl_desc92c_rate { - DESC92C_RATE1M = 0x00, - DESC92C_RATE2M = 0x01, - DESC92C_RATE5_5M = 0x02, - DESC92C_RATE11M = 0x03, - - DESC92C_RATE6M = 0x04, - DESC92C_RATE9M = 0x05, - DESC92C_RATE12M = 0x06, - DESC92C_RATE18M = 0x07, - DESC92C_RATE24M = 0x08, - DESC92C_RATE36M = 0x09, - DESC92C_RATE48M = 0x0a, - DESC92C_RATE54M = 0x0b, - - DESC92C_RATEMCS0 = 0x0c, - DESC92C_RATEMCS1 = 0x0d, - DESC92C_RATEMCS2 = 0x0e, - DESC92C_RATEMCS3 = 0x0f, - DESC92C_RATEMCS4 = 0x10, - DESC92C_RATEMCS5 = 0x11, - DESC92C_RATEMCS6 = 0x12, - DESC92C_RATEMCS7 = 0x13, - DESC92C_RATEMCS8 = 0x14, - DESC92C_RATEMCS9 = 0x15, - DESC92C_RATEMCS10 = 0x16, - DESC92C_RATEMCS11 = 0x17, - DESC92C_RATEMCS12 = 0x18, - DESC92C_RATEMCS13 = 0x19, - DESC92C_RATEMCS14 = 0x1a, - DESC92C_RATEMCS15 = 0x1b, - DESC92C_RATEMCS15_SG = 0x1c, - DESC92C_RATEMCS32 = 0x20, -}; - struct phy_sts_cck_8192s_t { u8 adc_pwdb_X[4]; u8 sq_rpt; @@ -267,108 +232,4 @@ struct h2c_cmd_8192c { u8 *p_cmdbuffer; }; -/* NOTE: reference to rtl8192c_rates struct */ -static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, - u8 desc_rate, bool first_ampdu) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int rate_idx = 0; - - if (first_ampdu) { - if (false == isHT) { - switch (desc_rate) { - case DESC92C_RATE1M: - rate_idx = 0; - break; - case DESC92C_RATE2M: - rate_idx = 1; - break; - case DESC92C_RATE5_5M: - rate_idx = 2; - break; - case DESC92C_RATE11M: - rate_idx = 3; - break; - case DESC92C_RATE6M: - rate_idx = 4; - break; - case DESC92C_RATE9M: - rate_idx = 5; - break; - case DESC92C_RATE12M: - rate_idx = 6; - break; - case DESC92C_RATE18M: - rate_idx = 7; - break; - case DESC92C_RATE24M: - rate_idx = 8; - break; - case DESC92C_RATE36M: - rate_idx = 9; - break; - case DESC92C_RATE48M: - rate_idx = 10; - break; - case DESC92C_RATE54M: - rate_idx = 11; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - ("Rate %d is not support, set to " - "1M rate.\n", desc_rate)); - rate_idx = 0; - break; - } - } else { - rate_idx = 11; - } - return rate_idx; - } - switch (desc_rate) { - case DESC92C_RATE1M: - rate_idx = 0; - break; - case DESC92C_RATE2M: - rate_idx = 1; - break; - case DESC92C_RATE5_5M: - rate_idx = 2; - break; - case DESC92C_RATE11M: - rate_idx = 3; - break; - case DESC92C_RATE6M: - rate_idx = 4; - break; - case DESC92C_RATE9M: - rate_idx = 5; - break; - case DESC92C_RATE12M: - rate_idx = 6; - break; - case DESC92C_RATE18M: - rate_idx = 7; - break; - case DESC92C_RATE24M: - rate_idx = 8; - break; - case DESC92C_RATE36M: - rate_idx = 9; - break; - case DESC92C_RATE48M: - rate_idx = 10; - break; - case DESC92C_RATE54M: - rate_idx = 11; - break; - /* TODO: How to mapping MCS rate? */ - /* NOTE: referenc to __ieee80211_rx */ - default: - rate_idx = 11; - break; - } - return rate_idx; -} - #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index 194fc69..060a06f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -892,8 +892,8 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; if (GET_RX_DESC_RX_MCS(pdesc) && - GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 && - GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15) + GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 && + GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h index 298fdb7..35529f7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h @@ -88,10 +88,10 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter); u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw); #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\ - GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\ - GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\ - GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M) + (GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||\ + GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||\ + GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ + GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE11M) struct rx_fwinfo_92c { u8 gain_trsw[4]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 17a8e96..1e851aa 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tx_agc[RF90_PATH_A] = 0x10101010; tx_agc[RF90_PATH_B] = 0x10101010; } else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL2) { + TXHIGHPWRLEVEL_LEVEL1) { tx_agc[RF90_PATH_A] = 0x00000000; tx_agc[RF90_PATH_B] = 0x00000000; } else{ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 942f7a3..195666a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -241,20 +241,20 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, - .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, + .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, }; #define USB_VENDER_ID_REALTEK 0x0bda diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 906e7aa..c416114 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -337,10 +337,10 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = _rtl92c_rate_mapping(hw, - (bool)GET_RX_DESC_RX_HT(pdesc), - (u8)GET_RX_DESC_RX_MCS(pdesc), - (bool)GET_RX_DESC_PAGGR(pdesc)); + rx_status->rate_idx = rtlwifi_rate_mapping(hw, + (bool)GET_RX_DESC_RX_HT(pdesc), + (u8)GET_RX_DESC_RX_MCS(pdesc), + (bool)GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); @@ -406,11 +406,10 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) if (GET_RX_DESC_RX_HT(rxdesc)) rx_status->flag |= RX_FLAG_HT; /* Data rate */ - rx_status->rate_idx = _rtl92c_rate_mapping(hw, - (bool)GET_RX_DESC_RX_HT(rxdesc), - (u8)GET_RX_DESC_RX_MCS(rxdesc), - (bool)GET_RX_DESC_PAGGR(rxdesc) - ); + rx_status->rate_idx = rtlwifi_rate_mapping(hw, + (bool)GET_RX_DESC_RX_HT(rxdesc), + (u8)GET_RX_DESC_RX_MCS(rxdesc), + (bool)GET_RX_DESC_PAGGR(rxdesc)); /* There is a phy status after this rx descriptor. */ if (GET_RX_DESC_PHY_STATUS(rxdesc)) { p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); @@ -545,7 +544,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_BW(txdesc, 0); SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(txdesc, - ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? + ((tcb_desc->rts_rate <= DESC92_RATE54M) ? (tcb_desc->rts_use_shortpreamble ? 1 : 0) : (tcb_desc->rts_use_shortgi ? 1 : 0))); if (mac->bw_40) { @@ -643,7 +642,7 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, } SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ SET_TX_DESC_OWN(pDesc, 1); - SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M); + SET_TX_DESC_TX_RATE(pDesc, DESC92_RATE1M); _rtl_tx_desc_checksum(pDesc); } @@ -659,7 +658,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); if (firstseg) SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); SET_TX_DESC_SEQ(pdesc, 0); SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); -- cgit v0.10.2 From 8e35337731abb901f3ae20ebc3f44a50ba6953e9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 22 Aug 2011 16:50:17 -0500 Subject: rtlwifi: rtl8192se: Convert to use the new rate-mapping routine in rtlwifi This patch also deletes the now unused parts of rtl8192se/def.h. Signed-off-by: Larry Finger Cc: Chaoming Li Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 69828f2..68204ea 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h @@ -33,37 +33,6 @@ #define RX_CMD_QUEUE 1 #define RX_MAX_QUEUE 2 -#define DESC92S_RATE1M 0x00 -#define DESC92S_RATE2M 0x01 -#define DESC92S_RATE5_5M 0x02 -#define DESC92S_RATE11M 0x03 -#define DESC92S_RATE6M 0x04 -#define DESC92S_RATE9M 0x05 -#define DESC92S_RATE12M 0x06 -#define DESC92S_RATE18M 0x07 -#define DESC92S_RATE24M 0x08 -#define DESC92S_RATE36M 0x09 -#define DESC92S_RATE48M 0x0a -#define DESC92S_RATE54M 0x0b -#define DESC92S_RATEMCS0 0x0c -#define DESC92S_RATEMCS1 0x0d -#define DESC92S_RATEMCS2 0x0e -#define DESC92S_RATEMCS3 0x0f -#define DESC92S_RATEMCS4 0x10 -#define DESC92S_RATEMCS5 0x11 -#define DESC92S_RATEMCS6 0x12 -#define DESC92S_RATEMCS7 0x13 -#define DESC92S_RATEMCS8 0x14 -#define DESC92S_RATEMCS9 0x15 -#define DESC92S_RATEMCS10 0x16 -#define DESC92S_RATEMCS11 0x17 -#define DESC92S_RATEMCS12 0x18 -#define DESC92S_RATEMCS13 0x19 -#define DESC92S_RATEMCS14 0x1a -#define DESC92S_RATEMCS15 0x1b -#define DESC92S_RATEMCS15_SG 0x1c -#define DESC92S_RATEMCS32 0x20 - #define SHORT_SLOT_TIME 9 #define NON_SHORT_SLOT_TIME 20 @@ -491,10 +460,10 @@ do { \ SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M) + (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE11M) enum rf_optype { RF_OP_BY_SW_3WIRE = 0, diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 3876078..0055a1c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -348,21 +348,21 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, }; static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index cffe308..d9aeae7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -51,104 +51,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) return skb->priority; } -static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -{ - int rate_idx = 0; - - if (first_ampdu) { - if (false == isht) { - switch (desc_rate) { - case DESC92S_RATE1M: - rate_idx = 0; - break; - case DESC92S_RATE2M: - rate_idx = 1; - break; - case DESC92S_RATE5_5M: - rate_idx = 2; - break; - case DESC92S_RATE11M: - rate_idx = 3; - break; - case DESC92S_RATE6M: - rate_idx = 4; - break; - case DESC92S_RATE9M: - rate_idx = 5; - break; - case DESC92S_RATE12M: - rate_idx = 6; - break; - case DESC92S_RATE18M: - rate_idx = 7; - break; - case DESC92S_RATE24M: - rate_idx = 8; - break; - case DESC92S_RATE36M: - rate_idx = 9; - break; - case DESC92S_RATE48M: - rate_idx = 10; - break; - case DESC92S_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 0; - break; - } - } else { - rate_idx = 11; - } - - return rate_idx; - } - - switch (desc_rate) { - case DESC92S_RATE1M: - rate_idx = 0; - break; - case DESC92S_RATE2M: - rate_idx = 1; - break; - case DESC92S_RATE5_5M: - rate_idx = 2; - break; - case DESC92S_RATE11M: - rate_idx = 3; - break; - case DESC92S_RATE6M: - rate_idx = 4; - break; - case DESC92S_RATE9M: - rate_idx = 5; - break; - case DESC92S_RATE12M: - rate_idx = 6; - break; - case DESC92S_RATE18M: - rate_idx = 7; - break; - case DESC92S_RATE24M: - rate_idx = 8; - break; - case DESC92S_RATE36M: - rate_idx = 9; - break; - case DESC92S_RATE48M: - rate_idx = 10; - break; - case DESC92S_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 11; - break; - } - return rate_idx; -} - static u8 _rtl92s_query_rxpwrpercentage(char antpower) { if ((antpower <= -100) || (antpower >= 20)) @@ -345,8 +247,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, pstats->recvsignalpower = rx_pwr_all; if (GET_RX_STATUS_DESC_RX_HT(pdesc) && - GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 && - GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15) + GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 && + GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -654,10 +556,10 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = _rtl92se_rate_mapping((bool) - GET_RX_STATUS_DESC_RX_HT(pdesc), - (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), - (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); + rx_status->rate_idx = rtlwifi_rate_mapping(hw, + (bool)GET_RX_STATUS_DESC_RX_HT(pdesc), + (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), + (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); @@ -723,14 +625,14 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= - DESC92S_RATEMCS0) ? 1 : 0)); + DESC92_RATEMCS0) ? 1 : 0)); if (rtlhal->version == VERSION_8192S_ACUT) { - if (ptcb_desc->hw_rate == DESC92S_RATE1M || - ptcb_desc->hw_rate == DESC92S_RATE2M || - ptcb_desc->hw_rate == DESC92S_RATE5_5M || - ptcb_desc->hw_rate == DESC92S_RATE11M) { - ptcb_desc->hw_rate = DESC92S_RATE12M; + if (ptcb_desc->hw_rate == DESC92_RATE1M || + ptcb_desc->hw_rate == DESC92_RATE2M || + ptcb_desc->hw_rate == DESC92_RATE5_5M || + ptcb_desc->hw_rate == DESC92_RATE11M) { + ptcb_desc->hw_rate = DESC92_RATE12M; } } @@ -759,7 +661,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= - DESC92S_RATE54M) ? + DESC92_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); -- cgit v0.10.2 From 5b62bb5cc1abe2a2c194833e9266cb78ae36fe61 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 22 Aug 2011 16:50:18 -0500 Subject: rtlwifi: rtl8192de: Convert to use the new rate-mapping routine in rtlwifi This patch also deletes the now unused parts of rtl8192de/def.h. Signed-off-by: Larry Finger Cc: Chaoming Li Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h index f0f5f9b..aff7e19 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h @@ -193,41 +193,6 @@ enum rtl_desc_qsel { QSLT_CMD = 0x13, }; -enum rtl_desc92d_rate { - DESC92D_RATE1M = 0x00, - DESC92D_RATE2M = 0x01, - DESC92D_RATE5_5M = 0x02, - DESC92D_RATE11M = 0x03, - - DESC92D_RATE6M = 0x04, - DESC92D_RATE9M = 0x05, - DESC92D_RATE12M = 0x06, - DESC92D_RATE18M = 0x07, - DESC92D_RATE24M = 0x08, - DESC92D_RATE36M = 0x09, - DESC92D_RATE48M = 0x0a, - DESC92D_RATE54M = 0x0b, - - DESC92D_RATEMCS0 = 0x0c, - DESC92D_RATEMCS1 = 0x0d, - DESC92D_RATEMCS2 = 0x0e, - DESC92D_RATEMCS3 = 0x0f, - DESC92D_RATEMCS4 = 0x10, - DESC92D_RATEMCS5 = 0x11, - DESC92D_RATEMCS6 = 0x12, - DESC92D_RATEMCS7 = 0x13, - DESC92D_RATEMCS8 = 0x14, - DESC92D_RATEMCS9 = 0x15, - DESC92D_RATEMCS10 = 0x16, - DESC92D_RATEMCS11 = 0x17, - DESC92D_RATEMCS12 = 0x18, - DESC92D_RATEMCS13 = 0x19, - DESC92D_RATEMCS14 = 0x1a, - DESC92D_RATEMCS15 = 0x1b, - DESC92D_RATEMCS15_SG = 0x1c, - DESC92D_RATEMCS32 = 0x20, -}; - enum channel_plan { CHPL_FCC = 0, CHPL_IC = 1, diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 351765d..f6419b7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -340,21 +340,21 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, }; static struct pci_device_id rtl92de_pci_ids[] __devinitdata = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index dc86fcb..3637c0c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -48,99 +48,6 @@ static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) return skb->priority; } -static int _rtl92de_rate_mapping(bool isht, u8 desc_rate) -{ - int rate_idx; - - if (false == isht) { - switch (desc_rate) { - case DESC92D_RATE1M: - rate_idx = 0; - break; - case DESC92D_RATE2M: - rate_idx = 1; - break; - case DESC92D_RATE5_5M: - rate_idx = 2; - break; - case DESC92D_RATE11M: - rate_idx = 3; - break; - case DESC92D_RATE6M: - rate_idx = 4; - break; - case DESC92D_RATE9M: - rate_idx = 5; - break; - case DESC92D_RATE12M: - rate_idx = 6; - break; - case DESC92D_RATE18M: - rate_idx = 7; - break; - case DESC92D_RATE24M: - rate_idx = 8; - break; - case DESC92D_RATE36M: - rate_idx = 9; - break; - case DESC92D_RATE48M: - rate_idx = 10; - break; - case DESC92D_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 0; - break; - } - return rate_idx; - } else { - switch (desc_rate) { - case DESC92D_RATE1M: - rate_idx = 0; - break; - case DESC92D_RATE2M: - rate_idx = 1; - break; - case DESC92D_RATE5_5M: - rate_idx = 2; - break; - case DESC92D_RATE11M: - rate_idx = 3; - break; - case DESC92D_RATE6M: - rate_idx = 4; - break; - case DESC92D_RATE9M: - rate_idx = 5; - break; - case DESC92D_RATE12M: - rate_idx = 6; - break; - case DESC92D_RATE18M: - rate_idx = 7; - break; - case DESC92D_RATE24M: - rate_idx = 8; - break; - case DESC92D_RATE36M: - rate_idx = 9; - break; - case DESC92D_RATE48M: - rate_idx = 10; - break; - case DESC92D_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 11; - break; - } - return rate_idx; - } -} - static u8 _rtl92d_query_rxpwrpercentage(char antpower) { if ((antpower <= -100) || (antpower >= 20)) @@ -328,8 +235,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, pstats->rx_pwdb_all = pwdb_all; pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; - if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 && - pdesc->rxmcs <= DESC92D_RATEMCS15) + if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && + pdesc->rxmcs <= DESC92_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -609,10 +516,10 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = _rtl92de_rate_mapping((bool) - GET_RX_DESC_RXHT(pdesc), - (u8) - GET_RX_DESC_RXMCS(pdesc)); + rx_status->rate_idx = rtlwifi_rate_mapping(hw, + (bool)GET_RX_DESC_RXHT(pdesc), + (u8)GET_RX_DESC_RXMCS(pdesc), + (bool)GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { p_drvinfo = (struct rx_fwinfo_92d *)(skb->data + @@ -705,14 +612,14 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, } /* 5G have no CCK rate */ if (rtlhal->current_bandtype == BAND_ON_5G) - if (ptcb_desc->hw_rate < DESC92D_RATE6M) - ptcb_desc->hw_rate = DESC92D_RATE6M; + if (ptcb_desc->hw_rate < DESC92_RATE6M) + ptcb_desc->hw_rate = DESC92_RATE6M; SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); if (rtlhal->macphymode == DUALMAC_DUALPHY && - ptcb_desc->hw_rate == DESC92D_RATEMCS7) + ptcb_desc->hw_rate == DESC92_RATEMCS7) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); if (info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -728,13 +635,13 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); /* 5G have no CCK rate */ if (rtlhal->current_bandtype == BAND_ON_5G) - if (ptcb_desc->rts_rate < DESC92D_RATE6M) - ptcb_desc->rts_rate = DESC92D_RATE6M; + if (ptcb_desc->rts_rate < DESC92_RATE6M) + ptcb_desc->rts_rate = DESC92_RATE6M; SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); SET_TX_DESC_RTS_BW(pdesc, 0); SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= - DESC92D_RATE54M) ? + DESC92_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); if (bw_40) { @@ -844,9 +751,9 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, * The braces are needed no matter what checkpatch says */ if (rtlhal->current_bandtype == BAND_ON_5G) { - SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M); + SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE6M); } else { - SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); } SET_TX_DESC_SEQ(pdesc, 0); SET_TX_DESC_LINIP(pdesc, 0); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h index 992d676..6c22368 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h @@ -538,10 +538,10 @@ do { \ } while (0); #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (_pdesc->rxmcs == DESC92D_RATE1M || \ - _pdesc->rxmcs == DESC92D_RATE2M || \ - _pdesc->rxmcs == DESC92D_RATE5_5M || \ - _pdesc->rxmcs == DESC92D_RATE11M) + (_pdesc->rxmcs == DESC92_RATE1M || \ + _pdesc->rxmcs == DESC92_RATE2M || \ + _pdesc->rxmcs == DESC92_RATE5_5M || \ + _pdesc->rxmcs == DESC92_RATE11M) /* For 92D early mode */ #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ -- cgit v0.10.2 From 25232490af96f899f7e17de2c136e03d2c9ded62 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 22 Aug 2011 17:26:37 -0700 Subject: libertas: update readme file Since all wext specific code is removed, currently there is no way to configure deep sleep mode. This patch removes deep sleep configuration information in readme file. Signed-off-by: Amitkumar Karwar Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index 1453eec..91f2ca9 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -238,28 +238,3 @@ hostsleep echo "1" > hostsleep : enable host sleep. echo "0" > hostsleep : disable host sleep -======================== -IWCONFIG COMMANDS -======================== -power period - - This command is used to configure the station in deep sleep mode / - auto deep sleep mode. - - The timer is implemented to monitor the activities (command, event, - etc.). When an activity is detected station will exit from deep - sleep mode automatically and restart the timer. At timer expiry - (no activity for defined time period) the deep sleep mode is entered - automatically. - - Note: this command is for SDIO interface only. - - Usage: - To enable deep sleep mode do: - iwconfig wlan0 power period 0 - To enable auto deep sleep mode with idle time period 5 seconds do: - iwconfig wlan0 power period 5 - To disable deep sleep/auto deep sleep mode do: - iwconfig wlan0 power period -1 - -============================================================================== -- cgit v0.10.2 From c613366113c8956ee869e12558099927586785bb Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 25 Aug 2011 10:36:14 -0700 Subject: mac80211: mesh gate fixes Since a v1 of the mesh gate series was accidentally applied, this patch contains the changes in v2. These are: - automatically make mesh gate a root node. - use TU_TO_EXP_TIME macro. - initialize timer instead of checking for NULL timer function. - cleanups. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7d17a91..6ab67ab 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1138,6 +1138,14 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, ieee80211_mesh_root_setup(ifmsh); } if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) { + /* our current gate announcement implementation rides on root + * announcements, so require this ifmsh to also be a root node + * */ + if (nconf->dot11MeshGateAnnouncementProtocol && + !conf->dot11MeshHWMPRootMode) { + conf->dot11MeshHWMPRootMode = 1; + ieee80211_mesh_root_setup(ifmsh); + } conf->dot11MeshGateAnnouncementProtocol = nconf->dot11MeshGateAnnouncementProtocol; } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1c4f53c..28ab510 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -537,8 +537,8 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) mesh_path_tx_root_frame(sdata); mod_timer(&ifmsh->mesh_path_root_timer, - round_jiffies(jiffies + - usecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPRannInterval * 1024))); + round_jiffies(TU_TO_EXP_TIME( + ifmsh->mshcfg.dot11MeshHWMPRannInterval))); } #ifdef CONFIG_PM diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 75e4b60..3c2bcb2 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -288,7 +288,7 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, struct mesh_path *from_mpath, bool copy) { - struct sk_buff *skb, *cp_skb; + struct sk_buff *skb, *cp_skb = NULL; struct sk_buff_head gateq, failq; unsigned long flags; int num_skbs; @@ -711,6 +711,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); new_node->mpath = new_mpath; + init_timer(&new_mpath->timer); new_mpath->exp_time = jiffies; spin_lock_init(&new_mpath->state_lock); @@ -843,8 +844,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) struct mpath_node *node = container_of(rp, struct mpath_node, rcu); struct ieee80211_sub_if_data *sdata = node->mpath->sdata; - if (node->mpath->timer.function) - del_timer_sync(&node->mpath->timer); + del_timer_sync(&node->mpath->timer); atomic_dec(&sdata->u.mesh.mpaths); kfree(node->mpath); kfree(node); @@ -1046,8 +1046,7 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs) mpath = node->mpath; hlist_del_rcu(p); if (free_leafs) { - if (mpath->timer.function) - del_timer_sync(&mpath->timer); + del_timer_sync(&mpath->timer); kfree(mpath); } kfree(node); @@ -1094,7 +1093,6 @@ int mesh_pathtbl_init(void) tbl_mpp->free_node = &mesh_path_node_free; tbl_mpp->copy_node = &mesh_path_node_copy; tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; - /* XXX: not needed */ tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); INIT_HLIST_HEAD(tbl_mpp->known_gates); -- cgit v0.10.2 From df766267c8d8d71acb0b23575250cac718c6b711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 16 Aug 2011 12:14:07 +0200 Subject: b43: drop Kconfig option of forcing PIO mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have module param called use_pio which is much easier to use. Cc: Larry Finger Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index b81a2a1..df2b7c0 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -169,13 +169,3 @@ config B43_DEBUG Say N, if you are a distributor or user building a release kernel for production use. Only say Y, if you are debugging a problem in the b43 driver sourcecode. - -config B43_FORCE_PIO - bool "Force usage of PIO instead of DMA" - depends on B43 && B43_DEBUG - ---help--- - This will disable DMA and always enable PIO instead. - - Say N! - This is only for debugging the PIO engine code. You do - _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 8a52657..8ff7062 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -970,12 +970,6 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev) return dev->__using_pio_transfers; } -#ifdef CONFIG_B43_FORCE_PIO -# define B43_PIO_DEFAULT 1 -#else -# define B43_PIO_DEFAULT 0 -#endif - /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 0628901..d2b1d1f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -107,7 +107,7 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -static int b43_modparam_pio = B43_PIO_DEFAULT; +static int b43_modparam_pio = 0; module_param_named(pio, b43_modparam_pio, int, 0644); MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); -- cgit v0.10.2 From 8c71df7a2f6a5345d6cad34e810c50edeca81521 Mon Sep 17 00:00:00 2001 From: Guy Eilam Date: Wed, 17 Aug 2011 15:18:14 +0300 Subject: mac80211: refactor sta_info_insert_rcu to 3 main stages Divided the sta_info_insert_rcu function to 3 mini-functions: sta_info_insert_check - the initial checks done when inserting a new station sta_info_insert_ibss - the function that handles the station addition for IBSS interfaces sta_info_insert_non_ibss - the function that handles the station addition in other cases The outer API was not changed. The refactoring was done for better usage of the different stages in the station addition in new scenarios added in the next commit. Signed-off-by: Guy Eilam Signed-off-by: John W. Linville diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 5eaa167..d469d9d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -368,93 +368,90 @@ static void sta_info_finish_work(struct work_struct *work) mutex_unlock(&local->sta_mtx); } -int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +static int sta_info_insert_check(struct sta_info *sta) { - struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - unsigned long flags; - int err = 0; /* * Can't be a WARN_ON because it can be triggered through a race: * something inserts a STA (on one CPU) without holding the RTNL * and another CPU turns off the net device. */ - if (unlikely(!ieee80211_sdata_running(sdata))) { - err = -ENETDOWN; - rcu_read_lock(); - goto out_free; - } + if (unlikely(!ieee80211_sdata_running(sdata))) + return -ENETDOWN; if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || - is_multicast_ether_addr(sta->sta.addr))) { - err = -EINVAL; + is_multicast_ether_addr(sta->sta.addr))) + return -EINVAL; + + return 0; +} + +static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) +{ + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + unsigned long flags; + + spin_lock_irqsave(&local->sta_lock, flags); + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + spin_unlock_irqrestore(&local->sta_lock, flags); rcu_read_lock(); - goto out_free; + return -EEXIST; } - /* - * In ad-hoc mode, we sometimes need to insert stations - * from tasklet context from the RX path. To avoid races, - * always do so in that case -- see the comment below. - */ - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - spin_lock_irqsave(&local->sta_lock, flags); - /* check if STA exists already */ - if (sta_info_get_bss(sdata, sta->sta.addr)) { - spin_unlock_irqrestore(&local->sta_lock, flags); - rcu_read_lock(); - err = -EEXIST; - goto out_free; - } - - local->num_sta++; - local->sta_generation++; - smp_mb(); - sta_info_hash_add(local, sta); + local->num_sta++; + local->sta_generation++; + smp_mb(); + sta_info_hash_add(local, sta); - list_add_tail(&sta->list, &local->sta_pending_list); + list_add_tail(&sta->list, &local->sta_pending_list); - rcu_read_lock(); - spin_unlock_irqrestore(&local->sta_lock, flags); + rcu_read_lock(); + spin_unlock_irqrestore(&local->sta_lock, flags); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", - sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", + sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - ieee80211_queue_work(&local->hw, &local->sta_finish_work); + ieee80211_queue_work(&local->hw, &local->sta_finish_work); - return 0; - } + return 0; +} + +/* + * should be called with sta_mtx locked + * this function replaces the mutex lock + * with a RCU lock + */ +static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) +{ + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + unsigned long flags; + int err = 0; + + lockdep_assert_held(&local->sta_mtx); /* * On first glance, this will look racy, because the code - * below this point, which inserts a station with sleeping, + * in this function, which inserts a station with sleeping, * unlocks the sta_lock between checking existence in the * hash table and inserting into it. * * However, it is not racy against itself because it keeps - * the mutex locked. It still seems to race against the - * above code that atomically inserts the station... That, - * however, is not true because the above code can only - * be invoked for IBSS interfaces, and the below code will - * not be -- and the two do not race against each other as - * the hash table also keys off the interface. + * the mutex locked. */ - might_sleep(); - - mutex_lock(&local->sta_mtx); - spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ if (sta_info_get_bss(sdata, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); mutex_unlock(&local->sta_mtx); rcu_read_lock(); - err = -EEXIST; - goto out_free; + return -EEXIST; } spin_unlock_irqrestore(&local->sta_lock, flags); @@ -463,7 +460,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) if (err) { mutex_unlock(&local->sta_mtx); rcu_read_lock(); - goto out_free; + return err; } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -478,6 +475,51 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) mesh_accept_plinks_update(sdata); return 0; +} + +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +{ + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + int err = 0; + + err = sta_info_insert_check(sta); + if (err) { + rcu_read_lock(); + goto out_free; + } + + /* + * In ad-hoc mode, we sometimes need to insert stations + * from tasklet context from the RX path. To avoid races, + * always do so in that case -- see the comment below. + */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + err = sta_info_insert_ibss(sta); + if (err) + goto out_free; + + return 0; + } + + /* + * It might seem that the function called below is in race against + * the function call above that atomically inserts the station... That, + * however, is not true because the above code can only + * be invoked for IBSS interfaces, and the below code will + * not be -- and the two do not race against each other as + * the hash table also keys off the interface. + */ + + might_sleep(); + + mutex_lock(&local->sta_mtx); + + err = sta_info_insert_non_ibss(sta); + if (err) + goto out_free; + + return 0; out_free: BUG_ON(!err); __sta_info_free(local, sta); -- cgit v0.10.2 From 2a33bee2753bf28411de8822e3e3c7501966eb1b Mon Sep 17 00:00:00 2001 From: Guy Eilam Date: Wed, 17 Aug 2011 15:18:15 +0300 Subject: mac80211: fix race condition between assoc_done and first EAP packet When associating to an AP, the station might miss the first EAP packet that the AP sends due to a race condition between the association success procedure and the rx flow in mac80211. In such cases, the packet might fall in ieee80211_rx_h_check due to the fact that the relevant rx->sta wasn't allocated yet. Allocation of the relevant station info struct before actually sending the association request and setting it with a new dummy_sta flag solve this problem. The station will accept only EAP packets from the AP while it is in the pre-association/dummy state. This dummy station entry is not seen by normal sta_info_get() calls, only by sta_info_get_bss_rx(). The driver is not notified for the first insertion of the dummy station. The driver is notified only after the association is complete and the dummy flag is removed from the station entry. That way, all the rest of the code flow should be untouched by this change. Signed-off-by: Guy Eilam Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d6470c7..60a6f27 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1482,10 +1482,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, ifmgd->aid = aid; - sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); - if (!sta) { - printk(KERN_DEBUG "%s: failed to alloc STA entry for" - " the AP\n", sdata->name); + mutex_lock(&sdata->local->sta_mtx); + /* + * station info was already allocated and inserted before + * the association and should be available to us + */ + sta = sta_info_get_rx(sdata, cbss->bssid); + if (WARN_ON(!sta)) { + mutex_unlock(&sdata->local->sta_mtx); return false; } @@ -1556,7 +1560,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, if (elems.wmm_param) set_sta_flags(sta, WLAN_STA_WME); - err = sta_info_insert(sta); + /* sta_info_reinsert will also unlock the mutex lock */ + err = sta_info_reinsert(sta); sta = NULL; if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" @@ -2429,6 +2434,32 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, return 0; } +/* create and insert a dummy station entry */ +static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, + u8 *bssid) { + struct sta_info *sta; + int err; + + sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); + if (!sta) { + printk(KERN_DEBUG "%s: failed to alloc STA entry for" + " the AP\n", sdata->name); + return -ENOMEM; + } + + sta->dummy = true; + + err = sta_info_insert(sta); + sta = NULL; + if (err) { + printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" + " the AP (error %d)\n", sdata->name, err); + return err; + } + + return 0; +} + static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, struct sk_buff *skb) { @@ -2436,9 +2467,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt; struct ieee80211_rx_status *rx_status; struct ieee802_11_elems elems; + struct cfg80211_bss *cbss = wk->assoc.bss; u16 status; if (!skb) { + sta_info_destroy_addr(wk->sdata, cbss->bssid); cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); goto destroy; } @@ -2468,12 +2501,16 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { mutex_unlock(&wk->sdata->u.mgd.mtx); /* oops -- internal error -- send timeout for now */ + sta_info_destroy_addr(wk->sdata, cbss->bssid); cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); return WORK_DONE_DESTROY; } mutex_unlock(&wk->sdata->u.mgd.mtx); + } else { + /* assoc failed - destroy the dummy station entry */ + sta_info_destroy_addr(wk->sdata, cbss->bssid); } cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); @@ -2492,7 +2529,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_work *wk; const u8 *ssid; - int i; + int i, err; mutex_lock(&ifmgd->mtx); if (ifmgd->associated) { @@ -2517,6 +2554,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (!wk) return -ENOMEM; + /* + * create a dummy station info entry in order + * to start accepting incoming EAPOL packets from the station + */ + err = ieee80211_pre_assoc(sdata, req->bss->bssid); + if (err) { + kfree(wk); + return err; + } + ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c4453fd..edd4619 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -850,8 +850,21 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ieee80211_is_pspoll(hdr->frame_control)) && rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && rx->sdata->vif.type != NL80211_IFTYPE_WDS && - (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) + (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { + if (rx->sta && rx->sta->dummy && + ieee80211_is_data_present(hdr->frame_control)) { + u16 ethertype; + u8 *payload; + + payload = rx->skb->data + + ieee80211_hdrlen(hdr->frame_control); + ethertype = (payload[6] << 8) | payload[7]; + if (cpu_to_be16(ethertype) == + rx->sdata->control_port_protocol) + return RX_CONTINUE; + } return RX_DROP_MONITOR; + } return RX_CONTINUE; } @@ -2808,7 +2821,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_is_data(fc)) { prev_sta = NULL; - for_each_sta_info(local, hdr->addr2, sta, tmp) { + for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { if (!prev_sta) { prev_sta = sta; continue; @@ -2852,7 +2865,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, continue; } - rx.sta = sta_info_get_bss(prev, hdr->addr2); + rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); rx.sdata = prev; ieee80211_prepare_and_rx_handle(&rx, skb, false); @@ -2860,7 +2873,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, } if (prev) { - rx.sta = sta_info_get_bss(prev, hdr->addr2); + rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); rx.sdata = prev; if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d469d9d..17caba2 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -100,6 +100,27 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, lockdep_is_held(&local->sta_lock) || lockdep_is_held(&local->sta_mtx)); while (sta) { + if (sta->sdata == sdata && !sta->dummy && + memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) + break; + sta = rcu_dereference_check(sta->hnext, + lockdep_is_held(&local->sta_lock) || + lockdep_is_held(&local->sta_mtx)); + } + return sta; +} + +/* get a station info entry even if it is a dummy station*/ +struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, + const u8 *addr) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + + sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], + lockdep_is_held(&local->sta_lock) || + lockdep_is_held(&local->sta_mtx)); + while (sta) { if (sta->sdata == sdata && memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) break; @@ -126,6 +147,32 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, while (sta) { if ((sta->sdata == sdata || (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && + !sta->dummy && + memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) + break; + sta = rcu_dereference_check(sta->hnext, + lockdep_is_held(&local->sta_lock) || + lockdep_is_held(&local->sta_mtx)); + } + return sta; +} + +/* + * Get sta info either from the specified interface + * or from one of its vlans (including dummy stations) + */ +struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, + const u8 *addr) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + + sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], + lockdep_is_held(&local->sta_lock) || + lockdep_is_held(&local->sta_mtx)); + while (sta) { + if ((sta->sdata == sdata || + (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) break; sta = rcu_dereference_check(sta->hnext, @@ -280,7 +327,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return sta; } -static int sta_info_finish_insert(struct sta_info *sta, bool async) +static int sta_info_finish_insert(struct sta_info *sta, + bool async, bool dummy_reinsert) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -290,51 +338,58 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) lockdep_assert_held(&local->sta_mtx); - /* notify driver */ - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - err = drv_sta_add(local, sdata, &sta->sta); - if (err) { - if (!async) - return err; - printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" - " - keeping it anyway.\n", - sdata->name, sta->sta.addr, err); - } else { - sta->uploaded = true; + if (!sta->dummy || dummy_reinsert) { + /* notify driver */ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + err = drv_sta_add(local, sdata, &sta->sta); + if (err) { + if (!async) + return err; + printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " + "driver (%d) - keeping it anyway.\n", + sdata->name, sta->sta.addr, err); + } else { + sta->uploaded = true; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - if (async) - wiphy_debug(local->hw.wiphy, - "Finished adding IBSS STA %pM\n", - sta->sta.addr); + if (async) + wiphy_debug(local->hw.wiphy, + "Finished adding IBSS STA %pM\n", + sta->sta.addr); #endif + } + + sdata = sta->sdata; } - sdata = sta->sdata; + if (!dummy_reinsert) { + if (!async) { + local->num_sta++; + local->sta_generation++; + smp_mb(); - if (!async) { - local->num_sta++; - local->sta_generation++; - smp_mb(); + /* make the station visible */ + spin_lock_irqsave(&local->sta_lock, flags); + sta_info_hash_add(local, sta); + spin_unlock_irqrestore(&local->sta_lock, flags); + } - /* make the station visible */ - spin_lock_irqsave(&local->sta_lock, flags); - sta_info_hash_add(local, sta); - spin_unlock_irqrestore(&local->sta_lock, flags); + list_add(&sta->list, &local->sta_list); + } else { + sta->dummy = false; } - list_add(&sta->list, &local->sta_list); - - ieee80211_sta_debugfs_add(sta); - rate_control_add_sta_debugfs(sta); - - memset(&sinfo, 0, sizeof(sinfo)); - sinfo.filled = 0; - sinfo.generation = local->sta_generation; - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); + if (!sta->dummy) { + ieee80211_sta_debugfs_add(sta); + rate_control_add_sta_debugfs(sta); + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.filled = 0; + sinfo.generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); + } return 0; } @@ -351,7 +406,7 @@ static void sta_info_finish_pending(struct ieee80211_local *local) list_del(&sta->list); spin_unlock_irqrestore(&local->sta_lock, flags); - sta_info_finish_insert(sta, true); + sta_info_finish_insert(sta, true, false); spin_lock_irqsave(&local->sta_lock, flags); } @@ -395,7 +450,7 @@ static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (sta_info_get_bss(sdata, sta->sta.addr)) { + if (sta_info_get_bss_rx(sdata, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); rcu_read_lock(); return -EEXIST; @@ -431,6 +486,8 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; unsigned long flags; + struct sta_info *exist_sta; + bool dummy_reinsert = false; int err = 0; lockdep_assert_held(&local->sta_mtx); @@ -446,17 +503,28 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) */ spin_lock_irqsave(&local->sta_lock, flags); - /* check if STA exists already */ - if (sta_info_get_bss(sdata, sta->sta.addr)) { - spin_unlock_irqrestore(&local->sta_lock, flags); - mutex_unlock(&local->sta_mtx); - rcu_read_lock(); - return -EEXIST; + /* + * check if STA exists already. + * only accept a scenario of a second call to sta_info_insert_non_ibss + * with a dummy station entry that was inserted earlier + * in that case - assume that the dummy station flag should + * be removed. + */ + exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); + if (exist_sta) { + if (exist_sta == sta && sta->dummy) { + dummy_reinsert = true; + } else { + spin_unlock_irqrestore(&local->sta_lock, flags); + mutex_unlock(&local->sta_mtx); + rcu_read_lock(); + return -EEXIST; + } } spin_unlock_irqrestore(&local->sta_lock, flags); - err = sta_info_finish_insert(sta, false); + err = sta_info_finish_insert(sta, false, dummy_reinsert); if (err) { mutex_unlock(&local->sta_mtx); rcu_read_lock(); @@ -464,7 +532,8 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", + sta->dummy ? "dummy " : "", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ /* move reference to rcu-protected */ @@ -535,6 +604,25 @@ int sta_info_insert(struct sta_info *sta) return err; } +/* Caller must hold sta->local->sta_mtx */ +int sta_info_reinsert(struct sta_info *sta) +{ + struct ieee80211_local *local = sta->local; + int err = 0; + + err = sta_info_insert_check(sta); + if (err) { + mutex_unlock(&local->sta_mtx); + return err; + } + + might_sleep(); + + err = sta_info_insert_non_ibss(sta); + rcu_read_unlock(); + return err; +} + static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) { /* @@ -775,7 +863,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) int ret; mutex_lock(&sdata->local->sta_mtx); - sta = sta_info_get(sdata, addr); + sta = sta_info_get_rx(sdata, addr); ret = __sta_info_destroy(sta); mutex_unlock(&sdata->local->sta_mtx); @@ -789,7 +877,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, int ret; mutex_lock(&sdata->local->sta_mtx); - sta = sta_info_get_bss(sdata, addr); + sta = sta_info_get_bss_rx(sdata, addr); ret = __sta_info_destroy(sta); mutex_unlock(&sdata->local->sta_mtx); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 28beb78..e9eb565 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -238,10 +238,12 @@ struct sta_ampdu_mlme { * @plink_timer: peer link watch timer * @plink_timer_was_running: used by suspend/resume to restore timers * @debugfs: debug filesystem info - * @sta: station information we share with the driver * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver * @lost_packets: number of consecutive lost packets + * @dummy: indicate a dummy station created for receiving + * EAP frames before association + * @sta: station information we share with the driver */ struct sta_info { /* General information, mostly static */ @@ -336,6 +338,9 @@ struct sta_info { unsigned int lost_packets; + /* should be right in front of sta to be in the same cache line */ + bool dummy; + /* keep last! */ struct ieee80211_sta sta; }; @@ -436,9 +441,15 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); +struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, + const u8 *addr); + struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, const u8 *addr); +struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, + const u8 *addr); + static inline void for_each_sta_info_type_check(struct ieee80211_local *local, const u8 *addr, @@ -459,6 +470,22 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, _sta = nxt, \ nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ ) \ + /* run code only if address matches and it's not a dummy sta */ \ + if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \ + !_sta->dummy) + +#define for_each_sta_info_rx(local, _addr, _sta, nxt) \ + for ( /* initialise loop */ \ + _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ + nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ + /* typecheck */ \ + for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ + /* continue condition */ \ + _sta; \ + /* advance loop */ \ + _sta = nxt, \ + nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ + ) \ /* compare address and run code only if it matches */ \ if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) @@ -484,6 +511,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, int sta_info_insert(struct sta_info *sta); int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); int sta_info_insert_atomic(struct sta_info *sta); +int sta_info_reinsert(struct sta_info *sta); int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr); -- cgit v0.10.2 From 1a6e9d0f2e5de4cc8dfa3e8e67c2decd02976cf3 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 23 Aug 2011 12:32:57 +0530 Subject: ath9k: Send legacy rated frames as unaggregated Currently the aggregation is formed till the aggregation limit is reached and the rate lookup is done for the first frame alone. But there can be a legacy rated frames in tid queue. This patch limits the subframe addition based on presence of legacy rate and sends the legacy rated frames as unaggregated one. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2062672..5e29829 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -571,6 +571,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_reset(sc, false); } +static bool ath_lookup_legacy(struct ath_buf *bf) +{ + struct sk_buff *skb; + struct ieee80211_tx_info *tx_info; + struct ieee80211_tx_rate *rates; + int i; + + skb = bf->bf_mpdu; + tx_info = IEEE80211_SKB_CB(skb); + rates = tx_info->control.rates; + + for (i = 3; i >= 0; i--) { + if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) + return true; + } + + return false; +} + static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, struct ath_atx_tid *tid) { @@ -750,7 +769,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; if (nframes && - (aggr_limit < (al + bpad + al_delta + prev_al))) { + ((aggr_limit < (al + bpad + al_delta + prev_al)) || + ath_lookup_legacy(bf))) { status = ATH_AGGR_LIMITED; break; } -- cgit v0.10.2 From a21fa87e3a3a8390f17f53967baa574f4e1e1e76 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 23 Aug 2011 10:21:27 +0300 Subject: mac80211: allow action frames with unknown BSSID in GO mode When operating as a P2P GO, we receive some P2P action frames where the BSSID is set to the peer MAC address. Specifically, this occurs for invitation responses. These are valid action frames and they should be passed up. Signed-off-by: Arik Nemtsov Signed-off-by: John W. Linville diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index edd4619..f45fd2f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2716,7 +2716,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && - !ieee80211_is_beacon(hdr->frame_control)) + !ieee80211_is_beacon(hdr->frame_control) && + !(ieee80211_is_action(hdr->frame_control) && + sdata->vif.p2p)) return 0; status->rx_flags &= ~IEEE80211_RX_RA_MATCH; } -- cgit v0.10.2 From c75786c9ef9e726dc139325a775e90a684b00ed7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 23 Aug 2011 14:37:46 +0300 Subject: nl80211/cfg80211: add STA WME parameters Add new NL80211_ATTR_STA_WME nested attribute that contains wme params needed by the low-level driver (uapsd_queues and max_sp). Add these params to the station_parameters struct as well. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 3769303..0343504 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1042,6 +1042,9 @@ enum nl80211_commands { * (Re)Association Response frames when the driver (or firmware) replies to * (Re)Association Request frames. * + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + * of the station, see &enum nl80211_sta_wme_attr. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1252,6 +1255,8 @@ enum nl80211_attrs { NL80211_ATTR_IE_PROBE_RESP, NL80211_ATTR_IE_ASSOC_RESP, + NL80211_ATTR_STA_WME, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2482,4 +2487,22 @@ enum nl80211_hidden_ssid { NL80211_HIDDEN_SSID_ZERO_CONTENTS }; +/** + * enum nl80211_sta_wme_attr - station WME attributes + * @__NL80211_STA_WME_INVALID: invalid number for nested attribute + * @NL80211_STA_WME_QUEUES: bitmap of uapsd queues. + * @NL80211_STA_WME_MAX_SP: max service period. + * @__NL80211_STA_WME_AFTER_LAST: internal + * @NL80211_STA_WME_MAX: highest station WME attribute + */ +enum nl80211_sta_wme_attr { + __NL80211_STA_WME_INVALID, + NL80211_STA_WME_UAPSD_QUEUES, + NL80211_STA_WME_MAX_SP, + + /* keep last */ + __NL80211_STA_WME_AFTER_LAST, + NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 77aa777..88112ca 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -452,6 +452,8 @@ struct station_parameters { u8 plink_action; u8 plink_state; struct ieee80211_ht_cap *ht_capa; + u8 uapsd_queues; + u8 max_sp; }; /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 57ecfa4..bddb559 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2545,6 +2545,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return err; } +static struct nla_policy +nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { + [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, + [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, +}; + static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2590,6 +2596,27 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (parse_station_flags(info, ¶ms)) return -EINVAL; + /* parse WME attributes if sta is WME capable */ + if ((params.sta_flags_set & NL80211_STA_FLAG_WME) && + info->attrs[NL80211_ATTR_STA_WME]) { + struct nlattr *tb[NL80211_STA_WME_MAX + 1]; + struct nlattr *nla; + + nla = info->attrs[NL80211_ATTR_STA_WME]; + err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, + nl80211_sta_wme_policy); + if (err) + return err; + + if (tb[NL80211_STA_WME_UAPSD_QUEUES]) + params.uapsd_queues = + nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); + + if (tb[NL80211_STA_WME_MAX_SP]) + params.max_sp = + nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); + } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && -- cgit v0.10.2 From 9533b4ac86e20656d95f25e536c81c994e5f57a6 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 23 Aug 2011 14:37:47 +0300 Subject: mac80211: add uapsd_queues and max_sp params fields Add uapsd_queues and max_sp fields to ieee80211_sta. These fields might be needed by low-level drivers in order to configure the AP. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2f01d84..2e752df 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -954,6 +954,8 @@ struct ieee80211_sta { u16 aid; struct ieee80211_sta_ht_cap ht_cap; bool wme; + u8 uapsd_queues; + u8 max_sp; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6ab67ab..0baaaec 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -697,6 +697,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, } spin_unlock_irqrestore(&sta->flaglock, flags); + sta->sta.uapsd_queues = params->uapsd_queues; + sta->sta.max_sp = params->max_sp; + /* * cfg80211 validates this (1-2007) and allows setting the AID * only when creating a new station entry -- cgit v0.10.2 From dde88b736f228be8bb2a831a4c373910d0b950fa Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Aug 2011 15:03:34 -0700 Subject: wireless: relicense regulatory header to ISC I will suck out stuff to userspace to start the regulatory revampamp, this work will be permissively licensed. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/include/net/regulatory.h b/include/net/regulatory.h index 356d6e3..eb7d3c2 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -3,11 +3,19 @@ /* * regulatory support structures * - * Copyright 2008-2009 Luis R. Rodriguez + * Copyright 2008-2009 Luis R. Rodriguez * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -- cgit v0.10.2 From fe8e084455f273b32cc57a5fbaf6c22ef984d657 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Aug 2011 15:07:31 -0700 Subject: MAINTANERS: update Qualcomm Atheros addresses Qualcomm ate up Atheros, all of the old e-mail addresses no longer work and e-mails sent to it will bounce. Update the addresses to the new shiny Qualcomm Atheros (QCA) ones. Cc: stable@kernel.org Cc: netdev@vger.kernel.org Cc: jouni@qca.qualcomm.com Cc: yangjie@qca.qualcomm.com Cc: vthiagar@qca.qualcomm.com Cc: senthilb@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 4771368..c66c093 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1230,7 +1230,7 @@ F: Documentation/aoe/ F: drivers/block/aoe/ ATHEROS ATH GENERIC UTILITIES -M: "Luis R. Rodriguez" +M: "Luis R. Rodriguez" L: linux-wireless@vger.kernel.org S: Supported F: drivers/net/wireless/ath/* @@ -1238,7 +1238,7 @@ F: drivers/net/wireless/ath/* ATHEROS ATH5K WIRELESS DRIVER M: Jiri Slaby M: Nick Kossifidis -M: "Luis R. Rodriguez" +M: "Luis R. Rodriguez" M: Bob Copeland L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org @@ -1247,10 +1247,10 @@ S: Maintained F: drivers/net/wireless/ath/ath5k/ ATHEROS ATH9K WIRELESS DRIVER -M: "Luis R. Rodriguez" -M: Jouni Malinen -M: Vasanthakumar Thiagarajan -M: Senthil Balasubramanian +M: "Luis R. Rodriguez" +M: Jouni Malinen +M: Vasanthakumar Thiagarajan +M: Senthil Balasubramanian L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org W: http://wireless.kernel.org/en/users/Drivers/ath9k @@ -1278,7 +1278,7 @@ F: drivers/input/misc/ati_remote2.c ATLX ETHERNET DRIVERS M: Jay Cliburn M: Chris Snook -M: Jie Yang +M: Jie Yang L: netdev@vger.kernel.org W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net -- cgit v0.10.2 From c750f795c721805f69254cf4dd91f67b28ff6ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 24 Aug 2011 11:52:34 +0200 Subject: b43: HT-PHY: use separated function for forcing RF sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comparison of the HT and N code has shown similarities in the ops performed after b43_mac_phy_clock_set. That way we understood what is happening in the HT-PHY code. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 62a9084..c0e436c 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -191,6 +191,27 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) } } +static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) +{ + u8 i; + + u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); + b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); + + b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); + for (i = 0; i < 200; i++) { + if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { + i = 0; + break; + } + msleep(1); + } + if (i) + b43err(dev->wl, "Forcing RF sequence timeout\n"); + + b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); +} + static void b43_phy_ht_bphy_init(struct b43_wldev *dev) { unsigned int i; @@ -313,7 +334,6 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) static int b43_phy_ht_op_init(struct b43_wldev *dev) { - u8 i; u16 tmp; b43_phy_ht_tables_init(dev); @@ -418,14 +438,8 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_mac_phy_clock_set(dev, true); - for (i = 0; i < 2; i++) { - tmp = b43_phy_read(dev, B43_PHY_EXTG(0)); - b43_phy_set(dev, B43_PHY_EXTG(0), 0x3); - b43_phy_set(dev, B43_PHY_EXTG(3), i ? 0x20 : 0x1); - /* FIXME: wait for some bit to be cleared (find out which) */ - b43_phy_read(dev, B43_PHY_EXTG(4)); - b43_phy_write(dev, B43_PHY_EXTG(0), tmp); - } + b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); + b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); /* TODO: PHY op on reg 0xb0 */ diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h index f70af0c..0661ae2 100644 --- a/drivers/net/wireless/b43/phy_ht.h +++ b/drivers/net/wireless/b43/phy_ht.h @@ -19,6 +19,17 @@ #define B43_PHY_HT_BW5 0x1D2 #define B43_PHY_HT_BW6 0x1D3 +#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) +#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) +#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ +#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ +#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */ +#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */ +#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */ +#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */ +#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004) +/* Values for the status are the same as for the trigger */ + #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) #define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110) -- cgit v0.10.2 From ea5a08cfa5fe9d10333eb7d65a7158ab766dae93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 24 Aug 2011 11:52:35 +0200 Subject: b43: HT-PHY: read clip state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't know yet when to restore it, implement just reading. We found out what for are that PHY ops by comparing HT with N code. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index c0e436c..4d6345e 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -212,6 +212,13 @@ static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); } +static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) +{ + clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); + clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES); + clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES); +} + static void b43_phy_ht_bphy_init(struct b43_wldev *dev) { unsigned int i; @@ -335,6 +342,7 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) static int b43_phy_ht_op_init(struct b43_wldev *dev) { u16 tmp; + u16 clip_state[3]; b43_phy_ht_tables_init(dev); @@ -443,7 +451,8 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) /* TODO: PHY op on reg 0xb0 */ - /* TODO: PHY ops on regs 0x40e, 0x44e, 0x48e */ + /* TODO: Should we restore it? Or store it in global PHY info? */ + b43_phy_ht_read_clip_detection(dev, clip_state); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) b43_phy_ht_bphy_init(dev); diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h index 0661ae2..6544c42 100644 --- a/drivers/net/wireless/b43/phy_ht.h +++ b/drivers/net/wireless/b43/phy_ht.h @@ -19,6 +19,10 @@ #define B43_PHY_HT_BW5 0x1D2 #define B43_PHY_HT_BW6 0x1D3 +#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) +#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) +#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) + #define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) #define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) #define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ -- cgit v0.10.2 From 22c55e6e7ed46ad3734c206d90b5ccba3b318d22 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 24 Aug 2011 14:08:41 -0400 Subject: ath9k: remove replicated null check in ath_pci_aspm_init Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index d704c8d..91c2e64 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -115,6 +115,8 @@ static void ath_pci_aspm_init(struct ath_common *common) return; parent = pdev->bus->self; + if (!parent) + return; if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) { /* Bluetooth coexistance requires disabling ASPM. */ @@ -126,9 +128,6 @@ static void ath_pci_aspm_init(struct ath_common *common) * Both upstream and downstream PCIe components should * have the same ASPM settings. */ - if (!parent) - return; - pos = pci_pcie_cap(parent); pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); @@ -137,9 +136,6 @@ static void ath_pci_aspm_init(struct ath_common *common) return; } - if (!parent) - return; - pos = pci_pcie_cap(parent); pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { -- cgit v0.10.2 From c3e5fac8e54591d2e4585d3329ead61ba059eb1d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 24 Aug 2011 15:05:14 -0400 Subject: b43: correct warning for uninitialized variable 'macstat' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/b43/pio.o drivers/net/wireless/b43/pio.c: In function ‘pio_rx_frame’: drivers/net/wireless/b43/pio.c:614:6: warning: ‘macstat’ may be used uninitialized in this function Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index ce8a4bd..fcff923 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -611,7 +611,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) struct b43_wldev *dev = q->dev; struct b43_wl *wl = dev->wl; u16 len; - u32 macstat; + u32 macstat = 0; unsigned int i, padding; struct sk_buff *skb; const char *err_msg = NULL; -- cgit v0.10.2 From 5fa71984f37e882d8c93e20f6db56d2ac3470178 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 25 Aug 2011 01:01:22 +0530 Subject: ath9k_htc: Add get_stats call back currently this call back is used only in debugfs of mac80211 Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7212acb..0248024 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1736,6 +1736,22 @@ out: return ret; } + +static int ath9k_htc_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_hw *ah = priv->ah; + struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; + + stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; + stats->dot11RTSFailureCount = mib_stats->rts_bad; + stats->dot11FCSErrorCount = mib_stats->fcs_bad; + stats->dot11RTSSuccessCount = mib_stats->rts_good; + + return 0; +} + struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, .start = ath9k_htc_start, @@ -1759,4 +1775,5 @@ struct ieee80211_ops ath9k_htc_ops = { .rfkill_poll = ath9k_htc_rfkill_poll_state, .set_coverage_class = ath9k_htc_set_coverage_class, .set_bitrate_mask = ath9k_htc_set_bitrate_mask, + .get_stats = ath9k_htc_get_stats, }; -- cgit v0.10.2 From 5a63ef0faf90985c847a2f924a72a22830ed1c10 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 24 Aug 2011 15:36:08 -0700 Subject: ath9k_hw: add AR9580 support Here are the AR9580 1.0 initvals checksums using the Atheros initvals-tools [1]. This is useful for when we udate the initvals again with other values. It ensures that we match the same initvals used internally. The tool is documented on the wiki [2]. $ ./initvals -f ar9580-1p0 0x00000000e912711f ar9580_1p0_modes_fast_clock 0x000000004a488fc7 ar9580_1p0_radio_postamble 0x00000000f3888b02 ar9580_1p0_baseband_core 0x0000000003f783bb ar9580_1p0_mac_postamble 0x0000000094be244a ar9580_1p0_low_ob_db_tx_gain_table 0x0000000094be244a ar9580_1p0_high_power_tx_gain_table 0x0000000090be244a ar9580_1p0_lowest_ob_db_tx_gain_table 0x00000000ed9eaac6 ar9580_1p0_baseband_core_txfir_coeff_japan_2484 0x00000000c4d66d1b ar9580_1p0_mac_core 0x00000000e8e9043a ar9580_1p0_mixed_ob_db_tx_gain_table 0x000000003521a300 ar9580_1p0_wo_xlna_rx_gain_table 0x00000000301fc841 ar9580_1p0_soc_postamble 0x00000000a9a06b3a ar9580_1p0_high_ob_db_tx_gain_table 0x00000000a15ccf1b ar9580_1p0_soc_preamble 0x0000000029495000 ar9580_1p0_rx_gain_table 0x0000000037ac0ee8 ar9580_1p0_radio_core 0x00000000603a1b80 ar9580_1p0_baseband_postamble 0x000000003d8b4396 ar9580_1p0_pcie_phy_clkreq_enable_L1 0x00000000398b4396 ar9580_1p0_pcie_phy_clkreq_disable_L1 0x00000000397b4396 ar9580_1p0_pcie_phy_pll_on_clkreq [1] git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/initvals-tool.git [2] http://wireless.kernel.org/en/users/Drivers/ath9k_hw/initvals-tool Cc: David Quan Cc: Kathy Giori Cc: Senthil Balasubramanian Tested-by: Florian Fainelli Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 9cf5d13..b6839e6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -21,6 +21,7 @@ #include "ar9340_initvals.h" #include "ar9330_1p1_initvals.h" #include "ar9330_1p2_initvals.h" +#include "ar9580_1p0_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -253,6 +254,56 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9485_1_1_pcie_phy_clkreq_disable_L1, ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), 2); + } else if (AR_SREV_9580(ah)) { + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9580_1p0_mac_core, + ARRAY_SIZE(ar9580_1p0_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9580_1p0_mac_postamble, + ARRAY_SIZE(ar9580_1p0_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9580_1p0_baseband_core, + ARRAY_SIZE(ar9580_1p0_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9580_1p0_baseband_postamble, + ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9580_1p0_radio_core, + ARRAY_SIZE(ar9580_1p0_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9580_1p0_radio_postamble, + ARRAY_SIZE(ar9580_1p0_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9580_1p0_soc_preamble, + ARRAY_SIZE(ar9580_1p0_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9580_1p0_soc_postamble, + ARRAY_SIZE(ar9580_1p0_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9580_1p0_rx_gain_table, + ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9580_1p0_low_ob_db_tx_gain_table, + ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), + 5); + + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9580_1p0_modes_fast_clock, + ARRAY_SIZE(ar9580_1p0_modes_fast_clock), + 3); } else { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -348,6 +399,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 5); + else if (AR_SREV_9580(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9580_1p0_lowest_ob_db_tx_gain_table, + ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_lowest_ob_db_tx_gain_table_2p2, @@ -375,6 +431,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_high_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), 5); + else if (AR_SREV_9580(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9580_1p0_high_ob_db_tx_gain_table, + ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_ob_db_tx_gain_table_2p2, @@ -402,6 +463,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_low_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), 5); + else if (AR_SREV_9580(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9580_1p0_low_ob_db_tx_gain_table, + ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_low_ob_db_tx_gain_table_2p2, @@ -429,6 +495,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_high_power_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), 5); + else if (AR_SREV_9580(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9580_1p0_high_power_tx_gain_table, + ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_power_tx_gain_table_2p2, @@ -463,6 +534,11 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); + else if (AR_SREV_9580(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9580_1p0_rx_gain_table, + ARRAY_SIZE(ar9580_1p0_rx_gain_table), + 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p2, @@ -490,6 +566,11 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); + else if (AR_SREV_9580(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9580_1p0_wo_xlna_rx_gain_table, + ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table), + 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_wo_xlna_rx_gain_table_2p2, diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h new file mode 100644 index 0000000..06b3f0d --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -0,0 +1,1673 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9580_1P0_H +#define INITVALS_9580_1P0_H + +/* AR9580 1.0 */ + +static const u32 ar9580_1p0_modes_fast_clock[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00001030, 0x00000268, 0x000004d0}, + {0x00001070, 0x0000018c, 0x00000318}, + {0x000010b0, 0x00000fd0, 0x00001fa0}, + {0x00008014, 0x044c044c, 0x08980898}, + {0x0000801c, 0x148ec02b, 0x148ec057}, + {0x00008318, 0x000044c0, 0x00008980}, + {0x00009e00, 0x0372131c, 0x0372131c}, + {0x0000a230, 0x0000000b, 0x00000016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9580_1p0_radio_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, + {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, + {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, + {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, + {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, + {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +}; + +static const u32 ar9580_1p0_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a9f6b}, + {0x0000980c, 0x04900000}, + {0x00009814, 0x3280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x6400a290}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x0d000600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x32840bbe}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0xff55ff55}, + {0x00009c08, 0x0320ff55}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x9883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c0040b}, + {0x00009d18, 0x00000000}, + {0x00009e08, 0x0038230c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0c6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009e54, 0x00000000}, + {0x00009fc0, 0x803e4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x00009fd0, 0x01193b93}, + {0x0000a20c, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000000}, + {0x0000a3f8, 0x0c9bd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d001dce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00100000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x05000080}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a640, 0x00000000}, + {0x0000a644, 0x3fad9d74}, + {0x0000a648, 0x0048060a}, + {0x0000a64c, 0x00003c37}, + {0x0000a670, 0x03020100}, + {0x0000a674, 0x09080504}, + {0x0000a678, 0x0d0c0b0a}, + {0x0000a67c, 0x13121110}, + {0x0000a680, 0x31301514}, + {0x0000a684, 0x35343332}, + {0x0000a688, 0x00000036}, + {0x0000a690, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000000}, + {0x0000a8d0, 0x004b6a8e}, + {0x0000a8d4, 0x00000820}, + {0x0000a8dc, 0x00000000}, + {0x0000a8f0, 0x00000000}, + {0x0000a8f4, 0x00000000}, + {0x0000b2d0, 0x00000080}, + {0x0000b2d4, 0x00000000}, + {0x0000b2ec, 0x00000000}, + {0x0000b2f0, 0x00000000}, + {0x0000b2f4, 0x00000000}, + {0x0000b2f8, 0x00000000}, + {0x0000b408, 0x0e79e5c0}, + {0x0000b40c, 0x00820820}, + {0x0000b420, 0x00000000}, + {0x0000b8d0, 0x004b6a8e}, + {0x0000b8d4, 0x00000820}, + {0x0000b8dc, 0x00000000}, + {0x0000b8f0, 0x00000000}, + {0x0000b8f4, 0x00000000}, + {0x0000c2d0, 0x00000080}, + {0x0000c2d4, 0x00000000}, + {0x0000c2ec, 0x00000000}, + {0x0000c2f0, 0x00000000}, + {0x0000c2f4, 0x00000000}, + {0x0000c2f8, 0x00000000}, + {0x0000c408, 0x0e79e5c0}, + {0x0000c40c, 0x00820820}, + {0x0000c420, 0x00000000}, +}; + +static const u32 ar9580_1p0_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { + /* Addr allmodes */ + {0x0000a398, 0x00000000}, + {0x0000a39c, 0x6f7f0301}, + {0x0000a3a0, 0xca9228ee}, +}; + +static const u32 ar9580_1p0_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x00020085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c22}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00a00000}, + {0x000080d8, 0x00400000}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x33332210}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f400}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e800}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x9bc00010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xaa48105b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; + +static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, + {0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, + {0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, + {0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_wo_xlna_rx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9580_1p0_soc_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, +}; + +static const u32 ar9580_1p0_high_ob_db_tx_gain_table[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, + {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_soc_preamble[][2] = { + /* Addr allmodes */ + {0x000040a4, 0x00a0c1c9}, + {0x00007008, 0x00000000}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, + {0x00007048, 0x00000008}, +}; + +static const u32 ar9580_1p0_rx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x01910190}, + {0x0000a030, 0x01930192}, + {0x0000a034, 0x01950194}, + {0x0000a038, 0x038a0196}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x22222229}, + {0x0000a084, 0x1d1d1d1d}, + {0x0000a088, 0x1d1d1d1d}, + {0x0000a08c, 0x1d1d1d1d}, + {0x0000a090, 0x171d1d1d}, + {0x0000a094, 0x11111717}, + {0x0000a098, 0x00030311}, + {0x0000a09c, 0x00000000}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x2a2d2f32}, + {0x0000b084, 0x21232328}, + {0x0000b088, 0x19191c1e}, + {0x0000b08c, 0x12141417}, + {0x0000b090, 0x07070e0e}, + {0x0000b094, 0x03030305}, + {0x0000b098, 0x00000003}, + {0x0000b09c, 0x00000000}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9580_1p0_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73f00000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x0001604c, 0x76d005b5}, + {0x00016050, 0x556cf031}, + {0x00016054, 0x13449440}, + {0x00016058, 0x0c51c92c}, + {0x0001605c, 0x3db7fffc}, + {0x00016060, 0xfffffffc}, + {0x00016064, 0x000f0278}, + {0x0001606c, 0x6db60000}, + {0x00016080, 0x00000000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x54214514}, + {0x0001608c, 0x119f481e}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd2888888}, + {0x000160a0, 0x0a108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92480080}, + {0x000160c0, 0x00adb6d0}, + {0x000160c4, 0x6db6db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x01e6c000}, + {0x00016100, 0x3fffbe01}, + {0x00016104, 0xfff80000}, + {0x00016108, 0x00080010}, + {0x00016144, 0x02084080}, + {0x00016148, 0x00000000}, + {0x00016280, 0x058a0001}, + {0x00016284, 0x3d840208}, + {0x00016288, 0x05a20408}, + {0x0001628c, 0x00038c07}, + {0x00016290, 0x00000004}, + {0x00016294, 0x458aa14f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016400, 0x36db6db6}, + {0x00016404, 0x6db6db40}, + {0x00016408, 0x73f00000}, + {0x0001640c, 0x00000000}, + {0x00016440, 0x7f80fff8}, + {0x0001644c, 0x76d005b5}, + {0x00016450, 0x556cf031}, + {0x00016454, 0x13449440}, + {0x00016458, 0x0c51c92c}, + {0x0001645c, 0x3db7fffc}, + {0x00016460, 0xfffffffc}, + {0x00016464, 0x000f0278}, + {0x0001646c, 0x6db60000}, + {0x00016500, 0x3fffbe01}, + {0x00016504, 0xfff80000}, + {0x00016508, 0x00080010}, + {0x00016544, 0x02084080}, + {0x00016548, 0x00000000}, + {0x00016780, 0x00000000}, + {0x00016784, 0x00000000}, + {0x00016788, 0x00800700}, + {0x0001678c, 0x00800700}, + {0x00016790, 0x00800700}, + {0x00016794, 0x00000000}, + {0x00016798, 0x00000000}, + {0x0001679c, 0x00000000}, + {0x000167a0, 0x00000001}, + {0x000167a4, 0x00000001}, + {0x000167a8, 0x00000000}, + {0x000167ac, 0x00000000}, + {0x000167b0, 0x00000000}, + {0x000167b4, 0x00000000}, + {0x000167b8, 0x00000000}, + {0x000167bc, 0x00000000}, + {0x000167c0, 0x000000a0}, + {0x000167c4, 0x000c0000}, + {0x000167c8, 0x14021402}, + {0x000167cc, 0x00001402}, + {0x000167d0, 0x00000000}, + {0x000167d4, 0x00000000}, + {0x00016800, 0x36db6db6}, + {0x00016804, 0x6db6db40}, + {0x00016808, 0x73f00000}, + {0x0001680c, 0x00000000}, + {0x00016840, 0x7f80fff8}, + {0x0001684c, 0x76d005b5}, + {0x00016850, 0x556cf031}, + {0x00016854, 0x13449440}, + {0x00016858, 0x0c51c92c}, + {0x0001685c, 0x3db7fffc}, + {0x00016860, 0xfffffffc}, + {0x00016864, 0x000f0278}, + {0x0001686c, 0x6db60000}, + {0x00016900, 0x3fffbe01}, + {0x00016904, 0xfff80000}, + {0x00016908, 0x00080010}, + {0x00016944, 0x02084080}, + {0x00016948, 0x00000000}, + {0x00016b80, 0x00000000}, + {0x00016b84, 0x00000000}, + {0x00016b88, 0x00800700}, + {0x00016b8c, 0x00800700}, + {0x00016b90, 0x00800700}, + {0x00016b94, 0x00000000}, + {0x00016b98, 0x00000000}, + {0x00016b9c, 0x00000000}, + {0x00016ba0, 0x00000001}, + {0x00016ba4, 0x00000001}, + {0x00016ba8, 0x00000000}, + {0x00016bac, 0x00000000}, + {0x00016bb0, 0x00000000}, + {0x00016bb4, 0x00000000}, + {0x00016bb8, 0x00000000}, + {0x00016bbc, 0x00000000}, + {0x00016bc0, 0x000000a0}, + {0x00016bc4, 0x000c0000}, + {0x00016bc8, 0x14021402}, + {0x00016bcc, 0x00001402}, + {0x00016bd0, 0x00000000}, + {0x00016bd4, 0x00000000}, +}; + +static const u32 ar9580_1p0_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, + {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, + {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, + {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, + {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, + {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, + {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, + {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, + {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, + {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, + {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +}; + +static const u32 ar9580_1p0_pcie_phy_clkreq_enable_L1[][2] = { + /* Addr allmodes */ + {0x00004040, 0x0835365e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +static const u32 ar9580_1p0_pcie_phy_clkreq_disable_L1[][2] = { + /* Addr allmodes */ + {0x00004040, 0x0831365e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = { + /* Addr allmodes */ + {0x00004040, 0x0831265e}, + {0x00004040, 0x0008003b}, + {0x00004044, 0x00000000}, +}; + +#endif /* INITVALS_9580_1P0_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 88100cc..a0d1147 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -663,6 +663,7 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_AR9485_PCIE: case AR9300_DEVID_AR9330: case AR9300_DEVID_AR9340: + case AR9300_DEVID_AR9580: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ee0d944..3aa3fb1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -45,6 +45,7 @@ #define AR9300_DEVID_PCIE 0x0030 #define AR9300_DEVID_AR9340 0x0031 #define AR9300_DEVID_AR9485_PCIE 0x0032 +#define AR9300_DEVID_AR9580 0x0033 #define AR9300_DEVID_AR9330 0x0035 #define AR5416_AR9100_DEVID 0x000b diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index fa4c0bb..a3b8bbc 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -793,6 +793,8 @@ #define AR_SREV_REVISION_9485_10 0 #define AR_SREV_REVISION_9485_11 1 #define AR_SREV_VERSION_9340 0x300 +#define AR_SREV_VERSION_9580 0x1C0 +#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -893,6 +895,18 @@ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) +#define AR_SREV_9580(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) + +#define AR_SREV_9580_10(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10)) + +/* NOTE: When adding chips newer than Peacock, add chip check here */ +#define AR_SREV_9580_10_OR_LATER(_ah) \ + (AR_SREV_9580(_ah)) + enum ath_usb_dev { AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ -- cgit v0.10.2 From 80d6e96be80593ae98a5d68c9ae4e054359d1a89 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 25 Aug 2011 15:00:54 +0200 Subject: carl9170: Use do_div for 64-bit division to fix 32-bit kernels Use the do_div macro for 64-bit division. Otherwise, the module will reference __udivdi3 under 32-bit kernels, which is not allowed in kernel space. drivers/built-in.o: In function `carl9170_collect_tally': cmd.c:191: undefined reference to `__udivdi3' cmd.c:192: undefined reference to `__udivdi3' cmd.c:193: undefined reference to `__udivdi3' Reported-by: Kalle Valo Signed-off-by: Christian Lamparter Tested-by: Kalle Valo Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index 9970bf8..195dc65 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -36,6 +36,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include "carl9170.h" #include "cmd.h" @@ -187,10 +188,12 @@ int carl9170_collect_tally(struct ar9170 *ar) if (ar->channel) { info = &ar->survey[ar->channel->hw_value]; - - info->channel_time = ar->tally.active / 1000; - info->channel_time_busy = ar->tally.cca / 1000; - info->channel_time_tx = ar->tally.tx_time / 1000; + info->channel_time = ar->tally.active; + info->channel_time_busy = ar->tally.cca; + info->channel_time_tx = ar->tally.tx_time; + do_div(info->channel_time, 1000); + do_div(info->channel_time_busy, 1000); + do_div(info->channel_time_tx, 1000); } } return 0; -- cgit v0.10.2 From a508a6ea234571e0e7d1e9f2455fc1eca54d1fef Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Aug 2011 13:37:07 -0700 Subject: ath9k: add AR9580 support This has been tested in STA and AP mode by Florian. Cc: David Quan Cc: Kathy Giori Cc: Senthil Balasubramanian Tested-by: Florian Fainelli Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 91c2e64..891661a 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -32,6 +32,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ + { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { 0 } }; -- cgit v0.10.2