]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 6 Jun 2011 17:58:21 +0000 (13:58 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 6 Jun 2011 17:58:21 +0000 (13:58 -0400)
14 files changed:
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/reset.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/libertas/if_sdio.c
drivers/ssb/driver_pcicore.c
net/mac80211/iface.c

index 22047628ccfa83bbd59242c511192e52ab04a12e..b6c5d3715b963e73f6b962070f6e78256449d107 100644 (file)
@@ -72,6 +72,11 @@ static int modparam_all_channels;
 module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
 MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
 
+static int modparam_fastchanswitch;
+module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO);
+MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios.");
+
+
 /* Module info */
 MODULE_AUTHOR("Jiri Slaby");
 MODULE_AUTHOR("Nick Kossifidis");
@@ -2686,6 +2691,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
        struct ath5k_hw *ah = sc->ah;
        struct ath_common *common = ath5k_hw_common(ah);
        int ret, ani_mode;
+       bool fast;
 
        ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
 
@@ -2705,7 +2711,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
        ath5k_drain_tx_buffs(sc);
        if (chan)
                sc->curchan = chan;
-       ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
+
+       fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
+
+       ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast,
                                                                skip_pcu);
        if (ret) {
                ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
index 3510de2cf6224c6ec11b091cfb3f50dd1fccf6b9..126a4eab35f39d7a10995f0f20ff814a87def88c 100644 (file)
@@ -1124,8 +1124,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
                        /* Non fatal, can happen eg.
                         * on mode change */
                        ret = 0;
-               } else
+               } else {
+                       ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+                               "fast chan change successful\n");
                        return 0;
+               }
        }
 
        /*
index 86feec86d13009c9b6266cd7bf102b8f3195af94..2282279cffc454c5089277a6cb1f279a60ad2dab 100644 (file)
@@ -177,79 +177,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
        return 0;
 }
 
-static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
-                                    struct ieee80211_channel_switch *ch_switch)
-{
-       /*
-        * MULTI-FIXME
-        * See iwl_mac_channel_switch.
-        */
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct iwl6000_channel_switch_cmd cmd;
-       const struct iwl_channel_info *ch_info;
-       u32 switch_time_in_usec, ucode_switch_time;
-       u16 ch;
-       u32 tsf_low;
-       u8 switch_count;
-       u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
-       struct ieee80211_vif *vif = ctx->vif;
-       struct iwl_host_cmd hcmd = {
-               .id = REPLY_CHANNEL_SWITCH,
-               .len = { sizeof(cmd), },
-               .flags = CMD_SYNC,
-               .data = { &cmd, },
-       };
-
-       cmd.band = priv->band == IEEE80211_BAND_2GHZ;
-       ch = ch_switch->channel->hw_value;
-       IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
-               ctx->active.channel, ch);
-       cmd.channel = cpu_to_le16(ch);
-       cmd.rxon_flags = ctx->staging.flags;
-       cmd.rxon_filter_flags = ctx->staging.filter_flags;
-       switch_count = ch_switch->count;
-       tsf_low = ch_switch->timestamp & 0x0ffffffff;
-       /*
-        * calculate the ucode channel switch time
-        * adding TSF as one of the factor for when to switch
-        */
-       if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
-               if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
-                   beacon_interval)) {
-                       switch_count -= (priv->ucode_beacon_time -
-                               tsf_low) / beacon_interval;
-               } else
-                       switch_count = 0;
-       }
-       if (switch_count <= 1)
-               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
-       else {
-               switch_time_in_usec =
-                       vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
-               ucode_switch_time = iwl_usecs_to_beacons(priv,
-                                               switch_time_in_usec,
-                                               beacon_interval);
-               cmd.switch_time = iwl_add_beacon_time(priv,
-                                               priv->ucode_beacon_time,
-                                               ucode_switch_time,
-                                               beacon_interval);
-       }
-       IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-                     cmd.switch_time);
-       ch_info = iwl_get_channel_info(priv, priv->band, ch);
-       if (ch_info)
-               cmd.expect_beacon = is_channel_radar(ch_info);
-       else {
-               IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-                       ctx->active.channel, ch);
-               return -EFAULT;
-       }
-       priv->switch_rxon.channel = cmd.channel;
-       priv->switch_rxon.switch_in_progress = true;
-
-       return iwl_send_cmd_sync(priv, &hcmd);
-}
-
 static struct iwl_lib_ops iwl2000_lib = {
        .set_hw_params = iwl2000_hw_set_hw_params,
        .rx_handler_setup = iwlagn_rx_handler_setup,
@@ -258,7 +185,6 @@ static struct iwl_lib_ops iwl2000_lib = {
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
-       .set_channel_switch = iwl2030_hw_channel_switch,
        .apm_ops = {
                .init = iwl_apm_init,
                .config = iwl2000_nic_config,
index a70b8cfafda195a3b92e1f46d2a7e617c3faba0f..5b721c56aee91ed133e932119aac5e2e14fca6bc 100644 (file)
@@ -331,8 +331,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
                        ctx->active.channel, ch);
                return -EFAULT;
        }
-       priv->switch_rxon.channel = cmd.channel;
-       priv->switch_rxon.switch_in_progress = true;
 
        return iwl_send_cmd_sync(priv, &hcmd);
 }
