aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k/wmi.c
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-01-23 06:48:21 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2014-01-24 03:23:37 -0500
commit748afc4735361e21ad655c0dc021ea3aaeeb3efd (patch)
tree950155c5fdf8671375d4e0af21c7857645b5ee83 /drivers/net/wireless/ath/ath10k/wmi.c
parentc2df44b39b31a730a89b13f7be90860d93d1f9d8 (diff)
ath10k: implement and use new beacon method
Until now ath10k used a copy-by-value beacon submission. The new method passes a DMA address via WMI command only. This command contains additional metadata that fixes AP behaviour with regard to powersave buffering. This also fixes strange bug when multicast traffic would freeze TX indefinitely. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Marek Puzyniak <marek.puzyniak@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/wmi.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index a1ec5d0fb0ef..bd01f0a7dafb 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -561,7 +561,6 @@ err_pull:
561 561
562static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) 562static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
563{ 563{
564 struct wmi_bcn_tx_arg arg = {0};
565 int ret; 564 int ret;
566 565
567 lockdep_assert_held(&arvif->ar->data_lock); 566 lockdep_assert_held(&arvif->ar->data_lock);
@@ -569,18 +568,16 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
569 if (arvif->beacon == NULL) 568 if (arvif->beacon == NULL)
570 return; 569 return;
571 570
572 arg.vdev_id = arvif->vdev_id; 571 if (arvif->beacon_sent)
573 arg.tx_rate = 0; 572 return;
574 arg.tx_power = 0;
575 arg.bcn = arvif->beacon->data;
576 arg.bcn_len = arvif->beacon->len;
577 573
578 ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg); 574 ret = ath10k_wmi_beacon_send_ref_nowait(arvif);
579 if (ret) 575 if (ret)
580 return; 576 return;
581 577
582 dev_kfree_skb_any(arvif->beacon); 578 /* We need to retain the arvif->beacon reference for DMA unmapping and
583 arvif->beacon = NULL; 579 * freeing the skbuff later. */
580 arvif->beacon_sent = true;
584} 581}
585 582
586static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, 583static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
@@ -1237,6 +1234,13 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
1237 tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); 1234 tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast);
1238 memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); 1235 memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
1239 1236
1237 if (tim->dtim_count == 0) {
1238 ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
1239
1240 if (__le32_to_cpu(bcn_info->tim_info.tim_mcast) == 1)
1241 ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
1242 }
1243
1240 ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", 1244 ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
1241 tim->dtim_count, tim->dtim_period, 1245 tim->dtim_count, tim->dtim_period,
1242 tim->bitmap_ctrl, pvm_len); 1246 tim->bitmap_ctrl, pvm_len);
@@ -1427,13 +1431,20 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
1427 ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); 1431 ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
1428 1432
1429 spin_lock_bh(&ar->data_lock); 1433 spin_lock_bh(&ar->data_lock);
1434
1430 if (arvif->beacon) { 1435 if (arvif->beacon) {
1431 ath10k_warn("SWBA overrun on vdev %d\n", 1436 if (!arvif->beacon_sent)
1432 arvif->vdev_id); 1437 ath10k_warn("SWBA overrun on vdev %d\n",
1438 arvif->vdev_id);
1439
1440 ath10k_skb_unmap(ar->dev, arvif->beacon);
1433 dev_kfree_skb_any(arvif->beacon); 1441 dev_kfree_skb_any(arvif->beacon);
1434 } 1442 }
1435 1443
1444 ath10k_skb_map(ar->dev, bcn);
1445
1436 arvif->beacon = bcn; 1446 arvif->beacon = bcn;
1447 arvif->beacon_sent = false;
1437 1448
1438 ath10k_wmi_tx_beacon_nowait(arvif); 1449 ath10k_wmi_tx_beacon_nowait(arvif);
1439 spin_unlock_bh(&ar->data_lock); 1450 spin_unlock_bh(&ar->data_lock);
@@ -3442,25 +3453,41 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
3442 return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); 3453 return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid);
3443} 3454}
3444 3455
3445int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, 3456/* This function assumes the beacon is already DMA mapped */
3446 const struct wmi_bcn_tx_arg *arg) 3457int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif)
3447{ 3458{
3448 struct wmi_bcn_tx_cmd *cmd; 3459 struct wmi_bcn_tx_ref_cmd *cmd;
3449 struct sk_buff *skb; 3460 struct sk_buff *skb;
3461 struct sk_buff *beacon = arvif->beacon;
3462 struct ath10k *ar = arvif->ar;
3463 struct ieee80211_hdr *hdr;
3450 int ret; 3464 int ret;
3465 u16 fc;
3451 3466
3452 skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len); 3467 skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
3453 if (!skb) 3468 if (!skb)
3454 return -ENOMEM; 3469 return -ENOMEM;
3455 3470
3456 cmd = (struct wmi_bcn_tx_cmd *)skb->data; 3471 hdr = (struct ieee80211_hdr *)beacon->data;
3457 cmd->hdr.vdev_id = __cpu_to_le32(arg->vdev_id); 3472 fc = le16_to_cpu(hdr->frame_control);
3458 cmd->hdr.tx_rate = __cpu_to_le32(arg->tx_rate); 3473
3459 cmd->hdr.tx_power = __cpu_to_le32(arg->tx_power); 3474 cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data;
3460 cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); 3475 cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
3461 memcpy(cmd->bcn, arg->bcn, arg->bcn_len); 3476 cmd->data_len = __cpu_to_le32(beacon->len);
3477 cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr);
3478 cmd->msdu_id = 0;
3479 cmd->frame_control = __cpu_to_le32(fc);
3480 cmd->flags = 0;
3481
3482 if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero)
3483 cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
3484
3485 if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab)
3486 cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
3487
3488 ret = ath10k_wmi_cmd_send_nowait(ar, skb,
3489 ar->wmi.cmd->pdev_send_bcn_cmdid);
3462 3490
3463 ret = ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid);
3464 if (ret) 3491 if (ret)
3465 dev_kfree_skb(skb); 3492 dev_kfree_skb(skb);
3466 3493