iwlwifi: mvm: add debug print for d0i3 exit indication
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / mvm / ops.c
index 51c2fd0..3f6428c 100644 (file)
@@ -201,13 +201,15 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
 }
 
 struct iwl_rx_handlers {
-       u8 cmd_id;
+       u16 cmd_id;
        bool async;
        void (*fn)(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
 };
 
 #define RX_HANDLER(_cmd_id, _fn, _async)       \
        { .cmd_id = _cmd_id , .fn = _fn , .async = _async }
+#define RX_HANDLER_GRP(_grp, _cmd, _fn, _async)        \
+       { .cmd_id = WIDE_ID(_grp, _cmd), .fn = _fn, .async = _async }
 
 /*
  * Handlers for fw notifications
@@ -259,14 +261,17 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
        RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif,
                   true),
        RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false),
+       RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true),
 
 };
 #undef RX_HANDLER
+#undef RX_HANDLER_GRP
 #define CMD(x) [x] = #x
 
-static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
+static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = {
        CMD(MVM_ALIVE),
        CMD(REPLY_ERROR),
+       CMD(ECHO_CMD),
        CMD(INIT_COMPLETE_NOTIF),
        CMD(PHY_CONTEXT_CMD),
        CMD(MGMT_MCAST_KEY),
@@ -284,8 +289,10 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(PHY_CONFIGURATION_CMD),
        CMD(CALIB_RES_NOTIF_PHY_DB),
        CMD(SET_CALIB_DEFAULT_CMD),
+       CMD(FW_PAGING_BLOCK_CMD),
        CMD(ADD_STA_KEY),
        CMD(ADD_STA),
+       CMD(FW_GET_ITEM_CMD),
        CMD(REMOVE_STA),
        CMD(LQ_CMD),
        CMD(SCAN_OFFLOAD_CONFIG_CMD),
@@ -468,6 +475,8 @@ 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);
        trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
+       trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
+                                              IWL_UCODE_TLV_API_WIDE_CMD_HDR);
 
        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
                trans_cfg.bc_table_dword = true;
@@ -574,6 +583,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        /* rpm starts with a taken ref. only set the appropriate bit here. */
        mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1;
 
+       iwl_mvm_tof_init(mvm);
+
        return op_mode;
 
  out_unregister:
@@ -621,6 +632,8 @@ 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_mvm_tof_clean(mvm);
+
        ieee80211_free_hw(mvm->hw);
 }
 
@@ -693,17 +706,19 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
                if (!cmds_trig->cmds[i].cmd_id)
                        break;
 
-               if (cmds_trig->cmds[i].cmd_id != pkt->hdr.cmd)
+               if (cmds_trig->cmds[i].cmd_id != pkt->hdr.cmd ||
+                   cmds_trig->cmds[i].group_id != pkt->hdr.group_id)
                        continue;
 
                iwl_mvm_fw_dbg_collect_trig(mvm, trig,
-                                           "CMD 0x%02x received",
-                                           pkt->hdr.cmd);
+                                           "CMD 0x%02x.%02x received",
+                                           pkt->hdr.group_id, pkt->hdr.cmd);
                break;
        }
 }
 
 static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
+                               struct napi_struct *napi,
                                struct iwl_rx_cmd_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -711,7 +726,7 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
        u8 i;
 
        if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) {
-               iwl_mvm_rx_rx_mpdu(mvm, rxb);
+               iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
                return;
        }
 
@@ -728,7 +743,7 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
                const struct iwl_rx_handlers *rx_h = &iwl_mvm_rx_handlers[i];
                struct iwl_async_handler_entry *entry;
 
