| .. | .. |
|---|
| 1 | | -/** |
|---|
| 1 | +/* |
|---|
| 2 | 2 | * Copyright (c) 2014 Redpine Signals Inc. |
|---|
| 3 | 3 | * |
|---|
| 4 | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
|---|
| .. | .. |
|---|
| 230 | 230 | return 0; |
|---|
| 231 | 231 | } |
|---|
| 232 | 232 | |
|---|
| 233 | +static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw, |
|---|
| 234 | + struct ieee80211_vif *vif, |
|---|
| 235 | + struct ieee80211_scan_request *hw_req) |
|---|
| 236 | +{ |
|---|
| 237 | + struct cfg80211_scan_request *scan_req = &hw_req->req; |
|---|
| 238 | + struct rsi_hw *adapter = hw->priv; |
|---|
| 239 | + struct rsi_common *common = adapter->priv; |
|---|
| 240 | + struct ieee80211_bss_conf *bss = &vif->bss_conf; |
|---|
| 241 | + |
|---|
| 242 | + rsi_dbg(INFO_ZONE, "***** Hardware scan start *****\n"); |
|---|
| 243 | + common->mac_ops_resumed = false; |
|---|
| 244 | + |
|---|
| 245 | + if (common->fsm_state != FSM_MAC_INIT_DONE) |
|---|
| 246 | + return -ENODEV; |
|---|
| 247 | + |
|---|
| 248 | + if ((common->wow_flags & RSI_WOW_ENABLED) || |
|---|
| 249 | + scan_req->n_channels == 0) |
|---|
| 250 | + return -EINVAL; |
|---|
| 251 | + |
|---|
| 252 | + /* Scan already in progress. So return */ |
|---|
| 253 | + if (common->bgscan_en) |
|---|
| 254 | + return -EBUSY; |
|---|
| 255 | + |
|---|
| 256 | + /* If STA is not connected, return with special value 1, in order |
|---|
| 257 | + * to start sw_scan in mac80211 |
|---|
| 258 | + */ |
|---|
| 259 | + if (!bss->assoc) |
|---|
| 260 | + return 1; |
|---|
| 261 | + |
|---|
| 262 | + mutex_lock(&common->mutex); |
|---|
| 263 | + common->hwscan = scan_req; |
|---|
| 264 | + if (!rsi_send_bgscan_params(common, RSI_START_BGSCAN)) { |
|---|
| 265 | + if (!rsi_send_bgscan_probe_req(common, vif)) { |
|---|
| 266 | + rsi_dbg(INFO_ZONE, "Background scan started...\n"); |
|---|
| 267 | + common->bgscan_en = true; |
|---|
| 268 | + } |
|---|
| 269 | + } |
|---|
| 270 | + mutex_unlock(&common->mutex); |
|---|
| 271 | + |
|---|
| 272 | + return 0; |
|---|
| 273 | +} |
|---|
| 274 | + |
|---|
| 275 | +static void rsi_mac80211_cancel_hw_scan(struct ieee80211_hw *hw, |
|---|
| 276 | + struct ieee80211_vif *vif) |
|---|
| 277 | +{ |
|---|
| 278 | + struct rsi_hw *adapter = hw->priv; |
|---|
| 279 | + struct rsi_common *common = adapter->priv; |
|---|
| 280 | + struct cfg80211_scan_info info; |
|---|
| 281 | + |
|---|
| 282 | + rsi_dbg(INFO_ZONE, "***** Hardware scan stop *****\n"); |
|---|
| 283 | + mutex_lock(&common->mutex); |
|---|
| 284 | + |
|---|
| 285 | + if (common->bgscan_en) { |
|---|
| 286 | + if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN)) |
|---|
| 287 | + common->bgscan_en = false; |
|---|
| 288 | + info.aborted = false; |
|---|
| 289 | + ieee80211_scan_completed(adapter->hw, &info); |
|---|
| 290 | + rsi_dbg(INFO_ZONE, "Back ground scan cancelled\n"); |
|---|
| 291 | + } |
|---|
| 292 | + common->hwscan = NULL; |
|---|
| 293 | + mutex_unlock(&common->mutex); |
|---|
| 294 | +} |
|---|
| 295 | + |
|---|
| 233 | 296 | /** |
|---|
| 234 | 297 | * rsi_mac80211_detach() - This function is used to de-initialize the |
|---|
| 235 | 298 | * Mac80211 stack. |
|---|
| .. | .. |
|---|
| 309 | 372 | { |
|---|
| 310 | 373 | struct rsi_hw *adapter = hw->priv; |
|---|
| 311 | 374 | struct rsi_common *common = adapter->priv; |
|---|
| 375 | + struct ieee80211_hdr *wlh = (struct ieee80211_hdr *)skb->data; |
|---|
| 376 | + |
|---|
| 377 | + if (ieee80211_is_auth(wlh->frame_control)) |
|---|
| 378 | + common->mac_ops_resumed = false; |
|---|
| 312 | 379 | |
|---|
| 313 | 380 | rsi_core_xmit(common, skb); |
|---|
| 314 | 381 | } |
|---|
| .. | .. |
|---|
| 615 | 682 | } |
|---|
| 616 | 683 | |
|---|
| 617 | 684 | /* Power save parameters */ |
|---|
| 618 | | - if (changed & IEEE80211_CONF_CHANGE_PS) { |
|---|
| 685 | + if ((changed & IEEE80211_CONF_CHANGE_PS) && |
|---|
| 686 | + !common->mac_ops_resumed) { |
|---|
| 619 | 687 | struct ieee80211_vif *vif, *sta_vif = NULL; |
|---|
| 620 | 688 | unsigned long flags; |
|---|
| 621 | 689 | int i, set_ps = 1; |
|---|
| .. | .. |
|---|
| 662 | 730 | /** |
|---|
| 663 | 731 | * rsi_get_connected_channel() - This function is used to get the current |
|---|
| 664 | 732 | * connected channel number. |
|---|
| 665 | | - * @adapter: Pointer to the adapter structure. |
|---|
| 733 | + * @vif: Pointer to the ieee80211_vif structure. |
|---|
| 666 | 734 | * |
|---|
| 667 | 735 | * Return: Current connected AP's channel number is returned. |
|---|
| 668 | 736 | */ |
|---|
| .. | .. |
|---|
| 748 | 816 | adapter->ps_info.dtim_interval_duration = bss->dtim_period; |
|---|
| 749 | 817 | adapter->ps_info.listen_interval = conf->listen_interval; |
|---|
| 750 | 818 | |
|---|
| 751 | | - /* If U-APSD is updated, send ps parameters to firmware */ |
|---|
| 752 | | - if (bss->assoc) { |
|---|
| 753 | | - if (common->uapsd_bitmap) { |
|---|
| 754 | | - rsi_dbg(INFO_ZONE, "Configuring UAPSD\n"); |
|---|
| 755 | | - rsi_conf_uapsd(adapter, vif); |
|---|
| 819 | + /* If U-APSD is updated, send ps parameters to firmware */ |
|---|
| 820 | + if (bss->assoc) { |
|---|
| 821 | + if (common->uapsd_bitmap) { |
|---|
| 822 | + rsi_dbg(INFO_ZONE, "Configuring UAPSD\n"); |
|---|
| 823 | + rsi_conf_uapsd(adapter, vif); |
|---|
| 824 | + } |
|---|
| 825 | + } else { |
|---|
| 826 | + common->uapsd_bitmap = 0; |
|---|
| 756 | 827 | } |
|---|
| 757 | | - } else { |
|---|
| 758 | | - common->uapsd_bitmap = 0; |
|---|
| 759 | | - } |
|---|
| 760 | 828 | } |
|---|
| 761 | 829 | |
|---|
| 762 | 830 | if (changed & BSS_CHANGED_CQM) { |
|---|
| 763 | 831 | common->cqm_info.last_cqm_event_rssi = 0; |
|---|
| 764 | 832 | common->cqm_info.rssi_thold = bss_conf->cqm_rssi_thold; |
|---|
| 765 | 833 | common->cqm_info.rssi_hyst = bss_conf->cqm_rssi_hyst; |
|---|
| 766 | | - rsi_dbg(INFO_ZONE, "RSSI throld & hysteresis are: %d %d\n", |
|---|
| 834 | + rsi_dbg(INFO_ZONE, "RSSI threshold & hysteresis are: %d %d\n", |
|---|
| 767 | 835 | common->cqm_info.rssi_thold, |
|---|
| 768 | 836 | common->cqm_info.rssi_hyst); |
|---|
| 769 | 837 | } |
|---|
| .. | .. |
|---|
| 786 | 854 | /** |
|---|
| 787 | 855 | * rsi_mac80211_conf_filter() - This function configure the device's RX filter. |
|---|
| 788 | 856 | * @hw: Pointer to the ieee80211_hw structure. |
|---|
| 789 | | - * @changed: Changed flags set. |
|---|
| 857 | + * @changed_flags: Changed flags set. |
|---|
| 790 | 858 | * @total_flags: Total initial flags set. |
|---|
| 791 | 859 | * @multicast: Multicast. |
|---|
| 792 | 860 | * |
|---|
| .. | .. |
|---|
| 867 | 935 | * @hw: Pointer to the ieee80211_hw structure. |
|---|
| 868 | 936 | * @vif: Pointer to the ieee80211_vif structure. |
|---|
| 869 | 937 | * @key: Pointer to the ieee80211_key_conf structure. |
|---|
| 938 | + * @sta: Pointer to the ieee80211_sta structure. |
|---|
| 870 | 939 | * |
|---|
| 871 | 940 | * Return: status: 0 on success, negative error codes on failure. |
|---|
| 872 | 941 | */ |
|---|
| .. | .. |
|---|
| 924 | 993 | if (status) |
|---|
| 925 | 994 | return status; |
|---|
| 926 | 995 | |
|---|
| 927 | | - if (vif->type == NL80211_IFTYPE_STATION && key->key && |
|---|
| 996 | + if (vif->type == NL80211_IFTYPE_STATION && |
|---|
| 928 | 997 | (key->cipher == WLAN_CIPHER_SUITE_WEP104 || |
|---|
| 929 | 998 | key->cipher == WLAN_CIPHER_SUITE_WEP40)) { |
|---|
| 930 | 999 | if (!rsi_send_block_unblock_frame(adapter->priv, false)) |
|---|
| .. | .. |
|---|
| 1068 | 1137 | else if ((vif->type == NL80211_IFTYPE_AP) || |
|---|
| 1069 | 1138 | (vif->type == NL80211_IFTYPE_P2P_GO)) |
|---|
| 1070 | 1139 | rsta->seq_start[tid] = seq_no; |
|---|
| 1071 | | - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
|---|
| 1072 | | - status = 0; |
|---|
| 1140 | + status = IEEE80211_AMPDU_TX_START_IMMEDIATE; |
|---|
| 1073 | 1141 | break; |
|---|
| 1074 | 1142 | |
|---|
| 1075 | 1143 | case IEEE80211_AMPDU_TX_STOP_CONT: |
|---|
| .. | .. |
|---|
| 1178 | 1246 | * @common: Pointer to the driver private structure. |
|---|
| 1179 | 1247 | * @bssid: pointer to the bssid. |
|---|
| 1180 | 1248 | * @rssi: RSSI value. |
|---|
| 1249 | + * @vif: Pointer to the ieee80211_vif structure. |
|---|
| 1181 | 1250 | */ |
|---|
| 1182 | 1251 | static void rsi_perform_cqm(struct rsi_common *common, |
|---|
| 1183 | 1252 | u8 *bssid, |
|---|
| .. | .. |
|---|
| 1279 | 1348 | } |
|---|
| 1280 | 1349 | |
|---|
| 1281 | 1350 | /** |
|---|
| 1282 | | - * rsi_indicate_pkt_to_os() - This function sends recieved packet to mac80211. |
|---|
| 1351 | + * rsi_indicate_pkt_to_os() - This function sends received packet to mac80211. |
|---|
| 1283 | 1352 | * @common: Pointer to the driver private structure. |
|---|
| 1284 | 1353 | * @skb: Pointer to the socket buffer structure. |
|---|
| 1285 | 1354 | * |
|---|
| .. | .. |
|---|
| 1717 | 1786 | return status; |
|---|
| 1718 | 1787 | } |
|---|
| 1719 | 1788 | |
|---|
| 1720 | | -static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw) |
|---|
| 1789 | +static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw, |
|---|
| 1790 | + struct ieee80211_vif *vif) |
|---|
| 1721 | 1791 | { |
|---|
| 1722 | 1792 | struct rsi_hw *adapter = hw->priv; |
|---|
| 1723 | 1793 | struct rsi_common *common = adapter->priv; |
|---|
| .. | .. |
|---|
| 1801 | 1871 | return 0; |
|---|
| 1802 | 1872 | } |
|---|
| 1803 | 1873 | rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers); |
|---|
| 1874 | + |
|---|
| 1875 | + if (common->coex_mode > 1) |
|---|
| 1876 | + rsi_disable_ps(adapter, adapter->vifs[0]); |
|---|
| 1877 | + |
|---|
| 1804 | 1878 | rsi_send_wowlan_request(common, triggers, 1); |
|---|
| 1805 | 1879 | |
|---|
| 1806 | 1880 | /** |
|---|
| .. | .. |
|---|
| 1844 | 1918 | |
|---|
| 1845 | 1919 | rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__); |
|---|
| 1846 | 1920 | |
|---|
| 1847 | | - if (common->hibernate_resume) |
|---|
| 1848 | | - return 0; |
|---|
| 1921 | + if (common->hibernate_resume) { |
|---|
| 1922 | + common->mac_ops_resumed = true; |
|---|
| 1923 | + /* Device need a complete restart of all MAC operations. |
|---|
| 1924 | + * returning 1 will serve this purpose. |
|---|
| 1925 | + */ |
|---|
| 1926 | + return 1; |
|---|
| 1927 | + } |
|---|
| 1849 | 1928 | |
|---|
| 1850 | 1929 | mutex_lock(&common->mutex); |
|---|
| 1851 | 1930 | rsi_send_wowlan_request(common, 0, 0); |
|---|
| .. | .. |
|---|
| 1885 | 1964 | .suspend = rsi_mac80211_suspend, |
|---|
| 1886 | 1965 | .resume = rsi_mac80211_resume, |
|---|
| 1887 | 1966 | #endif |
|---|
| 1967 | + .hw_scan = rsi_mac80211_hw_scan_start, |
|---|
| 1968 | + .cancel_hw_scan = rsi_mac80211_cancel_hw_scan, |
|---|
| 1888 | 1969 | }; |
|---|
| 1889 | 1970 | |
|---|
| 1890 | 1971 | /** |
|---|
| .. | .. |
|---|
| 1972 | 2053 | common->max_stations = wiphy->max_ap_assoc_sta; |
|---|
| 1973 | 2054 | rsi_dbg(ERR_ZONE, "Max Stations Allowed = %d\n", common->max_stations); |
|---|
| 1974 | 2055 | hw->sta_data_size = sizeof(struct rsi_sta); |
|---|
| 2056 | + |
|---|
| 2057 | + wiphy->max_scan_ssids = RSI_MAX_SCAN_SSIDS; |
|---|
| 2058 | + wiphy->max_scan_ie_len = RSI_MAX_SCAN_IE_LEN; |
|---|
| 1975 | 2059 | wiphy->flags = WIPHY_FLAG_REPORTS_OBSS; |
|---|
| 1976 | 2060 | wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
|---|
| 1977 | 2061 | wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; |
|---|