index fda6fe08cf91c10b875b9f738ca66d143fd2e2f4..fbe565c816e32ce367c09dad8ef5762e4c819d86 100644 (file)
@@ -270,8 +270,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
                        ctx->active.channel, ch);
                return -EFAULT;
        }
-       priv->switch_rxon.channel = cmd.channel;
-       priv->switch_rxon.switch_in_progress = true;
 
        return iwl_send_cmd_sync(priv, &hcmd);
 }
index a95ad84c537752c7c2c9491cc29eb8531c841b38..2532c7db3aff29946a3dcd8950086a604d393bde 100644 (file)
@@ -342,10 +342,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
         * receive commit_rxon request
         * abort any previous channel switch if still in process
         */
-       if (priv->switch_rxon.switch_in_progress &&
-           (priv->switch_rxon.channel != ctx->staging.channel)) {
+       if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
+           (priv->switch_channel != ctx->staging.channel)) {
                IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-                     le16_to_cpu(priv->switch_rxon.channel));
+                             le16_to_cpu(priv->switch_channel));
                iwl_chswitch_done(priv, false);
        }
 
index a662adcb2adbba26ce06045d48e7977390999447..8e1942ebd9a07aedc7c5e4c69a04b4ff690070a6 100644 (file)
@@ -2843,16 +2843,13 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
                goto out;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-           test_bit(STATUS_SCANNING, &priv->status))
+           test_bit(STATUS_SCANNING, &priv->status) ||
+           test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
                goto out;
 
        if (!iwl_is_associated_ctx(ctx))
                goto out;
 
-       /* channel switch in progress */
-       if (priv->switch_rxon.switch_in_progress == true)
-               goto out;
-
        if (priv->cfg->ops->lib->set_channel_switch) {
 
                ch = channel->hw_value;
@@ -2901,15 +2898,19 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
                         * at this point, staging_rxon has the
                         * configuration for channel switch
                         */
+                       set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+                       priv->switch_channel = cpu_to_le16(ch);
                        if (priv->cfg->ops->lib->set_channel_switch(priv,
-                                                                   ch_switch))
-                               priv->switch_rxon.switch_in_progress = false;
+                                                                   ch_switch)) {
+                               clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
+                                         &priv->status);
+                               priv->switch_channel = 0;
+                               ieee80211_chswitch_done(ctx->vif, false);
+                       }
                }
        }
 out:
        mutex_unlock(&priv->mutex);
-       if (!priv->switch_rxon.switch_in_progress)
-               ieee80211_chswitch_done(ctx->vif, false);
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
index 4653deada05b48b1383f1cda6b33c7477a1717d3..213c80c6a6682d000efff4b0d356cb5bafa691d4 100644 (file)
@@ -843,12 +843,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (priv->switch_rxon.switch_in_progress) {
+       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
                ieee80211_chswitch_done(ctx->vif, is_success);
-               mutex_lock(&priv->mutex);
-               priv->switch_rxon.switch_in_progress = false;
-               mutex_unlock(&priv->mutex);
-       }
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
index 3bb76f6ea41017448c5cc5ce99851c967d66dafe..a54d416ec345ce1b71d657de3ec92d4c5efb8ea6 100644 (file)
@@ -560,6 +560,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
 #define STATUS_POWER_PMI       16
 #define STATUS_FW_ERROR                17
 #define STATUS_DEVICE_ENABLED  18
+#define STATUS_CHANNEL_SWITCH_PENDING 19
 
 
 static inline int iwl_is_ready(struct iwl_priv *priv)
index 22a6e3ec7094e651b6afbe8245b778b25881bd77..c8de236c141be303d7ff6db5d058f4bfb093687f 100644 (file)
@@ -981,17 +981,6 @@ struct traffic_stats {
 #endif
 };
 
