Kalle Valo says: ==================== wireless-drivers-next patches for 4.10 Major changes: rsi * filter rx frames * configure tx power * make it possible to select antenna * support 802.11d brcmfmac * cleanup of scheduled scan code * support for bcm43341 chipset with different chip id * support rev6 of PCIe device interface ath10k * add spectral scan support for QCA6174 and QCA9377 families * show used tx bitrate with 10.4 firmware wil6210 * add power save mode support * add abort scan functionality * add support settings retry limit for short frames bcma * add Dell Inspiron 3148 ====================
Unified · Split
| @@ -295,6 +295,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { · 294 unmodified lines | |||
| 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) }, |
| @@ -326,6 +326,7 @@ static const char *const ath10k_core_fw_feature_str[] = { · 325 unmodified lines | |||
| 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) · 1204 unmodified lines | |||
| 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, · 314 unmodified lines | |||
| 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) · 188 unmodified lines | |||
| 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) · 326 unmodified lines | |||
| 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 | } |
| @@ -337,6 +337,7 @@ struct ath10k_sta { · 336 unmodified lines | |||
| 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 { · 219 unmodified lines | |||
| 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 { · 125 unmodified lines | |||
| 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 { · 207 unmodified lines | |||
| 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; |
| @@ -77,6 +77,19 @@ void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 76 unmodified lines | |||
| 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, |
| @@ -137,6 +137,8 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { · 136 unmodified lines | |||
| 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) |
| @@ -419,6 +419,7 @@ enum htt_10_4_t2h_msg_type { · 418 unmodified lines | |||
| 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 { · 28 unmodified lines | |||
| 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 { · 1011 unmodified lines | |||
| 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 { · 45 unmodified lines | |||
| 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 { · 165 unmodified lines | |||
| 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); · 56 unmodified lines | |||
| 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); |
| @@ -2194,6 +2194,128 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) · 2193 unmodified lines | |||
| 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) · 154 unmodified lines | |||
| 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", |
| @@ -350,21 +350,15 @@ static int ath10k_htt_tx_alloc_txdone_fifo(struct ath10k_htt *htt) · 349 unmodified lines | |||
| 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: · 25 unmodified lines | |||
| 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) · 16 unmodified lines | |||
| 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) |
| @@ -1167,7 +1167,9 @@ static bool ath10k_mac_monitor_vdev_is_needed(struct ath10k *ar) · 1166 unmodified lines | |||
| 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) · 3275 unmodified lines | |||
| 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, · 2520 unmodified lines | |||
| 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 = { · 458 unmodified lines | |||
| 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) · 524 unmodified lines | |||
| 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); |
| @@ -660,6 +660,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar, · 659 unmodified lines | |||
| 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, · 9 unmodified lines | |||
| 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)) |
| @@ -1313,8 +1313,8 @@ ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar, · 1312 unmodified lines | |||
| 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) · 1815 unmodified lines | |||
| 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 = { · 322 unmodified lines | |||
| 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 = { · 71 unmodified lines | |||
| 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 = { |
| @@ -785,7 +785,6 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = { · 784 unmodified lines | |||
| 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 = { · 69 unmodified lines | |||
| 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 = { · 68 unmodified lines | |||
| 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 = { · 69 unmodified lines | |||
| 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, · 3470 unmodified lines | |||
| 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; |
| @@ -4603,9 +4603,17 @@ enum wmi_rate_preamble { · 4602 unmodified lines | |||
| 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 { · 64 unmodified lines | |||
| 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 { · 326 unmodified lines | |||
| 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) |
| @@ -66,7 +66,6 @@ · 65 unmodified lines | |||
| 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" |
| @@ -62,7 +62,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) · 61 unmodified lines | |||
| 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, |
| @@ -528,6 +528,9 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h · 527 unmodified lines | |||
| 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 = { · 538 unmodified lines | |||
| 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, · 7 unmodified lines | |||
| 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, |
| @@ -997,7 +997,8 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) · 996 unmodified lines | |||
| 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) · 16 unmodified lines | |||
| 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) · 222 unmodified lines | |||
| 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) · 58 unmodified lines | |||
| 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 | ||
| @@ -71,6 +71,8 @@ extern int htc_use_dev_fw; · 70 unmodified lines | |||
| 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 | ||
| @@ -2792,7 +2792,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) · 2791 unmodified lines | |||
| 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 | ||
| @@ -867,10 +867,21 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, · 866 unmodified lines | |||
| 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 | ||
| @@ -354,14 +354,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, · 353 unmodified lines | |||
| 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, · 10 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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, · 16 unmodified lines | |||
| 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, · 26 unmodified lines | |||
| 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, · 4 unmodified lines | |||
| 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, · 199 unmodified lines | |||
| 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, · 260 unmodified lines | |||
| 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, · 463 unmodified lines | |||
| 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 = { · 14 unmodified lines | |||
| 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) · 10 unmodified lines | |||
| 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 = |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 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) · 183 unmodified lines | |||
| 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, · 47 unmodified lines | |||
| 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, · 9 unmodified lines | |||
| 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) · 93 unmodified lines | |||
| 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) · 110 unmodified lines | |||
| 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) · 49 unmodified lines | |||
| 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) · 108 unmodified lines | |||
| 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) · 110 unmodified lines | |||
| 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) · 46 unmodified lines | |||
| 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) · 70 unmodified lines | |||
| 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) · 110 unmodified lines | |||
| 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); |
| @@ -214,7 +214,7 @@ int wil_if_add(struct wil6210_priv *wil) · 213 unmodified lines | |||
| 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) { |
| @@ -22,6 +22,43 @@ · 21 unmodified lines | |||
| 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, · 18 unmodified lines | |||
| 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: · 50 unmodified lines | |||
| 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, · 4 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 78 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 16 unmodified lines | |||
| 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 | } |
| @@ -54,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, · 53 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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: · 121 unmodified lines | |||
| 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, · 99 unmodified lines | |||
| 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, · 4 unmodified lines | |||
| 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) · 33 unmodified lines | |||
| 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) · 9 unmodified lines | |||
| 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 | } |
| @@ -88,6 +88,18 @@ static inline int wil_vring_wmark_high(struct vring *vring) · 87 unmodified lines | |||
| 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, · 1686 unmodified lines | |||
| 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) · 36 unmodified lines | |||
| 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) · 142 unmodified lines | |||
| 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 | } |
| @@ -276,10 +276,11 @@ struct fw_map { · 275 unmodified lines | |||
| 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 { · 175 unmodified lines | |||
| 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 { · 155 unmodified lines | |||
| 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); · 187 unmodified lines | |||
| 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); · 14 unmodified lines | |||
| 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, · 19 unmodified lines | |||
| 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); · 11 unmodified lines | |||
| 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); |
| @@ -36,6 +36,9 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, · 35 unmodified lines | |||
| 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) · 31 unmodified lines | |||
| 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; |
| @@ -84,19 +84,29 @@ MODULE_PARM_DESC(led_id, · 83 unmodified lines | |||
| 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[] = { · 5 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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, · 303 unmodified lines | |||
| 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) · 103 unmodified lines | |||
| 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) · 33 unmodified lines | |||
| 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, · 969 unmodified lines | |||
| 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; |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | |||
| 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 { · 10 unmodified lines | |||
| 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 { · 7 unmodified lines | |||
| 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 { · 676 unmodified lines | |||
| 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 { · 57 unmodified lines | |||
| 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 { · 87 unmodified lines | |||
| 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 { · 119 unmodified lines | |||
| 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 { · 898 unmodified lines | |||
| 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 { · 108 unmodified lines | |||
| 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__ */ |
| @@ -35,7 +35,8 @@ brcmfmac-objs += \ · 34 unmodified lines | |||
| 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) += \ |
| @@ -22,10 +22,12 @@ · 21 unmodified lines | |||
| 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 { · 63 unmodified lines | |||
| 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 | ||
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 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 @@ · 3 unmodified lines | |||
| 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, · 711 unmodified lines | |||
| 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: · 311 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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, · 73 unmodified lines | |||
| 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) · 1836 unmodified lines | |||
| 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) · 16 unmodified lines | |||
| 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, · 76 unmodified lines | |||
| 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, · 39 unmodified lines | |||
| 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) · 18 unmodified lines | |||
| 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, · 7 unmodified lines | |||
| 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, · 19 unmodified lines | |||
| 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) · 2929 unmodified lines | |||
| 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 | ||
| @@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl { · 270 unmodified lines | |||
| 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 { · 25 unmodified lines | |||
| 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; |
| @@ -131,6 +131,7 @@ · 130 unmodified lines | |||
| 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) |
| @@ -718,6 +719,21 @@ struct brcmf_pno_param_le { · 581 unmodified lines | |||
| 718 | __le32 slow_freq; | 719 | __le32 slow_freq; |
| 719 | }; | 720 | }; |
| 720 | 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 | |||
| 721 | /** | 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 | * |
| @@ -769,6 +785,13 @@ struct brcmf_pno_scanresults_le { · 45 unmodified lines | |||
| 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 | * |
| @@ -87,11 +87,6 @@ struct msgbuf_common_hdr { · 86 unmodified lines | |||
| 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 { · 129 unmodified lines | |||
| 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, · 376 unmodified lines | |||
| 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) · 143 unmodified lines | |||
| 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) · 99 unmodified lines | |||
| 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, · 301 unmodified lines | |||
| 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, · 21 unmodified lines | |||
| 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) · 98 unmodified lines | |||
| 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) · 35 unmodified lines | |||
| 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) · 71 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 29 unmodified lines | |||
| 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) · 14 unmodified lines | |||
| 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 | ||
| @@ -31,6 +31,10 @@ · 30 unmodified lines | |||
| 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); |
| @@ -135,7 +135,7 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { · 134 unmodified lines | |||
| 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[] = { · 24 unmodified lines | |||
| 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 { · 48 unmodified lines | |||
| 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 { · 3 unmodified lines | |||
| 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 { · 37 unmodified lines | |||
| 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) · 764 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 24 unmodified lines | |||
| 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, · 176 unmodified lines | |||
| 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, · 287 unmodified lines | |||
| 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 | ||
| @@ -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 | |||
| @@ -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 */ | ||
| @@ -621,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { · 620 unmodified lines | |||
| 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), |
| @@ -179,7 +179,7 @@ s16 qm_norm32(s32 op) · 178 unmodified lines | |||
| 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[] = { · 26 unmodified lines | |||
| 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 */ |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | |||
| 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 |
| @@ -2143,6 +2143,16 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, · 2142 unmodified lines | |||
| 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, · 1831 unmodified lines | |||
| 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); |
| @@ -219,6 +219,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { · 218 unmodified lines | |||
| 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) | \ |
| @@ -518,7 +518,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) · 517 unmodified lines | |||
| 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) · 51 unmodified lines | |||
| 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, |
| @@ -1424,8 +1424,13 @@ static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter) · 1423 unmodified lines | |||
| 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 | ||
| @@ -135,6 +135,7 @@ static int mwifiex_pcie_suspend(struct device *dev) · 134 unmodified lines | |||
| 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, · 1909 unmodified lines | |||
| 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, · 5 unmodified lines | |||
| 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 | ||
| @@ -827,7 +827,6 @@ mwifiex_config_scan(struct mwifiex_private *priv, · 826 unmodified lines | |||
| 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, · 271 unmodified lines | |||
| 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 | } |
| @@ -186,9 +186,7 @@ static int mwifiex_sdio_resume(struct device *dev) · 185 unmodified lines | |||
| 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) · 103 unmodified lines | |||
| 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, · 832 unmodified lines | |||
| 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, · 14 unmodified lines | |||
| 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" |
| @@ -1746,7 +1746,6 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, · 1745 unmodified lines | |||
| 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, · 11 unmodified lines | |||
| 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, · 131 unmodified lines | |||
| 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, · 7 unmodified lines | |||
| 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) · 287 unmodified lines | |||
| 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) · 106 unmodified lines | |||
| 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 */ |
| @@ -379,7 +379,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf, · 378 unmodified lines | |||
| 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, · 4 unmodified lines | |||
| 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 | ||
| @@ -293,13 +293,13 @@ static void mt7601u_mac_stop_hw(struct mt7601u_dev *dev) · 292 unmodified lines | |||
| 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 | ||
| @@ -192,6 +192,9 @@ · 191 unmodified lines | |||
| 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) |
| @@ -1337,10 +1337,11 @@ struct rtl8xxxu_fileops { · 1336 unmodified lines | |||
| 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); · 87 unmodified lines | |||
| 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; |
| @@ -1556,7 +1556,7 @@ exit: · 1555 unmodified lines | |||
| 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; |
| @@ -4372,6 +4372,13 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, · 4371 unmodified lines | |||
| 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, · 5 unmodified lines | |||
| 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, · 370 unmodified lines | |||
| 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, · 24 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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, · 20 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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, · 20 unmodified lines | |||
| 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, · 47 unmodified lines | |||
| 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, · 4 unmodified lines | |||
| 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 | ||
| @@ -1303,12 +1303,13 @@ EXPORT_SYMBOL_GPL(rtl_action_proc); · 1302 unmodified lines | |||
| 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, · 66 unmodified lines | |||
| 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 | ||
| @@ -1150,10 +1150,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, · 1149 unmodified lines | |||
| 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, · 271 unmodified lines | |||
| 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); |
| @@ -659,11 +659,9 @@ tx_status_ok: · 658 unmodified lines | |||
| 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: · 244 unmodified lines | |||
| 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) { |
| @@ -407,8 +407,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) · 406 unmodified lines | |||
| 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) · 29 unmodified lines | |||
| 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) · 23 unmodified lines | |||
| 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) · 186 unmodified lines | |||
| 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, |
| @@ -275,6 +275,8 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw) · 274 unmodified lines | |||
| 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) · 107 unmodified lines | |||
| 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 && |
| @@ -408,6 +410,34 @@ static int rsi_channel_change(struct ieee80211_hw *hw) · 13 unmodified lines | |||
| 408 | return status; | 410 | return status; |
| 409 | } | 411 | } |
| 410 | 412 | ||
| 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 | |||
| 411 | /** | 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 |
| @@ -429,6 +459,12 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw, · 15 unmodified lines | |||
| 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, · 36 unmodified lines | |||
| 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, · 531 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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 = { · 12 unmodified lines | |||
| 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) · 58 unmodified lines | |||
| 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; |
| @@ -913,7 +913,8 @@ int rsi_band_check(struct rsi_common *common) · 912 unmodified lines | |||
| 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) · 8 unmodified lines | |||
| 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) · 291 unmodified lines | |||
| 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. |
| @@ -204,6 +204,9 @@ struct rsi_common { · 203 unmodified lines | |||
| 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 { · 10 unmodified lines | |||
| 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); |
| @@ -140,6 +140,19 @@ · 139 unmodified lines | |||
| 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 { · 44 unmodified lines | |||
| 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, · 102 unmodified lines | |||
| 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); · 7 unmodified lines | |||
| 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 |