iwlwifi: decouple PCIe transport from mac80211
[cascardo/linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / ops.c
index 5e8ab79..55d9096 100644 (file)
@@ -292,7 +292,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
        RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif,
                   RX_HANDLER_ASYNC_LOCKED),
        RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE,
-                      iwl_mvm_temp_notif, RX_HANDLER_ASYNC_LOCKED),
+                      iwl_mvm_temp_notif, RX_HANDLER_ASYNC_UNLOCKED),
        RX_HANDLER_GRP(PHY_OPS_GROUP, CT_KILL_NOTIFICATION,
                       iwl_mvm_ct_kill_notif, RX_HANDLER_SYNC),
 
@@ -418,6 +418,22 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
        HCMD_NAME(REPLY_DEBUG_CMD),
 };
 
+/* Please keep this array *SORTED* by hex value.
+ * Access is done through binary search
+ */
+static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
+       HCMD_NAME(SHARED_MEM_CFG_CMD),
+};
+
+/* Please keep this array *SORTED* by hex value.
+ * Access is done through binary search
+ */
+static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
+       HCMD_NAME(LINK_QUALITY_MEASUREMENT_CMD),
+       HCMD_NAME(LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF),
+       HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
+};
+
 /* Please keep this array *SORTED* by hex value.
  * Access is done through binary search
  */
@@ -449,6 +465,8 @@ static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = {
 static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
        [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
        [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
+       [SYSTEM_GROUP] = HCMD_ARR(iwl_mvm_system_names),
+       [MAC_CONF_GROUP] = HCMD_ARR(iwl_mvm_mac_conf_names),
        [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names),
        [DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names),
        [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names),
@@ -477,6 +495,29 @@ static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
 
 static void iwl_mvm_fw_error_dump_wk(struct work_struct *work);
 
+static void iwl_mvm_tx_unblock_dwork(struct work_struct *work)
+{
+       struct iwl_mvm *mvm =
+               container_of(work, struct iwl_mvm, cs_tx_unblock_dwork.work);
+       struct ieee80211_vif *tx_blocked_vif;
+       struct iwl_mvm_vif *mvmvif;
+
+       mutex_lock(&mvm->mutex);
+
+       tx_blocked_vif =
+               rcu_dereference_protected(mvm->csa_tx_blocked_vif,
+                                         lockdep_is_held(&mvm->mutex));
+
+       if (!tx_blocked_vif)
+               goto unlock;
+
+       mvmvif = iwl_mvm_vif_from_mac80211(tx_blocked_vif);
+       iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
+       RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
+unlock:
+       mutex_unlock(&mvm->mutex);
+}
+
 static struct iwl_op_mode *
 iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
                      const struct iwl_fw *fw, struct dentry *dbgfs_dir)
@@ -536,12 +577,20 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
 
-       mvm->aux_queue = 15;
-       mvm->first_agg_queue = 16;
-       mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1;
-       if (mvm->cfg->base_params->num_of_queues == 16) {
-               mvm->aux_queue = 11;
-               mvm->first_agg_queue = 12;
+       if (!iwl_mvm_is_dqa_supported(mvm)) {
+               mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1;
+
+               if (mvm->cfg->base_params->num_of_queues == 16) {
+                       mvm->aux_queue = 11;
+                       mvm->first_agg_queue = 12;
+               } else {
+                       mvm->aux_queue = 15;
+                       mvm->first_agg_queue = 16;
+               }
+       } else {
+               mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
+               mvm->first_agg_queue = IWL_MVM_DQA_MIN_DATA_QUEUE;
+               mvm->last_agg_queue = IWL_MVM_DQA_MAX_DATA_QUEUE;
        }
        mvm->sf_state = SF_UNINIT;
        mvm->cur_ucode = IWL_UCODE_INIT;
@@ -562,14 +611,20 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
        INIT_DELAYED_WORK(&mvm->fw_dump_wk, iwl_mvm_fw_error_dump_wk);
        INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
+       INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
+       INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
 
        spin_lock_init(&mvm->d0i3_tx_lock);
        spin_lock_init(&mvm->refs_lock);
        skb_queue_head_init(&mvm->d0i3_tx);
        init_waitqueue_head(&mvm->d0i3_exit_waitq);
 
+       atomic_set(&mvm->queue_sync_counter, 0);
+
        SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);
 
+       INIT_DELAYED_WORK(&mvm->cs_tx_unblock_dwork, iwl_mvm_tx_unblock_dwork);
+
        /*
         * Populate the state variables that the transport layer needs
         * to know about.
@@ -578,6 +633,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
        trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
        switch (iwlwifi_mod_params.amsdu_size) {
+       case IWL_AMSDU_DEF:
        case IWL_AMSDU_4K:
                trans_cfg.rx_buf_size = IWL_AMSDU_4K;
                break;
@@ -592,6 +648,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
                       iwlwifi_mod_params.amsdu_size);
                trans_cfg.rx_buf_size = IWL_AMSDU_4K;
        }
+
+       /* the hardware splits the A-MSDU */
+       if (mvm->cfg->mq_rx_supported)
+               trans_cfg.rx_buf_size = IWL_AMSDU_4K;
        trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
                                               IWL_UCODE_TLV_API_WIDE_CMD_HDR);
 
@@ -601,10 +661,16 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        trans_cfg.command_groups = iwl_mvm_groups;
        trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
 
-       trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
+       if (iwl_mvm_is_dqa_supported(mvm))
+               trans_cfg.cmd_queue = IWL_MVM_DQA_CMD_QUEUE;
+       else
+               trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
        trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
        trans_cfg.scd_set_active = true;
 
+       trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
+                                         driver_data[2]);
+
        trans_cfg.sdio_adma_addr = fw->sdio_adma_addr;
        trans_cfg.sw_csum_tx = IWL_MVM_SW_TX_CSUM_OFFLOAD;
 
