blob: ab6e729efacfea6817f4c16573fb3311e248e353 [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
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200555static inline int handle_cmd_response(u16 respcmd,
556 struct cmd_ds_command *resp,
Holger Schurig69f90322007-11-23 15:43:44 +0100557 struct lbs_private *priv)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200558{
559 int ret = 0;
560 unsigned long flags;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200561
Holger Schuriga6c87002007-08-02 11:54:10 -0400562 lbs_deb_enter(LBS_DEB_HOST);
563
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200564 switch (respcmd) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400565 case CMD_RET(CMD_MAC_REG_ACCESS):
566 case CMD_RET(CMD_BBP_REG_ACCESS):
567 case CMD_RET(CMD_RF_REG_ACCESS):
Holger Schurig10078322007-11-15 18:05:47 -0500568 ret = lbs_ret_reg_access(priv, respcmd, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200569 break;
570
Holger Schurig6b63cd02007-08-02 11:53:36 -0400571 case CMD_RET(CMD_GET_HW_SPEC):
Holger Schurig10078322007-11-15 18:05:47 -0500572 ret = lbs_ret_get_hw_spec(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200573 break;
574
Holger Schurig6b63cd02007-08-02 11:53:36 -0400575 case CMD_RET(CMD_802_11_SCAN):
Holger Schurig10078322007-11-15 18:05:47 -0500576 ret = lbs_ret_80211_scan(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200577 break;
578
Holger Schurig6b63cd02007-08-02 11:53:36 -0400579 case CMD_RET(CMD_802_11_GET_LOG):
Holger Schurig10078322007-11-15 18:05:47 -0500580 ret = lbs_ret_get_log(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200581 break;
582
Dan Williams0aef64d2007-08-02 11:31:18 -0400583 case CMD_RET_802_11_ASSOCIATE:
Holger Schurig6b63cd02007-08-02 11:53:36 -0400584 case CMD_RET(CMD_802_11_ASSOCIATE):
585 case CMD_RET(CMD_802_11_REASSOCIATE):
Holger Schurig10078322007-11-15 18:05:47 -0500586 ret = lbs_ret_80211_associate(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200587 break;
588
Holger Schurig6b63cd02007-08-02 11:53:36 -0400589 case CMD_RET(CMD_802_11_DISASSOCIATE):
590 case CMD_RET(CMD_802_11_DEAUTHENTICATE):
Holger Schurig10078322007-11-15 18:05:47 -0500591 ret = lbs_ret_80211_disassociate(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200592 break;
593
Holger Schurig6b63cd02007-08-02 11:53:36 -0400594 case CMD_RET(CMD_802_11_AD_HOC_START):
595 case CMD_RET(CMD_802_11_AD_HOC_JOIN):
Holger Schurig10078322007-11-15 18:05:47 -0500596 ret = lbs_ret_80211_ad_hoc_start(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200597 break;
598
Holger Schurig6b63cd02007-08-02 11:53:36 -0400599 case CMD_RET(CMD_802_11_GET_STAT):
Holger Schurig10078322007-11-15 18:05:47 -0500600 ret = lbs_ret_802_11_stat(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200601 break;
602
Holger Schurig6b63cd02007-08-02 11:53:36 -0400603 case CMD_RET(CMD_802_11_SNMP_MIB):
Holger Schurig10078322007-11-15 18:05:47 -0500604 ret = lbs_ret_802_11_snmp_mib(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200605 break;
606
Holger Schurig6b63cd02007-08-02 11:53:36 -0400607 case CMD_RET(CMD_802_11_RF_TX_POWER):
Holger Schurig10078322007-11-15 18:05:47 -0500608 ret = lbs_ret_802_11_rf_tx_power(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200609 break;
610
Holger Schurig6b63cd02007-08-02 11:53:36 -0400611 case CMD_RET(CMD_802_11_SET_AFC):
612 case CMD_RET(CMD_802_11_GET_AFC):
David Woodhouseaa21c002007-12-08 20:04:36 +0000613 spin_lock_irqsave(&priv->driver_lock, flags);
614 memmove(priv->cur_cmd->pdata_buf, &resp->params.afc,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200615 sizeof(struct cmd_ds_802_11_afc));
David Woodhouseaa21c002007-12-08 20:04:36 +0000616 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200617
618 break;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200619
Holger Schurig6b63cd02007-08-02 11:53:36 -0400620 case CMD_RET(CMD_MAC_MULTICAST_ADR):
621 case CMD_RET(CMD_MAC_CONTROL):
622 case CMD_RET(CMD_802_11_SET_WEP):
623 case CMD_RET(CMD_802_11_RESET):
624 case CMD_RET(CMD_802_11_AUTHENTICATE):
625 case CMD_RET(CMD_802_11_RADIO_CONTROL):
626 case CMD_RET(CMD_802_11_BEACON_STOP):
Dan Williams18c96c342007-06-18 12:01:12 -0400627 break;
628
Holger Schurig6b63cd02007-08-02 11:53:36 -0400629 case CMD_RET(CMD_802_11_ENABLE_RSN):
Holger Schurig10078322007-11-15 18:05:47 -0500630 ret = lbs_ret_802_11_enable_rsn(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200631 break;
632
Holger Schurig6b63cd02007-08-02 11:53:36 -0400633 case CMD_RET(CMD_802_11_DATA_RATE):
Holger Schurig10078322007-11-15 18:05:47 -0500634 ret = lbs_ret_802_11_data_rate(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200635 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400636 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
Holger Schurig10078322007-11-15 18:05:47 -0500637 ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200638 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400639 case CMD_RET(CMD_802_11_RF_CHANNEL):
Holger Schurig10078322007-11-15 18:05:47 -0500640 ret = lbs_ret_802_11_rf_channel(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200641 break;
642
Holger Schurig6b63cd02007-08-02 11:53:36 -0400643 case CMD_RET(CMD_802_11_RSSI):
Holger Schurig10078322007-11-15 18:05:47 -0500644 ret = lbs_ret_802_11_rssi(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200645 break;
646
Holger Schurig6b63cd02007-08-02 11:53:36 -0400647 case CMD_RET(CMD_802_11_MAC_ADDRESS):
Holger Schurig10078322007-11-15 18:05:47 -0500648 ret = lbs_ret_802_11_mac_address(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200649 break;
650
Holger Schurig6b63cd02007-08-02 11:53:36 -0400651 case CMD_RET(CMD_802_11_AD_HOC_STOP):
Holger Schurig10078322007-11-15 18:05:47 -0500652 ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200653 break;
654
Holger Schurig6b63cd02007-08-02 11:53:36 -0400655 case CMD_RET(CMD_802_11_KEY_MATERIAL):
Holger Schurig10078322007-11-15 18:05:47 -0500656 ret = lbs_ret_802_11_key_material(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200657 break;
658
Holger Schurig6b63cd02007-08-02 11:53:36 -0400659 case CMD_RET(CMD_802_11_EEPROM_ACCESS):
Holger Schurig10078322007-11-15 18:05:47 -0500660 ret = lbs_ret_802_11_eeprom_access(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200661 break;
662
Holger Schurig6b63cd02007-08-02 11:53:36 -0400663 case CMD_RET(CMD_802_11D_DOMAIN_INFO):
Holger Schurig10078322007-11-15 18:05:47 -0500664 ret = lbs_ret_802_11d_domain_info(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200665 break;
666
Holger Schurig6b63cd02007-08-02 11:53:36 -0400667 case CMD_RET(CMD_802_11_SLEEP_PARAMS):
Holger Schurig10078322007-11-15 18:05:47 -0500668 ret = lbs_ret_802_11_sleep_params(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200669 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400670 case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
David Woodhouseaa21c002007-12-08 20:04:36 +0000671 spin_lock_irqsave(&priv->driver_lock, flags);
672 *((u16 *) priv->cur_cmd->pdata_buf) =
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200673 le16_to_cpu(resp->params.inactivity_timeout.timeout);
David Woodhouseaa21c002007-12-08 20:04:36 +0000674 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200675 break;
676
Holger Schurig6b63cd02007-08-02 11:53:36 -0400677 case CMD_RET(CMD_802_11_TPC_CFG):
David Woodhouseaa21c002007-12-08 20:04:36 +0000678 spin_lock_irqsave(&priv->driver_lock, flags);
679 memmove(priv->cur_cmd->pdata_buf, &resp->params.tpccfg,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200680 sizeof(struct cmd_ds_802_11_tpc_cfg));
David Woodhouseaa21c002007-12-08 20:04:36 +0000681 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200682 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400683 case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
David Woodhouseaa21c002007-12-08 20:04:36 +0000684 spin_lock_irqsave(&priv->driver_lock, flags);
685 memmove(priv->cur_cmd->pdata_buf, &resp->params.ledgpio,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200686 sizeof(struct cmd_ds_802_11_led_ctrl));
David Woodhouseaa21c002007-12-08 20:04:36 +0000687 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200688 break;
Holger Schurig3a188642007-11-26 10:07:14 +0100689 case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT):
690 ret = lbs_ret_802_11_subscribe_event(priv, resp);
691 break;
692
Holger Schurig6b63cd02007-08-02 11:53:36 -0400693 case CMD_RET(CMD_802_11_PWR_CFG):
David Woodhouseaa21c002007-12-08 20:04:36 +0000694 spin_lock_irqsave(&priv->driver_lock, flags);
695 memmove(priv->cur_cmd->pdata_buf, &resp->params.pwrcfg,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200696 sizeof(struct cmd_ds_802_11_pwr_cfg));
David Woodhouseaa21c002007-12-08 20:04:36 +0000697 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200698
699 break;
700
Holger Schurig6b63cd02007-08-02 11:53:36 -0400701 case CMD_RET(CMD_GET_TSF):
David Woodhouseaa21c002007-12-08 20:04:36 +0000702 spin_lock_irqsave(&priv->driver_lock, flags);
703 memcpy(priv->cur_cmd->pdata_buf,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200704 &resp->params.gettsf.tsfvalue, sizeof(u64));
David Woodhouseaa21c002007-12-08 20:04:36 +0000705 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200706 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400707 case CMD_RET(CMD_BT_ACCESS):
David Woodhouseaa21c002007-12-08 20:04:36 +0000708 spin_lock_irqsave(&priv->driver_lock, flags);
709 if (priv->cur_cmd->pdata_buf)
710 memcpy(priv->cur_cmd->pdata_buf,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200711 &resp->params.bt.addr1, 2 * ETH_ALEN);
David Woodhouseaa21c002007-12-08 20:04:36 +0000712 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200713 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400714 case CMD_RET(CMD_FWT_ACCESS):
David Woodhouseaa21c002007-12-08 20:04:36 +0000715 spin_lock_irqsave(&priv->driver_lock, flags);
716 if (priv->cur_cmd->pdata_buf)
717 memcpy(priv->cur_cmd->pdata_buf, &resp->params.fwt,
David Woodhouse981f1872007-05-25 23:36:54 -0400718 sizeof(resp->params.fwt));
David Woodhouseaa21c002007-12-08 20:04:36 +0000719 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200720 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400721 case CMD_RET(CMD_MESH_ACCESS):
David Woodhouseaa21c002007-12-08 20:04:36 +0000722 if (priv->cur_cmd->pdata_buf)
723 memcpy(priv->cur_cmd->pdata_buf, &resp->params.mesh,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200724 sizeof(resp->params.mesh));
725 break;
Brajesh Dave96287ac2007-11-20 17:44:28 -0500726 case CMD_RET(CMD_802_11_BEACON_CTRL):
727 ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
728 break;
729
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200730 default:
Holger Schuriga6c87002007-08-02 11:54:10 -0400731 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400732 resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200733 break;
734 }
Holger Schuriga6c87002007-08-02 11:54:10 -0400735 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200736 return ret;
737}
738
Holger Schurig69f90322007-11-23 15:43:44 +0100739int lbs_process_rx_command(struct lbs_private *priv)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200740{
741 u16 respcmd;
742 struct cmd_ds_command *resp;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200743 int ret = 0;
744 ulong flags;
745 u16 result;
746
Holger Schuriga6c87002007-08-02 11:54:10 -0400747 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200748
749 /* Now we got response from FW, cancel the command timer */
David Woodhouseaa21c002007-12-08 20:04:36 +0000750 del_timer(&priv->command_timer);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200751
David Woodhouseaa21c002007-12-08 20:04:36 +0000752 mutex_lock(&priv->lock);
753 spin_lock_irqsave(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200754
David Woodhouseaa21c002007-12-08 20:04:36 +0000755 if (!priv->cur_cmd) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400756 lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200757 ret = -1;
David Woodhouseaa21c002007-12-08 20:04:36 +0000758 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200759 goto done;
760 }
David Woodhouseaa21c002007-12-08 20:04:36 +0000761 resp = (struct cmd_ds_command *)(priv->cur_cmd->bufvirtualaddr);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200762
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200763 respcmd = le16_to_cpu(resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200764 result = le16_to_cpu(resp->result);
765
Holger Schuriga6c87002007-08-02 11:54:10 -0400766 lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
767 respcmd, priv->upld_len, jiffies);
David Woodhouseaa21c002007-12-08 20:04:36 +0000768 lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", priv->cur_cmd->bufvirtualaddr,
Holger Schuriga6c87002007-08-02 11:54:10 -0400769 priv->upld_len);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200770
771 if (!(respcmd & 0x8000)) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400772 lbs_deb_host("invalid response!\n");
David Woodhouseaa21c002007-12-08 20:04:36 +0000773 priv->cur_cmd_retcode = -1;
774 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
775 priv->cur_cmd = NULL;
776 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200777 ret = -1;
778 goto done;
779 }
780
781 /* Store the response code to cur_cmd_retcode. */
David Woodhouseaa21c002007-12-08 20:04:36 +0000782 priv->cur_cmd_retcode = result;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200783
Holger Schurig6b63cd02007-08-02 11:53:36 -0400784 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
David Woodhouse981f1872007-05-25 23:36:54 -0400785 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
786 u16 action = le16_to_cpu(psmode->action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200787
Holger Schuriga6c87002007-08-02 11:54:10 -0400788 lbs_deb_host(
789 "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400790 result, action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200791
792 if (result) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400793 lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400794 result);
795 /*
796 * We should not re-try enter-ps command in
797 * ad-hoc mode. It takes place in
Holger Schurig10078322007-11-15 18:05:47 -0500798 * lbs_execute_next_command().
David Woodhouse981f1872007-05-25 23:36:54 -0400799 */
David Woodhouseaa21c002007-12-08 20:04:36 +0000800 if (priv->mode == IW_MODE_ADHOC &&
Dan Williams0aef64d2007-08-02 11:31:18 -0400801 action == CMD_SUBCMD_ENTER_PS)
David Woodhouseaa21c002007-12-08 20:04:36 +0000802 priv->psmode = LBS802_11POWERMODECAM;
Dan Williams0aef64d2007-08-02 11:31:18 -0400803 } else if (action == CMD_SUBCMD_ENTER_PS) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000804 priv->needtowakeup = 0;
805 priv->psstate = PS_STATE_AWAKE;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200806
Holger Schuriga6c87002007-08-02 11:54:10 -0400807 lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
David Woodhouseaa21c002007-12-08 20:04:36 +0000808 if (priv->connect_status != LBS_CONNECTED) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200809 /*
810 * When Deauth Event received before Enter_PS command
811 * response, We need to wake up the firmware.
812 */
Holger Schuriga6c87002007-08-02 11:54:10 -0400813 lbs_deb_host(
Holger Schurig10078322007-11-15 18:05:47 -0500814 "disconnected, invoking lbs_ps_wakeup\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200815
David Woodhouseaa21c002007-12-08 20:04:36 +0000816 spin_unlock_irqrestore(&priv->driver_lock, flags);
817 mutex_unlock(&priv->lock);
Holger Schurig10078322007-11-15 18:05:47 -0500818 lbs_ps_wakeup(priv, 0);
David Woodhouseaa21c002007-12-08 20:04:36 +0000819 mutex_lock(&priv->lock);
820 spin_lock_irqsave(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200821 }
Dan Williams0aef64d2007-08-02 11:31:18 -0400822 } else if (action == CMD_SUBCMD_EXIT_PS) {
David Woodhouseaa21c002007-12-08 20:04:36 +0000823 priv->needtowakeup = 0;
824 priv->psstate = PS_STATE_FULL_POWER;
Holger Schuriga6c87002007-08-02 11:54:10 -0400825 lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200826 } else {
Holger Schuriga6c87002007-08-02 11:54:10 -0400827 lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200828 }
829
David Woodhouseaa21c002007-12-08 20:04:36 +0000830 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
831 priv->cur_cmd = NULL;
832 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200833
834 ret = 0;
835 goto done;
836 }
837
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200838 /* If the command is not successful, cleanup and return failure */
839 if ((result != 0 || !(respcmd & 0x8000))) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400840 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
841 result, respcmd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200842 /*
843 * Handling errors here
844 */
845 switch (respcmd) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400846 case CMD_RET(CMD_GET_HW_SPEC):
847 case CMD_RET(CMD_802_11_RESET):
Holger Schuriga6c87002007-08-02 11:54:10 -0400848 lbs_deb_host("CMD_RESP: reset failed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200849 break;
850
851 }
852
David Woodhouseaa21c002007-12-08 20:04:36 +0000853 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
854 priv->cur_cmd = NULL;
855 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200856
857 ret = -1;
858 goto done;
859 }
860
David Woodhouseaa21c002007-12-08 20:04:36 +0000861 spin_unlock_irqrestore(&priv->driver_lock, flags);
David Woodhouse17230472007-12-07 15:13:05 +0000862
David Woodhouseaa21c002007-12-08 20:04:36 +0000863 if (priv->cur_cmd && priv->cur_cmd->callback)
864 ret = priv->cur_cmd->callback(respcmd, resp, priv);
David Woodhouse17230472007-12-07 15:13:05 +0000865 else
Holger Schurig675787e2007-12-05 17:58:11 +0100866 ret = handle_cmd_response(respcmd, resp, priv);
David Woodhouse17230472007-12-07 15:13:05 +0000867
David Woodhouseaa21c002007-12-08 20:04:36 +0000868 spin_lock_irqsave(&priv->driver_lock, flags);
David Woodhouse17230472007-12-07 15:13:05 +0000869
David Woodhouseaa21c002007-12-08 20:04:36 +0000870 if (priv->cur_cmd) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200871 /* Clean up and Put current command back to cmdfreeq */
David Woodhouseaa21c002007-12-08 20:04:36 +0000872 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
873 priv->cur_cmd = NULL;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200874 }
David Woodhouseaa21c002007-12-08 20:04:36 +0000875 spin_unlock_irqrestore(&priv->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200876
877done:
David Woodhouseaa21c002007-12-08 20:04:36 +0000878 mutex_unlock(&priv->lock);
Holger Schuriga6c87002007-08-02 11:54:10 -0400879 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200880 return ret;
881}
882
Holger Schurig69f90322007-11-23 15:43:44 +0100883int lbs_process_event(struct lbs_private *priv)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200884{
885 int ret = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200886 u32 eventcause;
887
Holger Schurig9556d212007-08-02 13:14:07 -0400888 lbs_deb_enter(LBS_DEB_CMD);
889
David Woodhouseaa21c002007-12-08 20:04:36 +0000890 spin_lock_irq(&priv->driver_lock);
891 eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
892 spin_unlock_irq(&priv->driver_lock);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200893
Holger Schurig0b3c07f2007-11-28 09:15:11 +0100894 lbs_deb_cmd("event cause %d\n", eventcause);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200895
Holger Schurig0b3c07f2007-11-28 09:15:11 +0100896 switch (eventcause) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200897 case MACREG_INT_CODE_LINK_SENSED:
Holger Schurig9012b282007-05-25 11:27:16 -0400898 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200899 break;
900
901 case MACREG_INT_CODE_DEAUTHENTICATED:
Holger Schuriga6c87002007-08-02 11:54:10 -0400902 lbs_deb_cmd("EVENT: deauthenticated\n");
Holger Schurig10078322007-11-15 18:05:47 -0500903 lbs_mac_event_disconnected(priv);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200904 break;
905
906 case MACREG_INT_CODE_DISASSOCIATED:
Holger Schuriga6c87002007-08-02 11:54:10 -0400907 lbs_deb_cmd("EVENT: disassociated\n");
Holger Schurig10078322007-11-15 18:05:47 -0500908 lbs_mac_event_disconnected(priv);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200909 break;
910
Holger Schurig0b3c07f2007-11-28 09:15:11 +0100911 case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
Holger Schuriga6c87002007-08-02 11:54:10 -0400912 lbs_deb_cmd("EVENT: link lost\n");
Holger Schurig10078322007-11-15 18:05:47 -0500913 lbs_mac_event_disconnected(priv);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200914 break;
915
916 case MACREG_INT_CODE_PS_SLEEP:
Holger Schuriga6c87002007-08-02 11:54:10 -0400917 lbs_deb_cmd("EVENT: sleep\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200918
919 /* handle unexpected PS SLEEP event */
David Woodhouseaa21c002007-12-08 20:04:36 +0000920 if (priv->psstate == PS_STATE_FULL_POWER) {
Holger Schurig9012b282007-05-25 11:27:16 -0400921 lbs_deb_cmd(
Holger Schuriga6c87002007-08-02 11:54:10 -0400922 "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200923 break;
924 }
David Woodhouseaa21c002007-12-08 20:04:36 +0000925 priv->psstate = PS_STATE_PRE_SLEEP;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200926
David Woodhouseaa21c002007-12-08 20:04:36 +0000927 lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200928
929 break;
930
931 case MACREG_INT_CODE_PS_AWAKE:
Holger Schuriga6c87002007-08-02 11:54:10 -0400932 lbs_deb_cmd("EVENT: awake\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200933
934 /* handle unexpected PS AWAKE event */
David Woodhouseaa21c002007-12-08 20:04:36 +0000935 if (priv->psstate == PS_STATE_FULL_POWER) {
Holger Schurig9012b282007-05-25 11:27:16 -0400936 lbs_deb_cmd(
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200937 "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
938 break;
939 }
940
David Woodhouseaa21c002007-12-08 20:04:36 +0000941 priv->psstate = PS_STATE_AWAKE;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200942
David Woodhouseaa21c002007-12-08 20:04:36 +0000943 if (priv->needtowakeup) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200944 /*
945 * wait for the command processing to finish
946 * before resuming sending
David Woodhouseaa21c002007-12-08 20:04:36 +0000947 * priv->needtowakeup will be set to FALSE
Holger Schurig10078322007-11-15 18:05:47 -0500948 * in lbs_ps_wakeup()
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200949 */
Holger Schuriga6c87002007-08-02 11:54:10 -0400950 lbs_deb_cmd("waking up ...\n");
Holger Schurig10078322007-11-15 18:05:47 -0500951 lbs_ps_wakeup(priv, 0);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200952 }
953 break;
954
955 case MACREG_INT_CODE_MIC_ERR_UNICAST:
Holger Schurig9012b282007-05-25 11:27:16 -0400956 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200957 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
958 break;
959
960 case MACREG_INT_CODE_MIC_ERR_MULTICAST:
Holger Schurig9012b282007-05-25 11:27:16 -0400961 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200962 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
963 break;
964 case MACREG_INT_CODE_MIB_CHANGED:
965 case MACREG_INT_CODE_INIT_DONE:
966 break;
967
968 case MACREG_INT_CODE_ADHOC_BCN_LOST:
Holger Schuriga6c87002007-08-02 11:54:10 -0400969 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200970 break;
971
972 case MACREG_INT_CODE_RSSI_LOW:
Holger Schuriga6c87002007-08-02 11:54:10 -0400973 lbs_pr_alert("EVENT: rssi low\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200974 break;
975 case MACREG_INT_CODE_SNR_LOW:
Holger Schuriga6c87002007-08-02 11:54:10 -0400976 lbs_pr_alert("EVENT: snr low\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200977 break;
978 case MACREG_INT_CODE_MAX_FAIL:
Holger Schuriga6c87002007-08-02 11:54:10 -0400979 lbs_pr_alert("EVENT: max fail\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200980 break;
981 case MACREG_INT_CODE_RSSI_HIGH:
Holger Schuriga6c87002007-08-02 11:54:10 -0400982 lbs_pr_alert("EVENT: rssi high\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200983 break;
984 case MACREG_INT_CODE_SNR_HIGH:
Holger Schuriga6c87002007-08-02 11:54:10 -0400985 lbs_pr_alert("EVENT: snr high\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200986 break;
987
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -0400988 case MACREG_INT_CODE_MESH_AUTO_STARTED:
Dan Williams5612c012007-08-02 13:20:12 -0400989 /* Ignore spurious autostart events if autostart is disabled */
990 if (!priv->mesh_autostart_enabled) {
991 lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
992 break;
993 }
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -0400994 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
David Woodhouseaa21c002007-12-08 20:04:36 +0000995 priv->mesh_connect_status = LBS_CONNECTED;
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -0400996 if (priv->mesh_open == 1) {
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -0400997 netif_wake_queue(priv->mesh_dev);
998 netif_carrier_on(priv->mesh_dev);
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -0400999 }
David Woodhouseaa21c002007-12-08 20:04:36 +00001000 priv->mode = IW_MODE_ADHOC;
Luis Carlos Cobo Rusb8bedef2007-05-30 12:14:34 -04001001 schedule_work(&priv->sync_channel);
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001002 break;
1003
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001004 default:
Holger Schurig0b3c07f2007-11-28 09:15:11 +01001005 lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001006 break;
1007 }
1008
David Woodhouseaa21c002007-12-08 20:04:36 +00001009 spin_lock_irq(&priv->driver_lock);
1010 priv->eventcause = 0;
1011 spin_unlock_irq(&priv->driver_lock);
Holger Schurig9012b282007-05-25 11:27:16 -04001012
Holger Schurig9556d212007-08-02 13:14:07 -04001013 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001014 return ret;
1015}