diff options
Diffstat (limited to 'drivers/net/wireless/quantenna/qtnfmac')
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 197 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/commands.c | 220 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/commands.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/core.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/core.h | 34 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/event.c | 48 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/qlink.h | 148 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/qlink_util.c | 113 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/qlink_util.h | 7 |
11 files changed, 466 insertions, 352 deletions
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index a450bc6bc774..e70f5bd5e498 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -73,7 +73,10 @@ qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_AP] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4), }, }; @@ -133,6 +136,7 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) vif->netdev = NULL; vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; eth_zero_addr(vif->mac_addr); + eth_zero_addr(vif->bssid); return 0; } @@ -201,6 +205,8 @@ err_mac: qtnf_cmd_send_del_intf(vif); err_cmd: vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; + eth_zero_addr(vif->mac_addr); + eth_zero_addr(vif->bssid); return ERR_PTR(-EFAULT); } @@ -256,11 +262,6 @@ static int qtnf_change_beacon(struct wiphy *wiphy, struct net_device *dev, { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); - if (!(vif->bss_status & QTNF_STATE_AP_START)) { - pr_err("VIF%u.%u: not started\n", vif->mac->macid, vif->vifid); - return -EFAULT; - } - return qtnf_mgmt_set_appie(vif, info); } @@ -268,46 +269,15 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings) { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); - struct qtnf_wmac *mac = wiphy_priv(wiphy); - struct qtnf_bss_config *bss_cfg; int ret; - if (!cfg80211_chandef_identical(&mac->chandef, &settings->chandef)) { - memcpy(&mac->chandef, &settings->chandef, sizeof(mac->chandef)); - if (vif->vifid != 0) - pr_warn("%s: unexpected chan %u (%u MHz)\n", dev->name, - settings->chandef.chan->hw_value, - settings->chandef.chan->center_freq); - } - - bss_cfg = &vif->bss_cfg; - memset(bss_cfg, 0, sizeof(*bss_cfg)); - - bss_cfg->bcn_period = settings->beacon_interval; - bss_cfg->dtim = settings->dtim_period; - bss_cfg->auth_type = settings->auth_type; - bss_cfg->privacy = settings->privacy; - - bss_cfg->ssid_len = settings->ssid_len; - memcpy(&bss_cfg->ssid, settings->ssid, bss_cfg->ssid_len); - - memcpy(&bss_cfg->crypto, &settings->crypto, - sizeof(struct cfg80211_crypto_settings)); - - ret = qtnf_cmd_send_config_ap(vif); + ret = qtnf_cmd_send_config_ap(vif, settings); if (ret) { pr_err("VIF%u.%u: failed to push config to FW\n", vif->mac->macid, vif->vifid); goto out; } - if (!(vif->bss_status & QTNF_STATE_AP_CONFIG)) { - pr_err("VIF%u.%u: AP config failed in FW\n", vif->mac->macid, - vif->vifid); - ret = -EFAULT; - goto out; - } - ret = qtnf_mgmt_set_appie(vif, &settings->beacon); if (ret) { pr_err("VIF%u.%u: failed to add IEs to beacon\n", @@ -316,17 +286,9 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev, } ret = qtnf_cmd_send_start_ap(vif); - if (ret) { + if (ret) pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid, vif->vifid); - goto out; - } - - if (!(vif->bss_status & QTNF_STATE_AP_START)) { - pr_err("VIF%u.%u: FW failed to start AP operation\n", - vif->mac->macid, vif->vifid); - ret = -EFAULT; - } out: return ret; @@ -343,8 +305,6 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev) if (ret) { pr_err("VIF%u.%u: failed to stop AP operation in FW\n", vif->mac->macid, vif->vifid); - vif->bss_status &= ~QTNF_STATE_AP_START; - vif->bss_status &= ~QTNF_STATE_AP_CONFIG; netif_carrier_off(vif->netdev); } @@ -396,6 +356,13 @@ qtnf_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, return; switch (frame_type & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_REASSOC_REQ: + case IEEE80211_STYPE_ASSOC_REQ: + qlink_frame_type = QLINK_MGMT_FRAME_ASSOC_REQ; + break; + case IEEE80211_STYPE_AUTH: + qlink_frame_type = QLINK_MGMT_FRAME_AUTH; + break; case IEEE80211_STYPE_PROBE_REQ: qlink_frame_type = QLINK_MGMT_FRAME_PROBE_REQ; break; @@ -581,9 +548,9 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev, return ret; } -static void qtnf_scan_timeout(unsigned long data) +static void qtnf_scan_timeout(struct timer_list *t) { - struct qtnf_wmac *mac = (struct qtnf_wmac *)data; + struct qtnf_wmac *mac = from_timer(mac, t, scan_timeout); pr_warn("mac%d scan timed out\n", mac->macid); qtnf_scan_done(mac, true); @@ -602,8 +569,7 @@ qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) return -EFAULT; } - mac->scan_timeout.data = (unsigned long)mac; - mac->scan_timeout.function = qtnf_scan_timeout; + mac->scan_timeout.function = (TIMER_FUNC_TYPE)qtnf_scan_timeout; mod_timer(&mac->scan_timeout, jiffies + QTNF_SCAN_TIMEOUT_SEC * HZ); @@ -615,9 +581,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); - struct qtnf_wmac *mac = wiphy_priv(wiphy); - struct cfg80211_chan_def chandef; - struct qtnf_bss_config *bss_cfg; int ret; if (vif->wdev.iftype != NL80211_IFTYPE_STATION) @@ -626,49 +589,10 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, if (vif->sta_state != QTNF_STA_DISCONNECTED) return -EBUSY; - bss_cfg = &vif->bss_cfg; - memset(bss_cfg, 0, sizeof(*bss_cfg)); - - if (sme->channel) { - /* FIXME: need to set proper nl80211_channel_type value */ - cfg80211_chandef_create(&chandef, sme->channel, - NL80211_CHAN_HT20); - /* fall-back to minimal safe chandef description */ - if (!cfg80211_chandef_valid(&chandef)) - cfg80211_chandef_create(&chandef, sme->channel, - NL80211_CHAN_HT20); - - memcpy(&mac->chandef, &chandef, sizeof(mac->chandef)); - } - - bss_cfg->ssid_len = sme->ssid_len; - memcpy(&bss_cfg->ssid, sme->ssid, bss_cfg->ssid_len); - bss_cfg->auth_type = sme->auth_type; - bss_cfg->privacy = sme->privacy; - bss_cfg->mfp = sme->mfp; - - if ((sme->bg_scan_period > 0) && - (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD)) - bss_cfg->bg_scan_period = sme->bg_scan_period; - else if (sme->bg_scan_period == -1) - bss_cfg->bg_scan_period = QTNF_DEFAULT_BG_SCAN_PERIOD; - else - bss_cfg->bg_scan_period = 0; /* disabled */ - - bss_cfg->connect_flags = 0; - - if (sme->flags & ASSOC_REQ_DISABLE_HT) - bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_HT; - if (sme->flags & ASSOC_REQ_DISABLE_VHT) - bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT; - if (sme->flags & ASSOC_REQ_USE_RRM) - bss_cfg->connect_flags |= QLINK_STA_CONNECT_USE_RRM; - - memcpy(&bss_cfg->crypto, &sme->crypto, sizeof(bss_cfg->crypto)); if (sme->bssid) - ether_addr_copy(bss_cfg->bssid, sme->bssid); + ether_addr_copy(vif->bssid, sme->bssid); else - eth_zero_addr(bss_cfg->bssid); + eth_zero_addr(vif->bssid); ret = qtnf_cmd_send_connect(vif, sme); if (ret) { @@ -717,15 +641,15 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, int idx, struct survey_info *survey) { struct qtnf_wmac *mac = wiphy_priv(wiphy); + struct wireless_dev *wdev = dev->ieee80211_ptr; struct ieee80211_supported_band *sband; - struct cfg80211_chan_def *chandef; + const struct cfg80211_chan_def *chandef = &wdev->chandef; struct ieee80211_channel *chan; struct qtnf_chan_stats stats; struct qtnf_vif *vif; int ret; vif = qtnf_netdev_get_priv(dev); - chandef = &mac->chandef; sband = wiphy->bands[NL80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { @@ -792,46 +716,35 @@ static int qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_chan_def *chandef) { - struct qtnf_wmac *mac = wiphy_priv(wiphy); struct net_device *ndev = wdev->netdev; struct qtnf_vif *vif; + int ret; if (!ndev) return -ENODEV; vif = qtnf_netdev_get_priv(wdev->netdev); - switch (vif->wdev.iftype) { - case NL80211_IFTYPE_STATION: - if (vif->sta_state == QTNF_STA_DISCONNECTED) { - pr_warn("%s: STA disconnected\n", ndev->name); - return -ENODATA; - } - break; - case NL80211_IFTYPE_AP: - if (!(vif->bss_status & QTNF_STATE_AP_START)) { - pr_warn("%s: AP not started\n", ndev->name); - return -ENODATA; - } - break; - default: - pr_err("unsupported vif type (%d)\n", vif->wdev.iftype); - return -ENODATA; + ret = qtnf_cmd_get_channel(vif, chandef); + if (ret) { + pr_err("%s: failed to get channel: %d\n", ndev->name, ret); + goto out; } - if (!cfg80211_chandef_valid(&mac->chandef)) { - pr_err("invalid channel settings on %s\n", ndev->name); - return -ENODATA; + if (!cfg80211_chandef_valid(chandef)) { + pr_err("%s: bad chan freq1=%u freq2=%u bw=%u\n", ndev->name, + chandef->center_freq1, chandef->center_freq2, + chandef->width); + ret = -ENODATA; } - memcpy(chandef, &mac->chandef, sizeof(*chandef)); - return 0; +out: + return ret; } static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params) { - struct qtnf_wmac *mac = wiphy_priv(wiphy); struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); int ret; @@ -839,41 +752,12 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev, params->chandef.chan->hw_value, params->count, params->radar_required, params->block_tx); - switch (vif->wdev.iftype) { - case NL80211_IFTYPE_AP: - if (!(vif->bss_status & QTNF_STATE_AP_START)) { - pr_warn("AP not started on %s\n", dev->name); - return -ENOTCONN; - } - break; - default: - pr_err("unsupported vif type (%d) on %s\n", - vif->wdev.iftype, dev->name); - return -EOPNOTSUPP; - } - - if (vif->vifid != 0) { - if (!(mac->status & QTNF_MAC_CSA_ACTIVE)) - return -EOPNOTSUPP; - - if (!cfg80211_chandef_identical(¶ms->chandef, - &mac->csa_chandef)) - return -EINVAL; - - return 0; - } - if (!cfg80211_chandef_valid(¶ms->chandef)) { pr_err("%s: invalid channel\n", dev->name); return -EINVAL; } - if (cfg80211_chandef_identical(¶ms->chandef, &mac->chandef)) { - pr_err("%s: switch request to the same channel\n", dev->name); - return -EALREADY; - } - - ret = qtnf_cmd_send_chan_switch(mac, params); + ret = qtnf_cmd_send_chan_switch(vif, params); if (ret) pr_warn("%s: failed to switch to channel (%u)\n", dev->name, params->chandef.chan->hw_value); @@ -1072,7 +956,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) ether_addr_copy(wiphy->perm_addr, mac->macaddr); - if (hw_info->hw_capab & QLINK_HW_SUPPORTS_REG_UPDATE) { + if (hw_info->hw_capab & QLINK_HW_CAPAB_STA_INACT_TIMEOUT) + wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; + + if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) { wiphy->regulatory_flags |= REGULATORY_STRICT_REG | REGULATORY_CUSTOM_REG; wiphy->reg_notifier = qtnf_cfg80211_reg_notifier; @@ -1119,7 +1006,7 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev) break; case QTNF_STA_CONNECTING: cfg80211_connect_result(vif->netdev, - vif->bss_cfg.bssid, NULL, 0, + vif->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); @@ -1147,7 +1034,7 @@ void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif) switch (vif->sta_state) { case QTNF_STA_CONNECTING: cfg80211_connect_result(vif->netdev, - vif->bss_cfg.bssid, NULL, 0, + vif->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 4206886b110c..b81f81bd1411 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -173,7 +173,6 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif) goto out; } - vif->bss_status |= QTNF_STATE_AP_START; netif_carrier_on(vif->netdev); out: @@ -181,62 +180,68 @@ out: return ret; } -int qtnf_cmd_send_config_ap(struct qtnf_vif *vif) +int qtnf_cmd_send_config_ap(struct qtnf_vif *vif, + const struct cfg80211_ap_settings *s) { struct sk_buff *cmd_skb; - struct qtnf_bss_config *bss_cfg = &vif->bss_cfg; - struct cfg80211_chan_def *chandef = &vif->mac->chandef; - struct qlink_tlv_channel *qchan; - struct qlink_auth_encr aen; + struct qlink_cmd_config_ap *cmd; + struct qlink_auth_encr *aen; u16 res_code = QLINK_CMD_RESULT_OK; int ret; int i; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, QLINK_CMD_CONFIG_AP, - sizeof(struct qlink_cmd)); + sizeof(*cmd)); if (unlikely(!cmd_skb)) return -ENOMEM; - qtnf_bus_lock(vif->mac->bus); - - qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid, - bss_cfg->ssid_len); - qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_BCN_PERIOD, - bss_cfg->bcn_period); - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, bss_cfg->dtim); - - qchan = skb_put_zero(cmd_skb, sizeof(*qchan)); - qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); - qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - - sizeof(struct qlink_tlv_hdr)); - qchan->hw_value = cpu_to_le16( - ieee80211_frequency_to_channel(chandef->chan->center_freq)); - - memset(&aen, 0, sizeof(aen)); - aen.auth_type = bss_cfg->auth_type; - aen.privacy = !!bss_cfg->privacy; - aen.mfp = bss_cfg->mfp; - aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions); - aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group); - aen.n_ciphers_pairwise = cpu_to_le32( - bss_cfg->crypto.n_ciphers_pairwise); + cmd = (struct qlink_cmd_config_ap *)cmd_skb->data; + cmd->dtim_period = s->dtim_period; + cmd->beacon_interval = cpu_to_le16(s->beacon_interval); + cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid); + cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout); + cmd->smps_mode = s->smps_mode; + cmd->p2p_ctwindow = s->p2p_ctwindow; + cmd->p2p_opp_ps = s->p2p_opp_ps; + cmd->pbss = s->pbss; + cmd->ht_required = s->ht_required; + cmd->vht_required = s->vht_required; + + aen = &cmd->aen; + aen->auth_type = s->auth_type; + aen->privacy = !!s->privacy; + aen->mfp = 0; + aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions); + aen->cipher_group = cpu_to_le32(s->crypto.cipher_group); + aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise); for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++) - aen.ciphers_pairwise[i] = cpu_to_le32( - bss_cfg->crypto.ciphers_pairwise[i]); - aen.n_akm_suites = cpu_to_le32( - bss_cfg->crypto.n_akm_suites); + aen->ciphers_pairwise[i] = + cpu_to_le32(s->crypto.ciphers_pairwise[i]); + aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites); for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++) - aen.akm_suites[i] = cpu_to_le32( - bss_cfg->crypto.akm_suites[i]); - aen.control_port = bss_cfg->crypto.control_port; - aen.control_port_no_encrypt = - bss_cfg->crypto.control_port_no_encrypt; - aen.control_port_ethertype = cpu_to_le16(be16_to_cpu( - bss_cfg->crypto.control_port_ethertype)); + aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]); + aen->control_port = s->crypto.control_port; + aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt; + aen->control_port_ethertype = + cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype)); + + if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN) + qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid, + s->ssid_len); - qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen, - sizeof(aen)); + if (cfg80211_chandef_valid(&s->chandef)) { + struct qlink_tlv_chandef *chtlv = + (struct qlink_tlv_chandef *)skb_put(cmd_skb, + sizeof(*chtlv)); + + chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF); + chtlv->hdr.len = cpu_to_le16(sizeof(*chtlv) - + sizeof(chtlv->hdr)); + qlink_chandef_cfg2q(&s->chandef, &chtlv->chan); + } + + qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); @@ -250,8 +255,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif) goto out; } - vif->bss_status |= QTNF_STATE_AP_CONFIG; - out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -283,9 +286,6 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif) goto out; } - vif->bss_status &= ~QTNF_STATE_AP_START; - vif->bss_status &= ~QTNF_STATE_AP_CONFIG; - netif_carrier_off(vif->netdev); out: @@ -975,10 +975,11 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, return -EINVAL; } - pr_info("fw_version=%d, MACs map %#x, alpha2=\"%c%c\", chains Tx=%u Rx=%u\n", + pr_info("fw_version=%d, MACs map %#x, alpha2=\"%c%c\", chains Tx=%u Rx=%u, capab=0x%x\n", hwinfo->fw_ver, hwinfo->mac_bitmap, hwinfo->rd->alpha2[0], hwinfo->rd->alpha2[1], - hwinfo->total_tx_chain, hwinfo->total_rx_chain); + hwinfo->total_tx_chain, hwinfo->total_rx_chain, + hwinfo->hw_capab); return 0; } @@ -2037,11 +2038,11 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, { struct sk_buff *cmd_skb; struct qlink_cmd_connect *cmd; - struct qtnf_bss_config *bss_cfg = &vif->bss_cfg; - struct qlink_auth_encr aen; + struct qlink_auth_encr *aen; u16 res_code = QLINK_CMD_RESULT_OK; int ret; int i; + u32 connect_flags = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, QLINK_CMD_CONNECT, @@ -2049,52 +2050,65 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, if (unlikely(!cmd_skb)) return -ENOMEM; - qtnf_bus_lock(vif->mac->bus); - cmd = (struct qlink_cmd_connect *)cmd_skb->data; - ether_addr_copy(cmd->bssid, bss_cfg->bssid); + ether_addr_copy(cmd->bssid, vif->bssid); + + if (sme->channel) + cmd->channel = cpu_to_le16(sme->channel->hw_value); + else + cmd->channel = 0; + + if ((sme->bg_scan_period > 0) && + (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD)) + cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period); + else if (sme->bg_scan_period == -1) + cmd->bg_scan_period = cpu_to_le16(QTNF_DEFAULT_BG_SCAN_PERIOD); + else + cmd->bg_scan_period = 0; /* disabled */ - if (vif->mac->chandef.chan) - cmd->channel = cpu_to_le16(vif->mac->chandef.chan->hw_value); + if (sme->flags & ASSOC_REQ_DISABLE_HT) + connect_flags |= QLINK_STA_CONNECT_DISABLE_HT; + if (sme->flags & ASSOC_REQ_DISABLE_VHT) + connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT; + if (sme->flags & ASSOC_REQ_USE_RRM) + connect_flags |= QLINK_STA_CONNECT_USE_RRM; - cmd->bg_scan_period = cpu_to_le16(bss_cfg->bg_scan_period); + cmd->flags = cpu_to_le32(connect_flags); - memset(&aen, 0, sizeof(aen)); - aen.auth_type = bss_cfg->auth_type; - aen.privacy = !!bss_cfg->privacy; - aen.mfp = bss_cfg->mfp; - aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions); - aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group); - aen.n_ciphers_pairwise = cpu_to_le32( - bss_cfg->crypto.n_ciphers_pairwise); + aen = &cmd->aen; + aen->auth_type = sme->auth_type; + aen->privacy = !!sme->privacy; + aen->mfp = sme->mfp; + aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions); + aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group); + aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise); for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++) - aen.ciphers_pairwise[i] = cpu_to_le32( - bss_cfg->crypto.ciphers_pairwise[i]); + aen->ciphers_pairwise[i] = + cpu_to_le32(sme->crypto.ciphers_pairwise[i]); - aen.n_akm_suites = cpu_to_le32(bss_cfg->crypto.n_akm_suites); + aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites); for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++) - aen.akm_suites[i] = cpu_to_le32( - bss_cfg->crypto.akm_suites[i]); + aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]); - aen.control_port = bss_cfg->crypto.control_port; - aen.control_port_no_encrypt = - bss_cfg->crypto.control_port_no_encrypt; - aen.control_port_ethertype = cpu_to_le16(be16_to_cpu( - bss_cfg->crypto.control_port_ethertype)); + aen->control_port = sme->crypto.control_port; + aen->control_port_no_encrypt = + sme->crypto.control_port_no_encrypt; + aen->control_port_ethertype = + cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype)); - qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid, - bss_cfg->ssid_len); - qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen, - sizeof(aen)); + qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid, + sme->ssid_len); if (sme->ie_len != 0) qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, sme->ie, sme->ie_len); + qtnf_bus_lock(vif->mac->bus); + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); if (unlikely(ret)) @@ -2304,15 +2318,16 @@ out: return ret; } -int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac, +int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct cfg80211_csa_settings *params) { + struct qtnf_wmac *mac = vif->mac; struct qlink_cmd_chan_switch *cmd; struct sk_buff *cmd_skb; u16 res_code = QLINK_CMD_RESULT_OK; int ret; - cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0x0, + cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid, QLINK_CMD_CHAN_SWITCH, sizeof(*cmd)); @@ -2334,9 +2349,6 @@ int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac, switch (res_code) { case QLINK_CMD_RESULT_OK: - memcpy(&mac->csa_chandef, ¶ms->chandef, - sizeof(mac->csa_chandef)); - mac->status |= QTNF_MAC_CSA_ACTIVE; ret = 0; break; case QLINK_CMD_RESULT_ENOTFOUND: @@ -2358,3 +2370,41 @@ out: qtnf_bus_unlock(mac->bus); return ret; } + +int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef) +{ + struct qtnf_bus *bus = vif->mac->bus; + const struct qlink_resp_channel_get *resp; + struct sk_buff *cmd_skb; + struct sk_buff *resp_skb = NULL; + u16 res_code = QLINK_CMD_RESULT_OK; + int ret; + + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, + QLINK_CMD_CHAN_GET, + sizeof(struct qlink_cmd)); + if (unlikely(!cmd_skb)) + return -ENOMEM; + + qtnf_bus_lock(bus); + + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code, + sizeof(*resp), NULL); + + qtnf_bus_unlock(bus); + + if (unlikely(ret)) + goto out; + + if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { + ret = -ENODATA; + goto out; + } + + resp = (const struct qlink_resp_channel_get *)resp_skb->data; + qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef); + +out: + consume_skb(resp_skb); + return ret; +} diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index 783b20364296..e87c4a484dd4 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -33,7 +33,8 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif); int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac, struct ieee80211_supported_band *band); int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2); -int qtnf_cmd_send_config_ap(struct qtnf_vif *vif); +int qtnf_cmd_send_config_ap(struct qtnf_vif *vif, + const struct cfg80211_ap_settings *s); int qtnf_cmd_send_start_ap(struct qtnf_vif *vif); int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif); int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg); @@ -73,7 +74,8 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req); int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, struct qtnf_chan_stats *stats); -int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac, +int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct cfg80211_csa_settings *params); +int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef); #endif /* QLINK_COMMANDS_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 5e60180482d1..6a6e5ffb0348 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -289,7 +289,7 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, mac->iflist[i].vifid = i; qtnf_sta_list_init(&mac->iflist[i].sta_list); mutex_init(&mac->mac_lock); - init_timer(&mac->scan_timeout); + setup_timer(&mac->scan_timeout, NULL, 0); } qtnf_mac_init_primary_intf(mac); @@ -618,6 +618,33 @@ out: } EXPORT_SYMBOL_GPL(qtnf_classify_skb); +void qtnf_wake_all_queues(struct net_device *ndev) +{ + struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev); + struct qtnf_wmac *mac; + struct qtnf_bus *bus; + int macid; + int i; + + if (unlikely(!vif || !vif->mac || !vif->mac->bus)) + return; + + bus = vif->mac->bus; + + for (macid = 0; macid < QTNF_MAX_MAC; macid++) { + if (!(bus->hw_info.mac_bitmap & BIT(macid))) + continue; + + mac = bus->mac[macid]; + for (i = 0; i < QTNF_MAX_INTF; i++) { + vif = &mac->iflist[i]; + if (vif->netdev && netif_queue_stopped(vif->netdev)) + netif_tx_wake_all_queues(vif->netdev); + } + } +} +EXPORT_SYMBOL_GPL(qtnf_wake_all_queues); + MODULE_AUTHOR("Quantenna Communications"); MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver."); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index 066fcd1095a0..da2c24e2271d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -52,27 +52,11 @@ #define QTNF_DEF_WDOG_TIMEOUT 5 #define QTNF_TX_TIMEOUT_TRSHLD 100 -#define QTNF_STATE_AP_CONFIG BIT(2) -#define QTNF_STATE_AP_START BIT(1) - extern const struct net_device_ops qtnf_netdev_ops; + struct qtnf_bus; struct qtnf_vif; -struct qtnf_bss_config { - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 bssid[ETH_ALEN]; - size_t ssid_len; - u8 dtim; - u16 bcn_period; - u16 auth_type; - bool privacy; - enum nl80211_mfp mfp; - struct cfg80211_crypto_settings crypto; - u16 bg_scan_period; - u32 connect_flags; -}; - struct qtnf_sta_node { struct list_head list; u8 mac_addr[ETH_ALEN]; @@ -89,12 +73,10 @@ enum qtnf_sta_state { QTNF_STA_CONNECTED }; -enum qtnf_mac_status { - QTNF_MAC_CSA_ACTIVE = BIT(0) -}; - struct qtnf_vif { struct wireless_dev wdev; + u8 bssid[ETH_ALEN]; + u8 mac_addr[ETH_ALEN]; u8 vifid; u8 bss_priority; u8 bss_status; @@ -102,9 +84,8 @@ struct qtnf_vif { u16 mgmt_frames_bitmask; struct net_device *netdev; struct qtnf_wmac *mac; - u8 mac_addr[ETH_ALEN]; + struct work_struct reset_work; - struct qtnf_bss_config bss_cfg; struct qtnf_sta_list sta_list; unsigned long cons_tx_timeout_cnt; }; @@ -141,13 +122,10 @@ struct qtnf_wmac { u8 macid; u8 wiphy_registered; u8 macaddr[ETH_ALEN]; - u32 status; struct qtnf_bus *bus; struct qtnf_mac_info macinfo; struct qtnf_vif iflist[QTNF_MAX_INTF]; struct cfg80211_scan_request *scan_req; - struct cfg80211_chan_def chandef; - struct cfg80211_chan_def csa_chandef; struct mutex mac_lock; /* lock during wmac speicific ops */ struct timer_list scan_timeout; }; @@ -175,9 +153,7 @@ int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac); struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid); struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb); -struct net_device *qtnf_classify_skb_no_mbss(struct qtnf_bus *bus, - struct sk_buff *skb); - +void qtnf_wake_all_queues(struct net_device *ndev); void qtnf_virtual_intf_cleanup(struct net_device *ndev); void qtnf_netdev_updown(struct net_device *ndev, bool up); diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 43d2e7fd6e02..4b29f9fb9c3c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -25,6 +25,7 @@ #include "trans.h" #include "util.h" #include "event.h" +#include "qlink_util.h" static int qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, @@ -52,12 +53,6 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, return -EPROTO; } - if (!(vif->bss_status & QTNF_STATE_AP_START)) { - pr_err("VIF%u.%u: STA_ASSOC event when AP is not started\n", - mac->macid, vif->vifid); - return -EPROTO; - } - sta_addr = sta_assoc->sta_addr; frame_control = le16_to_cpu(sta_assoc->frame_control); @@ -126,12 +121,6 @@ qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif, return -EPROTO; } - if (!(vif->bss_status & QTNF_STATE_AP_START)) { - pr_err("VIF%u.%u: STA_DEAUTH event when AP is not started\n", - mac->macid, vif->vifid); - return -EPROTO; - } - sta_addr = sta_deauth->sta_addr; reason = le16_to_cpu(sta_deauth->reason); @@ -357,40 +346,29 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac, { struct wiphy *wiphy = priv_to_wiphy(mac); struct cfg80211_chan_def chandef; - struct ieee80211_channel *chan; struct qtnf_vif *vif; - int freq; int i; if (len < sizeof(*data)) { - pr_err("payload is too short\n"); + pr_err("MAC%u: payload is too short\n", mac->macid); return -EINVAL; } - freq = le32_to_cpu(data->freq); - chan = ieee80211_get_channel(wiphy, freq); - if (!chan) { - pr_err("channel at %d MHz not found\n", freq); - return -EINVAL; - } + if (!wiphy->registered) + return 0; - pr_debug("MAC%d switch to new channel %u MHz\n", mac->macid, freq); + qlink_chandef_q2cfg(wiphy, &data->chan, &chandef); - if (mac->status & QTNF_MAC_CSA_ACTIVE) { - mac->status &= ~QTNF_MAC_CSA_ACTIVE; - if (chan->hw_value != mac->csa_chandef.chan->hw_value) - pr_warn("unexpected switch to %u during CSA to %u\n", - chan->hw_value, - mac->csa_chandef.chan->hw_value); + if (!cfg80211_chandef_valid(&chandef)) { + pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n", mac->macid, + chandef.center_freq1, chandef.center_freq2, + chandef.width); + return -EINVAL; } - /* FIXME: need to figure out proper nl80211_channel_type value */ - cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); - /* fall-back to minimal safe chandef description */ - if (!cfg80211_chandef_valid(&chandef)) - cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); - - memcpy(&mac->chandef, &chandef, sizeof(mac->chandef)); + pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n", + mac->macid, chandef.chan->hw_value, chandef.center_freq1, + chandef.center_freq2, chandef.width); for (i = 0; i < QTNF_MAX_INTF; i++) { vif = &mac->iflist[i]; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c index 69131965a298..7e487622d87d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c @@ -617,9 +617,10 @@ static void qtnf_pcie_data_tx_reclaim(struct qtnf_pcie_bus_priv *priv) if (skb->dev) { skb->dev->stats.tx_packets++; skb->dev->stats.tx_bytes += skb->len; - - if (netif_queue_stopped(skb->dev)) - netif_wake_queue(skb->dev); + if (unlikely(priv->tx_stopped)) { + qtnf_wake_all_queues(skb->dev); + priv->tx_stopped = 0; + } } dev_kfree_skb_any(skb); @@ -643,11 +644,11 @@ static int qtnf_tx_queue_ready(struct qtnf_pcie_bus_priv *priv) { if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, priv->tx_bd_num)) { - pr_err_ratelimited("reclaim full Tx queue\n"); qtnf_pcie_data_tx_reclaim(priv); if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, priv->tx_bd_num)) { + pr_warn_ratelimited("reclaim full Tx queue\n"); priv->tx_full_count++; return 0; } @@ -669,8 +670,10 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) spin_lock_irqsave(&priv->tx0_lock, flags); if (!qtnf_tx_queue_ready(priv)) { - if (skb->dev) - netif_stop_queue(skb->dev); + if (skb->dev) { + netif_tx_stop_all_queues(skb->dev); + priv->tx_stopped = 1; + } spin_unlock_irqrestore(&priv->tx0_lock, flags); return NETDEV_TX_BUSY; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h index 86ac1ccedb52..397875a50fc2 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h +++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h @@ -37,6 +37,7 @@ struct qtnf_pcie_bus_priv { /* lock for tx0 operations */ spinlock_t tx0_lock; u8 msi_enabled; + u8 tx_stopped; int mps; struct workqueue_struct *workqueue; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index a8242f678496..0f582782682f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -61,8 +61,17 @@ struct qlink_msg_header { /* Generic definitions of data and information carried in QLINK messages */ +/** + * enum qlink_hw_capab - device capabilities. + * + * @QLINK_HW_CAPAB_REG_UPDATE: device can update it's regulatory region. + * @QLINK_HW_CAPAB_STA_INACT_TIMEOUT: device implements a logic to kick-out + * associated STAs due to inactivity. Inactivity timeout period is taken + * from QLINK_CMD_START_AP parameters. + */ enum qlink_hw_capab { - QLINK_HW_SUPPORTS_REG_UPDATE = BIT(0), + QLINK_HW_CAPAB_REG_UPDATE = BIT(0), + QLINK_HW_CAPAB_STA_INACT_TIMEOUT = BIT(1), }; enum qlink_phy_mode { @@ -108,16 +117,48 @@ enum qlink_sta_flags { }; enum qlink_channel_width { - QLINK_CHAN_WIDTH_5 = BIT(0), - QLINK_CHAN_WIDTH_10 = BIT(1), - QLINK_CHAN_WIDTH_20_NOHT = BIT(2), - QLINK_CHAN_WIDTH_20 = BIT(3), - QLINK_CHAN_WIDTH_40 = BIT(4), - QLINK_CHAN_WIDTH_80 = BIT(5), - QLINK_CHAN_WIDTH_80P80 = BIT(6), - QLINK_CHAN_WIDTH_160 = BIT(7), + QLINK_CHAN_WIDTH_5 = 0, + QLINK_CHAN_WIDTH_10, + QLINK_CHAN_WIDTH_20_NOHT, + QLINK_CHAN_WIDTH_20, + QLINK_CHAN_WIDTH_40, + QLINK_CHAN_WIDTH_80, + QLINK_CHAN_WIDTH_80P80, + QLINK_CHAN_WIDTH_160, }; +/** + * struct qlink_chandef - qlink channel definition + * + * @center_freq1: center frequency of first segment + * @center_freq2: center frequency of second segment (80+80 only) + * @width: channel width, one of @enum qlink_channel_width + */ +struct qlink_chandef { + __le16 center_freq1; + __le16 center_freq2; + u8 width; + u8 rsvd[3]; +} __packed; + +#define QLINK_MAX_NR_CIPHER_SUITES 5 +#define QLINK_MAX_NR_AKM_SUITES 2 + +struct qlink_auth_encr { + __le32 wpa_versions; + __le32 cipher_group; + __le32 n_ciphers_pairwise; + __le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES]; + __le32 n_akm_suites; + __le32 akm_suites[QLINK_MAX_NR_AKM_SUITES]; + __le16 control_port_ethertype; + u8 auth_type; + u8 privacy; + u8 mfp; + u8 control_port; + u8 control_port_no_encrypt; +} __packed; + /* QLINK Command messages related definitions */ @@ -155,6 +196,7 @@ enum qlink_cmd_type { QLINK_CMD_REG_NOTIFY = 0x0019, QLINK_CMD_CHANS_INFO_GET = 0x001A, QLINK_CMD_CHAN_SWITCH = 0x001B, + QLINK_CMD_CHAN_GET = 0x001C, QLINK_CMD_CONFIG_AP = 0x0020, QLINK_CMD_START_AP = 0x0021, QLINK_CMD_STOP_AP = 0x0022, @@ -384,8 +426,9 @@ enum qlink_sta_connect_flags { * struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command * * @flags: for future use. - * @freq: center frequence of a channel which should be used to connect. + * @channel: channel which should be used to connect. * @bg_scan_period: period of background scan. + * @aen: authentication information. * @bssid: BSSID of the BSS to connect to. * @payload: variable portion of connection request. */ @@ -394,6 +437,7 @@ struct qlink_cmd_connect { __le32 flags; __le16 channel; __le16 bg_scan_period; + struct qlink_auth_encr aen; u8 bssid[ETH_ALEN]; u8 payload[0]; } __packed; @@ -506,6 +550,46 @@ struct qlink_cmd_chan_switch { u8 beacon_count; } __packed; +/** + * enum qlink_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID + * + * Refer to &enum nl80211_hidden_ssid + */ +enum qlink_hidden_ssid { + QLINK_HIDDEN_SSID_NOT_IN_USE, + QLINK_HIDDEN_SSID_ZERO_LEN, + QLINK_HIDDEN_SSID_ZERO_CONTENTS +}; + +/** + * struct qlink_cmd_config_ap - data for QLINK_CMD_CONFIG_AP command + * + * @beacon_interval: beacon interval + * @inactivity_timeout: station's inactivity period in seconds + * @dtim_period: DTIM period + * @hidden_ssid: whether to hide the SSID, one of &enum qlink_hidden_ssid + * @smps_mode: SMPS mode + * @ht_required: stations must support HT + * @vht_required: stations must support VHT + * @aen: encryption info + * @info: variable configurations + */ +struct qlink_cmd_config_ap { + struct qlink_cmd chdr; + __le16 beacon_interval; + __le16 inactivity_timeout; + u8 dtim_period; + u8 hidden_ssid; + u8 smps_mode; + u8 p2p_ctwindow; + u8 p2p_opp_ps; + u8 pbss; + u8 ht_required; + u8 vht_required; + struct qlink_auth_encr aen; + u8 info[0]; +} __packed; + /* QLINK Command Responses messages related definitions */ @@ -680,6 +764,16 @@ struct qlink_resp_get_chan_stats { u8 info[0]; } __packed; +/** + * struct qlink_resp_channel_get - response for QLINK_CMD_CHAN_GET command + * + * @chan: definition of current operating channel. + */ +struct qlink_resp_channel_get { + struct qlink_resp rhdr; + struct qlink_chandef chan; +} __packed; + /* QLINK Events messages related definitions */ @@ -764,11 +858,11 @@ struct qlink_event_bss_leave { /** * struct qlink_event_freq_change - data for QLINK_EVENT_FREQ_CHANGE event * - * @freq: new operating frequency in MHz + * @chan: new operating channel definition */ struct qlink_event_freq_change { struct qlink_event ehdr; - __le32 freq; + struct qlink_chandef chan; } __packed; enum qlink_rxmgmt_flags { @@ -856,10 +950,9 @@ enum qlink_tlv_id { QTN_TLV_ID_RTS_THRESH = 0x0202, QTN_TLV_ID_SRETRY_LIMIT = 0x0203, QTN_TLV_ID_LRETRY_LIMIT = 0x0204, - QTN_TLV_ID_BCN_PERIOD = 0x0205, - QTN_TLV_ID_DTIM = 0x0206, QTN_TLV_ID_REG_RULE = 0x0207, QTN_TLV_ID_CHANNEL = 0x020F, + QTN_TLV_ID_CHANDEF = 0x0210, QTN_TLV_ID_COVERAGE_CLASS = 0x0213, QTN_TLV_ID_IFACE_LIMIT = 0x0214, QTN_TLV_ID_NUM_IFACE_COMB = 0x0215, @@ -868,7 +961,6 @@ enum qlink_tlv_id { QTN_TLV_ID_STA_GENERIC_INFO = 0x0301, QTN_TLV_ID_KEY = 0x0302, QTN_TLV_ID_SEQ = 0x0303, - QTN_TLV_ID_CRYPTO = 0x0304, QTN_TLV_ID_IE_SET = 0x0305, }; @@ -1047,22 +1139,16 @@ struct qlink_tlv_channel { u8 rsvd[2]; } __packed; -#define QLINK_MAX_NR_CIPHER_SUITES 5 -#define QLINK_MAX_NR_AKM_SUITES 2 - -struct qlink_auth_encr { - __le32 wpa_versions; - __le32 cipher_group; - __le32 n_ciphers_pairwise; - __le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES]; - __le32 n_akm_suites; - __le32 akm_suites[QLINK_MAX_NR_AKM_SUITES]; - __le16 control_port_ethertype; - u8 auth_type; - u8 privacy; - u8 mfp; - u8 control_port; - u8 control_port_no_encrypt; +/** + * struct qlink_tlv_chandef - data for QTN_TLV_ID_CHANDEF TLV + * + * Channel definition. + * + * @chan: channel definition data. + */ +struct qlink_tlv_chandef { + struct qlink_tlv_hdr hdr; + struct qlink_chandef chan; } __packed; struct qlink_chan_stats { diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c index cf024c995fd6..61d999affb09 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c @@ -49,29 +49,126 @@ u8 qlink_chan_width_mask_to_nl(u16 qlink_mask) { u8 result = 0; - if (qlink_mask & QLINK_CHAN_WIDTH_5) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_5)) result |= BIT(NL80211_CHAN_WIDTH_5); - if (qlink_mask & QLINK_CHAN_WIDTH_10) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_10)) result |= BIT(NL80211_CHAN_WIDTH_10); - if (qlink_mask & QLINK_CHAN_WIDTH_20_NOHT) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20_NOHT)) result |= BIT(NL80211_CHAN_WIDTH_20_NOHT); - if (qlink_mask & QLINK_CHAN_WIDTH_20) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20)) result |= BIT(NL80211_CHAN_WIDTH_20); - if (qlink_mask & QLINK_CHAN_WIDTH_40) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_40)) result |= BIT(NL80211_CHAN_WIDTH_40); - if (qlink_mask & QLINK_CHAN_WIDTH_80) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80)) result |= BIT(NL80211_CHAN_WIDTH_80); - if (qlink_mask & QLINK_CHAN_WIDTH_80P80) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80P80)) result |= BIT(NL80211_CHAN_WIDTH_80P80); - if (qlink_mask & QLINK_CHAN_WIDTH_160) + if (qlink_mask & BIT(QLINK_CHAN_WIDTH_160)) result |= BIT(NL80211_CHAN_WIDTH_160); return result; } + +static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw) +{ + switch (qlw) { + case QLINK_CHAN_WIDTH_20_NOHT: + return NL80211_CHAN_WIDTH_20_NOHT; + case QLINK_CHAN_WIDTH_20: + return NL80211_CHAN_WIDTH_20; + case QLINK_CHAN_WIDTH_40: + return NL80211_CHAN_WIDTH_40; + case QLINK_CHAN_WIDTH_80: + return NL80211_CHAN_WIDTH_80; + case QLINK_CHAN_WIDTH_80P80: + return NL80211_CHAN_WIDTH_80P80; + case QLINK_CHAN_WIDTH_160: + return NL80211_CHAN_WIDTH_160; + case QLINK_CHAN_WIDTH_5: + return NL80211_CHAN_WIDTH_5; + case QLINK_CHAN_WIDTH_10: + return NL80211_CHAN_WIDTH_10; + default: + return -1; + } +} + +void qlink_chandef_q2cfg(struct wiphy *wiphy, + const struct qlink_chandef *qch, + struct cfg80211_chan_def *chdef) +{ + chdef->center_freq1 = le16_to_cpu(qch->center_freq1); + chdef->center_freq2 = le16_to_cpu(qch->center_freq2); + chdef->width = qlink_chanwidth_to_nl(qch->width); + + switch (chdef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: + chdef->chan = ieee80211_get_channel(wiphy, chdef->center_freq1); + break; + case NL80211_CHAN_WIDTH_40: + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + case NL80211_CHAN_WIDTH_160: + chdef->chan = ieee80211_get_channel(wiphy, + chdef->center_freq1 - 10); + break; + default: + chdef->chan = NULL; + break; + } +} + +static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth) +{ + switch (nlwidth) { + case NL80211_CHAN_WIDTH_20_NOHT: + return QLINK_CHAN_WIDTH_20_NOHT; + case NL80211_CHAN_WIDTH_20: + return QLINK_CHAN_WIDTH_20; + case NL80211_CHAN_WIDTH_40: + return QLINK_CHAN_WIDTH_40; + case NL80211_CHAN_WIDTH_80: + return QLINK_CHAN_WIDTH_80; + case NL80211_CHAN_WIDTH_80P80: + return QLINK_CHAN_WIDTH_80P80; + case NL80211_CHAN_WIDTH_160: + return QLINK_CHAN_WIDTH_160; + case NL80211_CHAN_WIDTH_5: + return QLINK_CHAN_WIDTH_5; + case NL80211_CHAN_WIDTH_10: + return QLINK_CHAN_WIDTH_10; + default: + return -1; + } +} + +void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef, + struct qlink_chandef *qch) +{ + qch->center_freq1 = cpu_to_le16(chdef->center_freq1); + qch->center_freq2 = cpu_to_le16(chdef->center_freq2); + qch->width = qlink_chanwidth_nl_to_qlink(chdef->width); +} + +enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val) +{ + switch (nl_val) { + case NL80211_HIDDEN_SSID_ZERO_LEN: + return QLINK_HIDDEN_SSID_ZERO_LEN; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + return QLINK_HIDDEN_SSID_ZERO_CONTENTS; + case NL80211_HIDDEN_SSID_NOT_IN_USE: + default: + return QLINK_HIDDEN_SSID_NOT_IN_USE; + } +} diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index de06c1e20b5b..260383d6d109 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -19,6 +19,7 @@ #include <linux/types.h> #include <linux/skbuff.h> +#include <net/cfg80211.h> #include "qlink.h" @@ -62,5 +63,11 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb, u16 qlink_iface_type_to_nl_mask(u16 qlink_type); u8 qlink_chan_width_mask_to_nl(u16 qlink_mask); +void qlink_chandef_q2cfg(struct wiphy *wiphy, + const struct qlink_chandef *qch, + struct cfg80211_chan_def *chdef); +void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef, + struct qlink_chandef *qch); +enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val); #endif /* _QTN_FMAC_QLINK_UTIL_H_ */ |