Commit 310cd5dd authored by Igor Mitsyanko's avatar Igor Mitsyanko Committed by Kalle Valo

qtnfmac: pass hardware capabilities in TLV element

To support any number of capabilities bits in the future,
replace u32 capabilities bitmask by array. Pass
capabilities from firmware using TLV element.
Signed-off-by: default avatarIgor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent a3ebb033
...@@ -248,7 +248,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, ...@@ -248,7 +248,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
goto error_del_vif; goto error_del_vif;
} }
if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) {
ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex);
if (ret) { if (ret) {
unregister_netdevice(vif->netdev); unregister_netdevice(vif->netdev);
...@@ -1080,10 +1080,10 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus) ...@@ -1080,10 +1080,10 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
struct wiphy *wiphy; struct wiphy *wiphy;
if (qtnf_dfs_offload_get() && if (qtnf_dfs_offload_get() &&
(bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_DFS_OFFLOAD))
qtn_cfg80211_ops.start_radar_detection = NULL; qtn_cfg80211_ops.start_radar_detection = NULL;
if (!(bus->hw_info.hw_capab & QLINK_HW_CAPAB_PWR_MGMT)) if (!qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_PWR_MGMT))
qtn_cfg80211_ops.set_power_mgmt = NULL; qtn_cfg80211_ops.set_power_mgmt = NULL;
wiphy = wiphy_new(&qtn_cfg80211_ops, sizeof(struct qtnf_wmac)); wiphy = wiphy_new(&qtn_cfg80211_ops, sizeof(struct qtnf_wmac));
...@@ -1166,10 +1166,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) ...@@ -1166,10 +1166,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
if (qtnf_dfs_offload_get() && if (qtnf_dfs_offload_get() &&
(hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_DFS_OFFLOAD))
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL) if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SCAN_DWELL))
wiphy_ext_feature_set(wiphy, wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_SET_SCAN_DWELL); NL80211_EXT_FEATURE_SET_SCAN_DWELL);
...@@ -1185,16 +1185,16 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) ...@@ -1185,16 +1185,16 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
ether_addr_copy(wiphy->perm_addr, mac->macaddr); ether_addr_copy(wiphy->perm_addr, mac->macaddr);
if (hw_info->hw_capab & QLINK_HW_CAPAB_STA_INACT_TIMEOUT) if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_STA_INACT_TIMEOUT))
wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR) if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR))
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN)) if (!qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_OBSS_SCAN))
wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN; wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
if (hw_info->hw_capab & QLINK_HW_CAPAB_SAE) if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SAE))
wiphy->features |= NL80211_FEATURE_SAE; wiphy->features |= NL80211_FEATURE_SAE;
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -1205,7 +1205,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) ...@@ -1205,7 +1205,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
regdomain_is_known = isalpha(mac->rd->alpha2[0]) && regdomain_is_known = isalpha(mac->rd->alpha2[0]) &&
isalpha(mac->rd->alpha2[1]); isalpha(mac->rd->alpha2[1]);
if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) { if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_REG_UPDATE)) {
wiphy->reg_notifier = qtnf_cfg80211_reg_notifier; wiphy->reg_notifier = qtnf_cfg80211_reg_notifier;
if (mac->rd->alpha2[0] == '9' && mac->rd->alpha2[1] == '9') { if (mac->rd->alpha2[0] == '9' && mac->rd->alpha2[1] == '9') {
......
...@@ -599,7 +599,7 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo, ...@@ -599,7 +599,7 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo,
tlv_len = le16_to_cpu(tlv->len); tlv_len = le16_to_cpu(tlv->len);
switch (le16_to_cpu(tlv->type)) { switch (le16_to_cpu(tlv->type)) {
case QTN_TLV_ID_STA_STATS_MAP: case QTN_TLV_ID_BITMAP:
map_len = tlv_len; map_len = tlv_len;
map = tlv->val; map = tlv->val;
break; break;
...@@ -895,14 +895,13 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, ...@@ -895,14 +895,13 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
const char *uboot_ver = NULL; const char *uboot_ver = NULL;
u32 hw_ver = 0; u32 hw_ver = 0;
u16 tlv_type; u16 tlv_type;
u16 tlv_value_len; u16 tlv_len;
hwinfo->num_mac = resp->num_mac; hwinfo->num_mac = resp->num_mac;
hwinfo->mac_bitmap = resp->mac_bitmap; hwinfo->mac_bitmap = resp->mac_bitmap;
hwinfo->fw_ver = le32_to_cpu(resp->fw_ver); hwinfo->fw_ver = le32_to_cpu(resp->fw_ver);
hwinfo->total_tx_chain = resp->total_tx_chain; hwinfo->total_tx_chain = resp->total_tx_chain;
hwinfo->total_rx_chain = resp->total_rx_chain; hwinfo->total_rx_chain = resp->total_rx_chain;
hwinfo->hw_capab = le32_to_cpu(resp->hw_capab);
bld_tmstamp = le32_to_cpu(resp->bld_tmstamp); bld_tmstamp = le32_to_cpu(resp->bld_tmstamp);
plat_id = le32_to_cpu(resp->plat_id); plat_id = le32_to_cpu(resp->plat_id);
...@@ -912,11 +911,11 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, ...@@ -912,11 +911,11 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
while (info_len >= sizeof(*tlv)) { while (info_len >= sizeof(*tlv)) {
tlv_type = le16_to_cpu(tlv->type); tlv_type = le16_to_cpu(tlv->type);
tlv_value_len = le16_to_cpu(tlv->len); tlv_len = le16_to_cpu(tlv->len);
if (tlv_value_len + sizeof(*tlv) > info_len) { if (tlv_len + sizeof(*tlv) > info_len) {
pr_warn("malformed TLV 0x%.2X; LEN: %u\n", pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
tlv_type, tlv_value_len); tlv_type, tlv_len);
return -EINVAL; return -EINVAL;
} }
...@@ -945,12 +944,16 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, ...@@ -945,12 +944,16 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
case QTN_TLV_ID_MAX_SCAN_SSIDS: case QTN_TLV_ID_MAX_SCAN_SSIDS:
hwinfo->max_scan_ssids = *tlv->val; hwinfo->max_scan_ssids = *tlv->val;
break; break;
case QTN_TLV_ID_BITMAP:
memcpy(hwinfo->hw_capab, tlv->val,
min(sizeof(hwinfo->hw_capab), (size_t)tlv_len));
break;
default: default:
break; break;
} }
info_len -= tlv_value_len + sizeof(*tlv); info_len -= tlv_len + sizeof(*tlv);
tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_len);
} }
pr_info("\nBuild name: %s\n" pr_info("\nBuild name: %s\n"
......
...@@ -497,7 +497,7 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif, ...@@ -497,7 +497,7 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
dev->tx_queue_len = 100; dev->tx_queue_len = 100;
dev->ethtool_ops = &qtnf_ethtool_ops; dev->ethtool_ops = &qtnf_ethtool_ops;
if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE))
dev->needed_tailroom = sizeof(struct qtnf_frame_meta_info); dev->needed_tailroom = sizeof(struct qtnf_frame_meta_info);
qdev_vif = netdev_priv(dev); qdev_vif = netdev_priv(dev);
...@@ -639,7 +639,7 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) ...@@ -639,7 +639,7 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid)
goto error_del_vif; goto error_del_vif;
} }
if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) {
ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex);
if (ret) if (ret)
goto error; goto error;
...@@ -705,7 +705,8 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb, ...@@ -705,7 +705,8 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb,
info->linking ? "add" : "del"); info->linking ? "add" : "del");
if (IS_ENABLED(CONFIG_NET_SWITCHDEV) && if (IS_ENABLED(CONFIG_NET_SWITCHDEV) &&
(bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE)) { qtnf_hwcap_is_set(&bus->hw_info,
QLINK_HW_CAPAB_HW_BRIDGE)) {
if (info->linking) if (info->linking)
br_domain = brdev->ifindex; br_domain = brdev->ifindex;
else else
...@@ -772,7 +773,7 @@ int qtnf_core_attach(struct qtnf_bus *bus) ...@@ -772,7 +773,7 @@ int qtnf_core_attach(struct qtnf_bus *bus)
goto error; goto error;
} }
if ((bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) && if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE) &&
bus->bus_ops->data_tx_use_meta_set) bus->bus_ops->data_tx_use_meta_set)
bus->bus_ops->data_tx_use_meta_set(bus, true); bus->bus_ops->data_tx_use_meta_set(bus, true);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "qlink.h" #include "qlink.h"
#include "trans.h" #include "trans.h"
#include "qlink_util.h"
#undef pr_fmt #undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
...@@ -121,12 +122,12 @@ struct qtnf_hw_info { ...@@ -121,12 +122,12 @@ struct qtnf_hw_info {
u8 num_mac; u8 num_mac;
u8 mac_bitmap; u8 mac_bitmap;
u32 fw_ver; u32 fw_ver;
u32 hw_capab;
u8 total_tx_chain; u8 total_tx_chain;
u8 total_rx_chain; u8 total_rx_chain;
char fw_version[ETHTOOL_FWVERS_LEN]; char fw_version[ETHTOOL_FWVERS_LEN];
u32 hw_version; u32 hw_version;
u8 max_scan_ssids; u8 max_scan_ssids;
u8 hw_capab[QLINK_HW_CAPAB_NUM / BITS_PER_BYTE + 1];
}; };
struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac); struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
...@@ -160,4 +161,11 @@ static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev) ...@@ -160,4 +161,11 @@ static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
return *((void **)netdev_priv(dev)); return *((void **)netdev_priv(dev));
} }
static inline bool qtnf_hwcap_is_set(const struct qtnf_hw_info *info,
unsigned int bit)
{
return qtnf_utils_is_bit_set(info->hw_capab, bit,
sizeof(info->hw_capab));
}
#endif /* _QTN_FMAC_CORE_H_ */ #endif /* _QTN_FMAC_CORE_H_ */
...@@ -73,15 +73,24 @@ struct qlink_msg_header { ...@@ -73,15 +73,24 @@ struct qlink_msg_header {
* @QLINK_HW_CAPAB_HW_BRIDGE: device has hardware switch capabilities. * @QLINK_HW_CAPAB_HW_BRIDGE: device has hardware switch capabilities.
*/ */
enum qlink_hw_capab { enum qlink_hw_capab {
QLINK_HW_CAPAB_REG_UPDATE = BIT(0), QLINK_HW_CAPAB_REG_UPDATE = 0,
QLINK_HW_CAPAB_STA_INACT_TIMEOUT = BIT(1), QLINK_HW_CAPAB_STA_INACT_TIMEOUT,
QLINK_HW_CAPAB_DFS_OFFLOAD = BIT(2), QLINK_HW_CAPAB_DFS_OFFLOAD,
QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3), QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR,
QLINK_HW_CAPAB_PWR_MGMT = BIT(4), QLINK_HW_CAPAB_PWR_MGMT,
QLINK_HW_CAPAB_OBSS_SCAN = BIT(5), QLINK_HW_CAPAB_OBSS_SCAN,
QLINK_HW_CAPAB_SCAN_DWELL = BIT(6), QLINK_HW_CAPAB_SCAN_DWELL,
QLINK_HW_CAPAB_SAE = BIT(8), QLINK_HW_CAPAB_SAE,
QLINK_HW_CAPAB_HW_BRIDGE = BIT(9), QLINK_HW_CAPAB_HW_BRIDGE,
QLINK_HW_CAPAB_NUM
};
/**
* enum qlink_driver_capab - host driver capabilities.
*
*/
enum qlink_driver_capab {
QLINK_DRV_CAPAB_NUM = 0
}; };
enum qlink_iface_type { enum qlink_iface_type {
...@@ -990,7 +999,6 @@ struct qlink_resp_get_mac_info { ...@@ -990,7 +999,6 @@ struct qlink_resp_get_mac_info {
* Description of wireless hardware capabilities and features. * Description of wireless hardware capabilities and features.
* *
* @fw_ver: wireless hardware firmware version. * @fw_ver: wireless hardware firmware version.
* @hw_capab: Bitmap of capabilities supported by firmware.
* @num_mac: Number of separate physical radio devices provided by hardware. * @num_mac: Number of separate physical radio devices provided by hardware.
* @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware. * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware.
* @total_tx_chains: total number of transmit chains used by device. * @total_tx_chains: total number of transmit chains used by device.
...@@ -1000,7 +1008,6 @@ struct qlink_resp_get_mac_info { ...@@ -1000,7 +1008,6 @@ struct qlink_resp_get_mac_info {
struct qlink_resp_get_hw_info { struct qlink_resp_get_hw_info {
struct qlink_resp rhdr; struct qlink_resp rhdr;
__le32 fw_ver; __le32 fw_ver;
__le32 hw_capab;
__le32 bld_tmstamp; __le32 bld_tmstamp;
__le32 plat_id; __le32 plat_id;
__le32 hw_ver; __le32 hw_ver;
...@@ -1337,11 +1344,15 @@ struct qlink_event_mic_failure { ...@@ -1337,11 +1344,15 @@ struct qlink_event_mic_failure {
/** /**
* enum qlink_tlv_id - list of TLVs that Qlink messages can carry * enum qlink_tlv_id - list of TLVs that Qlink messages can carry
* *
* @QTN_TLV_ID_STA_STATS_MAP: a bitmap of &enum qlink_sta_info, used to * @QTN_TLV_ID_BITMAP: a data representing a bitmap that is used together with
* indicate which statistic carried in QTN_TLV_ID_STA_STATS is valid. * other TLVs:
* &enum qlink_sta_info used to indicate which statistic carried in
* QTN_TLV_ID_STA_STATS is valid.
* &enum qlink_hw_capab listing wireless card capabilities.
* &enum qlink_driver_capab listing driver/host system capabilities.
* @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by
* &struct qlink_sta_stats. Valid values are marked as such in a bitmap * &struct qlink_sta_stats. Valid values are marked as such in a bitmap
* carried by QTN_TLV_ID_STA_STATS_MAP. * carried by QTN_TLV_ID_BITMAP.
* @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan * @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan
* for in any given scan. * for in any given scan.
* @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active
...@@ -1361,7 +1372,7 @@ enum qlink_tlv_id { ...@@ -1361,7 +1372,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_REG_RULE = 0x0207, QTN_TLV_ID_REG_RULE = 0x0207,
QTN_TLV_ID_CHANNEL = 0x020F, QTN_TLV_ID_CHANNEL = 0x020F,
QTN_TLV_ID_CHANDEF = 0x0210, QTN_TLV_ID_CHANDEF = 0x0210,
QTN_TLV_ID_STA_STATS_MAP = 0x0211, QTN_TLV_ID_BITMAP = 0x0211,
QTN_TLV_ID_STA_STATS = 0x0212, QTN_TLV_ID_STA_STATS = 0x0212,
QTN_TLV_ID_COVERAGE_CLASS = 0x0213, QTN_TLV_ID_COVERAGE_CLASS = 0x0213,
QTN_TLV_ID_IFACE_LIMIT = 0x0214, QTN_TLV_ID_IFACE_LIMIT = 0x0214,
...@@ -1596,7 +1607,7 @@ struct qlink_chan_stats { ...@@ -1596,7 +1607,7 @@ struct qlink_chan_stats {
* *
* Used to indicate which statistics values in &struct qlink_sta_stats * Used to indicate which statistics values in &struct qlink_sta_stats
* are valid. Individual values are used to fill a bitmap carried in a * are valid. Individual values are used to fill a bitmap carried in a
* payload of QTN_TLV_ID_STA_STATS_MAP. * payload of QTN_TLV_ID_BITMAP.
* *
* @QLINK_STA_INFO_CONNECTED_TIME: connected_time value is valid. * @QLINK_STA_INFO_CONNECTED_TIME: connected_time value is valid.
* @QLINK_STA_INFO_INACTIVE_TIME: inactive_time value is valid. * @QLINK_STA_INFO_INACTIVE_TIME: inactive_time value is valid.
...@@ -1660,7 +1671,7 @@ struct qlink_sta_info_rate { ...@@ -1660,7 +1671,7 @@ struct qlink_sta_info_rate {
* Carries statistics of a STA. Not all fields may be filled with * Carries statistics of a STA. Not all fields may be filled with
* valid values. Valid fields should be indicated as such using a bitmap of * valid values. Valid fields should be indicated as such using a bitmap of
* &enum qlink_sta_info. Bitmap is carried separately in a payload of * &enum qlink_sta_info. Bitmap is carried separately in a payload of
* QTN_TLV_ID_STA_STATS_MAP. * QTN_TLV_ID_BITMAP.
*/ */
struct qlink_sta_stats { struct qlink_sta_stats {
__le64 rx_bytes; __le64 rx_bytes;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment