aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/time-event.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-29 09:28:17 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-12 10:52:26 -0500
commitffdf968d878f85620c1d4685b9543f894ef56db0 (patch)
tree057aa7c53ddadd956f7af38a59ca7dae20744f24 /drivers/net/wireless/iwlwifi/mvm/time-event.c
parent210a544e78c7ce4e5aa5ec199eeb807b0f03b5b2 (diff)
iwlwifi: mvm: don't wait for session protection to start
Now that mac80211 no longer starts the auth/assoc timeouts when it transmits the frame, but only when the frame status arrives, we no longer need to wait for the session protection time event to start, we can schedule it and enqueue the auth/assoc frame right away. This reduces the amount of time we block mac80211's workqueue. Also, since now we no longer need different behavior for session protection and P2P time events, refactor the code to have just a common implementation. Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c215
1 files changed, 73 insertions, 142 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 194bfb7a7d7f..c09b71f23759 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -230,57 +230,86 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
230 return 0; 230 return 0;
231} 231}
232 232
233static bool iwl_mvm_time_event_notif(struct iwl_notif_wait_data *notif_wait, 233static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
234 struct iwl_rx_packet *pkt, void *data) 234 struct iwl_rx_packet *pkt, void *data)
235{ 235{
236 struct iwl_mvm *mvm = 236 struct iwl_mvm *mvm =
237 container_of(notif_wait, struct iwl_mvm, notif_wait); 237 container_of(notif_wait, struct iwl_mvm, notif_wait);
238 struct iwl_mvm_time_event_data *te_data = data; 238 struct iwl_mvm_time_event_data *te_data = data;
239 struct ieee80211_vif *vif = te_data->vif;
240 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
241 struct iwl_time_event_notif *notif;
242 struct iwl_time_event_resp *resp; 239 struct iwl_time_event_resp *resp;
240 int resp_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
243 241
244 u32 mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); 242 if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_CMD))
243 return true;
245 244
246 /* until we do something else */ 245 if (WARN_ON_ONCE(resp_len != sizeof(pkt->hdr) + sizeof(*resp))) {
247 WARN_ON(te_data->id != TE_BSS_STA_AGGRESSIVE_ASSOC); 246 IWL_ERR(mvm, "Invalid TIME_EVENT_CMD response\n");
247 return true;
248 }
248 249
249 switch (pkt->hdr.cmd) { 250 resp = (void *)pkt->data;
250 case TIME_EVENT_CMD: 251 te_data->uid = le32_to_cpu(resp->unique_id);
251 resp = (void *)pkt->data; 252 IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
252 /* TODO: I can't check that since the fw is buggy - it doesn't 253 te_data->uid);
253 * put the right values when we remove a TE. We can be here 254 return true;
254 * when we remove a TE because the remove TE command is sent in 255}
255 * ASYNC...
256 * WARN_ON(mac_id_n_color != le32_to_cpu(resp->id_and_color));
257 */
258 te_data->uid = le32_to_cpu(resp->unique_id);
259 IWL_DEBUG_TE(mvm, "Got response - UID = 0x%x\n", te_data->uid);
260 return false;
261
262 case TIME_EVENT_NOTIFICATION:
263 notif = (void *)pkt->data;
264 WARN_ON(le32_to_cpu(notif->status) != 1);
265 WARN_ON(mac_id_n_color != le32_to_cpu(notif->id_and_color));
266 /* check if this is our Time Event that is starting */
267 if (le32_to_cpu(notif->unique_id) != te_data->uid)
268 return false;
269 IWL_DEBUG_TE(mvm, "Event %d is starting - time is %d\n",
270 te_data->uid, le32_to_cpu(notif->timestamp));
271
272 WARN_ONCE(!le32_to_cpu(notif->status),
273 "Failed to schedule protected session TE\n");
274 256
275 te_data->running = true; 257static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
276 te_data->end_jiffies = jiffies + 258 struct ieee80211_vif *vif,
277 TU_TO_JIFFIES(te_data->duration); 259 struct iwl_mvm_time_event_data *te_data,
278 return true; 260 struct iwl_time_event_cmd *te_cmd)
261{
262 static const u8 time_event_response[] = { TIME_EVENT_CMD };
263 struct iwl_notification_wait wait_time_event;
264 int ret;
265
266 lockdep_assert_held(&mvm->mutex);
267
268 spin_lock_bh(&mvm->time_event_lock);
269 if (WARN_ON(te_data->id != TE_MAX)) {
270 spin_unlock_bh(&mvm->time_event_lock);
271 return -EIO;
272 }
273 te_data->vif = vif;
274 te_data->duration = le32_to_cpu(te_cmd->duration);
275 te_data->id = le32_to_cpu(te_cmd->id);
276 list_add_tail(&te_data->list, &mvm->time_event_list);
277 spin_unlock_bh(&mvm->time_event_lock);
278
279 /*
280 * Use a notification wait, which really just processes the
281 * command response and doesn't wait for anything, in order
282 * to be able to process the response and get the UID inside
283 * the RX path. Using CMD_WANT_SKB doesn't work because it
284 * stores the buffer and then wakes up this thread, by which
285 * time another notification (that the time event started)
286 * might already be processed unsuccessfully.
287 */
288 iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
289 time_event_response,
290 ARRAY_SIZE(time_event_response),
291 iwl_mvm_time_event_response, te_data);
292
293 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
294 sizeof(*te_cmd), te_cmd);
295 if (ret) {
296 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
297 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
298 goto out_clear_te;
299 }
279 300
280 default: 301 /* No need to wait for anything, so just pass 1 (0 isn't valid) */
281 WARN_ON(1); 302 ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
282 return false; 303 /* should never fail */
283 }; 304 WARN_ON_ONCE(ret);
305
306 if (ret) {
307 out_clear_te:
308 spin_lock_bh(&mvm->time_event_lock);
309 iwl_mvm_te_clear_data(mvm, te_data);
310 spin_unlock_bh(&mvm->time_event_lock);
311 }
312 return ret;
284} 313}
285 314
286void iwl_mvm_protect_session(struct iwl_mvm *mvm, 315void iwl_mvm_protect_session(struct iwl_mvm *mvm,
@@ -289,11 +318,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
289{ 318{
290 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 319 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
291 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 320 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
292 static const u8 time_event_notif[] = { TIME_EVENT_CMD,
293 TIME_EVENT_NOTIFICATION };
294 struct iwl_notification_wait wait_time_event;
295 struct iwl_time_event_cmd time_cmd = {}; 321 struct iwl_time_event_cmd time_cmd = {};
296 int ret;
297 322
298 lockdep_assert_held(&mvm->mutex); 323 lockdep_assert_held(&mvm->mutex);
299 324
@@ -320,12 +345,6 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
320 iwl_mvm_stop_session_protection(mvm, vif); 345 iwl_mvm_stop_session_protection(mvm, vif);
321 } 346 }
322 347
323 iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
324 time_event_notif,
325 ARRAY_SIZE(time_event_notif),
326 iwl_mvm_time_event_notif,
327 &mvmvif->time_event_data);
328
329 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); 348 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
330 time_cmd.id_and_color = 349 time_cmd.id_and_color =
331 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 350 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
@@ -333,6 +352,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
333 352
334 time_cmd.apply_time = 353 time_cmd.apply_time =
335 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); 354 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG));
355
336 time_cmd.dep_policy = TE_INDEPENDENT; 356 time_cmd.dep_policy = TE_INDEPENDENT;
337 time_cmd.is_present = cpu_to_le32(1); 357 time_cmd.is_present = cpu_to_le32(1);
338 time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE); 358 time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE);
@@ -344,33 +364,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
344 time_cmd.repeat = cpu_to_le32(1); 364 time_cmd.repeat = cpu_to_le32(1);
345 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END); 365 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
346 366
347 te_data->vif = vif; 367 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
348 te_data->duration = duration;
349
350 spin_lock_bh(&mvm->time_event_lock);
351 te_data->id = le32_to_cpu(time_cmd.id);
352 list_add_tail(&te_data->list, &mvm->time_event_list);
353 spin_unlock_bh(&mvm->time_event_lock);
354
355 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
356 sizeof(time_cmd), &time_cmd);
357 if (ret) {
358 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
359 goto out_remove_notif;
360 }
361
362 ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1 * HZ);
363 if (ret) {
364 IWL_ERR(mvm, "%s - failed on timeout\n", __func__);
365 spin_lock_bh(&mvm->time_event_lock);
366 iwl_mvm_te_clear_data(mvm, te_data);
367 spin_unlock_bh(&mvm->time_event_lock);
368 }
369
370 return;
371
372out_remove_notif:
373 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
374} 368}
375 369
376/* 370/*
@@ -435,43 +429,12 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
435 iwl_mvm_remove_time_event(mvm, mvmvif, te_data); 429 iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
436} 430}
437 431
438static bool iwl_mvm_roc_te_notif(struct iwl_notif_wait_data *notif_wait,
439 struct iwl_rx_packet *pkt, void *data)
440{
441 struct iwl_mvm *mvm =
442 container_of(notif_wait, struct iwl_mvm, notif_wait);
443 struct iwl_mvm_time_event_data *te_data = data;
444 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
445 struct iwl_time_event_resp *resp;
446
447 u32 mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
448
449 /* until we do something else */
450 WARN_ON(te_data->id != IWL_MVM_ROC_TE_TYPE);
451
452 switch (pkt->hdr.cmd) {
453 case TIME_EVENT_CMD:
454 resp = (void *)pkt->data;
455 WARN_ON(mac_id_n_color != le32_to_cpu(resp->id_and_color));
456 te_data->uid = le32_to_cpu(resp->unique_id);
457 IWL_DEBUG_TE(mvm, "Got response - UID = 0x%x\n", te_data->uid);
458 return true;
459
460 default:
461 WARN_ON(1);
462 return false;
463 };
464}
465
466int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 432int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
467 int duration) 433 int duration)
468{ 434{
469 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 435 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
470 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 436 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
471 static const u8 roc_te_notif[] = { TIME_EVENT_CMD };
472 struct iwl_notification_wait wait_time_event;
473 struct iwl_time_event_cmd time_cmd = {}; 437 struct iwl_time_event_cmd time_cmd = {};
474 int ret;
475 438
476 lockdep_assert_held(&mvm->mutex); 439 lockdep_assert_held(&mvm->mutex);
477 if (te_data->running) { 440 if (te_data->running) {
@@ -485,12 +448,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
485 */ 448 */
486 flush_work(&mvm->roc_done_wk); 449 flush_work(&mvm->roc_done_wk);
487 450
488 iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
489 roc_te_notif,
490 ARRAY_SIZE(roc_te_notif),
491 iwl_mvm_roc_te_notif,
492 &mvmvif->time_event_data);
493
494 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); 451 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
495 time_cmd.id_and_color = 452 time_cmd.id_and_color =
496 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 453 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
@@ -516,33 +473,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
516 time_cmd.repeat = cpu_to_le32(1); 473 time_cmd.repeat = cpu_to_le32(1);
517 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END); 474 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
518 475
519 /* Push the te data to the tracked te list */ 476 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
520 te_data->vif = vif;
521 te_data->duration = MSEC_TO_TU(duration);
522
523 spin_lock_bh(&mvm->time_event_lock);
524 te_data->id = le32_to_cpu(time_cmd.id);
525 list_add_tail(&te_data->list, &mvm->time_event_list);
526 spin_unlock_bh(&mvm->time_event_lock);
527
528 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
529 sizeof(time_cmd), &time_cmd);
530 if (ret) {
531 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
532 goto out_remove_notif;
533 }
534
535 ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1 * HZ);
536 if (ret) {
537 IWL_ERR(mvm, "%s - failed on timeout\n", __func__);
538 iwl_mvm_te_clear_data(mvm, te_data);
539 }
540
541 return ret;
542
543out_remove_notif:
544 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
545 return ret;
546} 477}
547 478
548void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm) 479void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)