wil6210: support rx key setting for all TIDs
authorMaya Erez <qca_merez@qca.qualcomm.com>
Thu, 18 Aug 2016 13:52:12 +0000 (16:52 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Fri, 19 Aug 2016 10:11:06 +0000 (13:11 +0300)
According to the spec the PN should be calculated per TID.
In the current implementation, the PN and key_set were set
only for TID 0, therefore only traffic for TID 0 was supported.
In order to support all TIDs, the key_set and PN should be set
for all the TIDs.

Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/wil6210/cfg80211.c

index f0e1175fb76aed8327e1233903ec0437f2a672e7..110098e9603b663ab553a141b2abf57001cb32a8 100644 (file)
@@ -760,14 +760,11 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
        return rc;
 }
 
-static struct wil_tid_crypto_rx_single *
-wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
-                   enum wmi_key_usage key_usage, const u8 *mac_addr)
+static struct wil_sta_info *
+wil_find_sta_by_key_usage(struct wil6210_priv *wil,
+                         enum wmi_key_usage key_usage, const u8 *mac_addr)
 {
        int cid = -EINVAL;
-       int tid = 0;
-       struct wil_sta_info *s;
-       struct wil_tid_crypto_rx *c;
 
        if (key_usage == WMI_KEY_USE_TX_GROUP)
                return NULL; /* not needed */
@@ -778,18 +775,72 @@ wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
        else if (key_usage == WMI_KEY_USE_RX_GROUP)
                cid = wil_find_cid_by_idx(wil, 0);
        if (cid < 0) {
-               wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr,
-                       key_usage_str[key_usage], key_index);
+               wil_err(wil, "No CID for %pM %s\n", mac_addr,
+                       key_usage_str[key_usage]);
                return ERR_PTR(cid);
        }
 
-       s = &wil->sta[cid];
-       if (key_usage == WMI_KEY_USE_PAIRWISE)
-               c = &s->tid_crypto_rx[tid];
-       else
-               c = &s->group_crypto_rx;
+       return &wil->sta[cid];
+}
+
+static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
+                             struct wil_sta_info *cs,
+                             struct key_params *params)
+{
+       struct wil_tid_crypto_rx_single *cc;
+       int tid;
+
+       if (!cs)
+               return;
 
-       return &c->key_id[key_index];
+       switch (key_usage) {
+       case WMI_KEY_USE_PAIRWISE:
+               for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
+                       cc = &cs->tid_crypto_rx[tid].key_id[key_index];
+                       if (params->seq)
+                               memcpy(cc->pn, params->seq,
+                                      IEEE80211_GCMP_PN_LEN);
+                       else
+                               memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
+                       cc->key_set = true;
+               }
+               break;
+       case WMI_KEY_USE_RX_GROUP:
+               cc = &cs->group_crypto_rx.key_id[key_index];
+               if (params->seq)
+                       memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
+               else
+                       memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
+               cc->key_set = true;
+               break;
+       default:
+               break;
+       }
+}
+
+static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage,
+                          struct wil_sta_info *cs)
+{
+       struct wil_tid_crypto_rx_single *cc;
+       int tid;
+
+       if (!cs)
+               return;
+
+       switch (key_usage) {
+       case WMI_KEY_USE_PAIRWISE:
+               for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
+                       cc = &cs->tid_crypto_rx[tid].key_id[key_index];
+                       cc->key_set = false;
+               }
+               break;
+       case WMI_KEY_USE_RX_GROUP:
+               cc = &cs->group_crypto_rx.key_id[key_index];
+               cc->key_set = false;
+               break;
+       default:
+               break;
+       }
 }
 
 static int wil_cfg80211_add_key(struct wiphy *wiphy,
@@ -801,24 +852,26 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
        int rc;
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
        enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
-       struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
-                                                                 key_index,
-                                                                 key_usage,
-                                                                 mac_addr);
+       struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
+                                                           mac_addr);
+
+       if (!params) {
+               wil_err(wil, "NULL params\n");
+               return -EINVAL;
+       }
 
        wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__,
                     mac_addr, key_usage_str[key_usage], key_index,
                     params->seq_len, params->seq);
 
-       if (IS_ERR(cc)) {
+       if (IS_ERR(cs)) {
                wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n",
                        __func__, mac_addr, key_usage_str[key_usage], key_index,
                        params->seq_len, params->seq);
                return -EINVAL;
        }
 
-       if (cc)
-               cc->key_set = false;
+       wil_del_rx_key(key_index, key_usage, cs);
 
        if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
                wil_err(wil,
@@ -831,13 +884,8 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
 
        rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
                                params->key, key_usage);
-       if ((rc == 0) && cc) {
-               if (params->seq)
-                       memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
-               else
-                       memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
-               cc->key_set = true;
-       }
+       if (!rc)
+               wil_set_crypto_rx(key_index, key_usage, cs, params);
 
        return rc;
 }
@@ -849,20 +897,18 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
        enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
-       struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
-                                                                 key_index,
-                                                                 key_usage,
-                                                                 mac_addr);
+       struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
+                                                           mac_addr);
 
        wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr,
                     key_usage_str[key_usage], key_index);
 
-       if (IS_ERR(cc))
+       if (IS_ERR(cs))
                wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__,
                         mac_addr, key_usage_str[key_usage], key_index);
 
-       if (!IS_ERR_OR_NULL(cc))
-               cc->key_set = false;
+       if (!IS_ERR_OR_NULL(cs))
+               wil_del_rx_key(key_index, key_usage, cs);
 
        return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
 }