qtnfmac: fix handling of iftype mask reported by firmware

Firmware sends supported interface type rather than mask. As a result,
types field of ieee80211_iface_limit structure may end up having
multiple iftype bits set. This leads to WARN_ON from
wiphy_verify_combinations.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Signed-off-by: Avinash Patil <avinashp@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Sergey Matyukevich 2017-07-28 02:06:52 +03:00 committed by Kalle Valo
parent c7ead2abd2
commit 41c8fa0c62
4 changed files with 20 additions and 16 deletions

View file

@ -989,7 +989,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
struct ieee80211_iface_limit *limits = NULL; struct ieee80211_iface_limit *limits = NULL;
const struct qlink_iface_limit *limit_record; const struct qlink_iface_limit *limit_record;
size_t record_count = 0, rec = 0; size_t record_count = 0, rec = 0;
u16 tlv_type, tlv_value_len, mask; u16 tlv_type, tlv_value_len;
struct qlink_iface_comb_num *comb; struct qlink_iface_comb_num *comb;
size_t tlv_full_len; size_t tlv_full_len;
const struct qlink_tlv_hdr *tlv; const struct qlink_tlv_hdr *tlv;
@ -1042,9 +1042,10 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
limit_record = (void *)tlv->val; limit_record = (void *)tlv->val;
limits[rec].max = le16_to_cpu(limit_record->max_num); limits[rec].max = le16_to_cpu(limit_record->max_num);
mask = le16_to_cpu(limit_record->type_mask); limits[rec].types = qlink_iface_type_to_nl_mask(
limits[rec].types = qlink_iface_type_mask_to_nl(mask); le16_to_cpu(limit_record->type));
/* only AP and STA modes are supported */
/* supported modes: STA, AP */
limits[rec].types &= BIT(NL80211_IFTYPE_AP) | limits[rec].types &= BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION); BIT(NL80211_IFTYPE_STATION);

View file

@ -873,7 +873,7 @@ struct qlink_tlv_hdr {
struct qlink_iface_limit { struct qlink_iface_limit {
__le16 max_num; __le16 max_num;
__le16 type_mask; __le16 type;
} __packed; } __packed;
struct qlink_iface_comb_num { struct qlink_iface_comb_num {

View file

@ -17,24 +17,27 @@
#include "qlink_util.h" #include "qlink_util.h"
u16 qlink_iface_type_mask_to_nl(u16 qlink_mask) u16 qlink_iface_type_to_nl_mask(u16 qlink_type)
{ {
u16 result = 0; u16 result = 0;
if (qlink_mask & QLINK_IFTYPE_AP) switch (qlink_type) {
case QLINK_IFTYPE_AP:
result |= BIT(NL80211_IFTYPE_AP); result |= BIT(NL80211_IFTYPE_AP);
break;
if (qlink_mask & QLINK_IFTYPE_STATION) case QLINK_IFTYPE_STATION:
result |= BIT(NL80211_IFTYPE_STATION); result |= BIT(NL80211_IFTYPE_STATION);
break;
if (qlink_mask & QLINK_IFTYPE_ADHOC) case QLINK_IFTYPE_ADHOC:
result |= BIT(NL80211_IFTYPE_ADHOC); result |= BIT(NL80211_IFTYPE_ADHOC);
break;
if (qlink_mask & QLINK_IFTYPE_MONITOR) case QLINK_IFTYPE_MONITOR:
result |= BIT(NL80211_IFTYPE_MONITOR); result |= BIT(NL80211_IFTYPE_MONITOR);
break;
if (qlink_mask & QLINK_IFTYPE_WDS) case QLINK_IFTYPE_WDS:
result |= BIT(NL80211_IFTYPE_WDS); result |= BIT(NL80211_IFTYPE_WDS);
break;
}
return result; return result;
} }

View file

@ -68,7 +68,7 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb,
memcpy(hdr->val, &tmp, sizeof(tmp)); memcpy(hdr->val, &tmp, sizeof(tmp));
} }
u16 qlink_iface_type_mask_to_nl(u16 qlink_mask); u16 qlink_iface_type_to_nl_mask(u16 qlink_type);
u8 qlink_chan_width_mask_to_nl(u16 qlink_mask); u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
#endif /* _QTN_FMAC_QLINK_UTIL_H_ */ #endif /* _QTN_FMAC_QLINK_UTIL_H_ */