-               if (rx_h->cmd_id != pkt->hdr.cmd)
+               if (rx_h->cmd_id != WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd))
                        continue;
 
                if (!rx_h->async) {
@@ -902,7 +917,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
         * can't recover this since we're already half suspended.
         */
        if (!mvm->restart_fw && fw_error) {
-               iwl_mvm_fw_dbg_collect_desc(mvm, &iwl_mvm_dump_desc_assert, 0);
+               iwl_mvm_fw_dbg_collect_desc(mvm, &iwl_mvm_dump_desc_assert,
+                                           NULL);
        } else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART,
                                    &mvm->status)) {
                struct iwl_mvm_reprobe *reprobe;
@@ -1099,9 +1115,7 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
 
        IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
 
-       /* make sure we have no running tx while configuring the qos */
        set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
-       synchronize_net();
 
        /*
         * iwl_mvm_ref_sync takes a reference before checking the flag.
@@ -1129,12 +1143,20 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
                mvm->d0i3_offloading = false;
        }
 
-       iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, &d0i3_iter_data);
-       ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
-                                  sizeof(wowlan_config_cmd),
-                                  &wowlan_config_cmd);
-       if (ret)
-               return ret;
+       /* make sure we have no running tx while configuring the seqno */
+       synchronize_net();
+
+       /* configure wowlan configuration only if needed */
+       if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) {
+               iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd,
+                                       &d0i3_iter_data);
+
+               ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
+                                          sizeof(wowlan_config_cmd),
+                                          &wowlan_config_cmd);
+               if (ret)
+                       return ret;
+       }
 
        return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD,
                                    flags | CMD_MAKE_TRANS_IDLE,
@@ -1155,15 +1177,25 @@ static void iwl_mvm_exit_d0i3_iterator(void *_data, u8 *mac,
        iwl_mvm_update_d0i3_power_mode(mvm, vif, false, flags);
 }
 
-static void iwl_mvm_d0i3_disconnect_iter(void *data, u8 *mac,
-                                        struct ieee80211_vif *vif)
+struct iwl_mvm_wakeup_reason_iter_data {
+       struct iwl_mvm *mvm;
+       u32 wakeup_reasons;
+};
+
+static void iwl_mvm_d0i3_wakeup_reason_iter(void *_data, u8 *mac,
+                                           struct ieee80211_vif *vif)
 {
-       struct iwl_mvm *mvm = data;
+       struct iwl_mvm_wakeup_reason_iter_data *data = _data;
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
        if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc &&
-           mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
-               iwl_mvm_connection_loss(mvm, vif, "D0i3");
+           data->mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id) {
+               if (data->wakeup_reasons &
+                   IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)
+                       iwl_mvm_connection_loss(data->mvm, vif, "D0i3");
+               else
+                       ieee80211_beacon_loss(vif);
+       }
 }
 
 void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
@@ -1231,7 +1263,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
        };
        struct iwl_wowlan_status *status;
        int ret;
-       u32 disconnection_reasons, wakeup_reasons;
+       u32 handled_reasons, wakeup_reasons = 0;
        __le16 *qos_seq = NULL;
 
        mutex_lock(&mvm->mutex);
@@ -1248,16 +1280,24 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
 
        IWL_DEBUG_RPM(mvm, "wakeup reasons: 0x%x\n", wakeup_reasons);
 
-       disconnection_reasons =
-               IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
-               IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH;
-       if (wakeup_reasons & disconnection_reasons)
+       handled_reasons = IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
+                               IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH;
+       if (wakeup_reasons & handled_reasons) {
+               struct iwl_mvm_wakeup_reason_iter_data data = {
+                       .mvm = mvm,
+                       .wakeup_reasons = wakeup_reasons,
+               };
+
                ieee80211_iterate_active_interfaces(
                        mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-                       iwl_mvm_d0i3_disconnect_iter, mvm);
+                       iwl_mvm_d0i3_wakeup_reason_iter, &data);
+       }
 out:
        iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
 
+       IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n",
+                      wakeup_reasons);
+
        /* qos_seq might point inside resp_pkt, so free it only now */
        if (get_status_cmd.resp_pkt)
                iwl_free_resp(&get_status_cmd);
@@ -1307,17 +1347,6 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
        return _iwl_mvm_exit_d0i3(mvm);
 }
 
-static void iwl_mvm_napi_add(struct iwl_op_mode *op_mode,
-                            struct napi_struct *napi,
-                            struct net_device *napi_dev,
-                            int (*poll)(struct napi_struct *, int),
-                            int weight)
-{
-       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-
-       ieee80211_napi_add(mvm->hw, napi, napi_dev, poll, weight);
-}
-
 static const struct iwl_op_mode_ops iwl_mvm_ops = {
        .start = iwl_op_mode_mvm_start,
        .stop = iwl_op_mode_mvm_stop,
@@ -1331,5 +1360,4 @@ static const struct iwl_op_mode_ops iwl_mvm_ops = {
        .nic_config = iwl_mvm_nic_config,
        .enter_d0i3 = iwl_mvm_enter_d0i3,
        .exit_d0i3 = iwl_mvm_exit_d0i3,
-       .napi_add = iwl_mvm_napi_add,
 };