Commit 9bf22f2c authored by Samuel Ortiz's avatar Samuel Ortiz Committed by John W. Linville

iwmc3200wifi: Implement cfg80211 PMKSA API

We need to implement the PMKSA API for proper WPA2 pre-auth and fast
re-association. Our fullmac device generates all (re-)assoc IEs, and thus it
needs the right PMKIDs. With this implementation we now get them from
wpa_supplicant.
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2944b2c2
...@@ -725,6 +725,33 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, ...@@ -725,6 +725,33 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
CFG_POWER_INDEX, iwm->conf.power_index); CFG_POWER_INDEX, iwm->conf.power_index);
} }
int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_pmksa *pmksa)
{
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
}
int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_pmksa *pmksa)
{
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
}
int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
{
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
struct cfg80211_pmksa pmksa;
memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
}
static struct cfg80211_ops iwm_cfg80211_ops = { static struct cfg80211_ops iwm_cfg80211_ops = {
.change_virtual_intf = iwm_cfg80211_change_iface, .change_virtual_intf = iwm_cfg80211_change_iface,
.add_key = iwm_cfg80211_add_key, .add_key = iwm_cfg80211_add_key,
...@@ -741,6 +768,9 @@ static struct cfg80211_ops iwm_cfg80211_ops = { ...@@ -741,6 +768,9 @@ static struct cfg80211_ops iwm_cfg80211_ops = {
.set_tx_power = iwm_cfg80211_set_txpower, .set_tx_power = iwm_cfg80211_set_txpower,
.get_tx_power = iwm_cfg80211_get_txpower, .get_tx_power = iwm_cfg80211_get_txpower,
.set_power_mgmt = iwm_cfg80211_set_power_mgmt, .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
.set_pmksa = iwm_cfg80211_set_pmksa,
.del_pmksa = iwm_cfg80211_del_pmksa,
.flush_pmksa = iwm_cfg80211_flush_pmksa,
}; };
static const u32 cipher_suites[] = { static const u32 cipher_suites[] = {
...@@ -786,6 +816,7 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) ...@@ -786,6 +816,7 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
set_wiphy_dev(wdev->wiphy, dev); set_wiphy_dev(wdev->wiphy, dev);
wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX; wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC); BIT(NL80211_IFTYPE_ADHOC);
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz; wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
......
...@@ -960,3 +960,25 @@ int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm, ...@@ -960,3 +960,25 @@ int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
sizeof(struct iwm_umac_cmd_stop_resume_tx)); sizeof(struct iwm_umac_cmd_stop_resume_tx));
} }
int iwm_send_pmkid_update(struct iwm_priv *iwm,
struct cfg80211_pmksa *pmksa, u32 command)
{
struct iwm_umac_pmkid_update update;
int ret;
memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
update.command = cpu_to_le32(command);
memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
ret = iwm_send_wifi_if_cmd(iwm, &update,
sizeof(struct iwm_umac_pmkid_update), 0);
if (ret) {
IWM_ERR(iwm, "PMKID update command failed\n");
return ret;
}
return 0;
}
...@@ -458,6 +458,17 @@ struct iwm_umac_cmd_stop_resume_tx { ...@@ -458,6 +458,17 @@ struct iwm_umac_cmd_stop_resume_tx {
u16 reserved; u16 reserved;
} __attribute__ ((packed)); } __attribute__ ((packed));
#define IWM_CMD_PMKID_ADD 1
#define IWM_CMD_PMKID_DEL 2
#define IWM_CMD_PMKID_FLUSH 3
struct iwm_umac_pmkid_update {
__le32 command;
u8 bssid[ETH_ALEN];
__le16 reserved;
u8 pmkid[WLAN_PMKID_LEN];
} __attribute__ ((packed));
/* LMAC commands */ /* LMAC commands */
int iwm_read_mac(struct iwm_priv *iwm, u8 *mac); int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
int iwm_send_prio_table(struct iwm_priv *iwm); int iwm_send_prio_table(struct iwm_priv *iwm);
...@@ -488,6 +499,8 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, ...@@ -488,6 +499,8 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len); int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm, int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
struct iwm_umac_notif_stop_resume_tx *ntf); struct iwm_umac_notif_stop_resume_tx *ntf);
int iwm_send_pmkid_update(struct iwm_priv *iwm,
struct cfg80211_pmksa *pmksa, u32 command);
/* UDMA commands */ /* UDMA commands */
int iwm_target_reset(struct iwm_priv *iwm); int iwm_target_reset(struct iwm_priv *iwm);
......
...@@ -298,6 +298,7 @@ struct iwm_udma_out_wifi_hdr { ...@@ -298,6 +298,7 @@ struct iwm_udma_out_wifi_hdr {
#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B #define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B
#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C #define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C
#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E #define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E
#define UMAC_WIFI_IF_CMD_PMKID_UPDATE 0x1F
#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20 #define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20
/* UMAC WiFi interface ports */ /* UMAC WiFi interface ports */
...@@ -771,6 +772,7 @@ struct iwm_umac_notif_stop_resume_tx { ...@@ -771,6 +772,7 @@ struct iwm_umac_notif_stop_resume_tx {
__le16 stop_resume_tid_msk; /* tid bitmask */ __le16 stop_resume_tid_msk; /* tid bitmask */
} __attribute__ ((packed)); } __attribute__ ((packed));
#define UMAC_MAX_NUM_PMKIDS 4
/* WiFi interface wrapper header */ /* WiFi interface wrapper header */
struct iwm_umac_wifi_if { struct iwm_umac_wifi_if {
......
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