diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/cfg80211.c')
| -rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 649 |
1 files changed, 516 insertions, 133 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ef5fa890a28..b511613bba2 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -25,7 +25,9 @@ module_param(reg_alpha2, charp, 0); static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { { - .max = 2, .types = BIT(NL80211_IFTYPE_STATION), + .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_CLIENT), }, { .max = 1, .types = BIT(NL80211_IFTYPE_AP), @@ -48,24 +50,24 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = { REG_RULE(2412-10, 2462+10, 40, 3, 20, 0), /* Channel 12 - 13 */ REG_RULE(2467-10, 2472+10, 20, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* Channel 14 */ REG_RULE(2484-10, 2484+10, 20, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM), /* Channel 36 - 48 */ REG_RULE(5180-10, 5240+10, 40, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* Channel 149 - 165 */ REG_RULE(5745-10, 5825+10, 40, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* Channel 52 - 64 */ REG_RULE(5260-10, 5320+10, 40, 3, 30, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_DFS), /* Channel 100 - 140 */ REG_RULE(5500-10, 5700+10, 40, 3, 30, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_DFS), } }; @@ -182,13 +184,14 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) */ static int mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, u64 *cookie) { + const u8 *buf = params->buf; + size_t len = params->len; struct sk_buff *skb; u16 pkt_len; const struct ieee80211_mgmt *mgmt; + struct mwifiex_txinfo *tx_info; struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); if (!buf || !len) { @@ -216,6 +219,12 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, return -ENOMEM; } + tx_info = MWIFIEX_SKB_TXCB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num = priv->bss_num; + tx_info->bss_type = priv->bss_type; + tx_info->pkt_len = pkt_len; + mwifiex_form_mgmt_frame(skb, buf, len); mwifiex_queue_tx_pkt(priv, skb); @@ -235,16 +244,20 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, u16 frame_type, bool reg) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); + u32 mask; if (reg) - priv->mgmt_frame_mask |= BIT(frame_type >> 4); + mask = priv->mgmt_frame_mask | BIT(frame_type >> 4); else - priv->mgmt_frame_mask &= ~BIT(frame_type >> 4); - - mwifiex_send_cmd_async(priv, HostCmd_CMD_MGMT_FRAME_REG, - HostCmd_ACT_GEN_SET, 0, &priv->mgmt_frame_mask); + mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4); - wiphy_dbg(wiphy, "info: mgmt frame registered\n"); + if (mask != priv->mgmt_frame_mask) { + priv->mgmt_frame_mask = mask; + mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, + HostCmd_ACT_GEN_SET, 0, + &priv->mgmt_frame_mask, false); + wiphy_dbg(wiphy, "info: mgmt frame registered\n"); + } } /* @@ -503,8 +516,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, - HostCmd_ACT_GEN_SET, 0, NULL)) { + if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, + HostCmd_ACT_GEN_SET, 0, NULL, false)) { wiphy_err(wiphy, "11D: setting domain info in FW\n"); return -1; } @@ -526,23 +539,33 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv = mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_ANY); wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", request->alpha2[0], request->alpha2[1]); - memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2)); - switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_CORE: case NL80211_REGDOM_SET_BY_USER: - break; - /* Todo: apply driver specific changes in channel flags based - on the request initiator if necessary. */ case NL80211_REGDOM_SET_BY_COUNTRY_IE: break; + default: + wiphy_err(wiphy, "unknown regdom initiator: %d\n", + request->initiator); + return; + } + + /* Don't send world or same regdom info to firmware */ + if (strncmp(request->alpha2, "00", 2) && + strncmp(request->alpha2, adapter->country_code, + sizeof(request->alpha2))) { + memcpy(adapter->country_code, request->alpha2, + sizeof(request->alpha2)); + mwifiex_send_domain_info_cmd_fw(wiphy); + mwifiex_dnld_txpwr_table(priv); } - mwifiex_send_domain_info_cmd_fw(wiphy); } /* @@ -558,9 +581,9 @@ mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) frag_thr > MWIFIEX_FRAG_MAX_VALUE) frag_thr = MWIFIEX_FRAG_MAX_VALUE; - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, FRAG_THRESH_I, - &frag_thr); + return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, FRAG_THRESH_I, + &frag_thr, true); } /* @@ -575,9 +598,9 @@ mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) rts_thr = MWIFIEX_RTS_MAX_VALUE; - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, RTS_THRESH_I, - &rts_thr); + return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, RTS_THRESH_I, + &rts_thr, true); } /* @@ -615,20 +638,19 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) bss_started = priv->bss_started; - ret = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, - NULL); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, + HostCmd_ACT_GEN_SET, 0, + NULL, true); if (ret) { wiphy_err(wiphy, "Failed to stop the BSS\n"); kfree(bss_cfg); return ret; } - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_UAP_SYS_CONFIG, - HostCmd_ACT_GEN_SET, - UAP_BSS_PARAMS_I, bss_cfg); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, + HostCmd_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg, + false); kfree(bss_cfg); @@ -640,10 +662,9 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) if (!bss_started) break; - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_UAP_BSS_START, - HostCmd_ACT_GEN_SET, 0, - NULL); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, + HostCmd_ACT_GEN_SET, 0, + NULL, false); if (ret) { wiphy_err(wiphy, "Failed to start BSS\n"); return ret; @@ -678,8 +699,8 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode, true)) return -1; return 0; @@ -699,13 +720,13 @@ mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) return -1; mode = P2P_MODE_DEVICE; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode, true)) return -1; mode = P2P_MODE_CLIENT; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode, true)) return -1; return 0; @@ -725,13 +746,13 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) return -1; mode = P2P_MODE_DEVICE; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode, true)) return -1; mode = P2P_MODE_GO; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode, true)) return -1; if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) @@ -831,8 +852,8 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, + HostCmd_ACT_GEN_SET, 0, NULL, true); return ret; } @@ -920,8 +941,8 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; /* Get signal information from the firmware */ - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, - HostCmd_ACT_GEN_GET, 0, NULL)) { + if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, + HostCmd_ACT_GEN_GET, 0, NULL, true)) { dev_err(priv->adapter->dev, "failed to get signal information\n"); return -EFAULT; } @@ -932,9 +953,9 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, } /* Get DTIM period information from firmware */ - mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, - &priv->dtim_period); + mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, + &priv->dtim_period, true); mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate); @@ -974,7 +995,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, */ static int mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_info *sinfo) + const u8 *mac, struct station_info *sinfo) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); @@ -1138,9 +1159,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; enum ieee80211_band band; + struct mwifiex_adapter *adapter = priv->adapter; if (!priv->media_connected) { - dev_err(priv->adapter->dev, + dev_err(adapter->dev, "Can not set Tx data rate in disconnected state\n"); return -EINVAL; } @@ -1159,13 +1181,20 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, else bitmap_rates[1] = mask->control[band].legacy; - /* Fill MCS rates */ - bitmap_rates[2] = mask->control[band].mcs[0]; - if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) - bitmap_rates[2] |= mask->control[band].mcs[1] << 8; + /* Fill HT MCS rates */ + bitmap_rates[2] = mask->control[band].ht_mcs[0]; + if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) + bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; + + /* Fill VHT MCS rates */ + if (adapter->fw_api_ver == MWIFIEX_FW_V15) { + bitmap_rates[10] = mask->control[band].vht_mcs[0]; + if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) + bitmap_rates[11] = mask->control[band].vht_mcs[1]; + } - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_SET, 0, bitmap_rates); + return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_SET, 0, bitmap_rates, true); } /* @@ -1194,14 +1223,14 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold); subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; - return mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_SUBSCRIBE_EVENT, - 0, 0, &subsc_evt); + return mwifiex_send_cmd(priv, + HostCmd_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, &subsc_evt, true); } else { subsc_evt.action = HostCmd_ACT_BITWISE_CLR; - return mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_SUBSCRIBE_EVENT, - 0, 0, &subsc_evt); + return mwifiex_send_cmd(priv, + HostCmd_CMD_802_11_SUBSCRIBE_EVENT, + 0, 0, &subsc_evt, true); } return 0; @@ -1242,7 +1271,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, */ static int mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac) + const u8 *mac) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct mwifiex_sta_node *sta_node; @@ -1254,10 +1283,9 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, if (!mac || is_broadcast_ether_addr(mac)) { wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); list_for_each_entry(sta_node, &priv->sta_list, list) { - if (mwifiex_send_cmd_sync(priv, - HostCmd_CMD_UAP_STA_DEAUTH, - HostCmd_ACT_GEN_SET, 0, - sta_node->mac_addr)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, + HostCmd_ACT_GEN_SET, 0, + sta_node->mac_addr, true)) return -1; mwifiex_uap_del_sta_data(priv, sta_node); } @@ -1267,10 +1295,9 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, sta_node = mwifiex_get_sta_entry(priv, mac); spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); if (sta_node) { - if (mwifiex_send_cmd_sync(priv, - HostCmd_CMD_UAP_STA_DEAUTH, - HostCmd_ACT_GEN_SET, 0, - sta_node->mac_addr)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, + HostCmd_ACT_GEN_SET, 0, + sta_node->mac_addr, true)) return -1; mwifiex_uap_del_sta_data(priv, sta_node); } @@ -1306,13 +1333,40 @@ mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) tx_ant = RF_ANTENNA_AUTO; rx_ant = RF_ANTENNA_AUTO; } + } else { + struct ieee80211_sta_ht_cap *ht_info; + int rx_mcs_supp; + enum ieee80211_band band; + + if ((tx_ant == 0x1 && rx_ant == 0x1)) { + adapter->user_dev_mcs_support = HT_STREAM_1X1; + if (adapter->is_hw_11ac_capable) + adapter->usr_dot_11ac_mcs_support = + MWIFIEX_11AC_MCS_MAP_1X1; + } else { + adapter->user_dev_mcs_support = HT_STREAM_2X2; + if (adapter->is_hw_11ac_capable) + adapter->usr_dot_11ac_mcs_support = + MWIFIEX_11AC_MCS_MAP_2X2; + } + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!adapter->wiphy->bands[band]) + continue; + + ht_info = &adapter->wiphy->bands[band]->ht_cap; + rx_mcs_supp = + GET_RXMCSSUPP(adapter->user_dev_mcs_support); + memset(&ht_info->mcs, 0, adapter->number_of_antenna); + memset(&ht_info->mcs, 0xff, rx_mcs_supp); + } } ant_cfg.tx_ant = tx_ant; ant_cfg.rx_ant = rx_ant; - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA, - HostCmd_ACT_GEN_SET, 0, &ant_cfg); + return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA, + HostCmd_ACT_GEN_SET, 0, &ant_cfg, true); } /* cfg80211 operation handler for stop ap. @@ -1327,8 +1381,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) priv->ap_11n_enabled = 0; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, NULL)) { + if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, + HostCmd_ACT_GEN_SET, 0, NULL, true)) { wiphy_err(wiphy, "Failed to stop the BSS\n"); return -1; } @@ -1394,9 +1448,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) config_bands |= BAND_GN; - - if (params->chandef.width > NL80211_CHAN_WIDTH_40) - config_bands |= BAND_GAC; } else { bss_cfg->band_cfg = BAND_CONFIG_A; config_bands = BAND_A; @@ -1442,16 +1493,16 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; } - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, NULL)) { + if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, + HostCmd_ACT_GEN_SET, 0, NULL, true)) { wiphy_err(wiphy, "Failed to stop the BSS\n"); kfree(bss_cfg); return -1; } - if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, - HostCmd_ACT_GEN_SET, - UAP_BSS_PARAMS_I, bss_cfg)) { + if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, + HostCmd_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg, false)) { wiphy_err(wiphy, "Failed to set the SSID\n"); kfree(bss_cfg); return -1; @@ -1459,8 +1510,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, kfree(bss_cfg); - if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START, - HostCmd_ACT_GEN_SET, 0, NULL)) { + if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, + HostCmd_ACT_GEN_SET, 0, NULL, false)) { wiphy_err(wiphy, "Failed to start the BSS\n"); return -1; } @@ -1470,9 +1521,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, else priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter)) + if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &priv->curr_pkt_filter, true)) return -1; return 0; @@ -1497,6 +1548,7 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, " reason code %d\n", priv->cfg_bssid, reason_code); memset(priv->cfg_bssid, 0, ETH_ALEN); + priv->hs2_enabled = false; return 0; } @@ -1560,8 +1612,9 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) * the function notifies the CFG802.11 subsystem of the new BSS connection. */ static int -mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, - u8 *bssid, int mode, struct ieee80211_channel *channel, +mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, + const u8 *ssid, const u8 *bssid, int mode, + struct ieee80211_channel *channel, struct cfg80211_connect_params *sme, bool privacy) { struct cfg80211_ssid req_ssid; @@ -1716,9 +1769,9 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); int ret; - if (priv->bss_mode != NL80211_IFTYPE_STATION) { + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) { wiphy_err(wiphy, - "%s: reject infra assoc request in non-STA mode\n", + "%s: reject infra assoc request in non-STA role\n", dev->name); return -EINVAL; } @@ -1858,7 +1911,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, params->privacy); done: if (!ret) { - cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); + cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, + params->chandef.chan, GFP_KERNEL); dev_dbg(priv->adapter->dev, "info: joined/created adhoc network with bssid" " %pM successfully\n", priv->cfg_bssid); @@ -1956,7 +2010,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, user_scan_cfg->chan_list[i].chan_number = chan->hw_value; user_scan_cfg->chan_list[i].radio_type = chan->band; - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + if (chan->flags & IEEE80211_CHAN_NO_IR) user_scan_cfg->chan_list[i].scan_type = MWIFIEX_SCAN_TYPE_PASSIVE; else @@ -2047,10 +2101,10 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, else ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; - if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; + if (adapter->user_dev_mcs_support == HT_STREAM_2X2) + ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT; else - ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; @@ -2075,8 +2129,8 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; ht_info->cap |= IEEE80211_HT_CAP_SM_PS; - rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); - /* Set MCS for 1x1 */ + rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support); + /* Set MCS for 1x1/2x2 */ memset(mcs, 0xff, rx_mcs_supp); /* Clear all the other values */ memset(&mcs[rx_mcs_supp], 0, @@ -2198,8 +2252,10 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_started = 0; priv->bss_num = 0; - if (mwifiex_cfg80211_init_p2p_client(priv)) - return ERR_PTR(-EFAULT); + if (mwifiex_cfg80211_init_p2p_client(priv)) { + wdev = ERR_PTR(-EFAULT); + goto done; + } break; default: @@ -2212,7 +2268,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, if (!dev) { wiphy_err(wiphy, "no memory available for netdevice\n"); priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-ENOMEM); + wdev = ERR_PTR(-ENOMEM); + goto done; } mwifiex_init_priv_params(priv, dev); @@ -2252,7 +2309,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, wiphy_err(wiphy, "cannot register virtual network device\n"); free_netdev(dev); priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-EFAULT); + priv->netdev = NULL; + wdev = ERR_PTR(-EFAULT); + goto done; } sema_init(&priv->async_sem, 1); @@ -2262,6 +2321,13 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, #ifdef CONFIG_DEBUG_FS mwifiex_dev_debugfs_init(priv); #endif + +done: + if (IS_ERR(wdev)) { + kfree(priv->wdev); + priv->wdev = NULL; + } + return wdev; } EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); @@ -2286,7 +2352,10 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) unregister_netdevice(wdev->netdev); /* Clear the priv in adapter */ + priv->netdev->ieee80211_ptr = NULL; priv->netdev = NULL; + kfree(wdev); + priv->wdev = NULL; priv->media_connected = false; @@ -2296,10 +2365,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) } EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); -#ifdef CONFIG_PM static bool -mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, - s8 *byte_seq) +mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq, + u8 max_byte_seq) { int j, k, valid_byte_cnt = 0; bool dont_care_byte = false; @@ -2317,16 +2385,17 @@ mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, dont_care_byte = true; } - if (valid_byte_cnt > MAX_BYTESEQ) + if (valid_byte_cnt > max_byte_seq) return false; } } - byte_seq[MAX_BYTESEQ] = valid_byte_cnt; + byte_seq[max_byte_seq] = valid_byte_cnt; return true; } +#ifdef CONFIG_PM static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan) { @@ -2335,7 +2404,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, struct mwifiex_mef_entry *mef_entry; int i, filt_num = 0, ret; bool first_pat = true; - u8 byte_seq[MAX_BYTESEQ + 1]; + u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; const u8 ipv4_mc_mac[] = {0x33, 0x33}; const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; struct mwifiex_private *priv = @@ -2365,7 +2434,8 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, for (i = 0; i < wowlan->n_patterns; i++) { memset(byte_seq, 0, sizeof(byte_seq)); if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], - byte_seq)) { + byte_seq, + MWIFIEX_MEF_MAX_BYTESEQ)) { wiphy_err(wiphy, "Pattern not supported\n"); kfree(mef_entry); return -EOPNOTSUPP; @@ -2373,16 +2443,16 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, if (!wowlan->patterns[i].pkt_offset) { if (!(byte_seq[0] & 0x01) && - (byte_seq[MAX_BYTESEQ] == 1)) { + (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) { mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; continue; } else if (is_broadcast_ether_addr(byte_seq)) { mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; continue; } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && - (byte_seq[MAX_BYTESEQ] == 2)) || + (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) || (!memcmp(byte_seq, ipv6_mc_mac, 3) && - (byte_seq[MAX_BYTESEQ] == 3))) { + (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) { mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; continue; } @@ -2408,8 +2478,9 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, mef_entry->filter[filt_num].repeat = 16; memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, ETH_ALEN); - mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN; - mef_entry->filter[filt_num].offset = 14; + mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = + ETH_ALEN; + mef_entry->filter[filt_num].offset = 28; mef_entry->filter[filt_num].filt_type = TYPE_EQ; if (filt_num) mef_entry->filter[filt_num].filt_action = TYPE_OR; @@ -2420,9 +2491,8 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, MWIFIEX_CRITERIA_UNICAST | MWIFIEX_CRITERIA_MULTICAST; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, - HostCmd_ACT_GEN_SET, 0, - &mef_cfg); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, + HostCmd_ACT_GEN_SET, 0, &mef_cfg, true); kfree(mef_entry); return ret; @@ -2442,6 +2512,282 @@ static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, } #endif +static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq) +{ + const u8 ipv4_mc_mac[] = {0x33, 0x33}; + const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; + const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff}; + + if ((byte_seq[0] & 0x01) && + (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1)) + return PACKET_TYPE_UNICAST; + else if (!memcmp(byte_seq, bc_mac, 4)) + return PACKET_TYPE_BROADCAST; + else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && + byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) || + (!memcmp(byte_seq, ipv6_mc_mac, 3) && + byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3)) + return PACKET_TYPE_MULTICAST; + + return 0; +} + +static int +mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv, + struct cfg80211_coalesce_rules *crule, + struct mwifiex_coalesce_rule *mrule) +{ + u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1]; + struct filt_field_param *param; + int i; + + mrule->max_coalescing_delay = crule->delay; + + param = mrule->params; + + for (i = 0; i < crule->n_patterns; i++) { + memset(byte_seq, 0, sizeof(byte_seq)); + if (!mwifiex_is_pattern_supported(&crule->patterns[i], + byte_seq, + MWIFIEX_COALESCE_MAX_BYTESEQ)) { + dev_err(priv->adapter->dev, "Pattern not supported\n"); + return -EOPNOTSUPP; + } + + if (!crule->patterns[i].pkt_offset) { + u8 pkt_type; + + pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq); + if (pkt_type && mrule->pkt_type) { + dev_err(priv->adapter->dev, + "Multiple packet types not allowed\n"); + return -EOPNOTSUPP; + } else if (pkt_type) { + mrule->pkt_type = pkt_type; + continue; + } + } + + if (crule->condition == NL80211_COALESCE_CONDITION_MATCH) + param->operation = RECV_FILTER_MATCH_TYPE_EQ; + else + param->operation = RECV_FILTER_MATCH_TYPE_NE; + + param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ]; + memcpy(param->operand_byte_stream, byte_seq, + param->operand_len); + param->offset = crule->patterns[i].pkt_offset; + param++; + + mrule->num_of_fields++; + } + + if (!mrule->pkt_type) { + dev_err(priv->adapter->dev, + "Packet type can not be determined\n"); + return -EOPNOTSUPP; + } + + return 0; +} + +static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, + struct cfg80211_coalesce *coalesce) +{ + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + int i, ret; + struct mwifiex_ds_coalesce_cfg coalesce_cfg; + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + + memset(&coalesce_cfg, 0, sizeof(coalesce_cfg)); + if (!coalesce) { + dev_dbg(adapter->dev, + "Disable coalesce and reset all previous rules\n"); + return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG, + HostCmd_ACT_GEN_SET, 0, + &coalesce_cfg, true); + } + + coalesce_cfg.num_of_rules = coalesce->n_rules; + for (i = 0; i < coalesce->n_rules; i++) { + ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i], + &coalesce_cfg.rule[i]); + if (ret) { + dev_err(priv->adapter->dev, + "Recheck the patterns provided for rule %d\n", + i + 1); + return ret; + } + } + + return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG, + HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true); +} + +/* cfg80211 ops handler for tdls_mgmt. + * Function prepares TDLS action frame packets and forwards them to FW + */ +static int +mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *extra_ies, size_t extra_ies_len) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + int ret; + + if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) + return -ENOTSUPP; + + /* make sure we are in station mode and connected */ + if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) + return -ENOTSUPP; + + switch (action_code) { + case WLAN_TDLS_SETUP_REQUEST: + dev_dbg(priv->adapter->dev, + "Send TDLS Setup Request to %pM status_code=%d\n", peer, + status_code); + ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, + dialog_token, status_code, + extra_ies, extra_ies_len); + break; + case WLAN_TDLS_SETUP_RESPONSE: + dev_dbg(priv->adapter->dev, + "Send TDLS Setup Response to %pM status_code=%d\n", + peer, status_code); + ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, + dialog_token, status_code, + extra_ies, extra_ies_len); + break; + case WLAN_TDLS_SETUP_CONFIRM: + dev_dbg(priv->adapter->dev, + "Send TDLS Confirm to %pM status_code=%d\n", peer, + status_code); + ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, + dialog_token, status_code, + extra_ies, extra_ies_len); + break; + case WLAN_TDLS_TEARDOWN: + dev_dbg(priv->adapter->dev, "Send TDLS Tear down to %pM\n", + peer); + ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, + dialog_token, status_code, + extra_ies, extra_ies_len); + break; + case WLAN_TDLS_DISCOVERY_REQUEST: + dev_dbg(priv->adapter->dev, + "Send TDLS Discovery Request to %pM\n", peer); + ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, + dialog_token, status_code, + extra_ies, extra_ies_len); + break; + case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: + dev_dbg(priv->adapter->dev, + "Send TDLS Discovery Response to %pM\n", peer); + ret = mwifiex_send_tdls_action_frame(priv, peer, action_code, + dialog_token, status_code, + extra_ies, extra_ies_len); + break; + default: + dev_warn(priv->adapter->dev, + "Unknown TDLS mgmt/action frame %pM\n", peer); + ret = -EINVAL; + break; + } + + return ret; +} + +static int +mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation action) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) || + !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) + return -ENOTSUPP; + + /* make sure we are in station mode and connected */ + if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) + return -ENOTSUPP; + + dev_dbg(priv->adapter->dev, + "TDLS peer=%pM, oper=%d\n", peer, action); + + switch (action) { + case NL80211_TDLS_ENABLE_LINK: + action = MWIFIEX_TDLS_ENABLE_LINK; + break; + case NL80211_TDLS_DISABLE_LINK: + action = MWIFIEX_TDLS_DISABLE_LINK; + break; + case NL80211_TDLS_TEARDOWN: + /* shouldn't happen!*/ + dev_warn(priv->adapter->dev, + "tdls_oper: teardown from driver not supported\n"); + return -EINVAL; + case NL80211_TDLS_SETUP: + /* shouldn't happen!*/ + dev_warn(priv->adapter->dev, + "tdls_oper: setup from driver not supported\n"); + return -EINVAL; + case NL80211_TDLS_DISCOVERY_REQ: + /* shouldn't happen!*/ + dev_warn(priv->adapter->dev, + "tdls_oper: discovery from driver not supported\n"); + return -EINVAL; + default: + dev_err(priv->adapter->dev, + "tdls_oper: operation not supported\n"); + return -ENOTSUPP; + } + + return mwifiex_tdls_oper(priv, peer, action); +} + +static int +mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac, struct station_parameters *params) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + return -ENOTSUPP; + + /* make sure we are in station mode and connected */ + if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected) + return -ENOTSUPP; + + return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK); +} + +static int +mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + int ret; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + /* we support change_station handler only for TDLS peers*/ + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + return -ENOTSUPP; + + /* make sure we are in station mode and connected */ + if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected) + return -ENOTSUPP; + + priv->sta_params = params; + + ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK); + priv->sta_params = NULL; + + return ret; +} + /* station cfg80211 operations */ static struct cfg80211_ops mwifiex_cfg80211_ops = { .add_virtual_intf = mwifiex_add_virtual_intf, @@ -2476,12 +2822,17 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .resume = mwifiex_cfg80211_resume, .set_wakeup = mwifiex_cfg80211_set_wakeup, #endif + .set_coalesce = mwifiex_cfg80211_set_coalesce, + .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, + .tdls_oper = mwifiex_cfg80211_tdls_oper, + .add_station = mwifiex_cfg80211_add_station, + .change_station = mwifiex_cfg80211_change_station, }; #ifdef CONFIG_PM static const struct wiphy_wowlan_support mwifiex_wowlan_support = { .flags = WIPHY_WOWLAN_MAGIC_PKT, - .n_patterns = MWIFIEX_MAX_FILTERS, + .n_patterns = MWIFIEX_MEF_MAX_FILTERS, .pattern_min_len = 1, .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, @@ -2499,6 +2850,15 @@ static bool mwifiex_is_valid_alpha2(const char *alpha2) return false; } +static const struct wiphy_coalesce_support mwifiex_coalesce_support = { + .n_rules = MWIFIEX_COALESCE_MAX_RULES, + .max_delay = MWIFIEX_MAX_COALESCING_DELAY, + .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS, + .pattern_min_len = 1, + .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, + .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, +}; + /* * This function registers the device with CFG802.11 subsystem. * @@ -2514,6 +2874,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) struct wiphy *wiphy; struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; u8 *country_code; + u32 thr, retry; /* create a new wiphy for use with cfg80211 */ wiphy = wiphy_new(&mwifiex_cfg80211_ops, @@ -2550,16 +2911,24 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | - WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_STRICT_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) + wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | + WIPHY_FLAG_TDLS_EXTERNAL_SETUP; + + wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG | + REGULATORY_STRICT_REG; + wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); #ifdef CONFIG_PM wiphy->wowlan = &mwifiex_wowlan_support; #endif + wiphy->coalesce = &mwifiex_coalesce_support; + wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; @@ -2569,7 +2938,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->features |= NL80211_FEATURE_HT_IBSS | NL80211_FEATURE_INACTIVITY_TIMER | - NL80211_FEATURE_LOW_PRIORITY_SCAN; + NL80211_FEATURE_LOW_PRIORITY_SCAN | + NL80211_FEATURE_NEED_OBSS_SCAN; /* Reserve space for mwifiex specific private data for BSS */ wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); @@ -2600,6 +2970,19 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) country_code); } + mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true); + wiphy->frag_threshold = thr; + mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true); + wiphy->rts_threshold = thr; + mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true); + wiphy->retry_short = (u8) retry; + mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true); + wiphy->retry_long = (u8) retry; + adapter->wiphy = wiphy; return ret; } |
