From: Nicolas Thill Date: Tue, 28 Apr 2009 00:14:31 +0000 (+0000) Subject: [package] madwifi: sync with trunk X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;h=4734f7b7ac1d456cefedf57de8ce47c2ef642f0d [package] madwifi: sync with trunk SVN-Revision: 15465 --- diff --git a/package/madwifi/Config.in b/package/madwifi/Config.in index 0a5412a74f..126639552a 100644 --- a/package/madwifi/Config.in +++ b/package/madwifi/Config.in @@ -16,6 +16,7 @@ config MADWIFI_STABLE bool "Use the OpenWrt stable version of madwifi" config MADWIFI_UPSTREAM + depends BROKEN depends !LINUX_2_6_26 depends !TARGET_atheros bool "Use the upstream release version 0.9.4" diff --git a/package/madwifi/Makefile b/package/madwifi/Makefile index 22aa904f8b..f787ffb4c2 100644 --- a/package/madwifi/Makefile +++ b/package/madwifi/Makefile @@ -13,7 +13,7 @@ PKG_NAME:=madwifi ifneq ($(CONFIG_MADWIFI_UPSTREAM),) PKG_VERSION:=0.9.4 - PKG_RELEASE:=2 + PKG_RELEASE:=2.1 PKG_SOURCE:=madwifi-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://downloads.sourceforge.net/madwifi/ @@ -26,7 +26,7 @@ else # PKG_BRANCH:=madwifi-dfs PKG_REV:=3314 PKG_VERSION:=r$(PKG_REV) - PKG_RELEASE:=2 + PKG_RELEASE:=2.1 PKG_SOURCE_PROTO:=svn PKG_SOURCE_VERSION:=$(PKG_REV) diff --git a/package/madwifi/files/lib/wifi/madwifi.sh b/package/madwifi/files/lib/wifi/madwifi.sh index eae82a7f04..8c4a75426e 100755 --- a/package/madwifi/files/lib/wifi/madwifi.sh +++ b/package/madwifi/files/lib/wifi/madwifi.sh @@ -42,7 +42,7 @@ scan_atheros() { *) echo "$device: Invalid mode combination in config"; return 1;; esac - config_set "$device" vifs "${ap:+$ap }${adhoc:+$adhoc }${ahdemo:+$ahdemo }${sta:+$sta }${wds:+$wds }${monitor:+$monitor}" + config_set "$device" vifs "${sta:+$sta }${ap:+$ap }${adhoc:+$adhoc }${ahdemo:+$ahdemo }${wds:+$wds }${monitor:+$monitor}" } @@ -67,6 +67,15 @@ disable_atheros() ( enable_atheros() { local device="$1" + # Can only set the country code to one setting for the entire system. The last country code is the one that will be applied. + config_get country "$device" country + [ -z "$country" ] && country="0" + local cc="0" + [ -e /proc/sys/dev/$device/countrycode ] && cc="$(cat /proc/sys/dev/$device/countrycode)" + if [ ! "$cc" = "$country" ] ; then + rmmod ath_pci + insmod ath_pci countrycode=$country + fi config_get channel "$device" channel config_get vifs "$device" vifs config_get txpower "$device" txpower @@ -111,10 +120,10 @@ enable_atheros() { *fh) hwmode=fh;; *) hwmode=auto;; esac - iwpriv "$ifname" mode "$hwmode" iwpriv "$ifname" pureg "$pureg" [ "$first" = 1 ] && { + iwpriv "$ifname" mode "$hwmode" iwconfig "$ifname" channel "$channel" >/dev/null 2>/dev/null } @@ -158,7 +167,7 @@ enable_atheros() { esac case "$mode" in - adhoc|ahdemo) + sta|adhoc|ahdemo) config_get addr "$vif" bssid [ -z "$addr" ] || { iwconfig "$ifname" ap "$addr" @@ -212,9 +221,6 @@ enable_atheros() { config_get distance "$device" distance [ -n "$distance" ] && athctrl -i "$device" -d "$distance" >&- - config_get txpwr "$vif" txpower - [ -n "$txpwr" ] && iwconfig "$ifname" txpower "${txpwr%%.*}" - config_get rate "$vif" rate [ -n "$rate" ] && iwconfig "$ifname" rate "${rate%%.*}" @@ -251,6 +257,9 @@ enable_atheros() { config_get_bool turbo "$vif" turbo [ -n "$turbo" ] && iwpriv "$ifname" turbo "$turbo" + config_get_bool beacon_power "$vif" beacon_power + [ -n "$beacon_power" ] && iwpriv "$ifname" beacon_pwr "$beacon_power" + config_get_bool doth "$vif" doth 0 [ -n "$doth" ] && iwpriv "$ifname" doth "$doth" @@ -281,6 +290,7 @@ enable_atheros() { esac ifconfig "$ifname" up + local net_cfg bridge net_cfg="$(find_net_config "$vif")" [ -z "$net_cfg" ] || { diff --git a/package/madwifi/patches/330-beaconcal.patch b/package/madwifi/patches/330-beaconcal.patch index 8556e0bb1d..2b4895f359 100644 --- a/package/madwifi/patches/330-beaconcal.patch +++ b/package/madwifi/patches/330-beaconcal.patch @@ -68,16 +68,18 @@ * Convert to a HAL channel description with the flags * constrained to reflect the current operating mode. */ -@@ -5154,6 +5178,8 @@ ath_beacon_send(struct ath_softc *sc, in +@@ -5154,6 +5178,10 @@ ath_beacon_send(struct ath_softc *sc, in "Invoking ath_hal_txstart with sc_bhalq: %d\n", sc->sc_bhalq); ath_hal_txstart(ah, sc->sc_bhalq); -+ if (sc->sc_beacon_cal && (jiffies > sc->sc_lastcal + (ath_calinterval * HZ))) -+ ath_calibrate((unsigned long) sc->sc_dev); ++ if (sc->sc_beacon_cal && (jiffies > sc->sc_lastcal + (ath_calinterval * HZ))) { ++ sc->sc_cal_ch.expires = jiffies + msecs_to_jiffies(10); ++ add_timer(&sc->sc_cal_ch); ++ } sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */ } -@@ -5403,6 +5429,7 @@ ath_beacon_config(struct ath_softc *sc, +@@ -5403,6 +5431,7 @@ ath_beacon_config(struct ath_softc *sc, ath_hal_beacontimers(ah, &bs); sc->sc_imask |= HAL_INT_BMISS; ath_hal_intrset(ah, sc->sc_imask); @@ -85,7 +87,7 @@ } else { ath_hal_intrset(ah, 0); if (reset_tsf) -@@ -5414,8 +5441,11 @@ ath_beacon_config(struct ath_softc *sc, +@@ -5414,8 +5443,11 @@ ath_beacon_config(struct ath_softc *sc, */ intval |= HAL_BEACON_ENA; sc->sc_imask |= HAL_INT_SWBA; @@ -98,7 +100,7 @@ #ifdef ATH_SUPERG_DYNTURBO ath_beacon_dturbo_config(vap, intval & ~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA)); -@@ -8879,6 +8909,9 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -8879,6 +8911,9 @@ ath_chan_set(struct ath_softc *sc, struc /* Enter DFS wait period */ mod_timer(&sc->sc_dfs_cac_timer, jiffies + (sc->sc_dfs_cac_period * HZ)); @@ -108,7 +110,7 @@ } /* * re configure beacons when it is a turbo mode switch. -@@ -8988,8 +9021,11 @@ ath_calibrate(unsigned long arg) +@@ -8988,8 +9023,11 @@ ath_calibrate(unsigned long arg) sc->sc_curchan.channel, sc->sc_curchan.channelFlags, isIQdone ? "done" : "not done"); @@ -122,7 +124,7 @@ } static void -@@ -9096,7 +9132,8 @@ ath_newstate(struct ieee80211vap *vap, e +@@ -9096,7 +9134,8 @@ ath_newstate(struct ieee80211vap *vap, e ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); @@ -132,7 +134,7 @@ ath_hal_setledstate(ah, leds[nstate]); /* set LED */ netif_stop_queue(dev); /* before we do anything else */ -@@ -9321,7 +9358,8 @@ ath_newstate(struct ieee80211vap *vap, e +@@ -9321,7 +9360,8 @@ ath_newstate(struct ieee80211vap *vap, e "VAP -> DFSWAIT_PENDING \n"); /* start calibration timer with a really small value * 1/10 sec */ @@ -142,7 +144,7 @@ /* wake the receiver */ netif_wake_queue(dev); /* don't do the other usual stuff... */ -@@ -9364,7 +9402,7 @@ done: +@@ -9364,7 +9404,7 @@ done: error = avp->av_newstate(vap, nstate, arg); /* Finally, start any timers. */ diff --git a/package/madwifi/patches/332-reset_beacons.patch b/package/madwifi/patches/332-reset_beacons.patch index 283f7f4f29..b776426f20 100644 --- a/package/madwifi/patches/332-reset_beacons.patch +++ b/package/madwifi/patches/332-reset_beacons.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8920,7 +8920,7 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -8922,7 +8922,7 @@ ath_chan_set(struct ath_softc *sc, struc * re configure beacons when it is a turbo mode switch. * HW seems to turn off beacons during turbo mode switch. */ diff --git a/package/madwifi/patches/343-txqueue_races.patch b/package/madwifi/patches/343-txqueue_races.patch index 4ae287e49d..a2b14d69a8 100644 --- a/package/madwifi/patches/343-txqueue_races.patch +++ b/package/madwifi/patches/343-txqueue_races.patch @@ -2,7 +2,7 @@ Merged from madwifi trunk r3551, r3552 --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8251,6 +8251,17 @@ ath_tx_processq(struct ath_softc *sc, st +@@ -8253,6 +8253,17 @@ ath_tx_processq(struct ath_softc *sc, st goto bf_fail; } diff --git a/package/madwifi/patches/345-minstrel_sampling.patch b/package/madwifi/patches/345-minstrel_sampling.patch index cf278a496f..d89990c837 100644 --- a/package/madwifi/patches/345-minstrel_sampling.patch +++ b/package/madwifi/patches/345-minstrel_sampling.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8101,6 +8101,7 @@ ath_tx_start(struct net_device *dev, str +@@ -8103,6 +8103,7 @@ ath_tx_start(struct net_device *dev, str ath_hal_setupxtxdesc(sc->sc_ah, ds, mrr.rate1, mrr.retries1, mrr.rate2, mrr.retries2, mrr.rate3, mrr.retries3); diff --git a/package/madwifi/patches/347-tuning.patch b/package/madwifi/patches/347-tuning.patch index ca005e7d76..1a73c42747 100644 --- a/package/madwifi/patches/347-tuning.patch +++ b/package/madwifi/patches/347-tuning.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -10274,11 +10274,11 @@ ath_setcurmode(struct ath_softc *sc, enu +@@ -10276,11 +10276,11 @@ ath_setcurmode(struct ath_softc *sc, enu sc->sc_currates = rt; sc->sc_curmode = mode; /* diff --git a/package/madwifi/patches/348-ackcts.patch b/package/madwifi/patches/348-ackcts.patch index 957e8ad55f..42b6fe2613 100644 --- a/package/madwifi/patches/348-ackcts.patch +++ b/package/madwifi/patches/348-ackcts.patch @@ -10,7 +10,7 @@ if (ar_device(sc->devid) == 5212 || ar_device(sc->devid) == 5213) { /* set ack to be sent at low bit-rate */ /* registers taken from the OpenBSD 5212 HAL */ -@@ -10789,8 +10792,13 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl +@@ -10791,8 +10794,13 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl break; #endif case ATH_ACKRATE: diff --git a/package/madwifi/patches/349-reset.patch b/package/madwifi/patches/349-reset.patch index 599948de0b..06e3fa86f7 100644 --- a/package/madwifi/patches/349-reset.patch +++ b/package/madwifi/patches/349-reset.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8862,8 +8862,7 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -8864,8 +8864,7 @@ ath_chan_set(struct ath_softc *sc, struc * needed to do the reset with chanchange = AH_FALSE in order * to receive traffic when peforming high velocity channel * changes. */ diff --git a/package/madwifi/patches/352-ani_fix.patch b/package/madwifi/patches/352-ani_fix.patch index af00f5e850..e8dce0cbe4 100644 --- a/package/madwifi/patches/352-ani_fix.patch +++ b/package/madwifi/patches/352-ani_fix.patch @@ -106,7 +106,7 @@ if (sc->sc_curchan.privFlags & CHANNEL_DFS) rfilt |= (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR); return rfilt; -@@ -6524,9 +6563,6 @@ process_rx_again: +@@ -6526,9 +6565,6 @@ process_rx_again: rs->rs_rssi = 0; len = rs->rs_datalen; @@ -116,7 +116,7 @@ if (rs->rs_more) { /* -@@ -8874,9 +8910,7 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -8876,9 +8912,7 @@ ath_chan_set(struct ath_softc *sc, struc if (sc->sc_softled) ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); @@ -127,7 +127,7 @@ sc->sc_curchan = hchan; ath_update_txpow(sc); /* update tx power state */ ath_radar_update(sc); -@@ -10653,9 +10687,54 @@ enum { +@@ -10655,9 +10689,54 @@ enum { ATH_RP_IGNORED = 24, ATH_RADAR_IGNORED = 25, ATH_MAXVAPS = 26, @@ -182,7 +182,7 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos) { struct ath_softc *sc = ctl->extra1; -@@ -10841,6 +10920,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl +@@ -10843,6 +10922,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl case ATH_RADAR_IGNORED: sc->sc_radar_ignored = val; break; @@ -194,7 +194,7 @@ default: ret = -EINVAL; break; -@@ -10907,6 +10991,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl +@@ -10909,6 +10993,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl case ATH_RADAR_IGNORED: val = sc->sc_radar_ignored; break; @@ -206,7 +206,7 @@ default: ret = -EINVAL; break; -@@ -11084,6 +11173,24 @@ static const ctl_table ath_sysctl_templa +@@ -11086,6 +11175,24 @@ static const ctl_table ath_sysctl_templa .proc_handler = ath_sysctl_halparam, .extra2 = (void *)ATH_RADAR_IGNORED, }, diff --git a/package/madwifi/patches/355-eap_auth_disassoc.patch b/package/madwifi/patches/355-eap_auth_disassoc.patch index 23cde7bcda..8bb1e93236 100644 --- a/package/madwifi/patches/355-eap_auth_disassoc.patch +++ b/package/madwifi/patches/355-eap_auth_disassoc.patch @@ -5,7 +5,7 @@ Signed-off-by: Felix Fietkau --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8332,6 +8332,14 @@ ath_tx_processq(struct ath_softc *sc, st +@@ -8334,6 +8334,14 @@ ath_tx_processq(struct ath_softc *sc, st #endif if (ts->ts_status & HAL_TXERR_XRETRY) { sc->sc_stats.ast_tx_xretries++; diff --git a/package/madwifi/patches/366-bstuck_thresh.patch b/package/madwifi/patches/366-bstuck_thresh.patch index f5a94c6b61..cde1f5c98c 100644 --- a/package/madwifi/patches/366-bstuck_thresh.patch +++ b/package/madwifi/patches/366-bstuck_thresh.patch @@ -41,7 +41,7 @@ ATH_SCHEDULE_TQUEUE(&sc->sc_bstucktq, needmark); return; } -@@ -5228,7 +5232,7 @@ ath_bstuck_tasklet(TQUEUE_ARG data) +@@ -5230,7 +5234,7 @@ ath_bstuck_tasklet(TQUEUE_ARG data) * check will be true, in which case return * without resetting the driver. */ diff --git a/package/madwifi/patches/370-wdsvap.patch b/package/madwifi/patches/370-wdsvap.patch index f35e657725..d68973737e 100644 --- a/package/madwifi/patches/370-wdsvap.patch +++ b/package/madwifi/patches/370-wdsvap.patch @@ -44,12 +44,13 @@ if (ic->ic_dev->flags & IFF_RUNNING) { /* needs to disable hardware too */ -@@ -1271,8 +1269,11 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1271,8 +1269,12 @@ ath_vap_create(struct ieee80211com *ic, } else ic_opmode = opmode; break; - case IEEE80211_M_HOSTAP: case IEEE80211_M_WDS: ++ ic_opmode = ic->ic_opmode; + if (!master) + return NULL; + break; @@ -57,7 +58,7 @@ /* permit multiple APs and/or WDS links */ /* XXX sta+ap for repeater/bridge application */ if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA)) -@@ -1304,7 +1305,7 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1304,7 +1306,7 @@ ath_vap_create(struct ieee80211com *ic, } avp = dev->priv; @@ -66,7 +67,7 @@ /* override with driver methods */ vap = &avp->av_vap; avp->av_newstate = vap->iv_newstate; -@@ -4209,8 +4210,7 @@ ath_calcrxfilter(struct ath_softc *sc) +@@ -4209,8 +4211,7 @@ ath_calcrxfilter(struct ath_softc *sc) if (ic->ic_opmode == IEEE80211_M_STA || sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */ (sc->sc_nostabeacons) || sc->sc_scanning || @@ -76,7 +77,7 @@ rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_nmonvaps > 0) rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON | -@@ -9030,8 +9030,6 @@ ath_calibrate(unsigned long arg) +@@ -9032,8 +9033,6 @@ ath_calibrate(unsigned long arg) * set sc->beacons if we might need to restart * them after ath_reset. */ if (!sc->sc_beacons && @@ -680,14 +681,10 @@ } break; case IEEE80211_M_IBSS: -@@ -540,16 +548,32 @@ ieee80211_input(struct ieee80211vap * va +@@ -540,16 +548,28 @@ ieee80211_input(struct ieee80211vap * va vap->iv_stats.is_rx_notassoc++; goto err; } -+ -+ /* subif isn't fully set up yet, drop the frame */ -+ if (ni->ni_subif == ni->ni_vap) -+ goto err; + /* * If we're a 4 address packet, make sure we have an entry in @@ -716,7 +713,7 @@ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) { IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, -@@ -557,7 +581,6 @@ ieee80211_input(struct ieee80211vap * va +@@ -557,7 +577,6 @@ ieee80211_input(struct ieee80211vap * va goto err; } wh4 = (struct ieee80211_frame_addr4 *)skb->data; @@ -724,7 +721,7 @@ ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4); /* Last call increments ref count if !NULL */ if ((ni_wds != NULL) && (ni_wds != ni)) { -@@ -608,6 +631,11 @@ ieee80211_input(struct ieee80211vap * va +@@ -608,6 +627,11 @@ ieee80211_input(struct ieee80211vap * va goto out; } @@ -736,7 +733,7 @@ /* * Handle privacy requirements. Note that we * must not be preempted from here until after -@@ -680,8 +708,12 @@ ieee80211_input(struct ieee80211vap * va +@@ -680,8 +704,12 @@ ieee80211_input(struct ieee80211vap * va if (! accept_data_frame(vap, ni, key, skb, eh)) goto out; @@ -751,15 +748,19 @@ IEEE80211_NODE_STAT(ni, rx_data); IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len); ic->ic_lastdata = jiffies; -@@ -1114,6 +1146,13 @@ ieee80211_deliver_data(struct ieee80211_ +@@ -1114,6 +1142,17 @@ ieee80211_deliver_data(struct ieee80211_ dev = vap->iv_xrvap->iv_dev; #endif + /* if the node has a wds subif, move data frames there, + * but keep EAP traffic on the master */ + if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE))) { -+ vap = ni->ni_subif; -+ dev = vap->iv_dev; ++ if (ni->ni_vap == ni->ni_subif) { ++ ieee80211_dev_kfree_skb(&skb); ++ } else { ++ vap = ni->ni_subif; ++ dev = vap->iv_dev; ++ } + } + /* perform as a bridge within the vap */ @@ -812,11 +813,10 @@ + (vap->iv_opmode == IEEE80211_M_WDS)) && + (scan.capinfo & IEEE80211_CAPINFO_ESS))) { + struct ieee80211vap *avp = NULL; ++ int found = 0; + + IEEE80211_LOCK_IRQ(vap->iv_ic); + if (vap->iv_opmode == IEEE80211_M_HOSTAP) { -+ int found = 0; -+ + TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) { + if (!memcmp(avp->wds_mac, wh->i_addr2, IEEE80211_ADDR_LEN)) { + if (avp->iv_state != IEEE80211_S_RUN) @@ -825,15 +825,16 @@ + break; + } + } -+ if (!found) -+ break; -+ -+ ni = ni_or_null = avp->iv_wdsnode; ++ if (found) ++ ni = ni_or_null = avp->iv_wdsnode; + } else if (vap->iv_opmode == IEEE80211_M_WDS) { ++ found = 1; + ni = ni_or_null = vap->iv_wdsnode; + } + IEEE80211_UNLOCK_IRQ(vap->iv_ic); + ++ if (!found) ++ break; + if (ni_or_null == NULL) { - /* Create a new entry in the neighbor table. */ @@ -902,7 +903,7 @@ } /* This is overridden by ath_node_alloc in ath/if_ath.c, and so -@@ -1134,6 +1145,62 @@ ieee80211_alloc_node(struct ieee80211vap +@@ -1134,6 +1145,65 @@ ieee80211_alloc_node(struct ieee80211vap return ni; } @@ -956,6 +957,9 @@ + if (ni->ni_subif) + return; + ++ if (!ni->ni_table) ++ return; ++ + ieee80211_ref_node(ni); + ni->ni_subif = ni->ni_vap; + IEEE80211_INIT_WORK(&ni->ni_create, ieee80211_wds_do_addif); @@ -965,7 +969,7 @@ /* Add wds address to the node table */ int #ifdef IEEE80211_DEBUG_REFCNT -@@ -1553,22 +1620,39 @@ ieee80211_find_rxnode(struct ieee80211co +@@ -1553,22 +1623,39 @@ ieee80211_find_rxnode(struct ieee80211co ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL) struct ieee80211_node_table *nt; struct ieee80211_node *ni; @@ -1014,7 +1018,7 @@ #endif IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); -@@ -1596,9 +1680,19 @@ ieee80211_find_txnode_debug(struct ieee8 +@@ -1596,9 +1683,19 @@ ieee80211_find_txnode_debug(struct ieee8 ieee80211_find_txnode(struct ieee80211vap *vap, const u_int8_t *mac) #endif { @@ -1034,7 +1038,7 @@ /* * The destination address should be in the node table * unless we are operating in station mode or this is a -@@ -1669,6 +1763,11 @@ ieee80211_free_node(struct ieee80211_nod +@@ -1669,6 +1766,11 @@ ieee80211_free_node(struct ieee80211_nod { struct ieee80211vap *vap = ni->ni_vap; @@ -1046,7 +1050,7 @@ atomic_dec(&ni->ni_ic->ic_node_counter); node_print_message(IEEE80211_MSG_NODE|IEEE80211_MSG_NODE_REF, 1 /* show counter */, -@@ -1781,22 +1880,6 @@ restart: +@@ -1781,22 +1883,6 @@ restart: jiffies > ni->ni_rxfragstamp + HZ) { ieee80211_dev_kfree_skb(&ni->ni_rxfrag); } @@ -1069,7 +1073,7 @@ ni->ni_inact--; if (ni->ni_associd != 0 || isadhoc) { struct ieee80211vap *vap = ni->ni_vap; -@@ -2263,6 +2346,36 @@ ieee80211_node_leave_11g(struct ieee8021 +@@ -2263,6 +2349,35 @@ ieee80211_node_leave_11g(struct ieee8021 } } @@ -1080,15 +1084,14 @@ + struct ieee80211vap *vap; + struct ieee80211com *ic; + ++ /* wait for full initialization before we start the teardown ++ * otherwise we could leak interfaces */ ++ while (ni->ni_subif == ni->ni_vap) ++ schedule(); ++ + rtnl_lock(); + vap = ni->ni_subif; + -+ /* if addif is waiting for the timer to fire, cancel! */ -+ if (vap == ni->ni_vap) { -+ ni->ni_subif = NULL; -+ goto done; -+ } -+ + if (!vap) + goto done; + @@ -1106,7 +1109,7 @@ /* * Handle bookkeeping for a station/neighbor leaving * the bss when operating in ap or adhoc modes. -@@ -2279,6 +2392,12 @@ ieee80211_node_leave(struct ieee80211_no +@@ -2279,6 +2394,12 @@ ieee80211_node_leave(struct ieee80211_no ni, "station with aid %d leaves (refcnt %u)", IEEE80211_NODE_AID(ni), atomic_read(&ni->ni_refcnt)); diff --git a/package/madwifi/patches/374-nbtt_fix.patch b/package/madwifi/patches/374-nbtt_fix.patch index b3237aef99..0a2982799f 100644 --- a/package/madwifi/patches/374-nbtt_fix.patch +++ b/package/madwifi/patches/374-nbtt_fix.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -5483,6 +5483,9 @@ ath_beacon_config(struct ath_softc *sc, +@@ -5486,6 +5486,9 @@ ath_beacon_config(struct ath_softc *sc, ath_beacon_dturbo_config(vap, intval & ~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA)); #endif diff --git a/package/madwifi/patches/375-atim_tsf_update.patch b/package/madwifi/patches/375-atim_tsf_update.patch index 64bd1c1973..9381f8a818 100644 --- a/package/madwifi/patches/375-atim_tsf_update.patch +++ b/package/madwifi/patches/375-atim_tsf_update.patch @@ -8,7 +8,7 @@ static int ath_desc_alloc(struct ath_softc *); static void ath_desc_free(struct ath_softc *); static void ath_desc_swap(struct ath_desc *); -@@ -2792,6 +2793,72 @@ ath_set_ack_bitrate(struct ath_softc *sc +@@ -2793,6 +2794,72 @@ ath_set_ack_bitrate(struct ath_softc *sc return 1; } @@ -81,7 +81,7 @@ /* * Reset the hardware w/o losing operational state. This is * basically a more efficient way of doing ath_stop, ath_init, -@@ -5291,6 +5358,7 @@ ath_beacon_config(struct ath_softc *sc, +@@ -5294,6 +5361,7 @@ ath_beacon_config(struct ath_softc *sc, u_int64_t tsf, hw_tsf; u_int32_t tsftu, hw_tsftu; u_int32_t intval, nexttbtt = 0; @@ -89,7 +89,7 @@ int reset_tsf = 0; if (vap == NULL) -@@ -5298,6 +5366,9 @@ ath_beacon_config(struct ath_softc *sc, +@@ -5301,6 +5369,9 @@ ath_beacon_config(struct ath_softc *sc, ni = vap->iv_bss; @@ -99,7 +99,7 @@ hw_tsf = ath_hal_gettsf64(ah); tsf = le64_to_cpu(ni->ni_tstamp.tsf); hw_tsftu = hw_tsf >> 10; -@@ -5487,15 +5558,27 @@ ath_beacon_config(struct ath_softc *sc, +@@ -5490,15 +5561,27 @@ ath_beacon_config(struct ath_softc *sc, <= ath_hal_sw_beacon_response_time) nexttbtt += intval; sc->sc_nexttbtt = nexttbtt; @@ -127,7 +127,7 @@ /* We print all debug messages here, in order to preserve the * time critical aspect of this function */ DPRINTF(sc, ATH_DEBUG_BEACON, -@@ -6398,6 +6481,11 @@ ath_recv_mgmt(struct ieee80211vap * vap, +@@ -6401,6 +6484,11 @@ ath_recv_mgmt(struct ieee80211vap * vap, DPRINTF(sc, ATH_DEBUG_BEACON, "Updated beacon timers\n"); } diff --git a/package/madwifi/patches/381-ibss_modes.patch b/package/madwifi/patches/381-ibss_modes.patch index ec04276dff..f904ed9721 100644 --- a/package/madwifi/patches/381-ibss_modes.patch +++ b/package/madwifi/patches/381-ibss_modes.patch @@ -12,7 +12,7 @@ break; case IEEE80211_M_AHDEMO: case IEEE80211_M_MONITOR: -@@ -1454,7 +1457,7 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1455,7 +1458,7 @@ ath_vap_create(struct ieee80211com *ic, * frames. Other modes carry over directly to the HAL. */ if (ic->ic_opmode == IEEE80211_M_AHDEMO) diff --git a/package/madwifi/patches/383-ibss_hostap.patch b/package/madwifi/patches/383-ibss_hostap.patch index 445f537373..a91753cc15 100644 --- a/package/madwifi/patches/383-ibss_hostap.patch +++ b/package/madwifi/patches/383-ibss_hostap.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -1451,6 +1451,23 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1452,6 +1452,23 @@ ath_vap_create(struct ieee80211com *ic, sc->sc_nstavaps++; else if (opmode == IEEE80211_M_MONITOR) sc->sc_nmonvaps++; @@ -24,7 +24,7 @@ /* * Adhoc demo mode is a pseudo mode; to the HAL it's * just IBSS mode and the driver doesn't use management -@@ -4278,7 +4295,8 @@ ath_calcrxfilter(struct ath_softc *sc) +@@ -4279,7 +4296,8 @@ ath_calcrxfilter(struct ath_softc *sc) if (ic->ic_opmode != IEEE80211_M_HOSTAP && (dev->flags & IFF_PROMISC)) rfilt |= HAL_RX_FILTER_PROM; if (ic->ic_opmode == IEEE80211_M_STA || @@ -34,7 +34,7 @@ (sc->sc_nostabeacons) || sc->sc_scanning || (ic->ic_opmode == IEEE80211_M_HOSTAP)) rfilt |= HAL_RX_FILTER_BEACON; -@@ -6432,6 +6450,33 @@ ath_capture(struct net_device *dev, cons +@@ -6435,6 +6453,33 @@ ath_capture(struct net_device *dev, cons } /* @@ -68,7 +68,7 @@ * Intercept management frames to collect beacon RSSI data and to do * ibss merges. This function is called for all management frames, * including those belonging to other BSS. -@@ -6484,10 +6529,19 @@ ath_recv_mgmt(struct ieee80211vap * vap, +@@ -6487,10 +6532,19 @@ ath_recv_mgmt(struct ieee80211vap * vap, DPRINTF(sc, ATH_DEBUG_BEACON, "Updated beacon timers\n"); } @@ -92,7 +92,7 @@ } /* NB: Fall Through */ case IEEE80211_FC0_SUBTYPE_PROBE_RESP: -@@ -6560,6 +6614,10 @@ ath_recv_mgmt(struct ieee80211vap * vap, +@@ -6563,6 +6617,10 @@ ath_recv_mgmt(struct ieee80211vap * vap, #endif if (do_merge) ieee80211_ibss_merge(ni); diff --git a/package/madwifi/patches/384-hwdetect.patch b/package/madwifi/patches/384-hwdetect.patch index aeaf8f6698..397b69c2e1 100644 --- a/package/madwifi/patches/384-hwdetect.patch +++ b/package/madwifi/patches/384-hwdetect.patch @@ -33,7 +33,7 @@ /* Allocate space for dynamically determined maximum VAP count */ sc->sc_bslot = kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL); -@@ -1507,6 +1519,28 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1508,6 +1520,28 @@ ath_vap_create(struct ieee80211com *ic, return vap; } @@ -62,7 +62,7 @@ static void ath_vap_delete(struct ieee80211vap *vap) { -@@ -10818,6 +10852,12 @@ ath_ioctl(struct net_device *dev, struct +@@ -10821,6 +10855,12 @@ ath_ioctl(struct net_device *dev, struct * is to add module parameters. */ @@ -75,7 +75,7 @@ /* * Dynamic (i.e. per-device) sysctls. These are automatically * mirrored in /proc/sys. -@@ -10897,6 +10937,38 @@ ath_sysctl_get_intmit(struct ath_softc * +@@ -10900,6 +10940,38 @@ ath_sysctl_get_intmit(struct ath_softc * } static int @@ -114,7 +114,7 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos) { struct ath_softc *sc = ctl->extra1; -@@ -11176,6 +11248,24 @@ static int maxint = 0x7fffffff; /* 32-b +@@ -11179,6 +11251,24 @@ static int maxint = 0x7fffffff; /* 32-b static const ctl_table ath_sysctl_template[] = { { .ctl_name = CTL_AUTO, diff --git a/package/madwifi/patches/385-antenna_fix.patch b/package/madwifi/patches/385-antenna_fix.patch index de4e9fe6bd..9e34304402 100644 --- a/package/madwifi/patches/385-antenna_fix.patch +++ b/package/madwifi/patches/385-antenna_fix.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -6665,6 +6665,7 @@ ath_setdefantenna(struct ath_softc *sc, +@@ -6668,6 +6668,7 @@ ath_setdefantenna(struct ath_softc *sc, struct ath_hal *ah = sc->sc_ah; /* XXX block beacon interrupts */ diff --git a/package/madwifi/patches/389-autochannel.patch b/package/madwifi/patches/389-autochannel.patch index 0e4cad873d..1c62285904 100644 --- a/package/madwifi/patches/389-autochannel.patch +++ b/package/madwifi/patches/389-autochannel.patch @@ -8,7 +8,7 @@ /* calibrate every 30 secs in steady state but check every second at first. */ static int ath_calinterval = ATH_SHORT_CALINTERVAL; -@@ -2579,6 +2580,7 @@ ath_init(struct net_device *dev) +@@ -2580,6 +2581,7 @@ ath_init(struct net_device *dev) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ @@ -16,7 +16,7 @@ sc->sc_curchan.channel = ic->ic_curchan->ic_freq; sc->sc_curchan.channelFlags = ath_chan2flags(ic->ic_curchan); if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan, AH_FALSE, &status)) { -@@ -2913,6 +2915,40 @@ ath_hw_check_atim(struct ath_softc *sc, +@@ -2914,6 +2916,40 @@ ath_hw_check_atim(struct ath_softc *sc, } @@ -57,7 +57,7 @@ /* * Reset the hardware w/o losing operational state. This is * basically a more efficient way of doing ath_stop, ath_init, -@@ -2939,6 +2975,7 @@ ath_reset(struct net_device *dev) +@@ -2940,6 +2976,7 @@ ath_reset(struct net_device *dev) * Convert to a HAL channel description with the flags * constrained to reflect the current operating mode. */ @@ -65,7 +65,7 @@ c = ic->ic_curchan; sc->sc_curchan.channel = c->ic_freq; sc->sc_curchan.channelFlags = ath_chan2flags(c); -@@ -9019,6 +9056,7 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -9022,6 +9059,7 @@ ath_chan_set(struct ath_softc *sc, struc u_int8_t channel_change_required = 0; struct timeval tv; diff --git a/package/madwifi/patches/391-vap_auth.patch b/package/madwifi/patches/391-vap_auth.patch new file mode 100644 index 0000000000..b317be0482 --- /dev/null +++ b/package/madwifi/patches/391-vap_auth.patch @@ -0,0 +1,29 @@ +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -1374,7 +1374,7 @@ ieee80211_auth_open(struct ieee80211_nod + vap->iv_stats.is_rx_bad_auth++; /* XXX maybe a unique error? */ + if (vap->iv_opmode == IEEE80211_M_HOSTAP) { + if (ni == vap->iv_bss) { +- ni = ieee80211_dup_bss(vap, wh->i_addr2, 0); ++ ni = ieee80211_dup_bss(vap, wh->i_addr2, 1); + if (ni == NULL) + return; + tmpnode = 1; +@@ -1762,6 +1762,8 @@ ieee80211_ssid_mismatch(struct ieee80211 + } + + #define IEEE80211_VERIFY_SSID(_ni, _ssid) do { \ ++ if ((_ni)->ni_esslen == 0) \ ++ return; \ + if ((_ssid)[1] != 0 && \ + ((_ssid)[1] != (_ni)->ni_esslen || \ + memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \ +@@ -1776,6 +1778,8 @@ ieee80211_ssid_mismatch(struct ieee80211 + } while (0) + #else /* !IEEE80211_DEBUG */ + #define IEEE80211_VERIFY_SSID(_ni, _ssid) do { \ ++ if ((_ni)->ni_esslen == 0) \ ++ return; \ + if ((_ssid)[1] != 0 && \ + ((_ssid)[1] != (_ni)->ni_esslen || \ + memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \ diff --git a/package/madwifi/patches/392-remove_wds_nodetracking.patch b/package/madwifi/patches/392-remove_wds_nodetracking.patch new file mode 100644 index 0000000000..fb9fb6a222 --- /dev/null +++ b/package/madwifi/patches/392-remove_wds_nodetracking.patch @@ -0,0 +1,388 @@ +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -568,36 +568,6 @@ ieee80211_input(struct ieee80211vap * va + } + } + +- /* XXX: Useless node mgmt API; make better */ +- if ((dir == IEEE80211_FC1_DIR_DSTODS) && !vap->iv_wdsnode && +- !ni_wds && !ni->ni_subif) { +- struct ieee80211_node_table *nt = &ic->ic_sta; +- struct ieee80211_frame_addr4 *wh4; +- +- if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) { +- IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, +- wh, "data", "%s", "4 addr not allowed"); +- goto err; +- } +- wh4 = (struct ieee80211_frame_addr4 *)skb->data; +- ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4); +- /* Last call increments ref count if !NULL */ +- if ((ni_wds != NULL) && (ni_wds != ni)) { +- /* +- * node with source address (addr4) moved +- * to another WDS capable station. remove the +- * reference to the previous station and add +- * reference to the new one +- */ +- (void) ieee80211_remove_wds_addr(nt, wh4->i_addr4); +- ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0); +- } +- if (ni_wds == NULL) +- ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0); +- else +- ieee80211_unref_node(&ni_wds); +- } +- + /* + * Check for power save state change. + */ +--- a/net80211/ieee80211_node.c ++++ b/net80211/ieee80211_node.c +@@ -122,7 +122,6 @@ static void ieee80211_node_table_init(st + static void ieee80211_node_table_cleanup(struct ieee80211_node_table *); + static void ieee80211_node_table_reset(struct ieee80211_node_table *, + struct ieee80211vap *); +-static void ieee80211_node_wds_ageout(unsigned long); + + MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state"); + +@@ -785,10 +784,6 @@ ieee80211_node_table_init(struct ieee802 + nt->nt_name = name; + nt->nt_scangen = 1; + nt->nt_inact_init = inact; +- init_timer(&nt->nt_wds_aging_timer); +- nt->nt_wds_aging_timer.function = ieee80211_node_wds_ageout; +- nt->nt_wds_aging_timer.data = (unsigned long) nt; +- mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL); + } + + static __inline +@@ -1204,142 +1199,6 @@ void ieee80211_wds_addif(struct ieee8021 + schedule_work(&ni->ni_create); + } + +-/* Add wds address to the node table */ +-int +-#ifdef IEEE80211_DEBUG_REFCNT +-ieee80211_add_wds_addr_debug(struct ieee80211_node_table *nt, +- struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static, +- const char* func, int line) +-#else +-ieee80211_add_wds_addr(struct ieee80211_node_table *nt, +- struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static) +-#endif +-{ +- int hash; +- struct ieee80211_wds_addr *wds; +- +- MALLOC(wds, struct ieee80211_wds_addr *, sizeof(struct ieee80211_wds_addr), +- M_80211_WDS, M_NOWAIT | M_ZERO); +- if (wds == NULL) { +- /* XXX msg */ +- return 1; +- } +- if (wds_static) +- wds->wds_agingcount = WDS_AGING_STATIC; +- else +- wds->wds_agingcount = WDS_AGING_COUNT; +- hash = IEEE80211_NODE_HASH(macaddr); +- IEEE80211_ADDR_COPY(wds->wds_macaddr, macaddr); +- +- IEEE80211_NODE_TABLE_LOCK_IRQ(nt); +-#ifdef IEEE80211_DEBUG_REFCNT +- wds->wds_ni = ieee80211_ref_node_debug(ni, func, line); +-#else +- wds->wds_ni = ieee80211_ref_node(ni); +-#endif +- LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash); +- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +- return 0; +-} +-#ifdef IEEE80211_DEBUG_REFCNT +-EXPORT_SYMBOL(ieee80211_add_wds_addr_debug); +-#else +-EXPORT_SYMBOL(ieee80211_add_wds_addr); +-#endif +- +-/* remove wds address from the wds hash table */ +-void +-#ifdef IEEE80211_DEBUG_REFCNT +-ieee80211_remove_wds_addr_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr, +- const char* func, int line) +-#else +-ieee80211_remove_wds_addr(struct ieee80211_node_table *nt, const u_int8_t *macaddr) +-#endif +-{ +- int hash; +- struct ieee80211_wds_addr *wds, *twds; +- +- hash = IEEE80211_NODE_HASH(macaddr); +- IEEE80211_NODE_TABLE_LOCK_IRQ(nt); +- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) { +- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { +- LIST_REMOVE(wds, wds_hash); +-#ifdef IEEE80211_DEBUG_REFCNT +- ieee80211_unref_node_debug(&wds->wds_ni, func, line); +-#else +- ieee80211_unref_node(&wds->wds_ni); +-#endif +- FREE(wds, M_80211_WDS); +- break; +- } +- } +- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +-} +-#ifdef IEEE80211_DEBUG_REFCNT +-EXPORT_SYMBOL(ieee80211_remove_wds_addr_debug); +-#else +-EXPORT_SYMBOL(ieee80211_remove_wds_addr); +-#endif +- +-/* Remove node references from wds table */ +-void +-#ifdef IEEE80211_DEBUG_REFCNT +-ieee80211_del_wds_node_debug(struct ieee80211_node_table *nt, struct ieee80211_node *ni, +- const char* func, int line) +-#else +-ieee80211_del_wds_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni) +-#endif +-{ +- int hash; +- struct ieee80211_wds_addr *wds, *twds; +- +- IEEE80211_NODE_TABLE_LOCK_IRQ(nt); +- for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { +- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) { +- if (wds->wds_ni == ni) { +- LIST_REMOVE(wds, wds_hash); +-#ifdef IEEE80211_DEBUG_REFCNT +- ieee80211_unref_node_debug(&wds->wds_ni, func, line); +-#else +- ieee80211_unref_node(&wds->wds_ni); +-#endif +- FREE(wds, M_80211_WDS); +- } +- } +- } +- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +-} +-#ifdef IEEE80211_DEBUG_REFCNT +-EXPORT_SYMBOL(ieee80211_del_wds_node_debug); +-#else +-EXPORT_SYMBOL(ieee80211_del_wds_node); +-#endif +- +-static void +-ieee80211_node_wds_ageout(unsigned long data) +-{ +- struct ieee80211_node_table *nt = (struct ieee80211_node_table *)data; +- int hash; +- struct ieee80211_wds_addr *wds, *twds; +- +- IEEE80211_NODE_TABLE_LOCK_IRQ(nt); +- for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { +- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) { +- if (wds->wds_agingcount != WDS_AGING_STATIC) { +- if (!wds->wds_agingcount) { +- LIST_REMOVE(wds, wds_hash); +- ieee80211_unref_node(&wds->wds_ni); +- FREE(wds, M_80211_WDS); +- } else +- wds->wds_agingcount--; +- } +- } +- } +- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +- mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL); +-} +- +- + /* Add the specified station to the station table. + * Allocates a new ieee80211_node* that has a reference count of one + * If tmp is 0, it is added to the node table and the reference is used. +@@ -1385,34 +1244,6 @@ ieee80211_dup_bss(struct ieee80211vap *v + return ni; + } + +-static struct ieee80211_node * +-#ifdef IEEE80211_DEBUG_REFCNT +-ieee80211_find_wds_node_locked_debug(struct ieee80211_node_table *nt, +- const u_int8_t *macaddr, const char* func, int line) +-#else +-ieee80211_find_wds_node_locked(struct ieee80211_node_table *nt, +- const u_int8_t *macaddr) +-#endif +-{ +- struct ieee80211_wds_addr *wds; +- int hash; +- IEEE80211_NODE_TABLE_LOCK_ASSERT(nt); +- +- hash = IEEE80211_NODE_HASH(macaddr); +- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { +- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { +- if (wds->wds_agingcount != WDS_AGING_STATIC) +- wds->wds_agingcount = WDS_AGING_COUNT; /* reset the aging count */ +-#ifdef IEEE80211_DEBUG_REFCNT +- return ieee80211_ref_node_debug(wds->wds_ni, func, line); +-#else +- return ieee80211_ref_node(wds->wds_ni); +-#endif +- } +- } +- return NULL; +-} +- + /* NB: A node reference is acquired here; the caller MUST release it. */ + #ifdef IEEE80211_DEBUG_REFCNT + #define ieee80211_find_node_locked(nt, mac) \ +@@ -1430,7 +1261,6 @@ ieee80211_find_node_locked(struct ieee80 + { + struct ieee80211_node *ni; + int hash; +- struct ieee80211_wds_addr *wds; + + IEEE80211_NODE_TABLE_LOCK_ASSERT(nt); + +@@ -1445,48 +1275,11 @@ ieee80211_find_node_locked(struct ieee80 + return ni; + } + } +- +- /* Now, we look for the desired mac address in the 4 address +- nodes. */ +- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { +- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { +-#ifdef IEEE80211_DEBUG_REFCNT +- return ieee80211_ref_node_debug(wds->wds_ni, func, line); +-#else +- return ieee80211_ref_node(wds->wds_ni); +-#endif +- } +- } + return NULL; + } + + struct ieee80211_node * + #ifdef IEEE80211_DEBUG_REFCNT +-ieee80211_find_wds_node_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr, +- const char* func, int line) +-#else +-ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr) +-#endif +-{ +- struct ieee80211_node *ni; +- +- IEEE80211_NODE_TABLE_LOCK_IRQ(nt); +-#ifdef IEEE80211_DEBUG_REFCNT +- ni = ieee80211_find_wds_node_locked_debug(nt, macaddr, func, line); +-#else +- ni = ieee80211_find_wds_node_locked(nt, macaddr); +-#endif +- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +- return ni; +-} +-#ifdef IEEE80211_DEBUG_REFCNT +-EXPORT_SYMBOL(ieee80211_find_wds_node_debug); +-#else +-EXPORT_SYMBOL(ieee80211_find_wds_node); +-#endif +- +-struct ieee80211_node * +-#ifdef IEEE80211_DEBUG_REFCNT + ieee80211_find_node_debug(struct ieee80211_node_table *nt, + const u_int8_t *macaddr, const char *func, int line) + #else +@@ -1838,7 +1631,6 @@ ieee80211_node_table_cleanup(struct ieee + ic->ic_node_cleanup(ni); + #endif + } +- del_timer(&nt->nt_wds_aging_timer); + IEEE80211_SCAN_LOCK_DESTROY(nt); + IEEE80211_NODE_TABLE_LOCK_DESTROY(nt); + } +@@ -2404,8 +2196,6 @@ ieee80211_node_leave(struct ieee80211_no + * so no more references are generated + */ + if (nt) { +- ieee80211_remove_wds_addr(nt, ni->ni_macaddr); +- ieee80211_del_wds_node(nt, ni); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); + node_table_leave_locked(nt, ni); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +--- a/net80211/ieee80211_node.h ++++ b/net80211/ieee80211_node.h +@@ -231,13 +231,6 @@ void ieee80211_sta_leave(struct ieee8021 + #define WDS_AGING_STATIC 0xffff + #define WDS_AGING_TIMER_VAL (WDS_AGING_TIME / 2) + +-struct ieee80211_wds_addr { +- LIST_ENTRY(ieee80211_wds_addr) wds_hash; +- u_int8_t wds_macaddr[IEEE80211_ADDR_LEN]; +- struct ieee80211_node *wds_ni; +- u_int16_t wds_agingcount; +-}; +- + /* + * Table of ieee80211_node instances. Each ieee80211com + * has at least one for holding the scan candidates. +@@ -250,11 +243,9 @@ struct ieee80211_node_table { + ieee80211_node_table_lock_t nt_nodelock; /* on node table */ + TAILQ_HEAD(, ieee80211_node) nt_node; /* information of all nodes */ + ATH_LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE]; +- ATH_LIST_HEAD(, ieee80211_wds_addr) nt_wds_hash[IEEE80211_NODE_HASHSIZE]; + ieee80211_scan_lock_t nt_scanlock; /* on nt_scangen */ + u_int nt_scangen; /* gen# for timeout scan */ + int nt_inact_init; /* initial node inact setting */ +- struct timer_list nt_wds_aging_timer; /* timer to age out wds entries */ + }; + + /* Allocates a new ieee80211_node* that has a reference count of one, and +@@ -363,47 +354,6 @@ void + ieee80211_unref_node(struct ieee80211_node **pni); + #endif /* #ifdef IEEE80211_DEBUG_REFCNT */ + +-/* Increments reference count of ieee80211_node *ni */ +-#ifdef IEEE80211_DEBUG_REFCNT +-#define ieee80211_add_wds_addr(_table, _node, _mac, _static) \ +- ieee80211_add_wds_addr_debug(_table, _node, _mac, _static, __func__, __LINE__) +-int ieee80211_add_wds_addr_debug(struct ieee80211_node_table *, struct ieee80211_node *, +- const u_int8_t *, u_int8_t, const char* func, int line); +-#else +-int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *, +- const u_int8_t *, u_int8_t); +-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */ +- +-/* Decrements reference count of ieee80211_node *ni */ +-#ifdef IEEE80211_DEBUG_REFCNT +-#define ieee80211_remove_wds_addr(_table, _mac) \ +- ieee80211_remove_wds_addr_debug(_table, _mac, __func__, __LINE__) +-void ieee80211_remove_wds_addr_debug(struct ieee80211_node_table *, const u_int8_t *, +- const char* func, int line); +-#else +-void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *); +-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */ +- +-/* Decrements reference count of node, if found */ +-#ifdef IEEE80211_DEBUG_REFCNT +-#define ieee80211_del_wds_node(_table, _node) \ +- ieee80211_del_wds_node_debug(_table, _node, __func__, __LINE__) +-void ieee80211_del_wds_node_debug(struct ieee80211_node_table *, struct ieee80211_node *, +- const char* func, int line); +-#else +-void ieee80211_del_wds_node(struct ieee80211_node_table *, struct ieee80211_node *); +-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */ +- +-/* Increments reference count of node, if found */ +-#ifdef IEEE80211_DEBUG_REFCNT +-#define ieee80211_find_wds_node(_table, _mac) \ +- ieee80211_find_wds_node_debug(_table, _mac, __func__, __LINE__) +-struct ieee80211_node *ieee80211_find_wds_node_debug(struct ieee80211_node_table *, +- const u_int8_t *, const char* func, int line); +-#else +-struct ieee80211_node *ieee80211_find_wds_node(struct ieee80211_node_table *, +- const u_int8_t *); +-#endif /* #ifdef IEEE80211_DEBUG_REFCNT */ + typedef void ieee80211_iter_func(void *, struct ieee80211_node *); + void ieee80211_iterate_nodes(struct ieee80211_node_table *, + ieee80211_iter_func *, void *); diff --git a/package/madwifi/patches/393-mbss_vap_auth.patch b/package/madwifi/patches/393-mbss_vap_auth.patch new file mode 100644 index 0000000000..233aeedb5c --- /dev/null +++ b/package/madwifi/patches/393-mbss_vap_auth.patch @@ -0,0 +1,454 @@ +--- a/net80211/ieee80211_node.c ++++ b/net80211/ieee80211_node.c +@@ -123,6 +123,9 @@ static void ieee80211_node_table_cleanup + static void ieee80211_node_table_reset(struct ieee80211_node_table *, + struct ieee80211vap *); + ++static struct ieee80211_node * ++lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, const u_int8_t *addr); ++ + MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state"); + + void +@@ -697,7 +700,7 @@ ieee80211_sta_join(struct ieee80211vap * + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node *ni; + +- ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr); ++ ni = lookup_rxnode(ic, vap, se->se_macaddr); + if (ni == NULL) { + ni = ieee80211_alloc_node_table(vap, se->se_macaddr); + IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, +@@ -1394,6 +1397,53 @@ ieee80211_add_neighbor(struct ieee80211v + return ni; + } + ++struct ieee80211vap * ++ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac) ++{ ++ struct ieee80211vap *vap; ++ ++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { ++ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, mac)) ++ return vap; ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(ieee80211_find_rxvap); ++ ++static struct ieee80211_node * ++lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, ++ const u_int8_t *addr) ++{ ++ struct ieee80211_node_table *nt; ++ struct ieee80211_node *ni = NULL; ++ int use_bss = 0; ++ int hash; ++ ++ nt = &ic->ic_sta; ++ IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ++ hash = IEEE80211_NODE_HASH(addr); ++ LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) { ++ if (IEEE80211_ADDR_EQ(ni->ni_macaddr, addr)) { ++ /* allow multiple nodes on different vaps */ ++ if (vap && (ni->ni_vap != vap)) ++ continue; ++ ++ ieee80211_ref_node(ni); ++ goto out; ++ } ++ } ++ ++ /* no match found */ ++ ni = NULL; ++ ++out: ++ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); ++ return ni; ++#undef IS_PSPOLL ++#undef IS_CTL ++} ++ ++ + /* + * Return the node for the sender of a frame; if the sender is unknown return + * NULL. The caller is expected to deal with this. (The frame is sent to all +@@ -1403,10 +1453,10 @@ ieee80211_add_neighbor(struct ieee80211v + */ + struct ieee80211_node * + #ifdef IEEE80211_DEBUG_REFCNT +-ieee80211_find_rxnode_debug(struct ieee80211com *ic, ++ieee80211_find_rxnode_debug(struct ieee80211com *ic, struct ieee80211vap *vap, + const struct ieee80211_frame_min *wh, const char *func, int line) + #else +-ieee80211_find_rxnode(struct ieee80211com *ic, ++ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, + const struct ieee80211_frame_min *wh) + #endif + { +@@ -1414,9 +1464,8 @@ ieee80211_find_rxnode(struct ieee80211co + ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) + #define IS_PSPOLL(wh) \ + ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL) +- struct ieee80211_node_table *nt; +- struct ieee80211_node *ni; +- struct ieee80211vap *vap, *avp; ++ struct ieee80211_node *ni = NULL; ++ struct ieee80211vap *avp; + const u_int8_t *addr; + + if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/) +@@ -1429,32 +1478,25 @@ ieee80211_find_rxnode(struct ieee80211co + + /* XXX check ic_bss first in station mode */ + /* XXX 4-address frames? */ +- nt = &ic->ic_sta; +- IEEE80211_NODE_TABLE_LOCK_IRQ(nt); + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { +- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { ++ if (vap) { /* assume unicast if vap is set, mcast not supported for wds */ + TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) { +- if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac)) ++ if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac) || ++ !IEEE80211_ADDR_EQ(wh->i_addr1, avp->iv_myaddr)) + continue; + + if (avp->iv_wdsnode) +- return ieee80211_ref_node(avp->iv_wdsnode); +- else +- return NULL; ++ ni = ieee80211_ref_node(avp->iv_wdsnode); ++ return ni; + } ++ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) ++ return NULL; ++ } else { ++ return NULL; + } + } + +-#ifdef IEEE80211_DEBUG_REFCNT +- ni = ieee80211_find_node_locked_debug(nt, addr, func, line); +-#else +- ni = ieee80211_find_node_locked(nt, addr); +-#endif +- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); +- +- return ni; +-#undef IS_PSPOLL +-#undef IS_CTL ++ return lookup_rxnode(ic, vap, addr); + } + #ifdef IEEE80211_DEBUG_REFCNT + EXPORT_SYMBOL(ieee80211_find_rxnode_debug); +@@ -1479,15 +1521,14 @@ ieee80211_find_txnode(struct ieee80211va + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node_table *nt; + struct ieee80211_node *ni = NULL; ++ int hash; + +- IEEE80211_LOCK_IRQ(ic); + if (vap->iv_opmode == IEEE80211_M_WDS) { + if (vap->iv_wdsnode && (vap->iv_state == IEEE80211_S_RUN)) + return ieee80211_ref_node(vap->iv_wdsnode); + else + return NULL; + } +- IEEE80211_UNLOCK_IRQ(ic); + + /* + * The destination address should be in the node table +@@ -1505,11 +1546,22 @@ ieee80211_find_txnode(struct ieee80211va + /* XXX: Can't hold lock across dup_bss due to recursive locking. */ + nt = &vap->iv_ic->ic_sta; + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ++ hash = IEEE80211_NODE_HASH(mac); ++ LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) { ++ if (ni->ni_vap != vap) ++ continue; ++ ++ if (IEEE80211_ADDR_EQ(ni->ni_macaddr, mac)) { + #ifdef IEEE80211_DEBUG_REFCNT +- ni = ieee80211_find_node_locked_debug(nt, mac, func, line); ++ ieee80211_ref_node_debug(ni, func, line); + #else +- ni = ieee80211_find_node_locked(nt, mac); ++ ieee80211_ref_node(ni); + #endif ++ goto found; ++ } ++ } ++ ni = NULL; ++found: + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); + + if (ni == NULL) { +@@ -1964,13 +2016,32 @@ remove_worse_nodes(void *arg, struct iee + } + } + ++static void ++remove_duplicate_nodes(void *arg, struct ieee80211_node *ni) ++{ ++ struct ieee80211_node *rni = arg; ++ ++ if (ni == rni) ++ return; ++ ++ if (ni->ni_vap == rni->ni_vap) ++ return; ++ ++ if (!IEEE80211_ADDR_EQ(rni->ni_macaddr, ni->ni_macaddr)) ++ return; ++ ++ ieee80211_node_leave(ni); ++} ++ + void + ieee80211_node_join(struct ieee80211_node *ni, int resp) + { + struct ieee80211com *ic = ni->ni_ic; + struct ieee80211vap *vap = ni->ni_vap; ++ struct ieee80211_node *tni; + int newassoc; + ++ ieee80211_iterate_nodes(&ic->ic_sta, remove_duplicate_nodes, ni); + if (ni->ni_associd == 0) { + u_int16_t aid; + +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -216,16 +216,14 @@ ieee80211_input(struct ieee80211vap * va + + type = -1; /* undefined */ + +- if (!vap) +- goto out; ++ if (!vap || !vap->iv_bss || !vap->iv_dev || !vap->iv_ic) ++ goto discard; + + ic = vap->iv_ic; +- if (!ic) +- goto out; +- + dev = vap->iv_dev; +- if (!dev) +- goto out; ++ ++ if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ++ goto discard; + + /* initialize ni as in the previous API */ + if (ni_or_null == NULL) { +@@ -233,9 +231,10 @@ ieee80211_input(struct ieee80211vap * va + * guarantee its existence during the following call, hence + * briefly grab our own reference. */ + ni = ieee80211_ref_node(vap->iv_bss); ++ KASSERT(ni != NULL, ("null node")); ++ } else { ++ ni->ni_inact = ni->ni_inact_reload; + } +- KASSERT(ni != NULL, ("null node")); +- ni->ni_inact = ni->ni_inact_reload; + + KASSERT(skb->len >= sizeof(struct ieee80211_frame_min), + ("frame length too short: %u", skb->len)); +@@ -844,10 +843,11 @@ ieee80211_input(struct ieee80211vap * va + err: + vap->iv_devstats.rx_errors++; + out: +- if (skb != NULL) +- ieee80211_dev_kfree_skb(&skb); + if (ni_or_null == NULL) + ieee80211_unref_node(&ni); ++discard: ++ if (skb != NULL) ++ ieee80211_dev_kfree_skb(&skb); + return type; + #undef HAS_SEQ + } +@@ -929,16 +929,23 @@ int + ieee80211_input_all(struct ieee80211com *ic, + struct sk_buff *skb, int rssi, u_int64_t rtsf) + { ++ struct ieee80211_frame_min *wh = (struct ieee80211_frame_min *) skb->data; + struct ieee80211vap *vap; + int type = -1; + + /* XXX locking */ + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { ++ struct ieee80211_node *ni = NULL; + struct sk_buff *skb1; + + if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) + continue; + ++ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) && ++ !IEEE80211_IS_MULTICAST(wh->i_addr1)) ++ continue; ++ ++ ni = ieee80211_find_rxnode(ic, vap, wh); + if (TAILQ_NEXT(vap, iv_next) != NULL) { + skb1 = skb_copy(skb, GFP_ATOMIC); + if (skb1 == NULL) { +@@ -950,8 +957,10 @@ ieee80211_input_all(struct ieee80211com + skb1 = skb; + skb = NULL; + } +- type = ieee80211_input(vap, NULL, skb1, rssi, rtsf); ++ type = ieee80211_input(vap, ni, skb1, rssi, rtsf); + } ++ ++out: + if (skb != NULL) /* no vaps, reclaim skb */ + ieee80211_dev_kfree_skb(&skb); + return type; +@@ -1146,11 +1155,9 @@ ieee80211_deliver_data(struct ieee80211_ + * sending it will not work; just let it be + * delivered normally. + */ +- struct ieee80211_node *ni1 = ieee80211_find_node( +- &vap->iv_ic->ic_sta, eh->ether_dhost); ++ struct ieee80211_node *ni1 = ieee80211_find_txnode(vap, eh->ether_dhost); + if (ni1 != NULL) { +- if (ni1->ni_vap == vap && +- ieee80211_node_is_authorized(ni1) && ++ if (ieee80211_node_is_authorized(ni1) && + !ni1->ni_subif && + ni1 != vap->iv_bss) { + +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -6580,9 +6580,8 @@ ath_recv_mgmt(struct ieee80211vap * vap, + + sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf); + +- + /* Lookup the new node if any (this grabs a reference to it) */ +- ni = ieee80211_find_rxnode(vap->iv_ic, ++ ni = ieee80211_find_rxnode(vap->iv_ic, vap, + (const struct ieee80211_frame_min *)skb->data); + if (ni == NULL) { + DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n"); +@@ -6737,7 +6736,9 @@ ath_rx_poll(struct net_device *dev, int + struct ath_desc *ds; + struct ath_rx_status *rs; + struct sk_buff *skb = NULL; ++ struct ieee80211vap *vap; + struct ieee80211_node *ni; ++ const struct ieee80211_frame_min *wh; + unsigned int len; + int type; + u_int phyerr; +@@ -6892,12 +6893,15 @@ rx_accept: + skb_trim(skb, skb->len - IEEE80211_CRC_LEN); + + if (mic_fail) { ++ wh = (const struct ieee80211_frame_min *) skb->data; ++ + /* Ignore control frames which are reported with mic error */ +- if ((((struct ieee80211_frame *)skb->data)->i_fc[0] & ++ if ((wh->i_fc[0] & + IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) + goto drop_micfail; + +- ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data); ++ vap = ieee80211_find_rxvap(ic, wh->i_addr1); ++ ni = ieee80211_find_rxnode(ic, vap, wh); + + if (ni && ni->ni_table) { + ieee80211_check_mic(ni, skb); +@@ -6959,11 +6963,24 @@ drop_micfail: + * for its use. If the sender is unknown spam the + * frame; it'll be dropped where it's not wanted. + */ +- if (rs->rs_keyix != HAL_RXKEYIX_INVALID && ++ wh = (const struct ieee80211_frame_min *) skb->data; ++ if ((rs->rs_keyix != HAL_RXKEYIX_INVALID) && + (ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) { + /* Fast path: node is present in the key map; + * grab a reference for processing the frame. */ +- ni = ieee80211_ref_node(ni); ++ ieee80211_ref_node(ni); ++ if ((ATH_GET_VAP_ID(wh->i_addr1) != ++ ATH_GET_VAP_ID(ni->ni_vap->iv_myaddr)) || ++ ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == ++ IEEE80211_FC1_DIR_DSTODS)) { ++ /* key cache node lookup is fast, but it can ++ * lead to problems in multi-bss (foreign vap ++ * node reference) or wds (wdsap node ref instead ++ * of base ap node ref). ++ * use slowpath lookup in both cases ++ */ ++ goto lookup_slowpath; ++ } + ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi); + type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf); + ieee80211_unref_node(&ni); +@@ -6972,24 +6989,35 @@ drop_micfail: + * No key index or no entry, do a lookup and + * add the node to the mapping table if possible. + */ +- ni = ieee80211_find_rxnode(ic, +- (const struct ieee80211_frame_min *)skb->data); ++ ++lookup_slowpath: ++ vap = ieee80211_find_rxvap(ic, wh->i_addr1); ++ if (vap) ++ ni = ieee80211_find_rxnode(ic, vap, wh); ++ else ++ ni = NULL; ++ + if (ni != NULL) { + ieee80211_keyix_t keyix; + + ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi); +- type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf); ++ type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf); + /* + * If the station has a key cache slot assigned + * update the key->node mapping table. + */ + keyix = ni->ni_ucastkey.wk_keyix; + if (keyix != IEEE80211_KEYIX_NONE && +- sc->sc_keyixmap[keyix] == NULL) ++ sc->sc_keyixmap[keyix] == NULL) { + sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni); ++ } + ieee80211_unref_node(&ni); +- } else +- type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf); ++ } else { ++ if (vap) ++ type = ieee80211_input(vap, NULL, skb, rs->rs_rssi, bf->bf_tsf); ++ else ++ type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf); ++ } + } + + if (sc->sc_diversity) { +--- a/net80211/ieee80211_node.h ++++ b/net80211/ieee80211_node.h +@@ -286,15 +286,18 @@ struct ieee80211_node *ieee80211_find_no + const u_int8_t *); + #endif /* #ifdef IEEE80211_DEBUG_REFCNT */ + ++struct ieee80211vap * ++ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac); ++ + /* Returns a ieee80211_node* with refcount incremented, if found */ + #ifdef IEEE80211_DEBUG_REFCNT +-#define ieee80211_find_rxnode(_nt, _wh) \ +- ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__) ++#define ieee80211_find_rxnode(_nt, _vap, _wh) \ ++ ieee80211_find_rxnode_debug(_nt, _vap, _wh, __func__, __LINE__) + struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *, +- const struct ieee80211_frame_min *, const char *, int); ++ struct ieee80211vap *, const struct ieee80211_frame_min *, const char *, int); + #else + struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *, +- const struct ieee80211_frame_min *); ++ struct ieee80211vap *, const struct ieee80211_frame_min *); + #endif /* #ifdef IEEE80211_DEBUG_REFCNT */ + + /* Returns a ieee80211_node* with refcount incremented, if found */ diff --git a/package/madwifi/patches/394-probereq.patch b/package/madwifi/patches/394-probereq.patch index fc8cda0d54..6d8b7c744b 100644 --- a/package/madwifi/patches/394-probereq.patch +++ b/package/madwifi/patches/394-probereq.patch @@ -1,6 +1,6 @@ --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c -@@ -3604,6 +3604,8 @@ ieee80211_recv_mgmt(struct ieee80211vap +@@ -3611,6 +3611,8 @@ ieee80211_recv_mgmt(struct ieee80211vap vap->iv_stats.is_rx_mgtdiscard++; return; } diff --git a/package/madwifi/patches/395-ath_ff_unmap.patch b/package/madwifi/patches/395-ath_ff_unmap.patch index 595c43d5b1..4c32995c87 100644 --- a/package/madwifi/patches/395-ath_ff_unmap.patch +++ b/package/madwifi/patches/395-ath_ff_unmap.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -13508,7 +13508,7 @@ cleanup_ath_buf(struct ath_softc *sc, st +@@ -13511,7 +13511,7 @@ cleanup_ath_buf(struct ath_softc *sc, st bus_unmap_single( sc->sc_bdev, bf->bf_skbaddrff[i], diff --git a/package/madwifi/patches/396-napi_ff_fix.patch b/package/madwifi/patches/396-napi_ff_fix.patch new file mode 100644 index 0000000000..0b9acdfb79 --- /dev/null +++ b/package/madwifi/patches/396-napi_ff_fix.patch @@ -0,0 +1,65 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -6725,10 +6725,10 @@ ath_rx_poll(struct net_device *dev, int + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi); + struct net_device *dev = sc->sc_dev; +- u_int rx_limit = budget; ++ int rx_limit = budget; + #else + struct ath_softc *sc = dev->priv; +- u_int rx_limit = min(dev->quota, *budget); ++ int rx_limit = min(dev->quota, *budget); + #endif + struct ath_buf *bf; + struct ieee80211com *ic = &sc->sc_ic; +@@ -6771,13 +6771,15 @@ process_rx_again: + break; + } + +- if (rx_limit-- < 2) { ++ processed += ic->ic_recv; ++ rx_limit -= ic->ic_recv; ++ ic->ic_recv = 0; ++ ++ /* keep a reserve for napi */ ++ if (rx_limit < 4) { + early_stop = 1; + break; + } +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +- processed++; +-#endif + + skb = bf->bf_skb; + if (skb == NULL) { +@@ -7061,8 +7063,8 @@ rx_next: + if (sc->sc_isr & HAL_INT_RX) { + u_int64_t hw_tsf = ath_hal_gettsf64(ah); + sc->sc_isr &= ~HAL_INT_RX; +- local_irq_restore(flags); + ath_uapsd_processtriggers(sc, hw_tsf); ++ local_irq_restore(flags); + goto process_rx_again; + } + local_irq_restore(flags); +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -1203,6 +1203,7 @@ ieee80211_deliver_data(struct ieee80211_ + } + } + ++ vap->iv_ic->ic_recv++; + if (skb != NULL) { + skb->dev = dev; + +--- a/net80211/ieee80211_var.h ++++ b/net80211/ieee80211_var.h +@@ -323,6 +323,7 @@ struct ieee80211com { + struct ifmedia ic_media; /* interface media config */ + u_int8_t ic_myaddr[IEEE80211_ADDR_LEN]; + struct timer_list ic_inact; /* mgmt/inactivity timer */ ++ u_int ic_recv; /* frame received counter */ + + unsigned int ic_subifs; + u_int32_t ic_flags; /* state flags */ diff --git a/package/madwifi/patches/400-changeset_r3402.patch b/package/madwifi/patches/400-changeset_r3402.patch deleted file mode 100644 index f43a6d90d2..0000000000 --- a/package/madwifi/patches/400-changeset_r3402.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- a/ath_hal/ah_os.h -+++ b/ath_hal/ah_os.h -@@ -194,10 +194,6 @@ extern u_int32_t __ahdecl ath_hal_getupt - */ - #if (AH_BYTE_ORDER == AH_BIG_ENDIAN) - #define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000)) --#else --#define is_reg_le(__reg) 1 --#endif -- - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) - #define _OS_REG_WRITE(_ah, _reg, _val) do { \ - is_reg_le(_reg) ? \ -@@ -219,6 +215,21 @@ extern u_int32_t __ahdecl ath_hal_getupt - readl((_ah)->ah_sh + (_reg)) : \ - cpu_to_le32(readl((_ah)->ah_sh + (_reg)))) - #endif /* KERNEL_VERSION(2,6,12) */ -+#else /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) -+#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -+ iowrite32((_val), (_ah)->ah_sh + (_reg)); \ -+ } while (0) -+#define _OS_REG_READ(_ah, _reg) \ -+ ioread32((_ah)->ah_sh + (_reg)) -+#else -+#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -+ writel((_val), (_ah)->ah_sh + (_reg)); \ -+ } while (0) -+#define _OS_REG_READ(_ah, _reg) \ -+ readl((_ah)->ah_sh + (_reg)) -+#endif /* KERNEL_VERSION(2,6,12) */ -+#endif /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ - - /* - * The functions in this section are not intended to be invoked by MadWifi diff --git a/package/madwifi/patches/400-new_hal.patch b/package/madwifi/patches/400-new_hal.patch new file mode 100644 index 0000000000..0db41683f0 --- /dev/null +++ b/package/madwifi/patches/400-new_hal.patch @@ -0,0 +1,124 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -606,6 +606,14 @@ ath_attach(u_int16_t devid, struct net_d + } + sc->sc_ah = ah; + ++ /* WAR for AR7100 PCI bug */ ++#ifdef CONFIG_ATHEROS_AR71XX ++ if ((ar_device(sc->devid) >= 5210) && (ar_device(sc->devid) < 5416)) { ++ ath_hal_setcapability(ah, HAL_CAP_DMABURST_RX, 0, HAL_DMABURST_4B, NULL); ++ ath_hal_setcapability(ah, HAL_CAP_DMABURST_TX, 0, HAL_DMABURST_4B, NULL); ++ } ++#endif ++ + /* + * Check if the MAC has multi-rate retry support. + * We do this by trying to setup a fake extended +@@ -7555,7 +7563,7 @@ ath_txq_setup(struct ath_softc *sc, int + if (qtype == HAL_TX_QUEUE_UAPSD) + qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; + else +- qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | ++ qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXOKINT_ENABLE | + HAL_TXQ_TXDESCINT_ENABLE; + qnum = ath_hal_setuptxqueue(ah, qtype, &qi); + if (qnum == -1) { +--- a/ath_hal/ah_os.c ++++ b/ath_hal/ah_os.c +@@ -126,6 +126,13 @@ ath_hal_printf(struct ath_hal *ah, const + } + EXPORT_SYMBOL(ath_hal_printf); + ++void __ahdecl ++ath_hal_printstr(struct ath_hal *ah, const char *str) ++{ ++ printk("%s", str); ++} ++EXPORT_SYMBOL(ath_hal_printstr); ++ + /* + * Format an Ethernet MAC for printing. + */ +--- a/ath_hal/ah_os.h ++++ b/ath_hal/ah_os.h +@@ -156,69 +156,23 @@ extern u_int32_t __ahdecl ath_hal_getupt + #endif + #endif /* AH_BYTE_ORDER */ + +-/* +- * Some big-endian architectures don't set CONFIG_GENERIC_IOMAP, but fail to +- * implement iowrite32be and ioread32be. Provide compatibility macros when +- * it's needed. +- * +- * As of Linux 2.6.24, only MIPS, PARISC and PowerPC implement iowrite32be and +- * ioread32be as functions. +- * +- * The downside or the replacement macros it that we may be byte-swapping data +- * for the second time, so the native implementations should be preferred. +- */ +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) && \ +- !defined(CONFIG_GENERIC_IOMAP) && (AH_BYTE_ORDER == AH_BIG_ENDIAN) && \ +- !defined(__mips__) && !defined(__hppa__) && !defined(__powerpc__) +-# ifndef iowrite32be +-# define iowrite32be(_val, _addr) iowrite32(swab32((_val)), (_addr)) +-# endif +-# ifndef ioread32be +-# define ioread32be(_addr) swab32(ioread32((_addr))) +-# endif +-#endif ++#define IS_SWAPPED(_ah, _reg) \ ++ ((_ah)->ah_swapped && \ ++ (((0x4000 <= (_reg)) && ((_reg) < 0x5000)) || \ ++ ((0x7000 <= (_reg)) && ((_reg) < 0x8000)))) ++ ++#define SWAPREG(_ah, _reg, _val) \ ++ (IS_SWAPPED(_ah, _reg) ? cpu_to_le32(_val) : (_val)) + + /* + * The register accesses are done using target-specific functions when + * debugging is enabled (AH_DEBUG) or it's explicitly requested for the target. +- * +- * The hardware registers use little-endian byte order natively. Big-endian +- * systems are configured by HAL to enable hardware byte-swap of register reads +- * and writes at reset. This avoid the need to byte-swap the data in software. +- * However, the registers in a certain area from 0x4000 to 0x4fff (PCI clock +- * domain registers) are not byte swapped! +- * +- * Since Linux I/O primitives default to little-endian operations, we only +- * need to suppress byte-swapping on big-endian systems outside the area used +- * by the PCI clock domain registers. + */ +-#if (AH_BYTE_ORDER == AH_BIG_ENDIAN) +-#define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000)) +-#else +-#define is_reg_le(__reg) 1 +-#endif +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +-#define _OS_REG_WRITE(_ah, _reg, _val) do { \ +- is_reg_le(_reg) ? \ +- iowrite32((_val), (_ah)->ah_sh + (_reg)) : \ +- iowrite32be((_val), (_ah)->ah_sh + (_reg)); \ +- } while (0) +-#define _OS_REG_READ(_ah, _reg) \ +- (is_reg_le(_reg) ? \ +- ioread32((_ah)->ah_sh + (_reg)) : \ +- ioread32be((_ah)->ah_sh + (_reg))) +-#else + #define _OS_REG_WRITE(_ah, _reg, _val) do { \ +- writel(is_reg_le(_reg) ? \ +- (_val) : cpu_to_le32(_val), \ +- (_ah)->ah_sh + (_reg)); \ +- } while (0) ++ __raw_writel(SWAPREG(_ah, _reg, _val), (_ah)->ah_sh + (_reg)); \ ++} while (0) + #define _OS_REG_READ(_ah, _reg) \ +- (is_reg_le(_reg) ? \ +- readl((_ah)->ah_sh + (_reg)) : \ +- cpu_to_le32(readl((_ah)->ah_sh + (_reg)))) +-#endif /* KERNEL_VERSION(2,6,12) */ ++ SWAPREG(_ah, _reg, __raw_readl((_ah)->ah_sh + (_reg))) + + /* + * The functions in this section are not intended to be invoked by MadWifi diff --git a/package/madwifi/patches/405-retransmit_check.patch b/package/madwifi/patches/405-retransmit_check.patch index b03232ad5e..11e78aba87 100644 --- a/package/madwifi/patches/405-retransmit_check.patch +++ b/package/madwifi/patches/405-retransmit_check.patch @@ -11,7 +11,7 @@ #define IEEE80211_QOS_TXOP 0x00ff --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c -@@ -429,7 +429,7 @@ ieee80211_input(struct ieee80211vap * va +@@ -428,7 +428,7 @@ ieee80211_input(struct ieee80211vap * va tid = 0; rxseq = le16toh(*(__le16 *)wh->i_seq); if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) && diff --git a/package/madwifi/patches/406-monitor_r3711.patch b/package/madwifi/patches/406-monitor_r3711.patch index 64f19e0b8c..af02edce85 100644 --- a/package/madwifi/patches/406-monitor_r3711.patch +++ b/package/madwifi/patches/406-monitor_r3711.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -6510,7 +6510,7 @@ ath_capture(struct net_device *dev, cons +@@ -6521,7 +6521,7 @@ ath_capture(struct net_device *dev, cons /* Never copy the SKB, as it is ours on the RX side, and this is the * last process on the TX side and we only modify our own headers. */ @@ -9,7 +9,7 @@ if (tskb == NULL) { DPRINTF(sc, ATH_DEBUG_ANY, "Dropping; ath_skb_removepad failed!\n"); -@@ -6518,6 +6518,8 @@ ath_capture(struct net_device *dev, cons +@@ -6529,6 +6529,8 @@ ath_capture(struct net_device *dev, cons } ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc); diff --git a/package/madwifi/patches/408-changeset_r3337.patch b/package/madwifi/patches/408-changeset_r3337.patch index 00f0955fa4..b798082412 100644 --- a/package/madwifi/patches/408-changeset_r3337.patch +++ b/package/madwifi/patches/408-changeset_r3337.patch @@ -10,7 +10,7 @@ Please let us know if you think your name should be mentioned here! --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -3129,7 +3129,7 @@ ath_tx_startraw(struct net_device *dev, +@@ -3138,7 +3138,7 @@ ath_tx_startraw(struct net_device *dev, struct ath_softc *sc = dev->priv; struct ath_hal *ah = sc->sc_ah; struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *) diff --git a/package/madwifi/patches/410-ar231x_2.6.28.patch b/package/madwifi/patches/410-ar231x_2.6.28.patch new file mode 100644 index 0000000000..87177c3986 --- /dev/null +++ b/package/madwifi/patches/410-ar231x_2.6.28.patch @@ -0,0 +1,281 @@ +--- a/ath/if_ath_ahb.c ++++ b/ath/if_ath_ahb.c +@@ -33,20 +33,15 @@ + #include "if_ath_ahb.h" + #include "ah_soc.h" + +-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +-#error "Kernel versions older than 2.6.19 are not supported!" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++#include + #endif + + struct ath_ahb_softc { + struct ath_softc aps_sc; +-#ifdef CONFIG_PM +- u32 aps_pmstate[16]; +-#endif ++ struct ar531x_config aps_config; + }; + +-static struct ath_ahb_softc *sclist[2] = {NULL, NULL}; +-static u_int8_t num_activesc = 0; +- + /* + * Module glue. + */ +@@ -101,13 +96,13 @@ ahb_enable_wmac(u_int16_t devid, u_int16 + while (REG_READ(AR5315_PCI_MAC_PCICFG) & AR5315_PCI_MAC_PCICFG_SPWR_DN); + } else { + switch (wlanNum) { +- case AR531X_WLAN0_NUM: ++ case 0: + reset = (AR531X_RESET_WLAN0 | + AR531X_RESET_WARM_WLAN0_MAC | + AR531X_RESET_WARM_WLAN0_BB); + enable = AR531X_ENABLE_WLAN0; + break; +- case AR531X_WLAN1_NUM: ++ case 1: + reset = (AR531X_RESET_WLAN1 | + AR531X_RESET_WARM_WLAN1_MAC | + AR531X_RESET_WARM_WLAN1_BB); +@@ -144,10 +139,10 @@ ahb_disable_wmac(u_int16_t devid, u_int1 + *en &= ~AR5315_ARB_WLAN; + } else { + switch (wlanNum) { +- case AR531X_WLAN0_NUM: ++ case 0: + enable = AR531X_ENABLE_WLAN0; + break; +- case AR531X_WLAN1_NUM: ++ case 1: + enable = AR531X_ENABLE_WLAN1; + break; + default: +@@ -159,29 +154,6 @@ ahb_disable_wmac(u_int16_t devid, u_int1 + } + + +-static int +-exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config) +-{ +- struct ath_ahb_softc *sc = sclist[wlanNum]; +- struct net_device *dev; +- u_int16_t devid; +- +- if (sc == NULL) +- return -ENODEV; /* XXX: correct return value? */ +- +- dev = sc->aps_sc.sc_dev; +- ath_detach(dev); +- if (dev->irq) +- free_irq(dev->irq, dev); +- devid = sc->aps_sc.devid; +- config->tag = (void *)((unsigned long) devid); +- +- ahb_disable_wmac(devid, wlanNum); +- free_netdev(dev); +- sclist[wlanNum] = NULL; +- return 0; +-} +- + static const char ubnt[] = "Ubiquiti Networks"; + static const struct ath_hw_detect cards[] = { + { +@@ -266,6 +238,114 @@ static const struct ath_hw_detect cards[ + }, + }; + ++static void ++ahb_hw_detect(struct ath_ahb_softc *sc, const char *radio) ++{ ++ u16 *radio_data = (u16 *) radio; ++ if (radio_data) { ++ u16 vendor, id, subvendor, subid; ++ vendor = radio_data[1]; ++ id = radio_data[0]; ++ subvendor = radio_data[8]; ++ subid = radio_data[7]; ++ ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid); ++ } ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ ++static int ahb_wmac_probe(struct platform_device *pdev) ++{ ++ struct ar231x_board_config *bcfg = pdev->dev.platform_data; ++ struct ath_ahb_softc *sc; ++ struct net_device *dev; ++ struct resource *res; ++ const char *athname; ++ int err; ++ ++ ahb_enable_wmac(bcfg->devid, pdev->id); ++ dev = alloc_netdev(sizeof(struct ath_ahb_softc), "wifi%d", ether_setup); ++ if (!dev) ++ return -ENOMEM; ++ ++ sc = dev->priv; ++ sc->aps_sc.sc_dev = dev; ++ ++ dev->irq = platform_get_irq(pdev, 0); ++ if (dev->irq <= 0) { ++ printk("%s: Cannot find IRQ resource\n", dev->name); ++ goto error; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ printk("%s: Cannot find MMIO resource\n", dev->name); ++ goto error; ++ } ++ ++ dev->mem_start = KSEG1ADDR(res->start); ++ dev->mem_end = KSEG1ADDR(res->end); ++ sc->aps_sc.sc_iobase = (void __iomem *) dev->mem_start; ++ sc->aps_sc.sc_bdev = NULL; ++ ++ /* bus information for the HAL */ ++ sc->aps_config.board = (const struct ar531x_boarddata *) bcfg->config; ++ sc->aps_config.radio = bcfg->radio; ++ sc->aps_config.unit = pdev->id; ++ sc->aps_config.tag = NULL; ++ ++ err = ath_attach(bcfg->devid, dev, &sc->aps_config); ++ if (err != 0) { ++ printk("%s: ath_attach failed: %d\n", dev->name, err); ++ goto error; ++ } ++ ++ athname = ath_hal_probe(ATHEROS_VENDOR_ID, bcfg->devid); ++ printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n", ++ dev_info, dev->name, athname ? athname : "Atheros ???", dev->mem_start, dev->irq); ++ ++ if (request_irq(dev->irq, ath_intr, IRQF_SHARED|IRQF_DISABLED, dev->name, dev)) { ++ printk(KERN_WARNING "%s: %s: request_irq failed\n", dev_info, dev->name); ++ goto error; ++ } ++ ++ sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */ ++ sc->aps_sc.sc_ledpin = bcfg->config->sysLedGpio; ++ sc->aps_sc.sc_invalid = 0; ++ ahb_hw_detect(sc, bcfg->radio); ++ platform_set_drvdata(pdev, dev); ++ return 0; ++ ++error_dev: ++ free_irq(dev->irq, dev); ++error: ++ free_netdev(dev); ++ ++ return -ENODEV; ++} ++ ++ ++static int ahb_wmac_remove(struct platform_device *pdev) ++{ ++ struct ar231x_board_config *bcfg = pdev->dev.platform_data; ++ struct net_device *dev; ++ ++ dev = platform_get_drvdata(pdev); ++ ath_detach(dev); ++ ++ if (dev->irq) ++ free_irq(dev->irq, dev); ++ ++ ahb_disable_wmac(bcfg->devid, pdev->id); ++ free_netdev(dev); ++ ++ return 0; ++} ++ ++#else ++ ++static struct ath_ahb_softc *sclist[2] = {NULL, NULL}; ++ + static int + init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config) + { +@@ -318,7 +398,7 @@ init_ath_wmac(u_int16_t devid, u_int16_t + sc->aps_sc.sc_iobase = (void __iomem *) dev->mem_start; + sc->aps_sc.sc_bdev = NULL; + +- if (request_irq(dev->irq, ath_intr, IRQF_SHARED, dev->name, dev)) { ++ if (request_irq(dev->irq, ath_intr, IRQF_SHARED|IRQF_DISABLED, dev->name, dev)) { + printk(KERN_WARNING "%s: %s: request_irq failed\n", dev_info, dev->name); + goto bad3; + } +@@ -328,21 +408,12 @@ init_ath_wmac(u_int16_t devid, u_int16_t + athname = ath_hal_probe(ATHEROS_VENDOR_ID, devid); + printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n", + dev_info, dev->name, athname ? athname : "Atheros ???", dev->mem_start, dev->irq); +- num_activesc++; + /* Ready to process interrupts */ + + sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */ + sc->aps_sc.sc_ledpin = config->board->sysLedGpio; + sc->aps_sc.sc_invalid = 0; +- radio_data = (u16 *) config->radio; +- if (radio_data) { +- u16 vendor, id, subvendor, subid; +- vendor = radio_data[1]; +- id = radio_data[0]; +- subvendor = radio_data[8]; +- subid = radio_data[7]; +- ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid); +- } ++ ahb_hw_detect(sc, config->radio); + + return 0; + +@@ -357,6 +428,29 @@ init_ath_wmac(u_int16_t devid, u_int16_t + return -ENODEV; + } + ++static int ++exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config) ++{ ++ struct ath_ahb_softc *sc = sclist[wlanNum]; ++ struct net_device *dev; ++ u_int16_t devid; ++ ++ if (sc == NULL) ++ return -ENODEV; /* XXX: correct return value? */ ++ ++ dev = sc->aps_sc.sc_dev; ++ ath_detach(dev); ++ if (dev->irq) ++ free_irq(dev->irq, dev); ++ devid = sc->aps_sc.devid; ++ config->tag = (void *)((unsigned long) devid); ++ ++ ahb_disable_wmac(devid, wlanNum); ++ free_netdev(dev); ++ sclist[wlanNum] = NULL; ++ return 0; ++} ++ + static int ahb_wmac_probe(struct platform_device *pdev) + { + u_int16_t devid; +@@ -377,11 +471,18 @@ static int ahb_wmac_remove(struct platfo + return 0; + } + ++#endif ++ + static struct platform_driver ahb_wmac_driver = { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ .driver.name = "ar231x-wmac", ++#else + .driver.name = "ar531x-wmac", ++#endif + .probe = ahb_wmac_probe, + .remove = ahb_wmac_remove + }; ++ + int + ath_ioctl_ethtool(struct ath_softc *sc, int cmd, void __user *addr) + { diff --git a/package/madwifi/patches/411-autochannel_multi.patch b/package/madwifi/patches/411-autochannel_multi.patch new file mode 100644 index 0000000000..ab48e70b2c --- /dev/null +++ b/package/madwifi/patches/411-autochannel_multi.patch @@ -0,0 +1,347 @@ +--- a/net80211/ieee80211_scan.c ++++ b/net80211/ieee80211_scan.c +@@ -97,6 +97,123 @@ struct scan_state { + static void scan_restart_pwrsav(unsigned long); + static void scan_next(unsigned long); + ++spinlock_t channel_lock = SPIN_LOCK_UNLOCKED; ++static LIST_HEAD(channels_inuse); ++ ++struct channel_inuse { ++ struct list_head list; ++ struct ieee80211com *ic; ++ u16 freq; ++ u8 bw; ++}; ++ ++static inline u32 ++get_signal(u8 bw, u8 distance) ++{ ++ u32 v; ++ ++ /* signal = 1 - (distance / bw)^2 [scale: 100] */ ++ v = 100 * distance / bw; ++ v = (100 - ((v * v) / 100)); ++ return v; ++} ++ ++static u32 ++get_overlap(u16 f1, u16 f2, u8 b1, u8 b2) ++{ ++ u32 v; ++ u16 d, c; ++ ++ /* add offsets for sidechannel interference */ ++ b1 += (b1 / 5); ++ b2 += (b2 / 5); ++ ++ /* use only one direction */ ++ b1 /= 2; ++ b2 /= 2; ++ ++ if (f1 + b1 < f2 - b2) ++ return 0; ++ ++ d = f2 - f1; ++ c = d * b1 / (b1 + b2); ++ v = get_signal(b1, c); ++ ++ return v * v / 100; ++} ++ ++static u8 ++get_channel_bw(struct ieee80211_channel *c) ++{ ++ switch(c->ic_flags & ( ++ IEEE80211_CHAN_HALF | ++ IEEE80211_CHAN_QUARTER | ++ IEEE80211_CHAN_TURBO | ++ IEEE80211_CHAN_STURBO)) { ++ case IEEE80211_CHAN_QUARTER: ++ return 5; ++ case IEEE80211_CHAN_HALF: ++ return 10; ++ case IEEE80211_CHAN_TURBO: ++ case IEEE80211_CHAN_STURBO: ++ return 40; ++ default: ++ return 20; ++ } ++} ++ ++/* must be called with channel_lock held */ ++u32 ++ieee80211_scan_get_bias(struct ieee80211_channel *c) ++{ ++ struct channel_inuse *ch; ++ u8 bw = get_channel_bw(c); ++ u32 bias = 0; ++ ++ list_for_each_entry(ch, &channels_inuse, list) { ++ if (ch->freq == c->ic_freq) { ++ bias += 50; ++ continue; ++ } ++ if (c->ic_freq < ch->freq) ++ bias += get_overlap(c->ic_freq, ch->freq, bw, ch->bw); ++ else ++ bias += get_overlap(ch->freq, c->ic_freq, ch->bw, bw); ++ } ++ return min(bias, (u32) 100); ++} ++EXPORT_SYMBOL(ieee80211_scan_get_bias); ++ ++/* must be called with channel_lock held */ ++void ++ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c) ++{ ++ unsigned long flags; ++ struct channel_inuse *ch; ++ ++ list_for_each_entry(ch, &channels_inuse, list) { ++ if (ch->ic == ic) ++ goto found; ++ } ++ ch = NULL; ++found: ++ if (c && (c != IEEE80211_CHAN_ANYC)) { ++ if (!ch) { ++ ch = kmalloc(sizeof(struct channel_inuse), GFP_ATOMIC); ++ ch->ic = ic; ++ INIT_LIST_HEAD(&ch->list); ++ list_add(&ch->list, &channels_inuse); ++ } ++ ch->freq = c->ic_freq; ++ ch->bw = get_channel_bw(c); ++ } else if (ch) { ++ list_del(&ch->list); ++ kfree(ch); ++ } ++} ++EXPORT_SYMBOL(ieee80211_scan_set_bss_channel); ++ ++ + void + ieee80211_scan_attach(struct ieee80211com *ic) + { +@@ -1155,7 +1272,7 @@ ieee80211_scan_dfs_action(struct ieee802 + IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT; + ic->ic_flags |= IEEE80211_F_CHANSWITCH; + } else { +- ++ unsigned long flags; + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, + "%s: directly switching to channel " + "%3d (%4d MHz)\n", __func__, +@@ -1166,6 +1283,9 @@ ieee80211_scan_dfs_action(struct ieee802 + * change the channel here. */ + change_channel(ic, new_channel); + ic->ic_bsschan = new_channel; ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + if (vap->iv_bss) + vap->iv_bss->ni_chan = new_channel; + } +--- a/net80211/ieee80211_scan.h ++++ b/net80211/ieee80211_scan.h +@@ -35,6 +35,7 @@ + + #define IEEE80211_SCAN_MAX IEEE80211_CHAN_MAX + ++extern spinlock_t channel_lock; + struct ieee80211_scanner; + struct ieee80211_scan_entry; + +@@ -116,6 +117,8 @@ void ieee80211_scan_flush(struct ieee802 + struct ieee80211_scan_entry; + typedef int ieee80211_scan_iter_func(void *, const struct ieee80211_scan_entry *); + int ieee80211_scan_iterate(struct ieee80211com *, ieee80211_scan_iter_func *, void *); ++u32 ieee80211_scan_get_bias(struct ieee80211_channel *c); ++void ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c); + + /* + * Parameters supplied when adding/updating an entry in a +--- a/net80211/ieee80211.c ++++ b/net80211/ieee80211.c +@@ -373,8 +373,16 @@ void + ieee80211_ifdetach(struct ieee80211com *ic) + { + struct ieee80211vap *vap; ++ unsigned long flags; + int count; + ++ /* mark the channel as no longer in use */ ++ ic->ic_bsschan = IEEE80211_CHAN_ANYC; ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); ++ ++ + /* bring down all vaps */ + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + ieee80211_stop(vap->iv_dev); +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -2772,6 +2772,7 @@ static void + ieee80211_doth_switch_channel(struct ieee80211vap *vap) + { + struct ieee80211com *ic = vap->iv_ic; ++ unsigned long flags; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, + "%s: Channel switch to %3d (%4d MHz) NOW!\n", +@@ -2794,6 +2795,9 @@ ieee80211_doth_switch_channel(struct iee + + ic->ic_curchan = ic->ic_bsschan = vap->iv_csa_chan; + ic->ic_set_channel(ic); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + } + + static void +--- a/net80211/ieee80211_node.c ++++ b/net80211/ieee80211_node.c +@@ -308,6 +308,7 @@ ieee80211_create_ibss(struct ieee80211va + { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node *ni; ++ unsigned long flags; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: creating ibss on channel %u\n", __func__, +@@ -386,6 +387,9 @@ ieee80211_create_ibss(struct ieee80211va + ic->ic_bsschan = chan; + ieee80211_node_set_chan(ic, ni); + ic->ic_curmode = ieee80211_chan2mode(chan); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + + /* Update country ie information */ + ieee80211_build_countryie(ic); +@@ -622,6 +626,7 @@ ieee80211_sta_join1(struct ieee80211_nod + struct ieee80211vap *vap = selbs->ni_vap; + struct ieee80211com *ic = selbs->ni_ic; + struct ieee80211_node *obss; ++ unsigned long flags; + int canreassoc; + + if (vap->iv_opmode == IEEE80211_M_IBSS) { +@@ -650,6 +655,9 @@ ieee80211_sta_join1(struct ieee80211_nod + ic->ic_curchan = ic->ic_bsschan; + ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); + ic->ic_set_channel(ic); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + /* + * Set the erp state (mostly the slot time) to deal with + * the auto-select case; this should be redundant if the +--- a/net80211/ieee80211_proto.c ++++ b/net80211/ieee80211_proto.c +@@ -1225,6 +1225,7 @@ ieee80211_dturbo_switch(struct ieee80211 + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + #endif + struct ieee80211_channel *chan; ++ unsigned long flags; + + chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags); + if (chan == NULL) { /* XXX should not happen */ +@@ -1243,6 +1244,9 @@ ieee80211_dturbo_switch(struct ieee80211 + ic->ic_bsschan = chan; + ic->ic_curchan = chan; + ic->ic_set_channel(ic); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + /* NB: do not need to reset ERP state because in sta mode */ + } + EXPORT_SYMBOL(ieee80211_dturbo_switch); +--- a/net80211/ieee80211_wireless.c ++++ b/net80211/ieee80211_wireless.c +@@ -4076,8 +4076,13 @@ ieee80211_ioctl_setchanlist(struct net_d + if (nchan == 0) /* no valid channels, disallow */ + return -EINVAL; + if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ +- isclr(chanlist, ic->ic_bsschan->ic_ieee)) ++ isclr(chanlist, ic->ic_bsschan->ic_ieee)) { ++ unsigned long flags; + ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* invalidate */ ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); ++ } + + memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); + /* update Supported Channels information element */ +--- a/net80211/ieee80211_scan_ap.c ++++ b/net80211/ieee80211_scan_ap.c +@@ -213,9 +213,15 @@ ap_start(struct ieee80211_scan_state *ss + struct ieee80211com *ic = NULL; + int i; + unsigned int mode = 0; ++ unsigned long sflags; + + SCAN_AP_LOCK_IRQ(as); + ic = vap->iv_ic; ++ ++ spin_lock_irqsave(&channel_lock, sflags); ++ ieee80211_scan_set_bss_channel(ic, NULL); ++ spin_unlock_irqrestore(&channel_lock, sflags); ++ + /* Determine mode flags to match, or leave zero for auto mode */ + as->as_vap_desired_mode = vap->iv_des_mode; + as->as_required_mode = 0; +@@ -429,8 +435,10 @@ pc_cmp_idletime(struct ieee80211_channel + if (!a->ic_idletime || !b->ic_idletime) + return 0; + +- /* a is better than b (return < 0) when a has more idle time than b */ +- return b->ic_idletime - a->ic_idletime; ++ /* a is better than b (return < 0) when a has more idle and less bias time than b */ ++ return ++ ((100 - (u32) a->ic_idletime) + ieee80211_scan_get_bias(a)) - ++ ((100 - (u32) b->ic_idletime) + ieee80211_scan_get_bias(b)); + } + + +@@ -616,6 +624,7 @@ ap_end(struct ieee80211_scan_state *ss, + struct ap_state *as = ss->ss_priv; + struct ieee80211_channel *bestchan = NULL; + struct ieee80211com *ic = NULL; ++ unsigned long sflags; + int res = 1; + + SCAN_AP_LOCK_IRQ(as); +@@ -624,8 +633,11 @@ ap_end(struct ieee80211_scan_state *ss, + ("wrong opmode %u", vap->iv_opmode)); + + ic = vap->iv_ic; ++ spin_lock_irqsave(&channel_lock, sflags); ++ ieee80211_scan_set_bss_channel(ic, NULL); + bestchan = pick_channel(ss, vap, flags); + if (bestchan == NULL) { ++ spin_unlock_irqrestore(&channel_lock, sflags); + if (ss->ss_last > 0) { + /* no suitable channel, should not happen */ + printk(KERN_ERR "%s: %s: no suitable channel! " +@@ -644,6 +656,7 @@ ap_end(struct ieee80211_scan_state *ss, + bestchan->ic_freq, bestchan->ic_flags & + ~IEEE80211_CHAN_TURBO)) == NULL) { + /* should never happen ?? */ ++ spin_unlock_irqrestore(&channel_lock, sflags); + SCAN_AP_UNLOCK_IRQ_EARLY(as); + return 0; + } +@@ -656,6 +669,9 @@ ap_end(struct ieee80211_scan_state *ss, + as->as_action = action; + as->as_selbss = se; + ++ ieee80211_scan_set_bss_channel(ic, bestchan); ++ spin_unlock_irqrestore(&channel_lock, sflags); ++ + /* Must defer action to avoid possible recursive call through + * 80211 state machine, which would result in recursive + * locking. */ diff --git a/package/madwifi/patches/412-fragmentation_fix.patch b/package/madwifi/patches/412-fragmentation_fix.patch new file mode 100644 index 0000000000..8c72f547ab --- /dev/null +++ b/package/madwifi/patches/412-fragmentation_fix.patch @@ -0,0 +1,10 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -3675,6 +3675,7 @@ ff_bypass: + * already alloc'd + */ + ATH_TXBUF_LOCK_IRQ(sc); ++ STAILQ_INSERT_TAIL(&bf_head, bf, bf_list); + for (bfcnt = 1; bfcnt < framecnt; ++bfcnt) { + tbf = ath_take_txbuf_locked(sc); + if (tbf == NULL) diff --git a/package/madwifi/patches/413-rxorn.patch b/package/madwifi/patches/413-rxorn.patch new file mode 100644 index 0000000000..b4174716d7 --- /dev/null +++ b/package/madwifi/patches/413-rxorn.patch @@ -0,0 +1,31 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -2307,6 +2307,17 @@ ath_intr(int irq, void *dev_id, struct p + + sc->sc_isr = status; + status &= sc->sc_imask; /* discard unasked for bits */ ++ ++ /* Treat RXORN as non-fatal. Either the bus is busy or the CPU ++ * is not fast enough to process all frames. Treat it like ++ * an Rx interrupt ++ */ ++ if (status & HAL_INT_RXORN) { ++ sc->sc_stats.ast_rxorn++; ++ status &= ~HAL_INT_RXORN; ++ status |= HAL_INT_RX; ++ } ++ + /* As soon as we know we have a real interrupt we intend to service, + * we will check to see if we need an initial hardware TSF reading. + * Normally we would just populate this all the time to keep things +@@ -2319,10 +2330,6 @@ ath_intr(int irq, void *dev_id, struct p + sc->sc_stats.ast_hardware++; + ath_hal_intrset(ah, 0); /* disable intr's until reset */ + ATH_SCHEDULE_TQUEUE(&sc->sc_fataltq, &needmark); +- } else if (status & HAL_INT_RXORN) { +- sc->sc_stats.ast_rxorn++; +- ath_hal_intrset(ah, 0); /* disable intr's until reset */ +- ATH_SCHEDULE_TQUEUE(&sc->sc_rxorntq, &needmark); + } else { + if (status & HAL_INT_SWBA) { + struct ieee80211vap * vap; diff --git a/package/madwifi/patches/414-txpower.patch b/package/madwifi/patches/414-txpower.patch new file mode 100644 index 0000000000..5300de90c6 --- /dev/null +++ b/package/madwifi/patches/414-txpower.patch @@ -0,0 +1,247 @@ +--- a/net80211/ieee80211.c ++++ b/net80211/ieee80211.c +@@ -270,6 +270,7 @@ ieee80211_ifattach(struct ieee80211com * + ("invalid number of channels specified: %u", ic->ic_nchans)); + memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); + ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; ++ ic->ic_max_txpower = IEEE80211_TXPOWER_MIN; + + for (i = 0; i < ic->ic_nchans; i++) { + c = &ic->ic_channels[i]; +@@ -277,6 +278,7 @@ ieee80211_ifattach(struct ieee80211com * + KASSERT(c->ic_ieee < IEEE80211_CHAN_MAX, + ("channel with bogus ieee number %u", c->ic_ieee)); + setbit(ic->ic_chan_avail, c->ic_ieee); ++ ic->ic_max_txpower = max(ic->ic_max_txpower, (u16) c->ic_maxpower * 2); + + if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT) + c->ic_scanflags |= IEEE80211_NOSCAN_SET; +@@ -346,8 +348,6 @@ ieee80211_ifattach(struct ieee80211com * + TAILQ_INIT(&ic->ic_vaps); + + ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; +- ic->ic_txpowlimit = IEEE80211_TXPOWER_MIN; +- ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX; + + init_timer(&ic->ic_dfs_excl_timer); + ic->ic_dfs_excl_timer.function = +--- a/net80211/ieee80211_node.c ++++ b/net80211/ieee80211_node.c +@@ -1125,7 +1125,7 @@ ieee80211_alloc_node(struct ieee80211vap + + ni->ni_chan = IEEE80211_CHAN_ANYC; + ni->ni_authmode = IEEE80211_AUTH_OPEN; +- ni->ni_txpower = ic->ic_txpowlimit; ++ ni->ni_txpower = IEEE80211_TXPOWER_MAX; + + ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, + IEEE80211_KEYIX_NONE); +--- a/net80211/ieee80211_var.h ++++ b/net80211/ieee80211_var.h +@@ -343,8 +343,9 @@ struct ieee80211com { + u_int16_t ic_holdover; /* PM hold over duration */ + u_int16_t ic_bmissthreshold; /* beacon miss threshold (# beacons) */ + unsigned long ic_bmiss_guard; /* when to cease ignoring bmiss (jiffies) */ +- u_int16_t ic_txpowlimit; /* global tx power limit (in 0.5 dBm) */ +- u_int16_t ic_newtxpowlimit; /* tx power limit to change to (in 0.5 dBm) */ ++ u_int16_t ic_txpowlimit; /* configured global tx power limit (in 0.5 dBm) */ ++ u_int16_t ic_max_txpower; /* global hardware tx power limit */ ++ u_int16_t ic_cur_txpower; /* current tx power */ + u_int16_t ic_uapsdmaxtriggers; /* max triggers that could arrive */ + u_int8_t ic_coverageclass; /* coverage class */ + u_int8_t ic_protmode_rssi; /* rssi threshold for protection mode */ +--- a/net80211/ieee80211_wireless.c ++++ b/net80211/ieee80211_wireless.c +@@ -920,17 +920,23 @@ ieee80211_ioctl_giwrange(struct net_devi + u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */ + int i, r; + int step = 0; ++ u_int16_t power; + + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + ++ power = ic->ic_max_txpower; ++ if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC)) ++ power = min(power, (u_int16_t) ic->ic_bsschan->ic_maxpower); ++ + /* txpower (128 values, but will print out only IW_MAX_TXPOWER) */ +- range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit; +- step = ic->ic_txpowlimit / (2 * (IW_MAX_TXPOWER - 1)); ++ power /= 2; /* Unit: 0.5 dBm */ ++ range->num_txpower = (power >= 8) ? IW_MAX_TXPOWER : power; ++ step = power / (IW_MAX_TXPOWER - 1); + + range->txpower[0] = 0; + for (i = 1; i < IW_MAX_TXPOWER; i++) +- range->txpower[i] = (ic->ic_txpowlimit/2) ++ range->txpower[i] = power + - (IW_MAX_TXPOWER - i - 1) * step; + + range->txpower_capa = IW_TXPOW_DBM; +@@ -1379,13 +1385,11 @@ ieee80211_ioctl_siwtxpow(struct net_devi + int fixed, disabled; + + fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED); +- disabled = (fixed && vap->iv_bss->ni_txpower == 0); ++ disabled = (fixed && ic->ic_txpowlimit == 0); + if (rrq->disabled) { + if (!disabled) { +- if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) +- return -EOPNOTSUPP; + ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; +- vap->iv_bss->ni_txpower = 0; ++ ic->ic_txpowlimit = 0; + goto done; + } + return 0; +@@ -1396,30 +1400,12 @@ ieee80211_ioctl_siwtxpow(struct net_devi + return -EOPNOTSUPP; + if (rrq->flags != IW_TXPOW_DBM) + return -EINVAL; +- if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) { +- if ((ic->ic_bsschan->ic_maxregpower >= rrq->value) && +- (ic->ic_txpowlimit/2 >= rrq->value)) { +- vap->iv_bss->ni_txpower = 2 * rrq->value; +- ic->ic_newtxpowlimit = 2 * rrq->value; +- ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; +- } else +- return -EINVAL; +- } else { +- /* +- * No channel set yet +- */ +- if (ic->ic_txpowlimit/2 >= rrq->value) { +- vap->iv_bss->ni_txpower = 2 * rrq->value; +- ic->ic_newtxpowlimit = 2 * rrq->value; +- ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; +- } +- else +- return -EINVAL; +- } ++ ic->ic_txpowlimit = 2 * rrq->value; ++ ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; + } else { + if (!fixed) /* no change */ + return 0; +- ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX; ++ ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; + ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED; + } + done: +@@ -1588,9 +1574,22 @@ ieee80211_ioctl_giwtxpow(struct net_devi + { + struct ieee80211vap *vap = dev->priv; + struct ieee80211com *ic = vap->iv_ic; +- +- rrq->value = vap->iv_bss->ni_txpower / 2; +- rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0; ++ unsigned int power = ic->ic_txpowlimit; ++ struct ieee80211_channel *c; ++ u_int16_t txp = ic->ic_max_txpower; ++ ++ if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC)) { ++ txp = min(txp, (u16) ic->ic_bsschan->ic_maxpower); ++ } else if (ic->ic_cur_txpower > 0) { ++ txp = min(txp, ic->ic_cur_txpower); ++ } ++ if (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) { ++ txp = min(txp, ic->ic_txpowlimit); ++ rrq->fixed = 1; ++ } else { ++ rrq->fixed = 0; ++ } ++ rrq->value = txp / 2; + rrq->disabled = (rrq->fixed && rrq->value == 0); + rrq->flags = IW_TXPOW_DBM; + return 0; +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -380,7 +380,6 @@ static unsigned int ath_dump_hal_map(str + static u_int32_t ath_get_clamped_maxtxpower(struct ath_softc *sc); + static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, + u_int32_t new_clamped_maxtxpower); +-static u_int32_t ath_get_real_maxtxpower(struct ath_softc *sc); + + static void ath_poll_disable(struct net_device *dev); + static void ath_poll_enable(struct net_device *dev); +@@ -3159,7 +3158,7 @@ ath_tx_startraw(struct net_device *dev, + try0 = ph->try0; + rt = sc->sc_currates; + txrate = dot11_to_ratecode(sc, rt, ph->rate0); +- power = ph->power > 60 ? 60 : ph->power; ++ power = ph->power > 63 ? 63 : ph->power; + hdrlen = ieee80211_anyhdrsize(wh); + pktlen = skb->len + IEEE80211_CRC_LEN; + +@@ -8381,7 +8380,7 @@ ath_tx_start(struct net_device *dev, str + pktlen, /* packet length */ + hdrlen, /* header length */ + atype, /* Atheros packet type */ +- MIN(ni->ni_txpower, 60), /* txpower */ ++ MIN(ni->ni_txpower, 63), /* txpower */ + txrate, try0, /* series 0 rate/tries */ + keyix, /* key cache index */ + antenna, /* antenna mode */ +@@ -10364,59 +10363,16 @@ ath_get_clamped_maxtxpower(struct ath_so + + /* XXX: this function needs some locking to avoid being called + * twice/interrupted */ +-/* 1. Save the currently specified maximum txpower (as clamped by madwifi) +- * 2. Determine the real maximum txpower the card can support by +- * setting a value that exceeds the maximum range (by one) and +- * finding out what it limits us to. +- * 3. Restore the saved maxtxpower value we had previously specified */ +-static u_int32_t +-ath_get_real_maxtxpower(struct ath_softc *sc) +-{ +- u_int32_t saved_clamped_maxtxpower; +- u_int32_t real_maxtxpower; +- +- saved_clamped_maxtxpower = ath_get_clamped_maxtxpower(sc); +- real_maxtxpower = +- ath_set_clamped_maxtxpower(sc, IEEE80211_TXPOWER_MAX + 1); +- ath_set_clamped_maxtxpower(sc, saved_clamped_maxtxpower); +- return real_maxtxpower; +-} +- +- +-/* XXX: this function needs some locking to avoid being called +- * twice/interrupted */ + static void + ath_update_txpow(struct ath_softc *sc) + { + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = NULL; + struct ath_hal *ah = sc->sc_ah; +- u_int32_t prev_clamped_maxtxpower = 0; +- u_int32_t new_clamped_maxtxpower = 0; + + /* Determine the previous value of maxtxpower */ +- prev_clamped_maxtxpower = ath_get_clamped_maxtxpower(sc); +- /* Determine the real maximum txpower the card can support */ +- ic->ic_txpowlimit = ath_get_real_maxtxpower(sc); +- /* Grab the new maxtxpower setting (which may have changed) */ +- new_clamped_maxtxpower = ic->ic_newtxpowlimit; +- /* Make sure the change is within limits, clamp it otherwise */ +- if (ic->ic_newtxpowlimit > ic->ic_txpowlimit) +- new_clamped_maxtxpower = ic->ic_txpowlimit; +- /* Search for the VAP that needs a txpow change, if any */ +- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { +- if (!tpc || ic->ic_newtxpowlimit != vap->iv_bss->ni_txpower) { +- vap->iv_bss->ni_txpower = new_clamped_maxtxpower; +- ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, +- set_node_txpower, +- &new_clamped_maxtxpower); +- } +- } +- +- /* Store the assigned (clamped) maximum txpower and update the HAL */ +- sc->sc_curtxpow = new_clamped_maxtxpower; +- if (new_clamped_maxtxpower != prev_clamped_maxtxpower) +- ath_hal_settxpowlimit(ah, new_clamped_maxtxpower); ++ ath_set_clamped_maxtxpower(sc, ic->ic_txpowlimit); ++ ic->ic_cur_txpower = ath_get_clamped_maxtxpower(sc); + } + + #ifdef ATH_SUPERG_XR diff --git a/package/madwifi/patches/415-chan_switch.patch b/package/madwifi/patches/415-chan_switch.patch new file mode 100644 index 0000000000..85050647ca --- /dev/null +++ b/package/madwifi/patches/415-chan_switch.patch @@ -0,0 +1,187 @@ +--- a/net80211/ieee80211_beacon.c ++++ b/net80211/ieee80211_beacon.c +@@ -224,18 +224,18 @@ ieee80211_beacon_alloc(struct ieee80211_ + pktlen = 8 /* time stamp */ + + sizeof(u_int16_t) /* beacon interval */ + + sizeof(u_int16_t) /* capability information */ +- + 2 + ni->ni_esslen /* ssid */ ++ + 2 + IEEE80211_NWID_LEN /* ssid */ + + 2 + IEEE80211_RATE_SIZE /* supported rates */ + + 7 /* FH/DS parameters max(7,3) */ +- + 2 + 4 + vap->iv_tim_len /* IBSS/TIM parameter set*/ ++ + sizeof(struct ieee80211_tim_ie) + 128 /* IBSS/TIM parameter set*/ + + ic->ic_country_ie.country_len + 2 /* country code */ + + 3 /* power constraint */ + + 5 /* channel switch announcement */ + + 3 /* ERP */ + + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) /* Ext. Supp. Rates */ +- + (vap->iv_caps & IEEE80211_C_WME ? /* WME */ ++ + (ic->ic_caps & IEEE80211_C_WME ? /* WME */ + sizeof(struct ieee80211_wme_param) : 0) +- + (vap->iv_caps & IEEE80211_C_WPA ? /* WPA 1+2 */ ++ + (ic->ic_caps & IEEE80211_C_WPA ? /* WPA 1+2 */ + 2 * sizeof(struct ieee80211_ie_wpa) : 0) + + sizeof(struct ieee80211_ie_athAdvCap) + #ifdef ATH_SUPERG_XR +@@ -290,17 +290,26 @@ ieee80211_beacon_update(struct ieee80211 + IEEE80211_LOCK_IRQ(ic); + + /* Check if we need to change channel right now */ +- if ((ic->ic_flags & IEEE80211_F_DOTH) && +- (vap->iv_flags & IEEE80211_F_CHANSWITCH)) { +- struct ieee80211_channel *c = ++ if (ic->ic_flags & IEEE80211_F_CHANSWITCH) { ++ struct ieee80211_channel *c = + ieee80211_doth_findchan(vap, ic->ic_chanchange_chan); +- +- if (!vap->iv_chanchange_count && !c) { +- vap->iv_flags &= ~IEEE80211_F_CHANSWITCH; +- ic->ic_flags &= ~IEEE80211_F_CHANSWITCH; +- } else if (vap->iv_chanchange_count && +- ((!ic->ic_chanchange_tbtt) || +- (vap->iv_chanchange_count == ic->ic_chanchange_tbtt))) { ++ struct ieee80211vap *avp; ++ int do_switch = 1; ++ ++ TAILQ_FOREACH(avp, &ic->ic_vaps, iv_next) { ++ if (!(avp->iv_flags & IEEE80211_F_CHANSWITCH)) ++ continue; ++ ++ do_switch = 0; ++ break; ++ } ++ if (vap->iv_flags & IEEE80211_F_CHANSWITCH) { ++ if (vap->iv_chanchange_count-- <= 1) { ++ vap->iv_flags &= ~IEEE80211_F_CHANSWITCH; ++ vap->iv_chanchange_count = 0; ++ } ++ } ++ if (do_switch) { + u_int8_t *frm; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, +@@ -316,16 +325,7 @@ ieee80211_beacon_update(struct ieee80211 + } else + ic->ic_bsschan = c; + +- skb_pull(skb, sizeof(struct ieee80211_frame)); +- skb_trim(skb, 0); +- frm = skb->data; +- skb_put(skb, ieee80211_beacon_init(ni, bo, frm) - frm); +- skb_push(skb, sizeof(struct ieee80211_frame)); +- +- vap->iv_chanchange_count = 0; +- vap->iv_flags &= ~IEEE80211_F_CHANSWITCH; + ic->ic_flags &= ~IEEE80211_F_CHANSWITCH; +- + /* NB: Only for the first VAP to get here, and when we + * have a valid channel to which to change. */ + if (c && (ic->ic_curchan != c)) { +@@ -488,22 +488,20 @@ ieee80211_beacon_update(struct ieee80211 + + if (IEEE80211_IS_MODE_BEACON(vap->iv_opmode)) { + +- if ((ic->ic_flags & IEEE80211_F_DOTH) && +- (ic->ic_flags & IEEE80211_F_CHANSWITCH)) { ++ if (ic->ic_flags & IEEE80211_F_CHANSWITCH) { + struct ieee80211_ie_csa *csa_ie = + (struct ieee80211_ie_csa *)bo->bo_chanswitch; + +- IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, ++ if (csa_ie->csa_len == 0) { ++ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, + "%s: Sending 802.11h chanswitch IE: " + "%d/%d\n", __func__, + ic->ic_chanchange_chan, + ic->ic_chanchange_tbtt); +- if (!vap->iv_chanchange_count) { +- vap->iv_flags |= IEEE80211_F_CHANSWITCH; + + /* copy out trailer to open up a slot */ + memmove(bo->bo_chanswitch + sizeof(*csa_ie), +- bo->bo_chanswitch, ++ bo->bo_chanswitch, + bo->bo_chanswitch_trailerlen); + + /* add ie in opened slot */ +@@ -523,17 +521,15 @@ ieee80211_beacon_update(struct ieee80211 + bo->bo_ath_caps += sizeof(*csa_ie); + bo->bo_xr += sizeof(*csa_ie); + +- /* indicate new beacon length so other layers ++ /* indicate new beacon length so other layers + * may manage memory */ + skb_put(skb, sizeof(*csa_ie)); + len_changed = 1; +- } else if(csa_ie->csa_count) +- csa_ie->csa_count--; +- +- vap->iv_chanchange_count++; +- IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, +- "%s: CHANSWITCH IE, change in %d TBTT\n", +- __func__, csa_ie->csa_count); ++ ++ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, ++ "%s: CHANSWITCH IE, change in %d TBTT\n", ++ __func__, csa_ie->csa_count); ++ } + } + #ifdef ATH_SUPERG_XR + if (vap->iv_flags & IEEE80211_F_XRUPDATE) { +--- a/net80211/ieee80211_wireless.c ++++ b/net80211/ieee80211_wireless.c +@@ -699,39 +699,11 @@ ieee80211_ioctl_siwfreq(struct net_devic + if (c == NULL) /* no channel */ + return -EINVAL; + } +- /* +- * Fine tune channel selection based on desired mode: +- * if 11b is requested, find the 11b version of any +- * 11g channel returned, +- * if static turbo, find the turbo version of any +- * 11a channel return, +- * otherwise we should be ok with what we've got. +- */ +- switch (vap->iv_des_mode) { +- case IEEE80211_MODE_11B: +- if (IEEE80211_IS_CHAN_ANYG(c)) { +- c2 = findchannel(ic, i, IEEE80211_MODE_11B); +- /* NB: should not happen, =>'s 11g w/o 11b */ +- if (c2 != NULL) +- c = c2; +- } +- break; +- case IEEE80211_MODE_TURBO_A: +- if (IEEE80211_IS_CHAN_A(c)) { +- c2 = findchannel(ic, i, IEEE80211_MODE_TURBO_A); +- if (c2 != NULL) +- c = c2; +- } +- break; +- default: /* NB: no static turboG */ +- break; +- } ++ + if (ieee80211_check_mode_consistency(ic, vap->iv_des_mode, c)) { + if (vap->iv_opmode == IEEE80211_M_HOSTAP) + return -EINVAL; + } +- if ((vap->iv_state == IEEE80211_S_RUN) && (c == vap->iv_des_chan)) +- return 0; /* no change, return */ + + /* Don't allow to change to channel with radar found */ + if (c->ic_flags & IEEE80211_CHAN_RADAR) +@@ -4625,7 +4597,13 @@ static void + pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) { + struct ieee80211vap *vap = dev->priv; + struct ieee80211com *ic = vap->iv_ic; ++ struct ieee80211vap *avp; ++ + /* now flag the beacon update to include the channel switch IE */ ++ TAILQ_FOREACH(avp, &ic->ic_vaps, iv_next) { ++ avp->iv_flags |= IEEE80211_F_CHANSWITCH; ++ avp->iv_chanchange_count = tbtt; ++ } + ic->ic_flags |= IEEE80211_F_CHANSWITCH; + ic->ic_chanchange_chan = channel; + ic->ic_chanchange_tbtt = tbtt; diff --git a/package/madwifi/patches/417-beacon_txpower.patch b/package/madwifi/patches/417-beacon_txpower.patch new file mode 100644 index 0000000000..4746116c41 --- /dev/null +++ b/package/madwifi/patches/417-beacon_txpower.patch @@ -0,0 +1,81 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -395,7 +395,7 @@ static int bstuck_thresh = BSTUCK_THRESH + static char *autocreate = NULL; + static char *ratectl = DEF_RATE_CTL; + static int rfkill = 0; +-static int tpc = 0; ++static int tpc = 1; + static int countrycode = -1; + static int maxvaps = -1; + static int outdoor = -1; +@@ -4923,6 +4923,7 @@ ath_beacon_setup(struct ath_softc *sc, s + (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\ + == IEEE80211_F_SHPREAMBLE) + struct ieee80211com *ic = bf->bf_node->ni_ic; ++ struct ieee80211vap *vap = bf->bf_node->ni_vap; + struct sk_buff *skb = bf->bf_skb; + struct ath_hal *ah = sc->sc_ah; + struct ath_desc *ds; +@@ -4990,7 +4991,7 @@ ath_beacon_setup(struct ath_softc *sc, s + skb->len + IEEE80211_CRC_LEN, /* frame length */ + sizeof(struct ieee80211_frame), /* header length */ + HAL_PKT_TYPE_BEACON, /* Atheros packet type */ +- bf->bf_node->ni_txpower, /* txpower XXX */ ++ (vap->iv_beacon_txpow ? vap->iv_beacon_txpow : 63), + rate, 1, /* series 0 rate/tries */ + HAL_TXKEYIX_INVALID, /* no encryption */ + antenna, /* antenna mode */ +--- a/net80211/ieee80211_ioctl.h ++++ b/net80211/ieee80211_ioctl.h +@@ -652,6 +652,7 @@ enum { + IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */ + IEEE80211_PARAM_MAXASSOC = 83, /* maximum associated stations */ + IEEE80211_PARAM_PROBEREQ = 84, /* enable handling of probe requests */ ++ IEEE80211_PARAM_BEACON_TXP = 85, /* set beacon tx power */ + }; + + #define SIOCG80211STATS (SIOCDEVPRIVATE+2) +--- a/net80211/ieee80211_var.h ++++ b/net80211/ieee80211_var.h +@@ -254,6 +254,7 @@ struct ieee80211vap { + u_int8_t iv_dtim_period; /* DTIM period */ + u_int8_t iv_dtim_count; /* DTIM count from last bcn */ + /* set/unset aid pwrsav state */ ++ u_int8_t iv_beacon_txpow; /* beacon tx power */ + void (*iv_set_tim)(struct ieee80211_node *, int); + u_int8_t iv_uapsdinfo; /* sta mode QoS Info flags */ + struct ieee80211_node *iv_bss; /* information for this node */ +--- a/net80211/ieee80211_wireless.c ++++ b/net80211/ieee80211_wireless.c +@@ -2862,6 +2862,9 @@ ieee80211_ioctl_setparam(struct net_devi + case IEEE80211_PARAM_PROBEREQ: + vap->iv_no_probereq = !value; + break; ++ case IEEE80211_PARAM_BEACON_TXP: ++ vap->iv_beacon_txpow = value; ++ break; + #ifdef ATH_REVERSE_ENGINEERING + case IEEE80211_PARAM_DUMPREGS: + ieee80211_dump_registers(dev, info, w, extra); +@@ -3227,6 +3230,9 @@ ieee80211_ioctl_getparam(struct net_devi + case IEEE80211_PARAM_PROBEREQ: + param[0] = !vap->iv_no_probereq; + break; ++ case IEEE80211_PARAM_BEACON_TXP: ++ param[0] = vap->iv_beacon_txpow; ++ break; + default: + return -EOPNOTSUPP; + } +@@ -5801,6 +5807,10 @@ static const struct iw_priv_args ieee802 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "probereq"}, + { IEEE80211_PARAM_PROBEREQ, + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_probereq"}, ++ { IEEE80211_PARAM_BEACON_TXP, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_pwr"}, ++ { IEEE80211_PARAM_BEACON_TXP, ++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_beacon_pwr"}, + + #ifdef ATH_REVERSE_ENGINEERING + /* diff --git a/package/madwifi/patches/418-turbo.patch b/package/madwifi/patches/418-turbo.patch new file mode 100644 index 0000000000..4e13f90d20 --- /dev/null +++ b/package/madwifi/patches/418-turbo.patch @@ -0,0 +1,15 @@ +--- a/net80211/ieee80211_scan.c ++++ b/net80211/ieee80211_scan.c +@@ -1129,7 +1129,11 @@ ieee80211_scan_add_channels(struct ieee8 + continue; + if (c->ic_scanflags & IEEE80211_NOSCAN_SET) + continue; +- if (modeflags && ++ if (ss->ss_vap->iv_opmode == IEEE80211_M_HOSTAP) { ++ if ((c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)) != ++ (modeflags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO))) ++ continue; ++ } else if (modeflags && + ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) != + (modeflags & IEEE80211_CHAN_ALLTURBO))) + continue; diff --git a/package/madwifi/patches/419-skb_unmap_crash.patch b/package/madwifi/patches/419-skb_unmap_crash.patch new file mode 100644 index 0000000000..28e72747c6 --- /dev/null +++ b/package/madwifi/patches/419-skb_unmap_crash.patch @@ -0,0 +1,20 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -13477,7 +13477,7 @@ cleanup_ath_buf(struct ath_softc *sc, st + if (bf == NULL) + return bf; + +- if (bf->bf_skbaddr) { ++ if (bf->bf_skb && bf->bf_skbaddr) { + bus_unmap_single( + sc->sc_bdev, + bf->bf_skbaddr, +@@ -13485,8 +13485,6 @@ cleanup_ath_buf(struct ath_softc *sc, st + sc->sc_rxbufsize : bf->bf_skb->len), + direction); + bf->bf_skbaddr = 0; +- bf->bf_desc->ds_link = 0; +- bf->bf_desc->ds_data = 0; + } + + #ifdef ATH_SUPERG_FF diff --git a/package/madwifi/patches/420-diversity_fix.patch b/package/madwifi/patches/420-diversity_fix.patch new file mode 100644 index 0000000000..b7d26d976d --- /dev/null +++ b/package/madwifi/patches/420-diversity_fix.patch @@ -0,0 +1,30 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -5344,27 +5344,6 @@ ath_beacon_send(struct ath_softc *sc, in + } else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot)) + ath_setslottime(sc); /* commit change to hardware */ + +- if ((!sc->sc_stagbeacons || slot == 0) && (!sc->sc_diversity)) { +- unsigned int otherant; +- /* +- * Check recent per-antenna transmit statistics and flip +- * the default rx antenna if noticeably more frames went out +- * on the non-default antenna. Only do this if rx diversity +- * is off. +- * XXX assumes 2 antennae +- */ +- otherant = sc->sc_defant & 1 ? 2 : 1; +- if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + +- ATH_ANTENNA_DIFF) { +- DPRINTF(sc, ATH_DEBUG_BEACON, +- "Flip default antenna to %u, %u > %u\n", +- otherant, sc->sc_ant_tx[otherant], +- sc->sc_ant_tx[sc->sc_defant]); +- ath_setdefantenna(sc, otherant); +- } +- sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0; +- } +- + if (bfaddr != 0) { + /* + * Stop any current DMA and put the new frame(s) on the queue. diff --git a/package/madwifi/patches/450-new_hal.patch b/package/madwifi/patches/450-new_hal.patch deleted file mode 100644 index 324f7dd6b3..0000000000 --- a/package/madwifi/patches/450-new_hal.patch +++ /dev/null @@ -1,135 +0,0 @@ ---- a/ath_hal/ah_os.h -+++ b/ath_hal/ah_os.h -@@ -156,80 +156,23 @@ extern u_int32_t __ahdecl ath_hal_getupt - #endif - #endif /* AH_BYTE_ORDER */ - --/* -- * Some big-endian architectures don't set CONFIG_GENERIC_IOMAP, but fail to -- * implement iowrite32be and ioread32be. Provide compatibility macros when -- * it's needed. -- * -- * As of Linux 2.6.24, only MIPS, PARISC and PowerPC implement iowrite32be and -- * ioread32be as functions. -- * -- * The downside or the replacement macros it that we may be byte-swapping data -- * for the second time, so the native implementations should be preferred. -- */ --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) && \ -- !defined(CONFIG_GENERIC_IOMAP) && (AH_BYTE_ORDER == AH_BIG_ENDIAN) && \ -- !defined(__mips__) && !defined(__hppa__) && !defined(__powerpc__) --# ifndef iowrite32be --# define iowrite32be(_val, _addr) iowrite32(swab32((_val)), (_addr)) --# endif --# ifndef ioread32be --# define ioread32be(_addr) swab32(ioread32((_addr))) --# endif --#endif -+#define IS_SWAPPED(_ah, _reg) \ -+ ((_ah)->ah_swapped && \ -+ (((0x4000 <= (_reg)) && ((_reg) < 0x5000)) || \ -+ ((0x7000 <= (_reg)) && ((_reg) < 0x8000)))) -+ -+#define SWAPREG(_ah, _reg, _val) \ -+ (IS_SWAPPED(_ah, _reg) ? cpu_to_le32(_val) : (_val)) - - /* - * The register accesses are done using target-specific functions when - * debugging is enabled (AH_DEBUG) or it's explicitly requested for the target. -- * -- * The hardware registers use little-endian byte order natively. Big-endian -- * systems are configured by HAL to enable hardware byte-swap of register reads -- * and writes at reset. This avoid the need to byte-swap the data in software. -- * However, the registers in a certain area from 0x4000 to 0x4fff (PCI clock -- * domain registers) are not byte swapped! -- * -- * Since Linux I/O primitives default to little-endian operations, we only -- * need to suppress byte-swapping on big-endian systems outside the area used -- * by the PCI clock domain registers. - */ --#if (AH_BYTE_ORDER == AH_BIG_ENDIAN) --#define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000)) --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) --#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- is_reg_le(_reg) ? \ -- iowrite32((_val), (_ah)->ah_sh + (_reg)) : \ -- iowrite32be((_val), (_ah)->ah_sh + (_reg)); \ -- } while (0) --#define _OS_REG_READ(_ah, _reg) \ -- (is_reg_le(_reg) ? \ -- ioread32((_ah)->ah_sh + (_reg)) : \ -- ioread32be((_ah)->ah_sh + (_reg))) --#else --#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- writel(is_reg_le(_reg) ? \ -- (_val) : cpu_to_le32(_val), \ -- (_ah)->ah_sh + (_reg)); \ -- } while (0) --#define _OS_REG_READ(_ah, _reg) \ -- (is_reg_le(_reg) ? \ -- readl((_ah)->ah_sh + (_reg)) : \ -- cpu_to_le32(readl((_ah)->ah_sh + (_reg)))) --#endif /* KERNEL_VERSION(2,6,12) */ --#else /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) --#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- iowrite32((_val), (_ah)->ah_sh + (_reg)); \ -- } while (0) --#define _OS_REG_READ(_ah, _reg) \ -- ioread32((_ah)->ah_sh + (_reg)) --#else - #define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- writel((_val), (_ah)->ah_sh + (_reg)); \ -- } while (0) -+ __raw_writel(SWAPREG(_ah, _reg, _val), (_ah)->ah_sh + (_reg)); \ -+} while (0) - #define _OS_REG_READ(_ah, _reg) \ -- readl((_ah)->ah_sh + (_reg)) --#endif /* KERNEL_VERSION(2,6,12) */ --#endif /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ -+ SWAPREG(_ah, _reg, __raw_readl((_ah)->ah_sh + (_reg))) - - /* - * The functions in this section are not intended to be invoked by MadWifi ---- a/ath/if_ath.c -+++ b/ath/if_ath.c -@@ -606,6 +606,14 @@ ath_attach(u_int16_t devid, struct net_d - } - sc->sc_ah = ah; - -+ /* WAR for AR7100 PCI bug */ -+#ifdef CONFIG_ATHEROS_AR71XX -+ if ((ar_device(sc->devid) >= 5210) && (ar_device(sc->devid) < 5416)) { -+ ath_hal_setcapability(ah, HAL_CAP_DMABURST_RX, 0, HAL_DMABURST_4B, NULL); -+ ath_hal_setcapability(ah, HAL_CAP_DMABURST_TX, 0, HAL_DMABURST_4B, NULL); -+ } -+#endif -+ - /* - * Check if the MAC has multi-rate retry support. - * We do this by trying to setup a fake extended -@@ -7524,7 +7532,7 @@ ath_txq_setup(struct ath_softc *sc, int - if (qtype == HAL_TX_QUEUE_UAPSD) - qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; - else -- qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | -+ qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXOKINT_ENABLE | - HAL_TXQ_TXDESCINT_ENABLE; - qnum = ath_hal_setuptxqueue(ah, qtype, &qi); - if (qnum == -1) { ---- a/ath_hal/ah_os.c -+++ b/ath_hal/ah_os.c -@@ -126,6 +126,13 @@ ath_hal_printf(struct ath_hal *ah, const - } - EXPORT_SYMBOL(ath_hal_printf); - -+void __ahdecl -+ath_hal_printstr(struct ath_hal *ah, const char *str) -+{ -+ printk("%s", str); -+} -+EXPORT_SYMBOL(ath_hal_printstr); -+ - /* - * Format an Ethernet MAC for printing. - */