@@ -707,9 +773,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        iwl_mvm_tof_init(mvm);
 
-       /* init RSS hash key */
-       get_random_bytes(mvm->secret_key, sizeof(mvm->secret_key));
-
        return op_mode;
 
  out_unregister:
@@ -761,10 +824,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
        for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
                kfree(mvm->nvm_sections[i].data);
 
-       iwl_free_fw_paging(mvm);
-
        iwl_mvm_tof_clean(mvm);
 
+       mutex_destroy(&mvm->mutex);
+       mutex_destroy(&mvm->d0i3_suspend_mutex);
+
        ieee80211_free_hw(mvm->hw);
 }
 
@@ -905,8 +969,6 @@ static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
 
        if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
                iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
-       else if (pkt->hdr.cmd == FRAME_RELEASE)
-               iwl_mvm_rx_frame_release(mvm, rxb, 0);
        else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
                iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
        else
@@ -922,11 +984,11 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
 
        if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
-       else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
-               iwl_mvm_rx_phy_cmd_mq(mvm, rxb);
        else if (unlikely(pkt->hdr.group_id == DATA_PATH_GROUP &&
                          pkt->hdr.cmd == RX_QUEUES_NOTIFICATION))
                iwl_mvm_rx_queue_notif(mvm, rxb, 0);
+       else if (pkt->hdr.cmd == FRAME_RELEASE)
+               iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
        else
                iwl_mvm_rx_common(mvm, rxb, pkt);
 }
@@ -1184,7 +1246,6 @@ static bool iwl_mvm_disallow_offloading(struct iwl_mvm *mvm,
                                        struct iwl_d0i3_iter_data *iter_data)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct ieee80211_sta *ap_sta;
        struct iwl_mvm_sta *mvmsta;
        u32 available_tids = 0;
        u8 tid;
@@ -1193,11 +1254,10 @@ static bool iwl_mvm_disallow_offloading(struct iwl_mvm *mvm,
                    mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT))
                return false;
 
-       ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
-       if (IS_ERR_OR_NULL(ap_sta))
+       mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
+       if (!mvmsta)
                return false;
 
-       mvmsta = iwl_mvm_sta_from_mac80211(ap_sta);
        spin_lock_bh(&mvmsta->lock);
        for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
                struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
@@ -1608,7 +1668,7 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
        if (unlikely(pkt->hdr.cmd == FRAME_RELEASE))
-               iwl_mvm_rx_frame_release(mvm, rxb, queue);
+               iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
        else if (unlikely(pkt->hdr.cmd == RX_QUEUES_NOTIFICATION &&
                          pkt->hdr.group_id == DATA_PATH_GROUP))
                iwl_mvm_rx_queue_notif(mvm, rxb, queue);