@@ -361,4 +361,12 @@ struct hif_cnf_sl_configure {
__le32 status;
} __packed;
+struct hif_req_prevent_rollback {
+ __le32 magic_word; // Return an error if not equal to 0x5C8912F3
+} __packed;
+
+struct hif_cnf_prevent_rollback {
+ __le32 status;
+} __packed;
+
#endif
@@ -535,6 +535,24 @@ int hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len)
return ret;
}
+int hif_burn_prevent_rollback(struct wfx_dev *wdev, u32 magic_word)
+{
+ int ret;
+ struct hif_msg *hif;
+ struct hif_req_prevent_rollback *body = wfx_alloc_hif(sizeof(*body),
+ &hif);
+
+ if (!hif)
+ return -ENOMEM;
+ body->magic_word = cpu_to_le32(magic_word);
+ wfx_fill_header(hif, -1, HIF_REQ_ID_PREVENT_ROLLBACK, sizeof(*body));
+ ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+ if (ret == le32_to_cpu(HIF_STATUS_ROLLBACK_SUCCESS))
+ ret = 0;
+ kfree(hif);
+ return ret;
+}
+
int hif_sl_send_pub_keys(struct wfx_dev *wdev,
const u8 *pubkey, const u8 *pubkey_hmac)
{
@@ -57,6 +57,7 @@ int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
int hif_beacon_transmit(struct wfx_vif *wvif, bool enable);
int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id);
int hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len);
+int hif_burn_prevent_rollback(struct wfx_dev *wdev, u32 magic_word);
int hif_sl_set_mac_key(struct wfx_dev *wdev,
const u8 *slk_key, int destination);
int hif_sl_config(struct wfx_dev *wdev, const unsigned long *bitmap);
@@ -7,6 +7,7 @@
#include "nl80211_vendor.h"
#include "wfx.h"
#include "sta.h"
+#include "hif_tx.h"
int wfx_nl_ps_timeout(struct wiphy *wiphy, struct wireless_dev *widev,
const void *data, int data_len)
@@ -47,3 +48,25 @@ int wfx_nl_ps_timeout(struct wiphy *wiphy, struct wireless_dev *widev,
return rc;
}
+int wfx_nl_burn_antirollback(struct wiphy *wiphy, struct wireless_dev *widev,
+ const void *data, int data_len)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct wfx_dev *wdev = (struct wfx_dev *)hw->priv;
+ struct nlattr *tb[WFX_NL80211_ATTR_MAX];
+ u32 magic;
+ int rc;
+
+ rc = nla_parse(tb, WFX_NL80211_ATTR_MAX - 1, data, data_len,
+ wfx_nl_policy, NULL);
+ if (rc)
+ return rc;
+ if (!tb[WFX_NL80211_ATTR_ROLLBACK_MAGIC])
+ return -EINVAL;
+ magic = nla_get_u32(tb[WFX_NL80211_ATTR_ROLLBACK_MAGIC]);
+ rc = hif_burn_prevent_rollback(wdev, magic);
+ if (rc)
+ return -EINVAL;
+ return 0;
+}
+
@@ -16,18 +16,23 @@
int wfx_nl_ps_timeout(struct wiphy *wiphy, struct wireless_dev *widev,
const void *data, int data_len);
+int wfx_nl_burn_antirollback(struct wiphy *wiphy, struct wireless_dev *widev,
+ const void *data, int data_len);
enum {
WFX_NL80211_SUBCMD_PS_TIMEOUT = 0x10,
+ WFX_NL80211_SUBCMD_BURN_PREVENT_ROLLBACK = 0x20,
};
enum {
WFX_NL80211_ATTR_PS_TIMEOUT = 1,
+ WFX_NL80211_ATTR_ROLLBACK_MAGIC = 2,
WFX_NL80211_ATTR_MAX
};
static const struct nla_policy wfx_nl_policy[WFX_NL80211_ATTR_MAX] = {
[WFX_NL80211_ATTR_PS_TIMEOUT] = NLA_POLICY_RANGE(NLA_S32, -1, 127),
+ [WFX_NL80211_ATTR_ROLLBACK_MAGIC] = { .type = NLA_U32 },
};
static const struct wiphy_vendor_command wfx_nl80211_vendor_commands[] = {
@@ -38,6 +43,12 @@ static const struct wiphy_vendor_command wfx_nl80211_vendor_commands[] = {
.policy = wfx_nl_policy,
.doit = wfx_nl_ps_timeout,
.maxattr = WFX_NL80211_ATTR_MAX - 1,
+ }, {
+ .info.vendor_id = WFX_NL80211_ID,
+ .info.subcmd = WFX_NL80211_SUBCMD_BURN_PREVENT_ROLLBACK,
+ .policy = wfx_nl_policy,
+ .doit = wfx_nl_burn_antirollback,
+ .maxattr = WFX_NL80211_ATTR_MAX - 1,
},
};