iwlwifi: send PAN parameters
authorJohannes Berg <johannes.berg@intel.com>
Fri, 27 Aug 2010 16:44:50 +0000 (09:44 -0700)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Fri, 27 Aug 2010 16:47:46 +0000 (09:47 -0700)
In order for the microcode to be able to handle
multiple interfaces, we need to give it the PAN
parameters that state how to allocate the time
between the two interfaces. Do this, and update
it wherever necessary.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.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-scan.c

index 2d4cdb027aa678f63aca51ef33eade4c5f82d513..6fb52abafc8d46e305328754564d25827cd8a16a 100644 (file)
@@ -270,12 +270,86 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
        return max_rssi - agc - IWLAGN_RSSI_OFFSET;
 }
 
+static int iwlagn_set_pan_params(struct iwl_priv *priv)
+{
+       struct iwl_wipan_params_cmd cmd;
+       struct iwl_rxon_context *ctx_bss, *ctx_pan;
+       int slot0 = 300, slot1 = 0;
+       int ret;
+
+       if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+               return 0;
+
+       BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+       lockdep_assert_held(&priv->mutex);
+
+       ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
+       ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       /* only 2 slots are currently allowed */
+       cmd.num_slots = 2;
+
+       cmd.slots[0].type = 0; /* BSS */
+       cmd.slots[1].type = 1; /* PAN */
+
+       if (ctx_bss->vif && ctx_pan->vif) {
+               int bcnint = ctx_pan->vif->bss_conf.beacon_int;
+
+               /* should be set, but seems unused?? */
+               cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
+
+               if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
+                   bcnint &&
+                   bcnint != ctx_bss->vif->bss_conf.beacon_int) {
+                       IWL_ERR(priv,
+                               "beacon intervals don't match (%d, %d)\n",
+                               ctx_bss->vif->bss_conf.beacon_int,
+                               ctx_pan->vif->bss_conf.beacon_int);
+               } else
+                       bcnint = max_t(int, bcnint,
+                                      ctx_bss->vif->bss_conf.beacon_int);
+               if (!bcnint)
+                       bcnint = 100;
+               slot0 = bcnint / 2;
+               slot1 = bcnint - slot0;
+
+               if (test_bit(STATUS_SCAN_HW, &priv->status) ||
+                   (!ctx_bss->vif->bss_conf.idle &&
+                    !ctx_bss->vif->bss_conf.assoc)) {
+                       slot0 = bcnint * 3 - 20;
+                       slot1 = 20;
+               } else if (!ctx_pan->vif->bss_conf.idle &&
+                           !ctx_pan->vif->bss_conf.assoc) {
+                       slot1 = bcnint * 3 - 20;
+                       slot0 = 20;
+               }
+       } else if (ctx_pan->vif) {
+               slot0 = 0;
+               slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
+                                       ctx_pan->vif->bss_conf.beacon_int;
+               slot1 = max_t(int, 100, slot1);
+       }
+
+       cmd.slots[0].width = cpu_to_le16(slot0);
+       cmd.slots[1].width = cpu_to_le16(slot1);
+
+       ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
+       if (ret)
+               IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
+
+       return ret;
+}
+
 struct iwl_hcmd_ops iwlagn_hcmd = {
        .rxon_assoc = iwlagn_send_rxon_assoc,
        .commit_rxon = iwl_commit_rxon,
        .set_rxon_chain = iwl_set_rxon_chain,
        .set_tx_ant = iwlagn_send_tx_ant_config,
        .send_bt_config = iwl_send_bt_config,
+       .set_pan_params = iwlagn_set_pan_params,
 };
 
 struct iwl_hcmd_ops iwlagn_bt_hcmd = {
@@ -284,6 +358,7 @@ struct iwl_hcmd_ops iwlagn_bt_hcmd = {
        .set_rxon_chain = iwl_set_rxon_chain,
        .set_tx_ant = iwlagn_send_tx_ant_config,
        .send_bt_config = iwlagn_send_advance_bt_config,
+       .set_pan_params = iwlagn_set_pan_params,
 };
 
 struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
index 7002d7d0fac4550d3d5a8b6dca710fe839cedb34..a8f2adfd799e790e009192a5bed1594ed602e87c 100644 (file)
@@ -1424,6 +1424,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        scan->len = cpu_to_le16(cmd.len);
 
        set_bit(STATUS_SCAN_HW, &priv->status);
+
+       if (priv->cfg->ops->hcmd->set_pan_params &&
+           priv->cfg->ops->hcmd->set_pan_params(priv))
+               goto done;
+
        if (iwl_send_cmd_sync(priv, &cmd))
                goto done;
 
index 8e072283041330a0e341eaab9fd6c55e038f007c..f2884b5ca5b44c00186bc675820ac6d8aaa0a711 100644 (file)
@@ -197,6 +197,12 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
                }
        }
 
+       if (priv->cfg->ops->hcmd->set_pan_params) {
+               ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+               if (ret)
+                       return ret;
+       }
+
        /* Apply the new configuration
         * RXON unassoc clears the station table in uCode so restoration of
         * stations is needed after it (the RXON command) completes
index 04d7894e0004d2e9c2904d3b7da9410b364e34fb..b61b838a24b50dc33a2d957049eb862c72cad699 100644 (file)
@@ -1931,6 +1931,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
                                bss_conf->bssid);
        }
 
+       if (changes & BSS_CHANGED_IDLE &&
+           priv->cfg->ops->hcmd->set_pan_params) {
+               if (priv->cfg->ops->hcmd->set_pan_params(priv))
+                       IWL_ERR(priv, "failed to update PAN params\n");
+       }
+
        mutex_unlock(&priv->mutex);
 
        IWL_DEBUG_MAC80211(priv, "leave\n");
index d2ee55d6811db6495a4b4541081c83afd37c4c60..ab465c5fd6f62dc16b7c99b285c1fbb0c26be75b 100644 (file)
@@ -94,6 +94,7 @@ struct iwl_hcmd_ops {
                               struct iwl_rxon_context *ctx);
        int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
        void (*send_bt_config)(struct iwl_priv *priv);
+       int (*set_pan_params)(struct iwl_priv *priv);
 };
 
 struct iwl_hcmd_utils_ops {
index 556dcaaa0efe8ec29b671fadbd10e5bcf0180cde..7727f0966d3168e971dad3c6ffd03d3e45c54369 100644 (file)
@@ -572,6 +572,9 @@ static void iwl_bg_scan_completed(struct work_struct *work)
                iwlcore_commit_rxon(priv, ctx);
 
  out:
+       if (priv->cfg->ops->hcmd->set_pan_params)
+               priv->cfg->ops->hcmd->set_pan_params(priv);
+
        mutex_unlock(&priv->mutex);
 
        /*