diff options
author | David S. Miller <davem@davemloft.net> | 2016-05-10 01:02:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-10 01:02:51 -0400 |
commit | 5e769ada93b2111010d3ca96213fc0b37c95afc8 (patch) | |
tree | d9e7f009a0e061d6bb3bc26724667573a3d13867 | |
parent | adc0a8bfdc52cbbfe76730b166a17cb0d5cbc0f4 (diff) | |
parent | cbbba30f1ac95a04aae9c61a55aebe5e6fdf29f0 (diff) |
Merge tag 'wireless-drivers-for-davem-2016-05-09' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers
Kalle Valo says:
====================
wireless-drivers fixes for 4.6
iwlwifi
* fix P2P rates (and possibly other issues)
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 75870e68a7c3..34731e29c589 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
@@ -105,6 +105,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
105 | struct iwl_tx_cmd *tx_cmd, | 105 | struct iwl_tx_cmd *tx_cmd, |
106 | struct ieee80211_tx_info *info, u8 sta_id) | 106 | struct ieee80211_tx_info *info, u8 sta_id) |
107 | { | 107 | { |
108 | struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); | ||
108 | struct ieee80211_hdr *hdr = (void *)skb->data; | 109 | struct ieee80211_hdr *hdr = (void *)skb->data; |
109 | __le16 fc = hdr->frame_control; | 110 | __le16 fc = hdr->frame_control; |
110 | u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); | 111 | u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); |
@@ -185,7 +186,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
185 | tx_cmd->tx_flags = cpu_to_le32(tx_flags); | 186 | tx_cmd->tx_flags = cpu_to_le32(tx_flags); |
186 | /* Total # bytes to be transmitted */ | 187 | /* Total # bytes to be transmitted */ |
187 | tx_cmd->len = cpu_to_le16((u16)skb->len + | 188 | tx_cmd->len = cpu_to_le16((u16)skb->len + |
188 | (uintptr_t)info->driver_data[0]); | 189 | (uintptr_t)skb_info->driver_data[0]); |
189 | tx_cmd->next_frame_len = 0; | 190 | tx_cmd->next_frame_len = 0; |
190 | tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); | 191 | tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); |
191 | tx_cmd->sta_id = sta_id; | 192 | tx_cmd->sta_id = sta_id; |
@@ -327,10 +328,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, | |||
327 | */ | 328 | */ |
328 | static struct iwl_device_cmd * | 329 | static struct iwl_device_cmd * |
329 | iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, | 330 | iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, |
330 | int hdrlen, struct ieee80211_sta *sta, u8 sta_id) | 331 | struct ieee80211_tx_info *info, int hdrlen, |
332 | struct ieee80211_sta *sta, u8 sta_id) | ||
331 | { | 333 | { |
332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 334 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
333 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 335 | struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); |
334 | struct iwl_device_cmd *dev_cmd; | 336 | struct iwl_device_cmd *dev_cmd; |
335 | struct iwl_tx_cmd *tx_cmd; | 337 | struct iwl_tx_cmd *tx_cmd; |
336 | 338 | ||
@@ -350,10 +352,10 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
350 | 352 | ||
351 | iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control); | 353 | iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control); |
352 | 354 | ||
353 | memset(&info->status, 0, sizeof(info->status)); | 355 | memset(&skb_info->status, 0, sizeof(skb_info->status)); |
354 | memset(info->driver_data, 0, sizeof(info->driver_data)); | 356 | memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data)); |
355 | 357 | ||
356 | info->driver_data[1] = dev_cmd; | 358 | skb_info->driver_data[1] = dev_cmd; |
357 | 359 | ||
358 | return dev_cmd; | 360 | return dev_cmd; |
359 | } | 361 | } |
@@ -361,22 +363,25 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
361 | int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | 363 | int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) |
362 | { | 364 | { |
363 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 365 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
364 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 366 | struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); |
367 | struct ieee80211_tx_info info; | ||
365 | struct iwl_device_cmd *dev_cmd; | 368 | struct iwl_device_cmd *dev_cmd; |
366 | struct iwl_tx_cmd *tx_cmd; | 369 | struct iwl_tx_cmd *tx_cmd; |
367 | u8 sta_id; | 370 | u8 sta_id; |
368 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); | 371 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
369 | 372 | ||
370 | if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU)) | 373 | memcpy(&info, skb->cb, sizeof(info)); |
374 | |||
375 | if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU)) | ||
371 | return -1; | 376 | return -1; |
372 | 377 | ||
373 | if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && | 378 | if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && |
374 | (!info->control.vif || | 379 | (!info.control.vif || |
375 | info->hw_queue != info->control.vif->cab_queue))) | 380 | info.hw_queue != info.control.vif->cab_queue))) |
376 | return -1; | 381 | return -1; |
377 | 382 | ||
378 | /* This holds the amsdu headers length */ | 383 | /* This holds the amsdu headers length */ |
379 | info->driver_data[0] = (void *)(uintptr_t)0; | 384 | skb_info->driver_data[0] = (void *)(uintptr_t)0; |
380 | 385 | ||
381 | /* | 386 | /* |
382 | * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used | 387 | * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used |
@@ -385,7 +390,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
385 | * and hence needs to be sent on the aux queue | 390 | * and hence needs to be sent on the aux queue |
386 | */ | 391 | */ |
387 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && | 392 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && |
388 | info->control.vif->type == NL80211_IFTYPE_STATION) | 393 | info.control.vif->type == NL80211_IFTYPE_STATION) |
389 | IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue; | 394 | IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue; |
390 | 395 | ||
391 | /* | 396 | /* |
@@ -398,14 +403,14 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
398 | * AUX station. | 403 | * AUX station. |
399 | */ | 404 | */ |
400 | sta_id = mvm->aux_sta.sta_id; | 405 | sta_id = mvm->aux_sta.sta_id; |
401 | if (info->control.vif) { | 406 | if (info.control.vif) { |
402 | struct iwl_mvm_vif *mvmvif = | 407 | struct iwl_mvm_vif *mvmvif = |
403 | iwl_mvm_vif_from_mac80211(info->control.vif); | 408 | iwl_mvm_vif_from_mac80211(info.control.vif); |
404 | 409 | ||
405 | if (info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE || | 410 | if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE || |
406 | info->control.vif->type == NL80211_IFTYPE_AP) | 411 | info.control.vif->type == NL80211_IFTYPE_AP) |
407 | sta_id = mvmvif->bcast_sta.sta_id; | 412 | sta_id = mvmvif->bcast_sta.sta_id; |
408 | else if (info->control.vif->type == NL80211_IFTYPE_STATION && | 413 | else if (info.control.vif->type == NL80211_IFTYPE_STATION && |
409 | is_multicast_ether_addr(hdr->addr1)) { | 414 | is_multicast_ether_addr(hdr->addr1)) { |
410 | u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id); | 415 | u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id); |
411 | 416 | ||
@@ -414,19 +419,18 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
414 | } | 419 | } |
415 | } | 420 | } |
416 | 421 | ||
417 | IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info->hw_queue); | 422 | IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info.hw_queue); |
418 | 423 | ||
419 | dev_cmd = iwl_mvm_set_tx_params(mvm, skb, hdrlen, NULL, sta_id); | 424 | dev_cmd = iwl_mvm_set_tx_params(mvm, skb, &info, hdrlen, NULL, sta_id); |
420 | if (!dev_cmd) | 425 | if (!dev_cmd) |
421 | return -1; | 426 | return -1; |
422 | 427 | ||
423 | /* From now on, we cannot access info->control */ | ||
424 | tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; | 428 | tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; |
425 | 429 | ||
426 | /* Copy MAC header from skb into command buffer */ | 430 | /* Copy MAC header from skb into command buffer */ |
427 | memcpy(tx_cmd->hdr, hdr, hdrlen); | 431 | memcpy(tx_cmd->hdr, hdr, hdrlen); |
428 | 432 | ||
429 | if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info->hw_queue)) { | 433 | if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info.hw_queue)) { |
430 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); | 434 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); |
431 | return -1; | 435 | return -1; |
432 | } | 436 | } |
@@ -445,11 +449,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
445 | 449 | ||
446 | #ifdef CONFIG_INET | 450 | #ifdef CONFIG_INET |
447 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | 451 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, |
452 | struct ieee80211_tx_info *info, | ||
448 | struct ieee80211_sta *sta, | 453 | struct ieee80211_sta *sta, |
449 | struct sk_buff_head *mpdus_skb) | 454 | struct sk_buff_head *mpdus_skb) |
450 | { | 455 | { |
451 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 456 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
452 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
453 | struct ieee80211_hdr *hdr = (void *)skb->data; | 457 | struct ieee80211_hdr *hdr = (void *)skb->data; |
454 | unsigned int mss = skb_shinfo(skb)->gso_size; | 458 | unsigned int mss = skb_shinfo(skb)->gso_size; |
455 | struct sk_buff *tmp, *next; | 459 | struct sk_buff *tmp, *next; |
@@ -544,6 +548,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
544 | 548 | ||
545 | /* This skb fits in one single A-MSDU */ | 549 | /* This skb fits in one single A-MSDU */ |
546 | if (num_subframes * mss >= tcp_payload_len) { | 550 | if (num_subframes * mss >= tcp_payload_len) { |
551 | struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); | ||
552 | |||
547 | /* | 553 | /* |
548 | * Compute the length of all the data added for the A-MSDU. | 554 | * Compute the length of all the data added for the A-MSDU. |
549 | * This will be used to compute the length to write in the TX | 555 | * This will be used to compute the length to write in the TX |
@@ -552,11 +558,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
552 | * already had one set of SNAP / IP / TCP headers. | 558 | * already had one set of SNAP / IP / TCP headers. |
553 | */ | 559 | */ |
554 | num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); | 560 | num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); |
555 | info = IEEE80211_SKB_CB(skb); | ||
556 | amsdu_add = num_subframes * sizeof(struct ethhdr) + | 561 | amsdu_add = num_subframes * sizeof(struct ethhdr) + |
557 | (num_subframes - 1) * (snap_ip_tcp + pad); | 562 | (num_subframes - 1) * (snap_ip_tcp + pad); |
558 | /* This holds the amsdu headers length */ | 563 | /* This holds the amsdu headers length */ |
559 | info->driver_data[0] = (void *)(uintptr_t)amsdu_add; | 564 | skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add; |
560 | 565 | ||
561 | __skb_queue_tail(mpdus_skb, skb); | 566 | __skb_queue_tail(mpdus_skb, skb); |
562 | return 0; | 567 | return 0; |
@@ -596,11 +601,14 @@ segment: | |||
596 | ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); | 601 | ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); |
597 | 602 | ||
598 | if (tcp_payload_len > mss) { | 603 | if (tcp_payload_len > mss) { |
604 | struct ieee80211_tx_info *skb_info = | ||
605 | IEEE80211_SKB_CB(tmp); | ||
606 | |||
599 | num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); | 607 | num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); |
600 | info = IEEE80211_SKB_CB(tmp); | ||
601 | amsdu_add = num_subframes * sizeof(struct ethhdr) + | 608 | amsdu_add = num_subframes * sizeof(struct ethhdr) + |
602 | (num_subframes - 1) * (snap_ip_tcp + pad); | 609 | (num_subframes - 1) * (snap_ip_tcp + pad); |
603 | info->driver_data[0] = (void *)(uintptr_t)amsdu_add; | 610 | skb_info->driver_data[0] = |
611 | (void *)(uintptr_t)amsdu_add; | ||
604 | skb_shinfo(tmp)->gso_size = mss; | 612 | skb_shinfo(tmp)->gso_size = mss; |
605 | } else { | 613 | } else { |
606 | qc = ieee80211_get_qos_ctl((void *)tmp->data); | 614 | qc = ieee80211_get_qos_ctl((void *)tmp->data); |
@@ -622,6 +630,7 @@ segment: | |||
622 | } | 630 | } |
623 | #else /* CONFIG_INET */ | 631 | #else /* CONFIG_INET */ |
624 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | 632 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, |
633 | struct ieee80211_tx_info *info, | ||
625 | struct ieee80211_sta *sta, | 634 | struct ieee80211_sta *sta, |
626 | struct sk_buff_head *mpdus_skb) | 635 | struct sk_buff_head *mpdus_skb) |
627 | { | 636 | { |
@@ -636,10 +645,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
636 | * Sets the fields in the Tx cmd that are crypto related | 645 | * Sets the fields in the Tx cmd that are crypto related |
637 | */ | 646 | */ |
638 | static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, | 647 | static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, |
648 | struct ieee80211_tx_info *info, | ||
639 | struct ieee80211_sta *sta) | 649 | struct ieee80211_sta *sta) |
640 | { | 650 | { |
641 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 651 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
642 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
643 | struct iwl_mvm_sta *mvmsta; | 652 | struct iwl_mvm_sta *mvmsta; |
644 | struct iwl_device_cmd *dev_cmd; | 653 | struct iwl_device_cmd *dev_cmd; |
645 | struct iwl_tx_cmd *tx_cmd; | 654 | struct iwl_tx_cmd *tx_cmd; |
@@ -660,7 +669,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
660 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) | 669 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
661 | return -1; | 670 | return -1; |
662 | 671 | ||
663 | dev_cmd = iwl_mvm_set_tx_params(mvm, skb, hdrlen, sta, mvmsta->sta_id); | 672 | dev_cmd = iwl_mvm_set_tx_params(mvm, skb, info, hdrlen, |
673 | sta, mvmsta->sta_id); | ||
664 | if (!dev_cmd) | 674 | if (!dev_cmd) |
665 | goto drop; | 675 | goto drop; |
666 | 676 | ||
@@ -736,7 +746,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
736 | struct ieee80211_sta *sta) | 746 | struct ieee80211_sta *sta) |
737 | { | 747 | { |
738 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 748 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
739 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 749 | struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); |
750 | struct ieee80211_tx_info info; | ||
740 | struct sk_buff_head mpdus_skbs; | 751 | struct sk_buff_head mpdus_skbs; |
741 | unsigned int payload_len; | 752 | unsigned int payload_len; |
742 | int ret; | 753 | int ret; |
@@ -747,21 +758,23 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
747 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) | 758 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
748 | return -1; | 759 | return -1; |
749 | 760 | ||
761 | memcpy(&info, skb->cb, sizeof(info)); | ||
762 | |||
750 | /* This holds the amsdu headers length */ | 763 | /* This holds the amsdu headers length */ |
751 | info->driver_data[0] = (void *)(uintptr_t)0; | 764 | skb_info->driver_data[0] = (void *)(uintptr_t)0; |
752 | 765 | ||
753 | if (!skb_is_gso(skb)) | 766 | if (!skb_is_gso(skb)) |
754 | return iwl_mvm_tx_mpdu(mvm, skb, sta); | 767 | return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); |
755 | 768 | ||
756 | payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - | 769 | payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - |
757 | tcp_hdrlen(skb) + skb->data_len; | 770 | tcp_hdrlen(skb) + skb->data_len; |
758 | 771 | ||
759 | if (payload_len <= skb_shinfo(skb)->gso_size) | 772 | if (payload_len <= skb_shinfo(skb)->gso_size) |
760 | return iwl_mvm_tx_mpdu(mvm, skb, sta); | 773 | return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); |
761 | 774 | ||
762 | __skb_queue_head_init(&mpdus_skbs); | 775 | __skb_queue_head_init(&mpdus_skbs); |
763 | 776 | ||
764 | ret = iwl_mvm_tx_tso(mvm, skb, sta, &mpdus_skbs); | 777 | ret = iwl_mvm_tx_tso(mvm, skb, &info, sta, &mpdus_skbs); |
765 | if (ret) | 778 | if (ret) |
766 | return ret; | 779 | return ret; |
767 | 780 | ||
@@ -771,7 +784,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
771 | while (!skb_queue_empty(&mpdus_skbs)) { | 784 | while (!skb_queue_empty(&mpdus_skbs)) { |
772 | skb = __skb_dequeue(&mpdus_skbs); | 785 | skb = __skb_dequeue(&mpdus_skbs); |
773 | 786 | ||
774 | ret = iwl_mvm_tx_mpdu(mvm, skb, sta); | 787 | ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta); |
775 | if (ret) { | 788 | if (ret) { |
776 | __skb_queue_purge(&mpdus_skbs); | 789 | __skb_queue_purge(&mpdus_skbs); |
777 | return ret; | 790 | return ret; |