diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/wmi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 132 |
1 files changed, 99 insertions, 33 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 712a606a080a..cb1f7b5bcf4c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -213,7 +213,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { | |||
213 | .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, | 213 | .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, |
214 | .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, | 214 | .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, |
215 | .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, | 215 | .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, |
216 | .ap_ps_peer_param_cmdid = WMI_CMD_UNSUPPORTED, | 216 | .ap_ps_peer_param_cmdid = WMI_10X_AP_PS_PEER_PARAM_CMDID, |
217 | .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, | 217 | .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, |
218 | .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, | 218 | .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, |
219 | .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, | 219 | .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, |
@@ -420,7 +420,6 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = { | |||
420 | .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | 420 | .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, |
421 | .pmf_qos = WMI_PDEV_PARAM_PMF_QOS, | 421 | .pmf_qos = WMI_PDEV_PARAM_PMF_QOS, |
422 | .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, | 422 | .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, |
423 | .arpdhcp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | ||
424 | .dcs = WMI_PDEV_PARAM_DCS, | 423 | .dcs = WMI_PDEV_PARAM_DCS, |
425 | .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, | 424 | .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, |
426 | .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, | 425 | .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, |
@@ -472,8 +471,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = { | |||
472 | .bcnflt_stats_update_period = | 471 | .bcnflt_stats_update_period = |
473 | WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | 472 | WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, |
474 | .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, | 473 | .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, |
475 | .arp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | 474 | .arp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, |
476 | .arpdhcp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, | ||
477 | .dcs = WMI_10X_PDEV_PARAM_DCS, | 475 | .dcs = WMI_10X_PDEV_PARAM_DCS, |
478 | .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, | 476 | .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, |
479 | .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, | 477 | .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, |
@@ -561,7 +559,6 @@ err_pull: | |||
561 | 559 | ||
562 | static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) | 560 | static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) |
563 | { | 561 | { |
564 | struct wmi_bcn_tx_arg arg = {0}; | ||
565 | int ret; | 562 | int ret; |
566 | 563 | ||
567 | lockdep_assert_held(&arvif->ar->data_lock); | 564 | lockdep_assert_held(&arvif->ar->data_lock); |
@@ -569,18 +566,16 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) | |||
569 | if (arvif->beacon == NULL) | 566 | if (arvif->beacon == NULL) |
570 | return; | 567 | return; |
571 | 568 | ||
572 | arg.vdev_id = arvif->vdev_id; | 569 | if (arvif->beacon_sent) |
573 | arg.tx_rate = 0; | 570 | return; |
574 | arg.tx_power = 0; | ||
575 | arg.bcn = arvif->beacon->data; | ||
576 | arg.bcn_len = arvif->beacon->len; | ||
577 | 571 | ||
578 | ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg); | 572 | ret = ath10k_wmi_beacon_send_ref_nowait(arvif); |
579 | if (ret) | 573 | if (ret) |
580 | return; | 574 | return; |
581 | 575 | ||
582 | dev_kfree_skb_any(arvif->beacon); | 576 | /* We need to retain the arvif->beacon reference for DMA unmapping and |
583 | arvif->beacon = NULL; | 577 | * freeing the skbuff later. */ |
578 | arvif->beacon_sent = true; | ||
584 | } | 579 | } |
585 | 580 | ||
586 | static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, | 581 | static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, |
@@ -1116,7 +1111,27 @@ static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, | |||
1116 | static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, | 1111 | static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, |
1117 | struct sk_buff *skb) | 1112 | struct sk_buff *skb) |
1118 | { | 1113 | { |
1119 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_PEER_STA_KICKOUT_EVENTID\n"); | 1114 | struct wmi_peer_sta_kickout_event *ev; |
1115 | struct ieee80211_sta *sta; | ||
1116 | |||
1117 | ev = (struct wmi_peer_sta_kickout_event *)skb->data; | ||
1118 | |||
1119 | ath10k_dbg(ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n", | ||
1120 | ev->peer_macaddr.addr); | ||
1121 | |||
1122 | rcu_read_lock(); | ||
1123 | |||
1124 | sta = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL); | ||
1125 | if (!sta) { | ||
1126 | ath10k_warn("Spurious quick kickout for STA %pM\n", | ||
1127 | ev->peer_macaddr.addr); | ||
1128 | goto exit; | ||
1129 | } | ||
1130 | |||
1131 | ieee80211_report_low_ack(sta, 10); | ||
1132 | |||
1133 | exit: | ||
1134 | rcu_read_unlock(); | ||
1120 | } | 1135 | } |
1121 | 1136 | ||
1122 | /* | 1137 | /* |
@@ -1217,6 +1232,13 @@ static void ath10k_wmi_update_tim(struct ath10k *ar, | |||
1217 | tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); | 1232 | tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); |
1218 | memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); | 1233 | memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); |
1219 | 1234 | ||
1235 | if (tim->dtim_count == 0) { | ||
1236 | ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true; | ||
1237 | |||
1238 | if (__le32_to_cpu(bcn_info->tim_info.tim_mcast) == 1) | ||
1239 | ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true; | ||
1240 | } | ||
1241 | |||
1220 | ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", | 1242 | ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", |
1221 | tim->dtim_count, tim->dtim_period, | 1243 | tim->dtim_count, tim->dtim_period, |
1222 | tim->bitmap_ctrl, pvm_len); | 1244 | tim->bitmap_ctrl, pvm_len); |
@@ -1338,7 +1360,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1338 | struct wmi_bcn_info *bcn_info; | 1360 | struct wmi_bcn_info *bcn_info; |
1339 | struct ath10k_vif *arvif; | 1361 | struct ath10k_vif *arvif; |
1340 | struct sk_buff *bcn; | 1362 | struct sk_buff *bcn; |
1341 | int vdev_id = 0; | 1363 | int ret, vdev_id = 0; |
1342 | 1364 | ||
1343 | ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); | 1365 | ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); |
1344 | 1366 | ||
@@ -1385,6 +1407,17 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1385 | continue; | 1407 | continue; |
1386 | } | 1408 | } |
1387 | 1409 | ||
1410 | /* There are no completions for beacons so wait for next SWBA | ||
1411 | * before telling mac80211 to decrement CSA counter | ||
1412 | * | ||
1413 | * Once CSA counter is completed stop sending beacons until | ||
1414 | * actual channel switch is done */ | ||
1415 | if (arvif->vif->csa_active && | ||
1416 | ieee80211_csa_is_complete(arvif->vif)) { | ||
1417 | ieee80211_csa_finish(arvif->vif); | ||
1418 | continue; | ||
1419 | } | ||
1420 | |||
1388 | bcn = ieee80211_beacon_get(ar->hw, arvif->vif); | 1421 | bcn = ieee80211_beacon_get(ar->hw, arvif->vif); |
1389 | if (!bcn) { | 1422 | if (!bcn) { |
1390 | ath10k_warn("could not get mac80211 beacon\n"); | 1423 | ath10k_warn("could not get mac80211 beacon\n"); |
@@ -1396,15 +1429,33 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1396 | ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); | 1429 | ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); |
1397 | 1430 | ||
1398 | spin_lock_bh(&ar->data_lock); | 1431 | spin_lock_bh(&ar->data_lock); |
1432 | |||
1399 | if (arvif->beacon) { | 1433 | if (arvif->beacon) { |
1400 | ath10k_warn("SWBA overrun on vdev %d\n", | 1434 | if (!arvif->beacon_sent) |
1401 | arvif->vdev_id); | 1435 | ath10k_warn("SWBA overrun on vdev %d\n", |
1436 | arvif->vdev_id); | ||
1437 | |||
1438 | dma_unmap_single(arvif->ar->dev, | ||
1439 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
1440 | arvif->beacon->len, DMA_TO_DEVICE); | ||
1402 | dev_kfree_skb_any(arvif->beacon); | 1441 | dev_kfree_skb_any(arvif->beacon); |
1403 | } | 1442 | } |
1404 | 1443 | ||
1444 | ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, | ||
1445 | bcn->data, bcn->len, | ||
1446 | DMA_TO_DEVICE); | ||
1447 | ret = dma_mapping_error(arvif->ar->dev, | ||
1448 | ATH10K_SKB_CB(bcn)->paddr); | ||
1449 | if (ret) { | ||
1450 | ath10k_warn("failed to map beacon: %d\n", ret); | ||
1451 | goto skip; | ||
1452 | } | ||
1453 | |||
1405 | arvif->beacon = bcn; | 1454 | arvif->beacon = bcn; |
1455 | arvif->beacon_sent = false; | ||
1406 | 1456 | ||
1407 | ath10k_wmi_tx_beacon_nowait(arvif); | 1457 | ath10k_wmi_tx_beacon_nowait(arvif); |
1458 | skip: | ||
1408 | spin_unlock_bh(&ar->data_lock); | 1459 | spin_unlock_bh(&ar->data_lock); |
1409 | } | 1460 | } |
1410 | } | 1461 | } |
@@ -2031,11 +2082,11 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2031 | memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); | 2082 | memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); |
2032 | 2083 | ||
2033 | ath10k_dbg(ATH10K_DBG_WMI, | 2084 | ath10k_dbg(ATH10K_DBG_WMI, |
2034 | "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n", | 2085 | "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n", |
2035 | __le32_to_cpu(ev->sw_version), | 2086 | __le32_to_cpu(ev->sw_version), |
2036 | __le32_to_cpu(ev->abi_version), | 2087 | __le32_to_cpu(ev->abi_version), |
2037 | ev->mac_addr.addr, | 2088 | ev->mac_addr.addr, |
2038 | __le32_to_cpu(ev->status)); | 2089 | __le32_to_cpu(ev->status), skb->len, sizeof(*ev)); |
2039 | 2090 | ||
2040 | complete(&ar->wmi.unified_ready); | 2091 | complete(&ar->wmi.unified_ready); |
2041 | return 0; | 2092 | return 0; |
@@ -2403,7 +2454,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | |||
2403 | ar->wmi.cmd->pdev_set_channel_cmdid); | 2454 | ar->wmi.cmd->pdev_set_channel_cmdid); |
2404 | } | 2455 | } |
2405 | 2456 | ||
2406 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) | 2457 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt) |
2407 | { | 2458 | { |
2408 | struct wmi_pdev_suspend_cmd *cmd; | 2459 | struct wmi_pdev_suspend_cmd *cmd; |
2409 | struct sk_buff *skb; | 2460 | struct sk_buff *skb; |
@@ -2413,7 +2464,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) | |||
2413 | return -ENOMEM; | 2464 | return -ENOMEM; |
2414 | 2465 | ||
2415 | cmd = (struct wmi_pdev_suspend_cmd *)skb->data; | 2466 | cmd = (struct wmi_pdev_suspend_cmd *)skb->data; |
2416 | cmd->suspend_opt = WMI_PDEV_SUSPEND; | 2467 | cmd->suspend_opt = __cpu_to_le32(suspend_opt); |
2417 | 2468 | ||
2418 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); | 2469 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); |
2419 | } | 2470 | } |
@@ -3342,7 +3393,6 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, | |||
3342 | ci->max_power = ch->max_power; | 3393 | ci->max_power = ch->max_power; |
3343 | ci->reg_power = ch->max_reg_power; | 3394 | ci->reg_power = ch->max_reg_power; |
3344 | ci->antenna_max = ch->max_antenna_gain; | 3395 | ci->antenna_max = ch->max_antenna_gain; |
3345 | ci->antenna_max = 0; | ||
3346 | 3396 | ||
3347 | /* mode & flags share storage */ | 3397 | /* mode & flags share storage */ |
3348 | ci->mode = ch->mode; | 3398 | ci->mode = ch->mode; |
@@ -3411,25 +3461,41 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, | |||
3411 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); | 3461 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); |
3412 | } | 3462 | } |
3413 | 3463 | ||
3414 | int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, | 3464 | /* This function assumes the beacon is already DMA mapped */ |
3415 | const struct wmi_bcn_tx_arg *arg) | 3465 | int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif) |
3416 | { | 3466 | { |
3417 | struct wmi_bcn_tx_cmd *cmd; | 3467 | struct wmi_bcn_tx_ref_cmd *cmd; |
3418 | struct sk_buff *skb; | 3468 | struct sk_buff *skb; |
3469 | struct sk_buff *beacon = arvif->beacon; | ||
3470 | struct ath10k *ar = arvif->ar; | ||
3471 | struct ieee80211_hdr *hdr; | ||
3419 | int ret; | 3472 | int ret; |
3473 | u16 fc; | ||
3420 | 3474 | ||
3421 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len); | 3475 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); |
3422 | if (!skb) | 3476 | if (!skb) |
3423 | return -ENOMEM; | 3477 | return -ENOMEM; |
3424 | 3478 | ||
3425 | cmd = (struct wmi_bcn_tx_cmd *)skb->data; | 3479 | hdr = (struct ieee80211_hdr *)beacon->data; |
3426 | cmd->hdr.vdev_id = __cpu_to_le32(arg->vdev_id); | 3480 | fc = le16_to_cpu(hdr->frame_control); |
3427 | cmd->hdr.tx_rate = __cpu_to_le32(arg->tx_rate); | 3481 | |
3428 | cmd->hdr.tx_power = __cpu_to_le32(arg->tx_power); | 3482 | cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data; |
3429 | cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); | 3483 | cmd->vdev_id = __cpu_to_le32(arvif->vdev_id); |
3430 | memcpy(cmd->bcn, arg->bcn, arg->bcn_len); | 3484 | cmd->data_len = __cpu_to_le32(beacon->len); |
3485 | cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr); | ||
3486 | cmd->msdu_id = 0; | ||
3487 | cmd->frame_control = __cpu_to_le32(fc); | ||
3488 | cmd->flags = 0; | ||
3489 | |||
3490 | if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero) | ||
3491 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); | ||
3492 | |||
3493 | if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab) | ||
3494 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); | ||
3495 | |||
3496 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, | ||
3497 | ar->wmi.cmd->pdev_send_bcn_cmdid); | ||
3431 | 3498 | ||
3432 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid); | ||
3433 | if (ret) | 3499 | if (ret) |
3434 | dev_kfree_skb(skb); | 3500 | dev_kfree_skb(skb); |
3435 | 3501 | ||