diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/wmi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 312 |
1 files changed, 135 insertions, 177 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index c7ea77edce24..6c046c244705 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "mac.h" | 26 | #include "mac.h" |
27 | #include "testmode.h" | 27 | #include "testmode.h" |
28 | #include "wmi-ops.h" | 28 | #include "wmi-ops.h" |
29 | #include "p2p.h" | ||
30 | #include "hw.h" | ||
29 | 31 | ||
30 | /* MAIN WMI cmd track */ | 32 | /* MAIN WMI cmd track */ |
31 | static struct wmi_cmd_map wmi_cmd_map = { | 33 | static struct wmi_cmd_map wmi_cmd_map = { |
@@ -884,20 +886,24 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, | |||
884 | 886 | ||
885 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) | 887 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) |
886 | { | 888 | { |
887 | int ret; | 889 | unsigned long time_left; |
888 | 890 | ||
889 | ret = wait_for_completion_timeout(&ar->wmi.service_ready, | 891 | time_left = wait_for_completion_timeout(&ar->wmi.service_ready, |
890 | WMI_SERVICE_READY_TIMEOUT_HZ); | 892 | WMI_SERVICE_READY_TIMEOUT_HZ); |
891 | return ret; | 893 | if (!time_left) |
894 | return -ETIMEDOUT; | ||
895 | return 0; | ||
892 | } | 896 | } |
893 | 897 | ||
894 | int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar) | 898 | int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar) |
895 | { | 899 | { |
896 | int ret; | 900 | unsigned long time_left; |
897 | 901 | ||
898 | ret = wait_for_completion_timeout(&ar->wmi.unified_ready, | 902 | time_left = wait_for_completion_timeout(&ar->wmi.unified_ready, |
899 | WMI_UNIFIED_READY_TIMEOUT_HZ); | 903 | WMI_UNIFIED_READY_TIMEOUT_HZ); |
900 | return ret; | 904 | if (!time_left) |
905 | return -ETIMEDOUT; | ||
906 | return 0; | ||
901 | } | 907 | } |
902 | 908 | ||
903 | struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len) | 909 | struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len) |
@@ -1351,63 +1357,6 @@ static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) | |||
1351 | return band; | 1357 | return band; |
1352 | } | 1358 | } |
1353 | 1359 | ||
1354 | static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band) | ||
1355 | { | ||
1356 | u8 rate_idx = 0; | ||
1357 | |||
1358 | /* rate in Kbps */ | ||
1359 | switch (rate) { | ||
1360 | case 1000: | ||
1361 | rate_idx = 0; | ||
1362 | break; | ||
1363 | case 2000: | ||
1364 | rate_idx = 1; | ||
1365 | break; | ||
1366 | case 5500: | ||
1367 | rate_idx = 2; | ||
1368 | break; | ||
1369 | case 11000: | ||
1370 | rate_idx = 3; | ||
1371 | break; | ||
1372 | case 6000: | ||
1373 | rate_idx = 4; | ||
1374 | break; | ||
1375 | case 9000: | ||
1376 | rate_idx = 5; | ||
1377 | break; | ||
1378 | case 12000: | ||
1379 | rate_idx = 6; | ||
1380 | break; | ||
1381 | case 18000: | ||
1382 | rate_idx = 7; | ||
1383 | break; | ||
1384 | case 24000: | ||
1385 | rate_idx = 8; | ||
1386 | break; | ||
1387 | case 36000: | ||
1388 | rate_idx = 9; | ||
1389 | break; | ||
1390 | case 48000: | ||
1391 | rate_idx = 10; | ||
1392 | break; | ||
1393 | case 54000: | ||
1394 | rate_idx = 11; | ||
1395 | break; | ||
1396 | default: | ||
1397 | break; | ||
1398 | } | ||
1399 | |||
1400 | if (band == IEEE80211_BAND_5GHZ) { | ||
1401 | if (rate_idx > 3) | ||
1402 | /* Omit CCK rates */ | ||
1403 | rate_idx -= 4; | ||
1404 | else | ||
1405 | rate_idx = 0; | ||
1406 | } | ||
1407 | |||
1408 | return rate_idx; | ||
1409 | } | ||
1410 | |||
1411 | /* If keys are configured, HW decrypts all frames | 1360 | /* If keys are configured, HW decrypts all frames |
1412 | * with protected bit set. Mark such frames as decrypted. | 1361 | * with protected bit set. Mark such frames as decrypted. |
1413 | */ | 1362 | */ |
@@ -1489,6 +1438,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1489 | struct wmi_mgmt_rx_ev_arg arg = {}; | 1438 | struct wmi_mgmt_rx_ev_arg arg = {}; |
1490 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1439 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1491 | struct ieee80211_hdr *hdr; | 1440 | struct ieee80211_hdr *hdr; |
1441 | struct ieee80211_supported_band *sband; | ||
1492 | u32 rx_status; | 1442 | u32 rx_status; |
1493 | u32 channel; | 1443 | u32 channel; |
1494 | u32 phy_mode; | 1444 | u32 phy_mode; |
@@ -1501,6 +1451,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1501 | ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg); | 1451 | ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg); |
1502 | if (ret) { | 1452 | if (ret) { |
1503 | ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret); | 1453 | ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret); |
1454 | dev_kfree_skb(skb); | ||
1504 | return ret; | 1455 | return ret; |
1505 | } | 1456 | } |
1506 | 1457 | ||
@@ -1559,9 +1510,11 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1559 | if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ) | 1510 | if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ) |
1560 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); | 1511 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); |
1561 | 1512 | ||
1513 | sband = &ar->mac.sbands[status->band]; | ||
1514 | |||
1562 | status->freq = ieee80211_channel_to_frequency(channel, status->band); | 1515 | status->freq = ieee80211_channel_to_frequency(channel, status->band); |
1563 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; | 1516 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; |
1564 | status->rate_idx = get_rate_idx(rate, status->band); | 1517 | status->rate_idx = ath10k_mac_bitrate_to_idx(sband, rate / 100); |
1565 | 1518 | ||
1566 | hdr = (struct ieee80211_hdr *)skb->data; | 1519 | hdr = (struct ieee80211_hdr *)skb->data; |
1567 | fc = le16_to_cpu(hdr->frame_control); | 1520 | fc = le16_to_cpu(hdr->frame_control); |
@@ -1585,6 +1538,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1585 | } | 1538 | } |
1586 | } | 1539 | } |
1587 | 1540 | ||
1541 | if (ieee80211_is_beacon(hdr->frame_control)) | ||
1542 | ath10k_mac_handle_beacon(ar, skb); | ||
1543 | |||
1588 | ath10k_dbg(ar, ATH10K_DBG_MGMT, | 1544 | ath10k_dbg(ar, ATH10K_DBG_MGMT, |
1589 | "event mgmt rx skb %p len %d ftype %02x stype %02x\n", | 1545 | "event mgmt rx skb %p len %d ftype %02x stype %02x\n", |
1590 | skb, skb->len, | 1546 | skb, skb->len, |
@@ -1682,20 +1638,22 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) | |||
1682 | } | 1638 | } |
1683 | 1639 | ||
1684 | if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { | 1640 | if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { |
1685 | /* During scanning chan info is reported twice for each | 1641 | if (ar->ch_info_can_report_survey) { |
1686 | * visited channel. The reported cycle count is global | 1642 | survey = &ar->survey[idx]; |
1687 | * and per-channel cycle count must be calculated */ | 1643 | survey->noise = noise_floor; |
1688 | 1644 | survey->filled = SURVEY_INFO_NOISE_DBM; | |
1689 | cycle_count -= ar->survey_last_cycle_count; | 1645 | |
1690 | rx_clear_count -= ar->survey_last_rx_clear_count; | 1646 | ath10k_hw_fill_survey_time(ar, |
1691 | 1647 | survey, | |
1692 | survey = &ar->survey[idx]; | 1648 | cycle_count, |
1693 | survey->time = WMI_CHAN_INFO_MSEC(cycle_count); | 1649 | rx_clear_count, |
1694 | survey->time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count); | 1650 | ar->survey_last_cycle_count, |
1695 | survey->noise = noise_floor; | 1651 | ar->survey_last_rx_clear_count); |
1696 | survey->filled = SURVEY_INFO_TIME | | 1652 | } |
1697 | SURVEY_INFO_TIME_RX | | 1653 | |
1698 | SURVEY_INFO_NOISE_DBM; | 1654 | ar->ch_info_can_report_survey = false; |
1655 | } else { | ||
1656 | ar->ch_info_can_report_survey = true; | ||
1699 | } | 1657 | } |
1700 | 1658 | ||
1701 | ar->survey_last_rx_clear_count = rx_clear_count; | 1659 | ar->survey_last_rx_clear_count = rx_clear_count; |
@@ -2276,109 +2234,25 @@ static void ath10k_wmi_update_tim(struct ath10k *ar, | |||
2276 | tim->bitmap_ctrl, pvm_len); | 2234 | tim->bitmap_ctrl, pvm_len); |
2277 | } | 2235 | } |
2278 | 2236 | ||
2279 | static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len, | ||
2280 | const struct wmi_p2p_noa_info *noa) | ||
2281 | { | ||
2282 | struct ieee80211_p2p_noa_attr *noa_attr; | ||
2283 | u8 ctwindow_oppps = noa->ctwindow_oppps; | ||
2284 | u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET; | ||
2285 | bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT); | ||
2286 | __le16 *noa_attr_len; | ||
2287 | u16 attr_len; | ||
2288 | u8 noa_descriptors = noa->num_descriptors; | ||
2289 | int i; | ||
2290 | |||
2291 | /* P2P IE */ | ||
2292 | data[0] = WLAN_EID_VENDOR_SPECIFIC; | ||
2293 | data[1] = len - 2; | ||
2294 | data[2] = (WLAN_OUI_WFA >> 16) & 0xff; | ||
2295 | data[3] = (WLAN_OUI_WFA >> 8) & 0xff; | ||
2296 | data[4] = (WLAN_OUI_WFA >> 0) & 0xff; | ||
2297 | data[5] = WLAN_OUI_TYPE_WFA_P2P; | ||
2298 | |||
2299 | /* NOA ATTR */ | ||
2300 | data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE; | ||
2301 | noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */ | ||
2302 | noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9]; | ||
2303 | |||
2304 | noa_attr->index = noa->index; | ||
2305 | noa_attr->oppps_ctwindow = ctwindow; | ||
2306 | if (oppps) | ||
2307 | noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
2308 | |||
2309 | for (i = 0; i < noa_descriptors; i++) { | ||
2310 | noa_attr->desc[i].count = | ||
2311 | __le32_to_cpu(noa->descriptors[i].type_count); | ||
2312 | noa_attr->desc[i].duration = noa->descriptors[i].duration; | ||
2313 | noa_attr->desc[i].interval = noa->descriptors[i].interval; | ||
2314 | noa_attr->desc[i].start_time = noa->descriptors[i].start_time; | ||
2315 | } | ||
2316 | |||
2317 | attr_len = 2; /* index + oppps_ctwindow */ | ||
2318 | attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); | ||
2319 | *noa_attr_len = __cpu_to_le16(attr_len); | ||
2320 | } | ||
2321 | |||
2322 | static u32 ath10k_p2p_calc_noa_ie_len(const struct wmi_p2p_noa_info *noa) | ||
2323 | { | ||
2324 | u32 len = 0; | ||
2325 | u8 noa_descriptors = noa->num_descriptors; | ||
2326 | u8 opp_ps_info = noa->ctwindow_oppps; | ||
2327 | bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT); | ||
2328 | |||
2329 | if (!noa_descriptors && !opps_enabled) | ||
2330 | return len; | ||
2331 | |||
2332 | len += 1 + 1 + 4; /* EID + len + OUI */ | ||
2333 | len += 1 + 2; /* noa attr + attr len */ | ||
2334 | len += 1 + 1; /* index + oppps_ctwindow */ | ||
2335 | len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); | ||
2336 | |||
2337 | return len; | ||
2338 | } | ||
2339 | |||
2340 | static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, | 2237 | static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, |
2341 | struct sk_buff *bcn, | 2238 | struct sk_buff *bcn, |
2342 | const struct wmi_p2p_noa_info *noa) | 2239 | const struct wmi_p2p_noa_info *noa) |
2343 | { | 2240 | { |
2344 | u8 *new_data, *old_data = arvif->u.ap.noa_data; | ||
2345 | u32 new_len; | ||
2346 | |||
2347 | if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) | 2241 | if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) |
2348 | return; | 2242 | return; |
2349 | 2243 | ||
2350 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); | 2244 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); |
2351 | if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) { | ||
2352 | new_len = ath10k_p2p_calc_noa_ie_len(noa); | ||
2353 | if (!new_len) | ||
2354 | goto cleanup; | ||
2355 | |||
2356 | new_data = kmalloc(new_len, GFP_ATOMIC); | ||
2357 | if (!new_data) | ||
2358 | goto cleanup; | ||
2359 | |||
2360 | ath10k_p2p_fill_noa_ie(new_data, new_len, noa); | ||
2361 | 2245 | ||
2362 | spin_lock_bh(&ar->data_lock); | 2246 | if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) |
2363 | arvif->u.ap.noa_data = new_data; | 2247 | ath10k_p2p_noa_update(arvif, noa); |
2364 | arvif->u.ap.noa_len = new_len; | ||
2365 | spin_unlock_bh(&ar->data_lock); | ||
2366 | kfree(old_data); | ||
2367 | } | ||
2368 | 2248 | ||
2369 | if (arvif->u.ap.noa_data) | 2249 | if (arvif->u.ap.noa_data) |
2370 | if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) | 2250 | if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) |
2371 | memcpy(skb_put(bcn, arvif->u.ap.noa_len), | 2251 | memcpy(skb_put(bcn, arvif->u.ap.noa_len), |
2372 | arvif->u.ap.noa_data, | 2252 | arvif->u.ap.noa_data, |
2373 | arvif->u.ap.noa_len); | 2253 | arvif->u.ap.noa_len); |
2374 | return; | ||
2375 | 2254 | ||
2376 | cleanup: | 2255 | return; |
2377 | spin_lock_bh(&ar->data_lock); | ||
2378 | arvif->u.ap.noa_data = NULL; | ||
2379 | arvif->u.ap.noa_len = 0; | ||
2380 | spin_unlock_bh(&ar->data_lock); | ||
2381 | kfree(old_data); | ||
2382 | } | 2256 | } |
2383 | 2257 | ||
2384 | static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, | 2258 | static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, |
@@ -2555,6 +2429,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
2555 | u64 tsf) | 2429 | u64 tsf) |
2556 | { | 2430 | { |
2557 | u32 reg0, reg1, tsf32l; | 2431 | u32 reg0, reg1, tsf32l; |
2432 | struct ieee80211_channel *ch; | ||
2558 | struct pulse_event pe; | 2433 | struct pulse_event pe; |
2559 | u64 tsf64; | 2434 | u64 tsf64; |
2560 | u8 rssi, width; | 2435 | u8 rssi, width; |
@@ -2583,6 +2458,15 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
2583 | if (!ar->dfs_detector) | 2458 | if (!ar->dfs_detector) |
2584 | return; | 2459 | return; |
2585 | 2460 | ||
2461 | spin_lock_bh(&ar->data_lock); | ||
2462 | ch = ar->rx_channel; | ||
2463 | spin_unlock_bh(&ar->data_lock); | ||
2464 | |||
2465 | if (!ch) { | ||
2466 | ath10k_warn(ar, "failed to derive channel for radar pulse, treating as radar\n"); | ||
2467 | goto radar_detected; | ||
2468 | } | ||
2469 | |||
2586 | /* report event to DFS pattern detector */ | 2470 | /* report event to DFS pattern detector */ |
2587 | tsf32l = __le32_to_cpu(phyerr->tsf_timestamp); | 2471 | tsf32l = __le32_to_cpu(phyerr->tsf_timestamp); |
2588 | tsf64 = tsf & (~0xFFFFFFFFULL); | 2472 | tsf64 = tsf & (~0xFFFFFFFFULL); |
@@ -2598,10 +2482,10 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
2598 | rssi = 0; | 2482 | rssi = 0; |
2599 | 2483 | ||
2600 | pe.ts = tsf64; | 2484 | pe.ts = tsf64; |
2601 | pe.freq = ar->hw->conf.chandef.chan->center_freq; | 2485 | pe.freq = ch->center_freq; |
2602 | pe.width = width; | 2486 | pe.width = width; |
2603 | pe.rssi = rssi; | 2487 | pe.rssi = rssi; |
2604 | 2488 | pe.chirp = (MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP) != 0); | |
2605 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 2489 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, |
2606 | "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n", | 2490 | "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n", |
2607 | pe.freq, pe.width, pe.rssi, pe.ts); | 2491 | pe.freq, pe.width, pe.rssi, pe.ts); |
@@ -2614,6 +2498,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
2614 | return; | 2498 | return; |
2615 | } | 2499 | } |
2616 | 2500 | ||
2501 | radar_detected: | ||
2617 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n"); | 2502 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n"); |
2618 | ATH10K_DFS_STAT_INC(ar, radar_detected); | 2503 | ATH10K_DFS_STAT_INC(ar, radar_detected); |
2619 | 2504 | ||
@@ -2872,7 +2757,43 @@ void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | |||
2872 | 2757 | ||
2873 | void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) | 2758 | void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) |
2874 | { | 2759 | { |
2875 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n"); | 2760 | struct wmi_roam_ev_arg arg = {}; |
2761 | int ret; | ||
2762 | u32 vdev_id; | ||
2763 | u32 reason; | ||
2764 | s32 rssi; | ||
2765 | |||
2766 | ret = ath10k_wmi_pull_roam_ev(ar, skb, &arg); | ||
2767 | if (ret) { | ||
2768 | ath10k_warn(ar, "failed to parse roam event: %d\n", ret); | ||
2769 | return; | ||
2770 | } | ||
2771 | |||
2772 | vdev_id = __le32_to_cpu(arg.vdev_id); | ||
2773 | reason = __le32_to_cpu(arg.reason); | ||
2774 | rssi = __le32_to_cpu(arg.rssi); | ||
2775 | rssi += WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT; | ||
2776 | |||
2777 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
2778 | "wmi roam event vdev %u reason 0x%08x rssi %d\n", | ||
2779 | vdev_id, reason, rssi); | ||
2780 | |||
2781 | if (reason >= WMI_ROAM_REASON_MAX) | ||
2782 | ath10k_warn(ar, "ignoring unknown roam event reason %d on vdev %i\n", | ||
2783 | reason, vdev_id); | ||
2784 | |||
2785 | switch (reason) { | ||
2786 | case WMI_ROAM_REASON_BEACON_MISS: | ||
2787 | ath10k_mac_handle_beacon_miss(ar, vdev_id); | ||
2788 | break; | ||
2789 | case WMI_ROAM_REASON_BETTER_AP: | ||
2790 | case WMI_ROAM_REASON_LOW_RSSI: | ||
2791 | case WMI_ROAM_REASON_SUITABLE_AP_FOUND: | ||
2792 | case WMI_ROAM_REASON_HO_FAILED: | ||
2793 | ath10k_warn(ar, "ignoring not implemented roam event reason %d on vdev %i\n", | ||
2794 | reason, vdev_id); | ||
2795 | break; | ||
2796 | } | ||
2876 | } | 2797 | } |
2877 | 2798 | ||
2878 | void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb) | 2799 | void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb) |
@@ -2942,7 +2863,19 @@ void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, struct sk_buff *skb) | |||
2942 | 2863 | ||
2943 | void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb) | 2864 | void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb) |
2944 | { | 2865 | { |
2945 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n"); | 2866 | struct wmi_wow_ev_arg ev = {}; |
2867 | int ret; | ||
2868 | |||
2869 | complete(&ar->wow.wakeup_completed); | ||
2870 | |||
2871 | ret = ath10k_wmi_pull_wow_event(ar, skb, &ev); | ||
2872 | if (ret) { | ||
2873 | ath10k_warn(ar, "failed to parse wow wakeup event: %d\n", ret); | ||
2874 | return; | ||
2875 | } | ||
2876 | |||
2877 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wow wakeup host reason %s\n", | ||
2878 | wow_reason(ev.wake_reason)); | ||
2946 | } | 2879 | } |
2947 | 2880 | ||
2948 | void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb) | 2881 | void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb) |
@@ -3231,6 +3164,21 @@ static int ath10k_wmi_op_pull_rdy_ev(struct ath10k *ar, struct sk_buff *skb, | |||
3231 | return 0; | 3164 | return 0; |
3232 | } | 3165 | } |
3233 | 3166 | ||
3167 | static int ath10k_wmi_op_pull_roam_ev(struct ath10k *ar, struct sk_buff *skb, | ||
3168 | struct wmi_roam_ev_arg *arg) | ||
3169 | { | ||
3170 | struct wmi_roam_ev *ev = (void *)skb->data; | ||
3171 | |||
3172 | if (skb->len < sizeof(*ev)) | ||
3173 | return -EPROTO; | ||
3174 | |||
3175 | skb_pull(skb, sizeof(*ev)); | ||
3176 | arg->vdev_id = ev->vdev_id; | ||
3177 | arg->reason = ev->reason; | ||
3178 | |||
3179 | return 0; | ||
3180 | } | ||
3181 | |||
3234 | int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb) | 3182 | int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb) |
3235 | { | 3183 | { |
3236 | struct wmi_rdy_ev_arg arg = {}; | 3184 | struct wmi_rdy_ev_arg arg = {}; |
@@ -3275,7 +3223,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3275 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 3223 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
3276 | 3224 | ||
3277 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 3225 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
3278 | return; | 3226 | goto out; |
3279 | 3227 | ||
3280 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 3228 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
3281 | 3229 | ||
@@ -3379,6 +3327,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3379 | break; | 3327 | break; |
3380 | } | 3328 | } |
3381 | 3329 | ||
3330 | out: | ||
3382 | dev_kfree_skb(skb); | 3331 | dev_kfree_skb(skb); |
3383 | } | 3332 | } |
3384 | 3333 | ||
@@ -3392,7 +3341,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3392 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 3341 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
3393 | 3342 | ||
3394 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 3343 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
3395 | return; | 3344 | goto out; |
3396 | 3345 | ||
3397 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 3346 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
3398 | 3347 | ||
@@ -3515,7 +3464,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3515 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 3464 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
3516 | 3465 | ||
3517 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 3466 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
3518 | return; | 3467 | goto out; |
3519 | 3468 | ||
3520 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 3469 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
3521 | 3470 | ||
@@ -3623,6 +3572,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
3623 | break; | 3572 | break; |
3624 | } | 3573 | } |
3625 | 3574 | ||
3575 | out: | ||
3626 | dev_kfree_skb(skb); | 3576 | dev_kfree_skb(skb); |
3627 | } | 3577 | } |
3628 | 3578 | ||
@@ -3989,6 +3939,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) | |||
3989 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; | 3939 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; |
3990 | 3940 | ||
3991 | features = WMI_10_2_RX_BATCH_MODE; | 3941 | features = WMI_10_2_RX_BATCH_MODE; |
3942 | if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map)) | ||
3943 | features |= WMI_10_2_COEX_GPIO; | ||
3992 | cmd->resource_config.feature_mask = __cpu_to_le32(features); | 3944 | cmd->resource_config.feature_mask = __cpu_to_le32(features); |
3993 | 3945 | ||
3994 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); | 3946 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); |
@@ -4315,8 +4267,6 @@ ath10k_wmi_op_gen_vdev_start(struct ath10k *ar, | |||
4315 | const char *cmdname; | 4267 | const char *cmdname; |
4316 | u32 flags = 0; | 4268 | u32 flags = 0; |
4317 | 4269 | ||
4318 | if (WARN_ON(arg->ssid && arg->ssid_len == 0)) | ||
4319 | return ERR_PTR(-EINVAL); | ||
4320 | if (WARN_ON(arg->hidden_ssid && !arg->ssid)) | 4270 | if (WARN_ON(arg->hidden_ssid && !arg->ssid)) |
4321 | return ERR_PTR(-EINVAL); | 4271 | return ERR_PTR(-EINVAL); |
4322 | if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) | 4272 | if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) |
@@ -4539,7 +4489,8 @@ ath10k_wmi_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, | |||
4539 | 4489 | ||
4540 | static struct sk_buff * | 4490 | static struct sk_buff * |
4541 | ath10k_wmi_op_gen_peer_create(struct ath10k *ar, u32 vdev_id, | 4491 | ath10k_wmi_op_gen_peer_create(struct ath10k *ar, u32 vdev_id, |
4542 | const u8 peer_addr[ETH_ALEN]) | 4492 | const u8 peer_addr[ETH_ALEN], |
4493 | enum wmi_peer_type peer_type) | ||
4543 | { | 4494 | { |
4544 | struct wmi_peer_create_cmd *cmd; | 4495 | struct wmi_peer_create_cmd *cmd; |
4545 | struct sk_buff *skb; | 4496 | struct sk_buff *skb; |
@@ -5223,6 +5174,7 @@ static const struct wmi_ops wmi_ops = { | |||
5223 | .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev, | 5174 | .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev, |
5224 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, | 5175 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, |
5225 | .pull_fw_stats = ath10k_wmi_main_op_pull_fw_stats, | 5176 | .pull_fw_stats = ath10k_wmi_main_op_pull_fw_stats, |
5177 | .pull_roam_ev = ath10k_wmi_op_pull_roam_ev, | ||
5226 | 5178 | ||
5227 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, | 5179 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, |
5228 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, | 5180 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, |
@@ -5268,6 +5220,7 @@ static const struct wmi_ops wmi_ops = { | |||
5268 | /* .gen_bcn_tmpl not implemented */ | 5220 | /* .gen_bcn_tmpl not implemented */ |
5269 | /* .gen_prb_tmpl not implemented */ | 5221 | /* .gen_prb_tmpl not implemented */ |
5270 | /* .gen_p2p_go_bcn_ie not implemented */ | 5222 | /* .gen_p2p_go_bcn_ie not implemented */ |
5223 | /* .gen_adaptive_qcs not implemented */ | ||
5271 | }; | 5224 | }; |
5272 | 5225 | ||
5273 | static const struct wmi_ops wmi_10_1_ops = { | 5226 | static const struct wmi_ops wmi_10_1_ops = { |
@@ -5290,6 +5243,7 @@ static const struct wmi_ops wmi_10_1_ops = { | |||
5290 | .pull_swba = ath10k_wmi_op_pull_swba_ev, | 5243 | .pull_swba = ath10k_wmi_op_pull_swba_ev, |
5291 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, | 5244 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, |
5292 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, | 5245 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, |
5246 | .pull_roam_ev = ath10k_wmi_op_pull_roam_ev, | ||
5293 | 5247 | ||
5294 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, | 5248 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, |
5295 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, | 5249 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, |
@@ -5330,6 +5284,7 @@ static const struct wmi_ops wmi_10_1_ops = { | |||
5330 | /* .gen_bcn_tmpl not implemented */ | 5284 | /* .gen_bcn_tmpl not implemented */ |
5331 | /* .gen_prb_tmpl not implemented */ | 5285 | /* .gen_prb_tmpl not implemented */ |
5332 | /* .gen_p2p_go_bcn_ie not implemented */ | 5286 | /* .gen_p2p_go_bcn_ie not implemented */ |
5287 | /* .gen_adaptive_qcs not implemented */ | ||
5333 | }; | 5288 | }; |
5334 | 5289 | ||
5335 | static const struct wmi_ops wmi_10_2_ops = { | 5290 | static const struct wmi_ops wmi_10_2_ops = { |
@@ -5353,6 +5308,7 @@ static const struct wmi_ops wmi_10_2_ops = { | |||
5353 | .pull_swba = ath10k_wmi_op_pull_swba_ev, | 5308 | .pull_swba = ath10k_wmi_op_pull_swba_ev, |
5354 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, | 5309 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, |
5355 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, | 5310 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, |
5311 | .pull_roam_ev = ath10k_wmi_op_pull_roam_ev, | ||
5356 | 5312 | ||
5357 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, | 5313 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, |
5358 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, | 5314 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, |
@@ -5413,6 +5369,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
5413 | .pull_swba = ath10k_wmi_op_pull_swba_ev, | 5369 | .pull_swba = ath10k_wmi_op_pull_swba_ev, |
5414 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, | 5370 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, |
5415 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, | 5371 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, |
5372 | .pull_roam_ev = ath10k_wmi_op_pull_roam_ev, | ||
5416 | 5373 | ||
5417 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, | 5374 | .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, |
5418 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, | 5375 | .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, |
@@ -5452,6 +5409,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
5452 | /* .gen_bcn_tmpl not implemented */ | 5409 | /* .gen_bcn_tmpl not implemented */ |
5453 | /* .gen_prb_tmpl not implemented */ | 5410 | /* .gen_prb_tmpl not implemented */ |
5454 | /* .gen_p2p_go_bcn_ie not implemented */ | 5411 | /* .gen_p2p_go_bcn_ie not implemented */ |
5412 | /* .gen_adaptive_qcs not implemented */ | ||
5455 | }; | 5413 | }; |
5456 | 5414 | ||
5457 | int ath10k_wmi_attach(struct ath10k *ar) | 5415 | int ath10k_wmi_attach(struct ath10k *ar) |