* Re: [PATCH] cfg80211: Fix user-space crda query stall
From: Luis R. Rodriguez @ 2010-05-25 19:19 UTC (permalink / raw)
To: Juuso Oikarinen; +Cc: linville, linux-wireless
In-Reply-To: <AANLkTinMo6L_LuCgcu9izxUVsFbi7kamHD2F_xThwJ2R@mail.gmail.com>
On Tue, May 25, 2010 at 12:02 PM, Luis R. Rodriguez <mcgrof@gmail.com> wrote:
> On Mon, May 24, 2010 at 11:50 PM, Juuso Oikarinen
> <juuso.oikarinen@nokia.com> wrote:
>> The userspace crda utility can fail to respond to kernel requests in (at least)
>> two scenarios: it is not runnable for any reason, or it is invoked with a
>> country code not in its database.
>>
>> When the userspace crda utility fails to respond to kernel requests (i.e. it
>> does not use NL80211_CMD_SET_REG to provide the kernel regulatory information
>> for the requested country) the kernel crda subsystem will stall. It will
>> refuse to process any further regulatory hints. This is easiest demonstrated
>> by using for instance the "iw" tool:
>>
>> iw reg set EU
>> iw reg set US
>>
>> "EU" is not a country code present in the database, so user space crda will
>> not respond. Attempting to define US after that will be silently ignored
>> (internally, an -EAGAIN is the result, as the "EU" request is still
>> "being processed".)
>>
>> To fix this issue, this patch implements timeout protection for the userspace
>> crda invocation. If there is no response for five seconds, the crda code will
>> force itself to the world regulatory domain for maximum safety.
>>
>> Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
>
> This is a great idea, I really like it and appreciate you taking the
> time to work on this, however to do this it requires a little more
> work and will point out the notes below. So NACK for now but with some
> fixes I think this would be great.
>
>> ---
>> net/wireless/reg.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
>> 1 files changed, 44 insertions(+), 0 deletions(-)
>>
>> diff --git a/net/wireless/reg.c b/net/wireless/reg.c
>> index 8f0d97d..6c945f0 100644
>> --- a/net/wireless/reg.c
>> +++ b/net/wireless/reg.c
>> @@ -385,6 +385,40 @@ static inline void reg_regdb_query(const char *alpha2) {}
>> #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
>>
>> /*
>> + * This gets invoked if crda in userspace is not responding (it's not getting
>> + * executed or the country code in the hint is not in the database.
>> + */
>> +
>> +static void call_crda_timeout_work(struct work_struct *work)
>> +{
>> + if (!last_request)
>> + return;
>> +
>> + printk(KERN_INFO "cfg80211: crda request timed out, reverting to 00\n");
>> +
>> + mutex_lock(&cfg80211_mutex);
>> +
>> + /*
>> + * As we are not getting data for the current country, force us back
>> + * to the world regdomain.
>> + */
>> + last_request->alpha2[0] = '0';
>> + last_request->alpha2[1] = '0';
>> + set_regdom(cfg80211_world_regdom);
>> + mutex_unlock(&cfg80211_mutex);
>> +}
>
>
> Actually you may want to consider using restore_regulatory_settings()
> instead as that would:
>
> * set the world regdom
> * then set the first user specified regulatory domain if they had one picked
>
> This would mean we would go into a loop here though if the user had
> specified 'EU' though so this routine first needs to be fixed to
> annotate a regulatory domain as invalid. Note that a regulatory cannot
> be invalid if CRDA just times out -- CRDA could time out if it was not
> present. So this is a bit tricky and not sure how to resolve it. John
> recently added support for building the regulatory database as part of
> the kernel but at the same time support letting CRDA still update the
> same info if it is present. Then for those setup it could be possible
> 'DE' exists on the core kernel regulatory database but if CRDA is not
> installed then CRDA will time out.
>
> Maybe what we can do is if both the internal kernel regdb *and* CRDA
> times out then mark the user specified request as invalid and restore
> to using the world regdom. This would allow the user to later install
> a CRDA with some newer regdb in userspace, for example. This allows
> for upgrading the db itself from userspace without making kernel
> changes. It allows for countries to be created.
>
>> +
>> +static DECLARE_WORK(crda_uevent_timeout_work, call_crda_timeout_work);
>> +
>> +#define CRDA_UEVENT_TIMEOUT 5000
>> +static void crda_uevent_timeout(unsigned long data)
>> +{
>> + schedule_work(&crda_uevent_timeout_work);
>> +}
>> +
>> +static DEFINE_TIMER(crda_uevent_timer, crda_uevent_timeout, 0, 0);
>
> I would prefer we use a completion here, seems a little cleaner. Check
> out ath9k/wmi.c for cmd_wait and its use with init_completion() and
> complete().
Actually it makes no sense to linger a thread here waiting for a
completion, your approach is better, never mind this comment.
Luis
^ permalink raw reply
* Re: pull request: wireless-2.6 2010-05-25
From: Sedat Dilek @ 2010-05-25 19:23 UTC (permalink / raw)
To: John W. Linville; +Cc: davem, linux-wireless, netdev, linux-kernel
In-Reply-To: <20100525170401.GE31753@tuxdriver.com>
"[1/2] iwlwifi: fix internal scan race" [1] is in this pull request.
Isn't "[2/2] iwlagn: work around rate scaling reset delay" [2] missing?
IIRC, both fixes were sent as a double-patch.
- Sedat -
[1] https://patchwork.kernel.org/patch/99439/
[2] https://patchwork.kernel.org/patch/99438/
On Tue, May 25, 2010 at 7:04 PM, John W. Linville
<linville@tuxdriver.com> wrote:
> Dave,
>
> Here are a number of fixes intended for 2.6.35. Included are some
> warning fixes from Randy, some smatch-identified fixes from Dan, some
> fixes for using ath9k and IBSS mode, the removal of a PCI ID that was
> optimistically added to ath9k, and a smattering of other driver fixes.
> This also includes a revert of "ath9k: Group Key fix for VAPs" which
> was reported to cause regressions due to a mac80211 change inside it
> that snuck past us... :-(
>
> Anyway, these are mostly small(ish) and obvious. Please let me know
> if there are problems!
>
> Thanks,
>
> John
>
> ---
>
> The following changes since commit acfbe96a3035639619a6533e04d88ed4ef9ccb61:
> Randy Dunlap (1):
> sock.h: fix kernel-doc warning
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master
>
> Bruno Randolf (1):
> ath5k: consistently use rx_bufsize for RX DMA
>
> Dan Carpenter (3):
> ath9k_htc: dereferencing before check in hif_usb_tx_cb()
> ath9k_htc: rare leak in ath9k_hif_usb_alloc_tx_urbs()
> iwlwifi: testing the wrong variable in iwl_add_bssid_station()
>
> Felix Fietkau (3):
> cfg80211: fix crash in cfg80211_set_freq()
> ath9k: change beacon allocation to prefer the first beacon slot
> ath9k: remove VEOL support for ad-hoc
>
> Gertjan van Wingerde (2):
> rt2x00: Fix failed SLEEP->AWAKE and AWAKE->SLEEP transitions.
> rt2x00: Fix rt2800usb TX descriptor writing.
>
> Helmut Schaa (1):
> rt2x00: don't use to_pci_dev in rt2x00pci_uninitialize
>
> Johannes Berg (1):
> cfg80211: add missing braces
>
> John W. Linville (1):
> Revert "ath9k: Group Key fix for VAPs"
>
> Jussi Kivilinna (1):
> rndis_wlan: replace wireless_send_event with cfg80211_disconnected
>
> Juuso Oikarinen (1):
> wl1271: Fix RX data path frame lengths
>
> Luis R. Rodriguez (1):
> ath9k: remove AR9003 from PCI IDs for now
>
> Randy Dunlap (2):
> wireless: fix mac80211.h kernel-doc warnings
> wireless: fix sta_info.h kernel-doc warnings
>
> Reinette Chatre (1):
> iwlwifi: fix internal scan race
>
> Sujith (1):
> cfg80211: Fix signal_type comparison
>
> Tejun Heo (1):
> wireless: update gfp/slab.h includes
>
> Vasanthakumar Thiagarajan (1):
> ath9k: Fix rx of mcast/bcast frames in PS mode with auto sleep
>
> drivers/net/wireless/ath/ath5k/base.c | 7 ++-
> drivers/net/wireless/ath/ath9k/beacon.c | 75 +++++-----------------------
> drivers/net/wireless/ath/ath9k/hif_usb.c | 10 +++-
> drivers/net/wireless/ath/ath9k/htc.h | 1 +
> drivers/net/wireless/ath/ath9k/main.c | 28 +---------
> drivers/net/wireless/ath/ath9k/pci.c | 1 -
> drivers/net/wireless/ath/ath9k/recv.c | 17 +++++--
> drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 1 +
> drivers/net/wireless/iwlwifi/iwl-scan.c | 21 +++++++-
> drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +-
> drivers/net/wireless/rndis_wlan.c | 16 ++++--
> drivers/net/wireless/rt2x00/rt2400pci.c | 9 ++--
> drivers/net/wireless/rt2x00/rt2500pci.c | 9 ++--
> drivers/net/wireless/rt2x00/rt2800usb.c | 2 +-
> drivers/net/wireless/rt2x00/rt2x00pci.c | 2 +-
> drivers/net/wireless/rt2x00/rt61pci.c | 7 ++-
> drivers/net/wireless/rt2x00/rt73usb.c | 7 ++-
> drivers/net/wireless/wl12xx/wl1271_rx.c | 2 +
> include/net/mac80211.h | 4 +-
> net/mac80211/key.c | 1 -
> net/mac80211/sta_info.h | 2 +-
> net/wireless/chan.c | 2 +-
> net/wireless/nl80211.c | 6 ++-
> net/wireless/scan.c | 4 +-
> 24 files changed, 104 insertions(+), 132 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
> index 5f04cf3..cc6d41d 100644
> --- a/drivers/net/wireless/ath/ath5k/base.c
> +++ b/drivers/net/wireless/ath/ath5k/base.c
> @@ -1214,6 +1214,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
> struct ath5k_hw *ah = sc->ah;
> struct sk_buff *skb = bf->skb;
> struct ath5k_desc *ds;
> + int ret;
>
> if (!skb) {
> skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
> @@ -1240,9 +1241,9 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
> ds = bf->desc;
> ds->ds_link = bf->daddr; /* link to self */
> ds->ds_data = bf->skbaddr;
> - ah->ah_setup_rx_desc(ah, ds,
> - skb_tailroom(skb), /* buffer size */
> - 0);
> + ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
> + if (ret)
> + return ret;
>
> if (sc->rxlink != NULL)
> *sc->rxlink = bf->daddr;
> diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
> index c8a4558..f43d85a 100644
> --- a/drivers/net/wireless/ath/ath9k/beacon.c
> +++ b/drivers/net/wireless/ath/ath9k/beacon.c
> @@ -76,22 +76,13 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
> ds = bf->bf_desc;
> flags = ATH9K_TXDESC_NOACK;
>
> - if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
> - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
> - (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
> - ds->ds_link = bf->bf_daddr; /* self-linked */
> - flags |= ATH9K_TXDESC_VEOL;
> - /* Let hardware handle antenna switching. */
> - antenna = 0;
> - } else {
> - ds->ds_link = 0;
> - /*
> - * Switch antenna every beacon.
> - * Should only switch every beacon period, not for every SWBA
> - * XXX assumes two antennae
> - */
> - antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
> - }
> + ds->ds_link = 0;
> + /*
> + * Switch antenna every beacon.
> + * Should only switch every beacon period, not for every SWBA
> + * XXX assumes two antennae
> + */
> + antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
>
> sband = &sc->sbands[common->hw->conf.channel->band];
> rate = sband->bitrates[rateidx].hw_value;
> @@ -215,36 +206,6 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
> return bf;
> }
>
> -/*
> - * Startup beacon transmission for adhoc mode when they are sent entirely
> - * by the hardware using the self-linked descriptor + veol trick.
> -*/
> -static void ath_beacon_start_adhoc(struct ath_softc *sc,
> - struct ieee80211_vif *vif)
> -{
> - struct ath_hw *ah = sc->sc_ah;
> - struct ath_common *common = ath9k_hw_common(ah);
> - struct ath_buf *bf;
> - struct ath_vif *avp;
> - struct sk_buff *skb;
> -
> - avp = (void *)vif->drv_priv;
> -
> - if (avp->av_bcbuf == NULL)
> - return;
> -
> - bf = avp->av_bcbuf;
> - skb = bf->bf_mpdu;
> -
> - ath_beacon_setup(sc, avp, bf, 0);
> -
> - /* NB: caller is known to have already stopped tx dma */
> - ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
> - ath9k_hw_txstart(ah, sc->beacon.beaconq);
> - ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
> - sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
> -}
> -
> int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
> {
> struct ath_softc *sc = aphy->sc;
> @@ -265,7 +226,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
> list_del(&avp->av_bcbuf->list);
>
> if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
> - !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
> + sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
> + sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
> int slot;
> /*
> * Assign the vif to a beacon xmit slot. As
> @@ -274,17 +236,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
> avp->av_bslot = 0;
> for (slot = 0; slot < ATH_BCBUF; slot++)
> if (sc->beacon.bslot[slot] == NULL) {
> - /*
> - * XXX hack, space out slots to better
> - * deal with misses
> - */
> - if (slot+1 < ATH_BCBUF &&
> - sc->beacon.bslot[slot+1] == NULL) {
> - avp->av_bslot = slot+1;
> - break;
> - }
> avp->av_bslot = slot;
> +
> /* NB: keep looking for a double slot */
> + if (slot == 0 || !sc->beacon.bslot[slot-1])
> + break;
> }
> BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
> sc->beacon.bslot[avp->av_bslot] = vif;
> @@ -721,8 +677,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
> * self-linked tx descriptor and let the hardware deal with things.
> */
> intval |= ATH9K_BEACON_ENA;
> - if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
> - ah->imask |= ATH9K_INT_SWBA;
> + ah->imask |= ATH9K_INT_SWBA;
>
> ath_beaconq_config(sc);
>
> @@ -732,10 +687,6 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
> ath9k_beacon_init(sc, nexttbtt, intval);
> sc->beacon.bmisscnt = 0;
> ath9k_hw_set_interrupts(ah, ah->imask);
> -
> - /* FIXME: Handle properly when vif is NULL */
> - if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
> - ath_beacon_start_adhoc(sc, vif);
> }
>
> void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
> index 46dc41a..77b3591 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> @@ -107,12 +107,14 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
> static void hif_usb_tx_cb(struct urb *urb)
> {
> struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
> - struct hif_device_usb *hif_dev = tx_buf->hif_dev;
> + struct hif_device_usb *hif_dev;
> struct sk_buff *skb;
>
> - if (!hif_dev || !tx_buf)
> + if (!tx_buf || !tx_buf->hif_dev)
> return;
>
> + hif_dev = tx_buf->hif_dev;
> +
> switch (urb->status) {
> case 0:
> break;
> @@ -607,6 +609,10 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
>
> return 0;
> err:
> + if (tx_buf) {
> + kfree(tx_buf->buf);
> + kfree(tx_buf);
> + }
> ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
> return -ENOMEM;
> }
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
> index ad556aa..c251603 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -23,6 +23,7 @@
> #include <linux/skbuff.h>
> #include <linux/netdevice.h>
> #include <linux/leds.h>
> +#include <linux/slab.h>
> #include <net/mac80211.h>
>
> #include "common.h"
> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> index 893b552..abfa049 100644
> --- a/drivers/net/wireless/ath/ath9k/main.c
> +++ b/drivers/net/wireless/ath/ath9k/main.c
> @@ -752,7 +752,6 @@ static int ath_key_config(struct ath_common *common,
> struct ath_hw *ah = common->ah;
> struct ath9k_keyval hk;
> const u8 *mac = NULL;
> - u8 gmac[ETH_ALEN];
> int ret = 0;
> int idx;
>
> @@ -776,30 +775,9 @@ static int ath_key_config(struct ath_common *common,
> memcpy(hk.kv_val, key->key, key->keylen);
>
> if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
> -
> - if (key->ap_addr) {
> - /*
> - * Group keys on hardware that supports multicast frame
> - * key search use a mac that is the sender's address with
> - * the high bit set instead of the app-specified address.
> - */
> - memcpy(gmac, key->ap_addr, ETH_ALEN);
> - gmac[0] |= 0x80;
> - mac = gmac;
> -
> - if (key->alg == ALG_TKIP)
> - idx = ath_reserve_key_cache_slot_tkip(common);
> - else
> - idx = ath_reserve_key_cache_slot(common);
> - if (idx < 0)
> - mac = NULL; /* no free key cache entries */
> - }
> -
> - if (!mac) {
> - /* For now, use the default keys for broadcast keys. This may
> - * need to change with virtual interfaces. */
> - idx = key->keyidx;
> - }
> + /* For now, use the default keys for broadcast keys. This may
> + * need to change with virtual interfaces. */
> + idx = key->keyidx;
> } else if (key->keyidx) {
> if (WARN_ON(!sta))
> return -EOPNOTSUPP;
> diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
> index 257b10b..1ec836c 100644
> --- a/drivers/net/wireless/ath/ath9k/pci.c
> +++ b/drivers/net/wireless/ath/ath9k/pci.c
> @@ -28,7 +28,6 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
> { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
> { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
> { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
> - { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
> { 0 }
> };
>
> diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
> index ba13913..ca6065b 100644
> --- a/drivers/net/wireless/ath/ath9k/recv.c
> +++ b/drivers/net/wireless/ath/ath9k/recv.c
> @@ -19,6 +19,12 @@
>
> #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb))
>
> +static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
> +{
> + return sc->ps_enabled &&
> + (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
> +}
> +
> static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
> struct ieee80211_hdr *hdr)
> {
> @@ -616,8 +622,8 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
> hdr = (struct ieee80211_hdr *)skb->data;
>
> /* Process Beacon and CAB receive in PS state */
> - if ((sc->ps_flags & PS_WAIT_FOR_BEACON) &&
> - ieee80211_is_beacon(hdr->frame_control))
> + if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc))
> + && ieee80211_is_beacon(hdr->frame_control))
> ath_rx_ps_beacon(sc, skb);
> else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
> (ieee80211_is_data(hdr->frame_control) ||
> @@ -932,9 +938,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
> sc->rx.rxotherant = 0;
> }
>
> - if (unlikely(sc->ps_flags & (PS_WAIT_FOR_BEACON |
> - PS_WAIT_FOR_CAB |
> - PS_WAIT_FOR_PSPOLL_DATA)))
> + if (unlikely(ath9k_check_auto_sleep(sc) ||
> + (sc->ps_flags & (PS_WAIT_FOR_BEACON |
> + PS_WAIT_FOR_CAB |
> + PS_WAIT_FOR_PSPOLL_DATA))))
> ath_rx_ps(sc, skb);
>
> ath_rx_send_to_mac80211(hw, sc, skb, rxs);
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
> index a273e37..c92b2c0 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
> @@ -30,6 +30,7 @@
> #include <linux/module.h>
> #include <linux/etherdevice.h>
> #include <linux/sched.h>
> +#include <linux/gfp.h>
> #include <net/mac80211.h>
>
> #include "iwl-dev.h"
> diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
> index 107e173..5d3f51f 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-scan.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
> @@ -376,6 +376,11 @@ void iwl_bg_start_internal_scan(struct work_struct *work)
>
> mutex_lock(&priv->mutex);
>
> + if (priv->is_internal_short_scan == true) {
> + IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
> + goto unlock;
> + }
> +
> if (!iwl_is_ready_rf(priv)) {
> IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
> goto unlock;
> @@ -497,17 +502,27 @@ void iwl_bg_scan_completed(struct work_struct *work)
> {
> struct iwl_priv *priv =
> container_of(work, struct iwl_priv, scan_completed);
> + bool internal = false;
>
> IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
>
> cancel_delayed_work(&priv->scan_check);
>
> - if (!priv->is_internal_short_scan)
> - ieee80211_scan_completed(priv->hw, false);
> - else {
> + mutex_lock(&priv->mutex);
> + if (priv->is_internal_short_scan) {
> priv->is_internal_short_scan = false;
> IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
> + internal = true;
> }
> + mutex_unlock(&priv->mutex);
> +
> + /*
> + * Do not hold mutex here since this will cause mac80211 to call
> + * into driver again into functions that will attempt to take
> + * mutex.
> + */
> + if (!internal)
> + ieee80211_scan_completed(priv->hw, false);
>
> if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> return;
> diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
> index 85ed235..83a2636 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-sta.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
> @@ -431,7 +431,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
> struct iwl_link_quality_cmd *link_cmd;
> unsigned long flags;
>
> - if (*sta_id_r)
> + if (sta_id_r)
> *sta_id_r = IWL_INVALID_STATION;
>
> ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
> diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
> index 2d28908..4bd61ee 100644
> --- a/drivers/net/wireless/rndis_wlan.c
> +++ b/drivers/net/wireless/rndis_wlan.c
> @@ -2572,14 +2572,18 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
>
> static void rndis_wlan_do_link_down_work(struct usbnet *usbdev)
> {
> - union iwreq_data evt;
> + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
>
> - netif_carrier_off(usbdev->net);
> + if (priv->connected) {
> + priv->connected = false;
> + memset(priv->bssid, 0, ETH_ALEN);
> +
> + deauthenticate(usbdev);
>
> - evt.data.flags = 0;
> - evt.data.length = 0;
> - memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
> - wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
> + cfg80211_disconnected(usbdev->net, 0, NULL, 0, GFP_KERNEL);
> + }
> +
> + netif_carrier_off(usbdev->net);
> }
>
> static void rndis_wlan_worker(struct work_struct *work)
> diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
> index 4ba7b03..ad2c98a 100644
> --- a/drivers/net/wireless/rt2x00/rt2400pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2400pci.c
> @@ -926,7 +926,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
> static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
> enum dev_state state)
> {
> - u32 reg;
> + u32 reg, reg2;
> unsigned int i;
> char put_to_sleep;
> char bbp_state;
> @@ -947,11 +947,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
> * device has entered the correct state.
> */
> for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> - rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®);
> - bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE);
> - rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE);
> + rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2);
> + bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
> + rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
> if (bbp_state == state && rf_state == state)
> return 0;
> + rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
> msleep(10);
> }
>
> diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
> index 89d132d..41da3d2 100644
> --- a/drivers/net/wireless/rt2x00/rt2500pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2500pci.c
> @@ -1084,7 +1084,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
> static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
> enum dev_state state)
> {
> - u32 reg;
> + u32 reg, reg2;
> unsigned int i;
> char put_to_sleep;
> char bbp_state;
> @@ -1105,11 +1105,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
> * device has entered the correct state.
> */
> for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> - rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®);
> - bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE);
> - rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE);
> + rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2);
> + bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
> + rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
> if (bbp_state == state && rf_state == state)
> return 0;
> + rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
> msleep(10);
> }
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
> index 0f8b84b..6991613 100644
> --- a/drivers/net/wireless/rt2x00/rt2800usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2800usb.c
> @@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
> */
> rt2x00_desc_read(txi, 0, &word);
> rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
> - skb->len + TXWI_DESC_SIZE);
> + skb->len - TXINFO_DESC_SIZE);
> rt2x00_set_field32(&word, TXINFO_W0_WIV,
> !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
> rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> index a016f7c..f71eee6 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> @@ -206,7 +206,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
> /*
> * Free irq line.
> */
> - free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev);
> + free_irq(rt2x00dev->irq, rt2x00dev);
>
> /*
> * Free DMA
> diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
> index 2e3076f..6a74baf 100644
> --- a/drivers/net/wireless/rt2x00/rt61pci.c
> +++ b/drivers/net/wireless/rt2x00/rt61pci.c
> @@ -1689,7 +1689,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
>
> static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
> {
> - u32 reg;
> + u32 reg, reg2;
> unsigned int i;
> char put_to_sleep;
>
> @@ -1706,10 +1706,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
> * device has entered the correct state.
> */
> for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> - rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®);
> - state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
> + rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®2);
> + state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
> if (state == !put_to_sleep)
> return 0;
> + rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg);
> msleep(10);
> }
>
> diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
> index e35bd19..6e0d82e 100644
> --- a/drivers/net/wireless/rt2x00/rt73usb.c
> +++ b/drivers/net/wireless/rt2x00/rt73usb.c
> @@ -1366,7 +1366,7 @@ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
>
> static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
> {
> - u32 reg;
> + u32 reg, reg2;
> unsigned int i;
> char put_to_sleep;
>
> @@ -1383,10 +1383,11 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
> * device has entered the correct state.
> */
> for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> - rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®);
> - state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
> + rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®2);
> + state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
> if (state == !put_to_sleep)
> return 0;
> + rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
> msleep(10);
> }
>
> diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
> index 57f4bfd..b98fb64 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_rx.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
> @@ -113,6 +113,8 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
> wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
> beacon ? "beacon" : "");
>
> + skb_trim(skb, skb->len - desc->pad_len);
> +
> memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
> ieee80211_rx_ni(wl->hw, skb);
> }
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index 5be900d..de22cbf 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -815,6 +815,7 @@ enum ieee80211_key_flags {
> * encrypted in hardware.
> * @alg: The key algorithm.
> * @flags: key flags, see &enum ieee80211_key_flags.
> + * @ap_addr: AP's MAC address
> * @keyidx: the key index (0-3)
> * @keylen: key material length
> * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte)
> @@ -831,7 +832,6 @@ struct ieee80211_key_conf {
> u8 iv_len;
> u8 hw_key_idx;
> u8 flags;
> - u8 *ap_addr;
> s8 keyidx;
> u8 keylen;
> u8 key[0];
> @@ -1638,6 +1638,8 @@ enum ieee80211_ampdu_mlme_action {
> * Returns a negative error code on failure.
> * The callback must be atomic.
> *
> + * @get_survey: Return per-channel survey information
> + *
> * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
> * need to set wiphy->rfkill_poll to %true before registration,
> * and need to call wiphy_rfkill_set_hw_state() in the callback.
> diff --git a/net/mac80211/key.c b/net/mac80211/key.c
> index 8d4b417..e8f6e3b 100644
> --- a/net/mac80211/key.c
> +++ b/net/mac80211/key.c
> @@ -140,7 +140,6 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
> struct ieee80211_sub_if_data,
> u.ap);
>
> - key->conf.ap_addr = sdata->dev->dev_addr;
> ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
>
> if (!ret) {
> diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
> index 48a5e80..df9d455 100644
> --- a/net/mac80211/sta_info.h
> +++ b/net/mac80211/sta_info.h
> @@ -145,7 +145,7 @@ enum plink_state {
> /**
> * struct sta_ampdu_mlme - STA aggregation information.
> *
> - * @tid_state_rx: TID's state in Rx session state machine.
> + * @tid_active_rx: TID's state in Rx session state machine.
> * @tid_rx: aggregation info for Rx per TID
> * @tid_state_tx: TID's state in Tx session state machine.
> * @tid_tx: aggregation info for Tx per TID
> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
> index d92d088..b01a6f6 100644
> --- a/net/wireless/chan.c
> +++ b/net/wireless/chan.c
> @@ -50,7 +50,7 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
> struct ieee80211_channel *chan;
> int result;
>
> - if (wdev->iftype == NL80211_IFTYPE_MONITOR)
> + if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR)
> wdev = NULL;
>
> if (wdev) {
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index aaa1aad..db71150 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -4443,9 +4443,10 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
> if (channel_type != NL80211_CHAN_NO_HT &&
> channel_type != NL80211_CHAN_HT20 &&
> channel_type != NL80211_CHAN_HT40PLUS &&
> - channel_type != NL80211_CHAN_HT40MINUS)
> + channel_type != NL80211_CHAN_HT40MINUS) {
> err = -EINVAL;
> goto out;
> + }
> }
>
> freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
> @@ -4717,9 +4718,10 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
> if (channel_type != NL80211_CHAN_NO_HT &&
> channel_type != NL80211_CHAN_HT20 &&
> channel_type != NL80211_CHAN_HT40PLUS &&
> - channel_type != NL80211_CHAN_HT40MINUS)
> + channel_type != NL80211_CHAN_HT40MINUS) {
> err = -EINVAL;
> goto out;
> + }
> }
>
> freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
> diff --git a/net/wireless/scan.c b/net/wireless/scan.c
> index a026c6d..58401d2 100644
> --- a/net/wireless/scan.c
> +++ b/net/wireless/scan.c
> @@ -515,7 +515,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
>
> privsz = wiphy->bss_priv_size;
>
> - if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
> + if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
> (signal < 0 || signal > 100)))
> return NULL;
>
> @@ -571,7 +571,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
> u.probe_resp.variable);
> size_t privsz = wiphy->bss_priv_size;
>
> - if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
> + if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
> (signal < 0 || signal > 100)))
> return NULL;
>
> --
> John W. Linville Someday the world will need a hero, and you
> linville@tuxdriver.com might be all we have. Be ready.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH] cfg80211: Fix user-space crda query stall
From: Luis R. Rodriguez @ 2010-05-25 19:22 UTC (permalink / raw)
To: Juuso Oikarinen, Johannes Berg; +Cc: linville, linux-wireless
In-Reply-To: <AANLkTinMo6L_LuCgcu9izxUVsFbi7kamHD2F_xThwJ2R@mail.gmail.com>
On Tue, May 25, 2010 at 12:02 PM, Luis R. Rodriguez <mcgrof@gmail.com> wrote:
> On Mon, May 24, 2010 at 11:50 PM, Juuso Oikarinen
> <juuso.oikarinen@nokia.com> wrote:
>> The userspace crda utility can fail to respond to kernel requests in (at least)
>> two scenarios: it is not runnable for any reason, or it is invoked with a
>> country code not in its database.
>>
>> When the userspace crda utility fails to respond to kernel requests (i.e. it
>> does not use NL80211_CMD_SET_REG to provide the kernel regulatory information
>> for the requested country) the kernel crda subsystem will stall. It will
>> refuse to process any further regulatory hints. This is easiest demonstrated
>> by using for instance the "iw" tool:
>>
>> iw reg set EU
>> iw reg set US
>>
>> "EU" is not a country code present in the database, so user space crda will
>> not respond. Attempting to define US after that will be silently ignored
>> (internally, an -EAGAIN is the result, as the "EU" request is still
>> "being processed".)
>>
>> To fix this issue, this patch implements timeout protection for the userspace
>> crda invocation. If there is no response for five seconds, the crda code will
>> force itself to the world regulatory domain for maximum safety.
>>
>> Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
>
> This is a great idea, I really like it and appreciate you taking the
> time to work on this, however to do this it requires a little more
> work and will point out the notes below. So NACK for now but with some
> fixes I think this would be great.
>
>> ---
>> net/wireless/reg.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
>> 1 files changed, 44 insertions(+), 0 deletions(-)
>>
>> diff --git a/net/wireless/reg.c b/net/wireless/reg.c
>> index 8f0d97d..6c945f0 100644
>> --- a/net/wireless/reg.c
>> +++ b/net/wireless/reg.c
>> @@ -385,6 +385,40 @@ static inline void reg_regdb_query(const char *alpha2) {}
>> #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
>>
>> /*
>> + * This gets invoked if crda in userspace is not responding (it's not getting
>> + * executed or the country code in the hint is not in the database.
>> + */
>> +
>> +static void call_crda_timeout_work(struct work_struct *work)
>> +{
>> + if (!last_request)
>> + return;
>> +
>> + printk(KERN_INFO "cfg80211: crda request timed out, reverting to 00\n");
>> +
>> + mutex_lock(&cfg80211_mutex);
>> +
>> + /*
>> + * As we are not getting data for the current country, force us back
>> + * to the world regdomain.
>> + */
>> + last_request->alpha2[0] = '0';
>> + last_request->alpha2[1] = '0';
>> + set_regdom(cfg80211_world_regdom);
>> + mutex_unlock(&cfg80211_mutex);
>> +}
>
>
> Actually you may want to consider using restore_regulatory_settings()
> instead as that would:
>
> * set the world regdom
> * then set the first user specified regulatory domain if they had one picked
>
> This would mean we would go into a loop here though if the user had
> specified 'EU' though so this routine first needs to be fixed to
> annotate a regulatory domain as invalid. Note that a regulatory cannot
> be invalid if CRDA just times out -- CRDA could time out if it was not
> present. So this is a bit tricky and not sure how to resolve it. John
> recently added support for building the regulatory database as part of
> the kernel but at the same time support letting CRDA still update the
> same info if it is present. Then for those setup it could be possible
> 'DE' exists on the core kernel regulatory database but if CRDA is not
> installed then CRDA will time out.
>
> Maybe what we can do is if both the internal kernel regdb *and* CRDA
> times out then mark the user specified request as invalid and restore
> to using the world regdom. This would allow the user to later install
> a CRDA with some newer regdb in userspace, for example. This allows
> for upgrading the db itself from userspace without making kernel
> changes. It allows for countries to be created.
We would also need to handle the case the user is already associated,
what do we do, do we disassociate? Maybe the right fix is to allow
user settings of the regulatory domain only if we are not associated.
Because otherwise we get into issues like what if the user was in 'IT'
but then chooses to be in 'EU' which is invalid, do we invalidate
their current settings / modes of operation / etc.
We already keep track of when we disassociate, but we do not sent an
event back to reg.c when we do, perhaps we need a counter for such
things on reg.c and only allow a user set regulatory domain if the
count is 0. Perhaps Johannes might have other better ideas how to do
this.
Luis
^ permalink raw reply
* Re: wireless-regdb: A band is missing for IL
From: Luis R. Rodriguez @ 2010-05-25 19:08 UTC (permalink / raw)
To: Emmanuel Grumbach, Michael Green, David Quan; +Cc: linville, linux-wireless
In-Reply-To: <AANLkTimkpbans5mUObR8PWzf2-Uh0K-cZVVg0HjNxnSv@mail.gmail.com>
Michael, please review and let us know what you think.
Luis
On Tue, May 25, 2010 at 12:03 AM, Emmanuel Grumbach <egrumbach@gmail.com> wrote:
> According to http://en.wikipedia.org/wiki/List_of_WLAN_channels#5.C2.A0GHz_.28802.11a.2Fh.2Fj.2Fn.29
>
> Channels 34 - 64 are allowed in 20 Mhz in Israel. This is not what is
> written in db.txt:
>
> country IL:
> (2402 - 2482 @ 40), (N/A, 20)
>
> This wikipedia page relies on an official page from the Israel
> Ministry of the Communication.
>
> Emmanuel Grumbach
> egrumbach@gmail.com
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: wireless-regdb: FI/CZ updates
From: Luis R. Rodriguez @ 2010-05-25 19:06 UTC (permalink / raw)
To: Pekka Pietikainen, Michael Green, David Quan; +Cc: linville, linux-wireless
In-Reply-To: <20100525132035.GA863@ee.oulu.fi>
Thanks for the patch, Michael, please review and let me know what you think.
Luis
On Tue, May 25, 2010 at 6:20 AM, Pekka Pietikainen <pp@ee.oulu.fi> wrote:
> Was looking at the relevant local regulations and noticed the regdb allowed
> less power at 5GHz than is actually allowed. Until I found the "If you don't do TPC you have
> to reduce your power by 3dB sometimes" bit on the next page.
>
> And looks like someone that did the entry for CZ fell into the same trap, they have
>
> "stations in the c and d bands must employ automatic transmitter power
> control, which provides, on average, an interference mitigation factor at
> least 3 dB on the maximum permitted output power of the systems. If
> automatic power control is not employed, the maximum permitted mean e.i.r.p.
> and the corresponding limit of the mean e.i.r.p. density for bands c and d
> must be reduced by 3 dB;"
>
> Please sanity check, I became very confused while looking into this.
> (like some places starting their freq ranges at 2400, others at 2402. Didn't
> touch those, regs say 2400-2485,5, 5150-5250, 5250-5350 and 5470-5725)
>
> Signed-off-by: Pekka Pietikäinen <pp@ee.oulu.fi>
> diff -up ./db.txt.orig ./db.txt
> --- ./db.txt.orig 2010-05-25 15:03:48.812116854 +0300
> +++ ./db.txt 2010-05-25 15:58:43.947117884 +0300
> @@ -170,11 +170,13 @@ country CY:
>
> # Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
> # and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
> +# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
> +# implemented.
> country CZ:
> (2400 - 2483.5 @ 40), (N/A, 100 mW)
> (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
> - (5250 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR, DFS
> - (5470 - 5725 @ 40), (N/A, 1000 mW), DFS
> + (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
> + (5470 - 5725 @ 40), (N/A, 500 mW), DFS
>
> # Data from "Frequenznutzungsplan" (as published in April 2008),
> # downloaded from http://www.bundesnetzagentur.de/media/archive/13358.pdf
> @@ -226,11 +228,15 @@ country ES:
> (5250 - 5330 @ 40), (N/A, 20), DFS
> (5490 - 5710 @ 40), (N/A, 27), DFS
>
> +# Data from FICORA Regulation 15Z / 2009 M
> +# http://www.ficora.fi/attachments/suomiry/5l1x1FIIk/Viestintavirasto15Z2009M.pdf
> +# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
> +# implemented.
> country FI:
> - (2402 - 2482 @ 40), (N/A, 20)
> - (5170 - 5250 @ 40), (N/A, 20)
> - (5250 - 5330 @ 40), (N/A, 20), DFS
> - (5490 - 5710 @ 40), (N/A, 27), DFS
> + (2402 - 2482 @ 40), (N/A, 100mW)
> + (5170 - 5250 @ 40), (N/A, 200mW), NO-OUTDOOR
> + (5250 - 5330 @ 40), (N/A, 100mW), NO-OUTDOOR, DFS
> + (5490 - 5710 @ 40), (N/A, 500mW), DFS
>
> country FR:
> (2402 - 2482 @ 40), (N/A, 20)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH] cfg80211: Fix user-space crda query stall
From: Luis R. Rodriguez @ 2010-05-25 19:02 UTC (permalink / raw)
To: Juuso Oikarinen; +Cc: linville, linux-wireless
In-Reply-To: <1274770211-22710-2-git-send-email-juuso.oikarinen@nokia.com>
On Mon, May 24, 2010 at 11:50 PM, Juuso Oikarinen
<juuso.oikarinen@nokia.com> wrote:
> The userspace crda utility can fail to respond to kernel requests in (at least)
> two scenarios: it is not runnable for any reason, or it is invoked with a
> country code not in its database.
>
> When the userspace crda utility fails to respond to kernel requests (i.e. it
> does not use NL80211_CMD_SET_REG to provide the kernel regulatory information
> for the requested country) the kernel crda subsystem will stall. It will
> refuse to process any further regulatory hints. This is easiest demonstrated
> by using for instance the "iw" tool:
>
> iw reg set EU
> iw reg set US
>
> "EU" is not a country code present in the database, so user space crda will
> not respond. Attempting to define US after that will be silently ignored
> (internally, an -EAGAIN is the result, as the "EU" request is still
> "being processed".)
>
> To fix this issue, this patch implements timeout protection for the userspace
> crda invocation. If there is no response for five seconds, the crda code will
> force itself to the world regulatory domain for maximum safety.
>
> Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
This is a great idea, I really like it and appreciate you taking the
time to work on this, however to do this it requires a little more
work and will point out the notes below. So NACK for now but with some
fixes I think this would be great.
> ---
> net/wireless/reg.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 44 insertions(+), 0 deletions(-)
>
> diff --git a/net/wireless/reg.c b/net/wireless/reg.c
> index 8f0d97d..6c945f0 100644
> --- a/net/wireless/reg.c
> +++ b/net/wireless/reg.c
> @@ -385,6 +385,40 @@ static inline void reg_regdb_query(const char *alpha2) {}
> #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
>
> /*
> + * This gets invoked if crda in userspace is not responding (it's not getting
> + * executed or the country code in the hint is not in the database.
> + */
> +
> +static void call_crda_timeout_work(struct work_struct *work)
> +{
> + if (!last_request)
> + return;
> +
> + printk(KERN_INFO "cfg80211: crda request timed out, reverting to 00\n");
> +
> + mutex_lock(&cfg80211_mutex);
> +
> + /*
> + * As we are not getting data for the current country, force us back
> + * to the world regdomain.
> + */
> + last_request->alpha2[0] = '0';
> + last_request->alpha2[1] = '0';
> + set_regdom(cfg80211_world_regdom);
> + mutex_unlock(&cfg80211_mutex);
> +}
Actually you may want to consider using restore_regulatory_settings()
instead as that would:
* set the world regdom
* then set the first user specified regulatory domain if they had one picked
This would mean we would go into a loop here though if the user had
specified 'EU' though so this routine first needs to be fixed to
annotate a regulatory domain as invalid. Note that a regulatory cannot
be invalid if CRDA just times out -- CRDA could time out if it was not
present. So this is a bit tricky and not sure how to resolve it. John
recently added support for building the regulatory database as part of
the kernel but at the same time support letting CRDA still update the
same info if it is present. Then for those setup it could be possible
'DE' exists on the core kernel regulatory database but if CRDA is not
installed then CRDA will time out.
Maybe what we can do is if both the internal kernel regdb *and* CRDA
times out then mark the user specified request as invalid and restore
to using the world regdom. This would allow the user to later install
a CRDA with some newer regdb in userspace, for example. This allows
for upgrading the db itself from userspace without making kernel
changes. It allows for countries to be created.
> +
> +static DECLARE_WORK(crda_uevent_timeout_work, call_crda_timeout_work);
> +
> +#define CRDA_UEVENT_TIMEOUT 5000
> +static void crda_uevent_timeout(unsigned long data)
> +{
> + schedule_work(&crda_uevent_timeout_work);
> +}
> +
> +static DEFINE_TIMER(crda_uevent_timer, crda_uevent_timeout, 0, 0);
I would prefer we use a completion here, seems a little cleaner. Check
out ath9k/wmi.c for cmd_wait and its use with init_completion() and
complete().
> +/*
> * This lets us keep regulatory code which is updated on a regulatory
> * basis in userspace.
> */
> @@ -409,6 +443,10 @@ static int call_crda(const char *alpha2)
> country_env[8] = alpha2[0];
> country_env[9] = alpha2[1];
>
> + /* start timeout timer */
> + mod_timer(&crda_uevent_timer,
> + jiffies + msecs_to_jiffies(CRDA_UEVENT_TIMEOUT));
> +
> return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, envp);
> }
>
> @@ -2581,6 +2619,9 @@ int set_regdom(const struct ieee80211_regdomain *rd)
>
> assert_cfg80211_lock();
>
> + /* cancel timeout */
> + del_timer(&crda_uevent_timer);
> +
> mutex_lock(®_mutex);
>
> /* Note that this doesn't update the wiphys, this is done below */
> @@ -2683,6 +2724,9 @@ void regulatory_exit(void)
>
> cancel_work_sync(®_work);
>
> + del_timer_sync(&crda_uevent_timer);
> + cancel_work_sync(&crda_uevent_timeout_work);
> +
> mutex_lock(&cfg80211_mutex);
> mutex_lock(®_mutex);
Thanks!!!
Luis
^ permalink raw reply
* [PATCH 2/3] ath9k_common: use allocated key cache entries for multi BSS crypto support
From: Felix Fietkau @ 2010-05-25 17:42 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, lrodriguez
In-Reply-To: <1274809366-73422-1-git-send-email-nbd@openwrt.org>
This patch replaces the buggy 'ath9k: Group Key fix for VAPs' change.
For AP mode group keys, use the BSSID as lookup mac address, with
the multicast keysearch bit set.
For IBSS mode, use the peer's MAC address with multicast keysearch.
For STA mode, keep using the group key slots.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/common.c | 37 ++++++++++++++++++++++--------
1 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 7707341..6407a7f 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -475,10 +475,14 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
return -1;
}
-static int ath_reserve_key_cache_slot(struct ath_common *common)
+static int ath_reserve_key_cache_slot(struct ath_common *common,
+ enum ieee80211_key_alg alg)
{
int i;
+ if (alg == ALG_TKIP)
+ return ath_reserve_key_cache_slot_tkip(common);
+
/* First, try to find slots that would not be available for TKIP. */
if (common->splitmic) {
for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
@@ -547,6 +551,7 @@ int ath9k_cmn_key_config(struct ath_common *common,
struct ath_hw *ah = common->ah;
struct ath9k_keyval hk;
const u8 *mac = NULL;
+ u8 gmac[ETH_ALEN];
int ret = 0;
int idx;
@@ -570,9 +575,23 @@ int ath9k_cmn_key_config(struct ath_common *common,
memcpy(hk.kv_val, key->key, key->keylen);
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
- /* For now, use the default keys for broadcast keys. This may
- * need to change with virtual interfaces. */
- idx = key->keyidx;
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
+ memcpy(gmac, vif->addr, ETH_ALEN);
+ gmac[0] |= 0x01;
+ mac = gmac;
+ idx = ath_reserve_key_cache_slot(common, key->alg);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ memcpy(gmac, sta->addr, ETH_ALEN);
+ gmac[0] |= 0x01;
+ mac = gmac;
+ idx = ath_reserve_key_cache_slot(common, key->alg);
+ break;
+ default:
+ idx = key->keyidx;
+ break;
+ }
} else if (key->keyidx) {
if (WARN_ON(!sta))
return -EOPNOTSUPP;
@@ -589,14 +608,12 @@ int ath9k_cmn_key_config(struct ath_common *common,
return -EOPNOTSUPP;
mac = sta->addr;
- if (key->alg == ALG_TKIP)
- idx = ath_reserve_key_cache_slot_tkip(common);
- else
- idx = ath_reserve_key_cache_slot(common);
- if (idx < 0)
- return -ENOSPC; /* no free key cache entries */
+ idx = ath_reserve_key_cache_slot(common, key->alg);
}
+ if (idx < 0)
+ return -ENOSPC; /* no free key cache entries */
+
if (key->alg == ALG_TKIP)
ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
vif->type == NL80211_IFTYPE_AP);
--
1.6.4.2
^ permalink raw reply related
* [PATCH 1/3] ath9k_hw: add multicast key search support
From: Felix Fietkau @ 2010-05-25 17:42 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, lrodriguez
If a MAC address for a key table entry is flagged with the
multicast bit (0x01), indicate to the hardware that multicast
lookup instead of unicast lookup should be used. The multicast
bit itself never makes it to the actual keytable entry register,
as it is shifted out.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/hw.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c33f17d..ce6b55c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1489,6 +1489,7 @@ EXPORT_SYMBOL(ath9k_hw_keyreset);
bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
{
u32 macHi, macLo;
+ u32 unicast_flag = AR_KEYTABLE_VALID;
if (entry >= ah->caps.keycache_size) {
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
@@ -1497,6 +1498,16 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
}
if (mac != NULL) {
+ /*
+ * AR_KEYTABLE_VALID indicates that the address is a unicast
+ * address, which must match the transmitter address for
+ * decrypting frames.
+ * Not setting this bit allows the hardware to use the key
+ * for multicast frame decryption.
+ */
+ if (mac[0] & 0x01)
+ unicast_flag = 0;
+
macHi = (mac[5] << 8) | mac[4];
macLo = (mac[3] << 24) |
(mac[2] << 16) |
@@ -1509,7 +1520,7 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
macLo = macHi = 0;
}
REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
return true;
}
--
1.6.4.2
^ permalink raw reply related
* [PATCH 3/3] ath9k: use the key handling code from ath9k_common instead of duplicating it
From: Felix Fietkau @ 2010-05-25 17:42 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, lrodriguez
In-Reply-To: <1274809366-73422-2-git-send-email-nbd@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/main.c | 232 +--------------------------------
1 files changed, 2 insertions(+), 230 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index abfa049..135eb4c 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -615,234 +615,6 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
return chanmode;
}
-static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
- struct ath9k_keyval *hk, const u8 *addr,
- bool authenticator)
-{
- struct ath_hw *ah = common->ah;
- const u8 *key_rxmic;
- const u8 *key_txmic;
-
- key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
- key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
-
- if (addr == NULL) {
- /*
- * Group key installation - only two key cache entries are used
- * regardless of splitmic capability since group key is only
- * used either for TX or RX.
- */
- if (authenticator) {
- memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
- memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
- } else {
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
- }
- return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
- }
- if (!common->splitmic) {
- /* TX and RX keys share the same key cache entry. */
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
- return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
- }
-
- /* Separate key cache entries for TX and RX */
-
- /* TX key goes at first index, RX key at +32. */
- memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
- if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
- /* TX MIC entry failed. No need to proceed further */
- ath_print(common, ATH_DBG_FATAL,
- "Setting TX MIC Key Failed\n");
- return 0;
- }
-
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- /* XXX delete tx key on failure? */
- return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
-}
-
-static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
-{
- int i;
-
- for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
- if (test_bit(i, common->keymap) ||
- test_bit(i + 64, common->keymap))
- continue; /* At least one part of TKIP key allocated */
- if (common->splitmic &&
- (test_bit(i + 32, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- continue; /* At least one part of TKIP key allocated */
-
- /* Found a free slot for a TKIP key */
- return i;
- }
- return -1;
-}
-
-static int ath_reserve_key_cache_slot(struct ath_common *common)
-{
- int i;
-
- /* First, try to find slots that would not be available for TKIP. */
- if (common->splitmic) {
- for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
- if (!test_bit(i, common->keymap) &&
- (test_bit(i + 32, common->keymap) ||
- test_bit(i + 64, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- return i;
- if (!test_bit(i + 32, common->keymap) &&
- (test_bit(i, common->keymap) ||
- test_bit(i + 64, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- return i + 32;
- if (!test_bit(i + 64, common->keymap) &&
- (test_bit(i , common->keymap) ||
- test_bit(i + 32, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- return i + 64;
- if (!test_bit(i + 64 + 32, common->keymap) &&
- (test_bit(i, common->keymap) ||
- test_bit(i + 32, common->keymap) ||
- test_bit(i + 64, common->keymap)))
- return i + 64 + 32;
- }
- } else {
- for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
- if (!test_bit(i, common->keymap) &&
- test_bit(i + 64, common->keymap))
- return i;
- if (test_bit(i, common->keymap) &&
- !test_bit(i + 64, common->keymap))
- return i + 64;
- }
- }
-
- /* No partially used TKIP slots, pick any available slot */
- for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
- /* Do not allow slots that could be needed for TKIP group keys
- * to be used. This limitation could be removed if we know that
- * TKIP will not be used. */
- if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
- continue;
- if (common->splitmic) {
- if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
- continue;
- if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
- continue;
- }
-
- if (!test_bit(i, common->keymap))
- return i; /* Found a free slot for a key */
- }
-
- /* No free slot found */
- return -1;
-}
-
-static int ath_key_config(struct ath_common *common,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-{
- struct ath_hw *ah = common->ah;
- struct ath9k_keyval hk;
- const u8 *mac = NULL;
- int ret = 0;
- int idx;
-
- memset(&hk, 0, sizeof(hk));
-
- switch (key->alg) {
- case ALG_WEP:
- hk.kv_type = ATH9K_CIPHER_WEP;
- break;
- case ALG_TKIP:
- hk.kv_type = ATH9K_CIPHER_TKIP;
- break;
- case ALG_CCMP:
- hk.kv_type = ATH9K_CIPHER_AES_CCM;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- hk.kv_len = key->keylen;
- memcpy(hk.kv_val, key->key, key->keylen);
-
- if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
- /* For now, use the default keys for broadcast keys. This may
- * need to change with virtual interfaces. */
- idx = key->keyidx;
- } else if (key->keyidx) {
- if (WARN_ON(!sta))
- return -EOPNOTSUPP;
- mac = sta->addr;
-
- if (vif->type != NL80211_IFTYPE_AP) {
- /* Only keyidx 0 should be used with unicast key, but
- * allow this for client mode for now. */
- idx = key->keyidx;
- } else
- return -EIO;
- } else {
- if (WARN_ON(!sta))
- return -EOPNOTSUPP;
- mac = sta->addr;
-
- if (key->alg == ALG_TKIP)
- idx = ath_reserve_key_cache_slot_tkip(common);
- else
- idx = ath_reserve_key_cache_slot(common);
- if (idx < 0)
- return -ENOSPC; /* no free key cache entries */
- }
-
- if (key->alg == ALG_TKIP)
- ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
- vif->type == NL80211_IFTYPE_AP);
- else
- ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
-
- if (!ret)
- return -EIO;
-
- set_bit(idx, common->keymap);
- if (key->alg == ALG_TKIP) {
- set_bit(idx + 64, common->keymap);
- if (common->splitmic) {
- set_bit(idx + 32, common->keymap);
- set_bit(idx + 64 + 32, common->keymap);
- }
- }
-
- return idx;
-}
-
-static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
-{
- struct ath_hw *ah = common->ah;
-
- ath9k_hw_keyreset(ah, key->hw_key_idx);
- if (key->hw_key_idx < IEEE80211_WEP_NKID)
- return;
-
- clear_bit(key->hw_key_idx, common->keymap);
- if (key->alg != ALG_TKIP)
- return;
-
- clear_bit(key->hw_key_idx + 64, common->keymap);
- if (common->splitmic) {
- ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
- clear_bit(key->hw_key_idx + 32, common->keymap);
- clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
- }
-}
-
static void ath9k_bss_assoc_info(struct ath_softc *sc,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
@@ -1804,7 +1576,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
switch (cmd) {
case SET_KEY:
- ret = ath_key_config(common, vif, sta, key);
+ ret = ath9k_cmn_key_config(common, vif, sta, key);
if (ret >= 0) {
key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
@@ -1817,7 +1589,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key);
+ ath9k_cmn_key_delete(common, key);
break;
default:
ret = -EINVAL;
--
1.6.4.2
^ permalink raw reply related
* Re: iwl3945 dies (oops) in post 2.6.34 kernels
From: Dmitry Torokhov @ 2010-05-25 17:27 UTC (permalink / raw)
To: Abhijeet Kolekar; +Cc: Johannes Berg, linux-wireless@vger.kernel.org, LKML
In-Reply-To: <1274807302.7494.1.camel@abhi-desktop>
On Tuesday 25 May 2010 10:08:22 am Abhijeet Kolekar wrote:
> On Tue, 2010-05-25 at 10:01 -0700, Johannes Berg wrote:
> > On Tue, 2010-05-25 at 09:39 -0700, Dmitry Torokhov wrote:
> > > Hi,
> > >
> > > I am getting the following crashers in iwl3945 after updating to
> > > post-2.6.34 kernels. This is with the pull from Linus's tree as of last
> > > night (the taint is from nvidia module):
> > >
> > > [ 3330.630734] general protection fault: 0000 [#1] PREEMPT SMP
> > > [ 3330.630752] last sysfs file: /sys/devices/platform/dock.0/docked
> > > [ 3330.630761] CPU 0
> > > [ 3330.630766] Modules linked in: cryptd aes_x86_64 aes_generic fuse
> > > rfcomm sco bnep l2cap autofs4 coretemp hwmon sunrpc ppdev parport_pc
> > > parport acpi_cpufreq mperf uinput nvidia(P) snd_hda_codec_idt arc4
> > > snd_hda_intel ecb snd_hda_codec snd_hwdep iwl3945 joydev snd_seq
> > > snd_seq_device snd_pcm iwlcore mac80211 snd_timer cfg80211 snd psmouse
> > > iTCO_wdt dell_wmi iTCO_vendor_support serio_raw tg3 battery
> > > dell_laptop dcdbas soundcore snd_page_alloc btusb bluetooth video
> > > pcspkr mac_hid ac wmi libphy firewire_ohci i2c_i801 firewire_core
> > > yenta_socket crc_itu_t ohci_hcd [last unloaded: microcode] [
> > > 3330.630950]
> > > [ 3330.630958] Pid: 455, comm: iwl3945 Tainted: P 2.6.35-rc0
> > > #293 0WM416/Latitude D630 [ 3330.630967] RIP:
> > > 0010:[<ffffffffa01e70d3>] [<ffffffffa01e70d3>]
> > > iwl3945_get_channels_for_scan+0xe3/0x460 [iwl3945]
> >
> > http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2208
>
> Can you please try this patch and report your findings?
>
> http://bugzilla.intellinuxwireless.org/attachment.cgi?id=2447
>
Thanks, will try both this patch and the one John mention. Later tonight
though.
--
Dmitry
^ permalink raw reply
* pull request: wireless-2.6 2010-05-25
From: John W. Linville @ 2010-05-25 17:04 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
Dave,
Here are a number of fixes intended for 2.6.35. Included are some
warning fixes from Randy, some smatch-identified fixes from Dan, some
fixes for using ath9k and IBSS mode, the removal of a PCI ID that was
optimistically added to ath9k, and a smattering of other driver fixes.
This also includes a revert of "ath9k: Group Key fix for VAPs" which
was reported to cause regressions due to a mac80211 change inside it
that snuck past us... :-(
Anyway, these are mostly small(ish) and obvious. Please let me know
if there are problems!
Thanks,
John
---
The following changes since commit acfbe96a3035639619a6533e04d88ed4ef9ccb61:
Randy Dunlap (1):
sock.h: fix kernel-doc warning
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master
Bruno Randolf (1):
ath5k: consistently use rx_bufsize for RX DMA
Dan Carpenter (3):
ath9k_htc: dereferencing before check in hif_usb_tx_cb()
ath9k_htc: rare leak in ath9k_hif_usb_alloc_tx_urbs()
iwlwifi: testing the wrong variable in iwl_add_bssid_station()
Felix Fietkau (3):
cfg80211: fix crash in cfg80211_set_freq()
ath9k: change beacon allocation to prefer the first beacon slot
ath9k: remove VEOL support for ad-hoc
Gertjan van Wingerde (2):
rt2x00: Fix failed SLEEP->AWAKE and AWAKE->SLEEP transitions.
rt2x00: Fix rt2800usb TX descriptor writing.
Helmut Schaa (1):
rt2x00: don't use to_pci_dev in rt2x00pci_uninitialize
Johannes Berg (1):
cfg80211: add missing braces
John W. Linville (1):
Revert "ath9k: Group Key fix for VAPs"
Jussi Kivilinna (1):
rndis_wlan: replace wireless_send_event with cfg80211_disconnected
Juuso Oikarinen (1):
wl1271: Fix RX data path frame lengths
Luis R. Rodriguez (1):
ath9k: remove AR9003 from PCI IDs for now
Randy Dunlap (2):
wireless: fix mac80211.h kernel-doc warnings
wireless: fix sta_info.h kernel-doc warnings
Reinette Chatre (1):
iwlwifi: fix internal scan race
Sujith (1):
cfg80211: Fix signal_type comparison
Tejun Heo (1):
wireless: update gfp/slab.h includes
Vasanthakumar Thiagarajan (1):
ath9k: Fix rx of mcast/bcast frames in PS mode with auto sleep
drivers/net/wireless/ath/ath5k/base.c | 7 ++-
drivers/net/wireless/ath/ath9k/beacon.c | 75 +++++-----------------------
drivers/net/wireless/ath/ath9k/hif_usb.c | 10 +++-
drivers/net/wireless/ath/ath9k/htc.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 28 +---------
drivers/net/wireless/ath/ath9k/pci.c | 1 -
drivers/net/wireless/ath/ath9k/recv.c | 17 +++++--
drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 1 +
drivers/net/wireless/iwlwifi/iwl-scan.c | 21 +++++++-
drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +-
drivers/net/wireless/rndis_wlan.c | 16 ++++--
drivers/net/wireless/rt2x00/rt2400pci.c | 9 ++--
drivers/net/wireless/rt2x00/rt2500pci.c | 9 ++--
drivers/net/wireless/rt2x00/rt2800usb.c | 2 +-
drivers/net/wireless/rt2x00/rt2x00pci.c | 2 +-
drivers/net/wireless/rt2x00/rt61pci.c | 7 ++-
drivers/net/wireless/rt2x00/rt73usb.c | 7 ++-
drivers/net/wireless/wl12xx/wl1271_rx.c | 2 +
include/net/mac80211.h | 4 +-
net/mac80211/key.c | 1 -
net/mac80211/sta_info.h | 2 +-
net/wireless/chan.c | 2 +-
net/wireless/nl80211.c | 6 ++-
net/wireless/scan.c | 4 +-
24 files changed, 104 insertions(+), 132 deletions(-)
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 5f04cf3..cc6d41d 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1214,6 +1214,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
struct ath5k_hw *ah = sc->ah;
struct sk_buff *skb = bf->skb;
struct ath5k_desc *ds;
+ int ret;
if (!skb) {
skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
@@ -1240,9 +1241,9 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds = bf->desc;
ds->ds_link = bf->daddr; /* link to self */
ds->ds_data = bf->skbaddr;
- ah->ah_setup_rx_desc(ah, ds,
- skb_tailroom(skb), /* buffer size */
- 0);
+ ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
+ if (ret)
+ return ret;
if (sc->rxlink != NULL)
*sc->rxlink = bf->daddr;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index c8a4558..f43d85a 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -76,22 +76,13 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
ds = bf->bf_desc;
flags = ATH9K_TXDESC_NOACK;
- if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
- (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
- ds->ds_link = bf->bf_daddr; /* self-linked */
- flags |= ATH9K_TXDESC_VEOL;
- /* Let hardware handle antenna switching. */
- antenna = 0;
- } else {
- ds->ds_link = 0;
- /*
- * Switch antenna every beacon.
- * Should only switch every beacon period, not for every SWBA
- * XXX assumes two antennae
- */
- antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
- }
+ ds->ds_link = 0;
+ /*
+ * Switch antenna every beacon.
+ * Should only switch every beacon period, not for every SWBA
+ * XXX assumes two antennae
+ */
+ antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value;
@@ -215,36 +206,6 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
return bf;
}
-/*
- * Startup beacon transmission for adhoc mode when they are sent entirely
- * by the hardware using the self-linked descriptor + veol trick.
-*/
-static void ath_beacon_start_adhoc(struct ath_softc *sc,
- struct ieee80211_vif *vif)
-{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_buf *bf;
- struct ath_vif *avp;
- struct sk_buff *skb;
-
- avp = (void *)vif->drv_priv;
-
- if (avp->av_bcbuf == NULL)
- return;
-
- bf = avp->av_bcbuf;
- skb = bf->bf_mpdu;
-
- ath_beacon_setup(sc, avp, bf, 0);
-
- /* NB: caller is known to have already stopped tx dma */
- ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
- ath9k_hw_txstart(ah, sc->beacon.beaconq);
- ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
- sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
-}
-
int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
{
struct ath_softc *sc = aphy->sc;
@@ -265,7 +226,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
list_del(&avp->av_bcbuf->list);
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
- !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
+ sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
+ sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
int slot;
/*
* Assign the vif to a beacon xmit slot. As
@@ -274,17 +236,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
avp->av_bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++)
if (sc->beacon.bslot[slot] == NULL) {
- /*
- * XXX hack, space out slots to better
- * deal with misses
- */
- if (slot+1 < ATH_BCBUF &&
- sc->beacon.bslot[slot+1] == NULL) {
- avp->av_bslot = slot+1;
- break;
- }
avp->av_bslot = slot;
+
/* NB: keep looking for a double slot */
+ if (slot == 0 || !sc->beacon.bslot[slot-1])
+ break;
}
BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
sc->beacon.bslot[avp->av_bslot] = vif;
@@ -721,8 +677,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
* self-linked tx descriptor and let the hardware deal with things.
*/
intval |= ATH9K_BEACON_ENA;
- if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
- ah->imask |= ATH9K_INT_SWBA;
+ ah->imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
@@ -732,10 +687,6 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, ah->imask);
-
- /* FIXME: Handle properly when vif is NULL */
- if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
- ath_beacon_start_adhoc(sc, vif);
}
void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 46dc41a..77b3591 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -107,12 +107,14 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
static void hif_usb_tx_cb(struct urb *urb)
{
struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
- struct hif_device_usb *hif_dev = tx_buf->hif_dev;
+ struct hif_device_usb *hif_dev;
struct sk_buff *skb;
- if (!hif_dev || !tx_buf)
+ if (!tx_buf || !tx_buf->hif_dev)
return;
+ hif_dev = tx_buf->hif_dev;
+
switch (urb->status) {
case 0:
break;
@@ -607,6 +609,10 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
return 0;
err:
+ if (tx_buf) {
+ kfree(tx_buf->buf);
+ kfree(tx_buf);
+ }
ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
return -ENOMEM;
}
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index ad556aa..c251603 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -23,6 +23,7 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/leds.h>
+#include <linux/slab.h>
#include <net/mac80211.h>
#include "common.h"
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 893b552..abfa049 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -752,7 +752,6 @@ static int ath_key_config(struct ath_common *common,
struct ath_hw *ah = common->ah;
struct ath9k_keyval hk;
const u8 *mac = NULL;
- u8 gmac[ETH_ALEN];
int ret = 0;
int idx;
@@ -776,30 +775,9 @@ static int ath_key_config(struct ath_common *common,
memcpy(hk.kv_val, key->key, key->keylen);
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
-
- if (key->ap_addr) {
- /*
- * Group keys on hardware that supports multicast frame
- * key search use a mac that is the sender's address with
- * the high bit set instead of the app-specified address.
- */
- memcpy(gmac, key->ap_addr, ETH_ALEN);
- gmac[0] |= 0x80;
- mac = gmac;
-
- if (key->alg == ALG_TKIP)
- idx = ath_reserve_key_cache_slot_tkip(common);
- else
- idx = ath_reserve_key_cache_slot(common);
- if (idx < 0)
- mac = NULL; /* no free key cache entries */
- }
-
- if (!mac) {
- /* For now, use the default keys for broadcast keys. This may
- * need to change with virtual interfaces. */
- idx = key->keyidx;
- }
+ /* For now, use the default keys for broadcast keys. This may
+ * need to change with virtual interfaces. */
+ idx = key->keyidx;
} else if (key->keyidx) {
if (WARN_ON(!sta))
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 257b10b..1ec836c 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -28,7 +28,6 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
- { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
{ 0 }
};
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ba13913..ca6065b 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -19,6 +19,12 @@
#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb))
+static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
+{
+ return sc->ps_enabled &&
+ (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
+}
+
static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
struct ieee80211_hdr *hdr)
{
@@ -616,8 +622,8 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
hdr = (struct ieee80211_hdr *)skb->data;
/* Process Beacon and CAB receive in PS state */
- if ((sc->ps_flags & PS_WAIT_FOR_BEACON) &&
- ieee80211_is_beacon(hdr->frame_control))
+ if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc))
+ && ieee80211_is_beacon(hdr->frame_control))
ath_rx_ps_beacon(sc, skb);
else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
(ieee80211_is_data(hdr->frame_control) ||
@@ -932,9 +938,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.rxotherant = 0;
}
- if (unlikely(sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA)))
+ if (unlikely(ath9k_check_auto_sleep(sc) ||
+ (sc->ps_flags & (PS_WAIT_FOR_BEACON |
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA))))
ath_rx_ps(sc, skb);
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
index a273e37..c92b2c0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
+#include <linux/gfp.h>
#include <net/mac80211.h>
#include "iwl-dev.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 107e173..5d3f51f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -376,6 +376,11 @@ void iwl_bg_start_internal_scan(struct work_struct *work)
mutex_lock(&priv->mutex);
+ if (priv->is_internal_short_scan == true) {
+ IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
+ goto unlock;
+ }
+
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
goto unlock;
@@ -497,17 +502,27 @@ void iwl_bg_scan_completed(struct work_struct *work)
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, scan_completed);
+ bool internal = false;
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
cancel_delayed_work(&priv->scan_check);
- if (!priv->is_internal_short_scan)
- ieee80211_scan_completed(priv->hw, false);
- else {
+ mutex_lock(&priv->mutex);
+ if (priv->is_internal_short_scan) {
priv->is_internal_short_scan = false;
IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
+ internal = true;
}
+ mutex_unlock(&priv->mutex);
+
+ /*
+ * Do not hold mutex here since this will cause mac80211 to call
+ * into driver again into functions that will attempt to take
+ * mutex.
+ */
+ if (!internal)
+ ieee80211_scan_completed(priv->hw, false);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 85ed235..83a2636 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -431,7 +431,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
struct iwl_link_quality_cmd *link_cmd;
unsigned long flags;
- if (*sta_id_r)
+ if (sta_id_r)
*sta_id_r = IWL_INVALID_STATION;
ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 2d28908..4bd61ee 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2572,14 +2572,18 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
static void rndis_wlan_do_link_down_work(struct usbnet *usbdev)
{
- union iwreq_data evt;
+ struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
- netif_carrier_off(usbdev->net);
+ if (priv->connected) {
+ priv->connected = false;
+ memset(priv->bssid, 0, ETH_ALEN);
+
+ deauthenticate(usbdev);
- evt.data.flags = 0;
- evt.data.length = 0;
- memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
- wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
+ cfg80211_disconnected(usbdev->net, 0, NULL, 0, GFP_KERNEL);
+ }
+
+ netif_carrier_off(usbdev->net);
}
static void rndis_wlan_worker(struct work_struct *work)
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 4ba7b03..ad2c98a 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -926,7 +926,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
- u32 reg;
+ u32 reg, reg2;
unsigned int i;
char put_to_sleep;
char bbp_state;
@@ -947,11 +947,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®);
- bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE);
- rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE);
+ rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2);
+ bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
+ rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
+ rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
msleep(10);
}
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 89d132d..41da3d2 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1084,7 +1084,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
- u32 reg;
+ u32 reg, reg2;
unsigned int i;
char put_to_sleep;
char bbp_state;
@@ -1105,11 +1105,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®);
- bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE);
- rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE);
+ rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2);
+ bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
+ rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
+ rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
msleep(10);
}
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 0f8b84b..6991613 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
*/
rt2x00_desc_read(txi, 0, &word);
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
- skb->len + TXWI_DESC_SIZE);
+ skb->len - TXINFO_DESC_SIZE);
rt2x00_set_field32(&word, TXINFO_W0_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index a016f7c..f71eee6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -206,7 +206,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
/*
* Free irq line.
*/
- free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev);
+ free_irq(rt2x00dev->irq, rt2x00dev);
/*
* Free DMA
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 2e3076f..6a74baf 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1689,7 +1689,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
{
- u32 reg;
+ u32 reg, reg2;
unsigned int i;
char put_to_sleep;
@@ -1706,10 +1706,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®);
- state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®2);
+ state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg);
msleep(10);
}
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index e35bd19..6e0d82e 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1366,7 +1366,7 @@ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
{
- u32 reg;
+ u32 reg, reg2;
unsigned int i;
char put_to_sleep;
@@ -1383,10 +1383,11 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®);
- state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®2);
+ state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
msleep(10);
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 57f4bfd..b98fb64 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -113,6 +113,8 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
beacon ? "beacon" : "");
+ skb_trim(skb, skb->len - desc->pad_len);
+
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
ieee80211_rx_ni(wl->hw, skb);
}
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5be900d..de22cbf 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -815,6 +815,7 @@ enum ieee80211_key_flags {
* encrypted in hardware.
* @alg: The key algorithm.
* @flags: key flags, see &enum ieee80211_key_flags.
+ * @ap_addr: AP's MAC address
* @keyidx: the key index (0-3)
* @keylen: key material length
* @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte)
@@ -831,7 +832,6 @@ struct ieee80211_key_conf {
u8 iv_len;
u8 hw_key_idx;
u8 flags;
- u8 *ap_addr;
s8 keyidx;
u8 keylen;
u8 key[0];
@@ -1638,6 +1638,8 @@ enum ieee80211_ampdu_mlme_action {
* Returns a negative error code on failure.
* The callback must be atomic.
*
+ * @get_survey: Return per-channel survey information
+ *
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
* need to set wiphy->rfkill_poll to %true before registration,
* and need to call wiphy_rfkill_set_hw_state() in the callback.
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 8d4b417..e8f6e3b 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -140,7 +140,6 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
struct ieee80211_sub_if_data,
u.ap);
- key->conf.ap_addr = sdata->dev->dev_addr;
ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
if (!ret) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 48a5e80..df9d455 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -145,7 +145,7 @@ enum plink_state {
/**
* struct sta_ampdu_mlme - STA aggregation information.
*
- * @tid_state_rx: TID's state in Rx session state machine.
+ * @tid_active_rx: TID's state in Rx session state machine.
* @tid_rx: aggregation info for Rx per TID
* @tid_state_tx: TID's state in Tx session state machine.
* @tid_tx: aggregation info for Tx per TID
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index d92d088..b01a6f6 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -50,7 +50,7 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
struct ieee80211_channel *chan;
int result;
- if (wdev->iftype == NL80211_IFTYPE_MONITOR)
+ if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR)
wdev = NULL;
if (wdev) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index aaa1aad..db71150 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4443,9 +4443,10 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
if (channel_type != NL80211_CHAN_NO_HT &&
channel_type != NL80211_CHAN_HT20 &&
channel_type != NL80211_CHAN_HT40PLUS &&
- channel_type != NL80211_CHAN_HT40MINUS)
+ channel_type != NL80211_CHAN_HT40MINUS) {
err = -EINVAL;
goto out;
+ }
}
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
@@ -4717,9 +4718,10 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
if (channel_type != NL80211_CHAN_NO_HT &&
channel_type != NL80211_CHAN_HT20 &&
channel_type != NL80211_CHAN_HT40PLUS &&
- channel_type != NL80211_CHAN_HT40MINUS)
+ channel_type != NL80211_CHAN_HT40MINUS) {
err = -EINVAL;
goto out;
+ }
}
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index a026c6d..58401d2 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -515,7 +515,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
privsz = wiphy->bss_priv_size;
- if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
+ if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
(signal < 0 || signal > 100)))
return NULL;
@@ -571,7 +571,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
u.probe_resp.variable);
size_t privsz = wiphy->bss_priv_size;
- if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
+ if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
(signal < 0 || signal > 100)))
return NULL;
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply related
* Re: iwl3945 dies (oops) in post 2.6.34 kernels
From: Abhijeet Kolekar @ 2010-05-25 17:08 UTC (permalink / raw)
To: Johannes Berg; +Cc: Dmitry Torokhov, linux-wireless@vger.kernel.org, LKML
In-Reply-To: <1274806916.18861.0.camel@jlt3.sipsolutions.net>
On Tue, 2010-05-25 at 10:01 -0700, Johannes Berg wrote:
> On Tue, 2010-05-25 at 09:39 -0700, Dmitry Torokhov wrote:
> > Hi,
> >
> > I am getting the following crashers in iwl3945 after updating to
> > post-2.6.34 kernels. This is with the pull from Linus's tree as of last
> > night (the taint is from nvidia module):
> >
> > [ 3330.630734] general protection fault: 0000 [#1] PREEMPT SMP
> > [ 3330.630752] last sysfs file: /sys/devices/platform/dock.0/docked
> > [ 3330.630761] CPU 0
> > [ 3330.630766] Modules linked in: cryptd aes_x86_64 aes_generic fuse rfcomm sco bnep l2cap autofs4
> > coretemp hwmon sunrpc ppdev parport_pc parport acpi_cpufreq mperf uinput nvidia(P) snd_hda_codec_idt
> > arc4 snd_hda_intel ecb snd_hda_codec snd_hwdep iwl3945 joydev snd_seq snd_seq_device snd_pcm iwlcore
> > mac80211 snd_timer cfg80211 snd psmouse iTCO_wdt dell_wmi iTCO_vendor_support serio_raw tg3 battery
> > dell_laptop dcdbas soundcore snd_page_alloc btusb bluetooth video pcspkr mac_hid ac wmi libphy
> > firewire_ohci i2c_i801 firewire_core yenta_socket crc_itu_t ohci_hcd [last unloaded: microcode]
> > [ 3330.630950]
> > [ 3330.630958] Pid: 455, comm: iwl3945 Tainted: P 2.6.35-rc0 #293 0WM416/Latitude D630
> > [ 3330.630967] RIP: 0010:[<ffffffffa01e70d3>] [<ffffffffa01e70d3>] iwl3945_get_channels_for_scan+0xe3/0x460 [iwl3945]
>
>
> http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2208
>
Can you please try this patch and report your findings?
http://bugzilla.intellinuxwireless.org/attachment.cgi?id=2447
Thanks
Abhijeet
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: iwl3945 dies (oops) in post 2.6.34 kernels
From: Johannes Berg @ 2010-05-25 17:01 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-wireless, LKML
In-Reply-To: <20100525163920.GA2730@core.coreip.homeip.net>
On Tue, 2010-05-25 at 09:39 -0700, Dmitry Torokhov wrote:
> Hi,
>
> I am getting the following crashers in iwl3945 after updating to
> post-2.6.34 kernels. This is with the pull from Linus's tree as of last
> night (the taint is from nvidia module):
>
> [ 3330.630734] general protection fault: 0000 [#1] PREEMPT SMP
> [ 3330.630752] last sysfs file: /sys/devices/platform/dock.0/docked
> [ 3330.630761] CPU 0
> [ 3330.630766] Modules linked in: cryptd aes_x86_64 aes_generic fuse rfcomm sco bnep l2cap autofs4
> coretemp hwmon sunrpc ppdev parport_pc parport acpi_cpufreq mperf uinput nvidia(P) snd_hda_codec_idt
> arc4 snd_hda_intel ecb snd_hda_codec snd_hwdep iwl3945 joydev snd_seq snd_seq_device snd_pcm iwlcore
> mac80211 snd_timer cfg80211 snd psmouse iTCO_wdt dell_wmi iTCO_vendor_support serio_raw tg3 battery
> dell_laptop dcdbas soundcore snd_page_alloc btusb bluetooth video pcspkr mac_hid ac wmi libphy
> firewire_ohci i2c_i801 firewire_core yenta_socket crc_itu_t ohci_hcd [last unloaded: microcode]
> [ 3330.630950]
> [ 3330.630958] Pid: 455, comm: iwl3945 Tainted: P 2.6.35-rc0 #293 0WM416/Latitude D630
> [ 3330.630967] RIP: 0010:[<ffffffffa01e70d3>] [<ffffffffa01e70d3>] iwl3945_get_channels_for_scan+0xe3/0x460 [iwl3945]
http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2208
johannes
^ permalink raw reply
* Re: iwl3945 dies (oops) in post 2.6.34 kernels
From: John W. Linville @ 2010-05-25 16:55 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-wireless, LKML
In-Reply-To: <20100525163920.GA2730@core.coreip.homeip.net>
On Tue, May 25, 2010 at 09:39:20AM -0700, Dmitry Torokhov wrote:
> Hi,
>
> I am getting the following crashers in iwl3945 after updating to
> post-2.6.34 kernels. This is with the pull from Linus's tree as of last
> night (the taint is from nvidia module):
Linus doesn't have this one yet:
commit 073d5eab6fc85b6c278d507a5633b759a85dc878
Author: Reinette Chatre <reinette.chatre@intel.com>
Date: Thu May 13 14:49:44 2010 -0700
iwlwifi: fix internal scan race
It is possible for internal scan to race against itself if the device is
not returning the scan results from first requests. What happens in this
case is the cleanup done during the abort of the first internal scan also
cleans up part of the new scan, causing it to access memory it shouldn't.
...
I suspect it might be related.
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* iwl3945 dies (oops) in post 2.6.34 kernels
From: Dmitry Torokhov @ 2010-05-25 16:39 UTC (permalink / raw)
To: linux-wireless; +Cc: LKML
Hi,
I am getting the following crashers in iwl3945 after updating to
post-2.6.34 kernels. This is with the pull from Linus's tree as of last
night (the taint is from nvidia module):
[ 3330.630734] general protection fault: 0000 [#1] PREEMPT SMP
[ 3330.630752] last sysfs file: /sys/devices/platform/dock.0/docked
[ 3330.630761] CPU 0
[ 3330.630766] Modules linked in: cryptd aes_x86_64 aes_generic fuse rfcomm sco bnep l2cap autofs4
coretemp hwmon sunrpc ppdev parport_pc parport acpi_cpufreq mperf uinput nvidia(P) snd_hda_codec_idt
arc4 snd_hda_intel ecb snd_hda_codec snd_hwdep iwl3945 joydev snd_seq snd_seq_device snd_pcm iwlcore
mac80211 snd_timer cfg80211 snd psmouse iTCO_wdt dell_wmi iTCO_vendor_support serio_raw tg3 battery
dell_laptop dcdbas soundcore snd_page_alloc btusb bluetooth video pcspkr mac_hid ac wmi libphy
firewire_ohci i2c_i801 firewire_core yenta_socket crc_itu_t ohci_hcd [last unloaded: microcode]
[ 3330.630950]
[ 3330.630958] Pid: 455, comm: iwl3945 Tainted: P 2.6.35-rc0 #293 0WM416/Latitude D630
[ 3330.630967] RIP: 0010:[<ffffffffa01e70d3>] [<ffffffffa01e70d3>] iwl3945_get_channels_for_scan+0xe3/0x460 [iwl3945]
[ 3330.630993] RSP: 0018:ffff8801126b1c10 EFLAGS: 00010297
[ 3330.631001] RAX: ffff8800b2853c00 RBX: 0000000000000000 RCX: 0002079700220078
[ 3330.631009] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff880112641aa0
[ 3330.631016] RBP: ffff8801126b1cc0 R08: ffff88010c22d0f2 R09: 0000000000000000
[ 3330.631024] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000001
[ 3330.631032] R13: ffff880112641aa0 R14: ffff88010c22d0f2 R15: 0000000000000000
[ 3330.631040] FS: 0000000000000000(0000) GS:ffff880002600000(0000) knlGS:0000000000000000
[ 3330.631049] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 3330.631056] CR2: 0000000005d03000 CR3: 0000000001806000 CR4: 00000000000006f0
[ 3330.631064] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 3330.631072] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 3330.631081] Process iwl3945 (pid: 455, threadinfo ffff8801126b0000, task ffff880115ab3fa0)
[ 3330.631087] Stack:
[ 3330.631092] 0000000000000000 ffffffffa01e7980 ffff880100000000 ffffffff814932ad
[ 3330.631106] <0> ffff8801126424c0 ffff880115ab3fa0 ffffffff00000000 0000005800000016
[ 3330.631123] <0> ffff8801126b1fd8 0058ffff00575231 ffff8801126b1fd8 0000000000000001
[ 3330.631143] Call Trace:
[ 3330.631161] [<ffffffffa01e7980>] ? iwl3945_request_scan+0x3f0/0xb40 [iwl3945]
[ 3330.631178] [<ffffffff814932ad>] ? _raw_spin_unlock_irqrestore+0x3d/0x70
[ 3330.631190] [<ffffffff81496dfd>] ? sub_preempt_count+0x9d/0xd0
[ 3330.631206] [<ffffffffa01e7ac4>] iwl3945_request_scan+0x534/0xb40 [iwl3945]
[ 3330.631233] [<ffffffffa018bf60>] ? iwl_bg_start_internal_scan+0x0/0x320 [iwlcore]
[ 3330.631254] [<ffffffffa018bf60>] ? iwl_bg_start_internal_scan+0x0/0x320 [iwlcore]
[ 3330.631274] [<ffffffffa018c166>] iwl_bg_start_internal_scan+0x206/0x320 [iwlcore]
[ 3330.631288] [<ffffffff81065f4c>] run_workqueue+0x12c/0x2a0
[ 3330.631298] [<ffffffff81065efb>] ? run_workqueue+0xdb/0x2a0
[ 3330.631311] [<ffffffff81066156>] worker_thread+0x96/0xf0
[ 3330.631323] [<ffffffff8106b1c0>] ? autoremove_wake_function+0x0/0x40
[ 3330.631333] [<ffffffff810660c0>] ? worker_thread+0x0/0xf0
[ 3330.631344] [<ffffffff8106acae>] kthread+0x8e/0xa0
[ 3330.631356] [<ffffffff81003d94>] kernel_thread_helper+0x4/0x10
[ 3330.631367] [<ffffffff81035c24>] ? finish_task_switch+0x74/0xd0
[ 3330.631377] [<ffffffff81493a40>] ? restore_args+0x0/0x30
[ 3330.631388] [<ffffffff8106ac20>] ? kthread+0x0/0xa0
[ 3330.631398] [<ffffffff81003d90>] ? kernel_thread_helper+0x0/0x10
[ 3330.631404] Code: b7 55 ce 89 55 88 41 8d 57 ff 45 89 d7 66 89 55 9a eb 10 0f 1f 44 00 00 ff c3
39 58 0c 0f 86 c5 00 00 00 48 63 d3 48 8b 4c d0 38 <44> 39 21 75 e8 0f b7 51 06 44 89 e6 41 88 56 01
48 89 4d 80 0f
[ 3330.631505] RIP [<ffffffffa01e70d3>] iwl3945_get_channels_for_scan+0xe3/0x460 [iwl3945]
[ 3330.631505] RSP <ffff8801126b1c10>
[ 3330.631657] ---[ end trace faaae140797cc308 ]---
--
Dmitry
^ permalink raw reply
* Re: wireless-regdb: A band is missing for IL
From: Emmanuel Grumbach @ 2010-05-25 16:09 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20100525133823.GC31753@tuxdriver.com>
>
> Would you care to send a patch?
It is ready, and under review by the Ministry of the Communications
^ permalink raw reply
* Re: WLAN Regulatory Domain Germany
From: Johannes Berg @ 2010-05-25 15:26 UTC (permalink / raw)
To: Kurt Garloff; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <20100525151429.GC6342@tpkurt2.garloff.de>
On Tue, 2010-05-25 at 17:14 +0200, Kurt Garloff wrote:
>
> OK, new suggestion.
>
> 8<------------------------------------------------------------------------
>
> # Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
> # http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
> # For the 5GHz range also see
> # http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
> # The values have been reduced by a factor of 2 (3db) for non TPC devices
> # (in other words: devices with TPC can use twice the tx power of this table).
> # Note that the docs do not require TPC for 5150--5250; the reduction to
> # 100mW thus is not strictly required -- however the conservative 100mW
> # limit is used here as the non-interference with radar and satellite
> # apps relies on the attenuation by the building walls only in the
> # absence of DFS; the neighbour countries have 100mW limit here as well.
>
> country DE:
> # entries 279004 and 280006
> (2400 - 2483.5 @ 40), (N/A, 100 mW)
> # entry 303005
> (5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
> # entries 304002 and 305002
> (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
> # entries 308002, 309001 and 310003
> (5470 - 5725 @ 40), (N/A, 500 mW), DFS
Ok, that looks fine to me.
> Can we actually put several entries covering the same frequency range?
> Then we could put 200mW for DFS and 100mW for non-DFS.
> This would also address the next issue you raise ...
I think you're confusing DFS and TPC requirements? Anyway, no, we can't
right now.
> > Also note that there are different requirements depending on the channel
> > bandwidth, which will eventually come up in Linux too. But I think for
> > that we need the new database format for that ... yet another thing to
> > do before we can support 5/10 MHz channels.
>
> Indeed. For 5150 -- 5350, the spectral power density may not exceed
> 10mW/MHz (and overall emitted power in the range per device not 200mW);
> this gives a limit of 200mW for 20MHz channels or 100mW if no TPC is
> used for 5250 -- 5350. (For 5470--5725 use 5x those values.)
> I'm not aware of WLAN devices with narrower channels yet, but if they
> come into existence, we'd have to reflect it somehow ...
They exist, we just don't support them right now ... I put it on the
todo list for now.
johannes
^ permalink raw reply
* Re: WLAN Regulatory Domain Germany
From: Kurt Garloff @ 2010-05-25 15:14 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1274690246.3743.20.camel@jlt3.sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 3761 bytes --]
Johannes,
On Mon, May 24, 2010 at 10:37:26AM +0200, Johannes Berg wrote:
> > 8<------------------------------------------------------------------------
> >
> > # Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
> > # http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
> > # For the 5GHz range also see
> > # http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
> > # The values have been reduced by a factor of 2 (3db) for non TPC devcies
> > # (in other words: devices with TPC can use twice the tx power of this table).
> >
> > country DE:
> > # entries 279004 and 280006
> > (2400 - 2483.5 @ 40), (N/A, 100 mW)
> > # entry 303005
> > (5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
> > # entries 304002 and 305002
> > (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
> > # entries 308002, 309001 and 310003
> > (5470 - 5725 @ 40), (N/A, 500 mW), DFS
>
> I haven't verified the entries in the Frequenznutzungsplan itself, but
> according to the second document this seems fine. I think there ought to
> be a comment in the db.txt file indicating the rationale for using 100mW
> rather than 200mW.
OK, new suggestion.
8<------------------------------------------------------------------------
# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
# For the 5GHz range also see
# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
# The values have been reduced by a factor of 2 (3db) for non TPC devices
# (in other words: devices with TPC can use twice the tx power of this table).
# Note that the docs do not require TPC for 5150--5250; the reduction to
# 100mW thus is not strictly required -- however the conservative 100mW
# limit is used here as the non-interference with radar and satellite
# apps relies on the attenuation by the building walls only in the
# absence of DFS; the neighbour countries have 100mW limit here as well.
country DE:
# entries 279004 and 280006
(2400 - 2483.5 @ 40), (N/A, 100 mW)
# entry 303005
(5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
# entries 304002 and 305002
(5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
# entries 308002, 309001 and 310003
(5470 - 5725 @ 40), (N/A, 500 mW), DFS
8<------------------------------------------------------------------------
Can we actually put several entries covering the same frequency range?
Then we could put 200mW for DFS and 100mW for non-DFS.
This would also address the next issue you raise ...
> Also note that there are different requirements depending on the channel
> bandwidth, which will eventually come up in Linux too. But I think for
> that we need the new database format for that ... yet another thing to
> do before we can support 5/10 MHz channels.
Indeed. For 5150 -- 5350, the spectral power density may not exceed
10mW/MHz (and overall emitted power in the range per device not 200mW);
this gives a limit of 200mW for 20MHz channels or 100mW if no TPC is
used for 5250 -- 5350. (For 5470--5725 use 5x those values.)
I'm not aware of WLAN devices with narrower channels yet, but if they
come into existence, we'd have to reflect it somehow ...
Best,
--
Kurt Garloff, VP OPS Partner Engineering -- Novell Inc.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: ath5k past 2.6.30 breaks monitor mode (and thus the aircrack suite)
From: Bob Copeland @ 2010-05-25 14:53 UTC (permalink / raw)
To: Weedy; +Cc: Gábor Stefanik, linux-wireless
In-Reply-To: <AANLkTinynNqs6_zyTJcpi7yKiSvC5fBhbM2tVZcnoNUq@mail.gmail.com>
2010/5/25 Weedy <weedy2887@gmail.com>:
> 2010/5/24 Gábor Stefanik <netrolller.3d@gmail.com>:
>> 2010/5/25 Weedy <weedy2887@gmail.com>:
>>> 2010/5/23 Gábor Stefanik <netrolller.3d@gmail.com>:
>>>> In the meantime, one thing to test: Add a printk of sc->opmode.
>>>
>>> May 24 22:04:20 tiny-h4x kernel: [41147.243149] sc->opmode: 02 (over9000 times)
>>>
>>> So i'm guessing I did it wrong (I don't know C).
>>> printk(KERN_NOTICE "sc->opmode: %02x\n", sc->opmode);
>>>
>>
>> No, that is correct, and proves my theory (2 is NL80211_IFTYPE_STATION
>> - it should be 6 for monitor mode).
>>
>> BTW, please use "Reply to all".
>>
> gmail got rid of the "Reply to all by default" option :<
>
> When you have a patch I will be waiting.
Sorry, I missed this thread somehow. Thanks for the detective
work and apologies for my stupid goof. Gábor, are you prepping
a patch? I can fix it if you like.
--
Bob Copeland %% www.bobcopeland.com
^ permalink raw reply
* wireless-regdb: FI/CZ updates
From: Pekka Pietikainen @ 2010-05-25 13:20 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
Was looking at the relevant local regulations and noticed the regdb allowed
less power at 5GHz than is actually allowed. Until I found the "If you don't do TPC you have
to reduce your power by 3dB sometimes" bit on the next page.
And looks like someone that did the entry for CZ fell into the same trap, they have
"stations in the c and d bands must employ automatic transmitter power
control, which provides, on average, an interference mitigation factor at
least 3 dB on the maximum permitted output power of the systems. If
automatic power control is not employed, the maximum permitted mean e.i.r.p.
and the corresponding limit of the mean e.i.r.p. density for bands c and d
must be reduced by 3 dB;"
Please sanity check, I became very confused while looking into this.
(like some places starting their freq ranges at 2400, others at 2402. Didn't
touch those, regs say 2400-2485,5, 5150-5250, 5250-5350 and 5470-5725)
Signed-off-by: Pekka Pietikäinen <pp@ee.oulu.fi>
diff -up ./db.txt.orig ./db.txt
--- ./db.txt.orig 2010-05-25 15:03:48.812116854 +0300
+++ ./db.txt 2010-05-25 15:58:43.947117884 +0300
@@ -170,11 +170,13 @@ country CY:
# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
+# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
+# implemented.
country CZ:
(2400 - 2483.5 @ 40), (N/A, 100 mW)
(5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
- (5250 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR, DFS
- (5470 - 5725 @ 40), (N/A, 1000 mW), DFS
+ (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+ (5470 - 5725 @ 40), (N/A, 500 mW), DFS
# Data from "Frequenznutzungsplan" (as published in April 2008),
# downloaded from http://www.bundesnetzagentur.de/media/archive/13358.pdf
@@ -226,11 +228,15 @@ country ES:
(5250 - 5330 @ 40), (N/A, 20), DFS
(5490 - 5710 @ 40), (N/A, 27), DFS
+# Data from FICORA Regulation 15Z / 2009 M
+# http://www.ficora.fi/attachments/suomiry/5l1x1FIIk/Viestintavirasto15Z2009M.pdf
+# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
+# implemented.
country FI:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (2402 - 2482 @ 40), (N/A, 100mW)
+ (5170 - 5250 @ 40), (N/A, 200mW), NO-OUTDOOR
+ (5250 - 5330 @ 40), (N/A, 100mW), NO-OUTDOOR, DFS
+ (5490 - 5710 @ 40), (N/A, 500mW), DFS
country FR:
(2402 - 2482 @ 40), (N/A, 20)
^ permalink raw reply
* Re: wireless-regdb: A band is missing for IL
From: John W. Linville @ 2010-05-25 13:38 UTC (permalink / raw)
To: Emmanuel Grumbach; +Cc: linux-wireless
In-Reply-To: <AANLkTimkpbans5mUObR8PWzf2-Uh0K-cZVVg0HjNxnSv@mail.gmail.com>
On Tue, May 25, 2010 at 10:03:05AM +0300, Emmanuel Grumbach wrote:
> According to http://en.wikipedia.org/wiki/List_of_WLAN_channels#5.C2.A0GHz_.28802.11a.2Fh.2Fj.2Fn.29
>
> Channels 34 - 64 are allowed in 20 Mhz in Israel. This is not what is
> written in db.txt:
>
> country IL:
> (2402 - 2482 @ 40), (N/A, 20)
>
> This wikipedia page relies on an official page from the Israel
> Ministry of the Communication.
Would you care to send a patch?
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: ath5k past 2.6.30 breaks monitor mode (and thus the aircrack suite)
From: Weedy @ 2010-05-25 13:30 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: linux-wireless
In-Reply-To: <AANLkTikOgv6d0FlXu2-smnYPApeehjRq_j8UxEealqFC@mail.gmail.com>
2010/5/24 Gábor Stefanik <netrolller.3d@gmail.com>:
> 2010/5/25 Weedy <weedy2887@gmail.com>:
>> 2010/5/23 Gábor Stefanik <netrolller.3d@gmail.com>:
>>> In the meantime, one thing to test: Add a printk of sc->opmode.
>>
>> May 24 22:04:20 tiny-h4x kernel: [41147.243149] sc->opmode: 02 (over9000 times)
>>
>> So i'm guessing I did it wrong (I don't know C).
>> printk(KERN_NOTICE "sc->opmode: %02x\n", sc->opmode);
>>
>
> No, that is correct, and proves my theory (2 is NL80211_IFTYPE_STATION
> - it should be 6 for monitor mode).
>
> BTW, please use "Reply to all".
>
gmail got rid of the "Reply to all by default" option :<
When you have a patch I will be waiting.
^ permalink raw reply
* Re: [RFC PATCH] mac80211: Add support for hardware ARP query filtering
From: Juuso Oikarinen @ 2010-05-25 11:34 UTC (permalink / raw)
To: ext Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1274786743.3635.33.camel@jlt3.sipsolutions.net>
On Tue, 2010-05-25 at 13:25 +0200, ext Johannes Berg wrote:
> On Tue, 2010-05-25 at 12:31 +0300, Juuso Oikarinen wrote:
>
> > > BTW, how will drivers deal with getting this while unassociated? If, for
> > > example, I set an address before associating, you'll get it while
> > > unassociated and not again when associated. Another thing to document --
> > > driver needs to handle that, DHCP is not everything :)
> >
> > This is actually a good point. The wl1271 driver configures the ARP
> > filter immediately - associated or not - once the chipset is booted up
> > (as above.) This is indeed not very generic.
> >
> > I will move the set_arp_filter -thingy from _open() to when the we are
> > associated. That way we get the initial IP address (if there happen to
> > be any) from start when the address is actually needed.
>
> But then you would still get a callback way before the hardware is even
> started if you set the address before ifup ... mac80211 should probably
> catch that. Or does the networking stack already defer it then?
True again. The call-backs will not get deferred by the stack. That must
also be handled.
> Another thing that came to mind -- how about locking? Will the callback
> have to be atomic? Can you really access idev->ifa_list without any
> locking at all?
AFAIK the callback need not be atomic. I will need to check about the
locking, but we probably do need that.
-Juuso
> > > This is obviously broken when you have multiple virtual interfaces, so
> > > you either need to build a common list of IP addresses, or punt the
> > > problem to the driver and give the callback an ieee80211_vif argument
> > > and clearly document that the driver will have to keep track of it for
> > > each interface.
> >
> > Good point. I will "punt" (never heard this expression before!)
>
> Don't take my word for it ... I heard that once but can't find reference
> to it being a correct use of the word ;)
>
> johannes
>
^ permalink raw reply
* Re: [RFC PATCH] mac80211: Add support for hardware ARP query filtering
From: Johannes Berg @ 2010-05-25 11:25 UTC (permalink / raw)
To: Juuso Oikarinen; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1274779914.5277.216.camel@wimaxnb.nmp.nokia.com>
On Tue, 2010-05-25 at 12:31 +0300, Juuso Oikarinen wrote:
> > BTW, how will drivers deal with getting this while unassociated? If, for
> > example, I set an address before associating, you'll get it while
> > unassociated and not again when associated. Another thing to document --
> > driver needs to handle that, DHCP is not everything :)
>
> This is actually a good point. The wl1271 driver configures the ARP
> filter immediately - associated or not - once the chipset is booted up
> (as above.) This is indeed not very generic.
>
> I will move the set_arp_filter -thingy from _open() to when the we are
> associated. That way we get the initial IP address (if there happen to
> be any) from start when the address is actually needed.
But then you would still get a callback way before the hardware is even
started if you set the address before ifup ... mac80211 should probably
catch that. Or does the networking stack already defer it then?
Another thing that came to mind -- how about locking? Will the callback
have to be atomic? Can you really access idev->ifa_list without any
locking at all?
> > This is obviously broken when you have multiple virtual interfaces, so
> > you either need to build a common list of IP addresses, or punt the
> > problem to the driver and give the callback an ieee80211_vif argument
> > and clearly document that the driver will have to keep track of it for
> > each interface.
>
> Good point. I will "punt" (never heard this expression before!)
Don't take my word for it ... I heard that once but can't find reference
to it being a correct use of the word ;)
johannes
^ permalink raw reply
* Re: [RFC PATCH] mac80211: Add support for hardware ARP query filtering
From: Juuso Oikarinen @ 2010-05-25 9:31 UTC (permalink / raw)
To: ext Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1274778802.3635.30.camel@jlt3.sipsolutions.net>
On Tue, 2010-05-25 at 11:13 +0200, ext Johannes Berg wrote:
> On Tue, 2010-05-25 at 10:48 +0300, Juuso Oikarinen wrote:
>
> > +struct in_ifaddr;
> > +
>
> I think you should include a header file for that, or was there a reason
> you didn't?
Yeah, I'll add the header.
> > + * @configure_ip_filter: Configuration function for IP address based filters,
> > + * such as an ARP query filter. This function is called with all the IP
> > + * addresses configured to the interface as argument - all frames targeted
> > + * to any of these addresses should pass through.
>
> Huh ok I thought you wanted ARP filtering, not IP filtering. You need to
> be more explicit about what this should do. IP filtering is not useful
> since those frames will be unicast on the ethernet layer. I think this
> should be more focused on ARP filtering.
True, this is about ARP filtering. I was pondering naming it arp or IP,
then opted to go with IP just because I was thinking that there may be
some other frames we might want to filter based on IP in the future.
Maybe I'm thinking too far ahead ;)
I'll update the naming to be ARP all around.
> Additionally, it needs to be very explicit that it must filter ONLY ARP
> packets that do not match any of the given IP addresses. If, for
> example, the hardware can only handle 2 addresses, but you have 3 in the
> list, the filter must be turned off. Any packet that the device cannot
> parse properly must also be passed through. All such things should be
> documented.
This is a valid point. That's actually what the wl1271 driver does - as
the HW only supports one address for its filter. I'll add some text for
this.
> > +struct in_ifaddr;
>
> You should get the right include too.
>
> > +static inline int drv_configure_ip_filter(struct ieee80211_hw *hw,
> > + struct in_ifaddr *ifa_list)
> > +{
> > + struct ieee80211_local *local = hw_to_local(hw);
> > + int ret = 0;
> > +
> > + if (local->ops->configure_ip_filter)
> > + ret = local->ops->configure_ip_filter(hw, ifa_list);
> > + return ret;
> > +}
>
> Tracing would be nice, you should even able able to trace all addresses
> in a variable-length array.
Yeah, I was lazy. I will look into this :P
>
> > @@ -330,6 +330,7 @@ static int ieee80211_open(struct net_device *dev)
> > if (sdata->vif.type == NL80211_IFTYPE_STATION)
> > ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
> >
> > + ieee80211_set_arp_filter(dev);
>
> That seems unnecessary if drivers assume that there are no addresses to
> start with?
>
The drivers assume there is no address to start with - this is for the
scenario when there is, so that the driver enables the filtering from
scratch. You can do this, for instance:
ifconfig wlan0 up 192.168.1.1
ifconfig wlan0 down
ifconfig wlan0 up
The address 192.168.1.1 will be there already on ifconfig wlan0 up.
> BTW, how will drivers deal with getting this while unassociated? If, for
> example, I set an address before associating, you'll get it while
> unassociated and not again when associated. Another thing to document --
> driver needs to handle that, DHCP is not everything :)
This is actually a good point. The wl1271 driver configures the ARP
filter immediately - associated or not - once the chipset is booted up
(as above.) This is indeed not very generic.
I will move the set_arp_filter -thingy from _open() to when the we are
associated. That way we get the initial IP address (if there happen to
be any) from start when the address is actually needed.
>
> > +static int ieee80211_ifa_changed(struct notifier_block *nb,
> > + unsigned long data, void *arg)
> > +{
> > + struct in_ifaddr *ifa = arg;
> > + struct ieee80211_local *local =
> > + container_of(nb, struct ieee80211_local,
> > + ifa_notifier);
> > + struct net_device *ndev = ifa->ifa_dev->dev;
> > + struct wireless_dev *wdev = ndev->ieee80211_ptr;
> > +
> > + if (!wdev)
> > + return NOTIFY_DONE;
> > +
> > + if (wdev->wiphy != local->hw.wiphy)
> > + return NOTIFY_DONE;
> > +
> > + ieee80211_set_arp_filter(ndev);
> > + return NOTIFY_DONE;
> > +}
>
> This is obviously broken when you have multiple virtual interfaces, so
> you either need to build a common list of IP addresses, or punt the
> problem to the driver and give the callback an ieee80211_vif argument
> and clearly document that the driver will have to keep track of it for
> each interface.
Good point. I will "punt" (never heard this expression before!) the
problem to the driver with a vif pointer.
Thanks for your review. :)
-Juuso
> johannes
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox