X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?p=kvmfornfv.git;a=blobdiff_plain;f=kernel%2Fdrivers%2Fnet%2Fwireless%2Fmwifiex%2Fcfg80211.c;h=4073116e6e9fa8915c9fd4d35d932ccd5f3f2a08;hp=bf9020ff2d33cf1cf9dc2c044f06a403b655e593;hb=e09b41010ba33a20a87472ee821fa407a5b8da36;hpb=f93b97fd65072de626c074dbe099a1fff05ce060 diff --git a/kernel/drivers/net/wireless/mwifiex/cfg80211.c b/kernel/drivers/net/wireless/mwifiex/cfg80211.c index bf9020ff2..4073116e6 100644 --- a/kernel/drivers/net/wireless/mwifiex/cfg80211.c +++ b/kernel/drivers/net/wireless/mwifiex/cfg80211.c @@ -19,6 +19,7 @@ #include "cfg80211.h" #include "main.h" +#include "11n.h" static char *reg_alpha2; module_param(reg_alpha2, charp, 0); @@ -34,12 +35,38 @@ static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { }, }; -static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = { +static const struct ieee80211_iface_combination +mwifiex_iface_comb_ap_sta = { .limits = mwifiex_ap_sta_limits, .num_different_channels = 1, .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), .max_interfaces = MWIFIEX_MAX_BSS_NUM, .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40), +}; + +static const struct ieee80211_iface_combination +mwifiex_iface_comb_ap_sta_vht = { + .limits = mwifiex_ap_sta_limits, + .num_different_channels = 1, + .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), + .max_interfaces = MWIFIEX_MAX_BSS_NUM, + .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), +}; + +static const struct +ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = { + .limits = mwifiex_ap_sta_limits, + .num_different_channels = 2, + .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), + .max_interfaces = MWIFIEX_MAX_BSS_NUM, + .beacon_int_infra_match = true, }; /* @@ -67,6 +94,22 @@ u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) } } +/* This function maps IEEE HT secondary channel type to NL80211 channel type + */ +u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset) +{ + switch (second_chan_offset) { + case IEEE80211_HT_PARAM_CHA_SEC_NONE: + return NL80211_CHAN_HT20; + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + return NL80211_CHAN_HT40PLUS; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + return NL80211_CHAN_HT40MINUS; + default: + return NL80211_CHAN_HT20; + } +} + /* * This function checks whether WEP is set. */ @@ -104,11 +147,11 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, const u8 *peer_mac = pairwise ? mac_addr : bc_mac; if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) { - wiphy_err(wiphy, "deleting the crypto keys\n"); + mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n"); return -EFAULT; } - wiphy_dbg(wiphy, "info: crypto keys deleted\n"); + mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n"); return 0; } @@ -163,7 +206,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); if (!buf || !len) { - wiphy_err(wiphy, "invalid buffer and length\n"); + mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n"); return -EFAULT; } @@ -172,8 +215,8 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ieee80211_is_probe_resp(mgmt->frame_control)) { /* Since we support offload probe resp, we need to skip probe * resp in AP or GO mode */ - wiphy_dbg(wiphy, - "info: skip to send probe resp in AP or GO mode\n"); + mwifiex_dbg(priv->adapter, INFO, + "info: skip to send probe resp in AP or GO mode\n"); return 0; } @@ -183,7 +226,8 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, pkt_len + sizeof(pkt_len)); if (!skb) { - wiphy_err(wiphy, "allocate skb failed for management frame\n"); + mwifiex_dbg(priv->adapter, ERROR, + "allocate skb failed for management frame\n"); return -ENOMEM; } @@ -206,7 +250,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, mwifiex_queue_tx_pkt(priv, skb); - wiphy_dbg(wiphy, "info: management frame transmitted\n"); + mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n"); return 0; } @@ -231,7 +275,7 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, 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"); + mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n"); } } @@ -248,13 +292,14 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, int ret; if (!chan || !cookie) { - wiphy_err(wiphy, "Invalid parameter for ROC\n"); + mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n"); return -EINVAL; } if (priv->roc_cfg.cookie) { - wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llx\n", - priv->roc_cfg.cookie); + mwifiex_dbg(priv->adapter, INFO, + "info: ongoing ROC, cookie = 0x%llx\n", + priv->roc_cfg.cookie); return -EBUSY; } @@ -269,7 +314,8 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_ATOMIC); - wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie); + mwifiex_dbg(priv->adapter, INFO, + "info: ROC, cookie = 0x%llx\n", *cookie); } return ret; @@ -298,7 +344,8 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg)); - wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie); + mwifiex_dbg(priv->adapter, INFO, + "info: cancel ROC, cookie = 0x%llx\n", cookie); } return ret; @@ -344,8 +391,8 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, u32 ps_mode; if (timeout) - wiphy_dbg(wiphy, - "info: ignore timeout value for IEEE Power Save\n"); + mwifiex_dbg(priv->adapter, INFO, + "info: ignore timeout value for IEEE Power Save\n"); ps_mode = enabled; @@ -370,7 +417,7 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, priv->wep_key_curr_index = key_index; } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, NULL, 0)) { - wiphy_err(wiphy, "set default Tx key index\n"); + mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n"); return -EFAULT; } @@ -407,7 +454,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, if (mwifiex_set_encode(priv, params, params->key, params->key_len, key_index, peer_mac, 0)) { - wiphy_err(wiphy, "crypto keys added\n"); + mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n"); return -EFAULT; } @@ -421,7 +468,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, * - Country codes * - Sub bands (first channel, number of channels, maximum Tx power) */ -static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) +int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) { u8 no_of_triplet = 0; struct ieee80211_country_ie_triplet *t; @@ -442,7 +489,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) band = mwifiex_band_to_radio_type(adapter->config_bands); if (!wiphy->bands[band]) { - wiphy_err(wiphy, "11D: setting domain info in FW\n"); + mwifiex_dbg(adapter, ERROR, + "11D: setting domain info in FW\n"); return -1; } @@ -493,7 +541,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) 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"); + mwifiex_dbg(adapter, INFO, + "11D: setting domain info in FW\n"); return -1; } @@ -516,9 +565,9 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy, 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]); + mwifiex_dbg(adapter, INFO, + "info: cfg80211 regulatory domain callback for %c%c\n", + request->alpha2[0], request->alpha2[1]); switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: @@ -527,8 +576,9 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy, case NL80211_REGDOM_SET_BY_COUNTRY_IE: break; default: - wiphy_err(wiphy, "unknown regdom initiator: %d\n", - request->initiator); + mwifiex_dbg(adapter, ERROR, + "unknown regdom initiator: %d\n", + request->initiator); return; } @@ -597,8 +647,8 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) switch (priv->bss_role) { case MWIFIEX_BSS_ROLE_UAP: if (priv->bss_started) { - dev_err(adapter->dev, - "cannot change wiphy params when bss started"); + mwifiex_dbg(adapter, ERROR, + "cannot change wiphy params when bss started"); return -EINVAL; } @@ -622,15 +672,16 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) kfree(bss_cfg); if (ret) { - wiphy_err(wiphy, "Failed to set wiphy phy params\n"); + mwifiex_dbg(adapter, ERROR, + "Failed to set wiphy phy params\n"); return ret; } break; case MWIFIEX_BSS_ROLE_STA: if (priv->media_connected) { - dev_err(adapter->dev, - "cannot change wiphy params when connected"); + mwifiex_dbg(adapter, ERROR, + "cannot change wiphy params when connected"); return -EINVAL; } if (changed & WIPHY_PARAM_RTS_THRESHOLD) { @@ -724,8 +775,8 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, HostCmd_ACT_GEN_SET, 0, &priv->mgmt_frame_mask, false)) { - dev_warn(priv->adapter->dev, - "could not unregister mgmt frame rx\n"); + mwifiex_dbg(adapter, ERROR, + "could not unregister mgmt frame rx\n"); return -1; } @@ -780,18 +831,21 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, priv->bss_type = MWIFIEX_BSS_TYPE_STA; break; case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: priv->bss_role = MWIFIEX_BSS_ROLE_STA; priv->bss_type = MWIFIEX_BSS_TYPE_P2P; break; + case NL80211_IFTYPE_P2P_GO: + priv->bss_role = MWIFIEX_BSS_ROLE_UAP; + priv->bss_type = MWIFIEX_BSS_TYPE_P2P; + break; case NL80211_IFTYPE_AP: priv->bss_type = MWIFIEX_BSS_TYPE_UAP; priv->bss_role = MWIFIEX_BSS_ROLE_UAP; break; default: - dev_err(priv->adapter->dev, - "%s: changing to %d not supported\n", - dev->name, type); + mwifiex_dbg(adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); return -EOPNOTSUPP; } @@ -824,12 +878,13 @@ mwifiex_change_vif_to_p2p(struct net_device *dev, if (adapter->curr_iface_comb.p2p_intf == adapter->iface_limit.p2p_intf) { - dev_err(adapter->dev, - "cannot create multiple P2P ifaces\n"); + mwifiex_dbg(adapter, ERROR, + "cannot create multiple P2P ifaces\n"); return -1; } - dev_dbg(priv->adapter->dev, "%s: changing role to p2p\n", dev->name); + mwifiex_dbg(adapter, INFO, + "%s: changing role to p2p\n", dev->name); if (mwifiex_deinit_priv_params(priv)) return -1; @@ -846,9 +901,9 @@ mwifiex_change_vif_to_p2p(struct net_device *dev, return -EFAULT; break; default: - dev_err(priv->adapter->dev, - "%s: changing to %d not supported\n", - dev->name, type); + mwifiex_dbg(adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); return -EOPNOTSUPP; } @@ -897,17 +952,17 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, curr_iftype != NL80211_IFTYPE_P2P_GO) && (adapter->curr_iface_comb.sta_intf == adapter->iface_limit.sta_intf)) { - dev_err(adapter->dev, - "cannot create multiple station/adhoc ifaces\n"); + mwifiex_dbg(adapter, ERROR, + "cannot create multiple station/adhoc ifaces\n"); return -1; } if (type == NL80211_IFTYPE_STATION) - dev_notice(adapter->dev, - "%s: changing role to station\n", dev->name); + mwifiex_dbg(adapter, INFO, + "%s: changing role to station\n", dev->name); else - dev_notice(adapter->dev, - "%s: changing role to adhoc\n", dev->name); + mwifiex_dbg(adapter, INFO, + "%s: changing role to adhoc\n", dev->name); if (mwifiex_deinit_priv_params(priv)) return -1; @@ -954,12 +1009,13 @@ mwifiex_change_vif_to_ap(struct net_device *dev, if (adapter->curr_iface_comb.uap_intf == adapter->iface_limit.uap_intf) { - dev_err(adapter->dev, - "cannot create multiple AP ifaces\n"); + mwifiex_dbg(adapter, ERROR, + "cannot create multiple AP ifaces\n"); return -1; } - dev_notice(adapter->dev, "%s: changing role to AP\n", dev->name); + mwifiex_dbg(adapter, INFO, + "%s: changing role to AP\n", dev->name); if (mwifiex_deinit_priv_params(priv)) return -1; @@ -1020,12 +1076,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return mwifiex_change_vif_to_ap(dev, curr_iftype, type, flags, params); case NL80211_IFTYPE_UNSPECIFIED: - wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); + mwifiex_dbg(priv->adapter, INFO, + "%s: kept type as IBSS\n", dev->name); case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ return 0; default: - wiphy_err(wiphy, "%s: changing to %d not supported\n", - dev->name, type); + mwifiex_dbg(priv->adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); return -EOPNOTSUPP; } break; @@ -1048,12 +1106,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return mwifiex_change_vif_to_ap(dev, curr_iftype, type, flags, params); case NL80211_IFTYPE_UNSPECIFIED: - wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); + mwifiex_dbg(priv->adapter, INFO, + "%s: kept type as STA\n", dev->name); case NL80211_IFTYPE_STATION: /* This shouldn't happen */ return 0; default: - wiphy_err(wiphy, "%s: changing to %d not supported\n", - dev->name, type); + mwifiex_dbg(priv->adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); return -EOPNOTSUPP; } break; @@ -1070,12 +1130,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return mwifiex_change_vif_to_p2p(dev, curr_iftype, type, flags, params); case NL80211_IFTYPE_UNSPECIFIED: - wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); + mwifiex_dbg(priv->adapter, INFO, + "%s: kept type as AP\n", dev->name); case NL80211_IFTYPE_AP: /* This shouldn't happen */ return 0; default: - wiphy_err(wiphy, "%s: changing to %d not supported\n", - dev->name, type); + mwifiex_dbg(priv->adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); return -EOPNOTSUPP; } break; @@ -1083,8 +1145,10 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, case NL80211_IFTYPE_P2P_GO: switch (type) { case NL80211_IFTYPE_STATION: - if (mwifiex_cfg80211_init_p2p_client(priv)) + if (mwifiex_cfg80211_deinit_p2p(priv)) return -EFAULT; + priv->adapter->curr_iface_comb.p2p_intf--; + priv->adapter->curr_iface_comb.sta_intf++; dev->ieee80211_ptr->iftype = type; break; case NL80211_IFTYPE_ADHOC: @@ -1100,19 +1164,22 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return mwifiex_change_vif_to_ap(dev, curr_iftype, type, flags, params); case NL80211_IFTYPE_UNSPECIFIED: - wiphy_warn(wiphy, "%s: kept type as P2P\n", dev->name); + mwifiex_dbg(priv->adapter, INFO, + "%s: kept type as P2P\n", dev->name); case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: return 0; default: - wiphy_err(wiphy, "%s: changing to %d not supported\n", - dev->name, type); + mwifiex_dbg(priv->adapter, ERROR, + "%s: changing to %d not supported\n", + dev->name, type); return -EOPNOTSUPP; } break; default: - wiphy_err(wiphy, "%s: unknown iftype: %d\n", - dev->name, dev->ieee80211_ptr->iftype); + mwifiex_dbg(priv->adapter, ERROR, + "%s: unknown iftype: %d\n", + dev->name, dev->ieee80211_ptr->iftype); return -EOPNOTSUPP; } @@ -1194,6 +1261,7 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, */ static int mwifiex_dump_station_info(struct mwifiex_private *priv, + struct mwifiex_sta_node *node, struct station_info *sinfo) { u32 rate; @@ -1203,15 +1271,41 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, BIT(NL80211_STA_INFO_TX_BITRATE) | BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG); + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { + if (!node) + return -ENOENT; + + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) | + BIT(NL80211_STA_INFO_TX_FAILED); + sinfo->inactive_time = + jiffies_to_msecs(jiffies - node->stats.last_rx); + + sinfo->signal = node->stats.rssi; + sinfo->signal_avg = node->stats.rssi; + sinfo->rx_bytes = node->stats.rx_bytes; + sinfo->tx_bytes = node->stats.tx_bytes; + sinfo->rx_packets = node->stats.rx_packets; + sinfo->tx_packets = node->stats.tx_packets; + sinfo->tx_failed = node->stats.tx_failed; + + mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo, + &sinfo->txrate); + sinfo->txrate.legacy = node->stats.last_tx_rate * 5; + + return 0; + } + /* Get signal information from the firmware */ 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"); + mwifiex_dbg(priv->adapter, ERROR, + "failed to get signal information\n"); return -EFAULT; } if (mwifiex_drv_get_data_rate(priv, &rate)) { - dev_err(priv->adapter->dev, "getting data rate\n"); + mwifiex_dbg(priv->adapter, ERROR, + "getting data rate error\n"); return -EFAULT; } @@ -1267,7 +1361,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) return -ENOENT; - return mwifiex_dump_station_info(priv, sinfo); + return mwifiex_dump_station_info(priv, NULL, sinfo); } /* @@ -1278,13 +1372,29 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + static struct mwifiex_sta_node *node; - if (!priv->media_connected || idx) - return -ENOENT; + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && + priv->media_connected && idx == 0) { + ether_addr_copy(mac, priv->cfg_bssid); + return mwifiex_dump_station_info(priv, NULL, sinfo); + } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { + mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST, + HostCmd_ACT_GEN_GET, 0, NULL, true); + + if (node && (&node->list == &priv->sta_list)) { + node = NULL; + return -ENOENT; + } - memcpy(mac, priv->cfg_bssid, ETH_ALEN); + node = list_prepare_entry(node, &priv->sta_list, list); + list_for_each_entry_continue(node, &priv->sta_list, list) { + ether_addr_copy(mac, node->mac_addr); + return mwifiex_dump_station_info(priv, node, sinfo); + } + } - return mwifiex_dump_station_info(priv, sinfo); + return -ENOENT; } static int @@ -1295,7 +1405,7 @@ mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats; enum ieee80211_band band; - dev_dbg(priv->adapter->dev, "dump_survey idx=%d\n", idx); + mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx); memset(survey, 0, sizeof(struct survey_info)); @@ -1472,8 +1582,8 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct mwifiex_adapter *adapter = priv->adapter; if (!priv->media_connected) { - dev_err(adapter->dev, - "Can not set Tx data rate in disconnected state\n"); + mwifiex_dbg(adapter, ERROR, + "Can not set Tx data rate in disconnected state\n"); return -EINVAL; } @@ -1556,17 +1666,20 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) { - wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__); + mwifiex_dbg(priv->adapter, ERROR, + "%s: bss_type mismatched\n", __func__); return -EINVAL; } if (!priv->bss_started) { - wiphy_err(wiphy, "%s: bss not started\n", __func__); + mwifiex_dbg(priv->adapter, ERROR, + "%s: bss not started\n", __func__); return -EINVAL; } if (mwifiex_set_mgmt_ies(priv, data)) { - wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__); + mwifiex_dbg(priv->adapter, ERROR, + "%s: setting mgmt ies failed\n", __func__); return -EFAULT; } @@ -1594,7 +1707,8 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, if (!params->mac || is_broadcast_ether_addr(params->mac)) return 0; - wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, params->mac); + mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n", + __func__, params->mac); eth_zero_addr(deauth_mac); @@ -1687,17 +1801,30 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) mwifiex_abort_cac(priv); if (mwifiex_del_mgmt_ies(priv)) - wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to delete mgmt IEs!\n"); priv->ap_11n_enabled = 0; memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg)); 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"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to stop the BSS\n"); + return -1; + } + + if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, + HostCmd_ACT_GEN_SET, 0, NULL, true)) { + mwifiex_dbg(priv->adapter, ERROR, + "Failed to reset BSS\n"); return -1; } + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); + return 0; } @@ -1751,12 +1878,13 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, return -EINVAL; } - mwifiex_uap_set_channel(bss_cfg, params->chandef); + mwifiex_uap_set_channel(priv, bss_cfg, params->chandef); mwifiex_set_uap_rates(bss_cfg, params); if (mwifiex_set_secure_params(priv, bss_cfg, params)) { kfree(bss_cfg); - wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to parse secuirty parameters!\n"); return -1; } @@ -1775,20 +1903,25 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, mwifiex_set_wmm_params(priv, bss_cfg, params); + if (mwifiex_is_11h_active(priv)) + mwifiex_set_tpc_params(priv, bss_cfg, params); + if (mwifiex_is_11h_active(priv) && !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, priv->bss_mode)) { - dev_dbg(priv->adapter->dev, "Disable 11h extensions in FW\n"); + mwifiex_dbg(priv->adapter, INFO, + "Disable 11h extensions in FW\n"); if (mwifiex_11h_activate(priv, false)) { - dev_err(priv->adapter->dev, - "Failed to disable 11h extensions!!"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to disable 11h extensions!!"); return -1; } - priv->state_11h.is_11h_active = true; + priv->state_11h.is_11h_active = false; } if (mwifiex_config_start_uap(priv, bss_cfg)) { - wiphy_err(wiphy, "Failed to start AP\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to start AP\n"); kfree(bss_cfg); return -1; } @@ -1796,6 +1929,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) return -1; + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter); + memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); kfree(bss_cfg); return 0; @@ -1816,8 +1953,9 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, if (mwifiex_deauthenticate(priv, NULL)) return -EFAULT; - wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" - " reason code %d\n", priv->cfg_bssid, reason_code); + mwifiex_dbg(priv->adapter, MSG, + "info: successfully disconnected from %pM:\t" + "reason code %d\n", priv->cfg_bssid, reason_code); eth_zero_addr(priv->cfg_bssid); priv->hs2_enabled = false; @@ -1864,8 +2002,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) CFG80211_BSS_FTYPE_UNKNOWN, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, 0, ie_buf, ie_len, 0, GFP_KERNEL); - cfg80211_put_bss(priv->wdev.wiphy, bss); - memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); + if (bss) { + cfg80211_put_bss(priv->wdev.wiphy, bss); + ether_addr_copy(priv->cfg_bssid, bss_info.bssid); + } return 0; } @@ -1899,13 +2039,13 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, req_ssid.ssid_len = ssid_len; if (ssid_len > IEEE80211_MAX_SSID_LEN) { - dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); + mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n"); return -EINVAL; } memcpy(req_ssid.ssid, ssid, ssid_len); if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) { - dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); + mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n"); return -EINVAL; } @@ -1959,9 +2099,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, if (sme->key) { if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) { - dev_dbg(priv->adapter->dev, - "info: setting wep encryption" - " with key len %d\n", sme->key_len); + mwifiex_dbg(priv->adapter, INFO, + "info: setting wep encryption\t" + "with key len %d\n", sme->key_len); priv->wep_key_curr_index = sme->key_idx; ret = mwifiex_set_encode(priv, NULL, sme->key, sme->key_len, sme->key_idx, @@ -1978,7 +2118,7 @@ done: if (is_scanning_required) { /* Do specific SSID scanning */ if (mwifiex_request_scan(priv, &req_ssid)) { - dev_err(priv->adapter->dev, "scan error\n"); + mwifiex_dbg(priv->adapter, ERROR, "scan error\n"); return -EFAULT; } } @@ -1997,15 +2137,15 @@ done: if (!bss) { if (is_scanning_required) { - dev_warn(priv->adapter->dev, - "assoc: requested bss not found in scan results\n"); + mwifiex_dbg(priv->adapter, WARN, + "assoc: requested bss not found in scan results\n"); break; } is_scanning_required = 1; } else { - dev_dbg(priv->adapter->dev, - "info: trying to associate to '%s' bssid %pM\n", - (char *) req_ssid.ssid, bss->bssid); + mwifiex_dbg(priv->adapter, MSG, + "info: trying to associate to '%s' bssid %pM\n", + (char *)req_ssid.ssid, bss->bssid); memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); break; } @@ -2041,26 +2181,29 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, int ret; if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) { - wiphy_err(wiphy, - "%s: reject infra assoc request in non-STA role\n", - dev->name); + mwifiex_dbg(adapter, ERROR, + "%s: reject infra assoc request in non-STA role\n", + dev->name); return -EINVAL; } if (priv->wdev.current_bss) { - wiphy_warn(wiphy, "%s: already connected\n", dev->name); + mwifiex_dbg(adapter, ERROR, + "%s: already connected\n", dev->name); return -EALREADY; } if (adapter->surprise_removed || adapter->is_cmd_timedout) { - wiphy_err(wiphy, - "%s: Ignore connection. Card removed or FW in bad state\n", - dev->name); + mwifiex_dbg(adapter, ERROR, + "%s: Ignore connection.\t" + "Card removed or FW in bad state\n", + dev->name); return -EFAULT; } - wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", - (char *) sme->ssid, sme->bssid); + mwifiex_dbg(adapter, INFO, + "info: Trying to associate to %s and bssid %pM\n", + (char *)sme->ssid, sme->bssid); ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); @@ -2068,17 +2211,17 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, NULL, 0, WLAN_STATUS_SUCCESS, GFP_KERNEL); - dev_dbg(priv->adapter->dev, - "info: associated to bssid %pM successfully\n", - priv->cfg_bssid); + mwifiex_dbg(priv->adapter, MSG, + "info: associated to bssid %pM successfully\n", + priv->cfg_bssid); if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && priv->adapter->auto_tdls && priv->bss_type == MWIFIEX_BSS_TYPE_STA) mwifiex_setup_auto_tdls_timer(priv); } else { - dev_dbg(priv->adapter->dev, - "info: association to bssid %pM failed\n", - priv->cfg_bssid); + mwifiex_dbg(priv->adapter, ERROR, + "info: association to bssid %pM failed\n", + priv->cfg_bssid); eth_zero_addr(priv->cfg_bssid); if (ret > 0) @@ -2105,7 +2248,6 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, static int mwifiex_set_ibss_params(struct mwifiex_private *priv, struct cfg80211_ibss_params *params) { - struct wiphy *wiphy = priv->wdev.wiphy; struct mwifiex_adapter *adapter = priv->adapter; int index = 0, i; u8 config_bands = 0; @@ -2162,8 +2304,10 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, priv->adhoc_channel = ieee80211_frequency_to_channel( params->chandef.chan->center_freq); - wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n", - config_bands, priv->adhoc_channel, adapter->sec_chan_offset); + mwifiex_dbg(adapter, INFO, + "info: set ibss band %d, chan %d, chan offset %d\n", + config_bands, priv->adhoc_channel, + adapter->sec_chan_offset); return 0; } @@ -2182,13 +2326,15 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, int ret = 0; if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { - wiphy_err(wiphy, "request to join ibss received " - "when station is not in ibss mode\n"); + mwifiex_dbg(priv->adapter, ERROR, + "request to join ibss received\t" + "when station is not in ibss mode\n"); goto done; } - wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", - (char *) params->ssid, params->bssid); + mwifiex_dbg(priv->adapter, MSG, + "info: trying to join to %s and bssid %pM\n", + (char *)params->ssid, params->bssid); mwifiex_set_ibss_params(priv, params); @@ -2200,12 +2346,12 @@ done: if (!ret) { 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); + mwifiex_dbg(priv->adapter, MSG, + "info: joined/created adhoc network with bssid\t" + "%pM successfully\n", priv->cfg_bssid); } else { - dev_dbg(priv->adapter->dev, - "info: failed creating/joining adhoc network\n"); + mwifiex_dbg(priv->adapter, ERROR, + "info: failed creating/joining adhoc network\n"); } return ret; @@ -2222,8 +2368,8 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", - priv->cfg_bssid); + mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n", + priv->cfg_bssid); if (mwifiex_deauthenticate(priv, NULL)) return -EFAULT; @@ -2236,7 +2382,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) * CFG802.11 operation handler for scan request. * * This function issues a scan request to the firmware based upon - * the user specified scan configuration. On successfull completion, + * the user specified scan configuration. On successful completion, * it also informs the results. */ static int @@ -2250,13 +2396,15 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct ieee_types_header *ie; struct mwifiex_user_scan_cfg *user_scan_cfg; - wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); + mwifiex_dbg(priv->adapter, CMD, + "info: received scan request on %s\n", dev->name); /* Block scan request if scan operation or scan cleanup when interface * is disabled is in process */ if (priv->scan_request || priv->scan_aborting) { - dev_err(priv->adapter->dev, "cmd: Scan already in process..\n"); + mwifiex_dbg(priv->adapter, WARN, + "cmd: Scan already in process..\n"); return -EBUSY; } @@ -2308,7 +2456,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ret = mwifiex_scan_networks(priv, user_scan_cfg); kfree(user_scan_cfg); if (ret) { - dev_err(priv->adapter->dev, "scan failed: %d\n", ret); + mwifiex_dbg(priv->adapter, ERROR, + "scan failed: %d\n", ret); priv->scan_aborting = false; priv->scan_request = NULL; return ret; @@ -2454,15 +2603,15 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, case NL80211_IFTYPE_ADHOC: if (adapter->curr_iface_comb.sta_intf == adapter->iface_limit.sta_intf) { - wiphy_err(wiphy, - "cannot create multiple sta/adhoc ifaces\n"); + mwifiex_dbg(adapter, ERROR, + "cannot create multiple sta/adhoc ifaces\n"); return ERR_PTR(-EINVAL); } priv = mwifiex_get_unused_priv(adapter); if (!priv) { - wiphy_err(wiphy, - "could not get free private struct\n"); + mwifiex_dbg(adapter, ERROR, + "could not get free private struct\n"); return ERR_PTR(-EFAULT); } @@ -2478,21 +2627,21 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; priv->bss_priority = 0; priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_num = 0; + priv->bss_num = adapter->curr_iface_comb.sta_intf; break; case NL80211_IFTYPE_AP: if (adapter->curr_iface_comb.uap_intf == adapter->iface_limit.uap_intf) { - wiphy_err(wiphy, - "cannot create multiple AP ifaces\n"); + mwifiex_dbg(adapter, ERROR, + "cannot create multiple AP ifaces\n"); return ERR_PTR(-EINVAL); } priv = mwifiex_get_unused_priv(adapter); if (!priv) { - wiphy_err(wiphy, - "could not get free private struct\n"); + mwifiex_dbg(adapter, ERROR, + "could not get free private struct\n"); return ERR_PTR(-EFAULT); } @@ -2504,22 +2653,22 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_priority = 0; priv->bss_role = MWIFIEX_BSS_ROLE_UAP; priv->bss_started = 0; - priv->bss_num = 0; + priv->bss_num = adapter->curr_iface_comb.uap_intf; priv->bss_mode = type; break; case NL80211_IFTYPE_P2P_CLIENT: if (adapter->curr_iface_comb.p2p_intf == adapter->iface_limit.p2p_intf) { - wiphy_err(wiphy, - "cannot create multiple P2P ifaces\n"); + mwifiex_dbg(adapter, ERROR, + "cannot create multiple P2P ifaces\n"); return ERR_PTR(-EINVAL); } priv = mwifiex_get_unused_priv(adapter); if (!priv) { - wiphy_err(wiphy, - "could not get free private struct\n"); + mwifiex_dbg(adapter, ERROR, + "could not get free private struct\n"); return ERR_PTR(-EFAULT); } @@ -2540,7 +2689,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_priority = MWIFIEX_BSS_ROLE_STA; priv->bss_role = MWIFIEX_BSS_ROLE_STA; priv->bss_started = 0; - priv->bss_num = 0; + priv->bss_num = adapter->curr_iface_comb.p2p_intf; if (mwifiex_cfg80211_init_p2p_client(priv)) { memset(&priv->wdev, 0, sizeof(priv->wdev)); @@ -2550,7 +2699,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, break; default: - wiphy_err(wiphy, "type not supported\n"); + mwifiex_dbg(adapter, ERROR, "type not supported\n"); return ERR_PTR(-EINVAL); } @@ -2558,7 +2707,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, name_assign_type, ether_setup, IEEE80211_NUM_ACS, 1); if (!dev) { - wiphy_err(wiphy, "no memory available for netdevice\n"); + mwifiex_dbg(adapter, ERROR, + "no memory available for netdevice\n"); memset(&priv->wdev, 0, sizeof(priv->wdev)); priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; @@ -2599,7 +2749,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, /* Register network device */ if (register_netdevice(dev)) { - wiphy_err(wiphy, "cannot register virtual network device\n"); + mwifiex_dbg(adapter, ERROR, + "cannot register virtual network device\n"); free_netdev(dev); priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->netdev = NULL; @@ -2613,7 +2764,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, WQ_MEM_RECLAIM | WQ_UNBOUND, 1, name); if (!priv->dfs_cac_workqueue) { - wiphy_err(wiphy, "cannot register virtual network device\n"); + mwifiex_dbg(adapter, ERROR, + "cannot register virtual network device\n"); free_netdev(dev); priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->netdev = NULL; @@ -2628,7 +2780,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1, name); if (!priv->dfs_chan_sw_workqueue) { - wiphy_err(wiphy, "cannot register virtual network device\n"); + mwifiex_dbg(adapter, ERROR, + "cannot register virtual network device\n"); free_netdev(dev); priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->netdev = NULL; @@ -2642,7 +2795,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, sema_init(&priv->async_sem, 1); - dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); + mwifiex_dbg(adapter, INFO, + "info: %s: Marvell 802.11 Adapter\n", dev->name); #ifdef CONFIG_DEBUG_FS mwifiex_dev_debugfs_init(priv); @@ -2661,7 +2815,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, adapter->curr_iface_comb.p2p_intf++; break; default: - wiphy_err(wiphy, "type not supported\n"); + mwifiex_dbg(adapter, ERROR, "type not supported\n"); return ERR_PTR(-EINVAL); } @@ -2676,6 +2830,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); struct mwifiex_adapter *adapter = priv->adapter; + struct sk_buff *skb, *tmp; #ifdef CONFIG_DEBUG_FS mwifiex_dev_debugfs_remove(priv); @@ -2683,6 +2838,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) mwifiex_stop_net_dev_queue(priv->netdev, adapter); + skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) + mwifiex_write_data_complete(priv->adapter, skb, 0, -1); + if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); @@ -2711,17 +2869,18 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf++; + adapter->curr_iface_comb.sta_intf--; break; case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf++; + adapter->curr_iface_comb.uap_intf--; break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf++; + adapter->curr_iface_comb.p2p_intf--; break; default: - dev_err(adapter->dev, "del_virtual_intf: type not supported\n"); + mwifiex_dbg(adapter, ERROR, + "del_virtual_intf: type not supported\n"); break; } @@ -2839,8 +2998,8 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], byte_seq, MWIFIEX_MEF_MAX_BYTESEQ)) { - dev_err(priv->adapter->dev, "Pattern not supported\n"); - kfree(mef_entry); + mwifiex_dbg(priv->adapter, ERROR, + "Pattern not supported\n"); return -EOPNOTSUPP; } @@ -2922,9 +3081,12 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]); - if (wowlan->n_patterns || wowlan->magic_pkt) + if (wowlan->n_patterns || wowlan->magic_pkt) { ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg, &mef_entry[1], wowlan); + if (ret) + goto err; + } if (!mef_cfg.criteria) mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | @@ -2934,6 +3096,8 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, HostCmd_ACT_GEN_SET, 0, &mef_cfg, true); + +err: kfree(mef_entry); return ret; } @@ -2954,21 +3118,22 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, mwifiex_cancel_all_pending_cmd(adapter); if (!wowlan) { - dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); + mwifiex_dbg(adapter, ERROR, + "None of the WOWLAN triggers enabled\n"); return 0; } priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); if (!priv->media_connected) { - dev_warn(adapter->dev, - "Can not configure WOWLAN in disconnected state\n"); + mwifiex_dbg(adapter, ERROR, + "Can not configure WOWLAN in disconnected state\n"); return 0; } ret = mwifiex_set_mef_filter(priv, wowlan); if (ret) { - dev_err(adapter->dev, "Failed to set MEF filter\n"); + mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n"); return ret; } @@ -2981,7 +3146,8 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, &hs_cfg); if (ret) { - dev_err(adapter->dev, "Failed to set HS params\n"); + mwifiex_dbg(adapter, ERROR, + "Failed to set HS params\n"); return ret; } } @@ -3041,7 +3207,8 @@ mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv, if (!mwifiex_is_pattern_supported(&crule->patterns[i], byte_seq, MWIFIEX_COALESCE_MAX_BYTESEQ)) { - dev_err(priv->adapter->dev, "Pattern not supported\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Pattern not supported\n"); return -EOPNOTSUPP; } @@ -3050,8 +3217,8 @@ mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv, 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"); + mwifiex_dbg(priv->adapter, ERROR, + "Multiple packet types not allowed\n"); return -EOPNOTSUPP; } else if (pkt_type) { mrule->pkt_type = pkt_type; @@ -3074,8 +3241,8 @@ mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv, } if (!mrule->pkt_type) { - dev_err(priv->adapter->dev, - "Packet type can not be determined\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Packet type can not be determined\n"); return -EOPNOTSUPP; } @@ -3093,8 +3260,8 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, memset(&coalesce_cfg, 0, sizeof(coalesce_cfg)); if (!coalesce) { - dev_dbg(adapter->dev, - "Disable coalesce and reset all previous rules\n"); + mwifiex_dbg(adapter, WARN, + "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); @@ -3105,8 +3272,8 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, 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", + mwifiex_dbg(adapter, ERROR, + "Recheck the patterns provided for rule %d\n", i + 1); return ret; } @@ -3138,9 +3305,9 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, 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); + mwifiex_dbg(priv->adapter, MSG, + "Send TDLS Setup Request to %pM status_code=%d\n", + peer, status_code); mwifiex_add_auto_tdls_peer(priv, peer); ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, dialog_token, status_code, @@ -3148,45 +3315,45 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, break; case WLAN_TDLS_SETUP_RESPONSE: mwifiex_add_auto_tdls_peer(priv, peer); - dev_dbg(priv->adapter->dev, - "Send TDLS Setup Response to %pM status_code=%d\n", - peer, status_code); + mwifiex_dbg(priv->adapter, MSG, + "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); + mwifiex_dbg(priv->adapter, MSG, + "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); + mwifiex_dbg(priv->adapter, MSG, + "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); + mwifiex_dbg(priv->adapter, MSG, + "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); + mwifiex_dbg(priv->adapter, MSG, + "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); + mwifiex_dbg(priv->adapter, ERROR, + "Unknown TDLS mgmt/action frame %pM\n", peer); ret = -EINVAL; break; } @@ -3208,8 +3375,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, 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); + mwifiex_dbg(priv->adapter, MSG, + "TDLS peer=%pM, oper=%d\n", peer, action); switch (action) { case NL80211_TDLS_ENABLE_LINK: @@ -3220,28 +3387,94 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_TDLS_TEARDOWN: /* shouldn't happen!*/ - dev_warn(priv->adapter->dev, - "tdls_oper: teardown from driver not supported\n"); + mwifiex_dbg(priv->adapter, ERROR, + "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"); + mwifiex_dbg(priv->adapter, ERROR, + "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"); + mwifiex_dbg(priv->adapter, ERROR, + "tdls_oper: discovery from driver not supported\n"); return -EINVAL; default: - dev_err(priv->adapter->dev, - "tdls_oper: operation not supported\n"); + mwifiex_dbg(priv->adapter, ERROR, + "tdls_oper: operation not supported\n"); return -ENOTSUPP; } return mwifiex_tdls_oper(priv, peer, action); } +static int +mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr, u8 oper_class, + struct cfg80211_chan_def *chandef) +{ + struct mwifiex_sta_node *sta_ptr; + unsigned long flags; + u16 chan; + u8 second_chan_offset, band; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + sta_ptr = mwifiex_get_sta_entry(priv, addr); + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + + if (!sta_ptr) { + wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n", + __func__, addr); + return -ENOENT; + } + + if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] & + WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) { + wiphy_err(wiphy, "%pM do not support tdls cs\n", addr); + return -ENOENT; + } + + if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING || + sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) { + wiphy_err(wiphy, "channel switch is running, abort request\n"); + return -EALREADY; + } + + chan = chandef->chan->hw_value; + second_chan_offset = mwifiex_get_sec_chan_offset(chan); + band = chandef->chan->band; + mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band); + + return 0; +} + +static void +mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy, + struct net_device *dev, + const u8 *addr) +{ + struct mwifiex_sta_node *sta_ptr; + unsigned long flags; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + sta_ptr = mwifiex_get_sta_entry(priv, addr); + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + + if (!sta_ptr) { + wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n", + __func__, addr); + } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING || + sta_ptr->tdls_status == TDLS_IN_BASE_CHAN || + sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) { + wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n", + addr); + } else + mwifiex_stop_tdls_cs(priv, addr); +} + static int mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_parameters *params) @@ -3268,8 +3501,8 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); if (priv->adapter->scan_processing) { - dev_err(priv->adapter->dev, - "radar detection: scan in process...\n"); + mwifiex_dbg(priv->adapter, ERROR, + "radar detection: scan in process...\n"); return -EBUSY; } @@ -3284,8 +3517,8 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, params->beacon_csa.tail, params->beacon_csa.tail_len); if (!chsw_ie) { - dev_err(priv->adapter->dev, - "Could not parse channel switch announcement IE\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Could not parse channel switch announcement IE\n"); return -EINVAL; } @@ -3297,10 +3530,12 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, } if (mwifiex_del_mgmt_ies(priv)) - wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to delete mgmt IEs!\n"); if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon_csa)) { - wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__); + mwifiex_dbg(priv->adapter, ERROR, + "%s: setting mgmt ies failed\n", __func__); return -EFAULT; } @@ -3314,6 +3549,45 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_chan_def *chandef) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); + struct mwifiex_bssdescriptor *curr_bss; + struct ieee80211_channel *chan; + u8 second_chan_offset; + enum nl80211_channel_type chan_type; + enum ieee80211_band band; + int freq; + int ret = -ENODATA; + + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP && + cfg80211_chandef_valid(&priv->bss_chandef)) { + *chandef = priv->bss_chandef; + ret = 0; + } else if (priv->media_connected) { + curr_bss = &priv->curr_bss_params.bss_descriptor; + band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); + freq = ieee80211_channel_to_frequency(curr_bss->channel, band); + chan = ieee80211_get_channel(wiphy, freq); + + if (curr_bss->bcn_ht_oper) { + second_chan_offset = curr_bss->bcn_ht_oper->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET; + chan_type = mwifiex_sec_chan_offset_to_chan_type + (second_chan_offset); + cfg80211_chandef_create(chandef, chan, chan_type); + } else { + cfg80211_chandef_create(chandef, chan, + NL80211_CHAN_NO_HT); + } + ret = 0; + } + + return ret; +} + static int mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, struct net_device *dev, @@ -3324,16 +3598,17 @@ mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, struct mwifiex_radar_params radar_params; if (priv->adapter->scan_processing) { - dev_err(priv->adapter->dev, - "radar detection: scan already in process...\n"); + mwifiex_dbg(priv->adapter, ERROR, + "radar detection: scan already in process...\n"); return -EBUSY; } if (!mwifiex_is_11h_active(priv)) { - dev_dbg(priv->adapter->dev, "Enable 11h extensions in FW\n"); + mwifiex_dbg(priv->adapter, INFO, + "Enable 11h extensions in FW\n"); if (mwifiex_11h_activate(priv, true)) { - dev_err(priv->adapter->dev, - "Failed to activate 11h extensions!!"); + mwifiex_dbg(priv->adapter, ERROR, + "Failed to activate 11h extensions!!"); return -1; } priv->state_11h.is_11h_active = true; @@ -3416,8 +3691,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .set_coalesce = mwifiex_cfg80211_set_coalesce, .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, .tdls_oper = mwifiex_cfg80211_tdls_oper, + .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch, + .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch, .add_station = mwifiex_cfg80211_add_station, .change_station = mwifiex_cfg80211_change_station, + .get_channel = mwifiex_cfg80211_get_channel, .start_radar_detection = mwifiex_cfg80211_start_radar_detection, .channel_switch = mwifiex_cfg80211_channel_switch, }; @@ -3492,7 +3770,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy = wiphy_new(&mwifiex_cfg80211_ops, sizeof(struct mwifiex_adapter *)); if (!wiphy) { - dev_err(adapter->dev, "%s: creating new wiphy\n", __func__); + mwifiex_dbg(adapter, ERROR, + "%s: creating new wiphy\n", __func__); return -ENOMEM; } wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; @@ -3511,7 +3790,12 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) else wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; + if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info)) + wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs; + else if (adapter->is_hw_11ac_capable) + wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht; + else + wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; wiphy->n_iface_combinations = 1; /* Initialize cipher suits */ @@ -3524,7 +3808,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | - WIPHY_FLAG_HAS_CHANNEL_SWITCH; + WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_PS_ON_BY_DEFAULT; if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | @@ -3547,6 +3832,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) NL80211_FEATURE_INACTIVITY_TIMER | NL80211_FEATURE_NEED_OBSS_SCAN; + if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) + wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH; + if (adapter->fw_api_ver == MWIFIEX_FW_V15) wiphy->features |= NL80211_FEATURE_SK_TX_STATUS; @@ -3563,20 +3851,22 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) ret = wiphy_register(wiphy); if (ret < 0) { - dev_err(adapter->dev, - "%s: wiphy_register failed: %d\n", __func__, ret); + mwifiex_dbg(adapter, ERROR, + "%s: wiphy_register failed: %d\n", __func__, ret); wiphy_free(wiphy); return ret; } if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) { - wiphy_info(wiphy, "driver hint alpha2: %2.2s\n", reg_alpha2); + mwifiex_dbg(adapter, INFO, + "driver hint alpha2: %2.2s\n", reg_alpha2); regulatory_hint(wiphy, reg_alpha2); } else { country_code = mwifiex_11d_code_2_region(adapter->region_code); if (country_code) - wiphy_info(wiphy, "ignoring F/W country code %2.2s\n", - country_code); + mwifiex_dbg(adapter, WARN, + "ignoring F/W country code %2.2s\n", + country_code); } mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,