]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 14 Mar 2014 18:33:19 +0000 (14:33 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 14 Mar 2014 18:33:19 +0000 (14:33 -0400)
1  2 
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/pcie/drv.c

index 38a54a3fde3425ee0dd6b301a09c06f1c330d775,18a895a949d4520a02af0f34232f6a739a4c4552..2aa3ee93c68ed7c9a9e2b93b00e512ac4003f71f
@@@ -378,6 -378,7 +378,6 @@@ int iwl_send_bt_init_conf(struct iwl_mv
  
        flags = iwlwifi_mod_params.bt_coex_active ?
                        BT_COEX_NW : BT_COEX_DISABLE;
 -      flags |= BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN | BT_SYNC_2_BT_DISABLE;
        bt_cmd->flags = cpu_to_le32(flags);
  
        bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
                                            BT_VALID_TXRX_MAX_FREQ_0 |
                                            BT_VALID_SYNC_TO_SCO);
  
 +      if (IWL_MVM_BT_COEX_SYNC2SCO)
 +              bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
 +
        if (mvm->cfg->bt_shared_single_ant)
                memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
                       sizeof(iwl_single_shared_ant));
@@@ -491,7 -489,8 +491,7 @@@ static int iwl_mvm_bt_udpate_ctrl_kill_
        return ret;
  }
  
 -static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
 -                                     bool enable)
 +int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable)
  {
        struct iwl_bt_coex_cmd *bt_cmd;
        /* Send ASYNC since this can be sent from an atomic context */
                .dataflags = { IWL_HCMD_DFL_DUP, },
                .flags = CMD_ASYNC,
        };
 -
 -      struct ieee80211_sta *sta;
        struct iwl_mvm_sta *mvmsta;
        int ret;
  
 -      if (sta_id == IWL_MVM_STATION_COUNT)
 -              return 0;
 -
 -      sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
 -                                      lockdep_is_held(&mvm->mutex));
 -
 -      /* This can happen if the station has been removed right now */
 -      if (IS_ERR_OR_NULL(sta))
 +      mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
 +      if (!mvmsta)
                return 0;
  
 -      mvmsta = iwl_mvm_sta_from_mac80211(sta);
 -
        /* nothing to do */
 -      if (mvmsta->bt_reduced_txpower == enable)
 +      if (mvmsta->bt_reduced_txpower_dbg ||
 +          mvmsta->bt_reduced_txpower == enable)
                return 0;
  
        bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
@@@ -544,7 -552,6 +544,7 @@@ struct iwl_bt_iterator_data 
        bool reduced_tx_power;
        struct ieee80211_chanctx_conf *primary;
        struct ieee80211_chanctx_conf *secondary;
 +      bool primary_ll;
  };
  
  static inline
