qtnfmac: process HE capabilities requests
Pass HE interface type data requests between firmware and driver. Signed-off-by: Mikhail Karpenko <mkarpenko@quantenna.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
be4f00cf15
commit
df0af4c7ba
@ -214,6 +214,20 @@ static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qtnf_cmd_tlv_ie_ext_add(struct sk_buff *cmd_skb, u8 eid_ext,
|
||||||
|
const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct qlink_tlv_ext_ie *tlv;
|
||||||
|
|
||||||
|
tlv = (struct qlink_tlv_ext_ie *)skb_put(cmd_skb, sizeof(*tlv) + len);
|
||||||
|
tlv->hdr.type = cpu_to_le16(WLAN_EID_EXTENSION);
|
||||||
|
tlv->hdr.len = cpu_to_le16(sizeof(*tlv) + len - sizeof(tlv->hdr));
|
||||||
|
tlv->eid_ext = eid_ext;
|
||||||
|
|
||||||
|
if (len && buf)
|
||||||
|
memcpy(tlv->ie_data, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
|
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
|
||||||
const struct cfg80211_ap_settings *s)
|
const struct cfg80211_ap_settings *s)
|
||||||
{
|
{
|
||||||
@ -309,6 +323,10 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
|
|||||||
memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
|
memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->he_cap)
|
||||||
|
qtnf_cmd_tlv_ie_ext_add(cmd_skb, WLAN_EID_EXT_HE_CAPABILITY,
|
||||||
|
s->he_cap, sizeof(*s->he_cap));
|
||||||
|
|
||||||
if (s->acl) {
|
if (s->acl) {
|
||||||
size_t acl_size = struct_size(s->acl, mac_addrs,
|
size_t acl_size = struct_size(s->acl, mac_addrs,
|
||||||
s->acl->n_acl_entries);
|
s->acl->n_acl_entries);
|
||||||
@ -1292,6 +1310,69 @@ static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info,
|
|||||||
memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
|
memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qtnf_cmd_conv_iftype(struct ieee80211_sband_iftype_data
|
||||||
|
*iftype_data,
|
||||||
|
const struct qlink_sband_iftype_data
|
||||||
|
*qlink_data)
|
||||||
|
{
|
||||||
|
iftype_data->types_mask = le16_to_cpu(qlink_data->types_mask);
|
||||||
|
|
||||||
|
iftype_data->he_cap.has_he = true;
|
||||||
|
memcpy(&iftype_data->he_cap.he_cap_elem, &qlink_data->he_cap_elem,
|
||||||
|
sizeof(qlink_data->he_cap_elem));
|
||||||
|
memcpy(iftype_data->he_cap.ppe_thres, qlink_data->ppe_thres,
|
||||||
|
ARRAY_SIZE(qlink_data->ppe_thres));
|
||||||
|
|
||||||
|
iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80 =
|
||||||
|
qlink_data->he_mcs_nss_supp.rx_mcs_80;
|
||||||
|
iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80 =
|
||||||
|
qlink_data->he_mcs_nss_supp.tx_mcs_80;
|
||||||
|
iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_160 =
|
||||||
|
qlink_data->he_mcs_nss_supp.rx_mcs_160;
|
||||||
|
iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160 =
|
||||||
|
qlink_data->he_mcs_nss_supp.tx_mcs_160;
|
||||||
|
iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_80p80 =
|
||||||
|
qlink_data->he_mcs_nss_supp.rx_mcs_80p80;
|
||||||
|
iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80p80 =
|
||||||
|
qlink_data->he_mcs_nss_supp.tx_mcs_80p80;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qtnf_cmd_band_fill_iftype(const u8 *data,
|
||||||
|
struct ieee80211_supported_band *band)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct ieee80211_sband_iftype_data *iftype_data;
|
||||||
|
const struct qlink_tlv_iftype_data *tlv =
|
||||||
|
(const struct qlink_tlv_iftype_data *)data;
|
||||||
|
size_t payload_len = tlv->n_iftype_data * sizeof(*tlv->iftype_data) +
|
||||||
|
sizeof(*tlv) -
|
||||||
|
sizeof(struct qlink_tlv_hdr);
|
||||||
|
|
||||||
|
if (tlv->hdr.len != cpu_to_le16(payload_len)) {
|
||||||
|
pr_err("bad IFTYPE_DATA TLV len %u\n", tlv->hdr.len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(band->iftype_data);
|
||||||
|
band->iftype_data = NULL;
|
||||||
|
band->n_iftype_data = tlv->n_iftype_data;
|
||||||
|
if (band->n_iftype_data == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
iftype_data = kcalloc(band->n_iftype_data, sizeof(*iftype_data),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!iftype_data) {
|
||||||
|
band->n_iftype_data = 0;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
band->iftype_data = iftype_data;
|
||||||
|
|
||||||
|
for (i = 0; i < band->n_iftype_data; i++)
|
||||||
|
qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
|
qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
|
||||||
struct qlink_resp_band_info_get *resp,
|
struct qlink_resp_band_info_get *resp,
|
||||||
@ -1305,6 +1386,7 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
|
|||||||
struct ieee80211_channel *chan;
|
struct ieee80211_channel *chan;
|
||||||
unsigned int chidx = 0;
|
unsigned int chidx = 0;
|
||||||
u32 qflags;
|
u32 qflags;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
memset(&band->ht_cap, 0, sizeof(band->ht_cap));
|
memset(&band->ht_cap, 0, sizeof(band->ht_cap));
|
||||||
memset(&band->vht_cap, 0, sizeof(band->vht_cap));
|
memset(&band->vht_cap, 0, sizeof(band->vht_cap));
|
||||||
@ -1442,6 +1524,12 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
|
|||||||
qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
|
qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
|
||||||
&band->vht_cap);
|
&band->vht_cap);
|
||||||
break;
|
break;
|
||||||
|
case QTN_TLV_ID_IFTYPE_DATA:
|
||||||
|
ret = qtnf_cmd_band_fill_iftype((const uint8_t *)tlv,
|
||||||
|
band);
|
||||||
|
if (ret)
|
||||||
|
goto error_ret;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_warn("unknown TLV type: %#x\n", tlv_type);
|
pr_warn("unknown TLV type: %#x\n", tlv_type);
|
||||||
break;
|
break;
|
||||||
@ -1469,7 +1557,7 @@ error_ret:
|
|||||||
band->channels = NULL;
|
band->channels = NULL;
|
||||||
band->n_channels = 0;
|
band->n_channels = 0;
|
||||||
|
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac,
|
static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac,
|
||||||
|
@ -543,6 +543,9 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
|
|||||||
if (!wiphy->bands[band])
|
if (!wiphy->bands[band])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
kfree(wiphy->bands[band]->iftype_data);
|
||||||
|
wiphy->bands[band]->n_iftype_data = 0;
|
||||||
|
|
||||||
kfree(wiphy->bands[band]->channels);
|
kfree(wiphy->bands[band]->channels);
|
||||||
wiphy->bands[band]->n_channels = 0;
|
wiphy->bands[band]->n_channels = 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user