1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2012-2014, 2018-2020 Intel Corporation 4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH 5 * Copyright (C) 2017 Intel Deutschland GmbH 6 */ 7 #include <linux/jiffies.h> 8 #include <net/mac80211.h> 9 10 #include "fw/notif-wait.h" 11 #include "iwl-trans.h" 12 #include "fw-api.h" 13 #include "time-event.h" 14 #include "mvm.h" 15 #include "iwl-io.h" 16 #include "iwl-prph.h" 17 18 /* 19 * For the high priority TE use a time event type that has similar priority to 20 * the FW's action scan priority. 21 */ 22 #define IWL_MVM_ROC_TE_TYPE_NORMAL TE_P2P_DEVICE_DISCOVERABLE 23 #define IWL_MVM_ROC_TE_TYPE_MGMT_TX TE_P2P_CLIENT_ASSOC 24 25 void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, 26 struct iwl_mvm_time_event_data *te_data) 27 { 28 lockdep_assert_held(&mvm->time_event_lock); 29 30 if (!te_data || !te_data->vif) 31 return; 32 33 list_del(&te_data->list); 34 te_data->running = false; 35 te_data->uid = 0; 36 te_data->id = TE_MAX; 37 te_data->vif = NULL; 38 } 39 40 void iwl_mvm_roc_done_wk(struct work_struct *wk) 41 { 42 struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk); 43 44 /* 45 * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit. 46 * This will cause the TX path to drop offchannel transmissions. 47 * That would also be done by mac80211, but it is racy, in particular 48 * in the case that the time event actually completed in the firmware 49 * (which is handled in iwl_mvm_te_handle_notif). 50 */ 51 clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); 52 clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); 53 54 synchronize_net(); 55 56 /* 57 * Flush the offchannel queue -- this is called when the time 58 * event finishes or is canceled, so that frames queued for it 59 * won't get stuck on the queue and be transmitted in the next 60 * time event. 61 */ 62 63 mutex_lock(&mvm->mutex); 64 if (test_and_clear_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status)) { 65 struct iwl_mvm_vif *mvmvif; 66 67 /* 68 * NB: access to this pointer would be racy, but the flush bit 69 * can only be set when we had a P2P-Device VIF, and we have a 70 * flush of this work in iwl_mvm_prepare_mac_removal() so it's 71 * not really racy. 72 */ 73 74 if (!WARN_ON(!mvm->p2p_device_vif)) { 75 mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif); 76 iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true); 77 } 78 } else { 79 /* do the same in case of hot spot 2.0 */ 80 iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true); 81 /* In newer version of this command an aux station is added only 82 * in cases of dedicated tx queue and need to be removed in end 83 * of use */ 84 if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, 85 ADD_STA, 0) >= 12) 86 iwl_mvm_rm_aux_sta(mvm); 87 } 88 89 mutex_unlock(&mvm->mutex); 90 } 91 92 static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) 93 { 94 /* 95 * Of course, our status bit is just as racy as mac80211, so in 96 * addition, fire off the work struct which will drop all frames 97 * from the hardware queues that made it through the race. First 98 * it will of course synchronize the TX path to make sure that 99 * any *new* TX will be rejected. 100 */ 101 schedule_work(&mvm->roc_done_wk); 102 } 103 104 static void iwl_mvm_csa_noa_start(struct iwl_mvm *mvm) 105 { 106 struct ieee80211_vif *csa_vif; 107 108 rcu_read_lock(); 109 110 csa_vif = rcu_dereference(mvm->csa_vif); 111 if (!csa_vif || !csa_vif->csa_active) 112 goto out_unlock; 113 114 IWL_DEBUG_TE(mvm, "CSA NOA started\n"); 115 116 /* 117 * CSA NoA is started but we still have beacons to 118 * transmit on the current channel. 119 * So we just do nothing here and the switch 120 * will be performed on the last TBTT. 121 */ 122 if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) { 123 IWL_WARN(mvm, "CSA NOA started too early\n"); 124 goto out_unlock; 125 } 126 127 ieee80211_csa_finish(csa_vif); 128 129 rcu_read_unlock(); 130 131 RCU_INIT_POINTER(mvm->csa_vif, NULL); 132 133 return; 134 135 out_unlock: 136 rcu_read_unlock(); 137 } 138 139 static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm, 140 struct ieee80211_vif *vif, 141 const char *errmsg) 142 { 143 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 144 145 if (vif->type != NL80211_IFTYPE_STATION) 146 return false; 147 148 if (!mvmvif->csa_bcn_pending && vif->bss_conf.assoc && 149 vif->bss_conf.dtim_period) 150 return false; 151 if (errmsg) 152 IWL_ERR(mvm, "%s\n", errmsg); 153 154 iwl_mvm_connection_loss(mvm, vif, errmsg); 155 return true; 156 } 157 158 static void 159 iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm, 160 struct iwl_mvm_time_event_data *te_data, 161 struct iwl_time_event_notif *notif) 162 { 163 struct ieee80211_vif *vif = te_data->vif; 164 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 165 166 if (!notif->status) 167 IWL_DEBUG_TE(mvm, "CSA time event failed to start\n"); 168 169 switch (te_data->vif->type) { 170 case NL80211_IFTYPE_AP: 171 if (!notif->status) 172 mvmvif->csa_failed = true; 173 iwl_mvm_csa_noa_start(mvm); 174 break; 175 case NL80211_IFTYPE_STATION: 176 if (!notif->status) { 177 iwl_mvm_connection_loss(mvm, vif, 178 "CSA TE failed to start"); 179 break; 180 } 181 iwl_mvm_csa_client_absent(mvm, te_data->vif); 182 cancel_delayed_work(&mvmvif->csa_work); 183 ieee80211_chswitch_done(te_data->vif, true); 184 break; 185 default: 186 /* should never happen */ 187 WARN_ON_ONCE(1); 188 break; 189 } 190 191 /* we don't need it anymore */ 192 iwl_mvm_te_clear_data(mvm, te_data); 193 } 194 195 static void iwl_mvm_te_check_trigger(struct iwl_mvm *mvm, 196 struct iwl_time_event_notif *notif, 197 struct iwl_mvm_time_event_data *te_data) 198 { 199 struct iwl_fw_dbg_trigger_tlv *trig; 200 struct iwl_fw_dbg_trigger_time_event *te_trig; 201 int i; 202 203 trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, 204 ieee80211_vif_to_wdev(te_data->vif), 205 FW_DBG_TRIGGER_TIME_EVENT); 206 if (!trig) 207 return; 208 209 te_trig = (void *)trig->data; 210 211 for (i = 0; i < ARRAY_SIZE(te_trig->time_events); i++) { 212 u32 trig_te_id = le32_to_cpu(te_trig->time_events[i].id); 213 u32 trig_action_bitmap = 214 le32_to_cpu(te_trig->time_events[i].action_bitmap); 215 u32 trig_status_bitmap = 216 le32_to_cpu(te_trig->time_events[i].status_bitmap); 217 218 if (trig_te_id != te_data->id || 219 !(trig_action_bitmap & le32_to_cpu(notif->action)) || 220 !(trig_status_bitmap & BIT(le32_to_cpu(notif->status)))) 221 continue; 222 223 iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, 224 "Time event %d Action 0x%x received status: %d", 225 te_data->id, 226 le32_to_cpu(notif->action), 227 le32_to_cpu(notif->status)); 228 break; 229 } 230 } 231 232 /* 233 * Handles a FW notification for an event that is known to the driver. 234 * 235 * @mvm: the mvm component 236 * @te_data: the time event data 237 * @notif: the notification data corresponding the time event data. 238 */ 239 static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, 240 struct iwl_mvm_time_event_data *te_data, 241 struct iwl_time_event_notif *notif) 242 { 243 lockdep_assert_held(&mvm->time_event_lock); 244 245 IWL_DEBUG_TE(mvm, "Handle time event notif - UID = 0x%x action %d\n", 246 le32_to_cpu(notif->unique_id), 247 le32_to_cpu(notif->action)); 248 249 iwl_mvm_te_check_trigger(mvm, notif, te_data); 250 251 /* 252 * The FW sends the start/end time event notifications even for events 253 * that it fails to schedule. This is indicated in the status field of 254 * the notification. This happens in cases that the scheduler cannot 255 * find a schedule that can handle the event (for example requesting a 256 * P2P Device discoveribility, while there are other higher priority 257 * events in the system). 258 */ 259 if (!le32_to_cpu(notif->status)) { 260 const char *msg; 261 262 if (notif->action & cpu_to_le32(TE_V2_NOTIF_HOST_EVENT_START)) 263 msg = "Time Event start notification failure"; 264 else 265 msg = "Time Event end notification failure"; 266 267 IWL_DEBUG_TE(mvm, "%s\n", msg); 268 269 if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, msg)) { 270 iwl_mvm_te_clear_data(mvm, te_data); 271 return; 272 } 273 } 274 275 if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_END) { 276 IWL_DEBUG_TE(mvm, 277 "TE ended - current time %lu, estimated end %lu\n", 278 jiffies, te_data->end_jiffies); 279 280 switch (te_data->vif->type) { 281 case NL80211_IFTYPE_P2P_DEVICE: 282 ieee80211_remain_on_channel_expired(mvm->hw); 283 set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); 284 iwl_mvm_roc_finished(mvm); 285 break; 286 case NL80211_IFTYPE_STATION: 287 /* 288 * By now, we should have finished association 289 * and know the dtim period. 290 */ 291 iwl_mvm_te_check_disconnect(mvm, te_data->vif, 292 "No beacon heard and the time event is over already..."); 293 break; 294 default: 295 break; 296 } 297 298 iwl_mvm_te_clear_data(mvm, te_data); 299 } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { 300 te_data->running = true; 301 te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration); 302 303 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { 304 set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); 305 ieee80211_ready_on_channel(mvm->hw); 306 } else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) { 307 iwl_mvm_te_handle_notify_csa(mvm, te_data, notif); 308 } 309 } else { 310 IWL_WARN(mvm, "Got TE with unknown action\n"); 311 } 312 } 313 314 /* 315 * Handle A Aux ROC time event 316 */ 317 static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm, 318 struct iwl_time_event_notif *notif) 319 { 320 struct iwl_mvm_time_event_data *te_data, *tmp; 321 bool aux_roc_te = false; 322 323 list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) { 324 if (le32_to_cpu(notif->unique_id) == te_data->uid) { 325 aux_roc_te = true; 326 break; 327 } 328 } 329 if (!aux_roc_te) /* Not a Aux ROC time event */ 330 return -EINVAL; 331 332 iwl_mvm_te_check_trigger(mvm, notif, te_data); 333 334 IWL_DEBUG_TE(mvm, 335 "Aux ROC time event notification - UID = 0x%x action %d (error = %d)\n", 336 le32_to_cpu(notif->unique_id), 337 le32_to_cpu(notif->action), le32_to_cpu(notif->status)); 338 339 if (!le32_to_cpu(notif->status) || 340 le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) { 341 /* End TE, notify mac80211 */ 342 ieee80211_remain_on_channel_expired(mvm->hw); 343 iwl_mvm_roc_finished(mvm); /* flush aux queue */ 344 list_del(&te_data->list); /* remove from list */ 345 te_data->running = false; 346 te_data->vif = NULL; 347 te_data->uid = 0; 348 te_data->id = TE_MAX; 349 } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) { 350 set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); 351 te_data->running = true; 352 ieee80211_ready_on_channel(mvm->hw); /* Start TE */ 353 } else { 354 IWL_DEBUG_TE(mvm, 355 "ERROR: Unknown Aux ROC Time Event (action = %d)\n", 356 le32_to_cpu(notif->action)); 357 return -EINVAL; 358 } 359 360 return 0; 361 } 362 363 /* 364 * The Rx handler for time event notifications 365 */ 366 void iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, 367 struct iwl_rx_cmd_buffer *rxb) 368 { 369 struct iwl_rx_packet *pkt = rxb_addr(rxb); 370 struct iwl_time_event_notif *notif = (void *)pkt->data; 371 struct iwl_mvm_time_event_data *te_data, *tmp; 372 373 IWL_DEBUG_TE(mvm, "Time event notification - UID = 0x%x action %d\n", 374 le32_to_cpu(notif->unique_id), 375 le32_to_cpu(notif->action)); 376 377 spin_lock_bh(&mvm->time_event_lock); 378 /* This time event is triggered for Aux ROC request */ 379 if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif)) 380 goto unlock; 381 382 list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) { 383 if (le32_to_cpu(notif->unique_id) == te_data->uid) 384 iwl_mvm_te_handle_notif(mvm, te_data, notif); 385 } 386 unlock: 387 spin_unlock_bh(&mvm->time_event_lock); 388 } 389 390 static bool iwl_mvm_te_notif(struct iwl_notif_wait_data *notif_wait, 391 struct iwl_rx_packet *pkt, void *data) 392 { 393 struct iwl_mvm *mvm = 394 container_of(notif_wait, struct iwl_mvm, notif_wait); 395 struct iwl_mvm_time_event_data *te_data = data; 396 struct iwl_time_event_notif *resp; 397 int resp_len = iwl_rx_packet_payload_len(pkt); 398 399 if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_NOTIFICATION)) 400 return true; 401 402 if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { 403 IWL_ERR(mvm, "Invalid TIME_EVENT_NOTIFICATION response\n"); 404 return true; 405 } 406 407 resp = (void *)pkt->data; 408 409 /* te_data->uid is already set in the TIME_EVENT_CMD response */ 410 if (le32_to_cpu(resp->unique_id) != te_data->uid) 411 return false; 412 413 IWL_DEBUG_TE(mvm, "TIME_EVENT_NOTIFICATION response - UID = 0x%x\n", 414 te_data->uid); 415 if (!resp->status) 416 IWL_ERR(mvm, 417 "TIME_EVENT_NOTIFICATION received but not executed\n"); 418 419 return true; 420 } 421 422 static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, 423 struct iwl_rx_packet *pkt, void *data) 424 { 425 struct iwl_mvm *mvm = 426 container_of(notif_wait, struct iwl_mvm, notif_wait); 427 struct iwl_mvm_time_event_data *te_data = data; 428 struct iwl_time_event_resp *resp; 429 int resp_len = iwl_rx_packet_payload_len(pkt); 430 431 if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_CMD)) 432 return true; 433 434 if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { 435 IWL_ERR(mvm, "Invalid TIME_EVENT_CMD response\n"); 436 return true; 437 } 438 439 resp = (void *)pkt->data; 440 441 /* we should never get a response to another TIME_EVENT_CMD here */ 442 if (WARN_ON_ONCE(le32_to_cpu(resp->id) != te_data->id)) 443 return false; 444 445 te_data->uid = le32_to_cpu(resp->unique_id); 446 IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n", 447 te_data->uid); 448 return true; 449 } 450 451 static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, 452 struct ieee80211_vif *vif, 453 struct iwl_mvm_time_event_data *te_data, 454 struct iwl_time_event_cmd *te_cmd) 455 { 456 static const u16 time_event_response[] = { TIME_EVENT_CMD }; 457 struct iwl_notification_wait wait_time_event; 458 int ret; 459 460 lockdep_assert_held(&mvm->mutex); 461 462 IWL_DEBUG_TE(mvm, "Add new TE, duration %d TU\n", 463 le32_to_cpu(te_cmd->duration)); 464 465 spin_lock_bh(&mvm->time_event_lock); 466 if (WARN_ON(te_data->id != TE_MAX)) { 467 spin_unlock_bh(&mvm->time_event_lock); 468 return -EIO; 469 } 470 te_data->vif = vif; 471 te_data->duration = le32_to_cpu(te_cmd->duration); 472 te_data->id = le32_to_cpu(te_cmd->id); 473 list_add_tail(&te_data->list, &mvm->time_event_list); 474 spin_unlock_bh(&mvm->time_event_lock); 475 476 /* 477 * Use a notification wait, which really just processes the 478 * command response and doesn't wait for anything, in order 479 * to be able to process the response and get the UID inside 480 * the RX path. Using CMD_WANT_SKB doesn't work because it 481 * stores the buffer and then wakes up this thread, by which 482 * time another notification (that the time event started) 483 * might already be processed unsuccessfully. 484 */ 485 iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event, 486 time_event_response, 487 ARRAY_SIZE(time_event_response), 488 iwl_mvm_time_event_response, te_data); 489 490 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, 491 sizeof(*te_cmd), te_cmd); 492 if (ret) { 493 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); 494 iwl_remove_notification(&mvm->notif_wait, &wait_time_event); 495 goto out_clear_te; 496 } 497 498 /* No need to wait for anything, so just pass 1 (0 isn't valid) */ 499 ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1); 500 /* should never fail */ 501 WARN_ON_ONCE(ret); 502 503 if (ret) { 504 out_clear_te: 505 spin_lock_bh(&mvm->time_event_lock); 506 iwl_mvm_te_clear_data(mvm, te_data); 507 spin_unlock_bh(&mvm->time_event_lock); 508 } 509 return ret; 510 } 511 512 void iwl_mvm_protect_session(struct iwl_mvm *mvm, 513 struct ieee80211_vif *vif, 514 u32 duration, u32 min_duration, 515 u32 max_delay, bool wait_for_notif) 516 { 517 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 518 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 519 const u16 te_notif_response[] = { TIME_EVENT_NOTIFICATION }; 520 struct iwl_notification_wait wait_te_notif; 521 struct iwl_time_event_cmd time_cmd = {}; 522 523 lockdep_assert_held(&mvm->mutex); 524 525 if (te_data->running && 526 time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) { 527 IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n", 528 jiffies_to_msecs(te_data->end_jiffies - jiffies)); 529 return; 530 } 531 532 if (te_data->running) { 533 IWL_DEBUG_TE(mvm, "extend 0x%x: only %u ms left\n", 534 te_data->uid, 535 jiffies_to_msecs(te_data->end_jiffies - jiffies)); 536 /* 537 * we don't have enough time 538 * cancel the current TE and issue a new one 539 * Of course it would be better to remove the old one only 540 * when the new one is added, but we don't care if we are off 541 * channel for a bit. All we need to do, is not to return 542 * before we actually begin to be on the channel. 543 */ 544 iwl_mvm_stop_session_protection(mvm, vif); 545 } 546 547 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); 548 time_cmd.id_and_color = 549 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 550 time_cmd.id = cpu_to_le32(TE_BSS_STA_AGGRESSIVE_ASSOC); 551 552 time_cmd.apply_time = cpu_to_le32(0); 553 554 time_cmd.max_frags = TE_V2_FRAG_NONE; 555 time_cmd.max_delay = cpu_to_le32(max_delay); 556 /* TODO: why do we need to interval = bi if it is not periodic? */ 557 time_cmd.interval = cpu_to_le32(1); 558 time_cmd.duration = cpu_to_le32(duration); 559 time_cmd.repeat = 1; 560 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | 561 TE_V2_NOTIF_HOST_EVENT_END | 562 TE_V2_START_IMMEDIATELY); 563 564 if (!wait_for_notif) { 565 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 566 return; 567 } 568 569 /* 570 * Create notification_wait for the TIME_EVENT_NOTIFICATION to use 571 * right after we send the time event 572 */ 573 iwl_init_notification_wait(&mvm->notif_wait, &wait_te_notif, 574 te_notif_response, 575 ARRAY_SIZE(te_notif_response), 576 iwl_mvm_te_notif, te_data); 577 578 /* If TE was sent OK - wait for the notification that started */ 579 if (iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd)) { 580 IWL_ERR(mvm, "Failed to add TE to protect session\n"); 581 iwl_remove_notification(&mvm->notif_wait, &wait_te_notif); 582 } else if (iwl_wait_notification(&mvm->notif_wait, &wait_te_notif, 583 TU_TO_JIFFIES(max_delay))) { 584 IWL_ERR(mvm, "Failed to protect session until TE\n"); 585 } 586 } 587 588 static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm, 589 struct iwl_mvm_vif *mvmvif) 590 { 591 struct iwl_mvm_session_prot_cmd cmd = { 592 .id_and_color = 593 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, 594 mvmvif->color)), 595 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), 596 .conf_id = cpu_to_le32(mvmvif->time_event_data.id), 597 }; 598 int ret; 599 600 ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, 601 MAC_CONF_GROUP, 0), 602 0, sizeof(cmd), &cmd); 603 if (ret) 604 IWL_ERR(mvm, 605 "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret); 606 } 607 608 static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, 609 struct iwl_mvm_time_event_data *te_data, 610 u32 *uid) 611 { 612 u32 id; 613 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif); 614 615 /* 616 * It is possible that by the time we got to this point the time 617 * event was already removed. 618 */ 619 spin_lock_bh(&mvm->time_event_lock); 620 621 /* Save time event uid before clearing its data */ 622 *uid = te_data->uid; 623 id = te_data->id; 624 625 /* 626 * The clear_data function handles time events that were already removed 627 */ 628 iwl_mvm_te_clear_data(mvm, te_data); 629 spin_unlock_bh(&mvm->time_event_lock); 630 631 /* When session protection is supported, the te_data->id field 632 * is reused to save session protection's configuration. 633 */ 634 if (fw_has_capa(&mvm->fw->ucode_capa, 635 IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { 636 if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) { 637 /* Session protection is still ongoing. Cancel it */ 638 iwl_mvm_cancel_session_protection(mvm, mvmvif); 639 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { 640 set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); 641 iwl_mvm_roc_finished(mvm); 642 } 643 } 644 return false; 645 } else { 646 /* It is possible that by the time we try to remove it, the 647 * time event has already ended and removed. In such a case 648 * there is no need to send a removal command. 649 */ 650 if (id == TE_MAX) { 651 IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid); 652 return false; 653 } 654 } 655 656 return true; 657 } 658 659 /* 660 * Explicit request to remove a aux roc time event. The removal of a time 661 * event needs to be synchronized with the flow of a time event's end 662 * notification, which also removes the time event from the op mode 663 * data structures. 664 */ 665 static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm, 666 struct iwl_mvm_vif *mvmvif, 667 struct iwl_mvm_time_event_data *te_data) 668 { 669 struct iwl_hs20_roc_req aux_cmd = {}; 670 u16 len = sizeof(aux_cmd) - iwl_mvm_chan_info_padding(mvm); 671 672 u32 uid; 673 int ret; 674 675 if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid)) 676 return; 677 678 aux_cmd.event_unique_id = cpu_to_le32(uid); 679 aux_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE); 680 aux_cmd.id_and_color = 681 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 682 IWL_DEBUG_TE(mvm, "Removing BSS AUX ROC TE 0x%x\n", 683 le32_to_cpu(aux_cmd.event_unique_id)); 684 ret = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, 685 len, &aux_cmd); 686 687 if (WARN_ON(ret)) 688 return; 689 } 690 691 /* 692 * Explicit request to remove a time event. The removal of a time event needs to 693 * be synchronized with the flow of a time event's end notification, which also 694 * removes the time event from the op mode data structures. 695 */ 696 void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, 697 struct iwl_mvm_vif *mvmvif, 698 struct iwl_mvm_time_event_data *te_data) 699 { 700 struct iwl_time_event_cmd time_cmd = {}; 701 u32 uid; 702 int ret; 703 704 if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid)) 705 return; 706 707 /* When we remove a TE, the UID is to be set in the id field */ 708 time_cmd.id = cpu_to_le32(uid); 709 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE); 710 time_cmd.id_and_color = 711 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 712 713 IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); 714 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, 715 sizeof(time_cmd), &time_cmd); 716 if (WARN_ON(ret)) 717 return; 718 } 719 720 /* 721 * When the firmware supports the session protection API, 722 * this is not needed since it'll automatically remove the 723 * session protection after association + beacon reception. 724 */ 725 void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm, 726 struct ieee80211_vif *vif) 727 { 728 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 729 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 730 u32 id; 731 732 lockdep_assert_held(&mvm->mutex); 733 734 spin_lock_bh(&mvm->time_event_lock); 735 id = te_data->id; 736 spin_unlock_bh(&mvm->time_event_lock); 737 738 if (id != TE_BSS_STA_AGGRESSIVE_ASSOC) { 739 IWL_DEBUG_TE(mvm, 740 "don't remove TE with id=%u (not session protection)\n", 741 id); 742 return; 743 } 744 745 iwl_mvm_remove_time_event(mvm, mvmvif, te_data); 746 } 747 748 void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, 749 struct iwl_rx_cmd_buffer *rxb) 750 { 751 struct iwl_rx_packet *pkt = rxb_addr(rxb); 752 struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data; 753 struct ieee80211_vif *vif; 754 struct iwl_mvm_vif *mvmvif; 755 756 rcu_read_lock(); 757 vif = iwl_mvm_rcu_dereference_vif_id(mvm, le32_to_cpu(notif->mac_id), 758 true); 759 760 if (!vif) 761 goto out_unlock; 762 763 mvmvif = iwl_mvm_vif_from_mac80211(vif); 764 765 /* The vif is not a P2P_DEVICE, maintain its time_event_data */ 766 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { 767 struct iwl_mvm_time_event_data *te_data = 768 &mvmvif->time_event_data; 769 770 if (!le32_to_cpu(notif->status)) { 771 iwl_mvm_te_check_disconnect(mvm, vif, 772 "Session protection failure"); 773 spin_lock_bh(&mvm->time_event_lock); 774 iwl_mvm_te_clear_data(mvm, te_data); 775 spin_unlock_bh(&mvm->time_event_lock); 776 } 777 778 if (le32_to_cpu(notif->start)) { 779 spin_lock_bh(&mvm->time_event_lock); 780 te_data->running = le32_to_cpu(notif->start); 781 te_data->end_jiffies = 782 TU_TO_EXP_TIME(te_data->duration); 783 spin_unlock_bh(&mvm->time_event_lock); 784 } else { 785 /* 786 * By now, we should have finished association 787 * and know the dtim period. 788 */ 789 iwl_mvm_te_check_disconnect(mvm, vif, 790 "No beacon heard and the session protection is over already..."); 791 spin_lock_bh(&mvm->time_event_lock); 792 iwl_mvm_te_clear_data(mvm, te_data); 793 spin_unlock_bh(&mvm->time_event_lock); 794 } 795 796 goto out_unlock; 797 } 798 799 if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) { 800 /* End TE, notify mac80211 */ 801 mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID; 802 ieee80211_remain_on_channel_expired(mvm->hw); 803 set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); 804 iwl_mvm_roc_finished(mvm); 805 } else if (le32_to_cpu(notif->start)) { 806 if (WARN_ON(mvmvif->time_event_data.id != 807 le32_to_cpu(notif->conf_id))) 808 goto out_unlock; 809 set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); 810 ieee80211_ready_on_channel(mvm->hw); /* Start TE */ 811 } 812 813 out_unlock: 814 rcu_read_unlock(); 815 } 816 817 static int 818 iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm, 819 struct ieee80211_vif *vif, 820 int duration, 821 enum ieee80211_roc_type type) 822 { 823 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 824 struct iwl_mvm_session_prot_cmd cmd = { 825 .id_and_color = 826 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, 827 mvmvif->color)), 828 .action = cpu_to_le32(FW_CTXT_ACTION_ADD), 829 .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)), 830 }; 831 832 lockdep_assert_held(&mvm->mutex); 833 834 /* The time_event_data.id field is reused to save session 835 * protection's configuration. 836 */ 837 switch (type) { 838 case IEEE80211_ROC_TYPE_NORMAL: 839 mvmvif->time_event_data.id = 840 SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV; 841 break; 842 case IEEE80211_ROC_TYPE_MGMT_TX: 843 mvmvif->time_event_data.id = 844 SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION; 845 break; 846 default: 847 WARN_ONCE(1, "Got an invalid ROC type\n"); 848 return -EINVAL; 849 } 850 851 cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); 852 return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, 853 MAC_CONF_GROUP, 0), 854 0, sizeof(cmd), &cmd); 855 } 856 857 int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 858 int duration, enum ieee80211_roc_type type) 859 { 860 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 861 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 862 struct iwl_time_event_cmd time_cmd = {}; 863 864 lockdep_assert_held(&mvm->mutex); 865 if (te_data->running) { 866 IWL_WARN(mvm, "P2P_DEVICE remain on channel already running\n"); 867 return -EBUSY; 868 } 869 870 if (fw_has_capa(&mvm->fw->ucode_capa, 871 IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) 872 return iwl_mvm_start_p2p_roc_session_protection(mvm, vif, 873 duration, 874 type); 875 876 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); 877 time_cmd.id_and_color = 878 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 879 880 switch (type) { 881 case IEEE80211_ROC_TYPE_NORMAL: 882 time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_NORMAL); 883 break; 884 case IEEE80211_ROC_TYPE_MGMT_TX: 885 time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_MGMT_TX); 886 break; 887 default: 888 WARN_ONCE(1, "Got an invalid ROC type\n"); 889 return -EINVAL; 890 } 891 892 time_cmd.apply_time = cpu_to_le32(0); 893 time_cmd.interval = cpu_to_le32(1); 894 895 /* 896 * The P2P Device TEs can have lower priority than other events 897 * that are being scheduled by the driver/fw, and thus it might not be 898 * scheduled. To improve the chances of it being scheduled, allow them 899 * to be fragmented, and in addition allow them to be delayed. 900 */ 901 time_cmd.max_frags = min(MSEC_TO_TU(duration)/50, TE_V2_FRAG_ENDLESS); 902 time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); 903 time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); 904 time_cmd.repeat = 1; 905 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | 906 TE_V2_NOTIF_HOST_EVENT_END | 907 TE_V2_START_IMMEDIATELY); 908 909 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 910 } 911 912 static struct iwl_mvm_time_event_data *iwl_mvm_get_roc_te(struct iwl_mvm *mvm) 913 { 914 struct iwl_mvm_time_event_data *te_data; 915 916 lockdep_assert_held(&mvm->mutex); 917 918 spin_lock_bh(&mvm->time_event_lock); 919 920 /* 921 * Iterate over the list of time events and find the time event that is 922 * associated with a P2P_DEVICE interface. 923 * This assumes that a P2P_DEVICE interface can have only a single time 924 * event at any given time and this time event coresponds to a ROC 925 * request 926 */ 927 list_for_each_entry(te_data, &mvm->time_event_list, list) { 928 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) 929 goto out; 930 } 931 932 /* There can only be at most one AUX ROC time event, we just use the 933 * list to simplify/unify code. Remove it if it exists. 934 */ 935 te_data = list_first_entry_or_null(&mvm->aux_roc_te_list, 936 struct iwl_mvm_time_event_data, 937 list); 938 out: 939 spin_unlock_bh(&mvm->time_event_lock); 940 return te_data; 941 } 942 943 void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm) 944 { 945 struct iwl_mvm_time_event_data *te_data; 946 u32 uid; 947 948 te_data = iwl_mvm_get_roc_te(mvm); 949 if (te_data) 950 __iwl_mvm_remove_time_event(mvm, te_data, &uid); 951 } 952 953 void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 954 { 955 struct iwl_mvm_vif *mvmvif; 956 struct iwl_mvm_time_event_data *te_data; 957 958 if (fw_has_capa(&mvm->fw->ucode_capa, 959 IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { 960 mvmvif = iwl_mvm_vif_from_mac80211(vif); 961 962 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { 963 iwl_mvm_cancel_session_protection(mvm, mvmvif); 964 set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); 965 } else { 966 iwl_mvm_remove_aux_roc_te(mvm, mvmvif, 967 &mvmvif->time_event_data); 968 } 969 970 iwl_mvm_roc_finished(mvm); 971 972 return; 973 } 974 975 te_data = iwl_mvm_get_roc_te(mvm); 976 if (!te_data) { 977 IWL_WARN(mvm, "No remain on channel event\n"); 978 return; 979 } 980 981 mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif); 982 983 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { 984 iwl_mvm_remove_time_event(mvm, mvmvif, te_data); 985 set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); 986 } else { 987 iwl_mvm_remove_aux_roc_te(mvm, mvmvif, te_data); 988 } 989 990 iwl_mvm_roc_finished(mvm); 991 } 992 993 void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm, 994 struct ieee80211_vif *vif) 995 { 996 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 997 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 998 u32 id; 999 1000 lockdep_assert_held(&mvm->mutex); 1001 1002 spin_lock_bh(&mvm->time_event_lock); 1003 id = te_data->id; 1004 spin_unlock_bh(&mvm->time_event_lock); 1005 1006 if (id != TE_CHANNEL_SWITCH_PERIOD) 1007 return; 1008 1009 iwl_mvm_remove_time_event(mvm, mvmvif, te_data); 1010 } 1011 1012 int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm, 1013 struct ieee80211_vif *vif, 1014 u32 duration, u32 apply_time) 1015 { 1016 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1017 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 1018 struct iwl_time_event_cmd time_cmd = {}; 1019 1020 lockdep_assert_held(&mvm->mutex); 1021 1022 if (te_data->running) { 1023 u32 id; 1024 1025 spin_lock_bh(&mvm->time_event_lock); 1026 id = te_data->id; 1027 spin_unlock_bh(&mvm->time_event_lock); 1028 1029 if (id == TE_CHANNEL_SWITCH_PERIOD) { 1030 IWL_DEBUG_TE(mvm, "CS period is already scheduled\n"); 1031 return -EBUSY; 1032 } 1033 1034 /* 1035 * Remove the session protection time event to allow the 1036 * channel switch. If we got here, we just heard a beacon so 1037 * the session protection is not needed anymore anyway. 1038 */ 1039 iwl_mvm_remove_time_event(mvm, mvmvif, te_data); 1040 } 1041 1042 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); 1043 time_cmd.id_and_color = 1044 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 1045 time_cmd.id = cpu_to_le32(TE_CHANNEL_SWITCH_PERIOD); 1046 time_cmd.apply_time = cpu_to_le32(apply_time); 1047 time_cmd.max_frags = TE_V2_FRAG_NONE; 1048 time_cmd.duration = cpu_to_le32(duration); 1049 time_cmd.repeat = 1; 1050 time_cmd.interval = cpu_to_le32(1); 1051 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | 1052 TE_V2_ABSENCE); 1053 if (!apply_time) 1054 time_cmd.policy |= cpu_to_le16(TE_V2_START_IMMEDIATELY); 1055 1056 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 1057 } 1058 1059 static bool iwl_mvm_session_prot_notif(struct iwl_notif_wait_data *notif_wait, 1060 struct iwl_rx_packet *pkt, void *data) 1061 { 1062 struct iwl_mvm *mvm = 1063 container_of(notif_wait, struct iwl_mvm, notif_wait); 1064 struct iwl_mvm_session_prot_notif *resp; 1065 int resp_len = iwl_rx_packet_payload_len(pkt); 1066 1067 if (WARN_ON(pkt->hdr.cmd != SESSION_PROTECTION_NOTIF || 1068 pkt->hdr.group_id != MAC_CONF_GROUP)) 1069 return true; 1070 1071 if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { 1072 IWL_ERR(mvm, "Invalid SESSION_PROTECTION_NOTIF response\n"); 1073 return true; 1074 } 1075 1076 resp = (void *)pkt->data; 1077 1078 if (!resp->status) 1079 IWL_ERR(mvm, 1080 "TIME_EVENT_NOTIFICATION received but not executed\n"); 1081 1082 return true; 1083 } 1084 1085 void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm, 1086 struct ieee80211_vif *vif, 1087 u32 duration, u32 min_duration, 1088 bool wait_for_notif) 1089 { 1090 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1091 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 1092 const u16 notif[] = { iwl_cmd_id(SESSION_PROTECTION_NOTIF, 1093 MAC_CONF_GROUP, 0) }; 1094 struct iwl_notification_wait wait_notif; 1095 struct iwl_mvm_session_prot_cmd cmd = { 1096 .id_and_color = 1097 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, 1098 mvmvif->color)), 1099 .action = cpu_to_le32(FW_CTXT_ACTION_ADD), 1100 .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)), 1101 }; 1102 1103 /* The time_event_data.id field is reused to save session 1104 * protection's configuration. 1105 */ 1106 mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC; 1107 cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); 1108 1109 lockdep_assert_held(&mvm->mutex); 1110 1111 spin_lock_bh(&mvm->time_event_lock); 1112 if (te_data->running && 1113 time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) { 1114 IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n", 1115 jiffies_to_msecs(te_data->end_jiffies - jiffies)); 1116 spin_unlock_bh(&mvm->time_event_lock); 1117 1118 return; 1119 } 1120 1121 iwl_mvm_te_clear_data(mvm, te_data); 1122 te_data->duration = le32_to_cpu(cmd.duration_tu); 1123 spin_unlock_bh(&mvm->time_event_lock); 1124 1125 IWL_DEBUG_TE(mvm, "Add new session protection, duration %d TU\n", 1126 le32_to_cpu(cmd.duration_tu)); 1127 1128 if (!wait_for_notif) { 1129 if (iwl_mvm_send_cmd_pdu(mvm, 1130 iwl_cmd_id(SESSION_PROTECTION_CMD, 1131 MAC_CONF_GROUP, 0), 1132 0, sizeof(cmd), &cmd)) { 1133 IWL_ERR(mvm, 1134 "Couldn't send the SESSION_PROTECTION_CMD\n"); 1135 spin_lock_bh(&mvm->time_event_lock); 1136 iwl_mvm_te_clear_data(mvm, te_data); 1137 spin_unlock_bh(&mvm->time_event_lock); 1138 } 1139 1140 return; 1141 } 1142 1143 iwl_init_notification_wait(&mvm->notif_wait, &wait_notif, 1144 notif, ARRAY_SIZE(notif), 1145 iwl_mvm_session_prot_notif, NULL); 1146 1147 if (iwl_mvm_send_cmd_pdu(mvm, 1148 iwl_cmd_id(SESSION_PROTECTION_CMD, 1149 MAC_CONF_GROUP, 0), 1150 0, sizeof(cmd), &cmd)) { 1151 IWL_ERR(mvm, 1152 "Couldn't send the SESSION_PROTECTION_CMD\n"); 1153 iwl_remove_notification(&mvm->notif_wait, &wait_notif); 1154 } else if (iwl_wait_notification(&mvm->notif_wait, &wait_notif, 1155 TU_TO_JIFFIES(100))) { 1156 IWL_ERR(mvm, 1157 "Failed to protect session until session protection\n"); 1158 } 1159 } 1160