@@@ -570,113 -577,72 +570,113 @@@ static void iwl_mvm_bt_notif_iterator(v
        struct iwl_mvm *mvm = data->mvm;
        struct ieee80211_chanctx_conf *chanctx_conf;
        enum ieee80211_smps_mode smps_mode;
 +      u32 bt_activity_grading;
        int ave_rssi;
  
        lockdep_assert_held(&mvm->mutex);
  
 -      if (vif->type != NL80211_IFTYPE_STATION &&
 -          vif->type != NL80211_IFTYPE_AP)
 -              return;
 +      switch (vif->type) {
 +      case NL80211_IFTYPE_STATION:
 +              /* default smps_mode for BSS / P2P client is AUTOMATIC */
 +              smps_mode = IEEE80211_SMPS_AUTOMATIC;
 +              data->num_bss_ifaces++;
 +
 +              /*
 +               * Count unassoc BSSes, relax SMSP constraints
 +               * and disable reduced Tx Power
 +               */
 +              if (!vif->bss_conf.assoc) {
 +                      iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
 +                                          smps_mode);
 +                      if (iwl_mvm_bt_coex_reduced_txp(mvm,
 +                                                      mvmvif->ap_sta_id,
 +                                                      false))
 +                              IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
 +                      return;
 +              }
 +              break;
 +      case NL80211_IFTYPE_AP:
 +              /* default smps_mode for AP / GO is OFF */
 +              smps_mode = IEEE80211_SMPS_OFF;
 +              if (!mvmvif->ap_ibss_active) {
 +                      iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
 +                                          smps_mode);
 +                      return;
 +              }
  
 -      smps_mode = IEEE80211_SMPS_AUTOMATIC;
 +              /* the Ack / Cts kill mask must be default if AP / GO */
 +              data->reduced_tx_power = false;
 +              break;
 +      default:
 +              return;
 +      }
  
        chanctx_conf = rcu_dereference(vif->chanctx_conf);
  
        /* If channel context is invalid or not on 2.4GHz .. */
        if ((!chanctx_conf ||
             chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
 -              /* ... and it is an associated STATION, relax constraints */
 -              if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc)
 -                      iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
 -                                          smps_mode);
 -              iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
 +              /* ... relax constraints and disable rssi events */
 +              iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
 +                                  smps_mode);
 +              if (vif->type == NL80211_IFTYPE_STATION)
 +                      iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
                return;
        }
  
 -      /* SoftAP / GO will always be primary */
 -      if (vif->type == NL80211_IFTYPE_AP) {
 -              if (!mvmvif->ap_ibss_active)
 -                      return;
 +      bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
 +      if (bt_activity_grading >= BT_HIGH_TRAFFIC)
 +              smps_mode = IEEE80211_SMPS_STATIC;
 +      else if (bt_activity_grading >= BT_LOW_TRAFFIC)
 +              smps_mode = vif->type == NL80211_IFTYPE_AP ?
 +                              IEEE80211_SMPS_OFF :
 +                              IEEE80211_SMPS_DYNAMIC;
 +      IWL_DEBUG_COEX(data->mvm,
 +                     "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
 +                     mvmvif->id, data->notif->bt_status, bt_activity_grading,
 +                     smps_mode);
  
 -              /* the Ack / Cts kill mask must be default if AP / GO */
 -              data->reduced_tx_power = false;
 +      iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
  
 -              if (chanctx_conf == data->primary)
 -                      return;
 +      /* low latency is always primary */
 +      if (iwl_mvm_vif_low_latency(mvmvif)) {
 +              data->primary_ll = true;
  
 -              /* downgrade the current primary no matter what its type is */
                data->secondary = data->primary;
                data->primary = chanctx_conf;
 -              return;
        }
  
 -      data->num_bss_ifaces++;
 +      if (vif->type == NL80211_IFTYPE_AP) {
 +              if (!mvmvif->ap_ibss_active)
 +                      return;
 +
 +              if (chanctx_conf == data->primary)
 +                      return;
  
 -      /* we are now a STA / P2P Client, and take associated ones only */
 -      if (!vif->bss_conf.assoc)
 +              if (!data->primary_ll) {
 +                      /*
 +                       * downgrade the current primary no matter what its
 +                       * type is.
 +                       */
 +                      data->secondary = data->primary;
 +                      data->primary = chanctx_conf;
 +              } else {
 +                      /* there is low latency vif - we will be secondary */
 +                      data->secondary = chanctx_conf;
 +              }
                return;
 +      }
  
 -      /* STA / P2P Client, try to be primary if first vif */
 +      /*
 +       * STA / P2P Client, try to be primary if first vif. If we are in low
 +       * latency mode, we are already in primary and just don't do much
 +       */
        if (!data->primary || data->primary == chanctx_conf)
                data->primary = chanctx_conf;
        else if (!data->secondary)
                /* if secondary is not NULL, it might be a GO */
                data->secondary = chanctx_conf;
  
 -      if (le32_to_cpu(data->notif->bt_activity_grading) >= BT_HIGH_TRAFFIC)
 -              smps_mode = IEEE80211_SMPS_STATIC;
 -      else if (le32_to_cpu(data->notif->bt_activity_grading) >=
 -               BT_LOW_TRAFFIC)
 -              smps_mode = IEEE80211_SMPS_DYNAMIC;
 -
 -      IWL_DEBUG_COEX(data->mvm,
 -                     "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
 -                     mvmvif->id,  data->notif->bt_status,
 -                     data->notif->bt_activity_grading, smps_mode);
 -
 -      iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
 -
        /* don't reduce the Tx power if in loose scheme */
        if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
            mvm->cfg->bt_shared_single_ant) {
@@@ -906,8 -872,11 +906,11 @@@ void iwl_mvm_bt_rssi_event(struct iwl_m
  
        lockdep_assert_held(&mvm->mutex);
  
-       /* Rssi update while not associated ?! */
-       if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT))
+       /*
+        * Rssi update while not associated - can happen since the statistics
+        * are handled asynchronously
+        */
+       if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
                return;
  
        /* No BT - reports should be disabled */