-/*
- * iwl_switch_rxon: "channel switch" structure
- *
- * @ switch_in_progress: channel switch in progress
- * @ channel: new channel
- */
-struct iwl_switch_rxon {
-       bool switch_in_progress;
-       __le16 channel;
-};
-
 /*
  * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
  * to perform continuous uCode event logging operation if enabled
@@ -1287,7 +1276,7 @@ struct iwl_priv {
 
        struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
 
-       struct iwl_switch_rxon switch_rxon;
+       __le16 switch_channel;
 
        struct {
                u32 error_event_table;
index 0053e9ea9021a433b98025701fcc1e9d703ea1f3..b774517aa9fa11dbe95c2f666ab88df0b915b1d9 100644 (file)
@@ -250,19 +250,19 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
 
-       if (priv->switch_rxon.switch_in_progress) {
-               if (!le32_to_cpu(csa->status) &&
-                   (csa->channel == priv->switch_rxon.channel)) {
-                       rxon->channel = csa->channel;
-                       ctx->staging.channel = csa->channel;
-                       IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-                             le16_to_cpu(csa->channel));
-                       iwl_chswitch_done(priv, true);
-               } else {
-                       IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+       if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+               return;
+
+       if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
+               rxon->channel = csa->channel;
+               ctx->staging.channel = csa->channel;
+               IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
                              le16_to_cpu(csa->channel));
-                       iwl_chswitch_done(priv, false);
-               }
+               iwl_chswitch_done(priv, true);
+       } else {
+               IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+                       le16_to_cpu(csa->channel));
+               iwl_chswitch_done(priv, false);
        }
 }
 
index a7b5cb0c2753845a581543e2ccca7963993592b0..224e9853c480605400a129fdda30b8298ca2d2bf 100644 (file)
@@ -907,7 +907,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
        card = sdio_get_drvdata(func);
 
        cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
-       if (ret)
+       if (ret || !cause)
                goto out;
 
        lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
@@ -1008,10 +1008,6 @@ static int if_sdio_probe(struct sdio_func *func,
        if (ret)
                goto release;
 
-       ret = sdio_claim_irq(func, if_sdio_interrupt);
-       if (ret)
-               goto disable;
-
        /* For 1-bit transfers to the 8686 model, we need to enable the
         * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
         * bit to allow access to non-vendor registers. */
@@ -1082,6 +1078,21 @@ static int if_sdio_probe(struct sdio_func *func,
        else
                card->rx_unit = 0;
 
+       /*
+        * Set up the interrupt handler late.
+        *
+        * If we set it up earlier, the (buggy) hardware generates a spurious
+        * interrupt, even before the interrupt has been enabled, with
+        * CCCR_INTx = 0.
+        *
+        * We register the interrupt handler late so that we can handle any
+        * spurious interrupts, and also to avoid generation of that known
+        * spurious interrupt in the first place.
+        */
+       ret = sdio_claim_irq(func, if_sdio_interrupt);
+       if (ret)
+               goto disable;
+
        /*
         * Enable interrupts now that everything is set up
         */
index 82feb348c8bbf3762195aaf2cf07668792f72721..2a20dabec76d722d1c311aad9e1e34a13382b6d2 100644 (file)
@@ -539,10 +539,12 @@ void ssb_pcicore_init(struct ssb_pcicore *pc)
        if (!pc->hostmode)
                ssb_pcicore_init_clientmode(pc);
 
-       /* Additional always once-executed workarounds */
-       ssb_pcicore_serdes_workaround(pc);
-       /* TODO: ASPM */
-       /* TODO: Clock Request Update */
+       /* Additional PCIe always once-executed workarounds */
+       if (dev->id.coreid == SSB_DEV_PCIE) {
+               ssb_pcicore_serdes_workaround(pc);
+               /* TODO: ASPM */
+               /* TODO: Clock Request Update */
+       }
 }
 
 static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
index 49d4f869e0bc74cfcd397558b2283440da761c1d..dee30aea9ab31eba7021812894c35d495e28ab71 100644 (file)
@@ -1145,6 +1145,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                                + IEEE80211_ENCRYPT_HEADROOM;
        ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
 
+       ret = dev_alloc_name(ndev, ndev->name);
+       if (ret < 0)
+               goto fail;
+
        ieee80211_assign_perm_addr(local, ndev, type);
        memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
        SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));