* @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
  *     %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
  * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
- *     %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER
- *     attributes.
+ *     %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
+ *     and %NL80211_ATTR_KEY_SEQ attributes.
  * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
  *     or %NL80211_ATTR_MAC.
  *
 
                return -EINVAL;
        }
 
-       key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
+       key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key,
+                                 params->seq_len, params->seq);
        if (!key)
                return -ENOMEM;
 
 
 struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
                                          int idx,
                                          size_t key_len,
-                                         const u8 *key_data)
+                                         const u8 *key_data,
+                                         size_t seq_len, const u8 *seq)
 {
        struct ieee80211_key *key;
+       int i, j;
 
        BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
 
        case ALG_TKIP:
                key->conf.iv_len = TKIP_IV_LEN;
                key->conf.icv_len = TKIP_ICV_LEN;
+               if (seq && seq_len == 6) {
+                       for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+                               key->u.tkip.rx[i].iv32 =
+                                       get_unaligned_le32(&seq[2]);
+                               key->u.tkip.rx[i].iv16 =
+                                       get_unaligned_le16(seq);
+                       }
+               }
                break;
        case ALG_CCMP:
                key->conf.iv_len = CCMP_HDR_LEN;
                key->conf.icv_len = CCMP_MIC_LEN;
+               if (seq && seq_len == CCMP_PN_LEN) {
+                       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+                               for (j = 0; j < CCMP_PN_LEN; j++)
+                                       key->u.ccmp.rx_pn[i][j] =
+                                               seq[CCMP_PN_LEN - j - 1];
+               }
                break;
        case ALG_AES_CMAC:
                key->conf.iv_len = 0;
                key->conf.icv_len = sizeof(struct ieee80211_mmie);
+               if (seq && seq_len == 6)
+                       for (j = 0; j < 6; j++)
+                               key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
                break;
        }
        memcpy(key->conf.key, key_data, key_len);
 
 struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
                                          int idx,
                                          size_t key_len,
-                                         const u8 *key_data);
+                                         const u8 *key_data,
+                                         size_t seq_len, const u8 *seq);
 /*
  * Insert a key into data structures (sdata, sta if necessary)
  * to make it used, free old key.
 
                params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
        }
 
+       if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
+               params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
+               params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
+       }
+
        if (info->attrs[NL80211_ATTR_KEY_IDX])
                key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 
 
        params.key_len = ext->key_len;
        params.cipher = cipher;
 
+       if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+               params.seq = ext->rx_seq;
+               params.seq_len = 6;
+       }
+
        return cfg80211_set_encryption(
                        rdev, dev, addr, remove,
                        ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,