blob: 91136697f697deed0fee1bde1a97454c591487a1 [file] [log] [blame]
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001/**
2 * This file contains the handling of command
3 * responses as well as events generated by firmware.
4 */
5#include <linux/delay.h>
6#include <linux/if_arp.h>
7#include <linux/netdevice.h>
8
9#include <net/iw_handler.h>
10
11#include "host.h"
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020012#include "decl.h"
13#include "defs.h"
14#include "dev.h"
15#include "join.h"
16#include "wext.h"
17
18/**
19 * @brief This function handles disconnect event. it
20 * reports disconnect to upper layer, clean tx/rx packets,
21 * reset link state etc.
22 *
Holger Schurig69f90322007-11-23 15:43:44 +010023 * @param priv A pointer to struct lbs_private structure
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020024 * @return n/a
25 */
Holger Schurig69f90322007-11-23 15:43:44 +010026void lbs_mac_event_disconnected(struct lbs_private *priv)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020027{
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020028 union iwreq_data wrqu;
29
David Woodhouseaa21c002007-12-08 20:04:36 +000030 if (priv->connect_status != LBS_CONNECTED)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020031 return;
32
Holger Schurig91843462007-11-28 14:05:02 +010033 lbs_deb_enter(LBS_DEB_ASSOC);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020034
35 memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
36 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
37
38 /*
39 * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
40 * It causes problem in the Supplicant
41 */
42
43 msleep_interruptible(1000);
Holger Schurig634b8f42007-05-25 13:05:16 -040044 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020045
46 /* Free Tx and Rx packets */
David Woodhouseaa21c002007-12-08 20:04:36 +000047 kfree_skb(priv->currenttxskb);
48 priv->currenttxskb = NULL;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020049
50 /* report disconnect to upper layer */
Holger Schurig634b8f42007-05-25 13:05:16 -040051 netif_stop_queue(priv->dev);
52 netif_carrier_off(priv->dev);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020053
54 /* reset SNR/NF/RSSI values */
David Woodhouseaa21c002007-12-08 20:04:36 +000055 memset(priv->SNR, 0x00, sizeof(priv->SNR));
56 memset(priv->NF, 0x00, sizeof(priv->NF));
57 memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
58 memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
59 memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
60 priv->nextSNRNF = 0;
61 priv->numSNRNF = 0;
62 priv->connect_status = LBS_DISCONNECTED;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020063
Dan Williamse76850d2007-05-25 17:09:41 -040064 /* Clear out associated SSID and BSSID since connection is
65 * no longer valid.
66 */
David Woodhouseaa21c002007-12-08 20:04:36 +000067 memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
68 memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
69 priv->curbssparams.ssid_len = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020070
David Woodhouseaa21c002007-12-08 20:04:36 +000071 if (priv->psstate != PS_STATE_FULL_POWER) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020072 /* make firmware to exit PS mode */
Holger Schuriga6c87002007-08-02 11:54:10 -040073 lbs_deb_cmd("disconnected, so exit PS mode\n");
Holger Schurig10078322007-11-15 18:05:47 -050074 lbs_ps_wakeup(priv, 0);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020075 }
Holger Schuriga6c87002007-08-02 11:54:10 -040076 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020077}
78
79/**
80 * @brief This function handles MIC failure event.
81 *
Holger Schurig69f90322007-11-23 15:43:44 +010082 * @param priv A pointer to struct lbs_private structure
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020083 * @para event the event id
84 * @return n/a
85 */
Holger Schurig69f90322007-11-23 15:43:44 +010086static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020087{
88 char buf[50];
89
Holger Schuriga6c87002007-08-02 11:54:10 -040090 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020091 memset(buf, 0, sizeof(buf));
92
93 sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
94
95 if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
96 strcat(buf, "unicast ");
97 } else {
98 strcat(buf, "multicast ");
99 }
100
Holger Schurig10078322007-11-15 18:05:47 -0500101 lbs_send_iwevcustom_event(priv, buf);
Holger Schuriga6c87002007-08-02 11:54:10 -0400102 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200103}
104
Holger Schurig69f90322007-11-23 15:43:44 +0100105static int lbs_ret_reg_access(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200106 u16 type, struct cmd_ds_command *resp)
107{
Holger Schurig9012b282007-05-25 11:27:16 -0400108 int ret = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200109
Holger Schurig9012b282007-05-25 11:27:16 -0400110 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200111
112 switch (type) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400113 case CMD_RET(CMD_MAC_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200114 {
David Woodhouse981f1872007-05-25 23:36:54 -0400115 struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200116
David Woodhouseaa21c002007-12-08 20:04:36 +0000117 priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
118 priv->offsetvalue.value = le32_to_cpu(reg->value);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200119 break;
120 }
121
Holger Schurig6b63cd02007-08-02 11:53:36 -0400122 case CMD_RET(CMD_BBP_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200123 {
David Woodhouse981f1872007-05-25 23:36:54 -0400124 struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200125
David Woodhouseaa21c002007-12-08 20:04:36 +0000126 priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
127 priv->offsetvalue.value = reg->value;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200128 break;
129 }
130
Holger Schurig6b63cd02007-08-02 11:53:36 -0400131 case CMD_RET(CMD_RF_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200132 {
David Woodhouse981f1872007-05-25 23:36:54 -0400133 struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200134
David Woodhouseaa21c002007-12-08 20:04:36 +0000135 priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
136 priv->offsetvalue.value = reg->value;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200137 break;
138 }
139
140 default:
Holger Schurig9012b282007-05-25 11:27:16 -0400141 ret = -1;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200142 }
143
Holger Schurig8b17d722007-10-08 11:09:30 +0200144 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Holger Schurig9012b282007-05-25 11:27:16 -0400145 return ret;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200146}
147
Holger Schurig69f90322007-11-23 15:43:44 +0100148static int lbs_ret_get_hw_spec(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200149 struct cmd_ds_command *resp)
150{
151 u32 i;
152 struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200153 int ret = 0;
Joe Perches0795af52007-10-03 17:59:30 -0700154 DECLARE_MAC_BUF(mac);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200155
Holger Schurig9012b282007-05-25 11:27:16 -0400156 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200157
David Woodhouseaa21c002007-12-08 20:04:36 +0000158 priv->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200159
David Woodhouseaa21c002007-12-08 20:04:36 +0000160 memcpy(priv->fwreleasenumber, hwspec->fwreleasenumber, 4);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200161
Holger Schuriga6c87002007-08-02 11:54:10 -0400162 lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
David Woodhouseaa21c002007-12-08 20:04:36 +0000163 priv->fwreleasenumber[2], priv->fwreleasenumber[1],
164 priv->fwreleasenumber[0], priv->fwreleasenumber[3]);
Joe Perches0795af52007-10-03 17:59:30 -0700165 lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n",
166 print_mac(mac, hwspec->permanentaddr));
Holger Schuriga6c87002007-08-02 11:54:10 -0400167 lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200168 hwspec->hwifversion, hwspec->version);
169
Marek Vašut70500f52007-08-20 12:55:41 -0400170 /* Clamp region code to 8-bit since FW spec indicates that it should
171 * only ever be 8-bit, even though the field size is 16-bit. Some firmware
172 * returns non-zero high 8 bits here.
173 */
David Woodhouseaa21c002007-12-08 20:04:36 +0000174 priv->regioncode = le16_to_cpu(hwspec->regioncode) & 0xFF;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200175
176 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
177 /* use the region code to search for the index */
David Woodhouseaa21c002007-12-08 20:04:36 +0000178 if (priv->regioncode == lbs_region_code_to_index[i]) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200179 break;
180 }
181 }
182
183 /* if it's unidentified region code, use the default (USA) */
184 if (i >= MRVDRV_MAX_REGION_CODE) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000185 priv->regioncode = 0x10;
David Woodhouse981f1872007-05-25 23:36:54 -0400186 lbs_pr_info("unidentified region code; using the default (USA)\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200187 }
188
David Woodhouseaa21c002007-12-08 20:04:36 +0000189 if (priv->current_addr[0] == 0xff)
190 memmove(priv->current_addr, hwspec->permanentaddr, ETH_ALEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200191
David Woodhouseaa21c002007-12-08 20:04:36 +0000192 memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
Holger Schurig78523da2007-05-25 11:49:19 -0400193 if (priv->mesh_dev)
David Woodhouseaa21c002007-12-08 20:04:36 +0000194 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200195
David Woodhouseaa21c002007-12-08 20:04:36 +0000196 if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200197 ret = -1;
198 goto done;
199 }
200
Holger Schurig10078322007-11-15 18:05:47 -0500201 if (lbs_set_universaltable(priv, 0)) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200202 ret = -1;
203 goto done;
204 }
205
Holger Schurig9012b282007-05-25 11:27:16 -0400206done:
207 lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200208 return ret;
209}
210
Holger Schurig69f90322007-11-23 15:43:44 +0100211static int lbs_ret_802_11_sleep_params(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200212 struct cmd_ds_command *resp)
213{
214 struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200215
Holger Schurig9012b282007-05-25 11:27:16 -0400216 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200217
Holger Schuriga6c87002007-08-02 11:54:10 -0400218 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
219 "extsleepclk 0x%x\n", le16_to_cpu(sp->error),
David Woodhouse981f1872007-05-25 23:36:54 -0400220 le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
221 sp->calcontrol, sp->externalsleepclk);
222
David Woodhouseaa21c002007-12-08 20:04:36 +0000223 priv->sp.sp_error = le16_to_cpu(sp->error);
224 priv->sp.sp_offset = le16_to_cpu(sp->offset);
225 priv->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
226 priv->sp.sp_calcontrol = sp->calcontrol;
227 priv->sp.sp_extsleepclk = sp->externalsleepclk;
228 priv->sp.sp_reserved = le16_to_cpu(sp->reserved);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200229
Holger Schurig9012b282007-05-25 11:27:16 -0400230 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200231 return 0;
232}
233
Holger Schurig69f90322007-11-23 15:43:44 +0100234static int lbs_ret_802_11_stat(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200235 struct cmd_ds_command *resp)
236{
Holger Schuriga6c87002007-08-02 11:54:10 -0400237 lbs_deb_enter(LBS_DEB_CMD);
David Woodhouseaa21c002007-12-08 20:04:36 +0000238/* currently priv->wlan802_11Stat is unused
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200239
240 struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200241
242 // TODO Convert it to Big endian befor copy
David Woodhouseaa21c002007-12-08 20:04:36 +0000243 memcpy(&priv->wlan802_11Stat,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200244 p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
245*/
Holger Schuriga6c87002007-08-02 11:54:10 -0400246 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200247 return 0;
248}
249
Holger Schurig69f90322007-11-23 15:43:44 +0100250static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200251 struct cmd_ds_command *resp)
252{
253 struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
254 u16 oid = le16_to_cpu(smib->oid);
255 u16 querytype = le16_to_cpu(smib->querytype);
256
Holger Schurig9012b282007-05-25 11:27:16 -0400257 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200258
Holger Schuriga6c87002007-08-02 11:54:10 -0400259 lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200260 querytype);
Holger Schuriga6c87002007-08-02 11:54:10 -0400261 lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200262
Dan Williams0aef64d2007-08-02 11:31:18 -0400263 if (querytype == CMD_ACT_GET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200264 switch (oid) {
Dan Williams0aef64d2007-08-02 11:31:18 -0400265 case FRAGTHRESH_I:
David Woodhouseaa21c002007-12-08 20:04:36 +0000266 priv->fragthsd =
David Woodhouse981f1872007-05-25 23:36:54 -0400267 le16_to_cpu(*((__le16 *)(smib->value)));
Holger Schuriga6c87002007-08-02 11:54:10 -0400268 lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
David Woodhouseaa21c002007-12-08 20:04:36 +0000269 priv->fragthsd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200270 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400271 case RTSTHRESH_I:
David Woodhouseaa21c002007-12-08 20:04:36 +0000272 priv->rtsthsd =
David Woodhouse981f1872007-05-25 23:36:54 -0400273 le16_to_cpu(*((__le16 *)(smib->value)));
Holger Schuriga6c87002007-08-02 11:54:10 -0400274 lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
David Woodhouseaa21c002007-12-08 20:04:36 +0000275 priv->rtsthsd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200276 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400277 case SHORT_RETRYLIM_I:
David Woodhouseaa21c002007-12-08 20:04:36 +0000278 priv->txretrycount =
David Woodhouse981f1872007-05-25 23:36:54 -0400279 le16_to_cpu(*((__le16 *)(smib->value)));
Holger Schuriga6c87002007-08-02 11:54:10 -0400280 lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
David Woodhouseaa21c002007-12-08 20:04:36 +0000281 priv->rtsthsd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200282 break;
283 default:
284 break;
285 }
286 }
287
Holger Schurig9012b282007-05-25 11:27:16 -0400288 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200289 return 0;
290}
291
Holger Schurig69f90322007-11-23 15:43:44 +0100292static int lbs_ret_802_11_key_material(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200293 struct cmd_ds_command *resp)
294{
295 struct cmd_ds_802_11_key_material *pkeymaterial =
296 &resp->params.keymaterial;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200297 u16 action = le16_to_cpu(pkeymaterial->action);
298
Holger Schurig9012b282007-05-25 11:27:16 -0400299 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200300
301 /* Copy the returned key to driver private data */
Dan Williams0aef64d2007-08-02 11:31:18 -0400302 if (action == CMD_ACT_GET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200303 u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
304 u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
305
306 while (buf_ptr < resp_end) {
307 struct MrvlIEtype_keyParamSet * pkeyparamset =
308 (struct MrvlIEtype_keyParamSet *) buf_ptr;
Dan Williams1443b652007-08-02 10:45:55 -0400309 struct enc_key * pkey;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200310 u16 param_set_len = le16_to_cpu(pkeyparamset->length);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200311 u16 key_len = le16_to_cpu(pkeyparamset->keylen);
Dan Williams1443b652007-08-02 10:45:55 -0400312 u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
313 u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
314 u8 * end;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200315
316 end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
317 + sizeof (pkeyparamset->length)
318 + param_set_len;
319 /* Make sure we don't access past the end of the IEs */
320 if (end > resp_end)
321 break;
322
Dan Williams1443b652007-08-02 10:45:55 -0400323 if (key_flags & KEY_INFO_WPA_UNICAST)
David Woodhouseaa21c002007-12-08 20:04:36 +0000324 pkey = &priv->wpa_unicast_key;
Dan Williams1443b652007-08-02 10:45:55 -0400325 else if (key_flags & KEY_INFO_WPA_MCAST)
David Woodhouseaa21c002007-12-08 20:04:36 +0000326 pkey = &priv->wpa_mcast_key;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200327 else
328 break;
329
330 /* Copy returned key into driver */
Dan Williams1443b652007-08-02 10:45:55 -0400331 memset(pkey, 0, sizeof(struct enc_key));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200332 if (key_len > sizeof(pkey->key))
333 break;
Dan Williams1443b652007-08-02 10:45:55 -0400334 pkey->type = key_type;
335 pkey->flags = key_flags;
336 pkey->len = key_len;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200337 memcpy(pkey->key, pkeyparamset->key, pkey->len);
338
339 buf_ptr = end + 1;
340 }
341 }
342
Holger Schurig9012b282007-05-25 11:27:16 -0400343 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200344 return 0;
345}
346
Holger Schurig69f90322007-11-23 15:43:44 +0100347static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200348 struct cmd_ds_command *resp)
349{
350 struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200351
Holger Schurig9012b282007-05-25 11:27:16 -0400352 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200353
David Woodhouseaa21c002007-12-08 20:04:36 +0000354 memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200355
Holger Schurig9012b282007-05-25 11:27:16 -0400356 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200357 return 0;
358}
359
Holger Schurig69f90322007-11-23 15:43:44 +0100360static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200361 struct cmd_ds_command *resp)
362{
363 struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200364
Holger Schurig9012b282007-05-25 11:27:16 -0400365 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200366
David Woodhouseaa21c002007-12-08 20:04:36 +0000367 priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200368
David Woodhouseaa21c002007-12-08 20:04:36 +0000369 lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200370
Holger Schuriga6c87002007-08-02 11:54:10 -0400371 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200372 return 0;
373}
374
Holger Schurig69f90322007-11-23 15:43:44 +0100375static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200376 struct cmd_ds_command *resp)
377{
David Woodhouse981f1872007-05-25 23:36:54 -0400378 struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200379
Holger Schurig9012b282007-05-25 11:27:16 -0400380 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200381
Dan Williams0aef64d2007-08-02 11:31:18 -0400382 if (rates->action == CMD_ACT_GET) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000383 priv->enablehwauto = le16_to_cpu(rates->enablehwauto);
384 priv->ratebitmap = le16_to_cpu(rates->bitmap);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200385 }
386
Holger Schuriga6c87002007-08-02 11:54:10 -0400387 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200388 return 0;
389}
390
Holger Schurig69f90322007-11-23 15:43:44 +0100391static int lbs_ret_802_11_data_rate(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200392 struct cmd_ds_command *resp)
393{
394 struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200395
Holger Schurig9012b282007-05-25 11:27:16 -0400396 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200397
Holger Schuriga6c87002007-08-02 11:54:10 -0400398 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) pdatarate,
Dan Williams8c512762007-08-02 11:40:45 -0400399 sizeof(struct cmd_ds_802_11_data_rate));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200400
Dan Williams8c512762007-08-02 11:40:45 -0400401 /* FIXME: get actual rates FW can do if this command actually returns
402 * all data rates supported.
403 */
David Woodhouseaa21c002007-12-08 20:04:36 +0000404 priv->cur_rate = lbs_fw_index_to_data_rate(pdatarate->rates[0]);
405 lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", priv->cur_rate);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200406
Dan Williams8c512762007-08-02 11:40:45 -0400407 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200408 return 0;
409}
410
Holger Schurig69f90322007-11-23 15:43:44 +0100411static int lbs_ret_802_11_rf_channel(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200412 struct cmd_ds_command *resp)
413{
David Woodhouse981f1872007-05-25 23:36:54 -0400414 struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200415 u16 action = le16_to_cpu(rfchannel->action);
416 u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
417
Holger Schurig9012b282007-05-25 11:27:16 -0400418 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200419
Dan Williams0aef64d2007-08-02 11:31:18 -0400420 if (action == CMD_OPT_802_11_RF_CHANNEL_GET
David Woodhouseaa21c002007-12-08 20:04:36 +0000421 && priv->curbssparams.channel != newchannel) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400422 lbs_deb_cmd("channel switch from %d to %d\n",
David Woodhouseaa21c002007-12-08 20:04:36 +0000423 priv->curbssparams.channel, newchannel);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200424
425 /* Update the channel again */
David Woodhouseaa21c002007-12-08 20:04:36 +0000426 priv->curbssparams.channel = newchannel;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200427 }
428
Holger Schurig9012b282007-05-25 11:27:16 -0400429 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200430 return 0;
431}
432
Holger Schurig69f90322007-11-23 15:43:44 +0100433static int lbs_ret_802_11_rssi(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200434 struct cmd_ds_command *resp)
435{
436 struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200437
Holger Schuriga6c87002007-08-02 11:54:10 -0400438 lbs_deb_enter(LBS_DEB_CMD);
439
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200440 /* store the non average value */
David Woodhouseaa21c002007-12-08 20:04:36 +0000441 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
442 priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200443
David Woodhouseaa21c002007-12-08 20:04:36 +0000444 priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
445 priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200446
David Woodhouseaa21c002007-12-08 20:04:36 +0000447 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
448 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
449 priv->NF[TYPE_BEACON][TYPE_NOAVG]);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200450
David Woodhouseaa21c002007-12-08 20:04:36 +0000451 priv->RSSI[TYPE_BEACON][TYPE_AVG] =
452 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
453 priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200454
Holger Schuriga6c87002007-08-02 11:54:10 -0400455 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
David Woodhouseaa21c002007-12-08 20:04:36 +0000456 priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
457 priv->RSSI[TYPE_BEACON][TYPE_AVG]);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200458
Holger Schuriga6c87002007-08-02 11:54:10 -0400459 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200460 return 0;
461}
462
Holger Schurig69f90322007-11-23 15:43:44 +0100463static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200464 struct cmd_ds_command *resp)
465{
Holger Schurig10078322007-11-15 18:05:47 -0500466 struct lbs_ioctl_regrdwr *pbuf;
David Woodhouseaa21c002007-12-08 20:04:36 +0000467 pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200468
Holger Schuriga6c87002007-08-02 11:54:10 -0400469 lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200470 le16_to_cpu(resp->params.rdeeprom.bytecount));
471 if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
472 pbuf->NOB = 0;
Holger Schuriga6c87002007-08-02 11:54:10 -0400473 lbs_deb_cmd("EEPROM read length too big\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200474 return -1;
475 }
476 pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
477 if (pbuf->NOB > 0) {
478
479 memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
480 le16_to_cpu(resp->params.rdeeprom.bytecount));
Holger Schuriga6c87002007-08-02 11:54:10 -0400481 lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200482 le16_to_cpu(resp->params.rdeeprom.bytecount));
483 }
Holger Schuriga6c87002007-08-02 11:54:10 -0400484 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200485 return 0;
486}
487
Holger Schurig69f90322007-11-23 15:43:44 +0100488static int lbs_ret_get_log(struct lbs_private *priv,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200489 struct cmd_ds_command *resp)
490{
David Woodhouse981f1872007-05-25 23:36:54 -0400491 struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200492
Holger Schurig9012b282007-05-25 11:27:16 -0400493 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200494
David Woodhouse981f1872007-05-25 23:36:54 -0400495 /* Stored little-endian */
David Woodhouseaa21c002007-12-08 20:04:36 +0000496 memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200497
Holger Schuriga6c87002007-08-02 11:54:10 -0400498 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200499 return 0;
500}
501
Holger Schurig69f90322007-11-23 15:43:44 +0100502static int lbs_ret_802_11_enable_rsn(struct lbs_private *priv,
Dan Williams18c96c342007-06-18 12:01:12 -0400503 struct cmd_ds_command *resp)
504{
505 struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
David Woodhouseaa21c002007-12-08 20:04:36 +0000506 u32 * pdata_buf = priv->cur_cmd->pdata_buf;
Dan Williams18c96c342007-06-18 12:01:12 -0400507
508 lbs_deb_enter(LBS_DEB_CMD);
509
Dan Williams0aef64d2007-08-02 11:31:18 -0400510 if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
Dan Williams18c96c342007-06-18 12:01:12 -0400511 if (pdata_buf)
512 *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
513 }
514
Holger Schuriga6c87002007-08-02 11:54:10 -0400515 lbs_deb_leave(LBS_DEB_CMD);
Dan Williams18c96c342007-06-18 12:01:12 -0400516 return 0;
517}
518
Brajesh Dave96287ac2007-11-20 17:44:28 -0500519static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
520 struct cmd_ds_command *resp)
521{
522 struct cmd_ds_802_11_beacon_control *bcn_ctrl =
523 &resp->params.bcn_ctrl;
Brajesh Dave96287ac2007-11-20 17:44:28 -0500524
525 lbs_deb_enter(LBS_DEB_CMD);
526
527 if (bcn_ctrl->action == CMD_ACT_GET) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000528 priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
529 priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
Brajesh Dave96287ac2007-11-20 17:44:28 -0500530 }
531
532 lbs_deb_enter(LBS_DEB_CMD);
533 return 0;
534}
535
Holger Schurig3a188642007-11-26 10:07:14 +0100536static int lbs_ret_802_11_subscribe_event(struct lbs_private *priv,
537 struct cmd_ds_command *resp)
538{
Holger Schurig3a188642007-11-26 10:07:14 +0100539 struct cmd_ds_802_11_subscribe_event *cmd_event =
540 &resp->params.subscribe_event;
541 struct cmd_ds_802_11_subscribe_event *dst_event =
David Woodhouseaa21c002007-12-08 20:04:36 +0000542 priv->cur_cmd->pdata_buf;
Holger Schurig3a188642007-11-26 10:07:14 +0100543
544 lbs_deb_enter(LBS_DEB_CMD);
545
546 if (dst_event->action == cpu_to_le16(CMD_ACT_GET)) {
Holger Schurigc2df2ef2007-12-07 15:30:44 +0000547 dst_event->events = cmd_event->events;
Holger Schurig3a188642007-11-26 10:07:14 +0100548 memcpy(dst_event->tlv, cmd_event->tlv, sizeof(dst_event->tlv));
549 }
550
551 lbs_deb_leave(LBS_DEB_CMD);
552 return 0;
553}
554
David Woodhouse1309b552007-12-10 13:36:10 -0500555static inline int handle_cmd_response(struct lbs_private *priv,
556 unsigned long dummy,
557 struct cmd_ds_command *resp)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200558{
559 int ret = 0;
560 unsigned long flags;
David Woodhouse1309b552007-12-10 13:36:10 -0500561 uint16_t respcmd = le16_to_cpu(resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200562
Holger Schuriga6c87002007-08-02 11:54:10 -0400563 lbs_deb_enter(LBS_DEB_HOST);
564
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200565 switch (respcmd) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400566 case CMD_RET(CMD_MAC_REG_ACCESS):
567 case CMD_RET(CMD_BBP_REG_ACCESS):
568 case CMD_RET(CMD_RF_REG_ACCESS):
Holger Schurig10078322007-11-15 18:05:47 -0500569 ret = lbs_ret_reg_access(priv, respcmd, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200570 break;
571
Holger Schurig6b63cd02007-08-02 11:53:36 -0400572 case CMD_RET(CMD_GET_HW_SPEC):
Holger Schurig10078322007-11-15 18:05:47 -0500573 ret = lbs_ret_get_hw_spec(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200574 break;
575
Holger Schurig6b63cd02007-08-02 11:53:36 -0400576 case CMD_RET(CMD_802_11_SCAN):
Holger Schurig10078322007-11-15 18:05:47 -0500577 ret = lbs_ret_80211_scan(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200578 break;
579
Holger Schurig6b63cd02007-08-02 11:53:36 -0400580 case CMD_RET(CMD_802_11_GET_LOG):
Holger Schurig10078322007-11-15 18:05:47 -0500581 ret = lbs_ret_get_log(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200582 break;
583
Dan Williams0aef64d2007-08-02 11:31:18 -0400584 case CMD_RET_802_11_ASSOCIATE:
Holger Schurig6b63cd02007-08-02 11:53:36 -0400585 case CMD_RET(CMD_802_11_ASSOCIATE):
586 case CMD_RET(CMD_802_11_REASSOCIATE):
Holger Schurig10078322007-11-15 18:05:47 -0500587 ret = lbs_ret_80211_associate(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200588 break;
589
Holger Schurig6b63cd02007-08-02 11:53:36 -0400590 case CMD_RET(CMD_802_11_DISASSOCIATE):
591 case CMD_RET(CMD_802_11_DEAUTHENTICATE):
Holger Schurig10078322007-11-15 18:05:47 -0500592 ret = lbs_ret_80211_disassociate(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200593 break;
594
Holger Schurig6b63cd02007-08-02 11:53:36 -0400595 case CMD_RET(CMD_802_11_AD_HOC_START):
596 case CMD_RET(CMD_802_11_AD_HOC_JOIN):
Holger Schurig10078322007-11-15 18:05:47 -0500597 ret = lbs_ret_80211_ad_hoc_start(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200598 break;
599
Holger Schurig6b63cd02007-08-02 11:53:36 -0400600 case CMD_RET(CMD_802_11_GET_STAT):
Holger Schurig10078322007-11-15 18:05:47 -0500601 ret = lbs_ret_802_11_stat(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200602 break;
603
Holger Schurig6b63cd02007-08-02 11:53:36 -0400604 case CMD_RET(CMD_802_11_SNMP_MIB):
Holger Schurig10078322007-11-15 18:05:47 -0500605 ret = lbs_ret_802_11_snmp_mib(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200606 break;
607
Holger Schurig6b63cd02007-08-02 11:53:36 -0400608 case CMD_RET(CMD_802_11_RF_TX_POWER):
Holger Schurig10078322007-11-15 18:05:47 -0500609 ret = lbs_ret_802_11_rf_tx_power(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200610 break;
611
Holger Schurig6b63cd02007-08-02 11:53:36 -0400612 case CMD_RET(CMD_802_11_SET_AFC):
613 case CMD_RET(CMD_802_11_GET_AFC):
David Woodhouseaa21c002007-12-08 20:04:36 +0000614 spin_lock_irqsave(&priv->driver_lock, flags);
615 memmove(priv->cur_cmd->pdata_buf, &resp->params.afc,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200616 sizeof(struct cmd_ds_802_11_afc));
David Woodhouseaa21c002007-12-08 20:04:36 +0000617 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200618
619 break;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200620
Holger Schurig6b63cd02007-08-02 11:53:36 -0400621 case CMD_RET(CMD_MAC_MULTICAST_ADR):
622 case CMD_RET(CMD_MAC_CONTROL):
623 case CMD_RET(CMD_802_11_SET_WEP):
624 case CMD_RET(CMD_802_11_RESET):
625 case CMD_RET(CMD_802_11_AUTHENTICATE):
626 case CMD_RET(CMD_802_11_RADIO_CONTROL):
627 case CMD_RET(CMD_802_11_BEACON_STOP):
Dan Williams18c96c342007-06-18 12:01:12 -0400628 break;
629
Holger Schurig6b63cd02007-08-02 11:53:36 -0400630 case CMD_RET(CMD_802_11_ENABLE_RSN):
Holger Schurig10078322007-11-15 18:05:47 -0500631 ret = lbs_ret_802_11_enable_rsn(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200632 break;
633
Holger Schurig6b63cd02007-08-02 11:53:36 -0400634 case CMD_RET(CMD_802_11_DATA_RATE):
Holger Schurig10078322007-11-15 18:05:47 -0500635 ret = lbs_ret_802_11_data_rate(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200636 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400637 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
Holger Schurig10078322007-11-15 18:05:47 -0500638 ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200639 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400640 case CMD_RET(CMD_802_11_RF_CHANNEL):
Holger Schurig10078322007-11-15 18:05:47 -0500641 ret = lbs_ret_802_11_rf_channel(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200642 break;
643
Holger Schurig6b63cd02007-08-02 11:53:36 -0400644 case CMD_RET(CMD_802_11_RSSI):
Holger Schurig10078322007-11-15 18:05:47 -0500645 ret = lbs_ret_802_11_rssi(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200646 break;
647
Holger Schurig6b63cd02007-08-02 11:53:36 -0400648 case CMD_RET(CMD_802_11_MAC_ADDRESS):
Holger Schurig10078322007-11-15 18:05:47 -0500649 ret = lbs_ret_802_11_mac_address(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200650 break;
651
Holger Schurig6b63cd02007-08-02 11:53:36 -0400652 case CMD_RET(CMD_802_11_AD_HOC_STOP):
Holger Schurig10078322007-11-15 18:05:47 -0500653 ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200654 break;
655
Holger Schurig6b63cd02007-08-02 11:53:36 -0400656 case CMD_RET(CMD_802_11_KEY_MATERIAL):
Holger Schurig10078322007-11-15 18:05:47 -0500657 ret = lbs_ret_802_11_key_material(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200658 break;
659
Holger Schurig6b63cd02007-08-02 11:53:36 -0400660 case CMD_RET(CMD_802_11_EEPROM_ACCESS):
Holger Schurig10078322007-11-15 18:05:47 -0500661 ret = lbs_ret_802_11_eeprom_access(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200662 break;
663
Holger Schurig6b63cd02007-08-02 11:53:36 -0400664 case CMD_RET(CMD_802_11D_DOMAIN_INFO):
Holger Schurig10078322007-11-15 18:05:47 -0500665 ret = lbs_ret_802_11d_domain_info(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200666 break;
667
Holger Schurig6b63cd02007-08-02 11:53:36 -0400668 case CMD_RET(CMD_802_11_SLEEP_PARAMS):
Holger Schurig10078322007-11-15 18:05:47 -0500669 ret = lbs_ret_802_11_sleep_params(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200670 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400671 case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
David Woodhouseaa21c002007-12-08 20:04:36 +0000672 spin_lock_irqsave(&priv->driver_lock, flags);
673 *((u16 *) priv->cur_cmd->pdata_buf) =
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200674 le16_to_cpu(resp->params.inactivity_timeout.timeout);
David Woodhouseaa21c002007-12-08 20:04:36 +0000675 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200676 break;
677
Holger Schurig6b63cd02007-08-02 11:53:36 -0400678 case CMD_RET(CMD_802_11_TPC_CFG):
David Woodhouseaa21c002007-12-08 20:04:36 +0000679 spin_lock_irqsave(&priv->driver_lock, flags);
680 memmove(priv->cur_cmd->pdata_buf, &resp->params.tpccfg,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200681 sizeof(struct cmd_ds_802_11_tpc_cfg));
David Woodhouseaa21c002007-12-08 20:04:36 +0000682 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200683 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400684 case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
David Woodhouseaa21c002007-12-08 20:04:36 +0000685 spin_lock_irqsave(&priv->driver_lock, flags);
686 memmove(priv->cur_cmd->pdata_buf, &resp->params.ledgpio,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200687 sizeof(struct cmd_ds_802_11_led_ctrl));
David Woodhouseaa21c002007-12-08 20:04:36 +0000688 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200689 break;
Holger Schurig3a188642007-11-26 10:07:14 +0100690 case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT):
691 ret = lbs_ret_802_11_subscribe_event(priv, resp);
692 break;
693
Holger Schurig6b63cd02007-08-02 11:53:36 -0400694 case CMD_RET(CMD_802_11_PWR_CFG):
David Woodhouseaa21c002007-12-08 20:04:36 +0000695 spin_lock_irqsave(&priv->driver_lock, flags);
696 memmove(priv->cur_cmd->pdata_buf, &resp->params.pwrcfg,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200697 sizeof(struct cmd_ds_802_11_pwr_cfg));
David Woodhouseaa21c002007-12-08 20:04:36 +0000698 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200699
700 break;
701
Holger Schurig6b63cd02007-08-02 11:53:36 -0400702 case CMD_RET(CMD_GET_TSF):
David Woodhouseaa21c002007-12-08 20:04:36 +0000703 spin_lock_irqsave(&priv->driver_lock, flags);
704 memcpy(priv->cur_cmd->pdata_buf,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200705 &resp->params.gettsf.tsfvalue, sizeof(u64));
David Woodhouseaa21c002007-12-08 20:04:36 +0000706 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200707 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400708 case CMD_RET(CMD_BT_ACCESS):
David Woodhouseaa21c002007-12-08 20:04:36 +0000709 spin_lock_irqsave(&priv->driver_lock, flags);
710 if (priv->cur_cmd->pdata_buf)
711 memcpy(priv->cur_cmd->pdata_buf,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200712 &resp->params.bt.addr1, 2 * ETH_ALEN);
David Woodhouseaa21c002007-12-08 20:04:36 +0000713 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200714 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400715 case CMD_RET(CMD_FWT_ACCESS):
David Woodhouseaa21c002007-12-08 20:04:36 +0000716 spin_lock_irqsave(&priv->driver_lock, flags);
717 if (priv->cur_cmd->pdata_buf)
718 memcpy(priv->cur_cmd->pdata_buf, &resp->params.fwt,
David Woodhouse981f1872007-05-25 23:36:54 -0400719 sizeof(resp->params.fwt));
David Woodhouseaa21c002007-12-08 20:04:36 +0000720 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200721 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400722 case CMD_RET(CMD_MESH_ACCESS):
David Woodhouseaa21c002007-12-08 20:04:36 +0000723 if (priv->cur_cmd->pdata_buf)
724 memcpy(priv->cur_cmd->pdata_buf, &resp->params.mesh,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200725 sizeof(resp->params.mesh));
726 break;
Brajesh Dave96287ac2007-11-20 17:44:28 -0500727 case CMD_RET(CMD_802_11_BEACON_CTRL):
728 ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
729 break;
730
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200731 default:
Holger Schuriga6c87002007-08-02 11:54:10 -0400732 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400733 resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200734 break;
735 }
Holger Schuriga6c87002007-08-02 11:54:10 -0400736 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200737 return ret;
738}
739
Holger Schurig69f90322007-11-23 15:43:44 +0100740int lbs_process_rx_command(struct lbs_private *priv)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200741{
742 u16 respcmd;
743 struct cmd_ds_command *resp;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200744 int ret = 0;
745 ulong flags;
746 u16 result;
747
Holger Schuriga6c87002007-08-02 11:54:10 -0400748 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200749
750 /* Now we got response from FW, cancel the command timer */
David Woodhouseaa21c002007-12-08 20:04:36 +0000751 del_timer(&priv->command_timer);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200752
David Woodhouseaa21c002007-12-08 20:04:36 +0000753 mutex_lock(&priv->lock);
754 spin_lock_irqsave(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200755
David Woodhouseaa21c002007-12-08 20:04:36 +0000756 if (!priv->cur_cmd) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400757 lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200758 ret = -1;
David Woodhouseaa21c002007-12-08 20:04:36 +0000759 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200760 goto done;
761 }
David Woodhouseaa21c002007-12-08 20:04:36 +0000762 resp = (struct cmd_ds_command *)(priv->cur_cmd->bufvirtualaddr);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200763
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200764 respcmd = le16_to_cpu(resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200765 result = le16_to_cpu(resp->result);
766
Holger Schuriga6c87002007-08-02 11:54:10 -0400767 lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
768 respcmd, priv->upld_len, jiffies);
David Woodhouseaa21c002007-12-08 20:04:36 +0000769 lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", priv->cur_cmd->bufvirtualaddr,
Holger Schuriga6c87002007-08-02 11:54:10 -0400770 priv->upld_len);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200771
772 if (!(respcmd & 0x8000)) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400773 lbs_deb_host("invalid response!\n");
David Woodhouseaa21c002007-12-08 20:04:36 +0000774 priv->cur_cmd_retcode = -1;
775 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
776 priv->cur_cmd = NULL;
777 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200778 ret = -1;
779 goto done;
780 }
781
782 /* Store the response code to cur_cmd_retcode. */
David Woodhouseaa21c002007-12-08 20:04:36 +0000783 priv->cur_cmd_retcode = result;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200784
Holger Schurig6b63cd02007-08-02 11:53:36 -0400785 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
David Woodhouse981f1872007-05-25 23:36:54 -0400786 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
787 u16 action = le16_to_cpu(psmode->action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200788
Holger Schuriga6c87002007-08-02 11:54:10 -0400789 lbs_deb_host(
790 "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400791 result, action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200792
793 if (result) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400794 lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400795 result);
796 /*
797 * We should not re-try enter-ps command in
798 * ad-hoc mode. It takes place in
Holger Schurig10078322007-11-15 18:05:47 -0500799 * lbs_execute_next_command().
David Woodhouse981f1872007-05-25 23:36:54 -0400800 */
David Woodhouseaa21c002007-12-08 20:04:36 +0000801 if (priv->mode == IW_MODE_ADHOC &&
Dan Williams0aef64d2007-08-02 11:31:18 -0400802 action == CMD_SUBCMD_ENTER_PS)
David Woodhouseaa21c002007-12-08 20:04:36 +0000803 priv->psmode = LBS802_11POWERMODECAM;
Dan Williams0aef64d2007-08-02 11:31:18 -0400804 } else if (action == CMD_SUBCMD_ENTER_PS) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000805 priv->needtowakeup = 0;
806 priv->psstate = PS_STATE_AWAKE;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200807
Holger Schuriga6c87002007-08-02 11:54:10 -0400808 lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
David Woodhouseaa21c002007-12-08 20:04:36 +0000809 if (priv->connect_status != LBS_CONNECTED) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200810 /*
811 * When Deauth Event received before Enter_PS command
812 * response, We need to wake up the firmware.
813 */
Holger Schuriga6c87002007-08-02 11:54:10 -0400814 lbs_deb_host(
Holger Schurig10078322007-11-15 18:05:47 -0500815 "disconnected, invoking lbs_ps_wakeup\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200816
David Woodhouseaa21c002007-12-08 20:04:36 +0000817 spin_unlock_irqrestore(&priv->driver_lock, flags);
818 mutex_unlock(&priv->lock);
Holger Schurig10078322007-11-15 18:05:47 -0500819 lbs_ps_wakeup(priv, 0);
David Woodhouseaa21c002007-12-08 20:04:36 +0000820 mutex_lock(&priv->lock);
821 spin_lock_irqsave(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200822 }
Dan Williams0aef64d2007-08-02 11:31:18 -0400823 } else if (action == CMD_SUBCMD_EXIT_PS) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000824 priv->needtowakeup = 0;
825 priv->psstate = PS_STATE_FULL_POWER;
Holger Schuriga6c87002007-08-02 11:54:10 -0400826 lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200827 } else {
Holger Schuriga6c87002007-08-02 11:54:10 -0400828 lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200829 }
830
David Woodhouseaa21c002007-12-08 20:04:36 +0000831 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
832 priv->cur_cmd = NULL;
833 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200834
835 ret = 0;
836 goto done;
837 }
838
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200839 /* If the command is not successful, cleanup and return failure */
840 if ((result != 0 || !(respcmd & 0x8000))) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400841 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
842 result, respcmd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200843 /*
844 * Handling errors here
845 */
846 switch (respcmd) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400847 case CMD_RET(CMD_GET_HW_SPEC):
848 case CMD_RET(CMD_802_11_RESET):
Holger Schuriga6c87002007-08-02 11:54:10 -0400849 lbs_deb_host("CMD_RESP: reset failed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200850 break;
851
852 }
853
David Woodhouseaa21c002007-12-08 20:04:36 +0000854 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
855 priv->cur_cmd = NULL;
856 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200857
858 ret = -1;
859 goto done;
860 }
861
David Woodhouseaa21c002007-12-08 20:04:36 +0000862 spin_unlock_irqrestore(&priv->driver_lock, flags);
David Woodhouse17230472007-12-07 15:13:05 +0000863
Dan Williams7ad994d2007-12-11 12:33:30 -0500864 if (priv->cur_cmd && priv->cur_cmd->callback) {
865 ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
866 (struct cmd_header *) resp);
867 } else
David Woodhouse1309b552007-12-10 13:36:10 -0500868 ret = handle_cmd_response(priv, 0, resp);
David Woodhouse17230472007-12-07 15:13:05 +0000869
David Woodhouseaa21c002007-12-08 20:04:36 +0000870 spin_lock_irqsave(&priv->driver_lock, flags);
David Woodhouse17230472007-12-07 15:13:05 +0000871
David Woodhouseaa21c002007-12-08 20:04:36 +0000872 if (priv->cur_cmd) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200873 /* Clean up and Put current command back to cmdfreeq */
David Woodhouseaa21c002007-12-08 20:04:36 +0000874 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
875 priv->cur_cmd = NULL;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200876 }
David Woodhouseaa21c002007-12-08 20:04:36 +0000877 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200878
879done:
David Woodhouseaa21c002007-12-08 20:04:36 +0000880 mutex_unlock(&priv->lock);
Holger Schuriga6c87002007-08-02 11:54:10 -0400881 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200882 return ret;
883}
884
Holger Schurig69f90322007-11-23 15:43:44 +0100885int lbs_process_event(struct lbs_private *priv)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200886{
887 int ret = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200888 u32 eventcause;
889
Holger Schurig9556d212007-08-02 13:14:07 -0400890 lbs_deb_enter(LBS_DEB_CMD);
891
David Woodhouseaa21c002007-12-08 20:04:36 +0000892 spin_lock_irq(&priv->driver_lock);
893 eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
894 spin_unlock_irq(&priv->driver_lock);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200895
Holger Schurig0b3c07f2007-11-28 09:15:11 +0100896 lbs_deb_cmd("event cause %d\n", eventcause);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200897
Holger Schurig0b3c07f2007-11-28 09:15:11 +0100898 switch (eventcause) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200899 case MACREG_INT_CODE_LINK_SENSED:
Holger Schurig9012b282007-05-25 11:27:16 -0400900 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200901 break;
902
903 case MACREG_INT_CODE_DEAUTHENTICATED:
Holger Schuriga6c87002007-08-02 11:54:10 -0400904 lbs_deb_cmd("EVENT: deauthenticated\n");
Holger Schurig10078322007-11-15 18:05:47 -0500905 lbs_mac_event_disconnected(priv);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200906 break;
907
908 case MACREG_INT_CODE_DISASSOCIATED:
Holger Schuriga6c87002007-08-02 11:54:10 -0400909 lbs_deb_cmd("EVENT: disassociated\n");
Holger Schurig10078322007-11-15 18:05:47 -0500910 lbs_mac_event_disconnected(priv);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200911 break;
912
Holger Schurig0b3c07f2007-11-28 09:15:11 +0100913 case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
Holger Schuriga6c87002007-08-02 11:54:10 -0400914 lbs_deb_cmd("EVENT: link lost\n");
Holger Schurig10078322007-11-15 18:05:47 -0500915 lbs_mac_event_disconnected(priv);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200916 break;
917
918 case MACREG_INT_CODE_PS_SLEEP:
Holger Schuriga6c87002007-08-02 11:54:10 -0400919 lbs_deb_cmd("EVENT: sleep\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200920
921 /* handle unexpected PS SLEEP event */
David Woodhouseaa21c002007-12-08 20:04:36 +0000922 if (priv->psstate == PS_STATE_FULL_POWER) {
Holger Schurig9012b282007-05-25 11:27:16 -0400923 lbs_deb_cmd(
Holger Schuriga6c87002007-08-02 11:54:10 -0400924 "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200925 break;
926 }
David Woodhouseaa21c002007-12-08 20:04:36 +0000927 priv->psstate = PS_STATE_PRE_SLEEP;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200928
David Woodhouseaa21c002007-12-08 20:04:36 +0000929 lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200930
931 break;
932
933 case MACREG_INT_CODE_PS_AWAKE:
Holger Schuriga6c87002007-08-02 11:54:10 -0400934 lbs_deb_cmd("EVENT: awake\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200935
936 /* handle unexpected PS AWAKE event */
David Woodhouseaa21c002007-12-08 20:04:36 +0000937 if (priv->psstate == PS_STATE_FULL_POWER) {
Holger Schurig9012b282007-05-25 11:27:16 -0400938 lbs_deb_cmd(
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200939 "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
940 break;
941 }
942
David Woodhouseaa21c002007-12-08 20:04:36 +0000943 priv->psstate = PS_STATE_AWAKE;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200944
David Woodhouseaa21c002007-12-08 20:04:36 +0000945 if (priv->needtowakeup) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200946 /*
947 * wait for the command processing to finish
948 * before resuming sending
David Woodhouseaa21c002007-12-08 20:04:36 +0000949 * priv->needtowakeup will be set to FALSE
Holger Schurig10078322007-11-15 18:05:47 -0500950 * in lbs_ps_wakeup()
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200951 */
Holger Schuriga6c87002007-08-02 11:54:10 -0400952 lbs_deb_cmd("waking up ...\n");
Holger Schurig10078322007-11-15 18:05:47 -0500953 lbs_ps_wakeup(priv, 0);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200954 }
955 break;
956
957 case MACREG_INT_CODE_MIC_ERR_UNICAST:
Holger Schurig9012b282007-05-25 11:27:16 -0400958 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200959 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
960 break;
961
962 case MACREG_INT_CODE_MIC_ERR_MULTICAST:
Holger Schurig9012b282007-05-25 11:27:16 -0400963 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200964 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
965 break;
966 case MACREG_INT_CODE_MIB_CHANGED:
967 case MACREG_INT_CODE_INIT_DONE:
968 break;
969
970 case MACREG_INT_CODE_ADHOC_BCN_LOST:
Holger Schuriga6c87002007-08-02 11:54:10 -0400971 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200972 break;
973
974 case MACREG_INT_CODE_RSSI_LOW:
Holger Schuriga6c87002007-08-02 11:54:10 -0400975 lbs_pr_alert("EVENT: rssi low\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200976 break;
977 case MACREG_INT_CODE_SNR_LOW:
Holger Schuriga6c87002007-08-02 11:54:10 -0400978 lbs_pr_alert("EVENT: snr low\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200979 break;
980 case MACREG_INT_CODE_MAX_FAIL:
Holger Schuriga6c87002007-08-02 11:54:10 -0400981 lbs_pr_alert("EVENT: max fail\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200982 break;
983 case MACREG_INT_CODE_RSSI_HIGH:
Holger Schuriga6c87002007-08-02 11:54:10 -0400984 lbs_pr_alert("EVENT: rssi high\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200985 break;
986 case MACREG_INT_CODE_SNR_HIGH:
Holger Schuriga6c87002007-08-02 11:54:10 -0400987 lbs_pr_alert("EVENT: snr high\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200988 break;
989
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -0400990 case MACREG_INT_CODE_MESH_AUTO_STARTED:
Dan Williams5612c012007-08-02 13:20:12 -0400991 /* Ignore spurious autostart events if autostart is disabled */
992 if (!priv->mesh_autostart_enabled) {
993 lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
994 break;
995 }
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -0400996 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
David Woodhouseaa21c002007-12-08 20:04:36 +0000997 priv->mesh_connect_status = LBS_CONNECTED;
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -0400998 if (priv->mesh_open == 1) {
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -0400999 netif_wake_queue(priv->mesh_dev);
1000 netif_carrier_on(priv->mesh_dev);
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001001 }
David Woodhouseaa21c002007-12-08 20:04:36 +00001002 priv->mode = IW_MODE_ADHOC;
Luis Carlos Cobo Rusb8bedef2007-05-30 12:14:34 -04001003 schedule_work(&priv->sync_channel);
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001004 break;
1005
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001006 default:
Holger Schurig0b3c07f2007-11-28 09:15:11 +01001007 lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001008 break;
1009 }
1010
David Woodhouseaa21c002007-12-08 20:04:36 +00001011 spin_lock_irq(&priv->driver_lock);
1012 priv->eventcause = 0;
1013 spin_unlock_irq(&priv->driver_lock);
Holger Schurig9012b282007-05-25 11:27:16 -04001014
Holger Schurig9556d212007-08-02 13:14:07 -04001015 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001016 return ret;
1017}