diff options
65 files changed, 2560 insertions, 788 deletions
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index bd46569e0e52..925842996986 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -295,6 +295,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { | |||
295 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, | 295 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, |
296 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) }, | 296 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) }, |
297 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) }, | 297 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) }, |
298 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) }, | ||
298 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) }, | 299 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) }, |
299 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, | 300 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, |
300 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, | 301 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7005e2a98726..749e381edd38 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -326,6 +326,7 @@ static const char *const ath10k_core_fw_feature_str[] = { | |||
326 | [ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl", | 326 | [ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl", |
327 | [ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param", | 327 | [ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param", |
328 | [ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war", | 328 | [ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war", |
329 | [ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast", | ||
329 | }; | 330 | }; |
330 | 331 | ||
331 | static unsigned int ath10k_core_get_fw_feature_str(char *buf, | 332 | static unsigned int ath10k_core_get_fw_feature_str(char *buf, |
@@ -1536,7 +1537,7 @@ static void ath10k_core_restart(struct work_struct *work) | |||
1536 | switch (ar->state) { | 1537 | switch (ar->state) { |
1537 | case ATH10K_STATE_ON: | 1538 | case ATH10K_STATE_ON: |
1538 | ar->state = ATH10K_STATE_RESTARTING; | 1539 | ar->state = ATH10K_STATE_RESTARTING; |
1539 | ath10k_hif_stop(ar); | 1540 | ath10k_halt(ar); |
1540 | ath10k_scan_finish(ar); | 1541 | ath10k_scan_finish(ar); |
1541 | ieee80211_restart_hw(ar->hw); | 1542 | ieee80211_restart_hw(ar->hw); |
1542 | break; | 1543 | break; |
@@ -1857,7 +1858,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, | |||
1857 | goto err_wmi_detach; | 1858 | goto err_wmi_detach; |
1858 | } | 1859 | } |
1859 | 1860 | ||
1860 | status = ath10k_htt_tx_alloc(&ar->htt); | 1861 | status = ath10k_htt_tx_start(&ar->htt); |
1861 | if (status) { | 1862 | if (status) { |
1862 | ath10k_err(ar, "failed to alloc htt tx: %d\n", status); | 1863 | ath10k_err(ar, "failed to alloc htt tx: %d\n", status); |
1863 | goto err_wmi_detach; | 1864 | goto err_wmi_detach; |
@@ -2052,7 +2053,7 @@ void ath10k_core_stop(struct ath10k *ar) | |||
2052 | ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR); | 2053 | ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR); |
2053 | 2054 | ||
2054 | ath10k_hif_stop(ar); | 2055 | ath10k_hif_stop(ar); |
2055 | ath10k_htt_tx_free(&ar->htt); | 2056 | ath10k_htt_tx_stop(&ar->htt); |
2056 | ath10k_htt_rx_free(&ar->htt); | 2057 | ath10k_htt_rx_free(&ar->htt); |
2057 | ath10k_wmi_detach(ar); | 2058 | ath10k_wmi_detach(ar); |
2058 | } | 2059 | } |
@@ -2385,6 +2386,7 @@ void ath10k_core_destroy(struct ath10k *ar) | |||
2385 | destroy_workqueue(ar->workqueue_aux); | 2386 | destroy_workqueue(ar->workqueue_aux); |
2386 | 2387 | ||
2387 | ath10k_debug_destroy(ar); | 2388 | ath10k_debug_destroy(ar); |
2389 | ath10k_htt_tx_destroy(&ar->htt); | ||
2388 | ath10k_wmi_free_host_mem(ar); | 2390 | ath10k_wmi_free_host_mem(ar); |
2389 | ath10k_mac_destroy(ar); | 2391 | ath10k_mac_destroy(ar); |
2390 | } | 2392 | } |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e8decfaba5b6..09ff8b8a6441 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -337,6 +337,7 @@ struct ath10k_sta { | |||
337 | u32 nss; | 337 | u32 nss; |
338 | u32 smps; | 338 | u32 smps; |
339 | u16 peer_id; | 339 | u16 peer_id; |
340 | struct rate_info txrate; | ||
340 | 341 | ||
341 | struct work_struct update_wk; | 342 | struct work_struct update_wk; |
342 | 343 | ||
@@ -562,6 +563,13 @@ enum ath10k_fw_features { | |||
562 | */ | 563 | */ |
563 | ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15, | 564 | ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15, |
564 | 565 | ||
566 | /* Firmware allow other BSS mesh broadcast/multicast frames without | ||
567 | * creating monitor interface. Appropriate rxfilters are programmed for | ||
568 | * mesh vdev by firmware itself. This feature flags will be used for | ||
569 | * not creating monitor vdev while configuring mesh node. | ||
570 | */ | ||
571 | ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16, | ||
572 | |||
565 | /* keep last */ | 573 | /* keep last */ |
566 | ATH10K_FW_FEATURE_COUNT, | 574 | ATH10K_FW_FEATURE_COUNT, |
567 | }; | 575 | }; |
@@ -693,6 +701,21 @@ struct ath10k_fw_components { | |||
693 | struct ath10k_fw_file fw_file; | 701 | struct ath10k_fw_file fw_file; |
694 | }; | 702 | }; |
695 | 703 | ||
704 | struct ath10k_per_peer_tx_stats { | ||
705 | u32 succ_bytes; | ||
706 | u32 retry_bytes; | ||
707 | u32 failed_bytes; | ||
708 | u8 ratecode; | ||
709 | u8 flags; | ||
710 | u16 peer_id; | ||
711 | u16 succ_pkts; | ||
712 | u16 retry_pkts; | ||
713 | u16 failed_pkts; | ||
714 | u16 duration; | ||
715 | u32 reserved1; | ||
716 | u32 reserved2; | ||
717 | }; | ||
718 | |||
696 | struct ath10k { | 719 | struct ath10k { |
697 | struct ath_common ath_common; | 720 | struct ath_common ath_common; |
698 | struct ieee80211_hw *hw; | 721 | struct ieee80211_hw *hw; |
@@ -906,6 +929,7 @@ struct ath10k { | |||
906 | 929 | ||
907 | struct ath10k_thermal thermal; | 930 | struct ath10k_thermal thermal; |
908 | struct ath10k_wow wow; | 931 | struct ath10k_wow wow; |
932 | struct ath10k_per_peer_tx_stats peer_tx_stats; | ||
909 | 933 | ||
910 | /* NAPI */ | 934 | /* NAPI */ |
911 | struct net_device napi_dev; | 935 | struct net_device napi_dev; |
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 9955fea0802a..fce6f8137d33 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c | |||
@@ -77,6 +77,19 @@ void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
77 | 77 | ||
78 | sinfo->rx_duration = arsta->rx_duration; | 78 | sinfo->rx_duration = arsta->rx_duration; |
79 | sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; | 79 | sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; |
80 | |||
81 | if (!arsta->txrate.legacy && !arsta->txrate.nss) | ||
82 | return; | ||
83 | |||
84 | if (arsta->txrate.legacy) { | ||
85 | sinfo->txrate.legacy = arsta->txrate.legacy; | ||
86 | } else { | ||
87 | sinfo->txrate.mcs = arsta->txrate.mcs; | ||
88 | sinfo->txrate.nss = arsta->txrate.nss; | ||
89 | sinfo->txrate.bw = arsta->txrate.bw; | ||
90 | } | ||
91 | sinfo->txrate.flags = arsta->txrate.flags; | ||
92 | sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE; | ||
80 | } | 93 | } |
81 | 94 | ||
82 | static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, | 95 | static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, |
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 130cd9502021..cd160b16db1e 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c | |||
@@ -137,6 +137,8 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { | |||
137 | HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, | 137 | HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, |
138 | [HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] = | 138 | [HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] = |
139 | HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, | 139 | HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, |
140 | [HTT_10_4_T2H_MSG_TYPE_PEER_STATS] = | ||
141 | HTT_T2H_MSG_TYPE_PEER_STATS, | ||
140 | }; | 142 | }; |
141 | 143 | ||
142 | int ath10k_htt_connect(struct ath10k_htt *htt) | 144 | int ath10k_htt_connect(struct ath10k_htt *htt) |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 0d2ed09f202b..44b25cf00553 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -419,6 +419,7 @@ enum htt_10_4_t2h_msg_type { | |||
419 | HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, | 419 | HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, |
420 | /* 0x19 to 0x2f are reserved */ | 420 | /* 0x19 to 0x2f are reserved */ |
421 | HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30, | 421 | HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30, |
422 | HTT_10_4_T2H_MSG_TYPE_PEER_STATS = 0x31, | ||
422 | /* keep this last */ | 423 | /* keep this last */ |
423 | HTT_10_4_T2H_NUM_MSGS | 424 | HTT_10_4_T2H_NUM_MSGS |
424 | }; | 425 | }; |
@@ -453,6 +454,7 @@ enum htt_t2h_msg_type { | |||
453 | HTT_T2H_MSG_TYPE_TX_FETCH_IND, | 454 | HTT_T2H_MSG_TYPE_TX_FETCH_IND, |
454 | HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, | 455 | HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, |
455 | HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, | 456 | HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, |
457 | HTT_T2H_MSG_TYPE_PEER_STATS, | ||
456 | /* keep this last */ | 458 | /* keep this last */ |
457 | HTT_T2H_NUM_MSGS | 459 | HTT_T2H_NUM_MSGS |
458 | }; | 460 | }; |
@@ -1470,6 +1472,28 @@ struct htt_channel_change { | |||
1470 | __le32 phymode; | 1472 | __le32 phymode; |
1471 | } __packed; | 1473 | } __packed; |
1472 | 1474 | ||
1475 | struct htt_per_peer_tx_stats_ind { | ||
1476 | __le32 succ_bytes; | ||
1477 | __le32 retry_bytes; | ||
1478 | __le32 failed_bytes; | ||
1479 | u8 ratecode; | ||
1480 | u8 flags; | ||
1481 | __le16 peer_id; | ||
1482 | __le16 succ_pkts; | ||
1483 | __le16 retry_pkts; | ||
1484 | __le16 failed_pkts; | ||
1485 | __le16 tx_duration; | ||
1486 | __le32 reserved1; | ||
1487 | __le32 reserved2; | ||
1488 | } __packed; | ||
1489 | |||
1490 | struct htt_peer_tx_stats { | ||
1491 | u8 num_ppdu; | ||
1492 | u8 ppdu_len; | ||
1493 | u8 version; | ||
1494 | u8 payload[0]; | ||
1495 | } __packed; | ||
1496 | |||
1473 | union htt_rx_pn_t { | 1497 | union htt_rx_pn_t { |
1474 | /* WEP: 24-bit PN */ | 1498 | /* WEP: 24-bit PN */ |
1475 | u32 pn24; | 1499 | u32 pn24; |
@@ -1521,6 +1545,7 @@ struct htt_resp { | |||
1521 | struct htt_tx_fetch_confirm tx_fetch_confirm; | 1545 | struct htt_tx_fetch_confirm tx_fetch_confirm; |
1522 | struct htt_tx_mode_switch_ind tx_mode_switch_ind; | 1546 | struct htt_tx_mode_switch_ind tx_mode_switch_ind; |
1523 | struct htt_channel_change chan_change; | 1547 | struct htt_channel_change chan_change; |
1548 | struct htt_peer_tx_stats peer_tx_stats; | ||
1524 | }; | 1549 | }; |
1525 | } __packed; | 1550 | } __packed; |
1526 | 1551 | ||
@@ -1692,6 +1717,8 @@ struct ath10k_htt { | |||
1692 | enum htt_tx_mode_switch_mode mode; | 1717 | enum htt_tx_mode_switch_mode mode; |
1693 | enum htt_q_depth_type type; | 1718 | enum htt_q_depth_type type; |
1694 | } tx_q_state; | 1719 | } tx_q_state; |
1720 | |||
1721 | bool tx_mem_allocated; | ||
1695 | }; | 1722 | }; |
1696 | 1723 | ||
1697 | #define RX_HTT_HDR_STATUS_LEN 64 | 1724 | #define RX_HTT_HDR_STATUS_LEN 64 |
@@ -1754,7 +1781,9 @@ int ath10k_htt_connect(struct ath10k_htt *htt); | |||
1754 | int ath10k_htt_init(struct ath10k *ar); | 1781 | int ath10k_htt_init(struct ath10k *ar); |
1755 | int ath10k_htt_setup(struct ath10k_htt *htt); | 1782 | int ath10k_htt_setup(struct ath10k_htt *htt); |
1756 | 1783 | ||
1757 | int ath10k_htt_tx_alloc(struct ath10k_htt *htt); | 1784 | int ath10k_htt_tx_start(struct ath10k_htt *htt); |
1785 | void ath10k_htt_tx_stop(struct ath10k_htt *htt); | ||
1786 | void ath10k_htt_tx_destroy(struct ath10k_htt *htt); | ||
1758 | void ath10k_htt_tx_free(struct ath10k_htt *htt); | 1787 | void ath10k_htt_tx_free(struct ath10k_htt *htt); |
1759 | 1788 | ||
1760 | int ath10k_htt_rx_alloc(struct ath10k_htt *htt); | 1789 | int ath10k_htt_rx_alloc(struct ath10k_htt *htt); |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 285b235268d7..86d082cf4eef 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -2194,6 +2194,128 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
2194 | dev_kfree_skb_any(skb); | 2194 | dev_kfree_skb_any(skb); |
2195 | } | 2195 | } |
2196 | 2196 | ||
2197 | static inline bool is_valid_legacy_rate(u8 rate) | ||
2198 | { | ||
2199 | static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12, | ||
2200 | 18, 24, 36, 48, 54}; | ||
2201 | int i; | ||
2202 | |||
2203 | for (i = 0; i < ARRAY_SIZE(legacy_rates); i++) { | ||
2204 | if (rate == legacy_rates[i]) | ||
2205 | return true; | ||
2206 | } | ||
2207 | |||
2208 | return false; | ||
2209 | } | ||
2210 | |||
2211 | static void | ||
2212 | ath10k_update_per_peer_tx_stats(struct ath10k *ar, | ||
2213 | struct ieee80211_sta *sta, | ||
2214 | struct ath10k_per_peer_tx_stats *peer_stats) | ||
2215 | { | ||
2216 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
2217 | u8 rate = 0, sgi; | ||
2218 | struct rate_info txrate; | ||
2219 | |||
2220 | lockdep_assert_held(&ar->data_lock); | ||
2221 | |||
2222 | txrate.flags = ATH10K_HW_PREAMBLE(peer_stats->ratecode); | ||
2223 | txrate.bw = ATH10K_HW_BW(peer_stats->flags); | ||
2224 | txrate.nss = ATH10K_HW_NSS(peer_stats->ratecode); | ||
2225 | txrate.mcs = ATH10K_HW_MCS_RATE(peer_stats->ratecode); | ||
2226 | sgi = ATH10K_HW_GI(peer_stats->flags); | ||
2227 | |||
2228 | if (((txrate.flags == WMI_RATE_PREAMBLE_HT) || | ||
2229 | (txrate.flags == WMI_RATE_PREAMBLE_VHT)) && txrate.mcs > 9) { | ||
2230 | ath10k_warn(ar, "Invalid mcs %hhd peer stats", txrate.mcs); | ||
2231 | return; | ||
2232 | } | ||
2233 | |||
2234 | if (txrate.flags == WMI_RATE_PREAMBLE_CCK || | ||
2235 | txrate.flags == WMI_RATE_PREAMBLE_OFDM) { | ||
2236 | rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode); | ||
2237 | |||
2238 | if (!is_valid_legacy_rate(rate)) { | ||
2239 | ath10k_warn(ar, "Invalid legacy rate %hhd peer stats", | ||
2240 | rate); | ||
2241 | return; | ||
2242 | } | ||
2243 | |||
2244 | /* This is hacky, FW sends CCK rate 5.5Mbps as 6 */ | ||
2245 | rate *= 10; | ||
2246 | if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK) | ||
2247 | rate = rate - 5; | ||
2248 | arsta->txrate.legacy = rate * 10; | ||
2249 | } else if (txrate.flags == WMI_RATE_PREAMBLE_HT) { | ||
2250 | arsta->txrate.flags = RATE_INFO_FLAGS_MCS; | ||
2251 | arsta->txrate.mcs = txrate.mcs; | ||
2252 | } else { | ||
2253 | arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; | ||
2254 | arsta->txrate.mcs = txrate.mcs; | ||
2255 | } | ||
2256 | |||
2257 | if (sgi) | ||
2258 | arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
2259 | |||
2260 | arsta->txrate.nss = txrate.nss; | ||
2261 | arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20; | ||
2262 | } | ||
2263 | |||
2264 | static void ath10k_htt_fetch_peer_stats(struct ath10k *ar, | ||
2265 | struct sk_buff *skb) | ||
2266 | { | ||
2267 | struct htt_resp *resp = (struct htt_resp *)skb->data; | ||
2268 | struct ath10k_per_peer_tx_stats *p_tx_stats = &ar->peer_tx_stats; | ||
2269 | struct htt_per_peer_tx_stats_ind *tx_stats; | ||
2270 | struct ieee80211_sta *sta; | ||
2271 | struct ath10k_peer *peer; | ||
2272 | int peer_id, i; | ||
2273 | u8 ppdu_len, num_ppdu; | ||
2274 | |||
2275 | num_ppdu = resp->peer_tx_stats.num_ppdu; | ||
2276 | ppdu_len = resp->peer_tx_stats.ppdu_len * sizeof(__le32); | ||
2277 | |||
2278 | if (skb->len < sizeof(struct htt_resp_hdr) + num_ppdu * ppdu_len) { | ||
2279 | ath10k_warn(ar, "Invalid peer stats buf length %d\n", skb->len); | ||
2280 | return; | ||
2281 | } | ||
2282 | |||
2283 | tx_stats = (struct htt_per_peer_tx_stats_ind *) | ||
2284 | (resp->peer_tx_stats.payload); | ||
2285 | peer_id = __le16_to_cpu(tx_stats->peer_id); | ||
2286 | |||
2287 | rcu_read_lock(); | ||
2288 | spin_lock_bh(&ar->data_lock); | ||
2289 | peer = ath10k_peer_find_by_id(ar, peer_id); | ||
2290 | if (!peer) { | ||
2291 | ath10k_warn(ar, "Invalid peer id %d peer stats buffer\n", | ||
2292 | peer_id); | ||
2293 | goto out; | ||
2294 | } | ||
2295 | |||
2296 | sta = peer->sta; | ||
2297 | for (i = 0; i < num_ppdu; i++) { | ||
2298 | tx_stats = (struct htt_per_peer_tx_stats_ind *) | ||
2299 | (resp->peer_tx_stats.payload + i * ppdu_len); | ||
2300 | |||
2301 | p_tx_stats->succ_bytes = __le32_to_cpu(tx_stats->succ_bytes); | ||
2302 | p_tx_stats->retry_bytes = __le32_to_cpu(tx_stats->retry_bytes); | ||
2303 | p_tx_stats->failed_bytes = | ||
2304 | __le32_to_cpu(tx_stats->failed_bytes); | ||
2305 | p_tx_stats->ratecode = tx_stats->ratecode; | ||
2306 | p_tx_stats->flags = tx_stats->flags; | ||
2307 | p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts); | ||
2308 | p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts); | ||
2309 | p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts); | ||
2310 | |||
2311 | ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats); | ||
2312 | } | ||
2313 | |||
2314 | out: | ||
2315 | spin_unlock_bh(&ar->data_lock); | ||
2316 | rcu_read_unlock(); | ||
2317 | } | ||
2318 | |||
2197 | bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | 2319 | bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) |
2198 | { | 2320 | { |
2199 | struct ath10k_htt *htt = &ar->htt; | 2321 | struct ath10k_htt *htt = &ar->htt; |
@@ -2354,6 +2476,9 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
2354 | case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: | 2476 | case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: |
2355 | ath10k_htt_rx_tx_mode_switch_ind(ar, skb); | 2477 | ath10k_htt_rx_tx_mode_switch_ind(ar, skb); |
2356 | break; | 2478 | break; |
2479 | case HTT_T2H_MSG_TYPE_PEER_STATS: | ||
2480 | ath10k_htt_fetch_peer_stats(ar, skb); | ||
2481 | break; | ||
2357 | case HTT_T2H_MSG_TYPE_EN_STATS: | 2482 | case HTT_T2H_MSG_TYPE_EN_STATS: |
2358 | default: | 2483 | default: |
2359 | ath10k_warn(ar, "htt event (%d) not handled\n", | 2484 | ath10k_warn(ar, "htt event (%d) not handled\n", |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index ccbc8c03abc1..27e49db4287a 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -350,21 +350,15 @@ static int ath10k_htt_tx_alloc_txdone_fifo(struct ath10k_htt *htt) | |||
350 | return ret; | 350 | return ret; |
351 | } | 351 | } |
352 | 352 | ||
353 | int ath10k_htt_tx_alloc(struct ath10k_htt *htt) | 353 | static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt) |
354 | { | 354 | { |
355 | struct ath10k *ar = htt->ar; | 355 | struct ath10k *ar = htt->ar; |
356 | int ret; | 356 | int ret; |
357 | 357 | ||
358 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", | ||
359 | htt->max_num_pending_tx); | ||
360 | |||
361 | spin_lock_init(&htt->tx_lock); | ||
362 | idr_init(&htt->pending_tx); | ||
363 | |||
364 | ret = ath10k_htt_tx_alloc_cont_txbuf(htt); | 358 | ret = ath10k_htt_tx_alloc_cont_txbuf(htt); |
365 | if (ret) { | 359 | if (ret) { |
366 | ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret); | 360 | ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret); |
367 | goto free_idr_pending_tx; | 361 | return ret; |
368 | } | 362 | } |
369 | 363 | ||
370 | ret = ath10k_htt_tx_alloc_cont_frag_desc(htt); | 364 | ret = ath10k_htt_tx_alloc_cont_frag_desc(htt); |
@@ -396,6 +390,31 @@ free_frag_desc: | |||
396 | free_txbuf: | 390 | free_txbuf: |
397 | ath10k_htt_tx_free_cont_txbuf(htt); | 391 | ath10k_htt_tx_free_cont_txbuf(htt); |
398 | 392 | ||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | int ath10k_htt_tx_start(struct ath10k_htt *htt) | ||
397 | { | ||
398 | struct ath10k *ar = htt->ar; | ||
399 | int ret; | ||
400 | |||
401 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", | ||
402 | htt->max_num_pending_tx); | ||
403 | |||
404 | spin_lock_init(&htt->tx_lock); | ||
405 | idr_init(&htt->pending_tx); | ||
406 | |||
407 | if (htt->tx_mem_allocated) | ||
408 | return 0; | ||
409 | |||
410 | ret = ath10k_htt_tx_alloc_buf(htt); | ||
411 | if (ret) | ||
412 | goto free_idr_pending_tx; | ||
413 | |||
414 | htt->tx_mem_allocated = true; | ||
415 | |||
416 | return 0; | ||
417 | |||
399 | free_idr_pending_tx: | 418 | free_idr_pending_tx: |
400 | idr_destroy(&htt->pending_tx); | 419 | idr_destroy(&htt->pending_tx); |
401 | 420 | ||
@@ -418,15 +437,28 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) | |||
418 | return 0; | 437 | return 0; |
419 | } | 438 | } |
420 | 439 | ||
421 | void ath10k_htt_tx_free(struct ath10k_htt *htt) | 440 | void ath10k_htt_tx_destroy(struct ath10k_htt *htt) |
422 | { | 441 | { |
423 | idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); | 442 | if (!htt->tx_mem_allocated) |
424 | idr_destroy(&htt->pending_tx); | 443 | return; |
425 | 444 | ||
426 | ath10k_htt_tx_free_cont_txbuf(htt); | 445 | ath10k_htt_tx_free_cont_txbuf(htt); |
427 | ath10k_htt_tx_free_txq(htt); | 446 | ath10k_htt_tx_free_txq(htt); |
428 | ath10k_htt_tx_free_cont_frag_desc(htt); | 447 | ath10k_htt_tx_free_cont_frag_desc(htt); |
429 | ath10k_htt_tx_free_txdone_fifo(htt); | 448 | ath10k_htt_tx_free_txdone_fifo(htt); |
449 | htt->tx_mem_allocated = false; | ||
450 | } | ||
451 | |||
452 | void ath10k_htt_tx_stop(struct ath10k_htt *htt) | ||
453 | { | ||
454 | idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); | ||
455 | idr_destroy(&htt->pending_tx); | ||
456 | } | ||
457 | |||
458 | void ath10k_htt_tx_free(struct ath10k_htt *htt) | ||
459 | { | ||
460 | ath10k_htt_tx_stop(htt); | ||
461 | ath10k_htt_tx_destroy(htt); | ||
430 | } | 462 | } |
431 | 463 | ||
432 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) | 464 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 717b2fad9a8a..aa545a1dbdc7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -1167,7 +1167,9 @@ static bool ath10k_mac_monitor_vdev_is_needed(struct ath10k *ar) | |||
1167 | return false; | 1167 | return false; |
1168 | 1168 | ||
1169 | return ar->monitor || | 1169 | return ar->monitor || |
1170 | ar->filter_flags & FIF_OTHER_BSS || | 1170 | (!test_bit(ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST, |
1171 | ar->running_fw->fw_file.fw_features) && | ||
1172 | (ar->filter_flags & FIF_OTHER_BSS)) || | ||
1171 | test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); | 1173 | test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); |
1172 | } | 1174 | } |
1173 | 1175 | ||
@@ -4449,7 +4451,6 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
4449 | ar->state = ATH10K_STATE_ON; | 4451 | ar->state = ATH10K_STATE_ON; |
4450 | break; | 4452 | break; |
4451 | case ATH10K_STATE_RESTARTING: | 4453 | case ATH10K_STATE_RESTARTING: |
4452 | ath10k_halt(ar); | ||
4453 | ar->state = ATH10K_STATE_RESTARTED; | 4454 | ar->state = ATH10K_STATE_RESTARTED; |
4454 | break; | 4455 | break; |
4455 | case ATH10K_STATE_ON: | 4456 | case ATH10K_STATE_ON: |
@@ -6976,40 +6977,28 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, | |||
6976 | ieee80211_queue_work(hw, &arsta->update_wk); | 6977 | ieee80211_queue_work(hw, &arsta->update_wk); |
6977 | } | 6978 | } |
6978 | 6979 | ||
6979 | static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 6980 | static void ath10k_offset_tsf(struct ieee80211_hw *hw, |
6980 | { | 6981 | struct ieee80211_vif *vif, s64 tsf_offset) |
6981 | /* | ||
6982 | * FIXME: Return 0 for time being. Need to figure out whether FW | ||
6983 | * has the API to fetch 64-bit local TSF | ||
6984 | */ | ||
6985 | |||
6986 | return 0; | ||
6987 | } | ||
6988 | |||
6989 | static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
6990 | u64 tsf) | ||
6991 | { | 6982 | { |
6992 | struct ath10k *ar = hw->priv; | 6983 | struct ath10k *ar = hw->priv; |
6993 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 6984 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
6994 | u32 tsf_offset, vdev_param = ar->wmi.vdev_param->set_tsf; | 6985 | u32 offset, vdev_param; |
6995 | int ret; | 6986 | int ret; |
6996 | 6987 | ||
6997 | /* Workaround: | 6988 | if (tsf_offset < 0) { |
6998 | * | 6989 | vdev_param = ar->wmi.vdev_param->dec_tsf; |
6999 | * Given tsf argument is entire TSF value, but firmware accepts | 6990 | offset = -tsf_offset; |
7000 | * only TSF offset to current TSF. | 6991 | } else { |
7001 | * | 6992 | vdev_param = ar->wmi.vdev_param->inc_tsf; |
7002 | * get_tsf function is used to get offset value, however since | 6993 | offset = tsf_offset; |
7003 | * ath10k_get_tsf is not implemented properly, it will return 0 always. | 6994 | } |
7004 | * Luckily all the caller functions to set_tsf, as of now, also rely on | 6995 | |
7005 | * get_tsf function to get entire tsf value such get_tsf() + tsf_delta, | ||
7006 | * final tsf offset value to firmware will be arithmetically correct. | ||
7007 | */ | ||
7008 | tsf_offset = tsf - ath10k_get_tsf(hw, vif); | ||
7009 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 6996 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, |
7010 | vdev_param, tsf_offset); | 6997 | vdev_param, offset); |
6998 | |||
7011 | if (ret && ret != -EOPNOTSUPP) | 6999 | if (ret && ret != -EOPNOTSUPP) |
7012 | ath10k_warn(ar, "failed to set tsf offset: %d\n", ret); | 7000 | ath10k_warn(ar, "failed to set tsf offset %d cmd %d: %d\n", |
7001 | offset, vdev_param, ret); | ||
7013 | } | 7002 | } |
7014 | 7003 | ||
7015 | static int ath10k_ampdu_action(struct ieee80211_hw *hw, | 7004 | static int ath10k_ampdu_action(struct ieee80211_hw *hw, |
@@ -7474,8 +7463,7 @@ static const struct ieee80211_ops ath10k_ops = { | |||
7474 | .get_survey = ath10k_get_survey, | 7463 | .get_survey = ath10k_get_survey, |
7475 | .set_bitrate_mask = ath10k_mac_op_set_bitrate_mask, | 7464 | .set_bitrate_mask = ath10k_mac_op_set_bitrate_mask, |
7476 | .sta_rc_update = ath10k_sta_rc_update, | 7465 | .sta_rc_update = ath10k_sta_rc_update, |
7477 | .get_tsf = ath10k_get_tsf, | 7466 | .offset_tsf = ath10k_offset_tsf, |
7478 | .set_tsf = ath10k_set_tsf, | ||
7479 | .ampdu_action = ath10k_ampdu_action, | 7467 | .ampdu_action = ath10k_ampdu_action, |
7480 | .get_et_sset_count = ath10k_debug_get_et_sset_count, | 7468 | .get_et_sset_count = ath10k_debug_get_et_sset_count, |
7481 | .get_et_stats = ath10k_debug_get_et_stats, | 7469 | .get_et_stats = ath10k_debug_get_et_stats, |
@@ -8006,6 +7994,7 @@ int ath10k_mac_register(struct ath10k *ar) | |||
8006 | ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA); | 7994 | ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA); |
8007 | ieee80211_hw_set(ar->hw, QUEUE_CONTROL); | 7995 | ieee80211_hw_set(ar->hw, QUEUE_CONTROL); |
8008 | ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); | 7996 | ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); |
7997 | ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); | ||
8009 | 7998 | ||
8010 | if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) | 7999 | if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) |
8011 | ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL); | 8000 | ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index c9a8bb1186f2..c7956e181f80 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h | |||
@@ -660,6 +660,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar, | |||
660 | struct sk_buff *skb; | 660 | struct sk_buff *skb; |
661 | u32 cmd_id; | 661 | u32 cmd_id; |
662 | 662 | ||
663 | if (!ar->wmi.ops->gen_vdev_spectral_conf) | ||
664 | return -EOPNOTSUPP; | ||
665 | |||
663 | skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg); | 666 | skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg); |
664 | if (IS_ERR(skb)) | 667 | if (IS_ERR(skb)) |
665 | return PTR_ERR(skb); | 668 | return PTR_ERR(skb); |
@@ -675,6 +678,9 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger, | |||
675 | struct sk_buff *skb; | 678 | struct sk_buff *skb; |
676 | u32 cmd_id; | 679 | u32 cmd_id; |
677 | 680 | ||
681 | if (!ar->wmi.ops->gen_vdev_spectral_enable) | ||
682 | return -EOPNOTSUPP; | ||
683 | |||
678 | skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger, | 684 | skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger, |
679 | enable); | 685 | enable); |
680 | if (IS_ERR(skb)) | 686 | if (IS_ERR(skb)) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index e64f59300a7c..f304f6632c4f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
@@ -1313,8 +1313,8 @@ ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar, | |||
1313 | cmd->regd = __cpu_to_le32(rd); | 1313 | cmd->regd = __cpu_to_le32(rd); |
1314 | cmd->regd_2ghz = __cpu_to_le32(rd2g); | 1314 | cmd->regd_2ghz = __cpu_to_le32(rd2g); |
1315 | cmd->regd_5ghz = __cpu_to_le32(rd5g); | 1315 | cmd->regd_5ghz = __cpu_to_le32(rd5g); |
1316 | cmd->conform_limit_2ghz = __cpu_to_le32(rd2g); | 1316 | cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g); |
1317 | cmd->conform_limit_5ghz = __cpu_to_le32(rd5g); | 1317 | cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g); |
1318 | 1318 | ||
1319 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n"); | 1319 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n"); |
1320 | return skb; | 1320 | return skb; |
@@ -3136,6 +3136,76 @@ ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value) | |||
3136 | return skb; | 3136 | return skb; |
3137 | } | 3137 | } |
3138 | 3138 | ||
3139 | static struct sk_buff * | ||
3140 | ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar, | ||
3141 | const struct wmi_vdev_spectral_conf_arg *arg) | ||
3142 | { | ||
3143 | struct wmi_vdev_spectral_conf_cmd *cmd; | ||
3144 | struct sk_buff *skb; | ||
3145 | struct wmi_tlv *tlv; | ||
3146 | void *ptr; | ||
3147 | size_t len; | ||
3148 | |||
3149 | len = sizeof(*tlv) + sizeof(*cmd); | ||
3150 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
3151 | if (!skb) | ||
3152 | return ERR_PTR(-ENOMEM); | ||
3153 | |||
3154 | ptr = (void *)skb->data; | ||
3155 | tlv = ptr; | ||
3156 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD); | ||
3157 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
3158 | cmd = (void *)tlv->value; | ||
3159 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); | ||
3160 | cmd->scan_count = __cpu_to_le32(arg->scan_count); | ||
3161 | cmd->scan_period = __cpu_to_le32(arg->scan_period); | ||
3162 | cmd->scan_priority = __cpu_to_le32(arg->scan_priority); | ||
3163 | cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size); | ||
3164 | cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena); | ||
3165 | cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena); | ||
3166 | cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref); | ||
3167 | cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay); | ||
3168 | cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr); | ||
3169 | cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr); | ||
3170 | cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode); | ||
3171 | cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode); | ||
3172 | cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr); | ||
3173 | cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format); | ||
3174 | cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode); | ||
3175 | cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale); | ||
3176 | cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj); | ||
3177 | cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask); | ||
3178 | |||
3179 | return skb; | ||
3180 | } | ||
3181 | |||
3182 | static struct sk_buff * | ||
3183 | ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, | ||
3184 | u32 trigger, u32 enable) | ||
3185 | { | ||
3186 | struct wmi_vdev_spectral_enable_cmd *cmd; | ||
3187 | struct sk_buff *skb; | ||
3188 | struct wmi_tlv *tlv; | ||
3189 | void *ptr; | ||
3190 | size_t len; | ||
3191 | |||
3192 | len = sizeof(*tlv) + sizeof(*cmd); | ||
3193 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
3194 | if (!skb) | ||
3195 | return ERR_PTR(-ENOMEM); | ||
3196 | |||
3197 | ptr = (void *)skb->data; | ||
3198 | tlv = ptr; | ||
3199 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD); | ||
3200 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
3201 | cmd = (void *)tlv->value; | ||
3202 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
3203 | cmd->trigger_cmd = __cpu_to_le32(trigger); | ||
3204 | cmd->enable_cmd = __cpu_to_le32(enable); | ||
3205 | |||
3206 | return skb; | ||
3207 | } | ||
3208 | |||
3139 | /****************/ | 3209 | /****************/ |
3140 | /* TLV mappings */ | 3210 | /* TLV mappings */ |
3141 | /****************/ | 3211 | /****************/ |
@@ -3464,7 +3534,6 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = { | |||
3464 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, | 3534 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, |
3465 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, | 3535 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, |
3466 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, | 3536 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, |
3467 | .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, | ||
3468 | }; | 3537 | }; |
3469 | 3538 | ||
3470 | static const struct wmi_ops wmi_tlv_ops = { | 3539 | static const struct wmi_ops wmi_tlv_ops = { |
@@ -3542,6 +3611,8 @@ static const struct wmi_ops wmi_tlv_ops = { | |||
3542 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, | 3611 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, |
3543 | .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, | 3612 | .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, |
3544 | .gen_echo = ath10k_wmi_tlv_op_gen_echo, | 3613 | .gen_echo = ath10k_wmi_tlv_op_gen_echo, |
3614 | .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, | ||
3615 | .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, | ||
3545 | }; | 3616 | }; |
3546 | 3617 | ||
3547 | static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { | 3618 | static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 387c4eede388..c893314a191f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -785,7 +785,6 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = { | |||
785 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, | 785 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, |
786 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, | 786 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, |
787 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, | 787 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, |
788 | .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, | ||
789 | }; | 788 | }; |
790 | 789 | ||
791 | /* 10.X WMI VDEV param map */ | 790 | /* 10.X WMI VDEV param map */ |
@@ -861,7 +860,6 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { | |||
861 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, | 860 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, |
862 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, | 861 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, |
863 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, | 862 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, |
864 | .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, | ||
865 | }; | 863 | }; |
866 | 864 | ||
867 | static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { | 865 | static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { |
@@ -936,7 +934,6 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { | |||
936 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, | 934 | .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, |
937 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, | 935 | .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, |
938 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, | 936 | .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, |
939 | .set_tsf = WMI_10X_VDEV_PARAM_TSF_INCREMENT, | ||
940 | }; | 937 | }; |
941 | 938 | ||
942 | static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { | 939 | static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { |
@@ -1012,7 +1009,8 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { | |||
1012 | .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC, | 1009 | .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC, |
1013 | .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, | 1010 | .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, |
1014 | .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, | 1011 | .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, |
1015 | .set_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT, | 1012 | .inc_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT, |
1013 | .dec_tsf = WMI_10_4_VDEV_PARAM_TSF_DECREMENT, | ||
1016 | }; | 1014 | }; |
1017 | 1015 | ||
1018 | static struct wmi_pdev_param_map wmi_pdev_param_map = { | 1016 | static struct wmi_pdev_param_map wmi_pdev_param_map = { |
@@ -4489,7 +4487,7 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id, | |||
4489 | if (!num_units) | 4487 | if (!num_units) |
4490 | return -ENOMEM; | 4488 | return -ENOMEM; |
4491 | 4489 | ||
4492 | paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE); | 4490 | paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_BIDIRECTIONAL); |
4493 | if (dma_mapping_error(ar->dev, paddr)) { | 4491 | if (dma_mapping_error(ar->dev, paddr)) { |
4494 | kfree(vaddr); | 4492 | kfree(vaddr); |
4495 | return -ENOMEM; | 4493 | return -ENOMEM; |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 1b243c899bef..5d3dff95b2e5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -4603,9 +4603,17 @@ enum wmi_rate_preamble { | |||
4603 | 4603 | ||
4604 | #define ATH10K_HW_NSS(rate) (1 + (((rate) >> 4) & 0x3)) | 4604 | #define ATH10K_HW_NSS(rate) (1 + (((rate) >> 4) & 0x3)) |
4605 | #define ATH10K_HW_PREAMBLE(rate) (((rate) >> 6) & 0x3) | 4605 | #define ATH10K_HW_PREAMBLE(rate) (((rate) >> 6) & 0x3) |
4606 | #define ATH10K_HW_RATECODE(rate, nss, preamble) \ | 4606 | #define ATH10K_HW_MCS_RATE(rate) ((rate) & 0xf) |
4607 | #define ATH10K_HW_LEGACY_RATE(rate) ((rate) & 0x3f) | ||
4608 | #define ATH10K_HW_BW(flags) (((flags) >> 3) & 0x3) | ||
4609 | #define ATH10K_HW_GI(flags) (((flags) >> 5) & 0x1) | ||
4610 | #define ATH10K_HW_RATECODE(rate, nss, preamble) \ | ||
4607 | (((preamble) << 6) | ((nss) << 4) | (rate)) | 4611 | (((preamble) << 6) | ((nss) << 4) | (rate)) |
4608 | 4612 | ||
4613 | #define VHT_MCS_NUM 10 | ||
4614 | #define VHT_BW_NUM 4 | ||
4615 | #define VHT_NSS_NUM 4 | ||
4616 | |||
4609 | /* Value to disable fixed rate setting */ | 4617 | /* Value to disable fixed rate setting */ |
4610 | #define WMI_FIXED_RATE_NONE (0xff) | 4618 | #define WMI_FIXED_RATE_NONE (0xff) |
4611 | 4619 | ||
@@ -4676,7 +4684,8 @@ struct wmi_vdev_param_map { | |||
4676 | u32 meru_vc; | 4684 | u32 meru_vc; |
4677 | u32 rx_decap_type; | 4685 | u32 rx_decap_type; |
4678 | u32 bw_nss_ratemask; | 4686 | u32 bw_nss_ratemask; |
4679 | u32 set_tsf; | 4687 | u32 inc_tsf; |
4688 | u32 dec_tsf; | ||
4680 | }; | 4689 | }; |
4681 | 4690 | ||
4682 | #define WMI_VDEV_PARAM_UNSUPPORTED 0 | 4691 | #define WMI_VDEV_PARAM_UNSUPPORTED 0 |
@@ -5009,6 +5018,11 @@ enum wmi_10_4_vdev_param { | |||
5009 | WMI_10_4_VDEV_PARAM_STA_KICKOUT, | 5018 | WMI_10_4_VDEV_PARAM_STA_KICKOUT, |
5010 | WMI_10_4_VDEV_PARAM_CAPABILITIES, | 5019 | WMI_10_4_VDEV_PARAM_CAPABILITIES, |
5011 | WMI_10_4_VDEV_PARAM_TSF_INCREMENT, | 5020 | WMI_10_4_VDEV_PARAM_TSF_INCREMENT, |
5021 | WMI_10_4_VDEV_PARAM_RX_FILTER, | ||
5022 | WMI_10_4_VDEV_PARAM_MGMT_TX_POWER, | ||
5023 | WMI_10_4_VDEV_PARAM_ATF_SSID_SCHED_POLICY, | ||
5024 | WMI_10_4_VDEV_PARAM_DISABLE_DYN_BW_RTS, | ||
5025 | WMI_10_4_VDEV_PARAM_TSF_DECREMENT, | ||
5012 | }; | 5026 | }; |
5013 | 5027 | ||
5014 | #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0) | 5028 | #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0) |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4f8d9ed04f5e..d068df520e7a 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -66,7 +66,6 @@ | |||
66 | 66 | ||
67 | #include <linux/seq_file.h> | 67 | #include <linux/seq_file.h> |
68 | #include <linux/list.h> | 68 | #include <linux/list.h> |
69 | #include <linux/vmalloc.h> | ||
70 | #include "debug.h" | 69 | #include "debug.h" |
71 | #include "ath5k.h" | 70 | #include "ath5k.h" |
72 | #include "reg.h" | 71 | #include "reg.h" |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index bea6186f745a..2bd982c3a479 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -62,7 +62,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
62 | return false; | 62 | return false; |
63 | } | 63 | } |
64 | 64 | ||
65 | static struct ath_bus_ops ath_ahb_bus_ops = { | 65 | static const struct ath_bus_ops ath_ahb_bus_ops = { |
66 | .ath_bus_type = ATH_AHB, | 66 | .ath_bus_type = ATH_AHB, |
67 | .read_cachesize = ath_ahb_read_cachesize, | 67 | .read_cachesize = ath_ahb_read_cachesize, |
68 | .eeprom_read = ath_ahb_eeprom_read, | 68 | .eeprom_read = ath_ahb_eeprom_read, |
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index e2512d5bc0e1..eedf86b67cf5 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c | |||
@@ -528,6 +528,9 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h | |||
528 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | 528 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) |
529 | return 0; | 529 | return 0; |
530 | 530 | ||
531 | if (!spec_priv->rfs_chan_spec_scan) | ||
532 | return 1; | ||
533 | |||
531 | /* Output buffers are full, no need to process anything | 534 | /* Output buffers are full, no need to process anything |
532 | * since there is no space to put the result anyway | 535 | * since there is no space to put the result anyway |
533 | */ | 536 | */ |
@@ -1072,7 +1075,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { | |||
1072 | 1075 | ||
1073 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) | 1076 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) |
1074 | { | 1077 | { |
1075 | if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS)) { | 1078 | if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { |
1076 | relay_close(spec_priv->rfs_chan_spec_scan); | 1079 | relay_close(spec_priv->rfs_chan_spec_scan); |
1077 | spec_priv->rfs_chan_spec_scan = NULL; | 1080 | spec_priv->rfs_chan_spec_scan = NULL; |
1078 | } | 1081 | } |
@@ -1086,6 +1089,9 @@ void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, | |||
1086 | debugfs_phy, | 1089 | debugfs_phy, |
1087 | 1024, 256, &rfs_spec_scan_cb, | 1090 | 1024, 256, &rfs_spec_scan_cb, |
1088 | NULL); | 1091 | NULL); |
1092 | if (!spec_priv->rfs_chan_spec_scan) | ||
1093 | return; | ||
1094 | |||
1089 | debugfs_create_file("spectral_scan_ctl", | 1095 | debugfs_create_file("spectral_scan_ctl", |
1090 | S_IRUSR | S_IWUSR, | 1096 | S_IRUSR | S_IWUSR, |
1091 | debugfs_phy, spec_priv, | 1097 | debugfs_phy, spec_priv, |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e1c338cb9cb5..de2d212f39ec 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -997,7 +997,8 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
997 | err = usb_control_msg(hif_dev->udev, | 997 | err = usb_control_msg(hif_dev->udev, |
998 | usb_sndctrlpipe(hif_dev->udev, 0), | 998 | usb_sndctrlpipe(hif_dev->udev, 0), |
999 | FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT, | 999 | FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT, |
1000 | addr >> 8, 0, buf, transfer, HZ); | 1000 | addr >> 8, 0, buf, transfer, |
1001 | USB_MSG_TIMEOUT); | ||
1001 | if (err < 0) { | 1002 | if (err < 0) { |
1002 | kfree(buf); | 1003 | kfree(buf); |
1003 | return err; | 1004 | return err; |
@@ -1020,7 +1021,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
1020 | err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), | 1021 | err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), |
1021 | FIRMWARE_DOWNLOAD_COMP, | 1022 | FIRMWARE_DOWNLOAD_COMP, |
1022 | 0x40 | USB_DIR_OUT, | 1023 | 0x40 | USB_DIR_OUT, |
1023 | firm_offset >> 8, 0, NULL, 0, HZ); | 1024 | firm_offset >> 8, 0, NULL, 0, USB_MSG_TIMEOUT); |
1024 | if (err) | 1025 | if (err) |
1025 | return -EIO; | 1026 | return -EIO; |
1026 | 1027 | ||
@@ -1249,7 +1250,7 @@ static int send_eject_command(struct usb_interface *interface) | |||
1249 | 1250 | ||
1250 | dev_info(&udev->dev, "Ejecting storage device...\n"); | 1251 | dev_info(&udev->dev, "Ejecting storage device...\n"); |
1251 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), | 1252 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), |
1252 | cmd, 31, NULL, 2000); | 1253 | cmd, 31, NULL, 2 * USB_MSG_TIMEOUT); |
1253 | kfree(cmd); | 1254 | kfree(cmd); |
1254 | if (r) | 1255 | if (r) |
1255 | return r; | 1256 | return r; |
@@ -1314,7 +1315,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) | |||
1314 | return; | 1315 | return; |
1315 | 1316 | ||
1316 | ret = usb_interrupt_msg(udev, usb_sndintpipe(udev, USB_REG_OUT_PIPE), | 1317 | ret = usb_interrupt_msg(udev, usb_sndintpipe(udev, USB_REG_OUT_PIPE), |
1317 | buf, 4, NULL, HZ); | 1318 | buf, 4, NULL, USB_MSG_TIMEOUT); |
1318 | if (ret) | 1319 | if (ret) |
1319 | dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); | 1320 | dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); |
1320 | 1321 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7c2ef7ecd98b..7846916aa01d 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h | |||
@@ -71,6 +71,8 @@ extern int htc_use_dev_fw; | |||
71 | #define USB_REG_IN_PIPE 3 | 71 | #define USB_REG_IN_PIPE 3 |
72 | #define USB_REG_OUT_PIPE 4 | 72 | #define USB_REG_OUT_PIPE 4 |
73 | 73 | ||
74 | #define USB_MSG_TIMEOUT 1000 /* (ms) */ | ||
75 | |||
74 | #define HIF_USB_MAX_RXPIPES 2 | 76 | #define HIF_USB_MAX_RXPIPES 2 |
75 | #define HIF_USB_MAX_TXPIPES 4 | 77 | #define HIF_USB_MAX_TXPIPES 4 |
76 | 78 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 14b13f07cd1f..a35f78be8dec 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2792,7 +2792,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) | |||
2792 | WARN_ON(1); | 2792 | WARN_ON(1); |
2793 | } | 2793 | } |
2794 | 2794 | ||
2795 | return val; | 2795 | return !!val; |
2796 | } | 2796 | } |
2797 | EXPORT_SYMBOL(ath9k_hw_gpio_get); | 2797 | EXPORT_SYMBOL(ath9k_hw_gpio_get); |
2798 | 2798 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 669734252664..fb4ba27d92b7 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -867,10 +867,21 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
867 | * can be dropped. | 867 | * can be dropped. |
868 | */ | 868 | */ |
869 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) { | 869 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) { |
870 | ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); | 870 | /* |
871 | if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime)) | 871 | * DFS and spectral are mutually exclusive |
872 | * | ||
873 | * Since some chips use PHYERR_RADAR as indication for both, we | ||
874 | * need to double check which feature is enabled to prevent | ||
875 | * feeding spectral or dfs-detector with wrong frames. | ||
876 | */ | ||
877 | if (hw->conf.radar_enabled) { | ||
878 | ath9k_dfs_process_phyerr(sc, hdr, rx_stats, | ||
879 | rx_status->mactime); | ||
880 | } else if (sc->spec_priv.spectral_mode != SPECTRAL_DISABLED && | ||
881 | ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, | ||
882 | rx_status->mactime)) { | ||
872 | RX_STAT_INC(rx_spectral); | 883 | RX_STAT_INC(rx_spectral); |
873 | 884 | } | |
874 | return -EINVAL; | 885 | return -EINVAL; |
875 | } | 886 | } |
876 | 887 | ||
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index d117240d9a73..6aa3ff4240a9 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -354,14 +354,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
354 | wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n", | 354 | wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n", |
355 | __func__, wdev, wdev->iftype); | 355 | __func__, wdev, wdev->iftype); |
356 | 356 | ||
357 | mutex_lock(&wil->p2p_wdev_mutex); | ||
358 | if (wil->scan_request) { | ||
359 | wil_err(wil, "Already scanning\n"); | ||
360 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
361 | return -EAGAIN; | ||
362 | } | ||
363 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
364 | |||
365 | /* check we are client side */ | 357 | /* check we are client side */ |
366 | switch (wdev->iftype) { | 358 | switch (wdev->iftype) { |
367 | case NL80211_IFTYPE_STATION: | 359 | case NL80211_IFTYPE_STATION: |
@@ -378,12 +370,24 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
378 | return -EBUSY; | 370 | return -EBUSY; |
379 | } | 371 | } |
380 | 372 | ||
373 | mutex_lock(&wil->mutex); | ||
374 | |||
375 | mutex_lock(&wil->p2p_wdev_mutex); | ||
376 | if (wil->scan_request || wil->p2p.discovery_started) { | ||
377 | wil_err(wil, "Already scanning\n"); | ||
378 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
379 | rc = -EAGAIN; | ||
380 | goto out; | ||
381 | } | ||
382 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
383 | |||
381 | /* social scan on P2P_DEVICE is handled as p2p search */ | 384 | /* social scan on P2P_DEVICE is handled as p2p search */ |
382 | if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE && | 385 | if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE && |
383 | wil_p2p_is_social_scan(request)) { | 386 | wil_p2p_is_social_scan(request)) { |
384 | if (!wil->p2p.p2p_dev_started) { | 387 | if (!wil->p2p.p2p_dev_started) { |
385 | wil_err(wil, "P2P search requested on stopped P2P device\n"); | 388 | wil_err(wil, "P2P search requested on stopped P2P device\n"); |
386 | return -EIO; | 389 | rc = -EIO; |
390 | goto out; | ||
387 | } | 391 | } |
388 | wil->scan_request = request; | 392 | wil->scan_request = request; |
389 | wil->radio_wdev = wdev; | 393 | wil->radio_wdev = wdev; |
@@ -392,7 +396,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
392 | wil->radio_wdev = wil_to_wdev(wil); | 396 | wil->radio_wdev = wil_to_wdev(wil); |
393 | wil->scan_request = NULL; | 397 | wil->scan_request = NULL; |
394 | } | 398 | } |
395 | return rc; | 399 | goto out; |
396 | } | 400 | } |
397 | 401 | ||
398 | (void)wil_p2p_stop_discovery(wil); | 402 | (void)wil_p2p_stop_discovery(wil); |
@@ -415,7 +419,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
415 | 419 | ||
416 | if (rc) { | 420 | if (rc) { |
417 | wil_err(wil, "set SSID for scan request failed: %d\n", rc); | 421 | wil_err(wil, "set SSID for scan request failed: %d\n", rc); |
418 | return rc; | 422 | goto out; |
419 | } | 423 | } |
420 | 424 | ||
421 | wil->scan_request = request; | 425 | wil->scan_request = request; |
@@ -448,7 +452,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
448 | 452 | ||
449 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); | 453 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); |
450 | if (rc) | 454 | if (rc) |
451 | goto out; | 455 | goto out_restore; |
452 | 456 | ||
453 | if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) { | 457 | if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) { |
454 | cmd.cmd.discovery_mode = 1; | 458 | cmd.cmd.discovery_mode = 1; |
@@ -459,16 +463,45 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
459 | rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + | 463 | rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + |
460 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | 464 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); |
461 | 465 | ||
462 | out: | 466 | out_restore: |
463 | if (rc) { | 467 | if (rc) { |
464 | del_timer_sync(&wil->scan_timer); | 468 | del_timer_sync(&wil->scan_timer); |
465 | wil->radio_wdev = wil_to_wdev(wil); | 469 | wil->radio_wdev = wil_to_wdev(wil); |
466 | wil->scan_request = NULL; | 470 | wil->scan_request = NULL; |
467 | } | 471 | } |
468 | 472 | out: | |
473 | mutex_unlock(&wil->mutex); | ||
469 | return rc; | 474 | return rc; |
470 | } | 475 | } |
471 | 476 | ||
477 | static void wil_cfg80211_abort_scan(struct wiphy *wiphy, | ||
478 | struct wireless_dev *wdev) | ||
479 | { | ||
480 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
481 | |||
482 | wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype); | ||
483 | |||
484 | mutex_lock(&wil->mutex); | ||
485 | mutex_lock(&wil->p2p_wdev_mutex); | ||
486 | |||
487 | if (!wil->scan_request) | ||
488 | goto out; | ||
489 | |||
490 | if (wdev != wil->scan_request->wdev) { | ||
491 | wil_dbg_misc(wil, "abort scan was called on the wrong iface\n"); | ||
492 | goto out; | ||
493 | } | ||
494 | |||
495 | if (wil->radio_wdev == wil->p2p_wdev) | ||
496 | wil_p2p_stop_radio_operations(wil); | ||
497 | else | ||
498 | wil_abort_scan(wil, true); | ||
499 | |||
500 | out: | ||
501 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
502 | mutex_unlock(&wil->mutex); | ||
503 | } | ||
504 | |||
472 | static void wil_print_crypto(struct wil6210_priv *wil, | 505 | static void wil_print_crypto(struct wil6210_priv *wil, |
473 | struct cfg80211_crypto_settings *c) | 506 | struct cfg80211_crypto_settings *c) |
474 | { | 507 | { |
@@ -674,6 +707,26 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, | |||
674 | return rc; | 707 | return rc; |
675 | } | 708 | } |
676 | 709 | ||
710 | static int wil_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | ||
711 | { | ||
712 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
713 | int rc; | ||
714 | |||
715 | /* these parameters are explicitly not supported */ | ||
716 | if (changed & (WIPHY_PARAM_RETRY_LONG | | ||
717 | WIPHY_PARAM_FRAG_THRESHOLD | | ||
718 | WIPHY_PARAM_RTS_THRESHOLD)) | ||
719 | return -ENOTSUPP; | ||
720 | |||
721 | if (changed & WIPHY_PARAM_RETRY_SHORT) { | ||
722 | rc = wmi_set_mgmt_retry(wil, wiphy->retry_short); | ||
723 | if (rc) | ||
724 | return rc; | ||
725 | } | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
677 | int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 730 | int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
678 | struct cfg80211_mgmt_tx_params *params, | 731 | struct cfg80211_mgmt_tx_params *params, |
679 | u64 *cookie) | 732 | u64 *cookie) |
@@ -940,16 +993,8 @@ static int wil_remain_on_channel(struct wiphy *wiphy, | |||
940 | wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n", | 993 | wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n", |
941 | __func__, chan->center_freq, duration, wdev->iftype); | 994 | __func__, chan->center_freq, duration, wdev->iftype); |
942 | 995 | ||
943 | rc = wil_p2p_listen(wil, duration, chan, cookie); | 996 | rc = wil_p2p_listen(wil, wdev, duration, chan, cookie); |
944 | if (rc) | 997 | return rc; |
945 | return rc; | ||
946 | |||
947 | wil->radio_wdev = wdev; | ||
948 | |||
949 | cfg80211_ready_on_channel(wdev, *cookie, chan, duration, | ||
950 | GFP_KERNEL); | ||
951 | |||
952 | return 0; | ||
953 | } | 998 | } |
954 | 999 | ||
955 | static int wil_cancel_remain_on_channel(struct wiphy *wiphy, | 1000 | static int wil_cancel_remain_on_channel(struct wiphy *wiphy, |
@@ -1419,17 +1464,49 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, | |||
1419 | 1464 | ||
1420 | wil_dbg_misc(wil, "%s: entered\n", __func__); | 1465 | wil_dbg_misc(wil, "%s: entered\n", __func__); |
1421 | mutex_lock(&wil->mutex); | 1466 | mutex_lock(&wil->mutex); |
1467 | mutex_lock(&wil->p2p_wdev_mutex); | ||
1422 | wil_p2p_stop_radio_operations(wil); | 1468 | wil_p2p_stop_radio_operations(wil); |
1423 | p2p->p2p_dev_started = 0; | 1469 | p2p->p2p_dev_started = 0; |
1470 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
1424 | mutex_unlock(&wil->mutex); | 1471 | mutex_unlock(&wil->mutex); |
1425 | } | 1472 | } |
1426 | 1473 | ||
1474 | static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy, | ||
1475 | struct net_device *dev, | ||
1476 | bool enabled, int timeout) | ||
1477 | { | ||
1478 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
1479 | enum wmi_ps_profile_type ps_profile; | ||
1480 | int rc; | ||
1481 | |||
1482 | if (!test_bit(WMI_FW_CAPABILITY_PS_CONFIG, wil->fw_capabilities)) { | ||
1483 | wil_err(wil, "set_power_mgmt not supported\n"); | ||
1484 | return -EOPNOTSUPP; | ||
1485 | } | ||
1486 | |||
1487 | wil_dbg_misc(wil, "enabled=%d, timeout=%d\n", | ||
1488 | enabled, timeout); | ||
1489 | |||
1490 | if (enabled) | ||
1491 | ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT; | ||
1492 | else | ||
1493 | ps_profile = WMI_PS_PROFILE_TYPE_PS_DISABLED; | ||
1494 | |||
1495 | rc = wmi_ps_dev_profile_cfg(wil, ps_profile); | ||
1496 | if (rc) | ||
1497 | wil_err(wil, "wmi_ps_dev_profile_cfg failed (%d)\n", rc); | ||
1498 | |||
1499 | return rc; | ||
1500 | } | ||
1501 | |||
1427 | static struct cfg80211_ops wil_cfg80211_ops = { | 1502 | static struct cfg80211_ops wil_cfg80211_ops = { |
1428 | .add_virtual_intf = wil_cfg80211_add_iface, | 1503 | .add_virtual_intf = wil_cfg80211_add_iface, |
1429 | .del_virtual_intf = wil_cfg80211_del_iface, | 1504 | .del_virtual_intf = wil_cfg80211_del_iface, |
1430 | .scan = wil_cfg80211_scan, | 1505 | .scan = wil_cfg80211_scan, |
1506 | .abort_scan = wil_cfg80211_abort_scan, | ||
1431 | .connect = wil_cfg80211_connect, | 1507 | .connect = wil_cfg80211_connect, |
1432 | .disconnect = wil_cfg80211_disconnect, | 1508 | .disconnect = wil_cfg80211_disconnect, |
1509 | .set_wiphy_params = wil_cfg80211_set_wiphy_params, | ||
1433 | .change_virtual_intf = wil_cfg80211_change_iface, | 1510 | .change_virtual_intf = wil_cfg80211_change_iface, |
1434 | .get_station = wil_cfg80211_get_station, | 1511 | .get_station = wil_cfg80211_get_station, |
1435 | .dump_station = wil_cfg80211_dump_station, | 1512 | .dump_station = wil_cfg80211_dump_station, |
@@ -1450,6 +1527,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { | |||
1450 | /* P2P device */ | 1527 | /* P2P device */ |
1451 | .start_p2p_device = wil_cfg80211_start_p2p_device, | 1528 | .start_p2p_device = wil_cfg80211_start_p2p_device, |
1452 | .stop_p2p_device = wil_cfg80211_stop_p2p_device, | 1529 | .stop_p2p_device = wil_cfg80211_stop_p2p_device, |
1530 | .set_power_mgmt = wil_cfg80211_set_power_mgmt, | ||
1453 | }; | 1531 | }; |
1454 | 1532 | ||
1455 | static void wil_wiphy_init(struct wiphy *wiphy) | 1533 | static void wil_wiphy_init(struct wiphy *wiphy) |
@@ -1466,7 +1544,8 @@ static void wil_wiphy_init(struct wiphy *wiphy) | |||
1466 | BIT(NL80211_IFTYPE_MONITOR); | 1544 | BIT(NL80211_IFTYPE_MONITOR); |
1467 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | 1545 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | |
1468 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | 1546 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
1469 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | 1547 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
1548 | WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1470 | dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", | 1549 | dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", |
1471 | __func__, wiphy->flags); | 1550 | __func__, wiphy->flags); |
1472 | wiphy->probe_resp_offload = | 1551 | wiphy->probe_resp_offload = |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index e7130b54d1d8..e2e021bcaa03 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "boot_loader.h" | 24 | #include "boot_loader.h" |
25 | 25 | ||
26 | #define WAIT_FOR_HALP_VOTE_MS 100 | 26 | #define WAIT_FOR_HALP_VOTE_MS 100 |
27 | #define WAIT_FOR_SCAN_ABORT_MS 1000 | ||
27 | 28 | ||
28 | bool debug_fw; /* = false; */ | 29 | bool debug_fw; /* = false; */ |
29 | module_param(debug_fw, bool, S_IRUGO); | 30 | module_param(debug_fw, bool, S_IRUGO); |
@@ -213,7 +214,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
213 | memset(&sta->stats, 0, sizeof(sta->stats)); | 214 | memset(&sta->stats, 0, sizeof(sta->stats)); |
214 | } | 215 | } |
215 | 216 | ||
216 | static bool wil_ap_is_connected(struct wil6210_priv *wil) | 217 | static bool wil_is_connected(struct wil6210_priv *wil) |
217 | { | 218 | { |
218 | int i; | 219 | int i; |
219 | 220 | ||
@@ -267,7 +268,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
267 | case NL80211_IFTYPE_STATION: | 268 | case NL80211_IFTYPE_STATION: |
268 | case NL80211_IFTYPE_P2P_CLIENT: | 269 | case NL80211_IFTYPE_P2P_CLIENT: |
269 | wil_bcast_fini(wil); | 270 | wil_bcast_fini(wil); |
270 | netif_tx_stop_all_queues(ndev); | 271 | wil_update_net_queues_bh(wil, NULL, true); |
271 | netif_carrier_off(ndev); | 272 | netif_carrier_off(ndev); |
272 | 273 | ||
273 | if (test_bit(wil_status_fwconnected, wil->status)) { | 274 | if (test_bit(wil_status_fwconnected, wil->status)) { |
@@ -283,8 +284,12 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
283 | break; | 284 | break; |
284 | case NL80211_IFTYPE_AP: | 285 | case NL80211_IFTYPE_AP: |
285 | case NL80211_IFTYPE_P2P_GO: | 286 | case NL80211_IFTYPE_P2P_GO: |
286 | if (!wil_ap_is_connected(wil)) | 287 | if (!wil_is_connected(wil)) { |
288 | wil_update_net_queues_bh(wil, NULL, true); | ||
287 | clear_bit(wil_status_fwconnected, wil->status); | 289 | clear_bit(wil_status_fwconnected, wil->status); |
290 | } else { | ||
291 | wil_update_net_queues_bh(wil, NULL, false); | ||
292 | } | ||
288 | break; | 293 | break; |
289 | default: | 294 | default: |
290 | break; | 295 | break; |
@@ -384,18 +389,19 @@ static void wil_fw_error_worker(struct work_struct *work) | |||
384 | 389 | ||
385 | wil->last_fw_recovery = jiffies; | 390 | wil->last_fw_recovery = jiffies; |
386 | 391 | ||
392 | wil_info(wil, "fw error recovery requested (try %d)...\n", | ||
393 | wil->recovery_count); | ||
394 | if (!no_fw_recovery) | ||
395 | wil->recovery_state = fw_recovery_running; | ||
396 | if (wil_wait_for_recovery(wil) != 0) | ||
397 | return; | ||
398 | |||
387 | mutex_lock(&wil->mutex); | 399 | mutex_lock(&wil->mutex); |
388 | switch (wdev->iftype) { | 400 | switch (wdev->iftype) { |
389 | case NL80211_IFTYPE_STATION: | 401 | case NL80211_IFTYPE_STATION: |
390 | case NL80211_IFTYPE_P2P_CLIENT: | 402 | case NL80211_IFTYPE_P2P_CLIENT: |
391 | case NL80211_IFTYPE_MONITOR: | 403 | case NL80211_IFTYPE_MONITOR: |
392 | wil_info(wil, "fw error recovery requested (try %d)...\n", | 404 | /* silent recovery, upper layers will see disconnect */ |
393 | wil->recovery_count); | ||
394 | if (!no_fw_recovery) | ||
395 | wil->recovery_state = fw_recovery_running; | ||
396 | if (0 != wil_wait_for_recovery(wil)) | ||
397 | break; | ||
398 | |||
399 | __wil_down(wil); | 405 | __wil_down(wil); |
400 | __wil_up(wil); | 406 | __wil_up(wil); |
401 | break; | 407 | break; |
@@ -512,10 +518,13 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
512 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 518 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
513 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); | 519 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); |
514 | INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); | 520 | INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); |
521 | INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); | ||
515 | 522 | ||
516 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | 523 | INIT_LIST_HEAD(&wil->pending_wmi_ev); |
517 | INIT_LIST_HEAD(&wil->probe_client_pending); | 524 | INIT_LIST_HEAD(&wil->probe_client_pending); |
518 | spin_lock_init(&wil->wmi_ev_lock); | 525 | spin_lock_init(&wil->wmi_ev_lock); |
526 | spin_lock_init(&wil->net_queue_lock); | ||
527 | wil->net_queue_stopped = 1; | ||
519 | init_waitqueue_head(&wil->wq); | 528 | init_waitqueue_head(&wil->wq); |
520 | 529 | ||
521 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); | 530 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); |
@@ -571,6 +580,7 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
571 | cancel_work_sync(&wil->disconnect_worker); | 580 | cancel_work_sync(&wil->disconnect_worker); |
572 | cancel_work_sync(&wil->fw_error_worker); | 581 | cancel_work_sync(&wil->fw_error_worker); |
573 | cancel_work_sync(&wil->p2p.discovery_expired_work); | 582 | cancel_work_sync(&wil->p2p.discovery_expired_work); |
583 | cancel_work_sync(&wil->p2p.delayed_listen_work); | ||
574 | mutex_lock(&wil->mutex); | 584 | mutex_lock(&wil->mutex); |
575 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | 585 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); |
576 | mutex_unlock(&wil->mutex); | 586 | mutex_unlock(&wil->mutex); |
@@ -685,6 +695,19 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
685 | return 0; | 695 | return 0; |
686 | } | 696 | } |
687 | 697 | ||
698 | static void wil_collect_fw_info(struct wil6210_priv *wil) | ||
699 | { | ||
700 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
701 | u8 retry_short; | ||
702 | int rc; | ||
703 | |||
704 | rc = wmi_get_mgmt_retry(wil, &retry_short); | ||
705 | if (!rc) { | ||
706 | wiphy->retry_short = retry_short; | ||
707 | wil_dbg_misc(wil, "FW retry_short: %d\n", retry_short); | ||
708 | } | ||
709 | } | ||
710 | |||
688 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) | 711 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) |
689 | { | 712 | { |
690 | le32_to_cpus(&r->base); | 713 | le32_to_cpus(&r->base); |
@@ -801,6 +824,34 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil) | |||
801 | return 0; | 824 | return 0; |
802 | } | 825 | } |
803 | 826 | ||
827 | void wil_abort_scan(struct wil6210_priv *wil, bool sync) | ||
828 | { | ||
829 | int rc; | ||
830 | struct cfg80211_scan_info info = { | ||
831 | .aborted = true, | ||
832 | }; | ||
833 | |||
834 | lockdep_assert_held(&wil->p2p_wdev_mutex); | ||
835 | |||
836 | if (!wil->scan_request) | ||
837 | return; | ||
838 | |||
839 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request); | ||
840 | del_timer_sync(&wil->scan_timer); | ||
841 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
842 | rc = wmi_abort_scan(wil); | ||
843 | if (!rc && sync) | ||
844 | wait_event_interruptible_timeout(wil->wq, !wil->scan_request, | ||
845 | msecs_to_jiffies( | ||
846 | WAIT_FOR_SCAN_ABORT_MS)); | ||
847 | |||
848 | mutex_lock(&wil->p2p_wdev_mutex); | ||
849 | if (wil->scan_request) { | ||
850 | cfg80211_scan_done(wil->scan_request, &info); | ||
851 | wil->scan_request = NULL; | ||
852 | } | ||
853 | } | ||
854 | |||
804 | /* | 855 | /* |
805 | * We reset all the structures, and we reset the UMAC. | 856 | * We reset all the structures, and we reset the UMAC. |
806 | * After calling this routine, you're expected to reload | 857 | * After calling this routine, you're expected to reload |
@@ -853,17 +904,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
853 | mutex_unlock(&wil->wmi_mutex); | 904 | mutex_unlock(&wil->wmi_mutex); |
854 | 905 | ||
855 | mutex_lock(&wil->p2p_wdev_mutex); | 906 | mutex_lock(&wil->p2p_wdev_mutex); |
856 | if (wil->scan_request) { | 907 | wil_abort_scan(wil, false); |
857 | struct cfg80211_scan_info info = { | ||
858 | .aborted = true, | ||
859 | }; | ||
860 | |||
861 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", | ||
862 | wil->scan_request); | ||
863 | del_timer_sync(&wil->scan_timer); | ||
864 | cfg80211_scan_done(wil->scan_request, &info); | ||
865 | wil->scan_request = NULL; | ||
866 | } | ||
867 | mutex_unlock(&wil->p2p_wdev_mutex); | 908 | mutex_unlock(&wil->p2p_wdev_mutex); |
868 | 909 | ||
869 | wil_mask_irq(wil); | 910 | wil_mask_irq(wil); |
@@ -940,6 +981,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
940 | return rc; | 981 | return rc; |
941 | } | 982 | } |
942 | 983 | ||
984 | wil_collect_fw_info(wil); | ||
985 | |||
943 | if (wil->platform_ops.notify) { | 986 | if (wil->platform_ops.notify) { |
944 | rc = wil->platform_ops.notify(wil->platform_handle, | 987 | rc = wil->platform_ops.notify(wil->platform_handle, |
945 | WIL_PLATFORM_EVT_FW_RDY); | 988 | WIL_PLATFORM_EVT_FW_RDY); |
@@ -1056,20 +1099,9 @@ int __wil_down(struct wil6210_priv *wil) | |||
1056 | } | 1099 | } |
1057 | wil_enable_irq(wil); | 1100 | wil_enable_irq(wil); |
1058 | 1101 | ||
1059 | wil_p2p_stop_radio_operations(wil); | ||
1060 | |||
1061 | mutex_lock(&wil->p2p_wdev_mutex); | 1102 | mutex_lock(&wil->p2p_wdev_mutex); |
1062 | if (wil->scan_request) { | 1103 | wil_p2p_stop_radio_operations(wil); |
1063 | struct cfg80211_scan_info info = { | 1104 | wil_abort_scan(wil, false); |
1064 | .aborted = true, | ||
1065 | }; | ||
1066 | |||
1067 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", | ||
1068 | wil->scan_request); | ||
1069 | del_timer_sync(&wil->scan_timer); | ||
1070 | cfg80211_scan_done(wil->scan_request, &info); | ||
1071 | wil->scan_request = NULL; | ||
1072 | } | ||
1073 | mutex_unlock(&wil->p2p_wdev_mutex); | 1105 | mutex_unlock(&wil->p2p_wdev_mutex); |
1074 | 1106 | ||
1075 | wil_reset(wil, false); | 1107 | wil_reset(wil, false); |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index d18372cdc8ca..6676001dcbca 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -214,7 +214,7 @@ int wil_if_add(struct wil6210_priv *wil) | |||
214 | netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, | 214 | netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, |
215 | WIL6210_NAPI_BUDGET); | 215 | WIL6210_NAPI_BUDGET); |
216 | 216 | ||
217 | netif_tx_stop_all_queues(ndev); | 217 | wil_update_net_queues_bh(wil, NULL, true); |
218 | 218 | ||
219 | rc = register_netdev(ndev); | 219 | rc = register_netdev(ndev); |
220 | if (rc < 0) { | 220 | if (rc < 0) { |
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 4087785d3090..fbae99525e01 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c | |||
@@ -22,6 +22,43 @@ | |||
22 | #define P2P_SEARCH_DURATION_MS 500 | 22 | #define P2P_SEARCH_DURATION_MS 500 |
23 | #define P2P_DEFAULT_BI 100 | 23 | #define P2P_DEFAULT_BI 100 |
24 | 24 | ||
25 | static int wil_p2p_start_listen(struct wil6210_priv *wil) | ||
26 | { | ||
27 | struct wil_p2p_info *p2p = &wil->p2p; | ||
28 | u8 channel = p2p->listen_chan.hw_value; | ||
29 | int rc; | ||
30 | |||
31 | lockdep_assert_held(&wil->mutex); | ||
32 | |||
33 | rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); | ||
34 | if (rc) { | ||
35 | wil_err(wil, "wmi_p2p_cfg failed\n"); | ||
36 | goto out; | ||
37 | } | ||
38 | |||
39 | rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); | ||
40 | if (rc) { | ||
41 | wil_err(wil, "wmi_set_ssid failed\n"); | ||
42 | goto out_stop; | ||
43 | } | ||
44 | |||
45 | rc = wmi_start_listen(wil); | ||
46 | if (rc) { | ||
47 | wil_err(wil, "wmi_start_listen failed\n"); | ||
48 | goto out_stop; | ||
49 | } | ||
50 | |||
51 | INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired); | ||
52 | mod_timer(&p2p->discovery_timer, | ||
53 | jiffies + msecs_to_jiffies(p2p->listen_duration)); | ||
54 | out_stop: | ||
55 | if (rc) | ||
56 | wmi_stop_discovery(wil); | ||
57 | |||
58 | out: | ||
59 | return rc; | ||
60 | } | ||
61 | |||
25 | bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request) | 62 | bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request) |
26 | { | 63 | { |
27 | return (request->n_channels == 1) && | 64 | return (request->n_channels == 1) && |
@@ -46,7 +83,7 @@ int wil_p2p_search(struct wil6210_priv *wil, | |||
46 | wil_dbg_misc(wil, "%s: channel %d\n", | 83 | wil_dbg_misc(wil, "%s: channel %d\n", |
47 | __func__, P2P_DMG_SOCIAL_CHANNEL); | 84 | __func__, P2P_DMG_SOCIAL_CHANNEL); |
48 | 85 | ||
49 | mutex_lock(&wil->mutex); | 86 | lockdep_assert_held(&wil->mutex); |
50 | 87 | ||
51 | if (p2p->discovery_started) { | 88 | if (p2p->discovery_started) { |
52 | wil_err(wil, "%s: search failed. discovery already ongoing\n", | 89 | wil_err(wil, "%s: search failed. discovery already ongoing\n", |
@@ -103,22 +140,19 @@ out_stop: | |||
103 | wmi_stop_discovery(wil); | 140 | wmi_stop_discovery(wil); |
104 | 141 | ||
105 | out: | 142 | out: |
106 | mutex_unlock(&wil->mutex); | ||
107 | return rc; | 143 | return rc; |
108 | } | 144 | } |
109 | 145 | ||
110 | int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, | 146 | int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, |
111 | struct ieee80211_channel *chan, u64 *cookie) | 147 | unsigned int duration, struct ieee80211_channel *chan, |
148 | u64 *cookie) | ||
112 | { | 149 | { |
113 | struct wil_p2p_info *p2p = &wil->p2p; | 150 | struct wil_p2p_info *p2p = &wil->p2p; |
114 | u8 channel = P2P_DMG_SOCIAL_CHANNEL; | ||
115 | int rc; | 151 | int rc; |
116 | 152 | ||
117 | if (!chan) | 153 | if (!chan) |
118 | return -EINVAL; | 154 | return -EINVAL; |
119 | 155 | ||
120 | channel = chan->hw_value; | ||
121 | |||
122 | wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration); | 156 | wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration); |
123 | 157 | ||
124 | mutex_lock(&wil->mutex); | 158 | mutex_lock(&wil->mutex); |
@@ -129,35 +163,30 @@ int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, | |||
129 | goto out; | 163 | goto out; |
130 | } | 164 | } |
131 | 165 | ||
132 | rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); | 166 | memcpy(&p2p->listen_chan, chan, sizeof(*chan)); |
133 | if (rc) { | 167 | *cookie = ++p2p->cookie; |
134 | wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__); | 168 | p2p->listen_duration = duration; |
135 | goto out; | ||
136 | } | ||
137 | |||
138 | rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); | ||
139 | if (rc) { | ||
140 | wil_err(wil, "%s: wmi_set_ssid failed\n", __func__); | ||
141 | goto out_stop; | ||
142 | } | ||
143 | 169 | ||
144 | rc = wmi_start_listen(wil); | 170 | mutex_lock(&wil->p2p_wdev_mutex); |
145 | if (rc) { | 171 | if (wil->scan_request) { |
146 | wil_err(wil, "%s: wmi_start_listen failed\n", __func__); | 172 | wil_dbg_misc(wil, "Delaying p2p listen until scan done\n"); |
147 | goto out_stop; | 173 | p2p->pending_listen_wdev = wdev; |
174 | p2p->discovery_started = 1; | ||
175 | rc = 0; | ||
176 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
177 | goto out; | ||
148 | } | 178 | } |
179 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
149 | 180 | ||
150 | memcpy(&p2p->listen_chan, chan, sizeof(*chan)); | 181 | rc = wil_p2p_start_listen(wil); |
151 | *cookie = ++p2p->cookie; | 182 | if (rc) |
183 | goto out; | ||
152 | 184 | ||
153 | p2p->discovery_started = 1; | 185 | p2p->discovery_started = 1; |
154 | INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired); | 186 | wil->radio_wdev = wdev; |
155 | mod_timer(&p2p->discovery_timer, | ||
156 | jiffies + msecs_to_jiffies(duration)); | ||
157 | 187 | ||
158 | out_stop: | 188 | cfg80211_ready_on_channel(wdev, *cookie, chan, duration, |
159 | if (rc) | 189 | GFP_KERNEL); |
160 | wmi_stop_discovery(wil); | ||
161 | 190 | ||
162 | out: | 191 | out: |
163 | mutex_unlock(&wil->mutex); | 192 | mutex_unlock(&wil->mutex); |
@@ -170,9 +199,14 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) | |||
170 | u8 started = p2p->discovery_started; | 199 | u8 started = p2p->discovery_started; |
171 | 200 | ||
172 | if (p2p->discovery_started) { | 201 | if (p2p->discovery_started) { |
173 | del_timer_sync(&p2p->discovery_timer); | 202 | if (p2p->pending_listen_wdev) { |
203 | /* discovery not really started, only pending */ | ||
204 | p2p->pending_listen_wdev = NULL; | ||
205 | } else { | ||
206 | del_timer_sync(&p2p->discovery_timer); | ||
207 | wmi_stop_discovery(wil); | ||
208 | } | ||
174 | p2p->discovery_started = 0; | 209 | p2p->discovery_started = 0; |
175 | wmi_stop_discovery(wil); | ||
176 | } | 210 | } |
177 | 211 | ||
178 | return started; | 212 | return started; |
@@ -257,13 +291,59 @@ void wil_p2p_search_expired(struct work_struct *work) | |||
257 | }; | 291 | }; |
258 | 292 | ||
259 | mutex_lock(&wil->p2p_wdev_mutex); | 293 | mutex_lock(&wil->p2p_wdev_mutex); |
260 | cfg80211_scan_done(wil->scan_request, &info); | 294 | if (wil->scan_request) { |
261 | wil->scan_request = NULL; | 295 | cfg80211_scan_done(wil->scan_request, &info); |
262 | wil->radio_wdev = wil->wdev; | 296 | wil->scan_request = NULL; |
297 | wil->radio_wdev = wil->wdev; | ||
298 | } | ||
263 | mutex_unlock(&wil->p2p_wdev_mutex); | 299 | mutex_unlock(&wil->p2p_wdev_mutex); |
264 | } | 300 | } |
265 | } | 301 | } |
266 | 302 | ||
303 | void wil_p2p_delayed_listen_work(struct work_struct *work) | ||
304 | { | ||
305 | struct wil_p2p_info *p2p = container_of(work, | ||
306 | struct wil_p2p_info, delayed_listen_work); | ||
307 | struct wil6210_priv *wil = container_of(p2p, | ||
308 | struct wil6210_priv, p2p); | ||
309 | int rc; | ||
310 | |||
311 | mutex_lock(&wil->mutex); | ||
312 | |||
313 | wil_dbg_misc(wil, "Checking delayed p2p listen\n"); | ||
314 | if (!p2p->discovery_started || !p2p->pending_listen_wdev) | ||
315 | goto out; | ||
316 | |||
317 | mutex_lock(&wil->p2p_wdev_mutex); | ||
318 | if (wil->scan_request) { | ||
319 | /* another scan started, wait again... */ | ||
320 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
321 | goto out; | ||
322 | } | ||
323 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
324 | |||
325 | rc = wil_p2p_start_listen(wil); | ||
326 | |||
327 | mutex_lock(&wil->p2p_wdev_mutex); | ||
328 | if (rc) { | ||
329 | cfg80211_remain_on_channel_expired(p2p->pending_listen_wdev, | ||
330 | p2p->cookie, | ||
331 | &p2p->listen_chan, | ||
332 | GFP_KERNEL); | ||
333 | wil->radio_wdev = wil->wdev; | ||
334 | } else { | ||
335 | cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie, | ||
336 | &p2p->listen_chan, | ||
337 | p2p->listen_duration, GFP_KERNEL); | ||
338 | wil->radio_wdev = p2p->pending_listen_wdev; | ||
339 | } | ||
340 | p2p->pending_listen_wdev = NULL; | ||
341 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
342 | |||
343 | out: | ||
344 | mutex_unlock(&wil->mutex); | ||
345 | } | ||
346 | |||
267 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) | 347 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) |
268 | { | 348 | { |
269 | struct wil_p2p_info *p2p = &wil->p2p; | 349 | struct wil_p2p_info *p2p = &wil->p2p; |
@@ -272,8 +352,7 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) | |||
272 | }; | 352 | }; |
273 | 353 | ||
274 | lockdep_assert_held(&wil->mutex); | 354 | lockdep_assert_held(&wil->mutex); |
275 | 355 | lockdep_assert_held(&wil->p2p_wdev_mutex); | |
276 | mutex_lock(&wil->p2p_wdev_mutex); | ||
277 | 356 | ||
278 | if (wil->radio_wdev != wil->p2p_wdev) | 357 | if (wil->radio_wdev != wil->p2p_wdev) |
279 | goto out; | 358 | goto out; |
@@ -281,10 +360,8 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) | |||
281 | if (!p2p->discovery_started) { | 360 | if (!p2p->discovery_started) { |
282 | /* Regular scan on the p2p device */ | 361 | /* Regular scan on the p2p device */ |
283 | if (wil->scan_request && | 362 | if (wil->scan_request && |
284 | wil->scan_request->wdev == wil->p2p_wdev) { | 363 | wil->scan_request->wdev == wil->p2p_wdev) |
285 | cfg80211_scan_done(wil->scan_request, &info); | 364 | wil_abort_scan(wil, true); |
286 | wil->scan_request = NULL; | ||
287 | } | ||
288 | goto out; | 365 | goto out; |
289 | } | 366 | } |
290 | 367 | ||
@@ -307,5 +384,4 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) | |||
307 | 384 | ||
308 | out: | 385 | out: |
309 | wil->radio_wdev = wil->wdev; | 386 | wil->radio_wdev = wil->wdev; |
310 | mutex_unlock(&wil->p2p_wdev_mutex); | ||
311 | } | 387 | } |
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index 5ca0307a3274..b9faae0278c9 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c | |||
@@ -54,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, | |||
54 | struct pmc_ctx *pmc = &wil->pmc; | 54 | struct pmc_ctx *pmc = &wil->pmc; |
55 | struct device *dev = wil_to_dev(wil); | 55 | struct device *dev = wil_to_dev(wil); |
56 | struct wmi_pmc_cmd pmc_cmd = {0}; | 56 | struct wmi_pmc_cmd pmc_cmd = {0}; |
57 | int last_cmd_err = -ENOMEM; | ||
57 | 58 | ||
58 | mutex_lock(&pmc->lock); | 59 | mutex_lock(&pmc->lock); |
59 | 60 | ||
@@ -62,6 +63,29 @@ void wil_pmc_alloc(struct wil6210_priv *wil, | |||
62 | wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__); | 63 | wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__); |
63 | goto no_release_err; | 64 | goto no_release_err; |
64 | } | 65 | } |
66 | if ((num_descriptors <= 0) || (descriptor_size <= 0)) { | ||
67 | wil_err(wil, | ||
68 | "Invalid params num_descriptors(%d), descriptor_size(%d)\n", | ||
69 | num_descriptors, descriptor_size); | ||
70 | last_cmd_err = -EINVAL; | ||
71 | goto no_release_err; | ||
72 | } | ||
73 | |||
74 | if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) { | ||
75 | wil_err(wil, | ||
76 | "num_descriptors(%d) exceeds max ring size %d\n", | ||
77 | num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX); | ||
78 | last_cmd_err = -EINVAL; | ||
79 | goto no_release_err; | ||
80 | } | ||
81 | |||
82 | if (num_descriptors > INT_MAX / descriptor_size) { | ||
83 | wil_err(wil, | ||
84 | "Overflow in num_descriptors(%d)*descriptor_size(%d)\n", | ||
85 | num_descriptors, descriptor_size); | ||
86 | last_cmd_err = -EINVAL; | ||
87 | goto no_release_err; | ||
88 | } | ||
65 | 89 | ||
66 | pmc->num_descriptors = num_descriptors; | 90 | pmc->num_descriptors = num_descriptors; |
67 | pmc->descriptor_size = descriptor_size; | 91 | pmc->descriptor_size = descriptor_size; |
@@ -189,7 +213,7 @@ release_pmc_skb_list: | |||
189 | pmc->descriptors = NULL; | 213 | pmc->descriptors = NULL; |
190 | 214 | ||
191 | no_release_err: | 215 | no_release_err: |
192 | pmc->last_cmd_status = -ENOMEM; | 216 | pmc->last_cmd_status = last_cmd_err; |
193 | mutex_unlock(&pmc->lock); | 217 | mutex_unlock(&pmc->lock); |
194 | } | 218 | } |
195 | 219 | ||
@@ -295,7 +319,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, | |||
295 | size_t retval = 0; | 319 | size_t retval = 0; |
296 | unsigned long long idx; | 320 | unsigned long long idx; |
297 | loff_t offset; | 321 | loff_t offset; |
298 | size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors; | 322 | size_t pmc_size; |
299 | 323 | ||
300 | mutex_lock(&pmc->lock); | 324 | mutex_lock(&pmc->lock); |
301 | 325 | ||
@@ -306,6 +330,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, | |||
306 | return -EPERM; | 330 | return -EPERM; |
307 | } | 331 | } |
308 | 332 | ||
333 | pmc_size = pmc->descriptor_size * pmc->num_descriptors; | ||
334 | |||
309 | wil_dbg_misc(wil, | 335 | wil_dbg_misc(wil, |
310 | "%s: size %u, pos %lld\n", | 336 | "%s: size %u, pos %lld\n", |
311 | __func__, (unsigned)count, *f_pos); | 337 | __func__, (unsigned)count, *f_pos); |
@@ -345,7 +371,18 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence) | |||
345 | loff_t newpos; | 371 | loff_t newpos; |
346 | struct wil6210_priv *wil = filp->private_data; | 372 | struct wil6210_priv *wil = filp->private_data; |
347 | struct pmc_ctx *pmc = &wil->pmc; | 373 | struct pmc_ctx *pmc = &wil->pmc; |
348 | size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors; | 374 | size_t pmc_size; |
375 | |||
376 | mutex_lock(&pmc->lock); | ||
377 | |||
378 | if (!wil_is_pmc_allocated(pmc)) { | ||
379 | wil_err(wil, "error, pmc is not allocated!\n"); | ||
380 | pmc->last_cmd_status = -EPERM; | ||
381 | mutex_unlock(&pmc->lock); | ||
382 | return -EPERM; | ||
383 | } | ||
384 | |||
385 | pmc_size = pmc->descriptor_size * pmc->num_descriptors; | ||
349 | 386 | ||
350 | switch (whence) { | 387 | switch (whence) { |
351 | case 0: /* SEEK_SET */ | 388 | case 0: /* SEEK_SET */ |
@@ -361,15 +398,21 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence) | |||
361 | break; | 398 | break; |
362 | 399 | ||
363 | default: /* can't happen */ | 400 | default: /* can't happen */ |
364 | return -EINVAL; | 401 | newpos = -EINVAL; |
402 | goto out; | ||
365 | } | 403 | } |
366 | 404 | ||
367 | if (newpos < 0) | 405 | if (newpos < 0) { |
368 | return -EINVAL; | 406 | newpos = -EINVAL; |
407 | goto out; | ||
408 | } | ||
369 | if (newpos > pmc_size) | 409 | if (newpos > pmc_size) |
370 | newpos = pmc_size; | 410 | newpos = pmc_size; |
371 | 411 | ||
372 | filp->f_pos = newpos; | 412 | filp->f_pos = newpos; |
373 | 413 | ||
414 | out: | ||
415 | mutex_unlock(&pmc->lock); | ||
416 | |||
374 | return newpos; | 417 | return newpos; |
375 | } | 418 | } |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 4c38520d4dd2..4ac9ba04afed 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -88,6 +88,18 @@ static inline int wil_vring_wmark_high(struct vring *vring) | |||
88 | return vring->size/4; | 88 | return vring->size/4; |
89 | } | 89 | } |
90 | 90 | ||
91 | /* returns true if num avail descriptors is lower than wmark_low */ | ||
92 | static inline int wil_vring_avail_low(struct vring *vring) | ||
93 | { | ||
94 | return wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring); | ||
95 | } | ||
96 | |||
97 | /* returns true if num avail descriptors is higher than wmark_high */ | ||
98 | static inline int wil_vring_avail_high(struct vring *vring) | ||
99 | { | ||
100 | return wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring); | ||
101 | } | ||
102 | |||
91 | /* wil_val_in_range - check if value in [min,max) */ | 103 | /* wil_val_in_range - check if value in [min,max) */ |
92 | static inline bool wil_val_in_range(int val, int min, int max) | 104 | static inline bool wil_val_in_range(int val, int min, int max) |
93 | { | 105 | { |
@@ -1780,6 +1792,89 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1780 | return rc; | 1792 | return rc; |
1781 | } | 1793 | } |
1782 | 1794 | ||
1795 | /** | ||
1796 | * Check status of tx vrings and stop/wake net queues if needed | ||
1797 | * | ||
1798 | * This function does one of two checks: | ||
1799 | * In case check_stop is true, will check if net queues need to be stopped. If | ||
1800 | * the conditions for stopping are met, netif_tx_stop_all_queues() is called. | ||
1801 | * In case check_stop is false, will check if net queues need to be waked. If | ||
1802 | * the conditions for waking are met, netif_tx_wake_all_queues() is called. | ||
1803 | * vring is the vring which is currently being modified by either adding | ||
1804 | * descriptors (tx) into it or removing descriptors (tx complete) from it. Can | ||
1805 | * be null when irrelevant (e.g. connect/disconnect events). | ||
1806 | * | ||
1807 | * The implementation is to stop net queues if modified vring has low | ||
1808 | * descriptor availability. Wake if all vrings are not in low descriptor | ||
1809 | * availability and modified vring has high descriptor availability. | ||
1810 | */ | ||
1811 | static inline void __wil_update_net_queues(struct wil6210_priv *wil, | ||
1812 | struct vring *vring, | ||
1813 | bool check_stop) | ||
1814 | { | ||
1815 | int i; | ||
1816 | |||
1817 | if (vring) | ||
1818 | wil_dbg_txrx(wil, "vring %d, check_stop=%d, stopped=%d", | ||
1819 | (int)(vring - wil->vring_tx), check_stop, | ||
1820 | wil->net_queue_stopped); | ||
1821 | else | ||
1822 | wil_dbg_txrx(wil, "check_stop=%d, stopped=%d", | ||
1823 | check_stop, wil->net_queue_stopped); | ||
1824 | |||
1825 | if (check_stop == wil->net_queue_stopped) | ||
1826 | /* net queues already in desired state */ | ||
1827 | return; | ||
1828 | |||
1829 | if (check_stop) { | ||
1830 | if (!vring || unlikely(wil_vring_avail_low(vring))) { | ||
1831 | /* not enough room in the vring */ | ||
1832 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
1833 | wil->net_queue_stopped = true; | ||
1834 | wil_dbg_txrx(wil, "netif_tx_stop called\n"); | ||
1835 | } | ||
1836 | return; | ||
1837 | } | ||
1838 | |||
1839 | /* check wake */ | ||
1840 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | ||
1841 | struct vring *cur_vring = &wil->vring_tx[i]; | ||
1842 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; | ||
1843 | |||
1844 | if (!cur_vring->va || !txdata->enabled || cur_vring == vring) | ||
1845 | continue; | ||
1846 | |||
1847 | if (wil_vring_avail_low(cur_vring)) { | ||
1848 | wil_dbg_txrx(wil, "vring %d full, can't wake\n", | ||
1849 | (int)(cur_vring - wil->vring_tx)); | ||
1850 | return; | ||
1851 | } | ||
1852 | } | ||
1853 | |||
1854 | if (!vring || wil_vring_avail_high(vring)) { | ||
1855 | /* enough room in the vring */ | ||
1856 | wil_dbg_txrx(wil, "calling netif_tx_wake\n"); | ||
1857 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | ||
1858 | wil->net_queue_stopped = false; | ||
1859 | } | ||
1860 | } | ||
1861 | |||
1862 | void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring, | ||
1863 | bool check_stop) | ||
1864 | { | ||
1865 | spin_lock(&wil->net_queue_lock); | ||
1866 | __wil_update_net_queues(wil, vring, check_stop); | ||
1867 | spin_unlock(&wil->net_queue_lock); | ||
1868 | } | ||
1869 | |||
1870 | void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring, | ||
1871 | bool check_stop) | ||
1872 | { | ||
1873 | spin_lock_bh(&wil->net_queue_lock); | ||
1874 | __wil_update_net_queues(wil, vring, check_stop); | ||
1875 | spin_unlock_bh(&wil->net_queue_lock); | ||
1876 | } | ||
1877 | |||
1783 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 1878 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
1784 | { | 1879 | { |
1785 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 1880 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
@@ -1822,14 +1917,10 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
1822 | /* set up vring entry */ | 1917 | /* set up vring entry */ |
1823 | rc = wil_tx_vring(wil, vring, skb); | 1918 | rc = wil_tx_vring(wil, vring, skb); |
1824 | 1919 | ||
1825 | /* do we still have enough room in the vring? */ | ||
1826 | if (unlikely(wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))) { | ||
1827 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
1828 | wil_dbg_txrx(wil, "netif_tx_stop : ring full\n"); | ||
1829 | } | ||
1830 | |||
1831 | switch (rc) { | 1920 | switch (rc) { |
1832 | case 0: | 1921 | case 0: |
1922 | /* shall we stop net queues? */ | ||
1923 | wil_update_net_queues_bh(wil, vring, true); | ||
1833 | /* statistics will be updated on the tx_complete */ | 1924 | /* statistics will be updated on the tx_complete */ |
1834 | dev_kfree_skb_any(skb); | 1925 | dev_kfree_skb_any(skb); |
1835 | return NETDEV_TX_OK; | 1926 | return NETDEV_TX_OK; |
@@ -1978,10 +2069,9 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1978 | txdata->last_idle = get_cycles(); | 2069 | txdata->last_idle = get_cycles(); |
1979 | } | 2070 | } |
1980 | 2071 | ||
1981 | if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring)) { | 2072 | /* shall we wake net queues? */ |
1982 | wil_dbg_txrx(wil, "netif_tx_wake : ring not full\n"); | 2073 | if (done) |
1983 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | 2074 | wil_update_net_queues(wil, vring, false); |
1984 | } | ||
1985 | 2075 | ||
1986 | return done; | 2076 | return done; |
1987 | } | 2077 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index a949cd62bc4e..237e1666df2d 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -276,10 +276,11 @@ struct fw_map { | |||
276 | u32 to; /* linker address - to, exclusive */ | 276 | u32 to; /* linker address - to, exclusive */ |
277 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ | 277 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ |
278 | const char *name; /* for debugfs */ | 278 | const char *name; /* for debugfs */ |
279 | bool fw; /* true if FW mapping, false if UCODE mapping */ | ||
279 | }; | 280 | }; |
280 | 281 | ||
281 | /* array size should be in sync with actual definition in the wmi.c */ | 282 | /* array size should be in sync with actual definition in the wmi.c */ |
282 | extern const struct fw_map fw_mapping[8]; | 283 | extern const struct fw_map fw_mapping[10]; |
283 | 284 | ||
284 | /** | 285 | /** |
285 | * mk_cidxtid - construct @cidxtid field | 286 | * mk_cidxtid - construct @cidxtid field |
@@ -461,8 +462,11 @@ struct wil_p2p_info { | |||
461 | u8 discovery_started; | 462 | u8 discovery_started; |
462 | u8 p2p_dev_started; | 463 | u8 p2p_dev_started; |
463 | u64 cookie; | 464 | u64 cookie; |
465 | struct wireless_dev *pending_listen_wdev; | ||
466 | unsigned int listen_duration; | ||
464 | struct timer_list discovery_timer; /* listen/search duration */ | 467 | struct timer_list discovery_timer; /* listen/search duration */ |
465 | struct work_struct discovery_expired_work; /* listen/search expire */ | 468 | struct work_struct discovery_expired_work; /* listen/search expire */ |
469 | struct work_struct delayed_listen_work; /* listen after scan done */ | ||
466 | }; | 470 | }; |
467 | 471 | ||
468 | enum wil_sta_status { | 472 | enum wil_sta_status { |
@@ -624,6 +628,8 @@ struct wil6210_priv { | |||
624 | * - consumed in thread by wmi_event_worker | 628 | * - consumed in thread by wmi_event_worker |
625 | */ | 629 | */ |
626 | spinlock_t wmi_ev_lock; | 630 | spinlock_t wmi_ev_lock; |
631 | spinlock_t net_queue_lock; /* guarding stop/wake netif queue */ | ||
632 | int net_queue_stopped; /* netif_tx_stop_all_queues invoked */ | ||
627 | struct napi_struct napi_rx; | 633 | struct napi_struct napi_rx; |
628 | struct napi_struct napi_tx; | 634 | struct napi_struct napi_tx; |
629 | /* keep alive */ | 635 | /* keep alive */ |
@@ -817,6 +823,10 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); | |||
817 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); | 823 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); |
818 | int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | 824 | int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, |
819 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); | 825 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); |
826 | int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, | ||
827 | enum wmi_ps_profile_type ps_profile); | ||
828 | int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); | ||
829 | int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); | ||
820 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, | 830 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, |
821 | u8 dialog_token, __le16 ba_param_set, | 831 | u8 dialog_token, __le16 ba_param_set, |
822 | __le16 ba_timeout, __le16 ba_seq_ctrl); | 832 | __le16 ba_timeout, __le16 ba_seq_ctrl); |
@@ -837,13 +847,15 @@ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request); | |||
837 | void wil_p2p_discovery_timer_fn(ulong x); | 847 | void wil_p2p_discovery_timer_fn(ulong x); |
838 | int wil_p2p_search(struct wil6210_priv *wil, | 848 | int wil_p2p_search(struct wil6210_priv *wil, |
839 | struct cfg80211_scan_request *request); | 849 | struct cfg80211_scan_request *request); |
840 | int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, | 850 | int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, |
841 | struct ieee80211_channel *chan, u64 *cookie); | 851 | unsigned int duration, struct ieee80211_channel *chan, |
852 | u64 *cookie); | ||
842 | u8 wil_p2p_stop_discovery(struct wil6210_priv *wil); | 853 | u8 wil_p2p_stop_discovery(struct wil6210_priv *wil); |
843 | int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); | 854 | int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); |
844 | void wil_p2p_listen_expired(struct work_struct *work); | 855 | void wil_p2p_listen_expired(struct work_struct *work); |
845 | void wil_p2p_search_expired(struct work_struct *work); | 856 | void wil_p2p_search_expired(struct work_struct *work); |
846 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil); | 857 | void wil_p2p_stop_radio_operations(struct wil6210_priv *wil); |
858 | void wil_p2p_delayed_listen_work(struct work_struct *work); | ||
847 | 859 | ||
848 | /* WMI for P2P */ | 860 | /* WMI for P2P */ |
849 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi); | 861 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi); |
@@ -869,6 +881,9 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, | |||
869 | u8 chan, u8 hidden_ssid, u8 is_go); | 881 | u8 chan, u8 hidden_ssid, u8 is_go); |
870 | int wmi_pcp_stop(struct wil6210_priv *wil); | 882 | int wmi_pcp_stop(struct wil6210_priv *wil); |
871 | int wmi_led_cfg(struct wil6210_priv *wil, bool enable); | 883 | int wmi_led_cfg(struct wil6210_priv *wil, bool enable); |
884 | int wmi_abort_scan(struct wil6210_priv *wil); | ||
885 | void wil_abort_scan(struct wil6210_priv *wil, bool sync); | ||
886 | |||
872 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 887 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
873 | u16 reason_code, bool from_event); | 888 | u16 reason_code, bool from_event); |
874 | void wil_probe_client_flush(struct wil6210_priv *wil); | 889 | void wil_probe_client_flush(struct wil6210_priv *wil); |
@@ -886,6 +901,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); | |||
886 | int wil_bcast_init(struct wil6210_priv *wil); | 901 | int wil_bcast_init(struct wil6210_priv *wil); |
887 | void wil_bcast_fini(struct wil6210_priv *wil); | 902 | void wil_bcast_fini(struct wil6210_priv *wil); |
888 | 903 | ||
904 | void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring, | ||
905 | bool should_stop); | ||
906 | void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring, | ||
907 | bool check_stop); | ||
889 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | 908 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); |
890 | int wil_tx_complete(struct wil6210_priv *wil, int ringid); | 909 | int wil_tx_complete(struct wil6210_priv *wil, int ringid); |
891 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil); | 910 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c index b57d280946e0..d051eea47a54 100644 --- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c | |||
@@ -36,6 +36,9 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, | |||
36 | for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) { | 36 | for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) { |
37 | map = &fw_mapping[i]; | 37 | map = &fw_mapping[i]; |
38 | 38 | ||
39 | if (!map->fw) | ||
40 | continue; | ||
41 | |||
39 | if (map->host < host_min) | 42 | if (map->host < host_min) |
40 | host_min = map->host; | 43 | host_min = map->host; |
41 | 44 | ||
@@ -73,6 +76,9 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) | |||
73 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { | 76 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { |
74 | map = &fw_mapping[i]; | 77 | map = &fw_mapping[i]; |
75 | 78 | ||
79 | if (!map->fw) | ||
80 | continue; | ||
81 | |||
76 | data = (void * __force)wil->csr + HOSTADDR(map->host); | 82 | data = (void * __force)wil->csr + HOSTADDR(map->host); |
77 | len = map->to - map->from; | 83 | len = map->to - map->from; |
78 | offset = map->host - host_min; | 84 | offset = map->host - host_min; |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index fae4f1285d08..7585003bef67 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -84,19 +84,29 @@ MODULE_PARM_DESC(led_id, | |||
84 | * array size should be in sync with the declaration in the wil6210.h | 84 | * array size should be in sync with the declaration in the wil6210.h |
85 | */ | 85 | */ |
86 | const struct fw_map fw_mapping[] = { | 86 | const struct fw_map fw_mapping[] = { |
87 | {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */ | 87 | /* FW code RAM 256k */ |
88 | {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */ | 88 | {0x000000, 0x040000, 0x8c0000, "fw_code", true}, |
89 | {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */ | 89 | /* FW data RAM 32k */ |
90 | {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */ | 90 | {0x800000, 0x808000, 0x900000, "fw_data", true}, |
91 | {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */ | 91 | /* periph data 128k */ |
92 | {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */ | 92 | {0x840000, 0x860000, 0x908000, "fw_peri", true}, |
93 | {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf 512b */ | 93 | /* various RGF 40k */ |
94 | {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */ | 94 | {0x880000, 0x88a000, 0x880000, "rgf", true}, |
95 | /* | 95 | /* AGC table 4k */ |
96 | * 920000..930000 ucode code RAM | 96 | {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true}, |
97 | * 930000..932000 ucode data RAM | 97 | /* Pcie_ext_rgf 4k */ |
98 | * 932000..949000 back-door debug data | 98 | {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true}, |
99 | /* mac_ext_rgf 512b */ | ||
100 | {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true}, | ||
101 | /* upper area 548k */ | ||
102 | {0x8c0000, 0x949000, 0x8c0000, "upper", true}, | ||
103 | /* UCODE areas - accessible by debugfs blobs but not by | ||
104 | * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas! | ||
99 | */ | 105 | */ |
106 | /* ucode code RAM 128k */ | ||
107 | {0x000000, 0x020000, 0x920000, "uc_code", false}, | ||
108 | /* ucode data RAM 16k */ | ||
109 | {0x800000, 0x804000, 0x940000, "uc_data", false}, | ||
100 | }; | 110 | }; |
101 | 111 | ||
102 | struct blink_on_off_time led_blink_time[] = { | 112 | struct blink_on_off_time led_blink_time[] = { |
@@ -108,7 +118,7 @@ struct blink_on_off_time led_blink_time[] = { | |||
108 | u8 led_polarity = LED_POLARITY_LOW_ACTIVE; | 118 | u8 led_polarity = LED_POLARITY_LOW_ACTIVE; |
109 | 119 | ||
110 | /** | 120 | /** |
111 | * return AHB address for given firmware/ucode internal (linker) address | 121 | * return AHB address for given firmware internal (linker) address |
112 | * @x - internal address | 122 | * @x - internal address |
113 | * If address have no valid AHB mapping, return 0 | 123 | * If address have no valid AHB mapping, return 0 |
114 | */ | 124 | */ |
@@ -117,7 +127,8 @@ static u32 wmi_addr_remap(u32 x) | |||
117 | uint i; | 127 | uint i; |
118 | 128 | ||
119 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { | 129 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { |
120 | if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) | 130 | if (fw_mapping[i].fw && |
131 | ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to))) | ||
121 | return x + fw_mapping[i].host - fw_mapping[i].from; | 132 | return x + fw_mapping[i].host - fw_mapping[i].from; |
122 | } | 133 | } |
123 | 134 | ||
@@ -427,18 +438,24 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, | |||
427 | mutex_lock(&wil->p2p_wdev_mutex); | 438 | mutex_lock(&wil->p2p_wdev_mutex); |
428 | if (wil->scan_request) { | 439 | if (wil->scan_request) { |
429 | struct wmi_scan_complete_event *data = d; | 440 | struct wmi_scan_complete_event *data = d; |
441 | int status = le32_to_cpu(data->status); | ||
430 | struct cfg80211_scan_info info = { | 442 | struct cfg80211_scan_info info = { |
431 | .aborted = (data->status != WMI_SCAN_SUCCESS), | 443 | .aborted = ((status != WMI_SCAN_SUCCESS) && |
444 | (status != WMI_SCAN_ABORT_REJECTED)), | ||
432 | }; | 445 | }; |
433 | 446 | ||
434 | wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); | 447 | wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status); |
435 | wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", | 448 | wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", |
436 | wil->scan_request, info.aborted); | 449 | wil->scan_request, info.aborted); |
437 | |||
438 | del_timer_sync(&wil->scan_timer); | 450 | del_timer_sync(&wil->scan_timer); |
439 | cfg80211_scan_done(wil->scan_request, &info); | 451 | cfg80211_scan_done(wil->scan_request, &info); |
440 | wil->radio_wdev = wil->wdev; | 452 | wil->radio_wdev = wil->wdev; |
441 | wil->scan_request = NULL; | 453 | wil->scan_request = NULL; |
454 | wake_up_interruptible(&wil->wq); | ||
455 | if (wil->p2p.pending_listen_wdev) { | ||
456 | wil_dbg_misc(wil, "Scheduling delayed listen\n"); | ||
457 | schedule_work(&wil->p2p.delayed_listen_work); | ||
458 | } | ||
442 | } else { | 459 | } else { |
443 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); | 460 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); |
444 | } | 461 | } |
@@ -548,7 +565,6 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
548 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | 565 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || |
549 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | 566 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { |
550 | if (rc) { | 567 | if (rc) { |
551 | netif_tx_stop_all_queues(ndev); | ||
552 | netif_carrier_off(ndev); | 568 | netif_carrier_off(ndev); |
553 | wil_err(wil, | 569 | wil_err(wil, |
554 | "%s: cfg80211_connect_result with failure\n", | 570 | "%s: cfg80211_connect_result with failure\n", |
@@ -588,7 +604,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
588 | 604 | ||
589 | wil->sta[evt->cid].status = wil_sta_connected; | 605 | wil->sta[evt->cid].status = wil_sta_connected; |
590 | set_bit(wil_status_fwconnected, wil->status); | 606 | set_bit(wil_status_fwconnected, wil->status); |
591 | netif_tx_wake_all_queues(ndev); | 607 | wil_update_net_queues_bh(wil, NULL, false); |
592 | 608 | ||
593 | out: | 609 | out: |
594 | if (rc) | 610 | if (rc) |
@@ -1564,6 +1580,112 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | |||
1564 | return rc; | 1580 | return rc; |
1565 | } | 1581 | } |
1566 | 1582 | ||
1583 | int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, | ||
1584 | enum wmi_ps_profile_type ps_profile) | ||
1585 | { | ||
1586 | int rc; | ||
1587 | struct wmi_ps_dev_profile_cfg_cmd cmd = { | ||
1588 | .ps_profile = ps_profile, | ||
1589 | }; | ||
1590 | struct { | ||
1591 | struct wmi_cmd_hdr wmi; | ||
1592 | struct wmi_ps_dev_profile_cfg_event evt; | ||
1593 | } __packed reply; | ||
1594 | u32 status; | ||
1595 | |||
1596 | wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile); | ||
1597 | |||
1598 | reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR); | ||
1599 | |||
1600 | rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd), | ||
1601 | WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply), | ||
1602 | 100); | ||
1603 | if (rc) | ||
1604 | return rc; | ||
1605 | |||
1606 | status = le32_to_cpu(reply.evt.status); | ||
1607 | |||
1608 | if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) { | ||
1609 | wil_err(wil, "ps dev profile cfg failed with status %d\n", | ||
1610 | status); | ||
1611 | rc = -EINVAL; | ||
1612 | } | ||
1613 | |||
1614 | return rc; | ||
1615 | } | ||
1616 | |||
1617 | int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) | ||
1618 | { | ||
1619 | int rc; | ||
1620 | struct wmi_set_mgmt_retry_limit_cmd cmd = { | ||
1621 | .mgmt_retry_limit = retry_short, | ||
1622 | }; | ||
1623 | struct { | ||
1624 | struct wmi_cmd_hdr wmi; | ||
1625 | struct wmi_set_mgmt_retry_limit_event evt; | ||
1626 | } __packed reply; | ||
1627 | |||
1628 | wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short); | ||
1629 | |||
1630 | if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities)) | ||
1631 | return -ENOTSUPP; | ||
1632 | |||
1633 | reply.evt.status = WMI_FW_STATUS_FAILURE; | ||
1634 | |||
1635 | rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd), | ||
1636 | WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), | ||
1637 | 100); | ||
1638 | if (rc) | ||
1639 | return rc; | ||
1640 | |||
1641 | if (reply.evt.status != WMI_FW_STATUS_SUCCESS) { | ||
1642 | wil_err(wil, "set mgmt retry limit failed with status %d\n", | ||
1643 | reply.evt.status); | ||
1644 | rc = -EINVAL; | ||
1645 | } | ||
1646 | |||
1647 | return rc; | ||
1648 | } | ||
1649 | |||
1650 | int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) | ||
1651 | { | ||
1652 | int rc; | ||
1653 | struct { | ||
1654 | struct wmi_cmd_hdr wmi; | ||
1655 | struct wmi_get_mgmt_retry_limit_event evt; | ||
1656 | } __packed reply; | ||
1657 | |||
1658 | wil_dbg_wmi(wil, "getting mgmt retry short\n"); | ||
1659 | |||
1660 | if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities)) | ||
1661 | return -ENOTSUPP; | ||
1662 | |||
1663 | reply.evt.mgmt_retry_limit = 0; | ||
1664 | rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0, | ||
1665 | WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), | ||
1666 | 100); | ||
1667 | if (rc) | ||
1668 | return rc; | ||
1669 | |||
1670 | if (retry_short) | ||
1671 | *retry_short = reply.evt.mgmt_retry_limit; | ||
1672 | |||
1673 | return 0; | ||
1674 | } | ||
1675 | |||
1676 | int wmi_abort_scan(struct wil6210_priv *wil) | ||
1677 | { | ||
1678 | int rc; | ||
1679 | |||
1680 | wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n"); | ||
1681 | |||
1682 | rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0); | ||
1683 | if (rc) | ||
1684 | wil_err(wil, "Failed to abort scan (%d)\n", rc); | ||
1685 | |||
1686 | return rc; | ||
1687 | } | ||
1688 | |||
1567 | void wmi_event_flush(struct wil6210_priv *wil) | 1689 | void wmi_event_flush(struct wil6210_priv *wil) |
1568 | { | 1690 | { |
1569 | struct pending_wmi_event *evt, *t; | 1691 | struct pending_wmi_event *evt, *t; |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index f430e8a80603..d93a4d490d24 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #define WMI_MAC_LEN (6) | 35 | #define WMI_MAC_LEN (6) |
36 | #define WMI_PROX_RANGE_NUM (3) | 36 | #define WMI_PROX_RANGE_NUM (3) |
37 | #define WMI_MAX_LOSS_DMG_BEACONS (20) | 37 | #define WMI_MAX_LOSS_DMG_BEACONS (20) |
38 | #define MAX_NUM_OF_SECTORS (128) | ||
38 | 39 | ||
39 | /* Mailbox interface | 40 | /* Mailbox interface |
40 | * used for commands and events | 41 | * used for commands and events |
@@ -51,8 +52,10 @@ enum wmi_mid { | |||
51 | * the host | 52 | * the host |
52 | */ | 53 | */ |
53 | enum wmi_fw_capability { | 54 | enum wmi_fw_capability { |
54 | WMI_FW_CAPABILITY_FTM = 0, | 55 | WMI_FW_CAPABILITY_FTM = 0, |
55 | WMI_FW_CAPABILITY_PS_CONFIG = 1, | 56 | WMI_FW_CAPABILITY_PS_CONFIG = 1, |
57 | WMI_FW_CAPABILITY_RF_SECTORS = 2, | ||
58 | WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3, | ||
56 | WMI_FW_CAPABILITY_MAX, | 59 | WMI_FW_CAPABILITY_MAX, |
57 | }; | 60 | }; |
58 | 61 | ||
@@ -66,137 +69,149 @@ struct wmi_cmd_hdr { | |||
66 | 69 | ||
67 | /* List of Commands */ | 70 | /* List of Commands */ |
68 | enum wmi_command_id { | 71 | enum wmi_command_id { |
69 | WMI_CONNECT_CMDID = 0x01, | 72 | WMI_CONNECT_CMDID = 0x01, |
70 | WMI_DISCONNECT_CMDID = 0x03, | 73 | WMI_DISCONNECT_CMDID = 0x03, |
71 | WMI_DISCONNECT_STA_CMDID = 0x04, | 74 | WMI_DISCONNECT_STA_CMDID = 0x04, |
72 | WMI_START_SCAN_CMDID = 0x07, | 75 | WMI_START_SCAN_CMDID = 0x07, |
73 | WMI_SET_BSS_FILTER_CMDID = 0x09, | 76 | WMI_SET_BSS_FILTER_CMDID = 0x09, |
74 | WMI_SET_PROBED_SSID_CMDID = 0x0A, | 77 | WMI_SET_PROBED_SSID_CMDID = 0x0A, |
75 | WMI_SET_LISTEN_INT_CMDID = 0x0B, | 78 | WMI_SET_LISTEN_INT_CMDID = 0x0B, |
76 | WMI_BCON_CTRL_CMDID = 0x0F, | 79 | WMI_BCON_CTRL_CMDID = 0x0F, |
77 | WMI_ADD_CIPHER_KEY_CMDID = 0x16, | 80 | WMI_ADD_CIPHER_KEY_CMDID = 0x16, |
78 | WMI_DELETE_CIPHER_KEY_CMDID = 0x17, | 81 | WMI_DELETE_CIPHER_KEY_CMDID = 0x17, |
79 | WMI_PCP_CONF_CMDID = 0x18, | 82 | WMI_PCP_CONF_CMDID = 0x18, |
80 | WMI_SET_APPIE_CMDID = 0x3F, | 83 | WMI_SET_APPIE_CMDID = 0x3F, |
81 | WMI_SET_WSC_STATUS_CMDID = 0x41, | 84 | WMI_SET_WSC_STATUS_CMDID = 0x41, |
82 | WMI_PXMT_RANGE_CFG_CMDID = 0x42, | 85 | WMI_PXMT_RANGE_CFG_CMDID = 0x42, |
83 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43, | 86 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43, |
84 | WMI_MEM_READ_CMDID = 0x800, | 87 | WMI_MEM_READ_CMDID = 0x800, |
85 | WMI_MEM_WR_CMDID = 0x801, | 88 | WMI_MEM_WR_CMDID = 0x801, |
86 | WMI_ECHO_CMDID = 0x803, | 89 | WMI_ECHO_CMDID = 0x803, |
87 | WMI_DEEP_ECHO_CMDID = 0x804, | 90 | WMI_DEEP_ECHO_CMDID = 0x804, |
88 | WMI_CONFIG_MAC_CMDID = 0x805, | 91 | WMI_CONFIG_MAC_CMDID = 0x805, |
89 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x806, | 92 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x806, |
90 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808, | 93 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808, |
91 | WMI_PHY_GET_STATISTICS_CMDID = 0x809, | 94 | WMI_PHY_GET_STATISTICS_CMDID = 0x809, |
92 | WMI_FS_TUNE_CMDID = 0x80A, | 95 | WMI_FS_TUNE_CMDID = 0x80A, |
93 | WMI_CORR_MEASURE_CMDID = 0x80B, | 96 | WMI_CORR_MEASURE_CMDID = 0x80B, |
94 | WMI_READ_RSSI_CMDID = 0x80C, | 97 | WMI_READ_RSSI_CMDID = 0x80C, |
95 | WMI_TEMP_SENSE_CMDID = 0x80E, | 98 | WMI_TEMP_SENSE_CMDID = 0x80E, |
96 | WMI_DC_CALIB_CMDID = 0x80F, | 99 | WMI_DC_CALIB_CMDID = 0x80F, |
97 | WMI_SEND_TONE_CMDID = 0x810, | 100 | WMI_SEND_TONE_CMDID = 0x810, |
98 | WMI_IQ_TX_CALIB_CMDID = 0x811, | 101 | WMI_IQ_TX_CALIB_CMDID = 0x811, |
99 | WMI_IQ_RX_CALIB_CMDID = 0x812, | 102 | WMI_IQ_RX_CALIB_CMDID = 0x812, |
100 | WMI_SET_UCODE_IDLE_CMDID = 0x813, | 103 | WMI_SET_UCODE_IDLE_CMDID = 0x813, |
101 | WMI_SET_WORK_MODE_CMDID = 0x815, | 104 | WMI_SET_WORK_MODE_CMDID = 0x815, |
102 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x816, | 105 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x816, |
103 | WMI_MARLON_R_READ_CMDID = 0x818, | 106 | WMI_MARLON_R_READ_CMDID = 0x818, |
104 | WMI_MARLON_R_WRITE_CMDID = 0x819, | 107 | WMI_MARLON_R_WRITE_CMDID = 0x819, |
105 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A, | 108 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A, |
106 | MAC_IO_STATIC_PARAMS_CMDID = 0x81B, | 109 | MAC_IO_STATIC_PARAMS_CMDID = 0x81B, |
107 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C, | 110 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C, |
108 | WMI_SILENT_RSSI_CALIB_CMDID = 0x81D, | 111 | WMI_SILENT_RSSI_CALIB_CMDID = 0x81D, |
109 | WMI_RF_RX_TEST_CMDID = 0x81E, | 112 | WMI_RF_RX_TEST_CMDID = 0x81E, |
110 | WMI_CFG_RX_CHAIN_CMDID = 0x820, | 113 | WMI_CFG_RX_CHAIN_CMDID = 0x820, |
111 | WMI_VRING_CFG_CMDID = 0x821, | 114 | WMI_VRING_CFG_CMDID = 0x821, |
112 | WMI_BCAST_VRING_CFG_CMDID = 0x822, | 115 | WMI_BCAST_VRING_CFG_CMDID = 0x822, |
113 | WMI_VRING_BA_EN_CMDID = 0x823, | 116 | WMI_VRING_BA_EN_CMDID = 0x823, |
114 | WMI_VRING_BA_DIS_CMDID = 0x824, | 117 | WMI_VRING_BA_DIS_CMDID = 0x824, |
115 | WMI_RCP_ADDBA_RESP_CMDID = 0x825, | 118 | WMI_RCP_ADDBA_RESP_CMDID = 0x825, |
116 | WMI_RCP_DELBA_CMDID = 0x826, | 119 | WMI_RCP_DELBA_CMDID = 0x826, |
117 | WMI_SET_SSID_CMDID = 0x827, | 120 | WMI_SET_SSID_CMDID = 0x827, |
118 | WMI_GET_SSID_CMDID = 0x828, | 121 | WMI_GET_SSID_CMDID = 0x828, |
119 | WMI_SET_PCP_CHANNEL_CMDID = 0x829, | 122 | WMI_SET_PCP_CHANNEL_CMDID = 0x829, |
120 | WMI_GET_PCP_CHANNEL_CMDID = 0x82A, | 123 | WMI_GET_PCP_CHANNEL_CMDID = 0x82A, |
121 | WMI_SW_TX_REQ_CMDID = 0x82B, | 124 | WMI_SW_TX_REQ_CMDID = 0x82B, |
122 | WMI_READ_MAC_RXQ_CMDID = 0x830, | 125 | WMI_READ_MAC_RXQ_CMDID = 0x830, |
123 | WMI_READ_MAC_TXQ_CMDID = 0x831, | 126 | WMI_READ_MAC_TXQ_CMDID = 0x831, |
124 | WMI_WRITE_MAC_RXQ_CMDID = 0x832, | 127 | WMI_WRITE_MAC_RXQ_CMDID = 0x832, |
125 | WMI_WRITE_MAC_TXQ_CMDID = 0x833, | 128 | WMI_WRITE_MAC_TXQ_CMDID = 0x833, |
126 | WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834, | 129 | WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834, |
127 | WMI_MLME_PUSH_CMDID = 0x835, | 130 | WMI_MLME_PUSH_CMDID = 0x835, |
128 | WMI_BEAMFORMING_MGMT_CMDID = 0x836, | 131 | WMI_BEAMFORMING_MGMT_CMDID = 0x836, |
129 | WMI_BF_TXSS_MGMT_CMDID = 0x837, | 132 | WMI_BF_TXSS_MGMT_CMDID = 0x837, |
130 | WMI_BF_SM_MGMT_CMDID = 0x838, | 133 | WMI_BF_SM_MGMT_CMDID = 0x838, |
131 | WMI_BF_RXSS_MGMT_CMDID = 0x839, | 134 | WMI_BF_RXSS_MGMT_CMDID = 0x839, |
132 | WMI_BF_TRIG_CMDID = 0x83A, | 135 | WMI_BF_TRIG_CMDID = 0x83A, |
133 | WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842, | 136 | WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842, |
134 | WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843, | 137 | WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843, |
135 | WMI_SET_SECTORS_CMDID = 0x849, | 138 | WMI_SET_SECTORS_CMDID = 0x849, |
136 | WMI_MAINTAIN_PAUSE_CMDID = 0x850, | 139 | WMI_MAINTAIN_PAUSE_CMDID = 0x850, |
137 | WMI_MAINTAIN_RESUME_CMDID = 0x851, | 140 | WMI_MAINTAIN_RESUME_CMDID = 0x851, |
138 | WMI_RS_MGMT_CMDID = 0x852, | 141 | WMI_RS_MGMT_CMDID = 0x852, |
139 | WMI_RF_MGMT_CMDID = 0x853, | 142 | WMI_RF_MGMT_CMDID = 0x853, |
140 | WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x854, | 143 | WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x854, |
141 | WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855, | 144 | WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855, |
142 | WMI_OTP_READ_CMDID = 0x856, | 145 | WMI_OTP_READ_CMDID = 0x856, |
143 | WMI_OTP_WRITE_CMDID = 0x857, | 146 | WMI_OTP_WRITE_CMDID = 0x857, |
144 | WMI_LED_CFG_CMDID = 0x858, | 147 | WMI_LED_CFG_CMDID = 0x858, |
145 | /* Performance monitoring commands */ | 148 | /* Performance monitoring commands */ |
146 | WMI_BF_CTRL_CMDID = 0x862, | 149 | WMI_BF_CTRL_CMDID = 0x862, |
147 | WMI_NOTIFY_REQ_CMDID = 0x863, | 150 | WMI_NOTIFY_REQ_CMDID = 0x863, |
148 | WMI_GET_STATUS_CMDID = 0x864, | 151 | WMI_GET_STATUS_CMDID = 0x864, |
149 | WMI_GET_RF_STATUS_CMDID = 0x866, | 152 | WMI_GET_RF_STATUS_CMDID = 0x866, |
150 | WMI_GET_BASEBAND_TYPE_CMDID = 0x867, | 153 | WMI_GET_BASEBAND_TYPE_CMDID = 0x867, |
151 | WMI_UNIT_TEST_CMDID = 0x900, | 154 | WMI_UNIT_TEST_CMDID = 0x900, |
152 | WMI_HICCUP_CMDID = 0x901, | 155 | WMI_HICCUP_CMDID = 0x901, |
153 | WMI_FLASH_READ_CMDID = 0x902, | 156 | WMI_FLASH_READ_CMDID = 0x902, |
154 | WMI_FLASH_WRITE_CMDID = 0x903, | 157 | WMI_FLASH_WRITE_CMDID = 0x903, |
155 | /* Power management */ | 158 | /* Power management */ |
156 | WMI_TRAFFIC_DEFERRAL_CMDID = 0x904, | 159 | WMI_TRAFFIC_DEFERRAL_CMDID = 0x904, |
157 | WMI_TRAFFIC_RESUME_CMDID = 0x905, | 160 | WMI_TRAFFIC_RESUME_CMDID = 0x905, |
158 | /* P2P */ | 161 | /* P2P */ |
159 | WMI_P2P_CFG_CMDID = 0x910, | 162 | WMI_P2P_CFG_CMDID = 0x910, |
160 | WMI_PORT_ALLOCATE_CMDID = 0x911, | 163 | WMI_PORT_ALLOCATE_CMDID = 0x911, |
161 | WMI_PORT_DELETE_CMDID = 0x912, | 164 | WMI_PORT_DELETE_CMDID = 0x912, |
162 | WMI_POWER_MGMT_CFG_CMDID = 0x913, | 165 | WMI_POWER_MGMT_CFG_CMDID = 0x913, |
163 | WMI_START_LISTEN_CMDID = 0x914, | 166 | WMI_START_LISTEN_CMDID = 0x914, |
164 | WMI_START_SEARCH_CMDID = 0x915, | 167 | WMI_START_SEARCH_CMDID = 0x915, |
165 | WMI_DISCOVERY_START_CMDID = 0x916, | 168 | WMI_DISCOVERY_START_CMDID = 0x916, |
166 | WMI_DISCOVERY_STOP_CMDID = 0x917, | 169 | WMI_DISCOVERY_STOP_CMDID = 0x917, |
167 | WMI_PCP_START_CMDID = 0x918, | 170 | WMI_PCP_START_CMDID = 0x918, |
168 | WMI_PCP_STOP_CMDID = 0x919, | 171 | WMI_PCP_STOP_CMDID = 0x919, |
169 | WMI_GET_PCP_FACTOR_CMDID = 0x91B, | 172 | WMI_GET_PCP_FACTOR_CMDID = 0x91B, |
170 | /* Power Save Configuration Commands */ | 173 | /* Power Save Configuration Commands */ |
171 | WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C, | 174 | WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C, |
172 | /* Not supported yet */ | 175 | /* Not supported yet */ |
173 | WMI_PS_DEV_CFG_CMDID = 0x91D, | 176 | WMI_PS_DEV_CFG_CMDID = 0x91D, |
174 | /* Not supported yet */ | 177 | /* Not supported yet */ |
175 | WMI_PS_DEV_CFG_READ_CMDID = 0x91E, | 178 | WMI_PS_DEV_CFG_READ_CMDID = 0x91E, |
176 | /* Per MAC Power Save Configuration commands | 179 | /* Per MAC Power Save Configuration commands |
177 | * Not supported yet | 180 | * Not supported yet |
178 | */ | 181 | */ |
179 | WMI_PS_MID_CFG_CMDID = 0x91F, | 182 | WMI_PS_MID_CFG_CMDID = 0x91F, |
180 | /* Not supported yet */ | 183 | /* Not supported yet */ |
181 | WMI_PS_MID_CFG_READ_CMDID = 0x920, | 184 | WMI_PS_MID_CFG_READ_CMDID = 0x920, |
182 | WMI_RS_CFG_CMDID = 0x921, | 185 | WMI_RS_CFG_CMDID = 0x921, |
183 | WMI_GET_DETAILED_RS_RES_CMDID = 0x922, | 186 | WMI_GET_DETAILED_RS_RES_CMDID = 0x922, |
184 | WMI_AOA_MEAS_CMDID = 0x923, | 187 | WMI_AOA_MEAS_CMDID = 0x923, |
185 | WMI_TOF_SESSION_START_CMDID = 0x991, | 188 | WMI_SET_MGMT_RETRY_LIMIT_CMDID = 0x930, |
186 | WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, | 189 | WMI_GET_MGMT_RETRY_LIMIT_CMDID = 0x931, |
187 | WMI_TOF_SET_LCR_CMDID = 0x993, | 190 | WMI_TOF_SESSION_START_CMDID = 0x991, |
188 | WMI_TOF_SET_LCI_CMDID = 0x994, | 191 | WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, |
189 | WMI_TOF_CHANNEL_INFO_CMDID = 0x995, | 192 | WMI_TOF_SET_LCR_CMDID = 0x993, |
190 | WMI_SET_MAC_ADDRESS_CMDID = 0xF003, | 193 | WMI_TOF_SET_LCI_CMDID = 0x994, |
191 | WMI_ABORT_SCAN_CMDID = 0xF007, | 194 | WMI_TOF_CHANNEL_INFO_CMDID = 0x995, |
192 | WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, | 195 | WMI_TOF_SET_TX_RX_OFFSET_CMDID = 0x997, |
193 | WMI_GET_PMK_CMDID = 0xF048, | 196 | WMI_TOF_GET_TX_RX_OFFSET_CMDID = 0x998, |
194 | WMI_SET_PASSPHRASE_CMDID = 0xF049, | 197 | WMI_GET_RF_SECTOR_PARAMS_CMDID = 0x9A0, |
195 | WMI_SEND_ASSOC_RES_CMDID = 0xF04A, | 198 | WMI_SET_RF_SECTOR_PARAMS_CMDID = 0x9A1, |
196 | WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B, | 199 | WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID = 0x9A2, |
197 | WMI_MAC_ADDR_REQ_CMDID = 0xF04D, | 200 | WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID = 0x9A3, |
198 | WMI_FW_VER_CMDID = 0xF04E, | 201 | WMI_SET_RF_SECTOR_ON_CMDID = 0x9A4, |
199 | WMI_PMC_CMDID = 0xF04F, | 202 | WMI_PRIO_TX_SECTORS_ORDER_CMDID = 0x9A5, |
203 | WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6, | ||
204 | WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7, | ||
205 | WMI_SET_MAC_ADDRESS_CMDID = 0xF003, | ||
206 | WMI_ABORT_SCAN_CMDID = 0xF007, | ||
207 | WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, | ||
208 | WMI_GET_PMK_CMDID = 0xF048, | ||
209 | WMI_SET_PASSPHRASE_CMDID = 0xF049, | ||
210 | WMI_SEND_ASSOC_RES_CMDID = 0xF04A, | ||
211 | WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B, | ||
212 | WMI_MAC_ADDR_REQ_CMDID = 0xF04D, | ||
213 | WMI_FW_VER_CMDID = 0xF04E, | ||
214 | WMI_PMC_CMDID = 0xF04F, | ||
200 | }; | 215 | }; |
201 | 216 | ||
202 | /* WMI_CONNECT_CMDID */ | 217 | /* WMI_CONNECT_CMDID */ |
@@ -879,6 +894,14 @@ struct wmi_aoa_meas_cmd { | |||
879 | __le32 meas_rf_mask; | 894 | __le32 meas_rf_mask; |
880 | } __packed; | 895 | } __packed; |
881 | 896 | ||
897 | /* WMI_SET_MGMT_RETRY_LIMIT_CMDID */ | ||
898 | struct wmi_set_mgmt_retry_limit_cmd { | ||
899 | /* MAC retransmit limit for mgmt frames */ | ||
900 | u8 mgmt_retry_limit; | ||
901 | /* alignment to 32b */ | ||
902 | u8 reserved[3]; | ||
903 | } __packed; | ||
904 | |||
882 | enum wmi_tof_burst_duration { | 905 | enum wmi_tof_burst_duration { |
883 | WMI_TOF_BURST_DURATION_250_USEC = 2, | 906 | WMI_TOF_BURST_DURATION_250_USEC = 2, |
884 | WMI_TOF_BURST_DURATION_500_USEC = 3, | 907 | WMI_TOF_BURST_DURATION_500_USEC = 3, |
@@ -942,6 +965,15 @@ struct wmi_tof_channel_info_cmd { | |||
942 | __le32 channel_info_report_request; | 965 | __le32 channel_info_report_request; |
943 | } __packed; | 966 | } __packed; |
944 | 967 | ||
968 | /* WMI_TOF_SET_TX_RX_OFFSET_CMDID */ | ||
969 | struct wmi_tof_set_tx_rx_offset_cmd { | ||
970 | /* TX delay offset */ | ||
971 | __le32 tx_offset; | ||
972 | /* RX delay offset */ | ||
973 | __le32 rx_offset; | ||
974 | __le32 reserved[2]; | ||
975 | } __packed; | ||
976 | |||
945 | /* WMI Events | 977 | /* WMI Events |
946 | * List of Events (target to host) | 978 | * List of Events (target to host) |
947 | */ | 979 | */ |
@@ -1035,12 +1067,24 @@ enum wmi_event_id { | |||
1035 | WMI_RS_CFG_DONE_EVENTID = 0x1921, | 1067 | WMI_RS_CFG_DONE_EVENTID = 0x1921, |
1036 | WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922, | 1068 | WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922, |
1037 | WMI_AOA_MEAS_EVENTID = 0x1923, | 1069 | WMI_AOA_MEAS_EVENTID = 0x1923, |
1070 | WMI_SET_MGMT_RETRY_LIMIT_EVENTID = 0x1930, | ||
1071 | WMI_GET_MGMT_RETRY_LIMIT_EVENTID = 0x1931, | ||
1038 | WMI_TOF_SESSION_END_EVENTID = 0x1991, | 1072 | WMI_TOF_SESSION_END_EVENTID = 0x1991, |
1039 | WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992, | 1073 | WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992, |
1040 | WMI_TOF_SET_LCR_EVENTID = 0x1993, | 1074 | WMI_TOF_SET_LCR_EVENTID = 0x1993, |
1041 | WMI_TOF_SET_LCI_EVENTID = 0x1994, | 1075 | WMI_TOF_SET_LCI_EVENTID = 0x1994, |
1042 | WMI_TOF_FTM_PER_DEST_RES_EVENTID = 0x1995, | 1076 | WMI_TOF_FTM_PER_DEST_RES_EVENTID = 0x1995, |
1043 | WMI_TOF_CHANNEL_INFO_EVENTID = 0x1996, | 1077 | WMI_TOF_CHANNEL_INFO_EVENTID = 0x1996, |
1078 | WMI_TOF_SET_TX_RX_OFFSET_EVENTID = 0x1997, | ||
1079 | WMI_TOF_GET_TX_RX_OFFSET_EVENTID = 0x1998, | ||
1080 | WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID = 0x19A0, | ||
1081 | WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID = 0x19A1, | ||
1082 | WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID = 0x19A2, | ||
1083 | WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID = 0x19A3, | ||
1084 | WMI_SET_RF_SECTOR_ON_DONE_EVENTID = 0x19A4, | ||
1085 | WMI_PRIO_TX_SECTORS_ORDER_EVENTID = 0x19A5, | ||
1086 | WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6, | ||
1087 | WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7, | ||
1044 | WMI_SET_CHANNEL_EVENTID = 0x9000, | 1088 | WMI_SET_CHANNEL_EVENTID = 0x9000, |
1045 | WMI_ASSOC_REQ_EVENTID = 0x9001, | 1089 | WMI_ASSOC_REQ_EVENTID = 0x9001, |
1046 | WMI_EAPOL_RX_EVENTID = 0x9002, | 1090 | WMI_EAPOL_RX_EVENTID = 0x9002, |
@@ -1166,6 +1210,7 @@ enum baseband_type { | |||
1166 | BASEBAND_SPARROW_M_B0 = 0x05, | 1210 | BASEBAND_SPARROW_M_B0 = 0x05, |
1167 | BASEBAND_SPARROW_M_C0 = 0x06, | 1211 | BASEBAND_SPARROW_M_C0 = 0x06, |
1168 | BASEBAND_SPARROW_M_D0 = 0x07, | 1212 | BASEBAND_SPARROW_M_D0 = 0x07, |
1213 | BASEBAND_TALYN_M_A0 = 0x08, | ||
1169 | }; | 1214 | }; |
1170 | 1215 | ||
1171 | /* WMI_GET_BASEBAND_TYPE_EVENTID */ | 1216 | /* WMI_GET_BASEBAND_TYPE_EVENTID */ |
@@ -2070,6 +2115,22 @@ struct wmi_aoa_meas_event { | |||
2070 | u8 meas_data[WMI_AOA_MAX_DATA_SIZE]; | 2115 | u8 meas_data[WMI_AOA_MAX_DATA_SIZE]; |
2071 | } __packed; | 2116 | } __packed; |
2072 | 2117 | ||
2118 | /* WMI_SET_MGMT_RETRY_LIMIT_EVENTID */ | ||
2119 | struct wmi_set_mgmt_retry_limit_event { | ||
2120 | /* enum wmi_fw_status */ | ||
2121 | u8 status; | ||
2122 | /* alignment to 32b */ | ||
2123 | u8 reserved[3]; | ||
2124 | } __packed; | ||
2125 | |||
2126 | /* WMI_GET_MGMT_RETRY_LIMIT_EVENTID */ | ||
2127 | struct wmi_get_mgmt_retry_limit_event { | ||
2128 | /* MAC retransmit limit for mgmt frames */ | ||
2129 | u8 mgmt_retry_limit; | ||
2130 | /* alignment to 32b */ | ||
2131 | u8 reserved[3]; | ||
2132 | } __packed; | ||
2133 | |||
2073 | /* WMI_TOF_GET_CAPABILITIES_EVENTID */ | 2134 | /* WMI_TOF_GET_CAPABILITIES_EVENTID */ |
2074 | struct wmi_tof_get_capabilities_event { | 2135 | struct wmi_tof_get_capabilities_event { |
2075 | u8 ftm_capability; | 2136 | u8 ftm_capability; |
@@ -2184,4 +2245,283 @@ struct wmi_tof_channel_info_event { | |||
2184 | u8 report[0]; | 2245 | u8 report[0]; |
2185 | } __packed; | 2246 | } __packed; |
2186 | 2247 | ||
2248 | /* WMI_TOF_SET_TX_RX_OFFSET_EVENTID */ | ||
2249 | struct wmi_tof_set_tx_rx_offset_event { | ||
2250 | /* enum wmi_fw_status */ | ||
2251 | u8 status; | ||
2252 | u8 reserved[3]; | ||
2253 | } __packed; | ||
2254 | |||
2255 | /* WMI_TOF_GET_TX_RX_OFFSET_EVENTID */ | ||
2256 | struct wmi_tof_get_tx_rx_offset_event { | ||
2257 | /* enum wmi_fw_status */ | ||
2258 | u8 status; | ||
2259 | u8 reserved1[3]; | ||
2260 | /* TX delay offset */ | ||
2261 | __le32 tx_offset; | ||
2262 | /* RX delay offset */ | ||
2263 | __le32 rx_offset; | ||
2264 | __le32 reserved2[2]; | ||
2265 | } __packed; | ||
2266 | |||
2267 | /* Result status codes for WMI commands */ | ||
2268 | enum wmi_rf_sector_status { | ||
2269 | WMI_RF_SECTOR_STATUS_SUCCESS = 0x00, | ||
2270 | WMI_RF_SECTOR_STATUS_BAD_PARAMETERS_ERROR = 0x01, | ||
2271 | WMI_RF_SECTOR_STATUS_BUSY_ERROR = 0x02, | ||
2272 | WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR = 0x03, | ||
2273 | }; | ||
2274 | |||
2275 | /* Types of the RF sector (TX,RX) */ | ||
2276 | enum wmi_rf_sector_type { | ||
2277 | WMI_RF_SECTOR_TYPE_RX = 0x00, | ||
2278 | WMI_RF_SECTOR_TYPE_TX = 0x01, | ||
2279 | }; | ||
2280 | |||
2281 | /* Content of RF Sector (six 32-bits registers) */ | ||
2282 | struct wmi_rf_sector_info { | ||
2283 | /* Phase values for RF Chains[15-0] (2bits per RF chain) */ | ||
2284 | __le32 psh_hi; | ||
2285 | /* Phase values for RF Chains[31-16] (2bits per RF chain) */ | ||
2286 | __le32 psh_lo; | ||
2287 | /* ETYPE Bit0 for all RF chains[31-0] - bit0 of Edge amplifier gain | ||
2288 | * index | ||
2289 | */ | ||
2290 | __le32 etype0; | ||
2291 | /* ETYPE Bit1 for all RF chains[31-0] - bit1 of Edge amplifier gain | ||
2292 | * index | ||
2293 | */ | ||
2294 | __le32 etype1; | ||
2295 | /* ETYPE Bit2 for all RF chains[31-0] - bit2 of Edge amplifier gain | ||
2296 | * index | ||
2297 | */ | ||
2298 | __le32 etype2; | ||
2299 | /* D-Type values (3bits each) for 8 Distribution amplifiers + X16 | ||
2300 | * switch bits | ||
2301 | */ | ||
2302 | __le32 dtype_swch_off; | ||
2303 | } __packed; | ||
2304 | |||
2305 | #define WMI_INVALID_RF_SECTOR_INDEX (0xFFFF) | ||
2306 | #define WMI_MAX_RF_MODULES_NUM (8) | ||
2307 | |||
2308 | /* WMI_GET_RF_SECTOR_PARAMS_CMD */ | ||
2309 | struct wmi_get_rf_sector_params_cmd { | ||
2310 | /* Sector number to be retrieved */ | ||
2311 | __le16 sector_idx; | ||
2312 | /* enum wmi_rf_sector_type - type of requested RF sector */ | ||
2313 | u8 sector_type; | ||
2314 | /* bitmask vector specifying destination RF modules */ | ||
2315 | u8 rf_modules_vec; | ||
2316 | } __packed; | ||
2317 | |||
2318 | /* \WMI_GET_RF_SECTOR_PARAMS_DONE_EVENT */ | ||
2319 | struct wmi_get_rf_sector_params_done_event { | ||
2320 | /* result status of WMI_GET_RF_SECTOR_PARAMS_CMD (enum | ||
2321 | * wmi_rf_sector_status) | ||
2322 | */ | ||
2323 | u8 status; | ||
2324 | /* align next field to U64 boundary */ | ||
2325 | u8 reserved[7]; | ||
2326 | /* TSF timestamp when RF sectors where retrieved */ | ||
2327 | __le64 tsf; | ||
2328 | /* Content of RF sector retrieved from each RF module */ | ||
2329 | struct wmi_rf_sector_info sectors_info[WMI_MAX_RF_MODULES_NUM]; | ||
2330 | } __packed; | ||
2331 | |||
2332 | /* WMI_SET_RF_SECTOR_PARAMS_CMD */ | ||
2333 | struct wmi_set_rf_sector_params_cmd { | ||
2334 | /* Sector number to be retrieved */ | ||
2335 | __le16 sector_idx; | ||
2336 | /* enum wmi_rf_sector_type - type of requested RF sector */ | ||
2337 | u8 sector_type; | ||
2338 | /* bitmask vector specifying destination RF modules */ | ||
2339 | u8 rf_modules_vec; | ||
2340 | /* Content of RF sector to be written to each RF module */ | ||
2341 | struct wmi_rf_sector_info sectors_info[WMI_MAX_RF_MODULES_NUM]; | ||
2342 | } __packed; | ||
2343 | |||
2344 | /* \WMI_SET_RF_SECTOR_PARAMS_DONE_EVENT */ | ||
2345 | struct wmi_set_rf_sector_params_done_event { | ||
2346 | /* result status of WMI_SET_RF_SECTOR_PARAMS_CMD (enum | ||
2347 | * wmi_rf_sector_status) | ||
2348 | */ | ||
2349 | u8 status; | ||
2350 | } __packed; | ||
2351 | |||
2352 | /* WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD - Get RF sector index selected by | ||
2353 | * TXSS/BRP for communication with specified CID | ||
2354 | */ | ||
2355 | struct wmi_get_selected_rf_sector_index_cmd { | ||
2356 | /* Connection/Station ID in [0:7] range */ | ||
2357 | u8 cid; | ||
2358 | /* type of requested RF sector (enum wmi_rf_sector_type) */ | ||
2359 | u8 sector_type; | ||
2360 | /* align to U32 boundary */ | ||
2361 | u8 reserved[2]; | ||
2362 | } __packed; | ||
2363 | |||
2364 | /* \WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT - Returns retrieved RF sector | ||
2365 | * index selected by TXSS/BRP for communication with specified CID | ||
2366 | */ | ||
2367 | struct wmi_get_selected_rf_sector_index_done_event { | ||
2368 | /* Retrieved sector index selected in TXSS (for TX sector request) or | ||
2369 | * BRP (for RX sector request) | ||
2370 | */ | ||
2371 | __le16 sector_idx; | ||
2372 | /* result status of WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD (enum | ||
2373 | * wmi_rf_sector_status) | ||
2374 | */ | ||
2375 | u8 status; | ||
2376 | /* align next field to U64 boundary */ | ||
2377 | u8 reserved[5]; | ||
2378 | /* TSF timestamp when result was retrieved */ | ||
2379 | __le64 tsf; | ||
2380 | } __packed; | ||
2381 | |||
2382 | /* WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD - Force RF sector index for | ||
2383 | * communication with specified CID. Assumes that TXSS/BRP is disabled by | ||
2384 | * other command | ||
2385 | */ | ||
2386 | struct wmi_set_selected_rf_sector_index_cmd { | ||
2387 | /* Connection/Station ID in [0:7] range */ | ||
2388 | u8 cid; | ||
2389 | /* type of requested RF sector (enum wmi_rf_sector_type) */ | ||
2390 | u8 sector_type; | ||
2391 | /* Forced sector index */ | ||
2392 | __le16 sector_idx; | ||
2393 | } __packed; | ||
2394 | |||
2395 | /* \WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT - Success/Fail status for | ||
2396 | * WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD | ||
2397 | */ | ||
2398 | struct wmi_set_selected_rf_sector_index_done_event { | ||
2399 | /* result status of WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD (enum | ||
2400 | * wmi_rf_sector_status) | ||
2401 | */ | ||
2402 | u8 status; | ||
2403 | /* align to U32 boundary */ | ||
2404 | u8 reserved[3]; | ||
2405 | } __packed; | ||
2406 | |||
2407 | /* WMI_SET_RF_SECTOR_ON_CMD - Activates specified sector for specified rf | ||
2408 | * modules | ||
2409 | */ | ||
2410 | struct wmi_set_rf_sector_on_cmd { | ||
2411 | /* Sector index to be activated */ | ||
2412 | __le16 sector_idx; | ||
2413 | /* type of requested RF sector (enum wmi_rf_sector_type) */ | ||
2414 | u8 sector_type; | ||
2415 | /* bitmask vector specifying destination RF modules */ | ||
2416 | u8 rf_modules_vec; | ||
2417 | } __packed; | ||
2418 | |||
2419 | /* \WMI_SET_RF_SECTOR_ON_DONE_EVENT - Success/Fail status for | ||
2420 | * WMI_SET_RF_SECTOR_ON_CMD | ||
2421 | */ | ||
2422 | struct wmi_set_rf_sector_on_done_event { | ||
2423 | /* result status of WMI_SET_RF_SECTOR_ON_CMD (enum | ||
2424 | * wmi_rf_sector_status) | ||
2425 | */ | ||
2426 | u8 status; | ||
2427 | /* align to U32 boundary */ | ||
2428 | u8 reserved[3]; | ||
2429 | } __packed; | ||
2430 | |||
2431 | enum wmi_sector_sweep_type { | ||
2432 | WMI_SECTOR_SWEEP_TYPE_TXSS = 0x00, | ||
2433 | WMI_SECTOR_SWEEP_TYPE_BCON = 0x01, | ||
2434 | WMI_SECTOR_SWEEP_TYPE_TXSS_AND_BCON = 0x02, | ||
2435 | WMI_SECTOR_SWEEP_TYPE_NUM = 0x03, | ||
2436 | }; | ||
2437 | |||
2438 | /* WMI_PRIO_TX_SECTORS_ORDER_CMDID | ||
2439 | * | ||
2440 | * Set the order of TX sectors in TXSS and/or Beacon(AP). | ||
2441 | * | ||
2442 | * Returned event: | ||
2443 | * - WMI_PRIO_TX_SECTORS_ORDER_EVENTID | ||
2444 | */ | ||
2445 | struct wmi_prio_tx_sectors_order_cmd { | ||
2446 | /* tx sectors order to be applied, 0xFF for end of array */ | ||
2447 | u8 tx_sectors_priority_array[MAX_NUM_OF_SECTORS]; | ||
2448 | /* enum wmi_sector_sweep_type, TXSS and/or Beacon */ | ||
2449 | u8 sector_sweep_type; | ||
2450 | /* needed only for TXSS configuration */ | ||
2451 | u8 cid; | ||
2452 | /* alignment to 32b */ | ||
2453 | u8 reserved[2]; | ||
2454 | } __packed; | ||
2455 | |||
2456 | /* completion status codes */ | ||
2457 | enum wmi_prio_tx_sectors_cmd_status { | ||
2458 | WMI_PRIO_TX_SECT_CMD_STATUS_SUCCESS = 0x00, | ||
2459 | WMI_PRIO_TX_SECT_CMD_STATUS_BAD_PARAM = 0x01, | ||
2460 | /* other error */ | ||
2461 | WMI_PRIO_TX_SECT_CMD_STATUS_ERROR = 0x02, | ||
2462 | }; | ||
2463 | |||
2464 | /* WMI_PRIO_TX_SECTORS_ORDER_EVENTID */ | ||
2465 | struct wmi_prio_tx_sectors_order_event { | ||
2466 | /* enum wmi_prio_tx_sectors_cmd_status */ | ||
2467 | u8 status; | ||
2468 | /* alignment to 32b */ | ||
2469 | u8 reserved[3]; | ||
2470 | } __packed; | ||
2471 | |||
2472 | struct wmi_prio_tx_sectors_num_cmd { | ||
2473 | /* [0-128], 0 = No changes */ | ||
2474 | u8 beacon_number_of_sectors; | ||
2475 | /* [0-128], 0 = No changes */ | ||
2476 | u8 txss_number_of_sectors; | ||
2477 | /* [0-8] needed only for TXSS configuration */ | ||
2478 | u8 cid; | ||
2479 | } __packed; | ||
2480 | |||
2481 | /* WMI_PRIO_TX_SECTORS_NUMBER_CMDID | ||
2482 | * | ||
2483 | * Set the number of active sectors in TXSS and/or Beacon. | ||
2484 | * | ||
2485 | * Returned event: | ||
2486 | * - WMI_PRIO_TX_SECTORS_NUMBER_EVENTID | ||
2487 | */ | ||
2488 | struct wmi_prio_tx_sectors_number_cmd { | ||
2489 | struct wmi_prio_tx_sectors_num_cmd active_sectors_num; | ||
2490 | /* alignment to 32b */ | ||
2491 | u8 reserved; | ||
2492 | } __packed; | ||
2493 | |||
2494 | /* WMI_PRIO_TX_SECTORS_NUMBER_EVENTID */ | ||
2495 | struct wmi_prio_tx_sectors_number_event { | ||
2496 | /* enum wmi_prio_tx_sectors_cmd_status */ | ||
2497 | u8 status; | ||
2498 | /* alignment to 32b */ | ||
2499 | u8 reserved[3]; | ||
2500 | } __packed; | ||
2501 | |||
2502 | /* WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID | ||
2503 | * | ||
2504 | * Set default sectors order and number (hard coded in board file) | ||
2505 | * in TXSS and/or Beacon. | ||
2506 | * | ||
2507 | * Returned event: | ||
2508 | * - WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID | ||
2509 | */ | ||
2510 | struct wmi_prio_tx_sectors_set_default_cfg_cmd { | ||
2511 | /* enum wmi_sector_sweep_type, TXSS and/or Beacon */ | ||
2512 | u8 sector_sweep_type; | ||
2513 | /* needed only for TXSS configuration */ | ||
2514 | u8 cid; | ||
2515 | /* alignment to 32b */ | ||
2516 | u8 reserved[2]; | ||
2517 | } __packed; | ||
2518 | |||
2519 | /* WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID */ | ||
2520 | struct wmi_prio_tx_sectors_set_default_cfg_event { | ||
2521 | /* enum wmi_prio_tx_sectors_cmd_status */ | ||
2522 | u8 status; | ||
2523 | /* alignment to 32b */ | ||
2524 | u8 reserved[3]; | ||
2525 | } __packed; | ||
2526 | |||
2187 | #endif /* __WILOCITY_WMI_H__ */ | 2527 | #endif /* __WILOCITY_WMI_H__ */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile index 9e4b505ca593..d1568bed1ad1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile | |||
@@ -35,7 +35,8 @@ brcmfmac-objs += \ | |||
35 | firmware.o \ | 35 | firmware.o \ |
36 | feature.o \ | 36 | feature.o \ |
37 | btcoex.o \ | 37 | btcoex.o \ |
38 | vendor.o | 38 | vendor.o \ |
39 | pno.o | ||
39 | brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \ | 40 | brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \ |
40 | bcdc.o | 41 | bcdc.o |
41 | brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \ | 42 | brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 2b246545647a..e21f7600122b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | |||
@@ -22,10 +22,12 @@ | |||
22 | /* IDs of the 6 default common rings of msgbuf protocol */ | 22 | /* IDs of the 6 default common rings of msgbuf protocol */ |
23 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 | 23 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 |
24 | #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1 | 24 | #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1 |
25 | #define BRCMF_H2D_MSGRING_FLOWRING_IDSTART 2 | ||
25 | #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2 | 26 | #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2 |
26 | #define BRCMF_D2H_MSGRING_TX_COMPLETE 3 | 27 | #define BRCMF_D2H_MSGRING_TX_COMPLETE 3 |
27 | #define BRCMF_D2H_MSGRING_RX_COMPLETE 4 | 28 | #define BRCMF_D2H_MSGRING_RX_COMPLETE 4 |
28 | 29 | ||
30 | |||
29 | #define BRCMF_NROF_H2D_COMMON_MSGRINGS 2 | 31 | #define BRCMF_NROF_H2D_COMMON_MSGRINGS 2 |
30 | #define BRCMF_NROF_D2H_COMMON_MSGRINGS 3 | 32 | #define BRCMF_NROF_D2H_COMMON_MSGRINGS 3 |
31 | #define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \ | 33 | #define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \ |
@@ -95,14 +97,18 @@ struct brcmf_bus_ops { | |||
95 | * @flowrings: commonrings which are dynamically created and destroyed for data. | 97 | * @flowrings: commonrings which are dynamically created and destroyed for data. |
96 | * @rx_dataoffset: if set then all rx data has this this offset. | 98 | * @rx_dataoffset: if set then all rx data has this this offset. |
97 | * @max_rxbufpost: maximum number of buffers to post for rx. | 99 | * @max_rxbufpost: maximum number of buffers to post for rx. |
98 | * @nrof_flowrings: number of flowrings. | 100 | * @max_flowrings: maximum number of tx flow rings supported. |
101 | * @max_submissionrings: maximum number of submission rings(h2d) supported. | ||
102 | * @max_completionrings: maximum number of completion rings(d2h) supported. | ||
99 | */ | 103 | */ |
100 | struct brcmf_bus_msgbuf { | 104 | struct brcmf_bus_msgbuf { |
101 | struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS]; | 105 | struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS]; |
102 | struct brcmf_commonring **flowrings; | 106 | struct brcmf_commonring **flowrings; |
103 | u32 rx_dataoffset; | 107 | u32 rx_dataoffset; |
104 | u32 max_rxbufpost; | 108 | u32 max_rxbufpost; |
105 | u32 nrof_flowrings; | 109 | u16 max_flowrings; |
110 | u16 max_submissionrings; | ||
111 | u16 max_completionrings; | ||
106 | }; | 112 | }; |
107 | 113 | ||
108 | 114 | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 4e238c0bdaf3..ccae3bbe7db2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "fwil_types.h" | 32 | #include "fwil_types.h" |
33 | #include "p2p.h" | 33 | #include "p2p.h" |
34 | #include "btcoex.h" | 34 | #include "btcoex.h" |
35 | #include "pno.h" | ||
35 | #include "cfg80211.h" | 36 | #include "cfg80211.h" |
36 | #include "feature.h" | 37 | #include "feature.h" |
37 | #include "fwil.h" | 38 | #include "fwil.h" |
@@ -41,16 +42,6 @@ | |||
41 | #include "common.h" | 42 | #include "common.h" |
42 | 43 | ||
43 | #define BRCMF_SCAN_IE_LEN_MAX 2048 | 44 | #define BRCMF_SCAN_IE_LEN_MAX 2048 |
44 | #define BRCMF_PNO_VERSION 2 | ||
45 | #define BRCMF_PNO_TIME 30 | ||
46 | #define BRCMF_PNO_REPEAT 4 | ||
47 | #define BRCMF_PNO_FREQ_EXPO_MAX 3 | ||
48 | #define BRCMF_PNO_MAX_PFN_COUNT 16 | ||
49 | #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 | ||
50 | #define BRCMF_PNO_HIDDEN_BIT 2 | ||
51 | #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF | ||
52 | #define BRCMF_PNO_SCAN_COMPLETE 1 | ||
53 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 | ||
54 | 45 | ||
55 | #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ | 46 | #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ |
56 | #define WPA_OUI_TYPE 1 | 47 | #define WPA_OUI_TYPE 1 |
@@ -768,12 +759,12 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
768 | brcmf_scan_config_mpc(ifp, 1); | 759 | brcmf_scan_config_mpc(ifp, 1); |
769 | 760 | ||
770 | /* | 761 | /* |
771 | * e-scan can be initiated by scheduled scan | 762 | * e-scan can be initiated internally |
772 | * which takes precedence. | 763 | * which takes precedence. |
773 | */ | 764 | */ |
774 | if (cfg->sched_escan) { | 765 | if (cfg->internal_escan) { |
775 | brcmf_dbg(SCAN, "scheduled scan completed\n"); | 766 | brcmf_dbg(SCAN, "scheduled scan completed\n"); |
776 | cfg->sched_escan = false; | 767 | cfg->internal_escan = false; |
777 | if (!aborted) | 768 | if (!aborted) |
778 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); | 769 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); |
779 | } else if (scan_request) { | 770 | } else if (scan_request) { |
@@ -1091,9 +1082,9 @@ exit: | |||
1091 | } | 1082 | } |
1092 | 1083 | ||
1093 | static s32 | 1084 | static s32 |
1094 | brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | 1085 | brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request) |
1095 | struct brcmf_if *ifp, struct cfg80211_scan_request *request) | ||
1096 | { | 1086 | { |
1087 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | ||
1097 | s32 err; | 1088 | s32 err; |
1098 | u32 passive_scan; | 1089 | u32 passive_scan; |
1099 | struct brcmf_scan_results *results; | 1090 | struct brcmf_scan_results *results; |
@@ -1101,7 +1092,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | |||
1101 | 1092 | ||
1102 | brcmf_dbg(SCAN, "Enter\n"); | 1093 | brcmf_dbg(SCAN, "Enter\n"); |
1103 | escan->ifp = ifp; | 1094 | escan->ifp = ifp; |
1104 | escan->wiphy = wiphy; | 1095 | escan->wiphy = cfg->wiphy; |
1105 | escan->escan_state = WL_ESCAN_STATE_SCANNING; | 1096 | escan->escan_state = WL_ESCAN_STATE_SCANNING; |
1106 | passive_scan = cfg->active_scan ? 0 : 1; | 1097 | passive_scan = cfg->active_scan ? 0 : 1; |
1107 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, | 1098 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, |
@@ -1181,7 +1172,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, | |||
1181 | if (err) | 1172 | if (err) |
1182 | goto scan_out; | 1173 | goto scan_out; |
1183 | 1174 | ||
1184 | err = brcmf_do_escan(cfg, wiphy, vif->ifp, request); | 1175 | err = brcmf_do_escan(vif->ifp, request); |
1185 | if (err) | 1176 | if (err) |
1186 | goto scan_out; | 1177 | goto scan_out; |
1187 | } else { | 1178 | } else { |
@@ -3024,7 +3015,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) | |||
3024 | struct escan_info *escan = &cfg->escan_info; | 3015 | struct escan_info *escan = &cfg->escan_info; |
3025 | 3016 | ||
3026 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | 3017 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
3027 | if (cfg->scan_request) { | 3018 | if (cfg->internal_escan || cfg->scan_request) { |
3028 | escan->escan_state = WL_ESCAN_STATE_IDLE; | 3019 | escan->escan_state = WL_ESCAN_STATE_IDLE; |
3029 | brcmf_notify_escan_complete(cfg, escan->ifp, true, true); | 3020 | brcmf_notify_escan_complete(cfg, escan->ifp, true, true); |
3030 | } | 3021 | } |
@@ -3047,7 +3038,7 @@ static void brcmf_escan_timeout(unsigned long data) | |||
3047 | struct brcmf_cfg80211_info *cfg = | 3038 | struct brcmf_cfg80211_info *cfg = |
3048 | (struct brcmf_cfg80211_info *)data; | 3039 | (struct brcmf_cfg80211_info *)data; |
3049 | 3040 | ||
3050 | if (cfg->scan_request) { | 3041 | if (cfg->internal_escan || cfg->scan_request) { |
3051 | brcmf_err("timer expired\n"); | 3042 | brcmf_err("timer expired\n"); |
3052 | schedule_work(&cfg->escan_timeout_work); | 3043 | schedule_work(&cfg->escan_timeout_work); |
3053 | } | 3044 | } |
@@ -3130,7 +3121,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3130 | if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le)) | 3121 | if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le)) |
3131 | goto exit; | 3122 | goto exit; |
3132 | 3123 | ||
3133 | if (!cfg->scan_request) { | 3124 | if (!cfg->internal_escan && !cfg->scan_request) { |
3134 | brcmf_dbg(SCAN, "result without cfg80211 request\n"); | 3125 | brcmf_dbg(SCAN, "result without cfg80211 request\n"); |
3135 | goto exit; | 3126 | goto exit; |
3136 | } | 3127 | } |
@@ -3176,7 +3167,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3176 | cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; | 3167 | cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; |
3177 | if (brcmf_p2p_scan_finding_common_channel(cfg, NULL)) | 3168 | if (brcmf_p2p_scan_finding_common_channel(cfg, NULL)) |
3178 | goto exit; | 3169 | goto exit; |
3179 | if (cfg->scan_request) { | 3170 | if (cfg->internal_escan || cfg->scan_request) { |
3180 | brcmf_inform_bss(cfg); | 3171 | brcmf_inform_bss(cfg); |
3181 | aborted = status != BRCMF_E_STATUS_SUCCESS; | 3172 | aborted = status != BRCMF_E_STATUS_SUCCESS; |
3182 | brcmf_notify_escan_complete(cfg, ifp, aborted, false); | 3173 | brcmf_notify_escan_complete(cfg, ifp, aborted, false); |
@@ -3201,6 +3192,95 @@ static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg) | |||
3201 | brcmf_cfg80211_escan_timeout_worker); | 3192 | brcmf_cfg80211_escan_timeout_worker); |
3202 | } | 3193 | } |
3203 | 3194 | ||
3195 | static struct cfg80211_scan_request * | ||
3196 | brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) { | ||
3197 | struct cfg80211_scan_request *req; | ||
3198 | size_t req_size; | ||
3199 | |||
3200 | req_size = sizeof(*req) + | ||
3201 | n_netinfo * sizeof(req->channels[0]) + | ||
3202 | n_netinfo * sizeof(*req->ssids); | ||
3203 | |||
3204 | req = kzalloc(req_size, GFP_KERNEL); | ||
3205 | if (req) { | ||
3206 | req->wiphy = wiphy; | ||
3207 | req->ssids = (void *)(&req->channels[0]) + | ||
3208 | n_netinfo * sizeof(req->channels[0]); | ||
3209 | } | ||
3210 | return req; | ||
3211 | } | ||
3212 | |||
3213 | static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req, | ||
3214 | u8 *ssid, u8 ssid_len, u8 channel) | ||
3215 | { | ||
3216 | struct ieee80211_channel *chan; | ||
3217 | enum nl80211_band band; | ||
3218 | int freq; | ||
3219 | |||
3220 | if (channel <= CH_MAX_2G_CHANNEL) | ||
3221 | band = NL80211_BAND_2GHZ; | ||
3222 | else | ||
3223 | band = NL80211_BAND_5GHZ; | ||
3224 | |||
3225 | freq = ieee80211_channel_to_frequency(channel, band); | ||
3226 | if (!freq) | ||
3227 | return -EINVAL; | ||
3228 | |||
3229 | chan = ieee80211_get_channel(req->wiphy, freq); | ||
3230 | if (!chan) | ||
3231 | return -EINVAL; | ||
3232 | |||
3233 | req->channels[req->n_channels++] = chan; | ||
3234 | memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len); | ||
3235 | req->ssids[req->n_ssids++].ssid_len = ssid_len; | ||
3236 | |||
3237 | return 0; | ||
3238 | } | ||
3239 | |||
3240 | static int brcmf_start_internal_escan(struct brcmf_if *ifp, | ||
3241 | struct cfg80211_scan_request *request) | ||
3242 | { | ||
3243 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | ||
3244 | int err; | ||
3245 | |||
3246 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | ||
3247 | /* Abort any on-going scan */ | ||
3248 | brcmf_abort_scanning(cfg); | ||
3249 | } | ||
3250 | |||
3251 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | ||
3252 | cfg->escan_info.run = brcmf_run_escan; | ||
3253 | err = brcmf_do_escan(ifp, request); | ||
3254 | if (err) { | ||
3255 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | ||
3256 | return err; | ||
3257 | } | ||
3258 | cfg->internal_escan = true; | ||
3259 | return 0; | ||
3260 | } | ||
3261 | |||
3262 | static struct brcmf_pno_net_info_le * | ||
3263 | brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1) | ||
3264 | { | ||
3265 | struct brcmf_pno_scanresults_v2_le *pfn_v2; | ||
3266 | struct brcmf_pno_net_info_le *netinfo; | ||
3267 | |||
3268 | switch (pfn_v1->version) { | ||
3269 | default: | ||
3270 | WARN_ON(1); | ||
3271 | /* fall-thru */ | ||
3272 | case cpu_to_le32(1): | ||
3273 | netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1); | ||
3274 | break; | ||
3275 | case cpu_to_le32(2): | ||
3276 | pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1; | ||
3277 | netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1); | ||
3278 | break; | ||
3279 | } | ||
3280 | |||
3281 | return netinfo; | ||
3282 | } | ||
3283 | |||
3204 | /* PFN result doesn't have all the info which are required by the supplicant | 3284 | /* PFN result doesn't have all the info which are required by the supplicant |
3205 | * (For e.g IEs) Do a target Escan so that sched scan results are reported | 3285 | * (For e.g IEs) Do a target Escan so that sched scan results are reported |
3206 | * via wl_inform_single_bss in the required format. Escan does require the | 3286 | * via wl_inform_single_bss in the required format. Escan does require the |
@@ -3214,12 +3294,8 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
3214 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 3294 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
3215 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; | 3295 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; |
3216 | struct cfg80211_scan_request *request = NULL; | 3296 | struct cfg80211_scan_request *request = NULL; |
3217 | struct cfg80211_ssid *ssid = NULL; | ||
3218 | struct ieee80211_channel *channel = NULL; | ||
3219 | struct wiphy *wiphy = cfg_to_wiphy(cfg); | 3297 | struct wiphy *wiphy = cfg_to_wiphy(cfg); |
3220 | int err = 0; | 3298 | int i, err = 0; |
3221 | int channel_req = 0; | ||
3222 | int band = 0; | ||
3223 | struct brcmf_pno_scanresults_le *pfn_result; | 3299 | struct brcmf_pno_scanresults_le *pfn_result; |
3224 | u32 result_count; | 3300 | u32 result_count; |
3225 | u32 status; | 3301 | u32 status; |
@@ -3245,254 +3321,86 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
3245 | */ | 3321 | */ |
3246 | WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); | 3322 | WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); |
3247 | brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count); | 3323 | brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count); |
3248 | if (result_count > 0) { | 3324 | if (!result_count) { |
3249 | int i; | ||
3250 | |||
3251 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
3252 | ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL); | ||
3253 | channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL); | ||
3254 | if (!request || !ssid || !channel) { | ||
3255 | err = -ENOMEM; | ||
3256 | goto out_err; | ||
3257 | } | ||
3258 | |||
3259 | request->wiphy = wiphy; | ||
3260 | data += sizeof(struct brcmf_pno_scanresults_le); | ||
3261 | netinfo_start = (struct brcmf_pno_net_info_le *)data; | ||
3262 | |||
3263 | for (i = 0; i < result_count; i++) { | ||
3264 | netinfo = &netinfo_start[i]; | ||
3265 | if (!netinfo) { | ||
3266 | brcmf_err("Invalid netinfo ptr. index: %d\n", | ||
3267 | i); | ||
3268 | err = -EINVAL; | ||
3269 | goto out_err; | ||
3270 | } | ||
3271 | |||
3272 | brcmf_dbg(SCAN, "SSID:%s Channel:%d\n", | ||
3273 | netinfo->SSID, netinfo->channel); | ||
3274 | memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len); | ||
3275 | ssid[i].ssid_len = netinfo->SSID_len; | ||
3276 | request->n_ssids++; | ||
3277 | |||
3278 | channel_req = netinfo->channel; | ||
3279 | if (channel_req <= CH_MAX_2G_CHANNEL) | ||
3280 | band = NL80211_BAND_2GHZ; | ||
3281 | else | ||
3282 | band = NL80211_BAND_5GHZ; | ||
3283 | channel[i].center_freq = | ||
3284 | ieee80211_channel_to_frequency(channel_req, | ||
3285 | band); | ||
3286 | channel[i].band = band; | ||
3287 | channel[i].flags |= IEEE80211_CHAN_NO_HT40; | ||
3288 | request->channels[i] = &channel[i]; | ||
3289 | request->n_channels++; | ||
3290 | } | ||
3291 | |||
3292 | /* assign parsed ssid array */ | ||
3293 | if (request->n_ssids) | ||
3294 | request->ssids = &ssid[0]; | ||
3295 | |||
3296 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | ||
3297 | /* Abort any on-going scan */ | ||
3298 | brcmf_abort_scanning(cfg); | ||
3299 | } | ||
3300 | |||
3301 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | ||
3302 | cfg->escan_info.run = brcmf_run_escan; | ||
3303 | err = brcmf_do_escan(cfg, wiphy, ifp, request); | ||
3304 | if (err) { | ||
3305 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | ||
3306 | goto out_err; | ||
3307 | } | ||
3308 | cfg->sched_escan = true; | ||
3309 | cfg->scan_request = request; | ||
3310 | } else { | ||
3311 | brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); | 3325 | brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); |
3312 | goto out_err; | 3326 | goto out_err; |
3313 | } | 3327 | } |
3314 | 3328 | request = brcmf_alloc_internal_escan_request(wiphy, | |
3315 | kfree(ssid); | 3329 | result_count); |
3316 | kfree(channel); | 3330 | if (!request) { |
3317 | kfree(request); | 3331 | err = -ENOMEM; |
3318 | return 0; | 3332 | goto out_err; |
3319 | |||
3320 | out_err: | ||
3321 | kfree(ssid); | ||
3322 | kfree(channel); | ||
3323 | kfree(request); | ||
3324 | cfg80211_sched_scan_stopped(wiphy); | ||
3325 | return err; | ||
3326 | } | ||
3327 | |||
3328 | static int brcmf_dev_pno_clean(struct net_device *ndev) | ||
3329 | { | ||
3330 | int ret; | ||
3331 | |||
3332 | /* Disable pfn */ | ||
3333 | ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0); | ||
3334 | if (ret == 0) { | ||
3335 | /* clear pfn */ | ||
3336 | ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear", | ||
3337 | NULL, 0); | ||
3338 | } | ||
3339 | if (ret < 0) | ||
3340 | brcmf_err("failed code %d\n", ret); | ||
3341 | |||
3342 | return ret; | ||
3343 | } | ||
3344 | |||
3345 | static int brcmf_dev_pno_config(struct brcmf_if *ifp, | ||
3346 | struct cfg80211_sched_scan_request *request) | ||
3347 | { | ||
3348 | struct brcmf_pno_param_le pfn_param; | ||
3349 | struct brcmf_pno_macaddr_le pfn_mac; | ||
3350 | s32 err; | ||
3351 | u8 *mac_mask; | ||
3352 | int i; | ||
3353 | |||
3354 | memset(&pfn_param, 0, sizeof(pfn_param)); | ||
3355 | pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); | ||
3356 | |||
3357 | /* set extra pno params */ | ||
3358 | pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); | ||
3359 | pfn_param.repeat = BRCMF_PNO_REPEAT; | ||
3360 | pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; | ||
3361 | |||
3362 | /* set up pno scan fr */ | ||
3363 | pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); | ||
3364 | |||
3365 | err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, | ||
3366 | sizeof(pfn_param)); | ||
3367 | if (err) { | ||
3368 | brcmf_err("pfn_set failed, err=%d\n", err); | ||
3369 | return err; | ||
3370 | } | 3333 | } |
3371 | 3334 | ||
3372 | /* Find out if mac randomization should be turned on */ | 3335 | data += sizeof(struct brcmf_pno_scanresults_le); |
3373 | if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) | 3336 | netinfo_start = brcmf_get_netinfo_array(pfn_result); |
3374 | return 0; | ||
3375 | 3337 | ||
3376 | pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; | 3338 | for (i = 0; i < result_count; i++) { |
3377 | pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; | 3339 | netinfo = &netinfo_start[i]; |
3340 | if (!netinfo) { | ||
3341 | brcmf_err("Invalid netinfo ptr. index: %d\n", | ||
3342 | i); | ||
3343 | err = -EINVAL; | ||
3344 | goto out_err; | ||
3345 | } | ||
3378 | 3346 | ||
3379 | memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN); | 3347 | brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n", |
3380 | mac_mask = request->mac_addr_mask; | 3348 | netinfo->SSID, netinfo->channel); |
3381 | for (i = 0; i < ETH_ALEN; i++) { | 3349 | err = brcmf_internal_escan_add_info(request, |
3382 | pfn_mac.mac[i] &= mac_mask[i]; | 3350 | netinfo->SSID, |
3383 | pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); | 3351 | netinfo->SSID_len, |
3352 | netinfo->channel); | ||
3353 | if (err) | ||
3354 | goto out_err; | ||
3384 | } | 3355 | } |
3385 | /* Clear multi bit */ | ||
3386 | pfn_mac.mac[0] &= 0xFE; | ||
3387 | /* Set locally administered */ | ||
3388 | pfn_mac.mac[0] |= 0x02; | ||
3389 | 3356 | ||
3390 | err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, | 3357 | err = brcmf_start_internal_escan(ifp, request); |
3391 | sizeof(pfn_mac)); | 3358 | if (!err) |
3392 | if (err) | 3359 | goto free_req; |
3393 | brcmf_err("pfn_macaddr failed, err=%d\n", err); | ||
3394 | 3360 | ||
3361 | out_err: | ||
3362 | cfg80211_sched_scan_stopped(wiphy); | ||
3363 | free_req: | ||
3364 | kfree(request); | ||
3395 | return err; | 3365 | return err; |
3396 | } | 3366 | } |
3397 | 3367 | ||
3398 | static int | 3368 | static int |
3399 | brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | 3369 | brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, |
3400 | struct net_device *ndev, | 3370 | struct net_device *ndev, |
3401 | struct cfg80211_sched_scan_request *request) | 3371 | struct cfg80211_sched_scan_request *req) |
3402 | { | 3372 | { |
3403 | struct brcmf_if *ifp = netdev_priv(ndev); | 3373 | struct brcmf_if *ifp = netdev_priv(ndev); |
3404 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); | 3374 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); |
3405 | struct brcmf_pno_net_param_le pfn; | ||
3406 | int i; | ||
3407 | int ret = 0; | ||
3408 | 3375 | ||
3409 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", | 3376 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", |
3410 | request->n_match_sets, request->n_ssids); | 3377 | req->n_match_sets, req->n_ssids); |
3411 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | 3378 | |
3412 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); | ||
3413 | return -EAGAIN; | ||
3414 | } | ||
3415 | if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { | 3379 | if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { |
3416 | brcmf_err("Scanning suppressed: status (%lu)\n", | 3380 | brcmf_err("Scanning suppressed: status (%lu)\n", |
3417 | cfg->scan_status); | 3381 | cfg->scan_status); |
3418 | return -EAGAIN; | 3382 | return -EAGAIN; |
3419 | } | 3383 | } |
3420 | 3384 | ||
3421 | if (!request->n_ssids || !request->n_match_sets) { | 3385 | if (req->n_match_sets <= 0) { |
3422 | brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n", | 3386 | brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n", |
3423 | request->n_ssids); | 3387 | req->n_match_sets); |
3424 | return -EINVAL; | 3388 | return -EINVAL; |
3425 | } | 3389 | } |
3426 | 3390 | ||
3427 | if (request->n_ssids > 0) { | 3391 | return brcmf_pno_start_sched_scan(ifp, req); |
3428 | for (i = 0; i < request->n_ssids; i++) { | ||
3429 | /* Active scan req for ssids */ | ||
3430 | brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n", | ||
3431 | request->ssids[i].ssid); | ||
3432 | |||
3433 | /* match_set ssids is a supert set of n_ssid list, | ||
3434 | * so we need not add these set separately. | ||
3435 | */ | ||
3436 | } | ||
3437 | } | ||
3438 | |||
3439 | if (request->n_match_sets > 0) { | ||
3440 | /* clean up everything */ | ||
3441 | ret = brcmf_dev_pno_clean(ndev); | ||
3442 | if (ret < 0) { | ||
3443 | brcmf_err("failed error=%d\n", ret); | ||
3444 | return ret; | ||
3445 | } | ||
3446 | |||
3447 | /* configure pno */ | ||
3448 | if (brcmf_dev_pno_config(ifp, request)) | ||
3449 | return -EINVAL; | ||
3450 | |||
3451 | /* configure each match set */ | ||
3452 | for (i = 0; i < request->n_match_sets; i++) { | ||
3453 | struct cfg80211_ssid *ssid; | ||
3454 | u32 ssid_len; | ||
3455 | |||
3456 | ssid = &request->match_sets[i].ssid; | ||
3457 | ssid_len = ssid->ssid_len; | ||
3458 | |||
3459 | if (!ssid_len) { | ||
3460 | brcmf_err("skip broadcast ssid\n"); | ||
3461 | continue; | ||
3462 | } | ||
3463 | pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); | ||
3464 | pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); | ||
3465 | pfn.wsec = cpu_to_le32(0); | ||
3466 | pfn.infra = cpu_to_le32(1); | ||
3467 | pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); | ||
3468 | pfn.ssid.SSID_len = cpu_to_le32(ssid_len); | ||
3469 | memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); | ||
3470 | ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, | ||
3471 | sizeof(pfn)); | ||
3472 | brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", | ||
3473 | ret == 0 ? "set" : "failed", ssid->ssid); | ||
3474 | } | ||
3475 | /* Enable the PNO */ | ||
3476 | if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) { | ||
3477 | brcmf_err("PNO enable failed!! ret=%d\n", ret); | ||
3478 | return -EINVAL; | ||
3479 | } | ||
3480 | } else { | ||
3481 | return -EINVAL; | ||
3482 | } | ||
3483 | |||
3484 | return 0; | ||
3485 | } | 3392 | } |
3486 | 3393 | ||
3487 | static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, | 3394 | static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, |
3488 | struct net_device *ndev) | 3395 | struct net_device *ndev) |
3489 | { | 3396 | { |
3490 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3397 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3398 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3491 | 3399 | ||
3492 | brcmf_dbg(SCAN, "enter\n"); | 3400 | brcmf_dbg(SCAN, "enter\n"); |
3493 | brcmf_dev_pno_clean(ndev); | 3401 | brcmf_pno_clean(ifp); |
3494 | if (cfg->sched_escan) | 3402 | if (cfg->internal_escan) |
3495 | brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true); | 3403 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
3496 | return 0; | 3404 | return 0; |
3497 | } | 3405 | } |
3498 | 3406 | ||
@@ -6428,6 +6336,7 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | |||
6428 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; | 6336 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; |
6429 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; | 6337 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; |
6430 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | 6338 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; |
6339 | wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD; | ||
6431 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 6340 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
6432 | } | 6341 | } |
6433 | 6342 | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 8889832c17e0..0c9a7081fca9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h | |||
@@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl { | |||
271 | * @pub: common driver information. | 271 | * @pub: common driver information. |
272 | * @channel: current channel. | 272 | * @channel: current channel. |
273 | * @active_scan: current scan mode. | 273 | * @active_scan: current scan mode. |
274 | * @sched_escan: e-scan for scheduled scan support running. | 274 | * @internal_escan: indicates internally initiated e-scan is running. |
275 | * @ibss_starter: indicates this sta is ibss starter. | 275 | * @ibss_starter: indicates this sta is ibss starter. |
276 | * @pwr_save: indicate whether dongle to support power save mode. | 276 | * @pwr_save: indicate whether dongle to support power save mode. |
277 | * @dongle_up: indicate whether dongle up or not. | 277 | * @dongle_up: indicate whether dongle up or not. |
@@ -303,7 +303,7 @@ struct brcmf_cfg80211_info { | |||
303 | struct brcmf_pub *pub; | 303 | struct brcmf_pub *pub; |
304 | u32 channel; | 304 | u32 channel; |
305 | bool active_scan; | 305 | bool active_scan; |
306 | bool sched_escan; | 306 | bool internal_escan; |
307 | bool ibss_starter; | 307 | bool ibss_starter; |
308 | bool pwr_save; | 308 | bool pwr_save; |
309 | bool dongle_up; | 309 | bool dongle_up; |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index a4118c0ef6ca..9a1eb5ab6c4b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h | |||
@@ -131,6 +131,7 @@ | |||
131 | #define BRCMF_TXBF_MU_BFR_CAP BIT(1) | 131 | #define BRCMF_TXBF_MU_BFR_CAP BIT(1) |
132 | 132 | ||
133 | #define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */ | 133 | #define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */ |
134 | #define BRCMF_NUMCHANNELS 64 | ||
134 | 135 | ||
135 | #define BRCMF_PFN_MACADDR_CFG_VER 1 | 136 | #define BRCMF_PFN_MACADDR_CFG_VER 1 |
136 | #define BRCMF_PFN_MAC_OUI_ONLY BIT(0) | 137 | #define BRCMF_PFN_MAC_OUI_ONLY BIT(0) |
@@ -719,6 +720,21 @@ struct brcmf_pno_param_le { | |||
719 | }; | 720 | }; |
720 | 721 | ||
721 | /** | 722 | /** |
723 | * struct brcmf_pno_config_le - PNO channel configuration. | ||
724 | * | ||
725 | * @reporttype: determines what is reported. | ||
726 | * @channel_num: number of channels specified in @channel_list. | ||
727 | * @channel_list: channels to use in PNO scan. | ||
728 | * @flags: reserved. | ||
729 | */ | ||
730 | struct brcmf_pno_config_le { | ||
731 | __le32 reporttype; | ||
732 | __le32 channel_num; | ||
733 | __le16 channel_list[BRCMF_NUMCHANNELS]; | ||
734 | __le32 flags; | ||
735 | }; | ||
736 | |||
737 | /** | ||
722 | * struct brcmf_pno_net_param_le - scan parameters per preferred network. | 738 | * struct brcmf_pno_net_param_le - scan parameters per preferred network. |
723 | * | 739 | * |
724 | * @ssid: ssid name and its length. | 740 | * @ssid: ssid name and its length. |
@@ -769,6 +785,13 @@ struct brcmf_pno_scanresults_le { | |||
769 | __le32 count; | 785 | __le32 count; |
770 | }; | 786 | }; |
771 | 787 | ||
788 | struct brcmf_pno_scanresults_v2_le { | ||
789 | __le32 version; | ||
790 | __le32 status; | ||
791 | __le32 count; | ||
792 | __le32 scan_ch_bucket; | ||
793 | }; | ||
794 | |||
772 | /** | 795 | /** |
773 | * struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization. | 796 | * struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization. |
774 | * | 797 | * |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 7cc8851c071e..d2c834c3b2fc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | |||
@@ -87,11 +87,6 @@ struct msgbuf_common_hdr { | |||
87 | __le32 request_id; | 87 | __le32 request_id; |
88 | }; | 88 | }; |
89 | 89 | ||
90 | struct msgbuf_buf_addr { | ||
91 | __le32 low_addr; | ||
92 | __le32 high_addr; | ||
93 | }; | ||
94 | |||
95 | struct msgbuf_ioctl_req_hdr { | 90 | struct msgbuf_ioctl_req_hdr { |
96 | struct msgbuf_common_hdr msg; | 91 | struct msgbuf_common_hdr msg; |
97 | __le32 cmd; | 92 | __le32 cmd; |
@@ -227,7 +222,10 @@ struct brcmf_msgbuf { | |||
227 | struct brcmf_commonring **commonrings; | 222 | struct brcmf_commonring **commonrings; |
228 | struct brcmf_commonring **flowrings; | 223 | struct brcmf_commonring **flowrings; |
229 | dma_addr_t *flowring_dma_handle; | 224 | dma_addr_t *flowring_dma_handle; |
230 | u16 nrof_flowrings; | 225 | |
226 | u16 max_flowrings; | ||
227 | u16 max_submissionrings; | ||
228 | u16 max_completionrings; | ||
231 | 229 | ||
232 | u16 rx_dataoffset; | 230 | u16 rx_dataoffset; |
233 | u32 max_rxbufpost; | 231 | u32 max_rxbufpost; |
@@ -610,7 +608,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf, | |||
610 | create->msg.request_id = 0; | 608 | create->msg.request_id = 0; |
611 | create->tid = brcmf_flowring_tid(msgbuf->flow, flowid); | 609 | create->tid = brcmf_flowring_tid(msgbuf->flow, flowid); |
612 | create->flow_ring_id = cpu_to_le16(flowid + | 610 | create->flow_ring_id = cpu_to_le16(flowid + |
613 | BRCMF_NROF_H2D_COMMON_MSGRINGS); | 611 | BRCMF_H2D_MSGRING_FLOWRING_IDSTART); |
614 | memcpy(create->sa, work->sa, ETH_ALEN); | 612 | memcpy(create->sa, work->sa, ETH_ALEN); |
615 | memcpy(create->da, work->da, ETH_ALEN); | 613 | memcpy(create->da, work->da, ETH_ALEN); |
616 | address = (u64)msgbuf->flowring_dma_handle[flowid]; | 614 | address = (u64)msgbuf->flowring_dma_handle[flowid]; |
@@ -760,7 +758,7 @@ static void brcmf_msgbuf_txflow_worker(struct work_struct *worker) | |||
760 | u32 flowid; | 758 | u32 flowid; |
761 | 759 | ||
762 | msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work); | 760 | msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work); |
763 | for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->nrof_flowrings) { | 761 | for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->max_flowrings) { |
764 | clear_bit(flowid, msgbuf->flow_map); | 762 | clear_bit(flowid, msgbuf->flow_map); |
765 | brcmf_msgbuf_txflow(msgbuf, flowid); | 763 | brcmf_msgbuf_txflow(msgbuf, flowid); |
766 | } | 764 | } |
@@ -866,7 +864,7 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) | |||
866 | tx_status = (struct msgbuf_tx_status *)buf; | 864 | tx_status = (struct msgbuf_tx_status *)buf; |
867 | idx = le32_to_cpu(tx_status->msg.request_id); | 865 | idx = le32_to_cpu(tx_status->msg.request_id); |
868 | flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id); | 866 | flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id); |
869 | flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; | 867 | flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; |
870 | skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, | 868 | skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, |
871 | msgbuf->tx_pktids, idx); | 869 | msgbuf->tx_pktids, idx); |
872 | if (!skb) | 870 | if (!skb) |
@@ -1174,7 +1172,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf, | |||
1174 | flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf; | 1172 | flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf; |
1175 | 1173 | ||
1176 | flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id); | 1174 | flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id); |
1177 | flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; | 1175 | flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; |
1178 | status = le16_to_cpu(flowring_create_resp->compl_hdr.status); | 1176 | status = le16_to_cpu(flowring_create_resp->compl_hdr.status); |
1179 | 1177 | ||
1180 | if (status) { | 1178 | if (status) { |
@@ -1202,7 +1200,7 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf, | |||
1202 | flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf; | 1200 | flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf; |
1203 | 1201 | ||
1204 | flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id); | 1202 | flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id); |
1205 | flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; | 1203 | flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; |
1206 | status = le16_to_cpu(flowring_delete_resp->compl_hdr.status); | 1204 | status = le16_to_cpu(flowring_delete_resp->compl_hdr.status); |
1207 | 1205 | ||
1208 | if (status) { | 1206 | if (status) { |
@@ -1307,7 +1305,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) | |||
1307 | brcmf_msgbuf_process_rx(msgbuf, buf); | 1305 | brcmf_msgbuf_process_rx(msgbuf, buf); |
1308 | 1306 | ||
1309 | for_each_set_bit(flowid, msgbuf->txstatus_done_map, | 1307 | for_each_set_bit(flowid, msgbuf->txstatus_done_map, |
1310 | msgbuf->nrof_flowrings) { | 1308 | msgbuf->max_flowrings) { |
1311 | clear_bit(flowid, msgbuf->txstatus_done_map); | 1309 | clear_bit(flowid, msgbuf->txstatus_done_map); |
1312 | commonring = msgbuf->flowrings[flowid]; | 1310 | commonring = msgbuf->flowrings[flowid]; |
1313 | qlen = brcmf_flowring_qlen(msgbuf->flow, flowid); | 1311 | qlen = brcmf_flowring_qlen(msgbuf->flow, flowid); |
@@ -1349,7 +1347,7 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) | |||
1349 | delete->msg.request_id = 0; | 1347 | delete->msg.request_id = 0; |
1350 | 1348 | ||
1351 | delete->flow_ring_id = cpu_to_le16(flowid + | 1349 | delete->flow_ring_id = cpu_to_le16(flowid + |
1352 | BRCMF_NROF_H2D_COMMON_MSGRINGS); | 1350 | BRCMF_H2D_MSGRING_FLOWRING_IDSTART); |
1353 | delete->reason = 0; | 1351 | delete->reason = 0; |
1354 | 1352 | ||
1355 | brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n", | 1353 | brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n", |
@@ -1427,10 +1425,10 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) | |||
1427 | 1425 | ||
1428 | if_msgbuf = drvr->bus_if->msgbuf; | 1426 | if_msgbuf = drvr->bus_if->msgbuf; |
1429 | 1427 | ||
1430 | if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) { | 1428 | if (if_msgbuf->max_flowrings >= BRCMF_FLOWRING_HASHSIZE) { |
1431 | brcmf_err("driver not configured for this many flowrings %d\n", | 1429 | brcmf_err("driver not configured for this many flowrings %d\n", |
1432 | if_msgbuf->nrof_flowrings); | 1430 | if_msgbuf->max_flowrings); |
1433 | if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; | 1431 | if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; |
1434 | } | 1432 | } |
1435 | 1433 | ||
1436 | msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); | 1434 | msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); |
@@ -1443,7 +1441,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) | |||
1443 | goto fail; | 1441 | goto fail; |
1444 | } | 1442 | } |
1445 | INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker); | 1443 | INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker); |
1446 | count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings); | 1444 | count = BITS_TO_LONGS(if_msgbuf->max_flowrings); |
1447 | count = count * sizeof(unsigned long); | 1445 | count = count * sizeof(unsigned long); |
1448 | msgbuf->flow_map = kzalloc(count, GFP_KERNEL); | 1446 | msgbuf->flow_map = kzalloc(count, GFP_KERNEL); |
1449 | if (!msgbuf->flow_map) | 1447 | if (!msgbuf->flow_map) |
@@ -1479,8 +1477,8 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) | |||
1479 | msgbuf->commonrings = | 1477 | msgbuf->commonrings = |
1480 | (struct brcmf_commonring **)if_msgbuf->commonrings; | 1478 | (struct brcmf_commonring **)if_msgbuf->commonrings; |
1481 | msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings; | 1479 | msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings; |
1482 | msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings; | 1480 | msgbuf->max_flowrings = if_msgbuf->max_flowrings; |
1483 | msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings * | 1481 | msgbuf->flowring_dma_handle = kzalloc(msgbuf->max_flowrings * |
1484 | sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL); | 1482 | sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL); |
1485 | if (!msgbuf->flowring_dma_handle) | 1483 | if (!msgbuf->flowring_dma_handle) |
1486 | goto fail; | 1484 | goto fail; |
@@ -1501,7 +1499,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) | |||
1501 | goto fail; | 1499 | goto fail; |
1502 | 1500 | ||
1503 | msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev, | 1501 | msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev, |
1504 | if_msgbuf->nrof_flowrings); | 1502 | if_msgbuf->max_flowrings); |
1505 | if (!msgbuf->flow) | 1503 | if (!msgbuf->flow) |
1506 | goto fail; | 1504 | goto fail; |
1507 | 1505 | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h index ee6906a3c3f6..f93ba6be1ef8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | |||
@@ -31,6 +31,10 @@ | |||
31 | #define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32 | 31 | #define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32 |
32 | #define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48 | 32 | #define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48 |
33 | 33 | ||
34 | struct msgbuf_buf_addr { | ||
35 | __le32 low_addr; | ||
36 | __le32 high_addr; | ||
37 | }; | ||
34 | 38 | ||
35 | int brcmf_proto_msgbuf_rx_trigger(struct device *dev); | 39 | int brcmf_proto_msgbuf_rx_trigger(struct device *dev); |
36 | void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid); | 40 | void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 3deba90c7eb5..048027f2085b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | |||
@@ -135,7 +135,7 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { | |||
135 | BRCMF_PCIE_MB_INT_D2H3_DB1) | 135 | BRCMF_PCIE_MB_INT_D2H3_DB1) |
136 | 136 | ||
137 | #define BRCMF_PCIE_MIN_SHARED_VERSION 5 | 137 | #define BRCMF_PCIE_MIN_SHARED_VERSION 5 |
138 | #define BRCMF_PCIE_MAX_SHARED_VERSION 5 | 138 | #define BRCMF_PCIE_MAX_SHARED_VERSION 6 |
139 | #define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF | 139 | #define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF |
140 | #define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000 | 140 | #define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000 |
141 | #define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000 | 141 | #define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000 |
@@ -166,17 +166,6 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { | |||
166 | #define BRCMF_RING_MEM_SZ 16 | 166 | #define BRCMF_RING_MEM_SZ 16 |
167 | #define BRCMF_RING_STATE_SZ 8 | 167 | #define BRCMF_RING_STATE_SZ 8 |
168 | 168 | ||
169 | #define BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET 4 | ||
170 | #define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8 | ||
171 | #define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12 | ||
172 | #define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16 | ||
173 | #define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET 20 | ||
174 | #define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET 28 | ||
175 | #define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET 36 | ||
176 | #define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET 44 | ||
177 | #define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0 | ||
178 | #define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52 | ||
179 | |||
180 | #define BRCMF_DEF_MAX_RXBUFPOST 255 | 169 | #define BRCMF_DEF_MAX_RXBUFPOST 255 |
181 | 170 | ||
182 | #define BRCMF_CONSOLE_BUFADDR_OFFSET 8 | 171 | #define BRCMF_CONSOLE_BUFADDR_OFFSET 8 |
@@ -231,7 +220,9 @@ struct brcmf_pcie_shared_info { | |||
231 | struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS]; | 220 | struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS]; |
232 | struct brcmf_pcie_ringbuf *flowrings; | 221 | struct brcmf_pcie_ringbuf *flowrings; |
233 | u16 max_rxbufpost; | 222 | u16 max_rxbufpost; |
234 | u32 nrof_flowrings; | 223 | u16 max_flowrings; |
224 | u16 max_submissionrings; | ||
225 | u16 max_completionrings; | ||
235 | u32 rx_dataoffset; | 226 | u32 rx_dataoffset; |
236 | u32 htod_mb_data_addr; | 227 | u32 htod_mb_data_addr; |
237 | u32 dtoh_mb_data_addr; | 228 | u32 dtoh_mb_data_addr; |
@@ -241,6 +232,7 @@ struct brcmf_pcie_shared_info { | |||
241 | dma_addr_t scratch_dmahandle; | 232 | dma_addr_t scratch_dmahandle; |
242 | void *ringupd; | 233 | void *ringupd; |
243 | dma_addr_t ringupd_dmahandle; | 234 | dma_addr_t ringupd_dmahandle; |
235 | u8 version; | ||
244 | }; | 236 | }; |
245 | 237 | ||
246 | struct brcmf_pcie_core_info { | 238 | struct brcmf_pcie_core_info { |
@@ -284,6 +276,36 @@ struct brcmf_pcie_ringbuf { | |||
284 | u8 id; | 276 | u8 id; |
285 | }; | 277 | }; |
286 | 278 | ||
279 | /** | ||
280 | * struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info | ||
281 | * | ||
282 | * @ringmem: dongle memory pointer to ring memory location | ||
283 | * @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers | ||
284 | * @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers | ||
285 | * @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers | ||
286 | * @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers | ||
287 | * @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers | ||
288 | * @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers | ||
289 | * @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers | ||
290 | * @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers | ||
291 | * @max_flowrings: maximum number of tx flow rings supported. | ||
292 | * @max_submissionrings: maximum number of submission rings(h2d) supported. | ||
293 | * @max_completionrings: maximum number of completion rings(d2h) supported. | ||
294 | */ | ||
295 | struct brcmf_pcie_dhi_ringinfo { | ||
296 | __le32 ringmem; | ||
297 | __le32 h2d_w_idx_ptr; | ||
298 | __le32 h2d_r_idx_ptr; | ||
299 | __le32 d2h_w_idx_ptr; | ||
300 | __le32 d2h_r_idx_ptr; | ||
301 | struct msgbuf_buf_addr h2d_w_idx_hostaddr; | ||
302 | struct msgbuf_buf_addr h2d_r_idx_hostaddr; | ||
303 | struct msgbuf_buf_addr d2h_w_idx_hostaddr; | ||
304 | struct msgbuf_buf_addr d2h_r_idx_hostaddr; | ||
305 | __le16 max_flowrings; | ||
306 | __le16 max_submissionrings; | ||
307 | __le16 max_completionrings; | ||
308 | }; | ||
287 | 309 | ||
288 | static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = { | 310 | static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = { |
289 | BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM, | 311 | BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM, |
@@ -1054,26 +1076,35 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) | |||
1054 | { | 1076 | { |
1055 | struct brcmf_pcie_ringbuf *ring; | 1077 | struct brcmf_pcie_ringbuf *ring; |
1056 | struct brcmf_pcie_ringbuf *rings; | 1078 | struct brcmf_pcie_ringbuf *rings; |
1057 | u32 ring_addr; | ||
1058 | u32 d2h_w_idx_ptr; | 1079 | u32 d2h_w_idx_ptr; |
1059 | u32 d2h_r_idx_ptr; | 1080 | u32 d2h_r_idx_ptr; |
1060 | u32 h2d_w_idx_ptr; | 1081 | u32 h2d_w_idx_ptr; |
1061 | u32 h2d_r_idx_ptr; | 1082 | u32 h2d_r_idx_ptr; |
1062 | u32 addr; | ||
1063 | u32 ring_mem_ptr; | 1083 | u32 ring_mem_ptr; |
1064 | u32 i; | 1084 | u32 i; |
1065 | u64 address; | 1085 | u64 address; |
1066 | u32 bufsz; | 1086 | u32 bufsz; |
1067 | u16 max_sub_queues; | ||
1068 | u8 idx_offset; | 1087 | u8 idx_offset; |
1069 | 1088 | struct brcmf_pcie_dhi_ringinfo ringinfo; | |
1070 | ring_addr = devinfo->shared.ring_info_addr; | 1089 | u16 max_flowrings; |
1071 | brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr); | 1090 | u16 max_submissionrings; |
1072 | addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES; | 1091 | u16 max_completionrings; |
1073 | max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr); | 1092 | |
1093 | memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr, | ||
1094 | sizeof(ringinfo)); | ||
1095 | if (devinfo->shared.version >= 6) { | ||
1096 | max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings); | ||
1097 | max_flowrings = le16_to_cpu(ringinfo.max_flowrings); | ||
1098 | max_completionrings = le16_to_cpu(ringinfo.max_completionrings); | ||
1099 | } else { | ||
1100 | max_submissionrings = le16_to_cpu(ringinfo.max_flowrings); | ||
1101 | max_flowrings = max_submissionrings - | ||
1102 | BRCMF_NROF_H2D_COMMON_MSGRINGS; | ||
1103 | max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS; | ||
1104 | } | ||
1074 | 1105 | ||
1075 | if (devinfo->dma_idx_sz != 0) { | 1106 | if (devinfo->dma_idx_sz != 0) { |
1076 | bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) * | 1107 | bufsz = (max_submissionrings + max_completionrings) * |
1077 | devinfo->dma_idx_sz * 2; | 1108 | devinfo->dma_idx_sz * 2; |
1078 | devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz, | 1109 | devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz, |
1079 | &devinfo->idxbuf_dmahandle, | 1110 | &devinfo->idxbuf_dmahandle, |
@@ -1083,14 +1114,10 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) | |||
1083 | } | 1114 | } |
1084 | 1115 | ||
1085 | if (devinfo->dma_idx_sz == 0) { | 1116 | if (devinfo->dma_idx_sz == 0) { |
1086 | addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET; | 1117 | d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr); |
1087 | d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); | 1118 | d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr); |
1088 | addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET; | 1119 | h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr); |
1089 | d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); | 1120 | h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr); |
1090 | addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET; | ||
1091 | h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); | ||
1092 | addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET; | ||
1093 | h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); | ||
1094 | idx_offset = sizeof(u32); | 1121 | idx_offset = sizeof(u32); |
1095 | devinfo->write_ptr = brcmf_pcie_write_tcm16; | 1122 | devinfo->write_ptr = brcmf_pcie_write_tcm16; |
1096 | devinfo->read_ptr = brcmf_pcie_read_tcm16; | 1123 | devinfo->read_ptr = brcmf_pcie_read_tcm16; |
@@ -1103,34 +1130,42 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) | |||
1103 | devinfo->read_ptr = brcmf_pcie_read_idx; | 1130 | devinfo->read_ptr = brcmf_pcie_read_idx; |
1104 | 1131 | ||
1105 | h2d_w_idx_ptr = 0; | 1132 | h2d_w_idx_ptr = 0; |
1106 | addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET; | ||
1107 | address = (u64)devinfo->idxbuf_dmahandle; | 1133 | address = (u64)devinfo->idxbuf_dmahandle; |
1108 | brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); | 1134 | ringinfo.h2d_w_idx_hostaddr.low_addr = |
1109 | brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); | 1135 | cpu_to_le32(address & 0xffffffff); |
1110 | 1136 | ringinfo.h2d_w_idx_hostaddr.high_addr = | |
1111 | h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset; | 1137 | cpu_to_le32(address >> 32); |
1112 | addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET; | 1138 | |
1113 | address += max_sub_queues * idx_offset; | 1139 | h2d_r_idx_ptr = h2d_w_idx_ptr + |
1114 | brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); | 1140 | max_submissionrings * idx_offset; |
1115 | brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); | 1141 | address += max_submissionrings * idx_offset; |
1116 | 1142 | ringinfo.h2d_r_idx_hostaddr.low_addr = | |
1117 | d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset; | 1143 | cpu_to_le32(address & 0xffffffff); |
1118 | addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET; | 1144 | ringinfo.h2d_r_idx_hostaddr.high_addr = |
1119 | address += max_sub_queues * idx_offset; | 1145 | cpu_to_le32(address >> 32); |
1120 | brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); | 1146 | |
1121 | brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); | 1147 | d2h_w_idx_ptr = h2d_r_idx_ptr + |
1148 | max_submissionrings * idx_offset; | ||
1149 | address += max_submissionrings * idx_offset; | ||
1150 | ringinfo.d2h_w_idx_hostaddr.low_addr = | ||
1151 | cpu_to_le32(address & 0xffffffff); | ||
1152 | ringinfo.d2h_w_idx_hostaddr.high_addr = | ||
1153 | cpu_to_le32(address >> 32); | ||
1122 | 1154 | ||
1123 | d2h_r_idx_ptr = d2h_w_idx_ptr + | 1155 | d2h_r_idx_ptr = d2h_w_idx_ptr + |
1124 | BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset; | 1156 | max_completionrings * idx_offset; |
1125 | addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET; | 1157 | address += max_completionrings * idx_offset; |
1126 | address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset; | 1158 | ringinfo.d2h_r_idx_hostaddr.low_addr = |
1127 | brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); | 1159 | cpu_to_le32(address & 0xffffffff); |
1128 | brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); | 1160 | ringinfo.d2h_r_idx_hostaddr.high_addr = |
1161 | cpu_to_le32(address >> 32); | ||
1162 | |||
1163 | memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr, | ||
1164 | &ringinfo, sizeof(ringinfo)); | ||
1129 | brcmf_dbg(PCIE, "Using host memory indices\n"); | 1165 | brcmf_dbg(PCIE, "Using host memory indices\n"); |
1130 | } | 1166 | } |
1131 | 1167 | ||
1132 | addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET; | 1168 | ring_mem_ptr = le32_to_cpu(ringinfo.ringmem); |
1133 | ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr); | ||
1134 | 1169 | ||
1135 | for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) { | 1170 | for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) { |
1136 | ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr); | 1171 | ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr); |
@@ -1161,20 +1196,19 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) | |||
1161 | ring_mem_ptr += BRCMF_RING_MEM_SZ; | 1196 | ring_mem_ptr += BRCMF_RING_MEM_SZ; |
1162 | } | 1197 | } |
1163 | 1198 | ||
1164 | devinfo->shared.nrof_flowrings = | 1199 | devinfo->shared.max_flowrings = max_flowrings; |
1165 | max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS; | 1200 | devinfo->shared.max_submissionrings = max_submissionrings; |
1166 | rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring), | 1201 | devinfo->shared.max_completionrings = max_completionrings; |
1167 | GFP_KERNEL); | 1202 | rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL); |
1168 | if (!rings) | 1203 | if (!rings) |
1169 | goto fail; | 1204 | goto fail; |
1170 | 1205 | ||
1171 | brcmf_dbg(PCIE, "Nr of flowrings is %d\n", | 1206 | brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings); |
1172 | devinfo->shared.nrof_flowrings); | ||
1173 | 1207 | ||
1174 | for (i = 0; i < devinfo->shared.nrof_flowrings; i++) { | 1208 | for (i = 0; i < max_flowrings; i++) { |
1175 | ring = &rings[i]; | 1209 | ring = &rings[i]; |
1176 | ring->devinfo = devinfo; | 1210 | ring->devinfo = devinfo; |
1177 | ring->id = i + BRCMF_NROF_COMMON_MSGRINGS; | 1211 | ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART; |
1178 | brcmf_commonring_register_cb(&ring->commonring, | 1212 | brcmf_commonring_register_cb(&ring->commonring, |
1179 | brcmf_pcie_ring_mb_ring_bell, | 1213 | brcmf_pcie_ring_mb_ring_bell, |
1180 | brcmf_pcie_ring_mb_update_rptr, | 1214 | brcmf_pcie_ring_mb_update_rptr, |
@@ -1357,17 +1391,16 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, | |||
1357 | { | 1391 | { |
1358 | struct brcmf_pcie_shared_info *shared; | 1392 | struct brcmf_pcie_shared_info *shared; |
1359 | u32 addr; | 1393 | u32 addr; |
1360 | u32 version; | ||
1361 | 1394 | ||
1362 | shared = &devinfo->shared; | 1395 | shared = &devinfo->shared; |
1363 | shared->tcm_base_address = sharedram_addr; | 1396 | shared->tcm_base_address = sharedram_addr; |
1364 | 1397 | ||
1365 | shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr); | 1398 | shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr); |
1366 | version = shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK; | 1399 | shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK); |
1367 | brcmf_dbg(PCIE, "PCIe protocol version %d\n", version); | 1400 | brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version); |
1368 | if ((version > BRCMF_PCIE_MAX_SHARED_VERSION) || | 1401 | if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) || |
1369 | (version < BRCMF_PCIE_MIN_SHARED_VERSION)) { | 1402 | (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) { |
1370 | brcmf_err("Unsupported PCIE version %d\n", version); | 1403 | brcmf_err("Unsupported PCIE version %d\n", shared->version); |
1371 | return -EINVAL; | 1404 | return -EINVAL; |
1372 | } | 1405 | } |
1373 | 1406 | ||
@@ -1661,18 +1694,18 @@ static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, | |||
1661 | bus->msgbuf->commonrings[i] = | 1694 | bus->msgbuf->commonrings[i] = |
1662 | &devinfo->shared.commonrings[i]->commonring; | 1695 | &devinfo->shared.commonrings[i]->commonring; |
1663 | 1696 | ||
1664 | flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings), | 1697 | flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings), |
1665 | GFP_KERNEL); | 1698 | GFP_KERNEL); |
1666 | if (!flowrings) | 1699 | if (!flowrings) |
1667 | goto fail; | 1700 | goto fail; |
1668 | 1701 | ||
1669 | for (i = 0; i < devinfo->shared.nrof_flowrings; i++) | 1702 | for (i = 0; i < devinfo->shared.max_flowrings; i++) |
1670 | flowrings[i] = &devinfo->shared.flowrings[i].commonring; | 1703 | flowrings[i] = &devinfo->shared.flowrings[i].commonring; |
1671 | bus->msgbuf->flowrings = flowrings; | 1704 | bus->msgbuf->flowrings = flowrings; |
1672 | 1705 | ||
1673 | bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset; | 1706 | bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset; |
1674 | bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost; | 1707 | bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost; |
1675 | bus->msgbuf->nrof_flowrings = devinfo->shared.nrof_flowrings; | 1708 | bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings; |
1676 | 1709 | ||
1677 | init_waitqueue_head(&devinfo->mbdata_resp_wait); | 1710 | init_waitqueue_head(&devinfo->mbdata_resp_wait); |
1678 | 1711 | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c new file mode 100644 index 000000000000..f273cab0da10 --- /dev/null +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Broadcom | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #include <linux/netdevice.h> | ||
17 | #include <net/cfg80211.h> | ||
18 | |||
19 | #include "core.h" | ||
20 | #include "debug.h" | ||
21 | #include "fwil.h" | ||
22 | #include "fwil_types.h" | ||
23 | #include "cfg80211.h" | ||
24 | #include "pno.h" | ||
25 | |||
26 | #define BRCMF_PNO_VERSION 2 | ||
27 | #define BRCMF_PNO_REPEAT 4 | ||
28 | #define BRCMF_PNO_FREQ_EXPO_MAX 3 | ||
29 | #define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3 | ||
30 | #define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5 | ||
31 | #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 | ||
32 | #define BRCMF_PNO_REPORT_SEPARATELY_BIT 11 | ||
33 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 | ||
34 | #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF | ||
35 | #define BRCMF_PNO_HIDDEN_BIT 2 | ||
36 | #define BRCMF_PNO_SCHED_SCAN_PERIOD 30 | ||
37 | |||
38 | static int brcmf_pno_channel_config(struct brcmf_if *ifp, | ||
39 | struct brcmf_pno_config_le *cfg) | ||
40 | { | ||
41 | cfg->reporttype = 0; | ||
42 | cfg->flags = 0; | ||
43 | |||
44 | return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg)); | ||
45 | } | ||
46 | |||
47 | static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, | ||
48 | u32 mscan, u32 bestn) | ||
49 | { | ||
50 | struct brcmf_pno_param_le pfn_param; | ||
51 | u16 flags; | ||
52 | u32 pfnmem; | ||
53 | s32 err; | ||
54 | |||
55 | memset(&pfn_param, 0, sizeof(pfn_param)); | ||
56 | pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); | ||
57 | |||
58 | /* set extra pno params */ | ||
59 | flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) | | ||
60 | BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) | | ||
61 | BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); | ||
62 | pfn_param.repeat = BRCMF_PNO_REPEAT; | ||
63 | pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; | ||
64 | |||
65 | /* set up pno scan fr */ | ||
66 | if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) { | ||
67 | brcmf_dbg(SCAN, "scan period too small, using minimum\n"); | ||
68 | scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD; | ||
69 | } | ||
70 | pfn_param.scan_freq = cpu_to_le32(scan_freq); | ||
71 | |||
72 | if (mscan) { | ||
73 | pfnmem = bestn; | ||
74 | |||
75 | /* set bestn in firmware */ | ||
76 | err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem); | ||
77 | if (err < 0) { | ||
78 | brcmf_err("failed to set pfnmem\n"); | ||
79 | goto exit; | ||
80 | } | ||
81 | /* get max mscan which the firmware supports */ | ||
82 | err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem); | ||
83 | if (err < 0) { | ||
84 | brcmf_err("failed to get pfnmem\n"); | ||
85 | goto exit; | ||
86 | } | ||
87 | mscan = min_t(u32, mscan, pfnmem); | ||
88 | pfn_param.mscan = mscan; | ||
89 | pfn_param.bestn = bestn; | ||
90 | flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT); | ||
91 | brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn); | ||
92 | } | ||
93 | |||
94 | pfn_param.flags = cpu_to_le16(flags); | ||
95 | err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, | ||
96 | sizeof(pfn_param)); | ||
97 | if (err) | ||
98 | brcmf_err("pfn_set failed, err=%d\n", err); | ||
99 | |||
100 | exit: | ||
101 | return err; | ||
102 | } | ||
103 | |||
104 | static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, | ||
105 | u8 *mac_mask) | ||
106 | { | ||
107 | struct brcmf_pno_macaddr_le pfn_mac; | ||
108 | int err, i; | ||
109 | |||
110 | pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; | ||
111 | pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; | ||
112 | |||
113 | memcpy(pfn_mac.mac, mac_addr, ETH_ALEN); | ||
114 | for (i = 0; i < ETH_ALEN; i++) { | ||
115 | pfn_mac.mac[i] &= mac_mask[i]; | ||
116 | pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); | ||
117 | } | ||
118 | /* Clear multi bit */ | ||
119 | pfn_mac.mac[0] &= 0xFE; | ||
120 | /* Set locally administered */ | ||
121 | pfn_mac.mac[0] |= 0x02; | ||
122 | |||
123 | err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, | ||
124 | sizeof(pfn_mac)); | ||
125 | if (err) | ||
126 | brcmf_err("pfn_macaddr failed, err=%d\n", err); | ||
127 | |||
128 | return err; | ||
129 | } | ||
130 | |||
131 | static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, | ||
132 | bool active) | ||
133 | { | ||
134 | struct brcmf_pno_net_param_le pfn; | ||
135 | |||
136 | pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); | ||
137 | pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); | ||
138 | pfn.wsec = cpu_to_le32(0); | ||
139 | pfn.infra = cpu_to_le32(1); | ||
140 | if (active) | ||
141 | pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); | ||
142 | pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len); | ||
143 | memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len); | ||
144 | return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn)); | ||
145 | } | ||
146 | |||
147 | static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid, | ||
148 | struct cfg80211_sched_scan_request *req) | ||
149 | { | ||
150 | int i; | ||
151 | |||
152 | if (!ssid || !req->ssids || !req->n_ssids) | ||
153 | return false; | ||
154 | |||
155 | for (i = 0; i < req->n_ssids; i++) { | ||
156 | if (ssid->ssid_len == req->ssids[i].ssid_len) { | ||
157 | if (!strncmp(ssid->ssid, req->ssids[i].ssid, | ||
158 | ssid->ssid_len)) | ||
159 | return true; | ||
160 | } | ||
161 | } | ||
162 | return false; | ||
163 | } | ||
164 | |||
165 | int brcmf_pno_clean(struct brcmf_if *ifp) | ||
166 | { | ||
167 | int ret; | ||
168 | |||
169 | /* Disable pfn */ | ||
170 | ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); | ||
171 | if (ret == 0) { | ||
172 | /* clear pfn */ | ||
173 | ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); | ||
174 | } | ||
175 | if (ret < 0) | ||
176 | brcmf_err("failed code %d\n", ret); | ||
177 | |||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, | ||
182 | struct cfg80211_sched_scan_request *req) | ||
183 | { | ||
184 | struct brcmu_d11inf *d11inf; | ||
185 | struct brcmf_pno_config_le pno_cfg; | ||
186 | struct cfg80211_ssid *ssid; | ||
187 | u16 chan; | ||
188 | int i, ret; | ||
189 | |||
190 | /* clean up everything */ | ||
191 | ret = brcmf_pno_clean(ifp); | ||
192 | if (ret < 0) { | ||
193 | brcmf_err("failed error=%d\n", ret); | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | /* configure pno */ | ||
198 | ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0); | ||
199 | if (ret < 0) | ||
200 | return ret; | ||
201 | |||
202 | /* configure random mac */ | ||
203 | if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { | ||
204 | ret = brcmf_pno_set_random(ifp, req->mac_addr, | ||
205 | req->mac_addr_mask); | ||
206 | if (ret < 0) | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /* configure channels to use */ | ||
211 | d11inf = &ifp->drvr->config->d11inf; | ||
212 | for (i = 0; i < req->n_channels; i++) { | ||
213 | chan = req->channels[i]->hw_value; | ||
214 | pno_cfg.channel_list[i] = cpu_to_le16(chan); | ||
215 | } | ||
216 | if (req->n_channels) { | ||
217 | pno_cfg.channel_num = cpu_to_le32(req->n_channels); | ||
218 | brcmf_pno_channel_config(ifp, &pno_cfg); | ||
219 | } | ||
220 | |||
221 | /* configure each match set */ | ||
222 | for (i = 0; i < req->n_match_sets; i++) { | ||
223 | ssid = &req->match_sets[i].ssid; | ||
224 | if (!ssid->ssid_len) { | ||
225 | brcmf_err("skip broadcast ssid\n"); | ||
226 | continue; | ||
227 | } | ||
228 | |||
229 | ret = brcmf_pno_add_ssid(ifp, ssid, | ||
230 | brcmf_is_ssid_active(ssid, req)); | ||
231 | if (ret < 0) | ||
232 | brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", | ||
233 | ret == 0 ? "set" : "failed", ssid->ssid); | ||
234 | } | ||
235 | /* Enable the PNO */ | ||
236 | ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1); | ||
237 | if (ret < 0) | ||
238 | brcmf_err("PNO enable failed!! ret=%d\n", ret); | ||
239 | |||
240 | return ret; | ||
241 | } | ||
242 | |||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h new file mode 100644 index 000000000000..bae55b2af78c --- /dev/null +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Broadcom | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef _BRCMF_PNO_H | ||
17 | #define _BRCMF_PNO_H | ||
18 | |||
19 | #define BRCMF_PNO_SCAN_COMPLETE 1 | ||
20 | #define BRCMF_PNO_MAX_PFN_COUNT 16 | ||
21 | #define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10 | ||
22 | #define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508 | ||
23 | |||
24 | /** | ||
25 | * brcmf_pno_clean - disable and clear pno in firmware. | ||
26 | * | ||
27 | * @ifp: interface object used. | ||
28 | */ | ||
29 | int brcmf_pno_clean(struct brcmf_if *ifp); | ||
30 | |||
31 | /** | ||
32 | * brcmf_pno_start_sched_scan - initiate scheduled scan on device. | ||
33 | * | ||
34 | * @ifp: interface object used. | ||
35 | * @req: configuration parameters for scheduled scan. | ||
36 | */ | ||
37 | int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, | ||
38 | struct cfg80211_sched_scan_request *req); | ||
39 | |||
40 | #endif /* _BRCMF_PNO_H */ | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index b892dac70f4b..dfb0658713d9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | |||
@@ -621,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { | |||
621 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), | 621 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), |
622 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), | 622 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), |
623 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), | 623 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), |
624 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340), | ||
624 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), | 625 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), |
625 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), | 626 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), |
626 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), | 627 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c index faf1ebe76068..b9672da24a9d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c | |||
@@ -179,7 +179,7 @@ s16 qm_norm32(s32 op) | |||
179 | return u16extraSignBits; | 179 | return u16extraSignBits; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */ | 182 | /* This table is log2(1+(i/32)) where i=[0:1:32], in q.15 format */ |
183 | static const s16 log_table[] = { | 183 | static const s16 log_table[] = { |
184 | 0, | 184 | 0, |
185 | 1455, | 185 | 1455, |
@@ -212,7 +212,8 @@ static const s16 log_table[] = { | |||
212 | 29717, | 212 | 29717, |
213 | 30498, | 213 | 30498, |
214 | 31267, | 214 | 31267, |
215 | 32024 | 215 | 32024, |
216 | 32768 | ||
216 | }; | 217 | }; |
217 | 218 | ||
218 | #define LOG_TABLE_SIZE 32 /* log_table size */ | 219 | #define LOG_TABLE_SIZE 32 /* log_table size */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h index d0407d9ad782..f1fb8a3c7a32 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #define BRCM_CC_4330_CHIP_ID 0x4330 | 36 | #define BRCM_CC_4330_CHIP_ID 0x4330 |
37 | #define BRCM_CC_4334_CHIP_ID 0x4334 | 37 | #define BRCM_CC_4334_CHIP_ID 0x4334 |
38 | #define BRCM_CC_43340_CHIP_ID 43340 | 38 | #define BRCM_CC_43340_CHIP_ID 43340 |
39 | #define BRCM_CC_43341_CHIP_ID 43341 | ||
39 | #define BRCM_CC_43362_CHIP_ID 43362 | 40 | #define BRCM_CC_43362_CHIP_ID 43362 |
40 | #define BRCM_CC_4335_CHIP_ID 0x4335 | 41 | #define BRCM_CC_4335_CHIP_ID 0x4335 |
41 | #define BRCM_CC_4339_CHIP_ID 0x4339 | 42 | #define BRCM_CC_4339_CHIP_ID 0x4339 |
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index c26469a5a5f3..a7d359e9f378 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c | |||
@@ -2143,6 +2143,16 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, | |||
2143 | ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1); | 2143 | ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1); |
2144 | 2144 | ||
2145 | if (mode == NL80211_IFTYPE_ADHOC) { | 2145 | if (mode == NL80211_IFTYPE_ADHOC) { |
2146 | u16 enable = true; | ||
2147 | |||
2148 | /* set ibss coalescing_status */ | ||
2149 | ret = mwifiex_send_cmd( | ||
2150 | priv, | ||
2151 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, | ||
2152 | HostCmd_ACT_GEN_SET, 0, &enable, true); | ||
2153 | if (ret) | ||
2154 | return ret; | ||
2155 | |||
2146 | /* "privacy" is set only for ad-hoc mode */ | 2156 | /* "privacy" is set only for ad-hoc mode */ |
2147 | if (privacy) { | 2157 | if (privacy) { |
2148 | /* | 2158 | /* |
@@ -3980,13 +3990,11 @@ static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3980 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); | 3990 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); |
3981 | struct mwifiex_ds_misc_cmd *hostcmd; | 3991 | struct mwifiex_ds_misc_cmd *hostcmd; |
3982 | struct nlattr *tb[MWIFIEX_TM_ATTR_MAX + 1]; | 3992 | struct nlattr *tb[MWIFIEX_TM_ATTR_MAX + 1]; |
3983 | struct mwifiex_adapter *adapter; | ||
3984 | struct sk_buff *skb; | 3993 | struct sk_buff *skb; |
3985 | int err; | 3994 | int err; |
3986 | 3995 | ||
3987 | if (!priv) | 3996 | if (!priv) |
3988 | return -EINVAL; | 3997 | return -EINVAL; |
3989 | adapter = priv->adapter; | ||
3990 | 3998 | ||
3991 | err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len, | 3999 | err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len, |
3992 | mwifiex_tm_policy); | 4000 | mwifiex_tm_policy); |
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 9b3cceadd707..ea455948a68a 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h | |||
@@ -219,6 +219,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
219 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) | 219 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) |
220 | #define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15)) | 220 | #define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15)) |
221 | #define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16)) | 221 | #define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16)) |
222 | #define ISSUPP_ADHOC_ENABLED(FwCapInfo) (FwCapInfo & BIT(25)) | ||
222 | 223 | ||
223 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ | 224 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ |
224 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ | 225 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ |
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index eac44fe9c416..e5c3a8aa3929 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c | |||
@@ -518,7 +518,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
518 | { | 518 | { |
519 | int ret; | 519 | int ret; |
520 | char fmt[64]; | 520 | char fmt[64]; |
521 | struct mwifiex_private *priv; | ||
522 | struct mwifiex_adapter *adapter = context; | 521 | struct mwifiex_adapter *adapter = context; |
523 | struct mwifiex_fw_image fw; | 522 | struct mwifiex_fw_image fw; |
524 | bool init_failed = false; | 523 | bool init_failed = false; |
@@ -576,8 +575,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
576 | goto err_init_fw; | 575 | goto err_init_fw; |
577 | } | 576 | } |
578 | 577 | ||
579 | priv = adapter->priv[MWIFIEX_BSS_ROLE_STA]; | ||
580 | |||
581 | if (!adapter->wiphy) { | 578 | if (!adapter->wiphy) { |
582 | if (mwifiex_register_cfg80211(adapter)) { | 579 | if (mwifiex_register_cfg80211(adapter)) { |
583 | mwifiex_dbg(adapter, ERROR, | 580 | mwifiex_dbg(adapter, ERROR, |
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index cf4c78080d94..5c9bd944b6ea 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h | |||
@@ -1424,8 +1424,13 @@ static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter) | |||
1424 | { | 1424 | { |
1425 | if (adapter->irq_wakeup >= 0) { | 1425 | if (adapter->irq_wakeup >= 0) { |
1426 | disable_irq_wake(adapter->irq_wakeup); | 1426 | disable_irq_wake(adapter->irq_wakeup); |
1427 | if (!adapter->wake_by_wifi) | 1427 | disable_irq(adapter->irq_wakeup); |
1428 | disable_irq(adapter->irq_wakeup); | 1428 | if (adapter->wake_by_wifi) |
1429 | /* Undo our disable, since interrupt handler already | ||
1430 | * did this. | ||
1431 | */ | ||
1432 | enable_irq(adapter->irq_wakeup); | ||
1433 | |||
1429 | } | 1434 | } |
1430 | } | 1435 | } |
1431 | 1436 | ||
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 4b89f557d0b6..4db07da81d8d 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c | |||
@@ -135,6 +135,7 @@ static int mwifiex_pcie_suspend(struct device *dev) | |||
135 | mwifiex_dbg(adapter, ERROR, | 135 | mwifiex_dbg(adapter, ERROR, |
136 | "cmd: failed to suspend\n"); | 136 | "cmd: failed to suspend\n"); |
137 | adapter->hs_enabling = false; | 137 | adapter->hs_enabling = false; |
138 | mwifiex_disable_wake(adapter); | ||
138 | return -EFAULT; | 139 | return -EFAULT; |
139 | } | 140 | } |
140 | 141 | ||
@@ -2050,7 +2051,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
2050 | } | 2051 | } |
2051 | 2052 | ||
2052 | /* Wait for the command done interrupt */ | 2053 | /* Wait for the command done interrupt */ |
2053 | do { | 2054 | for (tries = 0; tries < MAX_POLL_TRIES; tries++) { |
2054 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, | 2055 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, |
2055 | &ireg_intr)) { | 2056 | &ireg_intr)) { |
2056 | mwifiex_dbg(adapter, ERROR, | 2057 | mwifiex_dbg(adapter, ERROR, |
@@ -2062,8 +2063,18 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
2062 | ret = -1; | 2063 | ret = -1; |
2063 | goto done; | 2064 | goto done; |
2064 | } | 2065 | } |
2065 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == | 2066 | if (!(ireg_intr & CPU_INTR_DOOR_BELL)) |
2066 | CPU_INTR_DOOR_BELL); | 2067 | break; |
2068 | usleep_range(10, 20); | ||
2069 | } | ||
2070 | if (ireg_intr & CPU_INTR_DOOR_BELL) { | ||
2071 | mwifiex_dbg(adapter, ERROR, "%s: Card failed to ACK download\n", | ||
2072 | __func__); | ||
2073 | mwifiex_unmap_pci_memory(adapter, skb, | ||
2074 | PCI_DMA_TODEVICE); | ||
2075 | ret = -1; | ||
2076 | goto done; | ||
2077 | } | ||
2067 | 2078 | ||
2068 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); | 2079 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
2069 | 2080 | ||
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 98ce07280ae8..181691684a08 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c | |||
@@ -827,7 +827,6 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
827 | u32 num_probes; | 827 | u32 num_probes; |
828 | u32 ssid_len; | 828 | u32 ssid_len; |
829 | u32 chan_idx; | 829 | u32 chan_idx; |
830 | u32 chan_num; | ||
831 | u32 scan_type; | 830 | u32 scan_type; |
832 | u16 scan_dur; | 831 | u16 scan_dur; |
833 | u8 channel; | 832 | u8 channel; |
@@ -1105,13 +1104,12 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
1105 | mwifiex_dbg(adapter, INFO, | 1104 | mwifiex_dbg(adapter, INFO, |
1106 | "info: Scan: Scanning current channel only\n"); | 1105 | "info: Scan: Scanning current channel only\n"); |
1107 | } | 1106 | } |
1108 | chan_num = chan_idx; | ||
1109 | } else { | 1107 | } else { |
1110 | mwifiex_dbg(adapter, INFO, | 1108 | mwifiex_dbg(adapter, INFO, |
1111 | "info: Scan: Creating full region channel list\n"); | 1109 | "info: Scan: Creating full region channel list\n"); |
1112 | chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in, | 1110 | mwifiex_scan_create_channel_list(priv, user_scan_in, |
1113 | scan_chan_list, | 1111 | scan_chan_list, |
1114 | *filtered_scan); | 1112 | *filtered_scan); |
1115 | } | 1113 | } |
1116 | 1114 | ||
1117 | } | 1115 | } |
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 0d00db5142e6..740d79cd91fa 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c | |||
@@ -186,9 +186,7 @@ static int mwifiex_sdio_resume(struct device *dev) | |||
186 | struct sdio_func *func = dev_to_sdio_func(dev); | 186 | struct sdio_func *func = dev_to_sdio_func(dev); |
187 | struct sdio_mmc_card *card; | 187 | struct sdio_mmc_card *card; |
188 | struct mwifiex_adapter *adapter; | 188 | struct mwifiex_adapter *adapter; |
189 | mmc_pm_flag_t pm_flag = 0; | ||
190 | 189 | ||
191 | pm_flag = sdio_get_host_pm_caps(func); | ||
192 | card = sdio_get_drvdata(func); | 190 | card = sdio_get_drvdata(func); |
193 | if (!card || !card->adapter) { | 191 | if (!card || !card->adapter) { |
194 | dev_err(dev, "resume: invalid card or adapter\n"); | 192 | dev_err(dev, "resume: invalid card or adapter\n"); |
@@ -298,6 +296,7 @@ static int mwifiex_sdio_suspend(struct device *dev) | |||
298 | mwifiex_dbg(adapter, ERROR, | 296 | mwifiex_dbg(adapter, ERROR, |
299 | "cmd: failed to suspend\n"); | 297 | "cmd: failed to suspend\n"); |
300 | adapter->hs_enabling = false; | 298 | adapter->hs_enabling = false; |
299 | mwifiex_disable_wake(adapter); | ||
301 | return -EFAULT; | 300 | return -EFAULT; |
302 | } | 301 | } |
303 | 302 | ||
@@ -1136,7 +1135,6 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, | |||
1136 | { | 1135 | { |
1137 | u32 total_pkt_len, pkt_len; | 1136 | u32 total_pkt_len, pkt_len; |
1138 | struct sk_buff *skb_deaggr; | 1137 | struct sk_buff *skb_deaggr; |
1139 | u32 pkt_type; | ||
1140 | u16 blk_size; | 1138 | u16 blk_size; |
1141 | u8 blk_num; | 1139 | u8 blk_num; |
1142 | u8 *data; | 1140 | u8 *data; |
@@ -1157,8 +1155,6 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, | |||
1157 | break; | 1155 | break; |
1158 | } | 1156 | } |
1159 | pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET)); | 1157 | pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET)); |
1160 | pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET + | ||
1161 | 2)); | ||
1162 | if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) { | 1158 | if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) { |
1163 | mwifiex_dbg(adapter, ERROR, | 1159 | mwifiex_dbg(adapter, ERROR, |
1164 | "%s: error in pkt_len,\t" | 1160 | "%s: error in pkt_len,\t" |
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index bcd64081d4a8..125e448712dd 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c | |||
@@ -1746,7 +1746,6 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
1746 | { | 1746 | { |
1747 | struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper; | 1747 | struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper; |
1748 | struct mwifiex_ds_tdls_oper *oper = data_buf; | 1748 | struct mwifiex_ds_tdls_oper *oper = data_buf; |
1749 | struct mwifiex_sta_node *sta_ptr; | ||
1750 | struct host_cmd_tlv_rates *tlv_rates; | 1749 | struct host_cmd_tlv_rates *tlv_rates; |
1751 | struct mwifiex_ie_types_htcap *ht_capab; | 1750 | struct mwifiex_ie_types_htcap *ht_capab; |
1752 | struct mwifiex_ie_types_qos_info *wmm_qos_info; | 1751 | struct mwifiex_ie_types_qos_info *wmm_qos_info; |
@@ -1764,7 +1763,6 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
1764 | 1763 | ||
1765 | tdls_oper->reason = 0; | 1764 | tdls_oper->reason = 0; |
1766 | memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN); | 1765 | memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN); |
1767 | sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac); | ||
1768 | 1766 | ||
1769 | pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper); | 1767 | pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper); |
1770 | 1768 | ||
@@ -1902,6 +1900,24 @@ static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv, | |||
1902 | return 0; | 1900 | return 0; |
1903 | } | 1901 | } |
1904 | 1902 | ||
1903 | /* This function check if the command is supported by firmware */ | ||
1904 | static int mwifiex_is_cmd_supported(struct mwifiex_private *priv, u16 cmd_no) | ||
1905 | { | ||
1906 | if (!ISSUPP_ADHOC_ENABLED(priv->adapter->fw_cap_info)) { | ||
1907 | switch (cmd_no) { | ||
1908 | case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: | ||
1909 | case HostCmd_CMD_802_11_AD_HOC_START: | ||
1910 | case HostCmd_CMD_802_11_AD_HOC_JOIN: | ||
1911 | case HostCmd_CMD_802_11_AD_HOC_STOP: | ||
1912 | return -EOPNOTSUPP; | ||
1913 | default: | ||
1914 | break; | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | return 0; | ||
1919 | } | ||
1920 | |||
1905 | /* | 1921 | /* |
1906 | * This function prepares the commands before sending them to the firmware. | 1922 | * This function prepares the commands before sending them to the firmware. |
1907 | * | 1923 | * |
@@ -1915,6 +1931,13 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1915 | struct host_cmd_ds_command *cmd_ptr = cmd_buf; | 1931 | struct host_cmd_ds_command *cmd_ptr = cmd_buf; |
1916 | int ret = 0; | 1932 | int ret = 0; |
1917 | 1933 | ||
1934 | if (mwifiex_is_cmd_supported(priv, cmd_no)) { | ||
1935 | mwifiex_dbg(priv->adapter, ERROR, | ||
1936 | "0x%x command not supported by firmware\n", | ||
1937 | cmd_no); | ||
1938 | return -EOPNOTSUPP; | ||
1939 | } | ||
1940 | |||
1918 | /* Prepare command */ | 1941 | /* Prepare command */ |
1919 | switch (cmd_no) { | 1942 | switch (cmd_no) { |
1920 | case HostCmd_CMD_GET_HW_SPEC: | 1943 | case HostCmd_CMD_GET_HW_SPEC: |
@@ -2208,7 +2231,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) | |||
2208 | { | 2231 | { |
2209 | struct mwifiex_adapter *adapter = priv->adapter; | 2232 | struct mwifiex_adapter *adapter = priv->adapter; |
2210 | int ret; | 2233 | int ret; |
2211 | u16 enable = true; | ||
2212 | struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; | 2234 | struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; |
2213 | struct mwifiex_ds_auto_ds auto_ds; | 2235 | struct mwifiex_ds_auto_ds auto_ds; |
2214 | enum state_11d_t state_11d; | 2236 | enum state_11d_t state_11d; |
@@ -2321,16 +2343,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) | |||
2321 | if (ret) | 2343 | if (ret) |
2322 | return -1; | 2344 | return -1; |
2323 | 2345 | ||
2324 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { | ||
2325 | /* set ibss coalescing_status */ | ||
2326 | ret = mwifiex_send_cmd( | ||
2327 | priv, | ||
2328 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, | ||
2329 | HostCmd_ACT_GEN_SET, 0, &enable, true); | ||
2330 | if (ret) | ||
2331 | return -1; | ||
2332 | } | ||
2333 | |||
2334 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); | 2346 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); |
2335 | amsdu_aggr_ctrl.enable = true; | 2347 | amsdu_aggr_ctrl.enable = true; |
2336 | /* Send request to firmware */ | 2348 | /* Send request to firmware */ |
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index c3f696a2e852..c563160b3b6b 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c | |||
@@ -379,7 +379,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
379 | struct usb_endpoint_descriptor *epd; | 379 | struct usb_endpoint_descriptor *epd; |
380 | int ret, i; | 380 | int ret, i; |
381 | struct usb_card_rec *card; | 381 | struct usb_card_rec *card; |
382 | u16 id_vendor, id_product, bcd_device, bcd_usb; | 382 | u16 id_vendor, id_product, bcd_device; |
383 | 383 | ||
384 | card = devm_kzalloc(&intf->dev, sizeof(*card), GFP_KERNEL); | 384 | card = devm_kzalloc(&intf->dev, sizeof(*card), GFP_KERNEL); |
385 | if (!card) | 385 | if (!card) |
@@ -390,7 +390,6 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
390 | id_vendor = le16_to_cpu(udev->descriptor.idVendor); | 390 | id_vendor = le16_to_cpu(udev->descriptor.idVendor); |
391 | id_product = le16_to_cpu(udev->descriptor.idProduct); | 391 | id_product = le16_to_cpu(udev->descriptor.idProduct); |
392 | bcd_device = le16_to_cpu(udev->descriptor.bcdDevice); | 392 | bcd_device = le16_to_cpu(udev->descriptor.bcdDevice); |
393 | bcd_usb = le16_to_cpu(udev->descriptor.bcdUSB); | ||
394 | pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n", | 393 | pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n", |
395 | id_vendor, id_product, bcd_device); | 394 | id_vendor, id_product, bcd_device); |
396 | 395 | ||
diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c index 44d46e25db80..a6e901766226 100644 --- a/drivers/net/wireless/mediatek/mt7601u/init.c +++ b/drivers/net/wireless/mediatek/mt7601u/init.c | |||
@@ -293,13 +293,13 @@ static void mt7601u_mac_stop_hw(struct mt7601u_dev *dev) | |||
293 | ok = 0; | 293 | ok = 0; |
294 | i = 200; | 294 | i = 200; |
295 | while (i--) { | 295 | while (i--) { |
296 | if ((mt76_rr(dev, 0x0430) & 0x00ff0000) || | 296 | if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) && |
297 | (mt76_rr(dev, 0x0a30) & 0xffffffff) || | 297 | !mt76_rr(dev, 0x0a30) && |
298 | (mt76_rr(dev, 0x0a34) & 0xffffffff)) | 298 | !mt76_rr(dev, 0x0a34)) { |
299 | ok++; | 299 | if (ok++ > 5) |
300 | if (ok > 6) | 300 | break; |
301 | break; | 301 | continue; |
302 | 302 | } | |
303 | msleep(1); | 303 | msleep(1); |
304 | } | 304 | } |
305 | 305 | ||
diff --git a/drivers/net/wireless/mediatek/mt7601u/regs.h b/drivers/net/wireless/mediatek/mt7601u/regs.h index 27a429d90cec..2a8837002f00 100644 --- a/drivers/net/wireless/mediatek/mt7601u/regs.h +++ b/drivers/net/wireless/mediatek/mt7601u/regs.h | |||
@@ -192,6 +192,9 @@ | |||
192 | #define MT_BCN_OFFSET_BASE 0x041c | 192 | #define MT_BCN_OFFSET_BASE 0x041c |
193 | #define MT_BCN_OFFSET(_n) (MT_BCN_OFFSET_BASE + ((_n) << 2)) | 193 | #define MT_BCN_OFFSET(_n) (MT_BCN_OFFSET_BASE + ((_n) << 2)) |
194 | 194 | ||
195 | #define MT_RXQ_STA 0x0430 | ||
196 | #define MT_TXQ_STA 0x0434 | ||
197 | |||
195 | #define MT_RF_CSR_CFG 0x0500 | 198 | #define MT_RF_CSR_CFG 0x0500 |
196 | #define MT_RF_CSR_CFG_DATA GENMASK(7, 0) | 199 | #define MT_RF_CSR_CFG_DATA GENMASK(7, 0) |
197 | #define MT_RF_CSR_CFG_REG_ID GENMASK(13, 8) | 200 | #define MT_RF_CSR_CFG_REG_ID GENMASK(13, 8) |
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 08d587a342d3..df551b2b56eb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | |||
@@ -1337,10 +1337,11 @@ struct rtl8xxxu_fileops { | |||
1337 | u32 ramask, int sgi); | 1337 | u32 ramask, int sgi); |
1338 | void (*report_connect) (struct rtl8xxxu_priv *priv, | 1338 | void (*report_connect) (struct rtl8xxxu_priv *priv, |
1339 | u8 macid, bool connect); | 1339 | u8 macid, bool connect); |
1340 | void (*fill_txdesc) (struct ieee80211_hdr *hdr, | 1340 | void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
1341 | struct rtl8xxxu_txdesc32 *tx_desc, u32 rate, | 1341 | struct ieee80211_tx_info *tx_info, |
1342 | u16 rate_flag, bool sgi, bool short_preamble, | 1342 | struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, |
1343 | bool ampdu_enable); | 1343 | bool short_preamble, bool ampdu_enable, |
1344 | u32 rts_rate); | ||
1344 | int writeN_block_size; | 1345 | int writeN_block_size; |
1345 | int rx_agg_buf_size; | 1346 | int rx_agg_buf_size; |
1346 | char tx_desc_size; | 1347 | char tx_desc_size; |
@@ -1434,14 +1435,16 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb); | |||
1434 | int rtl8xxxu_gen2_channel_to_group(int channel); | 1435 | int rtl8xxxu_gen2_channel_to_group(int channel); |
1435 | bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, | 1436 | bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, |
1436 | int result[][8], int c1, int c2); | 1437 | int result[][8], int c1, int c2); |
1437 | void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr, | 1438 | void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
1438 | struct rtl8xxxu_txdesc32 *tx_desc, u32 rate, | 1439 | struct ieee80211_tx_info *tx_info, |
1439 | u16 rate_flag, bool sgi, bool short_preamble, | 1440 | struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, |
1440 | bool ampdu_enable); | 1441 | bool short_preamble, bool ampdu_enable, |
1441 | void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr, | 1442 | u32 rts_rate); |
1442 | struct rtl8xxxu_txdesc32 *tx_desc32, u32 rate, | 1443 | void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
1443 | u16 rate_flag, bool sgi, bool short_preamble, | 1444 | struct ieee80211_tx_info *tx_info, |
1444 | bool ampdu_enable); | 1445 | struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi, |
1446 | bool short_preamble, bool ampdu_enable, | ||
1447 | u32 rts_rate); | ||
1445 | 1448 | ||
1446 | extern struct rtl8xxxu_fileops rtl8192cu_fops; | 1449 | extern struct rtl8xxxu_fileops rtl8192cu_fops; |
1447 | extern struct rtl8xxxu_fileops rtl8192eu_fops; | 1450 | extern struct rtl8xxxu_fileops rtl8192eu_fops; |
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index a793fedc3654..a1178c5d6ad8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | |||
@@ -1556,7 +1556,7 @@ exit: | |||
1556 | return ret; | 1556 | return ret; |
1557 | } | 1557 | } |
1558 | 1558 | ||
1559 | void rtl8192eu_power_off(struct rtl8xxxu_priv *priv) | 1559 | static void rtl8192eu_power_off(struct rtl8xxxu_priv *priv) |
1560 | { | 1560 | { |
1561 | u8 val8; | 1561 | u8 val8; |
1562 | u16 val16; | 1562 | u16 val16; |
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index a5e6ec2152bf..3a86675020a2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | |||
@@ -4372,6 +4372,13 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, | |||
4372 | void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, | 4372 | void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, |
4373 | u8 macid, bool connect) | 4373 | u8 macid, bool connect) |
4374 | { | 4374 | { |
4375 | #ifdef RTL8XXXU_GEN2_REPORT_CONNECT | ||
4376 | /* | ||
4377 | * Barry Day reports this causes issues with 8192eu and 8723bu | ||
4378 | * devices reconnecting. The reason for this is unclear, but | ||
4379 | * until it is better understood, leave the code in place but | ||
4380 | * disabled, so it is not lost. | ||
4381 | */ | ||
4375 | struct h2c_cmd h2c; | 4382 | struct h2c_cmd h2c; |
4376 | 4383 | ||
4377 | memset(&h2c, 0, sizeof(struct h2c_cmd)); | 4384 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
@@ -4383,6 +4390,7 @@ void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, | |||
4383 | h2c.media_status_rpt.parm &= ~BIT(0); | 4390 | h2c.media_status_rpt.parm &= ~BIT(0); |
4384 | 4391 | ||
4385 | rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt)); | 4392 | rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt)); |
4393 | #endif | ||
4386 | } | 4394 | } |
4387 | 4395 | ||
4388 | void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv) | 4396 | void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv) |
@@ -4759,13 +4767,28 @@ static void rtl8xxxu_dump_action(struct device *dev, | |||
4759 | * This format is used on 8188cu/8192cu/8723au | 4767 | * This format is used on 8188cu/8192cu/8723au |
4760 | */ | 4768 | */ |
4761 | void | 4769 | void |
4762 | rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr, | 4770 | rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
4763 | struct rtl8xxxu_txdesc32 *tx_desc, u32 rate, | 4771 | struct ieee80211_tx_info *tx_info, |
4764 | u16 rate_flag, bool sgi, bool short_preamble, | 4772 | struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, |
4765 | bool ampdu_enable) | 4773 | bool short_preamble, bool ampdu_enable, u32 rts_rate) |
4766 | { | 4774 | { |
4775 | struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); | ||
4776 | struct rtl8xxxu_priv *priv = hw->priv; | ||
4777 | struct device *dev = &priv->udev->dev; | ||
4778 | u32 rate; | ||
4779 | u16 rate_flags = tx_info->control.rates[0].flags; | ||
4767 | u16 seq_number; | 4780 | u16 seq_number; |
4768 | 4781 | ||
4782 | if (rate_flags & IEEE80211_TX_RC_MCS && | ||
4783 | !ieee80211_is_mgmt(hdr->frame_control)) | ||
4784 | rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; | ||
4785 | else | ||
4786 | rate = tx_rate->hw_value; | ||
4787 | |||
4788 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) | ||
4789 | dev_info(dev, "%s: TX rate: %d, pkt size %d\n", | ||
4790 | __func__, rate, cpu_to_le16(tx_desc->pkt_size)); | ||
4791 | |||
4769 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | 4792 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
4770 | 4793 | ||
4771 | tx_desc->txdw5 = cpu_to_le32(rate); | 4794 | tx_desc->txdw5 = cpu_to_le32(rate); |
@@ -4796,15 +4819,16 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr, | |||
4796 | if (sgi) | 4819 | if (sgi) |
4797 | tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI); | 4820 | tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI); |
4798 | 4821 | ||
4799 | if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { | 4822 | /* |
4800 | /* | 4823 | * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled |
4801 | * Use RTS rate 24M - does the mac80211 tell | 4824 | */ |
4802 | * us which to use? | 4825 | tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT); |
4803 | */ | 4826 | if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
4804 | tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M << | ||
4805 | TXDESC32_RTS_RATE_SHIFT); | ||
4806 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); | 4827 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); |
4807 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); | 4828 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); |
4829 | } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
4830 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE); | ||
4831 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); | ||
4808 | } | 4832 | } |
4809 | } | 4833 | } |
4810 | 4834 | ||
@@ -4813,16 +4837,31 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr, | |||
4813 | * This format is used on 8192eu/8723bu | 4837 | * This format is used on 8192eu/8723bu |
4814 | */ | 4838 | */ |
4815 | void | 4839 | void |
4816 | rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr, | 4840 | rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
4817 | struct rtl8xxxu_txdesc32 *tx_desc32, u32 rate, | 4841 | struct ieee80211_tx_info *tx_info, |
4818 | u16 rate_flag, bool sgi, bool short_preamble, | 4842 | struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi, |
4819 | bool ampdu_enable) | 4843 | bool short_preamble, bool ampdu_enable, u32 rts_rate) |
4820 | { | 4844 | { |
4845 | struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); | ||
4846 | struct rtl8xxxu_priv *priv = hw->priv; | ||
4847 | struct device *dev = &priv->udev->dev; | ||
4821 | struct rtl8xxxu_txdesc40 *tx_desc40; | 4848 | struct rtl8xxxu_txdesc40 *tx_desc40; |
4849 | u32 rate; | ||
4850 | u16 rate_flags = tx_info->control.rates[0].flags; | ||
4822 | u16 seq_number; | 4851 | u16 seq_number; |
4823 | 4852 | ||
4824 | tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32; | 4853 | tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32; |
4825 | 4854 | ||
4855 | if (rate_flags & IEEE80211_TX_RC_MCS && | ||
4856 | !ieee80211_is_mgmt(hdr->frame_control)) | ||
4857 | rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; | ||
4858 | else | ||
4859 | rate = tx_rate->hw_value; | ||
4860 | |||
4861 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) | ||
4862 | dev_info(dev, "%s: TX rate: %d, pkt size %d\n", | ||
4863 | __func__, rate, cpu_to_le16(tx_desc40->pkt_size)); | ||
4864 | |||
4826 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | 4865 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
4827 | 4866 | ||
4828 | tx_desc40->txdw4 = cpu_to_le32(rate); | 4867 | tx_desc40->txdw4 = cpu_to_le32(rate); |
@@ -4849,15 +4888,19 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr, | |||
4849 | if (short_preamble) | 4888 | if (short_preamble) |
4850 | tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE); | 4889 | tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE); |
4851 | 4890 | ||
4852 | if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { | 4891 | tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT); |
4853 | /* | 4892 | /* |
4854 | * Use RTS rate 24M - does the mac80211 tell | 4893 | * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled |
4855 | * us which to use? | 4894 | */ |
4856 | */ | 4895 | if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
4857 | tx_desc40->txdw4 |= cpu_to_le32(DESC_RATE_24M << | ||
4858 | TXDESC40_RTS_RATE_SHIFT); | ||
4859 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE); | 4896 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE); |
4860 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE); | 4897 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE); |
4898 | } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
4899 | /* | ||
4900 | * For some reason the vendor driver doesn't set | ||
4901 | * TXDESC40_HW_RTS_ENABLE for CTS to SELF | ||
4902 | */ | ||
4903 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_CTS_SELF_ENABLE); | ||
4861 | } | 4904 | } |
4862 | } | 4905 | } |
4863 | 4906 | ||
@@ -4867,14 +4910,13 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, | |||
4867 | { | 4910 | { |
4868 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 4911 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
4869 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 4912 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
4870 | struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); | ||
4871 | struct rtl8xxxu_priv *priv = hw->priv; | 4913 | struct rtl8xxxu_priv *priv = hw->priv; |
4872 | struct rtl8xxxu_txdesc32 *tx_desc; | 4914 | struct rtl8xxxu_txdesc32 *tx_desc; |
4873 | struct rtl8xxxu_tx_urb *tx_urb; | 4915 | struct rtl8xxxu_tx_urb *tx_urb; |
4874 | struct ieee80211_sta *sta = NULL; | 4916 | struct ieee80211_sta *sta = NULL; |
4875 | struct ieee80211_vif *vif = tx_info->control.vif; | 4917 | struct ieee80211_vif *vif = tx_info->control.vif; |
4876 | struct device *dev = &priv->udev->dev; | 4918 | struct device *dev = &priv->udev->dev; |
4877 | u32 queue, rate; | 4919 | u32 queue, rts_rate; |
4878 | u16 pktlen = skb->len; | 4920 | u16 pktlen = skb->len; |
4879 | u16 seq_number; | 4921 | u16 seq_number; |
4880 | u16 rate_flag = tx_info->control.rates[0].flags; | 4922 | u16 rate_flag = tx_info->control.rates[0].flags; |
@@ -4901,10 +4943,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, | |||
4901 | goto error; | 4943 | goto error; |
4902 | } | 4944 | } |
4903 | 4945 | ||
4904 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) | ||
4905 | dev_info(dev, "%s: TX rate: %d (%d), pkt size %d\n", | ||
4906 | __func__, tx_rate->bitrate, tx_rate->hw_value, pktlen); | ||
4907 | |||
4908 | if (ieee80211_is_action(hdr->frame_control)) | 4946 | if (ieee80211_is_action(hdr->frame_control)) |
4909 | rtl8xxxu_dump_action(dev, hdr); | 4947 | rtl8xxxu_dump_action(dev, hdr); |
4910 | 4948 | ||
@@ -4958,12 +4996,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, | |||
4958 | } | 4996 | } |
4959 | } | 4997 | } |
4960 | 4998 | ||
4961 | if (rate_flag & IEEE80211_TX_RC_MCS && | ||
4962 | !ieee80211_is_mgmt(hdr->frame_control)) | ||
4963 | rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; | ||
4964 | else | ||
4965 | rate = tx_rate->hw_value; | ||
4966 | |||
4967 | if (rate_flag & IEEE80211_TX_RC_SHORT_GI || | 4999 | if (rate_flag & IEEE80211_TX_RC_SHORT_GI || |
4968 | (ieee80211_is_data_qos(hdr->frame_control) && | 5000 | (ieee80211_is_data_qos(hdr->frame_control) && |
4969 | sta && sta->ht_cap.cap & | 5001 | sta && sta->ht_cap.cap & |
@@ -4974,10 +5006,17 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, | |||
4974 | (sta && vif && vif->bss_conf.use_short_preamble)) | 5006 | (sta && vif && vif->bss_conf.use_short_preamble)) |
4975 | short_preamble = true; | 5007 | short_preamble = true; |
4976 | 5008 | ||
5009 | if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) | ||
5010 | rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value; | ||
5011 | else if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) | ||
5012 | rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value; | ||
5013 | else | ||
5014 | rts_rate = 0; | ||
5015 | |||
4977 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | 5016 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
4978 | 5017 | ||
4979 | priv->fops->fill_txdesc(hdr, tx_desc, rate, rate_flag, | 5018 | priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble, |
4980 | sgi, short_preamble, ampdu_enable); | 5019 | ampdu_enable, rts_rate); |
4981 | 5020 | ||
4982 | rtl8xxxu_calc_tx_desc_csum(tx_desc); | 5021 | rtl8xxxu_calc_tx_desc_csum(tx_desc); |
4983 | 5022 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 264466f59c57..4ac928bf1f8e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c | |||
@@ -1303,12 +1303,13 @@ EXPORT_SYMBOL_GPL(rtl_action_proc); | |||
1303 | 1303 | ||
1304 | static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc) | 1304 | static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc) |
1305 | { | 1305 | { |
1306 | struct ieee80211_hw *hw = rtlpriv->hw; | ||
1307 | |||
1306 | rtlpriv->ra.is_special_data = true; | 1308 | rtlpriv->ra.is_special_data = true; |
1307 | if (rtlpriv->cfg->ops->get_btc_status()) | 1309 | if (rtlpriv->cfg->ops->get_btc_status()) |
1308 | rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( | 1310 | rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( |
1309 | rtlpriv, 1); | 1311 | rtlpriv, 1); |
1310 | rtlpriv->enter_ps = false; | 1312 | rtl_lps_leave(hw); |
1311 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1312 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1313 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1313 | } | 1314 | } |
1314 | 1315 | ||
@@ -1381,8 +1382,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, | |||
1381 | 1382 | ||
1382 | if (is_tx) { | 1383 | if (is_tx) { |
1383 | rtlpriv->ra.is_special_data = true; | 1384 | rtlpriv->ra.is_special_data = true; |
1384 | rtlpriv->enter_ps = false; | 1385 | rtl_lps_leave(hw); |
1385 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1386 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1386 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1387 | } | 1387 | } |
1388 | 1388 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index e89681d2f83a..2caa4ad04dba 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c | |||
@@ -1150,10 +1150,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1150 | } else { | 1150 | } else { |
1151 | mstatus = RT_MEDIA_DISCONNECT; | 1151 | mstatus = RT_MEDIA_DISCONNECT; |
1152 | 1152 | ||
1153 | if (mac->link_state == MAC80211_LINKED) { | 1153 | if (mac->link_state == MAC80211_LINKED) |
1154 | rtlpriv->enter_ps = false; | 1154 | rtl_lps_leave(hw); |
1155 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1156 | } | ||
1157 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) | 1155 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) |
1158 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | 1156 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); |
1159 | mac->link_state = MAC80211_NOLINK; | 1157 | mac->link_state = MAC80211_NOLINK; |
@@ -1431,8 +1429,7 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, | |||
1431 | } | 1429 | } |
1432 | 1430 | ||
1433 | if (mac->link_state == MAC80211_LINKED) { | 1431 | if (mac->link_state == MAC80211_LINKED) { |
1434 | rtlpriv->enter_ps = false; | 1432 | rtl_lps_leave(hw); |
1435 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1436 | mac->link_state = MAC80211_LINKED_SCANNING; | 1433 | mac->link_state = MAC80211_LINKED_SCANNING; |
1437 | } else { | 1434 | } else { |
1438 | rtl_ips_nic_on(hw); | 1435 | rtl_ips_nic_on(hw); |
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index d044b23a0d33..8bfe020edd3a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c | |||
@@ -659,11 +659,9 @@ tx_status_ok: | |||
659 | } | 659 | } |
660 | 660 | ||
661 | if (((rtlpriv->link_info.num_rx_inperiod + | 661 | if (((rtlpriv->link_info.num_rx_inperiod + |
662 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 662 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
663 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 663 | (rtlpriv->link_info.num_rx_inperiod > 2)) |
664 | rtlpriv->enter_ps = false; | 664 | rtl_lps_leave(hw); |
665 | schedule_work(&rtlpriv->works.lps_change_work); | ||
666 | } | ||
667 | } | 665 | } |
668 | 666 | ||
669 | static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw, | 667 | static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw, |
@@ -914,10 +912,8 @@ new_trx_end: | |||
914 | } | 912 | } |
915 | if (((rtlpriv->link_info.num_rx_inperiod + | 913 | if (((rtlpriv->link_info.num_rx_inperiod + |
916 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 914 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
917 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 915 | (rtlpriv->link_info.num_rx_inperiod > 2)) |
918 | rtlpriv->enter_ps = false; | 916 | rtl_lps_leave(hw); |
919 | schedule_work(&rtlpriv->works.lps_change_work); | ||
920 | } | ||
921 | skb = new_skb; | 917 | skb = new_skb; |
922 | no_new: | 918 | no_new: |
923 | if (rtlpriv->use_new_trx_flow) { | 919 | if (rtlpriv->use_new_trx_flow) { |
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index 18d979affc18..d0ffc4d508cf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c | |||
@@ -407,8 +407,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
407 | } | 407 | } |
408 | } | 408 | } |
409 | 409 | ||
410 | /*Enter the leisure power save mode.*/ | 410 | /* Interrupt safe routine to enter the leisure power save mode.*/ |
411 | void rtl_lps_enter(struct ieee80211_hw *hw) | 411 | static void rtl_lps_enter_core(struct ieee80211_hw *hw) |
412 | { | 412 | { |
413 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 413 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
414 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 414 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
@@ -444,10 +444,9 @@ void rtl_lps_enter(struct ieee80211_hw *hw) | |||
444 | 444 | ||
445 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); | 445 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); |
446 | } | 446 | } |
447 | EXPORT_SYMBOL(rtl_lps_enter); | ||
448 | 447 | ||
449 | /*Leave the leisure power save mode.*/ | 448 | /* Interrupt safe routine to leave the leisure power save mode.*/ |
450 | void rtl_lps_leave(struct ieee80211_hw *hw) | 449 | static void rtl_lps_leave_core(struct ieee80211_hw *hw) |
451 | { | 450 | { |
452 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 451 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
453 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 452 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
@@ -477,7 +476,6 @@ void rtl_lps_leave(struct ieee80211_hw *hw) | |||
477 | } | 476 | } |
478 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); | 477 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); |
479 | } | 478 | } |
480 | EXPORT_SYMBOL(rtl_lps_leave); | ||
481 | 479 | ||
482 | /* For sw LPS*/ | 480 | /* For sw LPS*/ |
483 | void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) | 481 | void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) |
@@ -670,12 +668,34 @@ void rtl_lps_change_work_callback(struct work_struct *work) | |||
670 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 668 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
671 | 669 | ||
672 | if (rtlpriv->enter_ps) | 670 | if (rtlpriv->enter_ps) |
673 | rtl_lps_enter(hw); | 671 | rtl_lps_enter_core(hw); |
674 | else | 672 | else |
675 | rtl_lps_leave(hw); | 673 | rtl_lps_leave_core(hw); |
676 | } | 674 | } |
677 | EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback); | 675 | EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback); |
678 | 676 | ||
677 | void rtl_lps_enter(struct ieee80211_hw *hw) | ||
678 | { | ||
679 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
680 | |||
681 | if (!in_interrupt()) | ||
682 | return rtl_lps_enter_core(hw); | ||
683 | rtlpriv->enter_ps = true; | ||
684 | schedule_work(&rtlpriv->works.lps_change_work); | ||
685 | } | ||
686 | EXPORT_SYMBOL_GPL(rtl_lps_enter); | ||
687 | |||
688 | void rtl_lps_leave(struct ieee80211_hw *hw) | ||
689 | { | ||
690 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
691 | |||
692 | if (!in_interrupt()) | ||
693 | return rtl_lps_leave_core(hw); | ||
694 | rtlpriv->enter_ps = false; | ||
695 | schedule_work(&rtlpriv->works.lps_change_work); | ||
696 | } | ||
697 | EXPORT_SYMBOL_GPL(rtl_lps_leave); | ||
698 | |||
679 | void rtl_swlps_wq_callback(void *data) | 699 | void rtl_swlps_wq_callback(void *data) |
680 | { | 700 | { |
681 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, | 701 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, |
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index aaca25870bc1..dadaa73ab49d 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c | |||
@@ -275,6 +275,8 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw) | |||
275 | common->iface_down = false; | 275 | common->iface_down = false; |
276 | mutex_unlock(&common->mutex); | 276 | mutex_unlock(&common->mutex); |
277 | 277 | ||
278 | rsi_send_rx_filter_frame(common, 0); | ||
279 | |||
278 | return 0; | 280 | return 0; |
279 | } | 281 | } |
280 | 282 | ||
@@ -388,7 +390,7 @@ static int rsi_channel_change(struct ieee80211_hw *hw) | |||
388 | 390 | ||
389 | status = rsi_band_check(common); | 391 | status = rsi_band_check(common); |
390 | if (!status) | 392 | if (!status) |
391 | status = rsi_set_channel(adapter->priv, channel); | 393 | status = rsi_set_channel(adapter->priv, curchan); |
392 | 394 | ||
393 | if (bss->assoc) { | 395 | if (bss->assoc) { |
394 | if (common->hw_data_qs_blocked && | 396 | if (common->hw_data_qs_blocked && |
@@ -409,6 +411,34 @@ static int rsi_channel_change(struct ieee80211_hw *hw) | |||
409 | } | 411 | } |
410 | 412 | ||
411 | /** | 413 | /** |
414 | * rsi_config_power() - This function configures tx power to device | ||
415 | * @hw: Pointer to the ieee80211_hw structure. | ||
416 | * | ||
417 | * Return: 0 on success, negative error code on failure. | ||
418 | */ | ||
419 | static int rsi_config_power(struct ieee80211_hw *hw) | ||
420 | { | ||
421 | struct rsi_hw *adapter = hw->priv; | ||
422 | struct rsi_common *common = adapter->priv; | ||
423 | struct ieee80211_conf *conf = &hw->conf; | ||
424 | |||
425 | if (adapter->sc_nvifs <= 0) { | ||
426 | rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__); | ||
427 | return -EINVAL; | ||
428 | } | ||
429 | |||
430 | rsi_dbg(INFO_ZONE, | ||
431 | "%s: Set tx power: %d dBM\n", __func__, conf->power_level); | ||
432 | |||
433 | if (conf->power_level == common->tx_power) | ||
434 | return 0; | ||
435 | |||
436 | common->tx_power = conf->power_level; | ||
437 | |||
438 | return rsi_send_radio_params_update(common); | ||
439 | } | ||
440 | |||
441 | /** | ||
412 | * rsi_mac80211_config() - This function is a handler for configuration | 442 | * rsi_mac80211_config() - This function is a handler for configuration |
413 | * requests. The stack calls this function to | 443 | * requests. The stack calls this function to |
414 | * change hardware configuration, e.g., channel. | 444 | * change hardware configuration, e.g., channel. |
@@ -429,6 +459,12 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw, | |||
429 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) | 459 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) |
430 | status = rsi_channel_change(hw); | 460 | status = rsi_channel_change(hw); |
431 | 461 | ||
462 | /* tx power */ | ||
463 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
464 | rsi_dbg(INFO_ZONE, "%s: Configuring Power\n", __func__); | ||
465 | status = rsi_config_power(hw); | ||
466 | } | ||
467 | |||
432 | mutex_unlock(&common->mutex); | 468 | mutex_unlock(&common->mutex); |
433 | 469 | ||
434 | return status; | 470 | return status; |
@@ -471,11 +507,19 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw, | |||
471 | { | 507 | { |
472 | struct rsi_hw *adapter = hw->priv; | 508 | struct rsi_hw *adapter = hw->priv; |
473 | struct rsi_common *common = adapter->priv; | 509 | struct rsi_common *common = adapter->priv; |
510 | u16 rx_filter_word = 0; | ||
474 | 511 | ||
475 | mutex_lock(&common->mutex); | 512 | mutex_lock(&common->mutex); |
476 | if (changed & BSS_CHANGED_ASSOC) { | 513 | if (changed & BSS_CHANGED_ASSOC) { |
477 | rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n", | 514 | rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n", |
478 | __func__, bss_conf->assoc); | 515 | __func__, bss_conf->assoc); |
516 | if (bss_conf->assoc) { | ||
517 | /* Send the RX filter frame */ | ||
518 | rx_filter_word = (ALLOW_DATA_ASSOC_PEER | | ||
519 | ALLOW_CTRL_ASSOC_PEER | | ||
520 | ALLOW_MGMT_ASSOC_PEER); | ||
521 | rsi_send_rx_filter_frame(common, rx_filter_word); | ||
522 | } | ||
479 | rsi_inform_bss_status(common, | 523 | rsi_inform_bss_status(common, |
480 | bss_conf->assoc, | 524 | bss_conf->assoc, |
481 | bss_conf->bssid, | 525 | bss_conf->bssid, |
@@ -1013,6 +1057,7 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw, | |||
1013 | struct rsi_common *common = adapter->priv; | 1057 | struct rsi_common *common = adapter->priv; |
1014 | 1058 | ||
1015 | mutex_lock(&common->mutex); | 1059 | mutex_lock(&common->mutex); |
1060 | |||
1016 | /* Resetting all the fields to default values */ | 1061 | /* Resetting all the fields to default values */ |
1017 | common->bitrate_mask[NL80211_BAND_2GHZ] = 0; | 1062 | common->bitrate_mask[NL80211_BAND_2GHZ] = 0; |
1018 | common->bitrate_mask[NL80211_BAND_5GHZ] = 0; | 1063 | common->bitrate_mask[NL80211_BAND_5GHZ] = 0; |
@@ -1022,9 +1067,114 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw, | |||
1022 | common->vif_info[0].seq_start = 0; | 1067 | common->vif_info[0].seq_start = 0; |
1023 | common->secinfo.ptk_cipher = 0; | 1068 | common->secinfo.ptk_cipher = 0; |
1024 | common->secinfo.gtk_cipher = 0; | 1069 | common->secinfo.gtk_cipher = 0; |
1070 | |||
1071 | rsi_send_rx_filter_frame(common, 0); | ||
1072 | |||
1025 | mutex_unlock(&common->mutex); | 1073 | mutex_unlock(&common->mutex); |
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | /** | ||
1079 | * rsi_mac80211_set_antenna() - This function is used to configure | ||
1080 | * tx and rx antennas. | ||
1081 | * @hw: Pointer to the ieee80211_hw structure. | ||
1082 | * @tx_ant: Bitmap for tx antenna | ||
1083 | * @rx_ant: Bitmap for rx antenna | ||
1084 | * | ||
1085 | * Return: 0 on success, Negative error code on failure. | ||
1086 | */ | ||
1087 | static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw, | ||
1088 | u32 tx_ant, u32 rx_ant) | ||
1089 | { | ||
1090 | struct rsi_hw *adapter = hw->priv; | ||
1091 | struct rsi_common *common = adapter->priv; | ||
1092 | u8 antenna = 0; | ||
1026 | 1093 | ||
1094 | if (tx_ant > 1 || rx_ant > 1) { | ||
1095 | rsi_dbg(ERR_ZONE, | ||
1096 | "Invalid antenna selection (tx: %d, rx:%d)\n", | ||
1097 | tx_ant, rx_ant); | ||
1098 | rsi_dbg(ERR_ZONE, | ||
1099 | "Use 0 for int_ant, 1 for ext_ant\n"); | ||
1100 | return -EINVAL; | ||
1101 | } | ||
1102 | |||
1103 | rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n", | ||
1104 | __func__, tx_ant, rx_ant); | ||
1105 | |||
1106 | mutex_lock(&common->mutex); | ||
1107 | |||
1108 | antenna = tx_ant ? ANTENNA_SEL_UFL : ANTENNA_SEL_INT; | ||
1109 | if (common->ant_in_use != antenna) | ||
1110 | if (rsi_set_antenna(common, antenna)) | ||
1111 | goto fail_set_antenna; | ||
1112 | |||
1113 | rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n", | ||
1114 | tx_ant ? "UFL" : "INT"); | ||
1115 | |||
1116 | common->ant_in_use = antenna; | ||
1117 | |||
1118 | mutex_unlock(&common->mutex); | ||
1119 | |||
1027 | return 0; | 1120 | return 0; |
1121 | |||
1122 | fail_set_antenna: | ||
1123 | rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__); | ||
1124 | mutex_unlock(&common->mutex); | ||
1125 | return -EINVAL; | ||
1126 | } | ||
1127 | |||
1128 | /** | ||
1129 | * rsi_mac80211_get_antenna() - This function is used to configure | ||
1130 | * tx and rx antennas. | ||
1131 | * | ||
1132 | * @hw: Pointer to the ieee80211_hw structure. | ||
1133 | * @tx_ant: Bitmap for tx antenna | ||
1134 | * @rx_ant: Bitmap for rx antenna | ||
1135 | * | ||
1136 | * Return: 0 on success, -1 on failure. | ||
1137 | */ | ||
1138 | static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw, | ||
1139 | u32 *tx_ant, u32 *rx_ant) | ||
1140 | { | ||
1141 | struct rsi_hw *adapter = hw->priv; | ||
1142 | struct rsi_common *common = adapter->priv; | ||
1143 | |||
1144 | mutex_lock(&common->mutex); | ||
1145 | |||
1146 | *tx_ant = (common->ant_in_use == ANTENNA_SEL_UFL) ? 1 : 0; | ||
1147 | *rx_ant = 0; | ||
1148 | |||
1149 | mutex_unlock(&common->mutex); | ||
1150 | |||
1151 | return 0; | ||
1152 | } | ||
1153 | |||
1154 | static void rsi_reg_notify(struct wiphy *wiphy, | ||
1155 | struct regulatory_request *request) | ||
1156 | { | ||
1157 | struct ieee80211_supported_band *sband; | ||
1158 | struct ieee80211_channel *ch; | ||
1159 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
1160 | struct rsi_hw * adapter = hw->priv; | ||
1161 | int i; | ||
1162 | |||
1163 | sband = wiphy->bands[NL80211_BAND_5GHZ]; | ||
1164 | |||
1165 | for (i = 0; i < sband->n_channels; i++) { | ||
1166 | ch = &sband->channels[i]; | ||
1167 | if (ch->flags & IEEE80211_CHAN_DISABLED) | ||
1168 | continue; | ||
1169 | |||
1170 | if (ch->flags & IEEE80211_CHAN_RADAR) | ||
1171 | ch->flags |= IEEE80211_CHAN_NO_IR; | ||
1172 | } | ||
1173 | |||
1174 | rsi_dbg(INFO_ZONE, | ||
1175 | "country = %s dfs_region = %d\n", | ||
1176 | request->alpha2, request->dfs_region); | ||
1177 | adapter->dfs_region = request->dfs_region; | ||
1028 | } | 1178 | } |
1029 | 1179 | ||
1030 | static struct ieee80211_ops mac80211_ops = { | 1180 | static struct ieee80211_ops mac80211_ops = { |
@@ -1043,6 +1193,8 @@ static struct ieee80211_ops mac80211_ops = { | |||
1043 | .ampdu_action = rsi_mac80211_ampdu_action, | 1193 | .ampdu_action = rsi_mac80211_ampdu_action, |
1044 | .sta_add = rsi_mac80211_sta_add, | 1194 | .sta_add = rsi_mac80211_sta_add, |
1045 | .sta_remove = rsi_mac80211_sta_remove, | 1195 | .sta_remove = rsi_mac80211_sta_remove, |
1196 | .set_antenna = rsi_mac80211_set_antenna, | ||
1197 | .get_antenna = rsi_mac80211_get_antenna, | ||
1046 | }; | 1198 | }; |
1047 | 1199 | ||
1048 | /** | 1200 | /** |
@@ -1107,6 +1259,8 @@ int rsi_mac80211_attach(struct rsi_common *common) | |||
1107 | wiphy->bands[NL80211_BAND_5GHZ] = | 1259 | wiphy->bands[NL80211_BAND_5GHZ] = |
1108 | &adapter->sbands[NL80211_BAND_5GHZ]; | 1260 | &adapter->sbands[NL80211_BAND_5GHZ]; |
1109 | 1261 | ||
1262 | wiphy->reg_notifier = rsi_reg_notify; | ||
1263 | |||
1110 | status = ieee80211_register_hw(hw); | 1264 | status = ieee80211_register_hw(hw); |
1111 | if (status) | 1265 | if (status) |
1112 | return status; | 1266 | return status; |
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 30b9d44ff8f8..fac87c06357b 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c | |||
@@ -913,7 +913,8 @@ int rsi_band_check(struct rsi_common *common) | |||
913 | * | 913 | * |
914 | * Return: 0 on success, corresponding error code on failure. | 914 | * Return: 0 on success, corresponding error code on failure. |
915 | */ | 915 | */ |
916 | int rsi_set_channel(struct rsi_common *common, u16 channel) | 916 | int rsi_set_channel(struct rsi_common *common, |
917 | struct ieee80211_channel *channel) | ||
917 | { | 918 | { |
918 | struct sk_buff *skb = NULL; | 919 | struct sk_buff *skb = NULL; |
919 | struct rsi_mac_frame *mgmt_frame; | 920 | struct rsi_mac_frame *mgmt_frame; |
@@ -928,24 +929,76 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) | |||
928 | return -ENOMEM; | 929 | return -ENOMEM; |
929 | } | 930 | } |
930 | 931 | ||
932 | if (!channel) { | ||
933 | dev_kfree_skb(skb); | ||
934 | return 0; | ||
935 | } | ||
931 | memset(skb->data, 0, FRAME_DESC_SZ); | 936 | memset(skb->data, 0, FRAME_DESC_SZ); |
932 | mgmt_frame = (struct rsi_mac_frame *)skb->data; | 937 | mgmt_frame = (struct rsi_mac_frame *)skb->data; |
933 | 938 | ||
934 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | 939 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); |
935 | mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); | 940 | mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); |
936 | mgmt_frame->desc_word[4] = cpu_to_le16(channel); | 941 | mgmt_frame->desc_word[4] = cpu_to_le16(channel->hw_value); |
942 | |||
943 | mgmt_frame->desc_word[4] |= | ||
944 | cpu_to_le16(((char)(channel->max_antenna_gain)) << 8); | ||
945 | mgmt_frame->desc_word[5] = | ||
946 | cpu_to_le16((char)(channel->max_antenna_gain)); | ||
937 | 947 | ||
938 | mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET | | 948 | mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET | |
939 | BBP_REG_WRITE | | 949 | BBP_REG_WRITE | |
940 | (RSI_RF_TYPE << 4)); | 950 | (RSI_RF_TYPE << 4)); |
941 | 951 | ||
942 | mgmt_frame->desc_word[5] = cpu_to_le16(0x01); | 952 | if (!(channel->flags & IEEE80211_CHAN_NO_IR) && |
943 | mgmt_frame->desc_word[6] = cpu_to_le16(0x12); | 953 | !(channel->flags & IEEE80211_CHAN_RADAR)) { |
954 | if (common->tx_power < channel->max_power) | ||
955 | mgmt_frame->desc_word[6] = cpu_to_le16(common->tx_power); | ||
956 | else | ||
957 | mgmt_frame->desc_word[6] = cpu_to_le16(channel->max_power); | ||
958 | } | ||
959 | mgmt_frame->desc_word[7] = cpu_to_le16(common->priv->dfs_region); | ||
944 | 960 | ||
945 | if (common->channel_width == BW_40MHZ) | 961 | if (common->channel_width == BW_40MHZ) |
946 | mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8); | 962 | mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8); |
947 | 963 | ||
948 | common->channel = channel; | 964 | common->channel = channel->hw_value; |
965 | |||
966 | skb_put(skb, FRAME_DESC_SZ); | ||
967 | |||
968 | return rsi_send_internal_mgmt_frame(common, skb); | ||
969 | } | ||
970 | |||
971 | /** | ||
972 | * rsi_send_radio_params_update() - This function sends the radio | ||
973 | * parameters update to device | ||
974 | * @common: Pointer to the driver private structure. | ||
975 | * @channel: Channel value to be set. | ||
976 | * | ||
977 | * Return: 0 on success, corresponding error code on failure. | ||
978 | */ | ||
979 | int rsi_send_radio_params_update(struct rsi_common *common) | ||
980 | { | ||
981 | struct rsi_mac_frame *cmd_frame; | ||
982 | struct sk_buff *skb = NULL; | ||
983 | |||
984 | rsi_dbg(MGMT_TX_ZONE, | ||
985 | "%s: Sending Radio Params update frame\n", __func__); | ||
986 | |||
987 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
988 | if (!skb) { | ||
989 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
990 | __func__); | ||
991 | return -ENOMEM; | ||
992 | } | ||
993 | |||
994 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
995 | cmd_frame = (struct rsi_mac_frame *)skb->data; | ||
996 | |||
997 | cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
998 | cmd_frame->desc_word[1] = cpu_to_le16(RADIO_PARAMS_UPDATE); | ||
999 | cmd_frame->desc_word[3] = cpu_to_le16(BIT(0)); | ||
1000 | |||
1001 | cmd_frame->desc_word[3] |= cpu_to_le16(common->tx_power << 8); | ||
949 | 1002 | ||
950 | skb_put(skb, FRAME_DESC_SZ); | 1003 | skb_put(skb, FRAME_DESC_SZ); |
951 | 1004 | ||
@@ -1243,6 +1296,72 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event) | |||
1243 | 1296 | ||
1244 | } | 1297 | } |
1245 | 1298 | ||
1299 | /** | ||
1300 | * rsi_send_rx_filter_frame() - Sends a frame to filter the RX packets | ||
1301 | * | ||
1302 | * @common: Pointer to the driver private structure. | ||
1303 | * @rx_filter_word: Flags of filter packets | ||
1304 | * | ||
1305 | * @Return: 0 on success, -1 on failure. | ||
1306 | */ | ||
1307 | int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word) | ||
1308 | { | ||
1309 | struct rsi_mac_frame *cmd_frame; | ||
1310 | struct sk_buff *skb; | ||
1311 | |||
1312 | rsi_dbg(MGMT_TX_ZONE, "Sending RX filter frame\n"); | ||
1313 | |||
1314 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
1315 | if (!skb) { | ||
1316 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
1317 | __func__); | ||
1318 | return -ENOMEM; | ||
1319 | } | ||
1320 | |||
1321 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
1322 | cmd_frame = (struct rsi_mac_frame *)skb->data; | ||
1323 | |||
1324 | cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
1325 | cmd_frame->desc_word[1] = cpu_to_le16(SET_RX_FILTER); | ||
1326 | cmd_frame->desc_word[4] = cpu_to_le16(rx_filter_word); | ||
1327 | |||
1328 | skb_put(skb, FRAME_DESC_SZ); | ||
1329 | |||
1330 | return rsi_send_internal_mgmt_frame(common, skb); | ||
1331 | } | ||
1332 | |||
1333 | /** | ||
1334 | * rsi_set_antenna() - This fuction send antenna configuration request | ||
1335 | * to device | ||
1336 | * | ||
1337 | * @common: Pointer to the driver private structure. | ||
1338 | * @antenna: bitmap for tx antenna selection | ||
1339 | * | ||
1340 | * Return: 0 on Success, negative error code on failure | ||
1341 | */ | ||
1342 | int rsi_set_antenna(struct rsi_common *common, u8 antenna) | ||
1343 | { | ||
1344 | struct rsi_mac_frame *cmd_frame; | ||
1345 | struct sk_buff *skb; | ||
1346 | |||
1347 | skb = dev_alloc_skb(FRAME_DESC_SZ); | ||
1348 | if (!skb) { | ||
1349 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | ||
1350 | __func__); | ||
1351 | return -ENOMEM; | ||
1352 | } | ||
1353 | |||
1354 | memset(skb->data, 0, FRAME_DESC_SZ); | ||
1355 | cmd_frame = (struct rsi_mac_frame *)skb->data; | ||
1356 | |||
1357 | cmd_frame->desc_word[1] = cpu_to_le16(ANT_SEL_FRAME); | ||
1358 | cmd_frame->desc_word[3] = cpu_to_le16(antenna & 0x00ff); | ||
1359 | cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); | ||
1360 | |||
1361 | skb_put(skb, FRAME_DESC_SZ); | ||
1362 | |||
1363 | return rsi_send_internal_mgmt_frame(common, skb); | ||
1364 | } | ||
1246 | 1365 | ||
1247 | /** | 1366 | /** |
1248 | * rsi_handle_ta_confirm_type() - This function handles the confirm frames. | 1367 | * rsi_handle_ta_confirm_type() - This function handles the confirm frames. |
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index dcd095787166..1d5904bc2c74 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h | |||
@@ -204,6 +204,9 @@ struct rsi_common { | |||
204 | struct cqm_info cqm_info; | 204 | struct cqm_info cqm_info; |
205 | 205 | ||
206 | bool hw_data_qs_blocked; | 206 | bool hw_data_qs_blocked; |
207 | |||
208 | int tx_power; | ||
209 | u8 ant_in_use; | ||
207 | }; | 210 | }; |
208 | 211 | ||
209 | struct rsi_hw { | 212 | struct rsi_hw { |
@@ -220,6 +223,7 @@ struct rsi_hw { | |||
220 | struct rsi_debugfs *dfsentry; | 223 | struct rsi_debugfs *dfsentry; |
221 | u8 num_debugfs_entries; | 224 | u8 num_debugfs_entries; |
222 | #endif | 225 | #endif |
226 | u8 dfs_region; | ||
223 | void *rsi_dev; | 227 | void *rsi_dev; |
224 | int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len); | 228 | int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len); |
225 | int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len); | 229 | int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len); |
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h index d1553581e471..dfbf7a50269b 100644 --- a/drivers/net/wireless/rsi/rsi_mgmt.h +++ b/drivers/net/wireless/rsi/rsi_mgmt.h | |||
@@ -140,6 +140,19 @@ | |||
140 | 140 | ||
141 | #define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\ | 141 | #define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\ |
142 | FIF_BCN_PRBRESP_PROMISC) | 142 | FIF_BCN_PRBRESP_PROMISC) |
143 | |||
144 | #define ANTENNA_SEL_INT 0x02 /* RF_OUT_2 / Integerated */ | ||
145 | #define ANTENNA_SEL_UFL 0x03 /* RF_OUT_1 / U.FL */ | ||
146 | |||
147 | /* Rx filter word definitions */ | ||
148 | #define PROMISCOUS_MODE BIT(0) | ||
149 | #define ALLOW_DATA_ASSOC_PEER BIT(1) | ||
150 | #define ALLOW_MGMT_ASSOC_PEER BIT(2) | ||
151 | #define ALLOW_CTRL_ASSOC_PEER BIT(3) | ||
152 | #define DISALLOW_BEACONS BIT(4) | ||
153 | #define ALLOW_CONN_PEER_MGMT_WHILE_BUF_FULL BIT(5) | ||
154 | #define DISALLOW_BROADCAST_DATA BIT(6) | ||
155 | |||
143 | enum opmode { | 156 | enum opmode { |
144 | STA_OPMODE = 1, | 157 | STA_OPMODE = 1, |
145 | AP_OPMODE = 2 | 158 | AP_OPMODE = 2 |
@@ -190,7 +203,9 @@ enum cmd_frame_type { | |||
190 | BG_SCAN_PARAMS, | 203 | BG_SCAN_PARAMS, |
191 | BG_SCAN_PROBE_REQ, | 204 | BG_SCAN_PROBE_REQ, |
192 | CW_MODE_REQ, | 205 | CW_MODE_REQ, |
193 | PER_CMD_PKT | 206 | PER_CMD_PKT, |
207 | ANT_SEL_FRAME = 0x20, | ||
208 | RADIO_PARAMS_UPDATE = 0x29 | ||
194 | }; | 209 | }; |
195 | 210 | ||
196 | struct rsi_mac_frame { | 211 | struct rsi_mac_frame { |
@@ -299,7 +314,8 @@ int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid, | |||
299 | u16 ssn, u8 buf_size, u8 event); | 314 | u16 ssn, u8 buf_size, u8 event); |
300 | int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len, | 315 | int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len, |
301 | u8 key_type, u8 key_id, u32 cipher); | 316 | u8 key_type, u8 key_id, u32 cipher); |
302 | int rsi_set_channel(struct rsi_common *common, u16 chno); | 317 | int rsi_set_channel(struct rsi_common *common, |
318 | struct ieee80211_channel *channel); | ||
303 | int rsi_send_block_unblock_frame(struct rsi_common *common, bool event); | 319 | int rsi_send_block_unblock_frame(struct rsi_common *common, bool event); |
304 | void rsi_inform_bss_status(struct rsi_common *common, u8 status, | 320 | void rsi_inform_bss_status(struct rsi_common *common, u8 status, |
305 | const u8 *bssid, u8 qos_enable, u16 aid); | 321 | const u8 *bssid, u8 qos_enable, u16 aid); |
@@ -313,4 +329,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb); | |||
313 | int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb); | 329 | int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb); |
314 | int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb); | 330 | int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb); |
315 | int rsi_band_check(struct rsi_common *common); | 331 | int rsi_band_check(struct rsi_common *common); |
332 | int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word); | ||
333 | int rsi_send_radio_params_update(struct rsi_common *common); | ||
334 | int rsi_set_antenna(struct rsi_common *common, u8 antenna); | ||
316 | #endif | 335 | #endif |