index 0f52e961a5a514f069e80b139a3e5df484b5e76e,3872ead75488d6ac485a5cb147a4037988f7ee89..1f97631a82e423b1c0a09f709adbfe6ab6225d43
@@@ -66,7 -66,6 +66,7 @@@
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/pci-aspm.h>
 +#include <linux/acpi.h>
  
  #include "iwl-trans.h"
  #include "iwl-drv.h"
@@@ -360,13 -359,12 +360,12 @@@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_c
  /* 7265 Series */
        {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095A, 0x5112, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5100, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095A, 0x510A, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5412, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
 +
 +/* 8000 Series */
 +      {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
 +      {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)},
  #endif /* CONFIG_IWLMVM */
  
        {0}
  };
  MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
  
 +#ifdef CONFIG_ACPI
 +#define SPL_METHOD            "SPLC"
 +#define SPL_DOMAINTYPE_MODULE BIT(0)
 +#define SPL_DOMAINTYPE_WIFI   BIT(1)
 +#define SPL_DOMAINTYPE_WIGIG  BIT(2)
 +#define SPL_DOMAINTYPE_RFEM   BIT(3)
 +
 +static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
 +{
 +      union acpi_object *limits, *domain_type, *power_limit;
 +
 +      if (splx->type != ACPI_TYPE_PACKAGE ||
 +          splx->package.count != 2 ||
 +          splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
 +          splx->package.elements[0].integer.value != 0) {
 +              IWL_ERR(trans, "Unsupported splx structure");
 +              return 0;
 +      }
 +
 +      limits = &splx->package.elements[1];
 +      if (limits->type != ACPI_TYPE_PACKAGE ||
 +          limits->package.count < 2 ||
 +          limits->package.elements[0].type != ACPI_TYPE_INTEGER ||
 +          limits->package.elements[1].type != ACPI_TYPE_INTEGER) {
 +              IWL_ERR(trans, "Invalid limits element");
 +              return 0;
 +      }
 +
 +      domain_type = &limits->package.elements[0];
 +      power_limit = &limits->package.elements[1];
 +      if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) {
 +              IWL_DEBUG_INFO(trans, "WiFi power is not limited");
 +              return 0;
 +      }
 +
 +      return power_limit->integer.value;
 +}
 +
 +static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev)
 +{
 +      acpi_handle pxsx_handle;
 +      acpi_handle handle;
 +      struct acpi_buffer splx = {ACPI_ALLOCATE_BUFFER, NULL};
 +      acpi_status status;
 +
 +      pxsx_handle = ACPI_HANDLE(&pdev->dev);
 +      if (!pxsx_handle) {
 +              IWL_ERR(trans, "Could not retrieve root port ACPI handle");
 +              return;
 +      }
 +
 +      /* Get the method's handle */
 +      status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle);
 +      if (ACPI_FAILURE(status)) {
 +              IWL_DEBUG_INFO(trans, "SPL method not found");
 +              return;
 +      }
 +
 +      /* Call SPLC with no arguments */
 +      status = acpi_evaluate_object(handle, NULL, NULL, &splx);
 +      if (ACPI_FAILURE(status)) {
 +              IWL_ERR(trans, "SPLC invocation failed (0x%x)", status);
 +              return;
 +      }
 +
 +      trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer);
 +      IWL_DEBUG_INFO(trans, "Default power limit set to %lld",
 +                     trans->dflt_pwr_limit);
 +      kfree(splx.pointer);
 +}
 +
 +#else /* CONFIG_ACPI */
 +static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) {}
 +#endif
 +
  /* PCI registers */
  #define PCI_CFG_RETRY_TIMEOUT 0x041
  
@@@ -500,8 -419,6 +499,8 @@@ static int iwl_pci_probe(struct pci_de
                goto out_free_trans;
        }
  
 +      set_dflt_pwr_limit(iwl_trans, pdev);
 +
        /* register transport layer debugfs here */
        ret = iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir);
        if (ret)