diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/iwmc3200wifi/commands.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/commands.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/commands.c | 113 |
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 | ||
103 | static int modparam_wiwi = COEX_MODE_CM; | ||
104 | module_param_named(wiwi, modparam_wiwi, int, 0644); | ||
105 | MODULE_PARM_DESC(wiwi, "Wifi-WiMAX coexistence: 1=SA, 2=XOR, 3=CM (default)"); | ||
106 | |||
97 | static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = | 107 | static 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] = | |||
117 | static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = | 127 | static 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 | ||
193 | int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) | 203 | int 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 | ||
288 | int 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 | |||
278 | int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) | 299 | int 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 | ||
807 | int 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 | |||
786 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) | 820 | int 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 | |||
938 | int 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 | |||
969 | int 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 | } | ||