···12301230F: drivers/block/aoe/1231123112321232ATHEROS ATH GENERIC UTILITIES12331233-M: "Luis R. Rodriguez" <lrodriguez@atheros.com>12331233+M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>12341234L: linux-wireless@vger.kernel.org12351235S: Supported12361236F: drivers/net/wireless/ath/*···12381238ATHEROS ATH5K WIRELESS DRIVER12391239M: Jiri Slaby <jirislaby@gmail.com>12401240M: Nick Kossifidis <mickflemm@gmail.com>12411241-M: "Luis R. Rodriguez" <lrodriguez@atheros.com>12411241+M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>12421242M: Bob Copeland <me@bobcopeland.com>12431243L: linux-wireless@vger.kernel.org12441244L: ath5k-devel@lists.ath5k.org···12471247F: drivers/net/wireless/ath/ath5k/1248124812491249ATHEROS ATH9K WIRELESS DRIVER12501250-M: "Luis R. Rodriguez" <lrodriguez@atheros.com>12511251-M: Jouni Malinen <jmalinen@atheros.com>12521252-M: Vasanthakumar Thiagarajan <vasanth@atheros.com>12531253-M: Senthil Balasubramanian <senthilkumar@atheros.com>12501250+M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>12511251+M: Jouni Malinen <jouni@qca.qualcomm.com>12521252+M: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>12531253+M: Senthil Balasubramanian <senthilb@qca.qualcomm.com>12541254L: linux-wireless@vger.kernel.org12551255L: ath9k-devel@lists.ath9k.org12561256W: http://wireless.kernel.org/en/users/Drivers/ath9k···12781278ATLX ETHERNET DRIVERS12791279M: Jay Cliburn <jcliburn@gmail.com>12801280M: Chris Snook <chris.snook@gmail.com>12811281-M: Jie Yang <jie.yang@atheros.com>12811281+M: Jie Yang <yangjie@qca.qualcomm.com>12821282L: netdev@vger.kernel.org12831283W: http://sourceforge.net/projects/atl112841284W: http://atl1.sourceforge.net···45024502W: http://www.qlogic.com45034503S: Supported45044504F: drivers/net/ethernet/qlogic/netxen/45054505+45064506+NFC SUBSYSTEM45074507+M: Lauro Ramos Venancio <lauro.venancio@openbossa.org>45084508+M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>45094509+M: Samuel Ortiz <sameo@linux.intel.com>45104510+L: linux-wireless@vger.kernel.org45114511+S: Maintained45124512+F: net/nfc/45134513+F: include/linux/nfc.h45144514+F: include/net/nfc.h45154515+F: drivers/nfc/4505451645064517NFS, SUNRPC, AND LOCKD CLIENTS45074518M: Trond Myklebust <Trond.Myklebust@netapp.com>
+19-1
drivers/bcma/driver_chipcommon_pmu.c
···9090 }9191}92929393+/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */9494+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)9595+{9696+ struct bcma_bus *bus = cc->core->bus;9797+ u32 val;9898+9999+ val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);100100+ if (enable) {101101+ val |= BCMA_CHIPCTL_4331_EXTPA_EN;102102+ if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)103103+ val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;104104+ } else {105105+ val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;106106+ val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;107107+ }108108+ bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);109109+}110110+93111void bcma_pmu_workarounds(struct bcma_drv_cc *cc)94112{95113 struct bcma_bus *bus = cc->core->bus;···11799 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);118100 break;119101 case 0x4331:120120- pr_err("Enabling Ext PA lines not implemented\n");102102+ /* BCM4331 workaround is SPROM-related, we put it in sprom.c */121103 break;122104 case 43224:123105 if (bus->chipinfo.rev == 0) {
+1-1
drivers/bcma/scan.c
···281281282282 /* get & parse master ports */283283 for (i = 0; i < ports[0]; i++) {284284- u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);284284+ s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);285285 if (mst_port_d < 0)286286 return -EILSEQ;287287 }
+6
drivers/bcma/sprom.c
···152152 if (!sprom)153153 return -ENOMEM;154154155155+ if (bus->chipinfo.id == 0x4331)156156+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);157157+155158 /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).156159 * According to brcm80211 this applies to cards with PCIe rev >= 6157160 * TODO: understand this condition and use it */158161 offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :159162 BCMA_CC_SPROM_PCIE6;160163 bcma_sprom_read(bus, offset, sprom);164164+165165+ if (bus->chipinfo.id == 0x4331)166166+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);161167162168 err = bcma_sprom_valid(sprom);163169 if (err)
+2-6
drivers/net/wireless/ath/ath9k/ar9002_hw.c
···303303 * register as the other analog registers. Hence the 9 writes.304304 */305305static void ar9002_hw_configpcipowersave(struct ath_hw *ah,306306- int restore,307307- int power_off)306306+ bool power_off)308307{309308 u8 i;310309 u32 val;311310312312- if (ah->is_pciexpress != true || ah->aspm_enabled != true)313313- return;314314-315311 /* Nothing to do on restore for 11N */316316- if (!restore) {312312+ if (!power_off /* !restore */) {317313 if (AR_SREV_9280_20_OR_LATER(ah)) {318314 /*319315 * AR9280 2.0 or later chips use SerDes values from the
···169169}170170EXPORT_SYMBOL(ath9k_cmn_update_txpow);171171172172+void ath9k_cmn_init_crypto(struct ath_hw *ah)173173+{174174+ struct ath_common *common = ath9k_hw_common(ah);175175+ int i = 0;176176+177177+ /* Get the hardware key cache size. */178178+ common->keymax = AR_KEYTABLE_SIZE;179179+180180+ /*181181+ * Check whether the separate key cache entries182182+ * are required to handle both tx+rx MIC keys.183183+ * With split mic keys the number of stations is limited184184+ * to 27 otherwise 59.185185+ */186186+ if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)187187+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;188188+189189+ /*190190+ * Reset the key cache since some parts do not191191+ * reset the contents on initial power up.192192+ */193193+ for (i = 0; i < common->keymax; i++)194194+ ath_hw_keyreset(common, (u16) i);195195+}196196+EXPORT_SYMBOL(ath9k_cmn_init_crypto);197197+172198static int __init ath9k_cmn_init(void)173199{174200 return 0;
···572572 return -EINVAL;573573}574574575575-static void ath9k_init_crypto(struct ath9k_htc_priv *priv)576576-{577577- struct ath_common *common = ath9k_hw_common(priv->ah);578578- int i = 0;579579-580580- /* Get the hardware key cache size. */581581- common->keymax = AR_KEYTABLE_SIZE;582582-583583- if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)584584- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;585585-586586- /*587587- * Reset the key cache since some parts do not588588- * reset the contents on initial power up.589589- */590590- for (i = 0; i < common->keymax; i++)591591- ath_hw_keyreset(common, (u16) i);592592-}593593-594575static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)595576{596577 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {···701720 for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)702721 priv->cur_beacon_conf.bslot[i] = NULL;703722704704- ath9k_init_crypto(priv);723723+ ath9k_cmn_init_crypto(ah);705724 ath9k_init_channels_rates(priv);706725 ath9k_init_misc(priv);707726
···404404 return error;405405}406406407407-void ath9k_init_crypto(struct ath_softc *sc)408408-{409409- struct ath_common *common = ath9k_hw_common(sc->sc_ah);410410- int i = 0;411411-412412- /* Get the hardware key cache size. */413413- common->keymax = AR_KEYTABLE_SIZE;414414-415415- /*416416- * Reset the key cache since some parts do not417417- * reset the contents on initial power up.418418- */419419- for (i = 0; i < common->keymax; i++)420420- ath_hw_keyreset(common, (u16) i);421421-422422- /*423423- * Check whether the separate key cache entries424424- * are required to handle both tx+rx MIC keys.425425- * With split mic keys the number of stations is limited426426- * to 27 otherwise 59.427427- */428428- if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)429429- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;430430-}431431-432407static int ath9k_init_btcoex(struct ath_softc *sc)433408{434409 struct ath_txq *txq;···605630 if (ret)606631 goto err_btcoex;607632608608- ath9k_init_crypto(sc);633633+ ath9k_cmn_init_crypto(sc->sc_ah);609634 ath9k_init_misc(sc);610635611636 return 0;
···565565static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)566566{567567 struct ath_node *an;568568- struct ath_hw *ah = sc->sc_ah;569568 an = (struct ath_node *)sta->drv_priv;570569571570#ifdef CONFIG_ATH9K_DEBUGFS···573574 spin_unlock(&sc->nodes_lock);574575 an->sta = sta;575576#endif576576- if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)577577- sc->sc_flags |= SC_OP_ENABLE_APM;578578-579577 if (sc->sc_flags & SC_OP_TXAGGR) {580578 ath_tx_node_init(sc, an);581579 an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +···822826 if (status & ATH9K_INT_TXURN)823827 ath9k_hw_updatetxtriglevel(ah, true);824828825825- if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {826826- if (status & ATH9K_INT_RXEOL) {827827- ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);828828- ath9k_hw_set_interrupts(ah, ah->imask);829829- }829829+ if (status & ATH9K_INT_RXEOL) {830830+ ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);831831+ ath9k_hw_set_interrupts(ah, ah->imask);830832 }831833832834 if (status & ATH9K_INT_MIB) {···882888 spin_lock_bh(&sc->sc_pcu_lock);883889 atomic_set(&ah->intr_ref_cnt, -1);884890885885- ath9k_hw_configpcipowersave(ah, 0, 0);891891+ ath9k_hw_configpcipowersave(ah, false);886892887893 if (!ah->curchan)888894 ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);···963969964970 ath9k_hw_phy_disable(ah);965971966966- ath9k_hw_configpcipowersave(ah, 1, 1);972972+ ath9k_hw_configpcipowersave(ah, true);967973968974 spin_unlock_bh(&sc->sc_pcu_lock);969975 ath9k_ps_restore(sc);···10631069 init_channel = ath9k_cmn_get_curchannel(hw, ah);1064107010651071 /* Reset SERDES registers */10661066- ath9k_hw_configpcipowersave(ah, 0, 0);10721072+ ath9k_hw_configpcipowersave(ah, false);1067107310681074 /*10691075 * The basic interface to setting the hardware in a good···11391145 AR_STOMP_LOW_WLAN_WGHT);11401146 ath9k_hw_btcoex_enable(ah);1141114711421142- if (common->bus_ops->bt_coex_prep)11431143- common->bus_ops->bt_coex_prep(common);11441148 if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)11451149 ath9k_btcoex_timer_resume(sc);11461150 }···1672168016731681 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {16741682 struct ieee80211_channel *curchan = hw->conf.channel;16831683+ struct ath9k_channel old_chan;16751684 int pos = curchan->hw_value;16761685 int old_pos = -1;16771686 unsigned long flags;···16891696 "Set channel: %d MHz type: %d\n",16901697 curchan->center_freq, conf->channel_type);1691169816921692- ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],16931693- curchan, conf->channel_type);16941694-16951699 /* update survey stats for the old channel before switching */16961700 spin_lock_irqsave(&common->cc_lock, flags);16971701 ath_update_survey_stats(sc);16981702 spin_unlock_irqrestore(&common->cc_lock, flags);17031703+17041704+ /*17051705+ * Preserve the current channel values, before updating17061706+ * the same channel17071707+ */17081708+ if (old_pos == pos) {17091709+ memcpy(&old_chan, &sc->sc_ah->channels[pos],17101710+ sizeof(struct ath9k_channel));17111711+ ah->curchan = &old_chan;17121712+ }17131713+17141714+ ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],17151715+ curchan, conf->channel_type);1699171617001717 /*17011718 * If the operating channel changes, change the survey in-use flags···24032400 return sc->beacon.tx_last;24042401}2405240224032403+static int ath9k_get_stats(struct ieee80211_hw *hw,24042404+ struct ieee80211_low_level_stats *stats)24052405+{24062406+ struct ath_softc *sc = hw->priv;24072407+ struct ath_hw *ah = sc->sc_ah;24082408+ struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;24092409+24102410+ stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;24112411+ stats->dot11RTSFailureCount = mib_stats->rts_bad;24122412+ stats->dot11FCSErrorCount = mib_stats->fcs_bad;24132413+ stats->dot11RTSSuccessCount = mib_stats->rts_good;24142414+ return 0;24152415+}24162416+24062417struct ieee80211_ops ath9k_ops = {24072418 .tx = ath9k_tx,24082419 .start = ath9k_start,···24412424 .set_coverage_class = ath9k_set_coverage_class,24422425 .flush = ath9k_flush,24432426 .tx_frames_pending = ath9k_tx_frames_pending,24442444- .tx_last_beacon = ath9k_tx_last_beacon,24272427+ .tx_last_beacon = ath9k_tx_last_beacon,24282428+ .get_stats = ath9k_get_stats,24452429};
+26-22
drivers/net/wireless/ath/ath9k/pci.c
···3232 { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */3333 { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */3434 { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */3535+ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */3536 { 0 }3637};3838+37393840/* return bus cachesize in 4B word units */3941static void ath_pci_read_cachesize(struct ath_common *common, int *csz)···9088 return true;9189}92909393-/*9494- * Bluetooth coexistance requires disabling ASPM.9595- */9696-static void ath_pci_bt_coex_prep(struct ath_common *common)9797-{9898- struct ath_softc *sc = (struct ath_softc *) common->priv;9999- struct pci_dev *pdev = to_pci_dev(sc->dev);100100- u8 aspm;101101-102102- if (!pci_is_pcie(pdev))103103- return;104104-105105- pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);106106- aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);107107- pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);108108-}109109-11091static void ath_pci_extn_synch_enable(struct ath_common *common)11192{11293 struct ath_softc *sc = (struct ath_softc *) common->priv;···101116 pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);102117}103118119119+/* Need to be called after we discover btcoex capabilities */104120static void ath_pci_aspm_init(struct ath_common *common)105121{106122 struct ath_softc *sc = (struct ath_softc *) common->priv;···111125 int pos;112126 u8 aspm;113127114114- if (!pci_is_pcie(pdev))128128+ pos = pci_pcie_cap(pdev);129129+ if (!pos)115130 return;116131117132 parent = pdev->bus->self;118118- if (WARN_ON(!parent))133133+ if (!parent)119134 return;135135+136136+ if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) {137137+ /* Bluetooth coexistance requires disabling ASPM. */138138+ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);139139+ aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);140140+ pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);141141+142142+ /*143143+ * Both upstream and downstream PCIe components should144144+ * have the same ASPM settings.145145+ */146146+ pos = pci_pcie_cap(parent);147147+ pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);148148+ aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);149149+ pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);150150+151151+ return;152152+ }120153121154 pos = pci_pcie_cap(parent);122155 pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);123156 if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {124157 ah->aspm_enabled = true;125158 /* Initialize PCIe PM and SERDES registers. */126126- ath9k_hw_configpcipowersave(ah, 0, 0);159159+ ath9k_hw_configpcipowersave(ah, false);127160 }128161}129162···150145 .ath_bus_type = ATH_PCI,151146 .read_cachesize = ath_pci_read_cachesize,152147 .eeprom_read = ath_pci_eeprom_read,153153- .bt_coex_prep = ath_pci_bt_coex_prep,154148 .extn_synch_en = ath_pci_extn_synch_enable,155149 .aspm_init = ath_pci_aspm_init,156150};···342338 * semi-random values after suspend/resume.343339 */344340 ath9k_ps_wakeup(sc);345345- ath9k_init_crypto(sc);341341+ ath9k_cmn_init_crypto(sc->sc_ah);346342 ath9k_ps_restore(sc);347343348344 sc->ps_idle = true;
+27-7
drivers/net/wireless/ath/ath9k/rc.c
···603603static u8 ath_rc_get_highest_rix(struct ath_softc *sc,604604 struct ath_rate_priv *ath_rc_priv,605605 const struct ath_rate_table *rate_table,606606- int *is_probing)606606+ int *is_probing,607607+ bool legacy)607608{608609 u32 best_thruput, this_thruput, now_msec;609610 u8 rate, next_rate, best_rate, maxindex, minindex;···625624 u8 per_thres;626625627626 rate = ath_rc_priv->valid_rate_index[index];627627+ if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY))628628+ continue;628629 if (rate > ath_rc_priv->rate_max_phy)629630 continue;630631···770767 struct ieee80211_tx_rate *rates = tx_info->control.rates;771768 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;772769 __le16 fc = hdr->frame_control;773773- u8 try_per_rate, i = 0, rix;770770+ u8 try_per_rate, i = 0, rix, high_rix;774771 int is_probe = 0;775772776773 if (rate_control_send_low(sta, priv_sta, txrc))···789786 try_per_rate = 4;790787791788 rate_table = ath_rc_priv->rate_table;792792- rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);789789+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,790790+ &is_probe, false);791791+ high_rix = rix;793792794793 /*795794 * If we're in HT mode and both us and our peer supports LDPC.···827822 }828823829824 /* Fill in the other rates for multirate retry */830830- for ( ; i < 4; i++) {831831- /* Use twice the number of tries for the last MRR segment. */832832- if (i + 1 == 4)833833- try_per_rate = 8;825825+ for ( ; i < 3; i++) {834826835827 ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);836828 /* All other rates in the series have RTS enabled */···835833 try_per_rate, rix, 1);836834 }837835836836+ /* Use twice the number of tries for the last MRR segment. */837837+ try_per_rate = 8;838838+839839+ /*840840+ * Use a legacy rate as last retry to ensure that the frame841841+ * is tried in both MCS and legacy rates.842842+ */843843+ if ((rates[2].flags & IEEE80211_TX_RC_MCS) &&844844+ (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) ||845845+ (ath_rc_priv->per[high_rix] > 45)))846846+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,847847+ &is_probe, true);848848+ else849849+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);850850+851851+ /* All other rates in the series have RTS enabled */852852+ ath_rc_rate_set_series(rate_table, &rates[i], txrc,853853+ try_per_rate, rix, 1);838854 /*839855 * NB:Change rate series to enable aggregation when operating840856 * at lower MCS rates. When first rate in series is MCS2
+9-3
drivers/net/wireless/ath/ath9k/recv.c
···761761 * on. All this is necessary because of our use of762762 * a self-linked list to avoid rx overruns.763763 */764764- ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);764764+ ret = ath9k_hw_rxprocdesc(ah, ds, rs);765765 if (ret == -EINPROGRESS) {766766 struct ath_rx_status trs;767767 struct ath_buf *tbf;···787787 */788788789789 tds = tbf->bf_desc;790790- ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);790790+ ret = ath9k_hw_rxprocdesc(ah, tds, &trs);791791 if (ret == -EINPROGRESS)792792 return NULL;793793 }···824824 is_mc = !!is_multicast_ether_addr(hdr->addr1);825825 is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&826826 test_bit(rx_stats->rs_keyix, common->tkip_keymap);827827- strip_mic = is_valid_tkip && !(rx_stats->rs_status &827827+ strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&828828+ !(rx_stats->rs_status &828829 (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));829830830831 if (!rx_stats->rs_datalen)···19781977 } while (1);1979197819801979 spin_unlock_bh(&sc->rx.rxbuflock);19801980+19811981+ if (!(ah->imask & ATH9K_INT_RXEOL)) {19821982+ ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);19831983+ ath9k_hw_set_interrupts(ah, ah->imask);19841984+ }1981198519821986 return 0;19831987}
···571571 ath_reset(sc, false);572572}573573574574+static bool ath_lookup_legacy(struct ath_buf *bf)575575+{576576+ struct sk_buff *skb;577577+ struct ieee80211_tx_info *tx_info;578578+ struct ieee80211_tx_rate *rates;579579+ int i;580580+581581+ skb = bf->bf_mpdu;582582+ tx_info = IEEE80211_SKB_CB(skb);583583+ rates = tx_info->control.rates;584584+585585+ for (i = 3; i >= 0; i--) {586586+ if (!(rates[i].flags & IEEE80211_TX_RC_MCS))587587+ return true;588588+ }589589+590590+ return false;591591+}592592+574593static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,575594 struct ath_atx_tid *tid)576595{···663644 * meet the minimum required mpdudensity.664645 */665646static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,666666- struct ath_buf *bf, u16 frmlen)647647+ struct ath_buf *bf, u16 frmlen,648648+ bool first_subfrm)667649{650650+#define FIRST_DESC_NDELIMS 60668651 struct sk_buff *skb = bf->bf_mpdu;669652 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);670653 u32 nsymbits, nsymbols;···687666 if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&688667 !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))689668 ndelim += ATH_AGGR_ENCRYPTDELIM;669669+670670+ /*671671+ * Add delimiter when using RTS/CTS with aggregation672672+ * and non enterprise AR9003 card673673+ */674674+ if (first_subfrm)675675+ ndelim = max(ndelim, FIRST_DESC_NDELIMS);690676691677 /*692678 * Convert desired mpdu density from microeconds to bytes based···769741 al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;770742771743 if (nframes &&772772- (aggr_limit < (al + bpad + al_delta + prev_al))) {744744+ ((aggr_limit < (al + bpad + al_delta + prev_al)) ||745745+ ath_lookup_legacy(bf))) {773746 status = ATH_AGGR_LIMITED;774747 break;775748 }···785756 status = ATH_AGGR_LIMITED;786757 break;787758 }788788- nframes++;789759790760 /* add padding for previous frame to aggregation length */791761 al += bpad + al_delta;···793765 * Get the delimiters needed to meet the MPDU794766 * density for this node.795767 */796796- ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);768768+ ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,769769+ !nframes);797770 bpad = PADBYTES(al_delta) + (ndelim << 2);798771772772+ nframes++;799773 bf->bf_next = NULL;800774 ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);801775···16041574{16051575 struct ath_hw *ah = sc->sc_ah;16061576 struct ath9k_channel *curchan = ah->curchan;16071607- if ((sc->sc_flags & SC_OP_ENABLE_APM) &&16081608- (curchan->channelFlags & CHANNEL_5GHZ) &&16091609- (chainmask == 0x7) && (rate < 0x90))15771577+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&15781578+ (curchan->channelFlags & CHANNEL_5GHZ) &&15791579+ (chainmask == 0x7) && (rate < 0x90))16101580 return 0x3;16111581 else16121582 return chainmask;
+14
drivers/net/wireless/ath/carl9170/Kconfig
···3939 bool4040 depends on CARL9170 && (INPUT = y || INPUT = CARL9170)4141 default y4242+4343+config CARL9170_HWRNG4444+ bool "Random number generator"4545+ depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170)4646+ default n4747+ help4848+ Provides a hardware random number generator to the kernel.4949+5050+ SECURITY WARNING: It's relatively easy to eavesdrop all5151+ generated random numbers from the transport stream with5252+ usbmon [software] or special usb sniffer hardware.5353+5454+ Say N, unless your setup[i.e.: embedded system] has no5555+ other rng source and you can afford to take the risk.
···169169 Say N, if you are a distributor or user building a release kernel170170 for production use.171171 Only say Y, if you are debugging a problem in the b43 driver sourcecode.172172-173173-config B43_FORCE_PIO174174- bool "Force usage of PIO instead of DMA"175175- depends on B43 && B43_DEBUG176176- ---help---177177- This will disable DMA and always enable PIO instead.178178-179179- Say N!180180- This is only for debugging the PIO engine code. You do181181- _NOT_ want to enable this.
+11-12
drivers/net/wireless/b43/b43.h
···1717#include "phy_common.h"181819192020-/* The unique identifier of the firmware that's officially supported by2121- * this driver version. */2222-#define B43_SUPPORTED_FIRMWARE_ID "FW13"2323-2424-2520#ifdef CONFIG_B43_DEBUG2621# define B43_DEBUG 12722#else···589594 struct b43_dmaring *rx_ring;590595591596 u32 translation; /* Routing bits */597597+ bool translation_in_low; /* Should translation bit go into low addr? */592598 bool parity; /* Check for parity */593599};594600···690694 enum b43_firmware_file_type type;691695};692696697697+enum b43_firmware_hdr_format {698698+ B43_FW_HDR_598,699699+ B43_FW_HDR_410,700700+ B43_FW_HDR_351,701701+};702702+693703/* Pointers to the firmware data and meta information about it. */694704struct b43_firmware {695705 /* Microcode */···711709 u16 rev;712710 /* Firmware patchlevel */713711 u16 patch;712712+713713+ /* Format of header used by firmware */714714+ enum b43_firmware_hdr_format hdr_format;714715715716 /* Set to true, if we are using an opensource firmware.716717 * Use this to check for proprietary vs opensource. */···880875 struct b43_leds leds;881876882877 /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */883883- u8 pio_scratchspace[110] __attribute__((__aligned__(8)));878878+ u8 pio_scratchspace[118] __attribute__((__aligned__(8)));884879 u8 pio_tailspace[4] __attribute__((__aligned__(8)));885880};886881···969964{970965 return dev->__using_pio_transfers;971966}972972-973973-#ifdef CONFIG_B43_FORCE_PIO974974-# define B43_PIO_DEFAULT 1975975-#else976976-# define B43_PIO_DEFAULT 0977977-#endif978967979968/* Message printing */980969void b43info(struct b43_wl *wl, const char *fmt, ...)
···44#include "phy_common.h"556677+#define B43_PHY_HT_BBCFG 0x001 /* BB config */88+#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */99+#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */710#define B43_PHY_HT_BANDCTL 0x009 /* Band control */1111+#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */812#define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */913#define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */1014#define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */···1814#define B43_PHY_HT_BW4 0x1D11915#define B43_PHY_HT_BW5 0x1D22016#define B43_PHY_HT_BW6 0x1D31717+1818+#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E)1919+#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E)2020+#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E)2121+2222+#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000)2323+#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003)2424+#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */2525+#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */2626+#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */2727+#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */2828+#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */2929+#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */3030+#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004)3131+/* Values for the status are the same as for the trigger */21322233#define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010)2334
···238238 echo "1" > hostsleep : enable host sleep.239239 echo "0" > hostsleep : disable host sleep240240241241-========================242242-IWCONFIG COMMANDS243243-========================244244-power period245245-246246- This command is used to configure the station in deep sleep mode /247247- auto deep sleep mode.248248-249249- The timer is implemented to monitor the activities (command, event,250250- etc.). When an activity is detected station will exit from deep251251- sleep mode automatically and restart the timer. At timer expiry252252- (no activity for defined time period) the deep sleep mode is entered253253- automatically.254254-255255- Note: this command is for SDIO interface only.256256-257257- Usage:258258- To enable deep sleep mode do:259259- iwconfig wlan0 power period 0260260- To enable auto deep sleep mode with idle time period 5 seconds do:261261- iwconfig wlan0 power period 5262262- To disable deep sleep/auto deep sleep mode do:263263- iwconfig wlan0 power period -1264264-265265-==============================================================================
+2-2
drivers/net/wireless/libertas/dev.h
···190190 int r;191191192192 r = netif_running(priv->dev);193193- if (priv->mesh_dev);194194- r |= netif_running(priv->dev);193193+ if (priv->mesh_dev)194194+ r |= netif_running(priv->mesh_dev);195195196196 return r;197197}
+2-2
drivers/net/wireless/mwifiex/scan.c
···14801480 return -ENOMEM;14811481 }14821482 beacon_ie = kzalloc(ie_len, GFP_KERNEL);14831483- if (!bss_desc) {14841484- dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");14831483+ if (!beacon_ie) {14841484+ dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");14851485 return -ENOMEM;14861486 }14871487 memcpy(beacon_ie, ie_buf, ie_len);
···10421042 * (Re)Association Response frames when the driver (or firmware) replies to10431043 * (Re)Association Request frames.10441044 *10451045+ * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration10461046+ * of the station, see &enum nl80211_sta_wme_attr.10471047+ *10451048 * @NL80211_ATTR_MAX: highest attribute number currently defined10461049 * @__NL80211_ATTR_AFTER_LAST: internal use10471050 */···1254125112551252 NL80211_ATTR_IE_PROBE_RESP,12561253 NL80211_ATTR_IE_ASSOC_RESP,12541254+12551255+ NL80211_ATTR_STA_WME,1257125612581257 /* add attributes here, update the policy in nl80211.c */12591258···18661861 * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a18671862 * source mesh point for path selection elements.18681863 *18641864+ * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between18651865+ * root announcements are transmitted.18661866+ *18671867+ * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has18681868+ * access to a broader network beyond the MBSS. This is done via Root18691869+ * Announcement frames.18701870+ *18691871 * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute18701872 *18711873 * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use···18941882 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,18951883 NL80211_MESHCONF_HWMP_ROOTMODE,18961884 NL80211_MESHCONF_ELEMENT_TTL,18851885+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,18861886+ NL80211_MESHCONF_GATE_ANNOUNCEMENTS,1897188718981888 /* keep last */18991889 __NL80211_MESHCONF_ATTR_AFTER_LAST,···24852471 NL80211_HIDDEN_SSID_NOT_IN_USE,24862472 NL80211_HIDDEN_SSID_ZERO_LEN,24872473 NL80211_HIDDEN_SSID_ZERO_CONTENTS24742474+};24752475+24762476+/**24772477+ * enum nl80211_sta_wme_attr - station WME attributes24782478+ * @__NL80211_STA_WME_INVALID: invalid number for nested attribute24792479+ * @NL80211_STA_WME_QUEUES: bitmap of uapsd queues.24802480+ * @NL80211_STA_WME_MAX_SP: max service period.24812481+ * @__NL80211_STA_WME_AFTER_LAST: internal24822482+ * @NL80211_STA_WME_MAX: highest station WME attribute24832483+ */24842484+enum nl80211_sta_wme_attr {24852485+ __NL80211_STA_WME_INVALID,24862486+ NL80211_STA_WME_UAPSD_QUEUES,24872487+ NL80211_STA_WME_MAX_SP,24882488+24892489+ /* keep last */24902490+ __NL80211_STA_WME_AFTER_LAST,24912491+ NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 124882492};2489249324902494#endif /* __LINUX_NL80211_H */
+10-2
include/net/cfg80211.h
···452452 u8 plink_action;453453 u8 plink_state;454454 struct ieee80211_ht_cap *ht_capa;455455+ u8 uapsd_queues;456456+ u8 max_sp;455457};456458457459/**···757755 u16 dot11MeshHWMPpreqMinInterval;758756 u16 dot11MeshHWMPnetDiameterTraversalTime;759757 u8 dot11MeshHWMPRootMode;758758+ u16 dot11MeshHWMPRannInterval;759759+ /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol760760+ * set to true only means that the station will announce others it's a761761+ * mesh gate, but not necessarily using the gate announcement protocol.762762+ * Still keeping the same nomenclature to be in sync with the spec. */763763+ bool dot11MeshGateAnnouncementProtocol;760764};761765762766/**···22992291 struct ieee80211_ht_info *ht_info_elem;23002292 struct ieee80211_meshconf_ie *mesh_config;23012293 u8 *mesh_id;23022302- u8 *peer_link;22942294+ u8 *peering;23032295 u8 *preq;23042296 u8 *prep;23052297 u8 *perr;···23262318 u8 wmm_info_len;23272319 u8 wmm_param_len;23282320 u8 mesh_id_len;23292329- u8 peer_link_len;23212321+ u8 peering_len;23302322 u8 preq_len;23312323 u8 prep_len;23322324 u8 perr_len;
+2
include/net/mac80211.h
···954954 u16 aid;955955 struct ieee80211_sta_ht_cap ht_cap;956956 bool wme;957957+ u8 uapsd_queues;958958+ u8 max_sp;957959958960 /* must be last */959961 u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+6-1
include/net/nfc.h
···8282 struct nfc_genl_data genl_data;8383 u32 supported_protocols;84848585+ int tx_headroom;8686+ int tx_tailroom;8787+8588 struct nfc_ops *ops;8689};8790#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)···9289extern struct class nfc_class;93909491struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,9595- u32 supported_protocols);9292+ u32 supported_protocols,9393+ int tx_headroom,9494+ int tx_tailroom);96959796/**9897 * nfc_free_device - free nfc device
+12-4
include/net/regulatory.h
···33/*44 * regulatory support structures55 *66- * Copyright 2008-2009 Luis R. Rodriguez <lrodriguez@atheros.com>66+ * Copyright 2008-2009 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>77 *88- * This program is free software; you can redistribute it and/or modify99- * it under the terms of the GNU General Public License version 2 as1010- * published by the Free Software Foundation.88+ * Permission to use, copy, modify, and/or distribute this software for any99+ * purpose with or without fee is hereby granted, provided that the above1010+ * copyright notice and this permission notice appear in all copies.1111+ *1212+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES1313+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1414+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1515+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1616+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1717+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1818+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1119 */12201321
+13
net/mac80211/Kconfig
···199199200200 Do not select this option.201201202202+config MAC80211_VERBOSE_MPATH_DEBUG203203+ bool "Verbose mesh path debugging"204204+ depends on MAC80211_DEBUG_MENU205205+ depends on MAC80211_MESH206206+ ---help---207207+ Selecting this option causes mac80211 to print out very208208+ verbose mesh path selection debugging messages (when mac80211209209+ is taking part in a mesh network).210210+ It should not be selected on production systems as those211211+ messages are remotely triggerable.212212+213213+ Do not select this option.214214+202215config MAC80211_VERBOSE_MHWMP_DEBUG203216 bool "Verbose mesh HWMP routing debugging"204217 depends on MAC80211_DEBUG_MENU
···697697 }698698 spin_unlock_irqrestore(&sta->flaglock, flags);699699700700+ sta->sta.uapsd_queues = params->uapsd_queues;701701+ sta->sta.max_sp = params->max_sp;702702+700703 /*701704 * cfg80211 validates this (1-2007) and allows setting the AID702705 * only when creating a new station entry···11391136 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask)) {11401137 conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;11411138 ieee80211_mesh_root_setup(ifmsh);11391139+ }11401140+ if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) {11411141+ /* our current gate announcement implementation rides on root11421142+ * announcements, so require this ifmsh to also be a root node11431143+ * */11441144+ if (nconf->dot11MeshGateAnnouncementProtocol &&11451145+ !conf->dot11MeshHWMPRootMode) {11461146+ conf->dot11MeshHWMPRootMode = 1;11471147+ ieee80211_mesh_root_setup(ifmsh);11481148+ }11491149+ conf->dot11MeshGateAnnouncementProtocol =11501150+ nconf->dot11MeshGateAnnouncementProtocol;11511151+ }11521152+ if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {11531153+ conf->dot11MeshHWMPRannInterval =11541154+ nconf->dot11MeshHWMPRannInterval;11421155 }11431156 return 0;11441157}
···1717#include "ieee80211_i.h"1818#include "mesh.h"19192020+#ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG2121+#define mpath_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args)2222+#else2323+#define mpath_dbg(fmt, args...) do { (void)(0); } while (0)2424+#endif2525+2026/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */2127#define INIT_PATHS_SIZE_ORDER 22228···6559 return rcu_dereference_protected(mpp_paths,6660 lockdep_is_held(&pathtbl_resize_lock));6761}6262+6363+static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath);68646965/*7066 * CAREFUL -- "tbl" must not be an expression,···111103 sizeof(newtbl->hash_rnd));112104 for (i = 0; i <= newtbl->hash_mask; i++)113105 spin_lock_init(&newtbl->hashwlock[i]);106106+ spin_lock_init(&newtbl->gates_lock);114107115108 return newtbl;116109}···127118{128119 struct hlist_head *mesh_hash;129120 struct hlist_node *p, *q;121121+ struct mpath_node *gate;130122 int i;131123132124 mesh_hash = tbl->hash_buckets;···139129 }140130 spin_unlock_bh(&tbl->hashwlock[i]);141131 }132132+ if (free_leafs) {133133+ spin_lock_bh(&tbl->gates_lock);134134+ hlist_for_each_entry_safe(gate, p, q,135135+ tbl->known_gates, list) {136136+ hlist_del(&gate->list);137137+ kfree(gate);138138+ }139139+ kfree(tbl->known_gates);140140+ spin_unlock_bh(&tbl->gates_lock);141141+ }142142+142143 __mesh_table_free(tbl);143144}144145···167146 newtbl->free_node = oldtbl->free_node;168147 newtbl->mean_chain_len = oldtbl->mean_chain_len;169148 newtbl->copy_node = oldtbl->copy_node;149149+ newtbl->known_gates = oldtbl->known_gates;170150 atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));171151172152 oldhash = oldtbl->hash_buckets;···225203226204 skb_queue_splice(&tmpq, &mpath->frame_queue);227205 spin_unlock_irqrestore(&mpath->frame_queue.lock, flags);206206+}207207+208208+static void prepare_for_gate(struct sk_buff *skb, char *dst_addr,209209+ struct mesh_path *gate_mpath)210210+{211211+ struct ieee80211_hdr *hdr;212212+ struct ieee80211s_hdr *mshdr;213213+ int mesh_hdrlen, hdrlen;214214+ char *next_hop;215215+216216+ hdr = (struct ieee80211_hdr *) skb->data;217217+ hdrlen = ieee80211_hdrlen(hdr->frame_control);218218+ mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);219219+220220+ if (!(mshdr->flags & MESH_FLAGS_AE)) {221221+ /* size of the fixed part of the mesh header */222222+ mesh_hdrlen = 6;223223+224224+ /* make room for the two extended addresses */225225+ skb_push(skb, 2 * ETH_ALEN);226226+ memmove(skb->data, hdr, hdrlen + mesh_hdrlen);227227+228228+ hdr = (struct ieee80211_hdr *) skb->data;229229+230230+ /* we preserve the previous mesh header and only add231231+ * the new addreses */232232+ mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);233233+ mshdr->flags = MESH_FLAGS_AE_A5_A6;234234+ memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN);235235+ memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN);236236+ }237237+238238+ /* update next hop */239239+ hdr = (struct ieee80211_hdr *) skb->data;240240+ rcu_read_lock();241241+ next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr;242242+ memcpy(hdr->addr1, next_hop, ETH_ALEN);243243+ rcu_read_unlock();244244+ memcpy(hdr->addr3, dst_addr, ETH_ALEN);245245+}246246+247247+/**248248+ *249249+ * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another250250+ *251251+ * This function is used to transfer or copy frames from an unresolved mpath to252252+ * a gate mpath. The function also adds the Address Extension field and253253+ * updates the next hop.254254+ *255255+ * If a frame already has an Address Extension field, only the next hop and256256+ * destination addresses are updated.257257+ *258258+ * The gate mpath must be an active mpath with a valid mpath->next_hop.259259+ *260260+ * @mpath: An active mpath the frames will be sent to (i.e. the gate)261261+ * @from_mpath: The failed mpath262262+ * @copy: When true, copy all the frames to the new mpath queue. When false,263263+ * move them.264264+ */265265+static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,266266+ struct mesh_path *from_mpath,267267+ bool copy)268268+{269269+ struct sk_buff *skb, *cp_skb = NULL;270270+ struct sk_buff_head gateq, failq;271271+ unsigned long flags;272272+ int num_skbs;273273+274274+ BUG_ON(gate_mpath == from_mpath);275275+ BUG_ON(!gate_mpath->next_hop);276276+277277+ __skb_queue_head_init(&gateq);278278+ __skb_queue_head_init(&failq);279279+280280+ spin_lock_irqsave(&from_mpath->frame_queue.lock, flags);281281+ skb_queue_splice_init(&from_mpath->frame_queue, &failq);282282+ spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);283283+284284+ num_skbs = skb_queue_len(&failq);285285+286286+ while (num_skbs--) {287287+ skb = __skb_dequeue(&failq);288288+ if (copy)289289+ cp_skb = skb_copy(skb, GFP_ATOMIC);290290+291291+ prepare_for_gate(skb, gate_mpath->dst, gate_mpath);292292+ __skb_queue_tail(&gateq, skb);293293+294294+ if (copy && cp_skb)295295+ __skb_queue_tail(&failq, cp_skb);296296+ }297297+298298+ spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags);299299+ skb_queue_splice(&gateq, &gate_mpath->frame_queue);300300+ mpath_dbg("Mpath queue for gate %pM has %d frames\n",301301+ gate_mpath->dst,302302+ skb_queue_len(&gate_mpath->frame_queue));303303+ spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags);304304+305305+ if (!copy)306306+ return;307307+308308+ spin_lock_irqsave(&from_mpath->frame_queue.lock, flags);309309+ skb_queue_splice(&failq, &from_mpath->frame_queue);310310+ spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);228311}229312230313···429302 }430303431304 return NULL;305305+}306306+307307+static void mesh_gate_node_reclaim(struct rcu_head *rp)308308+{309309+ struct mpath_node *node = container_of(rp, struct mpath_node, rcu);310310+ kfree(node);311311+}312312+313313+/**314314+ * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates315315+ * @mesh_tbl: table which contains known_gates list316316+ * @mpath: mpath to known mesh gate317317+ *318318+ * Returns: 0 on success319319+ *320320+ */321321+static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath)322322+{323323+ struct mpath_node *gate, *new_gate;324324+ struct hlist_node *n;325325+ int err;326326+327327+ rcu_read_lock();328328+ tbl = rcu_dereference(tbl);329329+330330+ hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list)331331+ if (gate->mpath == mpath) {332332+ err = -EEXIST;333333+ goto err_rcu;334334+ }335335+336336+ new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC);337337+ if (!new_gate) {338338+ err = -ENOMEM;339339+ goto err_rcu;340340+ }341341+342342+ mpath->is_gate = true;343343+ mpath->sdata->u.mesh.num_gates++;344344+ new_gate->mpath = mpath;345345+ spin_lock_bh(&tbl->gates_lock);346346+ hlist_add_head_rcu(&new_gate->list, tbl->known_gates);347347+ spin_unlock_bh(&tbl->gates_lock);348348+ rcu_read_unlock();349349+ mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n",350350+ mpath->sdata->name, mpath->dst,351351+ mpath->sdata->u.mesh.num_gates);352352+ return 0;353353+err_rcu:354354+ rcu_read_unlock();355355+ return err;356356+}357357+358358+/**359359+ * mesh_gate_del - remove a mesh gate from the list of known gates360360+ * @tbl: table which holds our list of known gates361361+ * @mpath: gate mpath362362+ *363363+ * Returns: 0 on success364364+ *365365+ * Locking: must be called inside rcu_read_lock() section366366+ */367367+static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)368368+{369369+ struct mpath_node *gate;370370+ struct hlist_node *p, *q;371371+372372+ tbl = rcu_dereference(tbl);373373+374374+ hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list)375375+ if (gate->mpath == mpath) {376376+ spin_lock_bh(&tbl->gates_lock);377377+ hlist_del_rcu(&gate->list);378378+ call_rcu(&gate->rcu, mesh_gate_node_reclaim);379379+ spin_unlock_bh(&tbl->gates_lock);380380+ mpath->sdata->u.mesh.num_gates--;381381+ mpath->is_gate = false;382382+ mpath_dbg("Mesh path (%s): Deleted gate: %pM. "383383+ "%d known gates\n", mpath->sdata->name,384384+ mpath->dst, mpath->sdata->u.mesh.num_gates);385385+ break;386386+ }387387+388388+ return 0;389389+}390390+391391+/**392392+ *393393+ * mesh_path_add_gate - add the given mpath to a mesh gate to our path table394394+ * @mpath: gate path to add to table395395+ */396396+int mesh_path_add_gate(struct mesh_path *mpath)397397+{398398+ return mesh_gate_add(mesh_paths, mpath);399399+}400400+401401+/**402402+ * mesh_gate_num - number of gates known to this interface403403+ * @sdata: subif data404404+ */405405+int mesh_gate_num(struct ieee80211_sub_if_data *sdata)406406+{407407+ return sdata->u.mesh.num_gates;432408}433409434410/**···711481 new_mpath->flags = 0;712482 skb_queue_head_init(&new_mpath->frame_queue);713483 new_node->mpath = new_mpath;484484+ init_timer(&new_mpath->timer);714485 new_mpath->exp_time = jiffies;715486 spin_lock_init(&new_mpath->state_lock);716487···770539 struct hlist_node *p;771540 struct ieee80211_sub_if_data *sdata = sta->sdata;772541 int i;542542+ __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);773543774544 rcu_read_lock();775545 tbl = rcu_dereference(mesh_paths);···785553 spin_unlock_bh(&mpath->state_lock);786554 mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl,787555 mpath->dst, cpu_to_le32(mpath->sn),788788- cpu_to_le16(PERR_RCODE_DEST_UNREACH),789789- bcast, sdata);556556+ reason, bcast, sdata);790557 } else791558 spin_unlock_bh(&mpath->state_lock);792559 }···878647 mpath = node->mpath;879648 if (mpath->sdata == sdata &&880649 memcmp(addr, mpath->dst, ETH_ALEN) == 0) {881881- spin_lock(&mpath->state_lock);650650+ spin_lock_bh(&mpath->state_lock);651651+ if (mpath->is_gate)652652+ mesh_gate_del(tbl, mpath);882653 mpath->flags |= MESH_PATH_RESOLVING;883654 hlist_del_rcu(&node->list);884655 call_rcu(&node->rcu, mesh_path_node_reclaim);885656 atomic_dec(&tbl->entries);886886- spin_unlock(&mpath->state_lock);657657+ spin_unlock_bh(&mpath->state_lock);887658 goto enddel;888659 }889660 }···914681}915682916683/**684684+ * mesh_path_send_to_gates - sends pending frames to all known mesh gates685685+ *686686+ * @mpath: mesh path whose queue will be emptied687687+ *688688+ * If there is only one gate, the frames are transferred from the failed mpath689689+ * queue to that gate's queue. If there are more than one gates, the frames690690+ * are copied from each gate to the next. After frames are copied, the691691+ * mpath queues are emptied onto the transmission queue.692692+ */693693+int mesh_path_send_to_gates(struct mesh_path *mpath)694694+{695695+ struct ieee80211_sub_if_data *sdata = mpath->sdata;696696+ struct hlist_node *n;697697+ struct mesh_table *tbl;698698+ struct mesh_path *from_mpath = mpath;699699+ struct mpath_node *gate = NULL;700700+ bool copy = false;701701+ struct hlist_head *known_gates;702702+703703+ rcu_read_lock();704704+ tbl = rcu_dereference(mesh_paths);705705+ known_gates = tbl->known_gates;706706+ rcu_read_unlock();707707+708708+ if (!known_gates)709709+ return -EHOSTUNREACH;710710+711711+ hlist_for_each_entry_rcu(gate, n, known_gates, list) {712712+ if (gate->mpath->sdata != sdata)713713+ continue;714714+715715+ if (gate->mpath->flags & MESH_PATH_ACTIVE) {716716+ mpath_dbg("Forwarding to %pM\n", gate->mpath->dst);717717+ mesh_path_move_to_queue(gate->mpath, from_mpath, copy);718718+ from_mpath = gate->mpath;719719+ copy = true;720720+ } else {721721+ mpath_dbg("Not forwarding %p\n", gate->mpath);722722+ mpath_dbg("flags %x\n", gate->mpath->flags);723723+ }724724+ }725725+726726+ hlist_for_each_entry_rcu(gate, n, known_gates, list)727727+ if (gate->mpath->sdata == sdata) {728728+ mpath_dbg("Sending to %pM\n", gate->mpath->dst);729729+ mesh_path_tx_pending(gate->mpath);730730+ }731731+732732+ return (from_mpath == mpath) ? -EHOSTUNREACH : 0;733733+}734734+735735+/**917736 * mesh_path_discard_frame - discard a frame whose path could not be resolved918737 *919738 * @skb: frame to discard···984699 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;985700 struct mesh_path *mpath;986701 u32 sn = 0;702702+ __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);987703988704 if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {989705 u8 *ra, *da;···995709 if (mpath)996710 sn = ++mpath->sn;997711 mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data,998998- cpu_to_le32(sn),999999- cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata);712712+ cpu_to_le32(sn), reason, ra, sdata);1000713 }10017141002715 kfree_skb(skb);···1013728{1014729 struct sk_buff *skb;101573010161016- while ((skb = skb_dequeue(&mpath->frame_queue)) &&10171017- (mpath->flags & MESH_PATH_ACTIVE))731731+ while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL)1018732 mesh_path_discard_frame(skb, mpath->sdata);1019733}1020734···1081797 tbl_path->free_node = &mesh_path_node_free;1082798 tbl_path->copy_node = &mesh_path_node_copy;1083799 tbl_path->mean_chain_len = MEAN_CHAIN_LEN;800800+ tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);801801+ INIT_HLIST_HEAD(tbl_path->known_gates);802802+10848031085804 tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);1086805 if (!tbl_mpp) {···1093806 tbl_mpp->free_node = &mesh_path_node_free;1094807 tbl_mpp->copy_node = &mesh_path_node_copy;1095808 tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;809809+ tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);810810+ INIT_HLIST_HEAD(tbl_mpp->known_gates);10968111097812 /* Need no locking since this is during init */1098813 RCU_INIT_POINTER(mesh_paths, tbl_path);
+124-117
net/mac80211/mesh_plink.c
···1919#define mpl_dbg(fmt, args...) do { (void)(0); } while (0)2020#endif21212222-#define PLINK_GET_LLID(p) (p + 4)2323-#define PLINK_GET_PLID(p) (p + 6)2222+#define PLINK_GET_LLID(p) (p + 2)2323+#define PLINK_GET_PLID(p) (p + 4)24242525#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \2626 jiffies + HZ * t / 1000))2727-2828-/* Peer link cancel reasons, all subject to ANA approval */2929-#define MESH_LINK_CANCELLED 23030-#define MESH_MAX_NEIGHBORS 33131-#define MESH_CAPABILITY_POLICY_VIOLATION 43232-#define MESH_CLOSE_RCVD 53333-#define MESH_MAX_RETRIES 63434-#define MESH_CONFIRM_TIMEOUT 73535-#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 83636-#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 93737-#define MESH_SECURITY_FAILED_VERIFICATION 1038273928#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)4029#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)4130#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)4231#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)4332#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)4444-4545-enum plink_frame_type {4646- PLINK_OPEN = 1,4747- PLINK_CONFIRM,4848- PLINK_CLOSE4949-};50335134enum plink_event {5235 PLINK_UNDEFINED,···140157}141158142159static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,143143- enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid,144144- __le16 reason) {160160+ enum ieee80211_self_protected_actioncode action,161161+ u8 *da, __le16 llid, __le16 plid, __le16 reason) {145162 struct ieee80211_local *local = sdata->local;146163 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +147164 sdata->u.mesh.ie_len);148165 struct ieee80211_mgmt *mgmt;149166 bool include_plid = false;150150- static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A };167167+ int ie_len = 4;168168+ u16 peering_proto = 0;151169 u8 *pos;152152- int ie_len;153170154171 if (!skb)155172 return -1;···158175 * common action part (1)159176 */160177 mgmt = (struct ieee80211_mgmt *)161161- skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action));162162- memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action));178178+ skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot));179179+ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot));163180 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |164181 IEEE80211_STYPE_ACTION);165182 memcpy(mgmt->da, da, ETH_ALEN);166183 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);167184 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);168168- mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;169169- mgmt->u.action.u.plink_action.action_code = action;185185+ mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;186186+ mgmt->u.action.u.self_prot.action_code = action;170187171171- if (action == PLINK_CLOSE)172172- mgmt->u.action.u.plink_action.aux = reason;173173- else {174174- mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0);175175- if (action == PLINK_CONFIRM) {176176- pos = skb_put(skb, 4);177177- /* two-byte status code followed by two-byte AID */178178- memset(pos, 0, 2);188188+ if (action != WLAN_SP_MESH_PEERING_CLOSE) {189189+ /* capability info */190190+ pos = skb_put(skb, 2);191191+ memset(pos, 0, 2);192192+ if (action == WLAN_SP_MESH_PEERING_CONFIRM) {193193+ /* AID */194194+ pos = skb_put(skb, 2);179195 memcpy(pos + 2, &plid, 2);180196 }181181- mesh_mgmt_ies_add(skb, sdata);197197+ if (mesh_add_srates_ie(skb, sdata) ||198198+ mesh_add_ext_srates_ie(skb, sdata) ||199199+ mesh_add_rsn_ie(skb, sdata) ||200200+ mesh_add_meshid_ie(skb, sdata) ||201201+ mesh_add_meshconf_ie(skb, sdata))202202+ return -1;203203+ } else { /* WLAN_SP_MESH_PEERING_CLOSE */204204+ if (mesh_add_meshid_ie(skb, sdata))205205+ return -1;182206 }183207184184- /* Add Peer Link Management element */208208+ /* Add Mesh Peering Management element */185209 switch (action) {186186- case PLINK_OPEN:187187- ie_len = 6;210210+ case WLAN_SP_MESH_PEERING_OPEN:188211 break;189189- case PLINK_CONFIRM:190190- ie_len = 8;212212+ case WLAN_SP_MESH_PEERING_CONFIRM:213213+ ie_len += 2;191214 include_plid = true;192215 break;193193- case PLINK_CLOSE:194194- default:195195- if (!plid)196196- ie_len = 8;197197- else {198198- ie_len = 10;216216+ case WLAN_SP_MESH_PEERING_CLOSE:217217+ if (plid) {218218+ ie_len += 2;199219 include_plid = true;200220 }221221+ ie_len += 2; /* reason code */201222 break;223223+ default:224224+ return -EINVAL;202225 }203226227227+ if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))228228+ return -ENOMEM;229229+204230 pos = skb_put(skb, 2 + ie_len);205205- *pos++ = WLAN_EID_PEER_LINK;231231+ *pos++ = WLAN_EID_PEER_MGMT;206232 *pos++ = ie_len;207207- memcpy(pos, meshpeeringproto, sizeof(meshpeeringproto));208208- pos += 4;233233+ memcpy(pos, &peering_proto, 2);234234+ pos += 2;209235 memcpy(pos, &llid, 2);236236+ pos += 2;210237 if (include_plid) {211211- pos += 2;212238 memcpy(pos, &plid, 2);213213- }214214- if (action == PLINK_CLOSE) {215239 pos += 2;216216- memcpy(pos, &reason, 2);217240 }241241+ if (action == WLAN_SP_MESH_PEERING_CLOSE) {242242+ memcpy(pos, &reason, 2);243243+ pos += 2;244244+ }245245+ if (mesh_add_vendor_ies(skb, sdata))246246+ return -1;218247219248 ieee80211_tx_skb(sdata, skb);220249 return 0;···317322 ++sta->plink_retries;318323 mod_plink_timer(sta, sta->plink_timeout);319324 spin_unlock_bh(&sta->lock);320320- mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid,321321- 0, 0);325325+ mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,326326+ sta->sta.addr, llid, 0, 0);322327 break;323328 }324324- reason = cpu_to_le16(MESH_MAX_RETRIES);329329+ reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);325330 /* fall through on else */326331 case NL80211_PLINK_CNF_RCVD:327332 /* confirm timer */328333 if (!reason)329329- reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);334334+ reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);330335 sta->plink_state = NL80211_PLINK_HOLDING;331336 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));332337 spin_unlock_bh(&sta->lock);333333- mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid,334334- reason);338338+ mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,339339+ sta->sta.addr, llid, plid, reason);335340 break;336341 case NL80211_PLINK_HOLDING:337342 /* holding timer */···391396 mpl_dbg("Mesh plink: starting establishment with %pM\n",392397 sta->sta.addr);393398394394- return mesh_plink_frame_tx(sdata, PLINK_OPEN,399399+ return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,395400 sta->sta.addr, llid, 0, 0);396401}397402···417422 struct ieee802_11_elems elems;418423 struct sta_info *sta;419424 enum plink_event event;420420- enum plink_frame_type ftype;425425+ enum ieee80211_self_protected_actioncode ftype;421426 size_t baselen;422427 bool deactivated, matches_local = true;423428 u8 ie_len;···444449 return;445450 }446451447447- baseaddr = mgmt->u.action.u.plink_action.variable;448448- baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;449449- if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {452452+ baseaddr = mgmt->u.action.u.self_prot.variable;453453+ baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;454454+ if (mgmt->u.action.u.self_prot.action_code ==455455+ WLAN_SP_MESH_PEERING_CONFIRM) {450456 baseaddr += 4;451457 baselen += 4;452458 }453459 ieee802_11_parse_elems(baseaddr, len - baselen, &elems);454454- if (!elems.peer_link) {460460+ if (!elems.peering) {455461 mpl_dbg("Mesh plink: missing necessary peer link ie\n");456462 return;457463 }···462466 return;463467 }464468465465- ftype = mgmt->u.action.u.plink_action.action_code;466466- ie_len = elems.peer_link_len;467467- if ((ftype == PLINK_OPEN && ie_len != 6) ||468468- (ftype == PLINK_CONFIRM && ie_len != 8) ||469469- (ftype == PLINK_CLOSE && ie_len != 8 && ie_len != 10)) {469469+ ftype = mgmt->u.action.u.self_prot.action_code;470470+ ie_len = elems.peering_len;471471+ if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||472472+ (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||473473+ (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6474474+ && ie_len != 8)) {470475 mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",471476 ftype, ie_len);472477 return;473478 }474479475475- if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {480480+ if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&481481+ (!elems.mesh_id || !elems.mesh_config)) {476482 mpl_dbg("Mesh plink: missing necessary ie\n");477483 return;478484 }479485 /* Note the lines below are correct, the llid in the frame is the plid480486 * from the point of view of this host.481487 */482482- memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);483483- if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10))484484- memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);488488+ memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);489489+ if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||490490+ (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))491491+ memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);485492486493 rcu_read_lock();487494488495 sta = sta_info_get(sdata, mgmt->sa);489489- if (!sta && ftype != PLINK_OPEN) {496496+ if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {490497 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");491498 rcu_read_unlock();492499 return;···508509509510 /* Now we will figure out the appropriate event... */510511 event = PLINK_UNDEFINED;511511- if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) {512512+ if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&513513+ (!mesh_matches_local(&elems, sdata))) {512514 matches_local = false;513515 switch (ftype) {514514- case PLINK_OPEN:516516+ case WLAN_SP_MESH_PEERING_OPEN:515517 event = OPN_RJCT;516518 break;517517- case PLINK_CONFIRM:519519+ case WLAN_SP_MESH_PEERING_CONFIRM:518520 event = CNF_RJCT;519521 break;520520- case PLINK_CLOSE:521521- /* avoid warning */522522+ default:522523 break;523524 }524525 }525526526527 if (!sta && !matches_local) {527528 rcu_read_unlock();528528- reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);529529+ reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);529530 llid = 0;530530- mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid,531531- plid, reason);531531+ mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,532532+ mgmt->sa, llid, plid, reason);532533 return;533534 } else if (!sta) {534534- /* ftype == PLINK_OPEN */535535+ /* ftype == WLAN_SP_MESH_PEERING_OPEN */535536 u32 rates;536537537538 rcu_read_unlock();···556557 } else if (matches_local) {557558 spin_lock_bh(&sta->lock);558559 switch (ftype) {559559- case PLINK_OPEN:560560+ case WLAN_SP_MESH_PEERING_OPEN:560561 if (!mesh_plink_free_count(sdata) ||561562 (sta->plid && sta->plid != plid))562563 event = OPN_IGNR;563564 else564565 event = OPN_ACPT;565566 break;566566- case PLINK_CONFIRM:567567+ case WLAN_SP_MESH_PEERING_CONFIRM:567568 if (!mesh_plink_free_count(sdata) ||568569 (sta->llid != llid || sta->plid != plid))569570 event = CNF_IGNR;570571 else571572 event = CNF_ACPT;572573 break;573573- case PLINK_CLOSE:574574+ case WLAN_SP_MESH_PEERING_CLOSE:574575 if (sta->plink_state == NL80211_PLINK_ESTAB)575576 /* Do not check for llid or plid. This does not576577 * follow the standard but since multiple plinks···619620 sta->llid = llid;620621 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));621622 spin_unlock_bh(&sta->lock);622622- mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid,623623- 0, 0);624624- mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr,625625- llid, plid, 0);623623+ mesh_plink_frame_tx(sdata,624624+ WLAN_SP_MESH_PEERING_OPEN,625625+ sta->sta.addr, llid, 0, 0);626626+ mesh_plink_frame_tx(sdata,627627+ WLAN_SP_MESH_PEERING_CONFIRM,628628+ sta->sta.addr, llid, plid, 0);626629 break;627630 default:628631 spin_unlock_bh(&sta->lock);···636635 switch (event) {637636 case OPN_RJCT:638637 case CNF_RJCT:639639- reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);638638+ reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);640639 case CLS_ACPT:641640 if (!reason)642642- reason = cpu_to_le16(MESH_CLOSE_RCVD);641641+ reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);643642 sta->reason = reason;644643 sta->plink_state = NL80211_PLINK_HOLDING;645644 if (!mod_plink_timer(sta,···648647649648 llid = sta->llid;650649 spin_unlock_bh(&sta->lock);651651- mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,652652- plid, reason);650650+ mesh_plink_frame_tx(sdata,651651+ WLAN_SP_MESH_PEERING_CLOSE,652652+ sta->sta.addr, llid, plid, reason);653653 break;654654 case OPN_ACPT:655655 /* retry timer is left untouched */···658656 sta->plid = plid;659657 llid = sta->llid;660658 spin_unlock_bh(&sta->lock);661661- mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,662662- plid, 0);659659+ mesh_plink_frame_tx(sdata,660660+ WLAN_SP_MESH_PEERING_CONFIRM,661661+ sta->sta.addr, llid, plid, 0);663662 break;664663 case CNF_ACPT:665664 sta->plink_state = NL80211_PLINK_CNF_RCVD;···680677 switch (event) {681678 case OPN_RJCT:682679 case CNF_RJCT:683683- reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);680680+ reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);684681 case CLS_ACPT:685682 if (!reason)686686- reason = cpu_to_le16(MESH_CLOSE_RCVD);683683+ reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);687684 sta->reason = reason;688685 sta->plink_state = NL80211_PLINK_HOLDING;689686 if (!mod_plink_timer(sta,···692689693690 llid = sta->llid;694691 spin_unlock_bh(&sta->lock);695695- mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,696696- plid, reason);692692+ mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,693693+ sta->sta.addr, llid, plid, reason);697694 break;698695 case OPN_ACPT:699696 llid = sta->llid;700697 spin_unlock_bh(&sta->lock);701701- mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,702702- plid, 0);698698+ mesh_plink_frame_tx(sdata,699699+ WLAN_SP_MESH_PEERING_CONFIRM,700700+ sta->sta.addr, llid, plid, 0);703701 break;704702 case CNF_ACPT:705703 del_timer(&sta->plink_timer);···721717 switch (event) {722718 case OPN_RJCT:723719 case CNF_RJCT:724724- reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);720720+ reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);725721 case CLS_ACPT:726722 if (!reason)727727- reason = cpu_to_le16(MESH_CLOSE_RCVD);723723+ reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);728724 sta->reason = reason;729725 sta->plink_state = NL80211_PLINK_HOLDING;730726 if (!mod_plink_timer(sta,···733729734730 llid = sta->llid;735731 spin_unlock_bh(&sta->lock);736736- mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,737737- plid, reason);732732+ mesh_plink_frame_tx(sdata,733733+ WLAN_SP_MESH_PEERING_CLOSE,734734+ sta->sta.addr, llid, plid, reason);738735 break;739736 case OPN_ACPT:740737 del_timer(&sta->plink_timer);···745740 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);746741 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",747742 sta->sta.addr);748748- mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,749749- plid, 0);743743+ mesh_plink_frame_tx(sdata,744744+ WLAN_SP_MESH_PEERING_CONFIRM,745745+ sta->sta.addr, llid, plid, 0);750746 break;751747 default:752748 spin_unlock_bh(&sta->lock);···758752 case NL80211_PLINK_ESTAB:759753 switch (event) {760754 case CLS_ACPT:761761- reason = cpu_to_le16(MESH_CLOSE_RCVD);755755+ reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);762756 sta->reason = reason;763757 deactivated = __mesh_plink_deactivate(sta);764758 sta->plink_state = NL80211_PLINK_HOLDING;···767761 spin_unlock_bh(&sta->lock);768762 if (deactivated)769763 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);770770- mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,771771- plid, reason);764764+ mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,765765+ sta->sta.addr, llid, plid, reason);772766 break;773767 case OPN_ACPT:774768 llid = sta->llid;775769 spin_unlock_bh(&sta->lock);776776- mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,777777- plid, 0);770770+ mesh_plink_frame_tx(sdata,771771+ WLAN_SP_MESH_PEERING_CONFIRM,772772+ sta->sta.addr, llid, plid, 0);778773 break;779774 default:780775 spin_unlock_bh(&sta->lock);···797790 llid = sta->llid;798791 reason = sta->reason;799792 spin_unlock_bh(&sta->lock);800800- mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr,801801- llid, plid, reason);793793+ mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,794794+ sta->sta.addr, llid, plid, reason);802795 break;803796 default:804797 spin_unlock_bh(&sta->lock);
+53-6
net/mac80211/mlme.c
···1482148214831483 ifmgd->aid = aid;1484148414851485- sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);14861486- if (!sta) {14871487- printk(KERN_DEBUG "%s: failed to alloc STA entry for"14881488- " the AP\n", sdata->name);14851485+ mutex_lock(&sdata->local->sta_mtx);14861486+ /*14871487+ * station info was already allocated and inserted before14881488+ * the association and should be available to us14891489+ */14901490+ sta = sta_info_get_rx(sdata, cbss->bssid);14911491+ if (WARN_ON(!sta)) {14921492+ mutex_unlock(&sdata->local->sta_mtx);14891493 return false;14901494 }14911495···15601556 if (elems.wmm_param)15611557 set_sta_flags(sta, WLAN_STA_WME);1562155815631563- err = sta_info_insert(sta);15591559+ /* sta_info_reinsert will also unlock the mutex lock */15601560+ err = sta_info_reinsert(sta);15641561 sta = NULL;15651562 if (err) {15661563 printk(KERN_DEBUG "%s: failed to insert STA entry for"···24342429 return 0;24352430}2436243124322432+/* create and insert a dummy station entry */24332433+static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata,24342434+ u8 *bssid) {24352435+ struct sta_info *sta;24362436+ int err;24372437+24382438+ sta = sta_info_alloc(sdata, bssid, GFP_KERNEL);24392439+ if (!sta) {24402440+ printk(KERN_DEBUG "%s: failed to alloc STA entry for"24412441+ " the AP\n", sdata->name);24422442+ return -ENOMEM;24432443+ }24442444+24452445+ sta->dummy = true;24462446+24472447+ err = sta_info_insert(sta);24482448+ sta = NULL;24492449+ if (err) {24502450+ printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for"24512451+ " the AP (error %d)\n", sdata->name, err);24522452+ return err;24532453+ }24542454+24552455+ return 0;24562456+}24572457+24372458static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,24382459 struct sk_buff *skb)24392460{···24672436 struct ieee80211_mgmt *mgmt;24682437 struct ieee80211_rx_status *rx_status;24692438 struct ieee802_11_elems elems;24392439+ struct cfg80211_bss *cbss = wk->assoc.bss;24702440 u16 status;2471244124722442 if (!skb) {24432443+ sta_info_destroy_addr(wk->sdata, cbss->bssid);24732444 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);24742445 goto destroy;24752446 }···25012468 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {25022469 mutex_unlock(&wk->sdata->u.mgd.mtx);25032470 /* oops -- internal error -- send timeout for now */24712471+ sta_info_destroy_addr(wk->sdata, cbss->bssid);25042472 cfg80211_send_assoc_timeout(wk->sdata->dev,25052473 wk->filter_ta);25062474 return WORK_DONE_DESTROY;25072475 }2508247625092477 mutex_unlock(&wk->sdata->u.mgd.mtx);24782478+ } else {24792479+ /* assoc failed - destroy the dummy station entry */24802480+ sta_info_destroy_addr(wk->sdata, cbss->bssid);25102481 }2511248225122483 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);···25292492 struct ieee80211_bss *bss = (void *)req->bss->priv;25302493 struct ieee80211_work *wk;25312494 const u8 *ssid;25322532- int i;24952495+ int i, err;2533249625342497 mutex_lock(&ifmgd->mtx);25352498 if (ifmgd->associated) {···25532516 wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL);25542517 if (!wk)25552518 return -ENOMEM;25192519+25202520+ /*25212521+ * create a dummy station info entry in order25222522+ * to start accepting incoming EAPOL packets from the station25232523+ */25242524+ err = ieee80211_pre_assoc(sdata, req->bss->bssid);25252525+ if (err) {25262526+ kfree(wk);25272527+ return err;25282528+ }2556252925572530 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;25582531 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
+40-8
net/mac80211/rx.c
···850850 ieee80211_is_pspoll(hdr->frame_control)) &&851851 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&852852 rx->sdata->vif.type != NL80211_IFTYPE_WDS &&853853- (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC))))853853+ (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {854854+ if (rx->sta && rx->sta->dummy &&855855+ ieee80211_is_data_present(hdr->frame_control)) {856856+ u16 ethertype;857857+ u8 *payload;858858+859859+ payload = rx->skb->data +860860+ ieee80211_hdrlen(hdr->frame_control);861861+ ethertype = (payload[6] << 8) | payload[7];862862+ if (cpu_to_be16(ethertype) ==863863+ rx->sdata->control_port_protocol)864864+ return RX_CONTINUE;865865+ }854866 return RX_DROP_MONITOR;867867+ }855868856869 return RX_CONTINUE;857870}···22332220 goto handled;22342221 }22352222 break;22232223+ case WLAN_CATEGORY_SELF_PROTECTED:22242224+ switch (mgmt->u.action.u.self_prot.action_code) {22252225+ case WLAN_SP_MESH_PEERING_OPEN:22262226+ case WLAN_SP_MESH_PEERING_CLOSE:22272227+ case WLAN_SP_MESH_PEERING_CONFIRM:22282228+ if (!ieee80211_vif_is_mesh(&sdata->vif))22292229+ goto invalid;22302230+ if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)22312231+ /* userspace handles this frame */22322232+ break;22332233+ goto queue;22342234+ case WLAN_SP_MGK_INFORM:22352235+ case WLAN_SP_MGK_ACK:22362236+ if (!ieee80211_vif_is_mesh(&sdata->vif))22372237+ goto invalid;22382238+ break;22392239+ }22402240+ break;22362241 case WLAN_CATEGORY_MESH_ACTION:22372242 if (!ieee80211_vif_is_mesh(&sdata->vif))22382243 break;22392239- goto queue;22402240- case WLAN_CATEGORY_MESH_PATH_SEL:22412241- if (!mesh_path_sel_is_hwmp(sdata))22442244+ if (mesh_action_is_path_sel(mgmt) &&22452245+ (!mesh_path_sel_is_hwmp(sdata)))22422246 break;22432247 goto queue;22442248 }···27162686 } else if (!ieee80211_bssid_match(bssid,27172687 sdata->vif.addr)) {27182688 if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&27192719- !ieee80211_is_beacon(hdr->frame_control))26892689+ !ieee80211_is_beacon(hdr->frame_control) &&26902690+ !(ieee80211_is_action(hdr->frame_control) &&26912691+ sdata->vif.p2p))27202692 return 0;27212693 status->rx_flags &= ~IEEE80211_RX_RA_MATCH;27222694 }···28232791 if (ieee80211_is_data(fc)) {28242792 prev_sta = NULL;2825279328262826- for_each_sta_info(local, hdr->addr2, sta, tmp) {27942794+ for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {28272795 if (!prev_sta) {28282796 prev_sta = sta;28292797 continue;···28672835 continue;28682836 }2869283728702870- rx.sta = sta_info_get_bss(prev, hdr->addr2);28382838+ rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);28712839 rx.sdata = prev;28722840 ieee80211_prepare_and_rx_handle(&rx, skb, false);28732841···28752843 }2876284428772845 if (prev) {28782878- rx.sta = sta_info_get_bss(prev, hdr->addr2);28462846+ rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);28792847 rx.sdata = prev;2880284828812849 if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
+241-111
net/mac80211/sta_info.c
···100100 lockdep_is_held(&local->sta_lock) ||101101 lockdep_is_held(&local->sta_mtx));102102 while (sta) {103103+ if (sta->sdata == sdata && !sta->dummy &&104104+ memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)105105+ break;106106+ sta = rcu_dereference_check(sta->hnext,107107+ lockdep_is_held(&local->sta_lock) ||108108+ lockdep_is_held(&local->sta_mtx));109109+ }110110+ return sta;111111+}112112+113113+/* get a station info entry even if it is a dummy station*/114114+struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,115115+ const u8 *addr)116116+{117117+ struct ieee80211_local *local = sdata->local;118118+ struct sta_info *sta;119119+120120+ sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],121121+ lockdep_is_held(&local->sta_lock) ||122122+ lockdep_is_held(&local->sta_mtx));123123+ while (sta) {103124 if (sta->sdata == sdata &&104125 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)105126 break;···136115 * or from one of its vlans137116 */138117struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,118118+ const u8 *addr)119119+{120120+ struct ieee80211_local *local = sdata->local;121121+ struct sta_info *sta;122122+123123+ sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],124124+ lockdep_is_held(&local->sta_lock) ||125125+ lockdep_is_held(&local->sta_mtx));126126+ while (sta) {127127+ if ((sta->sdata == sdata ||128128+ (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&129129+ !sta->dummy &&130130+ memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)131131+ break;132132+ sta = rcu_dereference_check(sta->hnext,133133+ lockdep_is_held(&local->sta_lock) ||134134+ lockdep_is_held(&local->sta_mtx));135135+ }136136+ return sta;137137+}138138+139139+/*140140+ * Get sta info either from the specified interface141141+ * or from one of its vlans (including dummy stations)142142+ */143143+struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,139144 const u8 *addr)140145{141146 struct ieee80211_local *local = sdata->local;···327280 return sta;328281}329282330330-static int sta_info_finish_insert(struct sta_info *sta, bool async)283283+static int sta_info_finish_insert(struct sta_info *sta,284284+ bool async, bool dummy_reinsert)331285{332286 struct ieee80211_local *local = sta->local;333287 struct ieee80211_sub_if_data *sdata = sta->sdata;···338290339291 lockdep_assert_held(&local->sta_mtx);340292341341- /* notify driver */342342- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)343343- sdata = container_of(sdata->bss,344344- struct ieee80211_sub_if_data,345345- u.ap);346346- err = drv_sta_add(local, sdata, &sta->sta);347347- if (err) {348348- if (!async)349349- return err;350350- printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)"351351- " - keeping it anyway.\n",352352- sdata->name, sta->sta.addr, err);353353- } else {354354- sta->uploaded = true;293293+ if (!sta->dummy || dummy_reinsert) {294294+ /* notify driver */295295+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)296296+ sdata = container_of(sdata->bss,297297+ struct ieee80211_sub_if_data,298298+ u.ap);299299+ err = drv_sta_add(local, sdata, &sta->sta);300300+ if (err) {301301+ if (!async)302302+ return err;303303+ printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "304304+ "driver (%d) - keeping it anyway.\n",305305+ sdata->name, sta->sta.addr, err);306306+ } else {307307+ sta->uploaded = true;355308#ifdef CONFIG_MAC80211_VERBOSE_DEBUG356356- if (async)357357- wiphy_debug(local->hw.wiphy,358358- "Finished adding IBSS STA %pM\n",359359- sta->sta.addr);309309+ if (async)310310+ wiphy_debug(local->hw.wiphy,311311+ "Finished adding IBSS STA %pM\n",312312+ sta->sta.addr);360313#endif314314+ }315315+316316+ sdata = sta->sdata;361317 }362318363363- sdata = sta->sdata;319319+ if (!dummy_reinsert) {320320+ if (!async) {321321+ local->num_sta++;322322+ local->sta_generation++;323323+ smp_mb();364324365365- if (!async) {366366- local->num_sta++;367367- local->sta_generation++;368368- smp_mb();325325+ /* make the station visible */326326+ spin_lock_irqsave(&local->sta_lock, flags);327327+ sta_info_hash_add(local, sta);328328+ spin_unlock_irqrestore(&local->sta_lock, flags);329329+ }369330370370- /* make the station visible */371371- spin_lock_irqsave(&local->sta_lock, flags);372372- sta_info_hash_add(local, sta);373373- spin_unlock_irqrestore(&local->sta_lock, flags);331331+ list_add(&sta->list, &local->sta_list);332332+ } else {333333+ sta->dummy = false;374334 }375335376376- list_add(&sta->list, &local->sta_list);336336+ if (!sta->dummy) {337337+ ieee80211_sta_debugfs_add(sta);338338+ rate_control_add_sta_debugfs(sta);377339378378- ieee80211_sta_debugfs_add(sta);379379- rate_control_add_sta_debugfs(sta);380380-381381- memset(&sinfo, 0, sizeof(sinfo));382382- sinfo.filled = 0;383383- sinfo.generation = local->sta_generation;384384- cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);385385-340340+ memset(&sinfo, 0, sizeof(sinfo));341341+ sinfo.filled = 0;342342+ sinfo.generation = local->sta_generation;343343+ cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);344344+ }386345387346 return 0;388347}···406351 list_del(&sta->list);407352 spin_unlock_irqrestore(&local->sta_lock, flags);408353409409- sta_info_finish_insert(sta, true);354354+ sta_info_finish_insert(sta, true, false);410355411356 spin_lock_irqsave(&local->sta_lock, flags);412357 }···423368 mutex_unlock(&local->sta_mtx);424369}425370426426-int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)371371+static int sta_info_insert_check(struct sta_info *sta)427372{428428- struct ieee80211_local *local = sta->local;429373 struct ieee80211_sub_if_data *sdata = sta->sdata;430430- unsigned long flags;431431- int err = 0;432374433375 /*434376 * Can't be a WARN_ON because it can be triggered through a race:435377 * something inserts a STA (on one CPU) without holding the RTNL436378 * and another CPU turns off the net device.437379 */438438- if (unlikely(!ieee80211_sdata_running(sdata))) {439439- err = -ENETDOWN;440440- rcu_read_lock();441441- goto out_free;442442- }380380+ if (unlikely(!ieee80211_sdata_running(sdata)))381381+ return -ENETDOWN;443382444383 if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 ||445445- is_multicast_ether_addr(sta->sta.addr))) {446446- err = -EINVAL;384384+ is_multicast_ether_addr(sta->sta.addr)))385385+ return -EINVAL;386386+387387+ return 0;388388+}389389+390390+static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU)391391+{392392+ struct ieee80211_local *local = sta->local;393393+ struct ieee80211_sub_if_data *sdata = sta->sdata;394394+ unsigned long flags;395395+396396+ spin_lock_irqsave(&local->sta_lock, flags);397397+ /* check if STA exists already */398398+ if (sta_info_get_bss_rx(sdata, sta->sta.addr)) {399399+ spin_unlock_irqrestore(&local->sta_lock, flags);400400+ rcu_read_lock();401401+ return -EEXIST;402402+ }403403+404404+ local->num_sta++;405405+ local->sta_generation++;406406+ smp_mb();407407+ sta_info_hash_add(local, sta);408408+409409+ list_add_tail(&sta->list, &local->sta_pending_list);410410+411411+ rcu_read_lock();412412+ spin_unlock_irqrestore(&local->sta_lock, flags);413413+414414+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG415415+ wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n",416416+ sta->sta.addr);417417+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */418418+419419+ ieee80211_queue_work(&local->hw, &local->sta_finish_work);420420+421421+ return 0;422422+}423423+424424+/*425425+ * should be called with sta_mtx locked426426+ * this function replaces the mutex lock427427+ * with a RCU lock428428+ */429429+static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)430430+{431431+ struct ieee80211_local *local = sta->local;432432+ struct ieee80211_sub_if_data *sdata = sta->sdata;433433+ unsigned long flags;434434+ struct sta_info *exist_sta;435435+ bool dummy_reinsert = false;436436+ int err = 0;437437+438438+ lockdep_assert_held(&local->sta_mtx);439439+440440+ /*441441+ * On first glance, this will look racy, because the code442442+ * in this function, which inserts a station with sleeping,443443+ * unlocks the sta_lock between checking existence in the444444+ * hash table and inserting into it.445445+ *446446+ * However, it is not racy against itself because it keeps447447+ * the mutex locked.448448+ */449449+450450+ spin_lock_irqsave(&local->sta_lock, flags);451451+ /*452452+ * check if STA exists already.453453+ * only accept a scenario of a second call to sta_info_insert_non_ibss454454+ * with a dummy station entry that was inserted earlier455455+ * in that case - assume that the dummy station flag should456456+ * be removed.457457+ */458458+ exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr);459459+ if (exist_sta) {460460+ if (exist_sta == sta && sta->dummy) {461461+ dummy_reinsert = true;462462+ } else {463463+ spin_unlock_irqrestore(&local->sta_lock, flags);464464+ mutex_unlock(&local->sta_mtx);465465+ rcu_read_lock();466466+ return -EEXIST;467467+ }468468+ }469469+470470+ spin_unlock_irqrestore(&local->sta_lock, flags);471471+472472+ err = sta_info_finish_insert(sta, false, dummy_reinsert);473473+ if (err) {474474+ mutex_unlock(&local->sta_mtx);475475+ rcu_read_lock();476476+ return err;477477+ }478478+479479+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG480480+ wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n",481481+ sta->dummy ? "dummy " : "", sta->sta.addr);482482+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */483483+484484+ /* move reference to rcu-protected */485485+ rcu_read_lock();486486+ mutex_unlock(&local->sta_mtx);487487+488488+ if (ieee80211_vif_is_mesh(&sdata->vif))489489+ mesh_accept_plinks_update(sdata);490490+491491+ return 0;492492+}493493+494494+int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)495495+{496496+ struct ieee80211_local *local = sta->local;497497+ struct ieee80211_sub_if_data *sdata = sta->sdata;498498+ int err = 0;499499+500500+ err = sta_info_insert_check(sta);501501+ if (err) {447502 rcu_read_lock();448503 goto out_free;449504 }···564399 * always do so in that case -- see the comment below.565400 */566401 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {567567- spin_lock_irqsave(&local->sta_lock, flags);568568- /* check if STA exists already */569569- if (sta_info_get_bss(sdata, sta->sta.addr)) {570570- spin_unlock_irqrestore(&local->sta_lock, flags);571571- rcu_read_lock();572572- err = -EEXIST;402402+ err = sta_info_insert_ibss(sta);403403+ if (err)573404 goto out_free;574574- }575575-576576- local->num_sta++;577577- local->sta_generation++;578578- smp_mb();579579- sta_info_hash_add(local, sta);580580-581581- list_add_tail(&sta->list, &local->sta_pending_list);582582-583583- rcu_read_lock();584584- spin_unlock_irqrestore(&local->sta_lock, flags);585585-586586-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG587587- wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n",588588- sta->sta.addr);589589-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */590590-591591- ieee80211_queue_work(&local->hw, &local->sta_finish_work);592405593406 return 0;594407 }595408596409 /*597597- * On first glance, this will look racy, because the code598598- * below this point, which inserts a station with sleeping,599599- * unlocks the sta_lock between checking existence in the600600- * hash table and inserting into it.601601- *602602- * However, it is not racy against itself because it keeps603603- * the mutex locked. It still seems to race against the604604- * above code that atomically inserts the station... That,410410+ * It might seem that the function called below is in race against411411+ * the function call above that atomically inserts the station... That,605412 * however, is not true because the above code can only606413 * be invoked for IBSS interfaces, and the below code will607414 * not be -- and the two do not race against each other as···584447585448 mutex_lock(&local->sta_mtx);586449587587- spin_lock_irqsave(&local->sta_lock, flags);588588- /* check if STA exists already */589589- if (sta_info_get_bss(sdata, sta->sta.addr)) {590590- spin_unlock_irqrestore(&local->sta_lock, flags);591591- mutex_unlock(&local->sta_mtx);592592- rcu_read_lock();593593- err = -EEXIST;450450+ err = sta_info_insert_non_ibss(sta);451451+ if (err)594452 goto out_free;595595- }596596-597597- spin_unlock_irqrestore(&local->sta_lock, flags);598598-599599- err = sta_info_finish_insert(sta, false);600600- if (err) {601601- mutex_unlock(&local->sta_mtx);602602- rcu_read_lock();603603- goto out_free;604604- }605605-606606-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG607607- wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);608608-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */609609-610610- /* move reference to rcu-protected */611611- rcu_read_lock();612612- mutex_unlock(&local->sta_mtx);613613-614614- if (ieee80211_vif_is_mesh(&sdata->vif))615615- mesh_accept_plinks_update(sdata);616453617454 return 0;618455 out_free:···601490602491 rcu_read_unlock();603492493493+ return err;494494+}495495+496496+/* Caller must hold sta->local->sta_mtx */497497+int sta_info_reinsert(struct sta_info *sta)498498+{499499+ struct ieee80211_local *local = sta->local;500500+ int err = 0;501501+502502+ err = sta_info_insert_check(sta);503503+ if (err) {504504+ mutex_unlock(&local->sta_mtx);505505+ return err;506506+ }507507+508508+ might_sleep();509509+510510+ err = sta_info_insert_non_ibss(sta);511511+ rcu_read_unlock();604512 return err;605513}606514···863733 int ret;864734865735 mutex_lock(&sdata->local->sta_mtx);866866- sta = sta_info_get(sdata, addr);736736+ sta = sta_info_get_rx(sdata, addr);867737 ret = __sta_info_destroy(sta);868738 mutex_unlock(&sdata->local->sta_mtx);869739···877747 int ret;878748879749 mutex_lock(&sdata->local->sta_mtx);880880- sta = sta_info_get_bss(sdata, addr);750750+ sta = sta_info_get_bss_rx(sdata, addr);881751 ret = __sta_info_destroy(sta);882752 mutex_unlock(&sdata->local->sta_mtx);883753
+29-1
net/mac80211/sta_info.h
···238238 * @plink_timer: peer link watch timer239239 * @plink_timer_was_running: used by suspend/resume to restore timers240240 * @debugfs: debug filesystem info241241- * @sta: station information we share with the driver242241 * @dead: set to true when sta is unlinked243242 * @uploaded: set to true when sta is uploaded to the driver244243 * @lost_packets: number of consecutive lost packets244244+ * @dummy: indicate a dummy station created for receiving245245+ * EAP frames before association246246+ * @sta: station information we share with the driver245247 */246248struct sta_info {247249 /* General information, mostly static */···337335#endif338336339337 unsigned int lost_packets;338338+339339+ /* should be right in front of sta to be in the same cache line */340340+ bool dummy;340341341342 /* keep last! */342343 struct ieee80211_sta sta;···441436struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,442437 const u8 *addr);443438439439+struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,440440+ const u8 *addr);441441+444442struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,443443+ const u8 *addr);444444+445445+struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,445446 const u8 *addr);446447447448static inline···459448}460449461450#define for_each_sta_info(local, _addr, _sta, nxt) \451451+ for ( /* initialise loop */ \452452+ _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\453453+ nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \454454+ /* typecheck */ \455455+ for_each_sta_info_type_check(local, (_addr), _sta, nxt),\456456+ /* continue condition */ \457457+ _sta; \458458+ /* advance loop */ \459459+ _sta = nxt, \460460+ nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \461461+ ) \462462+ /* run code only if address matches and it's not a dummy sta */ \463463+ if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \464464+ !_sta->dummy)465465+466466+#define for_each_sta_info_rx(local, _addr, _sta, nxt) \462467 for ( /* initialise loop */ \463468 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\464469 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \···511484int sta_info_insert(struct sta_info *sta);512485int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);513486int sta_info_insert_atomic(struct sta_info *sta);487487+int sta_info_reinsert(struct sta_info *sta);514488515489int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,516490 const u8 *addr);
+18
net/mac80211/status.c
···187187 int rates_idx = -1;188188 bool send_to_cooked;189189 bool acked;190190+ struct ieee80211_bar *bar;191191+ u16 tid;190192191193 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {192194 if (info->status.rates[i].idx < 0) {···243241 & IEEE80211_SCTL_SEQ);244242 ieee80211_send_bar(sta->sdata, hdr->addr1,245243 tid, ssn);244244+ }245245+246246+ if (!acked && ieee80211_is_back_req(fc)) {247247+ /*248248+ * BAR failed, let's tear down the BA session as a249249+ * last resort as some STAs (Intel 5100 on Windows)250250+ * can get stuck when the BA window isn't flushed251251+ * correctly.252252+ */253253+ bar = (struct ieee80211_bar *) skb->data;254254+ if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {255255+ tid = (bar->control &256256+ IEEE80211_BAR_CTRL_TID_INFO_MASK) >>257257+ IEEE80211_BAR_CTRL_TID_INFO_SHIFT;258258+ ieee80211_stop_tx_ba_session(&sta->sta, tid);259259+ }246260 }247261248262 if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {