aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/commands.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c113
1 files changed, 103 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
index 84158b6d35d8..42df7262f9f7 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ b/drivers/net/wireless/iwmc3200wifi/commands.c
@@ -41,6 +41,7 @@
41#include <linux/etherdevice.h> 41#include <linux/etherdevice.h>
42#include <linux/ieee80211.h> 42#include <linux/ieee80211.h>
43#include <linux/sched.h> 43#include <linux/sched.h>
44#include <linux/slab.h>
44 45
45#include "iwm.h" 46#include "iwm.h"
46#include "bus.h" 47#include "bus.h"
@@ -77,6 +78,11 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
77 int ret; 78 int ret;
78 u8 oid = hdr->oid; 79 u8 oid = hdr->oid;
79 80
81 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
82 IWM_ERR(iwm, "Interface is not ready yet");
83 return -EAGAIN;
84 }
85
80 umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; 86 umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
81 umac_cmd.resp = resp; 87 umac_cmd.resp = resp;
82 88
@@ -94,6 +100,10 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
94 return ret; 100 return ret;
95} 101}
96 102
103static int modparam_wiwi = COEX_MODE_CM;
104module_param_named(wiwi, modparam_wiwi, int, 0644);
105MODULE_PARM_DESC(wiwi, "Wifi-WiMAX coexistence: 1=SA, 2=XOR, 3=CM (default)");
106
97static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = 107static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
98{ 108{
99 {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS}, 109 {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS},
@@ -117,18 +127,18 @@ static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
117static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = 127static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
118{ 128{
119 {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS}, 129 {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS},
120 {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, 130 {4, 4, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
121 {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, 131 {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
122 {5, 5, 0, COEX_CALIBRATION_FLAGS}, 132 {6, 6, 0, COEX_CALIBRATION_FLAGS},
123 {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, 133 {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
124 {5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS}, 134 {6, 5, 0, COEX_CONNECTION_ESTAB_FLAGS},
125 {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS}, 135 {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
126 {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, 136 {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
127 {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, 137 {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
128 {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, 138 {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
129 {1, 1, 0, COEX_RF_ON_FLAGS}, 139 {1, 1, 0, COEX_RF_ON_FLAGS},
130 {1, 1, 0, COEX_RF_OFF_FLAGS}, 140 {1, 1, 0, COEX_RF_OFF_FLAGS},
131 {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, 141 {7, 7, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
132 {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, 142 {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
133 {1, 1, 0, COEX_RSRVD1_FLAGS}, 143 {1, 1, 0, COEX_RSRVD1_FLAGS},
134 {1, 1, 0, COEX_RSRVD2_FLAGS} 144 {1, 1, 0, COEX_RSRVD2_FLAGS}
@@ -143,7 +153,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
143 153
144 coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK; 154 coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK;
145 155
146 switch (iwm->conf.coexist_mode) { 156 switch (modparam_wiwi) {
147 case COEX_MODE_XOR: 157 case COEX_MODE_XOR:
148 case COEX_MODE_CM: 158 case COEX_MODE_CM:
149 coex_enabled = 1; 159 coex_enabled = 1;
@@ -168,7 +178,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
168 COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK | 178 COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK |
169 COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK; 179 COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK;
170 180
171 switch (iwm->conf.coexist_mode) { 181 switch (modparam_wiwi) {
172 case COEX_MODE_XOR: 182 case COEX_MODE_XOR:
173 memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl, 183 memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl,
174 sizeof(iwm_sta_xor_prio_tbl)); 184 sizeof(iwm_sta_xor_prio_tbl));
@@ -179,7 +189,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
179 break; 189 break;
180 default: 190 default:
181 IWM_ERR(iwm, "Invalid coex_mode 0x%x\n", 191 IWM_ERR(iwm, "Invalid coex_mode 0x%x\n",
182 iwm->conf.coexist_mode); 192 modparam_wiwi);
183 break; 193 break;
184 } 194 }
185 } else 195 } else
@@ -187,7 +197,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
187 197
188 return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD, 198 return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD,
189 &coex_table_cmd, 199 &coex_table_cmd,
190 sizeof(struct iwm_coex_prio_table_cmd), 1); 200 sizeof(struct iwm_coex_prio_table_cmd), 0);
191} 201}
192 202
193int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) 203int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
@@ -275,6 +285,17 @@ int iwm_send_calib_results(struct iwm_priv *iwm)
275 return ret; 285 return ret;
276} 286}
277 287
288int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit)
289{
290 struct iwm_ct_kill_cfg_cmd cmd;
291
292 cmd.entry_threshold = entry;
293 cmd.exit_threshold = exit;
294
295 return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd,
296 sizeof(struct iwm_ct_kill_cfg_cmd), 0);
297}
298
278int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) 299int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
279{ 300{
280 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; 301 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
@@ -380,7 +401,7 @@ int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags)
380 return ret; 401 return ret;
381 402
382 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 403 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
383 CFG_COEX_MODE, iwm->conf.coexist_mode); 404 CFG_COEX_MODE, modparam_wiwi);
384 if (ret < 0) 405 if (ret < 0)
385 return ret; 406 return ret;
386 407
@@ -778,11 +799,24 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
778 return ret; 799 return ret;
779 800
780 ret = wait_event_interruptible_timeout(iwm->mlme_queue, 801 ret = wait_event_interruptible_timeout(iwm->mlme_queue,
781 (iwm->umac_profile_active == 0), 2 * HZ); 802 (iwm->umac_profile_active == 0), 5 * HZ);
782 803
783 return ret ? 0 : -EBUSY; 804 return ret ? 0 : -EBUSY;
784} 805}
785 806
807int iwm_tx_power_trigger(struct iwm_priv *iwm)
808{
809 struct iwm_umac_pwr_trigger pwr_trigger;
810
811 pwr_trigger.hdr.oid = UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER;
812 pwr_trigger.hdr.buf_size =
813 cpu_to_le16(sizeof(struct iwm_umac_pwr_trigger) -
814 sizeof(struct iwm_umac_wifi_if));
815
816
817 return iwm_send_wifi_if_cmd(iwm, &pwr_trigger, sizeof(pwr_trigger), 1);
818}
819
786int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) 820int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
787{ 821{
788 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; 822 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
@@ -900,3 +934,62 @@ int iwm_target_reset(struct iwm_priv *iwm)
900 934
901 return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); 935 return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
902} 936}
937
938int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
939 struct iwm_umac_notif_stop_resume_tx *ntf)
940{
941 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
942 struct iwm_umac_cmd umac_cmd;
943 struct iwm_umac_cmd_stop_resume_tx stp_res_cmd;
944 struct iwm_sta_info *sta_info;
945 u8 sta_id = STA_ID_N_COLOR_ID(ntf->sta_id);
946 int i;
947
948 sta_info = &iwm->sta_table[sta_id];
949 if (!sta_info->valid) {
950 IWM_ERR(iwm, "Invalid STA: %d\n", sta_id);
951 return -EINVAL;
952 }
953
954 umac_cmd.id = UMAC_CMD_OPCODE_STOP_RESUME_STA_TX;
955 umac_cmd.resp = 0;
956
957 stp_res_cmd.flags = ntf->flags;
958 stp_res_cmd.sta_id = ntf->sta_id;
959 stp_res_cmd.stop_resume_tid_msk = ntf->stop_resume_tid_msk;
960 for (i = 0; i < IWM_UMAC_TID_NR; i++)
961 stp_res_cmd.last_seq_num[i] =
962 sta_info->tid_info[i].last_seq_num;
963
964 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stp_res_cmd,
965 sizeof(struct iwm_umac_cmd_stop_resume_tx));
966
967}
968
969int iwm_send_pmkid_update(struct iwm_priv *iwm,
970 struct cfg80211_pmksa *pmksa, u32 command)
971{
972 struct iwm_umac_pmkid_update update;
973 int ret;
974
975 memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
976
977 update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE;
978 update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) -
979 sizeof(struct iwm_umac_wifi_if));
980
981 update.command = cpu_to_le32(command);
982 if (pmksa->bssid)
983 memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
984 if (pmksa->pmkid)
985 memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
986
987 ret = iwm_send_wifi_if_cmd(iwm, &update,
988 sizeof(struct iwm_umac_pmkid_update), 0);
989 if (ret) {
990 IWM_ERR(iwm, "PMKID update command failed\n");
991 return ret;
992 }
993
994 return 0;
995}