aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorAbhijeet Kolekar <abhijeet.kolekar@intel.com>2009-02-27 19:21:21 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-03-05 14:39:36 -0500
commit6e21f15cac2c6c25b6a5874a98420e1b9064f0c1 (patch)
tree9d580956e43f024055d0093df1c2e3ce905f3024 /drivers/net/wireless/iwlwifi/iwl3945-base.c
parent7c4cbb6ee0a55885d697a5b07b6c4c8fd10d573a (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.c172
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
459static int iwl3945_update_sta_key_info(struct iwl_priv *priv, 461static 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; 512static 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
519static 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
498static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) 526static 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
545int 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
574static int iwl3945_remove_static_key(struct iwl_priv *priv)
575{
576 int ret = -EOPNOTSUPP;
577
578 return ret;
579}
580
581static 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
517static void iwl3945_clear_free_frames(struct iwl_priv *priv) 591static 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}