diff options
author | Abhijeet Kolekar <abhijeet.kolekar@intel.com> | 2009-02-27 19:21:21 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-05 14:39:36 -0500 |
commit | 6e21f15cac2c6c25b6a5874a98420e1b9064f0c1 (patch) | |
tree | 9d580956e43f024055d0093df1c2e3ce905f3024 /drivers/net/wireless/iwlwifi/iwl3945-base.c | |
parent | 7c4cbb6ee0a55885d697a5b07b6c4c8fd10d573a (diff) |
iwl3945: unify set key flow with iwlwifi
unify the set key flow with iwlwifi.
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Acked-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 172 |
1 files changed, 118 insertions, 54 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4dbaf04c5f51..96672b691946 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -407,6 +407,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
407 | staging_rxon->reserved4 = 0; | 407 | staging_rxon->reserved4 = 0; |
408 | staging_rxon->reserved5 = 0; | 408 | staging_rxon->reserved5 = 0; |
409 | 409 | ||
410 | iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); | ||
411 | |||
410 | /* Apply the new configuration */ | 412 | /* Apply the new configuration */ |
411 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | 413 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, |
412 | sizeof(struct iwl3945_rxon_cmd), | 414 | sizeof(struct iwl3945_rxon_cmd), |
@@ -456,25 +458,24 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
456 | return 0; | 458 | return 0; |
457 | } | 459 | } |
458 | 460 | ||
459 | static int iwl3945_update_sta_key_info(struct iwl_priv *priv, | 461 | static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, |
460 | struct ieee80211_key_conf *keyconf, | 462 | struct ieee80211_key_conf *keyconf, |
461 | u8 sta_id) | 463 | u8 sta_id) |
462 | { | 464 | { |
463 | unsigned long flags; | 465 | unsigned long flags; |
464 | __le16 key_flags = 0; | 466 | __le16 key_flags = 0; |
467 | int ret; | ||
468 | |||
469 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); | ||
470 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
471 | |||
472 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
473 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
474 | |||
475 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
476 | keyconf->hw_key_idx = keyconf->keyidx; | ||
477 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
465 | 478 | ||
466 | switch (keyconf->alg) { | ||
467 | case ALG_CCMP: | ||
468 | key_flags |= STA_KEY_FLG_CCMP; | ||
469 | key_flags |= cpu_to_le16( | ||
470 | keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
471 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
472 | break; | ||
473 | case ALG_TKIP: | ||
474 | case ALG_WEP: | ||
475 | default: | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | spin_lock_irqsave(&priv->sta_lock, flags); | 479 | spin_lock_irqsave(&priv->sta_lock, flags); |
479 | priv->stations_39[sta_id].keyinfo.alg = keyconf->alg; | 480 | priv->stations_39[sta_id].keyinfo.alg = keyconf->alg; |
480 | priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen; | 481 | priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen; |
@@ -483,16 +484,43 @@ static int iwl3945_update_sta_key_info(struct iwl_priv *priv, | |||
483 | 484 | ||
484 | memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key, | 485 | memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key, |
485 | keyconf->keylen); | 486 | keyconf->keylen); |
487 | |||
488 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) | ||
489 | == STA_KEY_FLG_NO_ENC) | ||
490 | priv->stations[sta_id].sta.key.key_offset = | ||
491 | iwl_get_free_ucode_key_index(priv); | ||
492 | /* else, we are overriding an existing key => no need to allocated room | ||
493 | * in uCode. */ | ||
494 | |||
495 | WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, | ||
496 | "no space for a new key"); | ||
497 | |||
486 | priv->stations_39[sta_id].sta.key.key_flags = key_flags; | 498 | priv->stations_39[sta_id].sta.key.key_flags = key_flags; |
487 | priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 499 | priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
488 | priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 500 | priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
489 | 501 | ||
502 | IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n"); | ||
503 | |||
504 | ret = iwl_send_add_sta(priv, | ||
505 | (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, CMD_ASYNC); | ||
506 | |||
490 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 507 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
491 | 508 | ||
492 | IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n"); | 509 | return ret; |
493 | iwl_send_add_sta(priv, | 510 | } |
494 | (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0); | 511 | |
495 | return 0; | 512 | static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv, |
513 | struct ieee80211_key_conf *keyconf, | ||
514 | u8 sta_id) | ||
515 | { | ||
516 | return -EOPNOTSUPP; | ||
517 | } | ||
518 | |||
519 | static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv, | ||
520 | struct ieee80211_key_conf *keyconf, | ||
521 | u8 sta_id) | ||
522 | { | ||
523 | return -EOPNOTSUPP; | ||
496 | } | 524 | } |
497 | 525 | ||
498 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | 526 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) |
@@ -514,6 +542,52 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | |||
514 | return 0; | 542 | return 0; |
515 | } | 543 | } |
516 | 544 | ||
545 | int iwl3945_set_dynamic_key(struct iwl_priv *priv, | ||
546 | struct ieee80211_key_conf *keyconf, u8 sta_id) | ||
547 | { | ||
548 | int ret = 0; | ||
549 | |||
550 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | ||
551 | |||
552 | switch (keyconf->alg) { | ||
553 | case ALG_CCMP: | ||
554 | ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | ||
555 | break; | ||
556 | case ALG_TKIP: | ||
557 | ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | ||
558 | break; | ||
559 | case ALG_WEP: | ||
560 | ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); | ||
561 | break; | ||
562 | default: | ||
563 | IWL_ERR(priv,"Unknown alg: %s alg = %d\n", __func__, keyconf->alg); | ||
564 | ret = -EINVAL; | ||
565 | } | ||
566 | |||
567 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", | ||
568 | keyconf->alg, keyconf->keylen, keyconf->keyidx, | ||
569 | sta_id, ret); | ||
570 | |||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | static int iwl3945_remove_static_key(struct iwl_priv *priv) | ||
575 | { | ||
576 | int ret = -EOPNOTSUPP; | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | static int iwl3945_set_static_key(struct iwl_priv *priv, | ||
582 | struct ieee80211_key_conf *key) | ||
583 | { | ||
584 | if (key->alg == ALG_WEP) | ||
585 | return -EOPNOTSUPP; | ||
586 | |||
587 | IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg); | ||
588 | return -EINVAL; | ||
589 | } | ||
590 | |||
517 | static void iwl3945_clear_free_frames(struct iwl_priv *priv) | 591 | static void iwl3945_clear_free_frames(struct iwl_priv *priv) |
518 | { | 592 | { |
519 | struct list_head *element; | 593 | struct list_head *element; |
@@ -766,11 +840,11 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
766 | struct ieee80211_tx_info *info, | 840 | struct ieee80211_tx_info *info, |
767 | struct iwl_cmd *cmd, | 841 | struct iwl_cmd *cmd, |
768 | struct sk_buff *skb_frag, | 842 | struct sk_buff *skb_frag, |
769 | int last_frag) | 843 | int sta_id) |
770 | { | 844 | { |
771 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 845 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
772 | struct iwl3945_hw_key *keyinfo = | 846 | struct iwl3945_hw_key *keyinfo = |
773 | &priv->stations_39[info->control.hw_key->hw_key_idx].keyinfo; | 847 | &priv->stations_39[sta_id].keyinfo; |
774 | 848 | ||
775 | switch (keyinfo->alg) { | 849 | switch (keyinfo->alg) { |
776 | case ALG_CCMP: | 850 | case ALG_CCMP: |
@@ -780,15 +854,6 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
780 | break; | 854 | break; |
781 | 855 | ||
782 | case ALG_TKIP: | 856 | case ALG_TKIP: |
783 | #if 0 | ||
784 | tx->sec_ctl = TX_CMD_SEC_TKIP; | ||
785 | |||
786 | if (last_frag) | ||
787 | memcpy(tx->tkip_mic.byte, skb_frag->tail - 8, | ||
788 | 8); | ||
789 | else | ||
790 | memset(tx->tkip_mic.byte, 0, 8); | ||
791 | #endif | ||
792 | break; | 857 | break; |
793 | 858 | ||
794 | case ALG_WEP: | 859 | case ALG_WEP: |
@@ -1088,7 +1153,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
1088 | txcmd_phys, len, 1, 0); | 1153 | txcmd_phys, len, 1, 0); |
1089 | 1154 | ||
1090 | if (info->control.hw_key) | 1155 | if (info->control.hw_key) |
1091 | iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0); | 1156 | iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id); |
1092 | 1157 | ||
1093 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 1158 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
1094 | * if any (802.11 null frames have no payload). */ | 1159 | * if any (802.11 null frames have no payload). */ |
@@ -4110,8 +4175,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
4110 | { | 4175 | { |
4111 | struct iwl_priv *priv = hw->priv; | 4176 | struct iwl_priv *priv = hw->priv; |
4112 | const u8 *addr; | 4177 | const u8 *addr; |
4113 | int ret; | 4178 | int ret = 0; |
4114 | u8 sta_id; | 4179 | u8 sta_id = IWL_INVALID_STATION; |
4180 | u8 static_key; | ||
4115 | 4181 | ||
4116 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 4182 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
4117 | 4183 | ||
@@ -4121,43 +4187,41 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
4121 | } | 4187 | } |
4122 | 4188 | ||
4123 | addr = sta ? sta->addr : iwl_bcast_addr; | 4189 | addr = sta ? sta->addr : iwl_bcast_addr; |
4124 | sta_id = iwl3945_hw_find_station(priv, addr); | 4190 | static_key = !iwl_is_associated(priv); |
4125 | if (sta_id == IWL_INVALID_STATION) { | 4191 | |
4126 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | 4192 | if (!static_key) { |
4127 | addr); | 4193 | sta_id = iwl3945_hw_find_station(priv, addr); |
4128 | return -EINVAL; | 4194 | if (sta_id == IWL_INVALID_STATION) { |
4195 | IWL_DEBUG_MAC80211(priv, "leave - %pMnot in station map.\n", | ||
4196 | addr); | ||
4197 | return -EINVAL; | ||
4198 | } | ||
4129 | } | 4199 | } |
4130 | 4200 | ||
4131 | mutex_lock(&priv->mutex); | 4201 | mutex_lock(&priv->mutex); |
4132 | |||
4133 | iwl_scan_cancel_timeout(priv, 100); | 4202 | iwl_scan_cancel_timeout(priv, 100); |
4203 | mutex_unlock(&priv->mutex); | ||
4134 | 4204 | ||
4135 | switch (cmd) { | 4205 | switch (cmd) { |
4136 | case SET_KEY: | 4206 | case SET_KEY: |
4137 | ret = iwl3945_update_sta_key_info(priv, key, sta_id); | 4207 | if (static_key) |
4138 | if (!ret) { | 4208 | ret = iwl3945_set_static_key(priv, key); |
4139 | iwl_set_rxon_hwcrypto(priv, 1); | 4209 | else |
4140 | iwl3945_commit_rxon(priv); | 4210 | ret = iwl3945_set_dynamic_key(priv, key, sta_id); |
4141 | key->hw_key_idx = sta_id; | 4211 | IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); |
4142 | IWL_DEBUG_MAC80211(priv, | ||
4143 | "set_key success, using hwcrypto\n"); | ||
4144 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
4145 | } | ||
4146 | break; | 4212 | break; |
4147 | case DISABLE_KEY: | 4213 | case DISABLE_KEY: |
4148 | ret = iwl3945_clear_sta_key_info(priv, sta_id); | 4214 | if (static_key) |
4149 | if (!ret) { | 4215 | ret = iwl3945_remove_static_key(priv); |
4150 | iwl_set_rxon_hwcrypto(priv, 0); | 4216 | else |
4151 | iwl3945_commit_rxon(priv); | 4217 | ret = iwl3945_clear_sta_key_info(priv, sta_id); |
4152 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); | 4218 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); |
4153 | } | ||
4154 | break; | 4219 | break; |
4155 | default: | 4220 | default: |
4156 | ret = -EINVAL; | 4221 | ret = -EINVAL; |
4157 | } | 4222 | } |
4158 | 4223 | ||
4159 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 4224 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
4160 | mutex_unlock(&priv->mutex); | ||
4161 | 4225 | ||
4162 | return ret; | 4226 | return ret; |
4163 | } | 4227 | } |