~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/net/wireless/libertas/cmd.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file contains the handling of command.
 
3
 * It prepares command and sends it to firmware when it is ready.
 
4
 */
 
5
 
 
6
#include <linux/hardirq.h>
 
7
#include <linux/kfifo.h>
 
8
#include <linux/sched.h>
 
9
#include <linux/slab.h>
 
10
#include <linux/if_arp.h>
 
11
#include <linux/export.h>
 
12
 
 
13
#include "decl.h"
 
14
#include "cfg.h"
 
15
#include "cmd.h"
 
16
 
 
17
#define CAL_NF(nf)              ((s32)(-(s32)(nf)))
 
18
#define CAL_RSSI(snr, nf)       ((s32)((s32)(snr) + CAL_NF(nf)))
 
19
 
 
20
/**
 
21
 * lbs_cmd_copyback - Simple callback that copies response back into command
 
22
 *
 
23
 * @priv:       A pointer to &struct lbs_private structure
 
24
 * @extra:      A pointer to the original command structure for which
 
25
 *              'resp' is a response
 
26
 * @resp:       A pointer to the command response
 
27
 *
 
28
 * returns:     0 on success, error on failure
 
29
 */
 
30
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
 
31
                     struct cmd_header *resp)
 
32
{
 
33
        struct cmd_header *buf = (void *)extra;
 
34
        uint16_t copy_len;
 
35
 
 
36
        copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
 
37
        memcpy(buf, resp, copy_len);
 
38
        return 0;
 
39
}
 
40
EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
 
41
 
 
42
/**
 
43
 *  lbs_cmd_async_callback - Simple callback that ignores the result.
 
44
 *  Use this if you just want to send a command to the hardware, but don't
 
45
 *  care for the result.
 
46
 *
 
47
 *  @priv:      ignored
 
48
 *  @extra:     ignored
 
49
 *  @resp:      ignored
 
50
 *
 
51
 *  returns:    0 for success
 
52
 */
 
53
static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
 
54
                     struct cmd_header *resp)
 
55
{
 
56
        return 0;
 
57
}
 
58
 
 
59
 
 
60
/**
 
61
 *  is_command_allowed_in_ps - tests if a command is allowed in Power Save mode
 
62
 *
 
63
 *  @cmd:       the command ID
 
64
 *
 
65
 *  returns:    1 if allowed, 0 if not allowed
 
66
 */
 
67
static u8 is_command_allowed_in_ps(u16 cmd)
 
68
{
 
69
        switch (cmd) {
 
70
        case CMD_802_11_RSSI:
 
71
                return 1;
 
72
        case CMD_802_11_HOST_SLEEP_CFG:
 
73
                return 1;
 
74
        default:
 
75
                break;
 
76
        }
 
77
        return 0;
 
78
}
 
79
 
 
80
/**
 
81
 *  lbs_update_hw_spec - Updates the hardware details like MAC address
 
82
 *  and regulatory region
 
83
 *
 
84
 *  @priv:      A pointer to &struct lbs_private structure
 
85
 *
 
86
 *  returns:    0 on success, error on failure
 
87
 */
 
88
int lbs_update_hw_spec(struct lbs_private *priv)
 
89
{
 
90
        struct cmd_ds_get_hw_spec cmd;
 
91
        int ret = -1;
 
92
        u32 i;
 
93
 
 
94
        lbs_deb_enter(LBS_DEB_CMD);
 
95
 
 
96
        memset(&cmd, 0, sizeof(cmd));
 
97
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
98
        memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
 
99
        ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
 
100
        if (ret)
 
101
                goto out;
 
102
 
 
103
        priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
 
104
 
 
105
        /* The firmware release is in an interesting format: the patch
 
106
         * level is in the most significant nibble ... so fix that: */
 
107
        priv->fwrelease = le32_to_cpu(cmd.fwrelease);
 
108
        priv->fwrelease = (priv->fwrelease << 8) |
 
109
                (priv->fwrelease >> 24 & 0xff);
 
110
 
 
111
        /* Some firmware capabilities:
 
112
         * CF card    firmware 5.0.16p0:   cap 0x00000303
 
113
         * USB dongle firmware 5.110.17p2: cap 0x00000303
 
114
         */
 
115
        netdev_info(priv->dev, "%pM, fw %u.%u.%up%u, cap 0x%08x\n",
 
116
                cmd.permanentaddr,
 
117
                priv->fwrelease >> 24 & 0xff,
 
118
                priv->fwrelease >> 16 & 0xff,
 
119
                priv->fwrelease >>  8 & 0xff,
 
120
                priv->fwrelease       & 0xff,
 
121
                priv->fwcapinfo);
 
122
        lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
 
123
                    cmd.hwifversion, cmd.version);
 
124
 
 
125
        /* Clamp region code to 8-bit since FW spec indicates that it should
 
126
         * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
 
127
         * returns non-zero high 8 bits here.
 
128
         *
 
129
         * Firmware version 4.0.102 used in CF8381 has region code shifted.  We
 
130
         * need to check for this problem and handle it properly.
 
131
         */
 
132
        if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4)
 
133
                priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF;
 
134
        else
 
135
                priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
 
136
 
 
137
        for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
 
138
                /* use the region code to search for the index */
 
139
                if (priv->regioncode == lbs_region_code_to_index[i])
 
140
                        break;
 
141
        }
 
142
 
 
143
        /* if it's unidentified region code, use the default (USA) */
 
144
        if (i >= MRVDRV_MAX_REGION_CODE) {
 
145
                priv->regioncode = 0x10;
 
146
                netdev_info(priv->dev,
 
147
                            "unidentified region code; using the default (USA)\n");
 
148
        }
 
149
 
 
150
        if (priv->current_addr[0] == 0xff)
 
151
                memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
 
152
 
 
153
        if (!priv->copied_hwaddr) {
 
154
                memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
 
155
                if (priv->mesh_dev)
 
156
                        memcpy(priv->mesh_dev->dev_addr,
 
157
                                priv->current_addr, ETH_ALEN);
 
158
                priv->copied_hwaddr = 1;
 
159
        }
 
160
 
 
161
out:
 
162
        lbs_deb_leave(LBS_DEB_CMD);
 
163
        return ret;
 
164
}
 
165
 
 
166
static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
 
167
                        struct cmd_header *resp)
 
168
{
 
169
        lbs_deb_enter(LBS_DEB_CMD);
 
170
        if (priv->is_host_sleep_activated) {
 
171
                priv->is_host_sleep_configured = 0;
 
172
                if (priv->psstate == PS_STATE_FULL_POWER) {
 
173
                        priv->is_host_sleep_activated = 0;
 
174
                        wake_up_interruptible(&priv->host_sleep_q);
 
175
                }
 
176
        } else {
 
177
                priv->is_host_sleep_configured = 1;
 
178
        }
 
179
        lbs_deb_leave(LBS_DEB_CMD);
 
180
        return 0;
 
181
}
 
182
 
 
183
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
 
184
                struct wol_config *p_wol_config)
 
185
{
 
186
        struct cmd_ds_host_sleep cmd_config;
 
187
        int ret;
 
188
 
 
189
        /*
 
190
         * Certain firmware versions do not support EHS_REMOVE_WAKEUP command
 
191
         * and the card will return a failure.  Since we need to be
 
192
         * able to reset the mask, in those cases we set a 0 mask instead.
 
193
         */
 
194
        if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported)
 
195
                criteria = 0;
 
196
 
 
197
        cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
 
198
        cmd_config.criteria = cpu_to_le32(criteria);
 
199
        cmd_config.gpio = priv->wol_gpio;
 
200
        cmd_config.gap = priv->wol_gap;
 
201
 
 
202
        if (p_wol_config != NULL)
 
203
                memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config,
 
204
                                sizeof(struct wol_config));
 
205
        else
 
206
                cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
 
207
 
 
208
        ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
 
209
                        le16_to_cpu(cmd_config.hdr.size),
 
210
                        lbs_ret_host_sleep_cfg, 0);
 
211
        if (!ret) {
 
212
                if (p_wol_config)
 
213
                        memcpy((uint8_t *) p_wol_config,
 
214
                                        (uint8_t *)&cmd_config.wol_conf,
 
215
                                        sizeof(struct wol_config));
 
216
        } else {
 
217
                netdev_info(priv->dev, "HOST_SLEEP_CFG failed %d\n", ret);
 
218
        }
 
219
 
 
220
        return ret;
 
221
}
 
222
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
 
223
 
 
224
/**
 
225
 *  lbs_set_ps_mode - Sets the Power Save mode
 
226
 *
 
227
 *  @priv:      A pointer to &struct lbs_private structure
 
228
 *  @cmd_action: The Power Save operation (PS_MODE_ACTION_ENTER_PS or
 
229
 *                         PS_MODE_ACTION_EXIT_PS)
 
230
 *  @block:     Whether to block on a response or not
 
231
 *
 
232
 *  returns:    0 on success, error on failure
 
233
 */
 
234
int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
 
235
{
 
236
        struct cmd_ds_802_11_ps_mode cmd;
 
237
        int ret = 0;
 
238
 
 
239
        lbs_deb_enter(LBS_DEB_CMD);
 
240
 
 
241
        memset(&cmd, 0, sizeof(cmd));
 
242
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
243
        cmd.action = cpu_to_le16(cmd_action);
 
244
 
 
245
        if (cmd_action == PS_MODE_ACTION_ENTER_PS) {
 
246
                lbs_deb_cmd("PS_MODE: action ENTER_PS\n");
 
247
                cmd.multipledtim = cpu_to_le16(1);  /* Default DTIM multiple */
 
248
        } else if (cmd_action == PS_MODE_ACTION_EXIT_PS) {
 
249
                lbs_deb_cmd("PS_MODE: action EXIT_PS\n");
 
250
        } else {
 
251
                /* We don't handle CONFIRM_SLEEP here because it needs to
 
252
                 * be fastpathed to the firmware.
 
253
                 */
 
254
                lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action);
 
255
                ret = -EOPNOTSUPP;
 
256
                goto out;
 
257
        }
 
258
 
 
259
        if (block)
 
260
                ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd);
 
261
        else
 
262
                lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));
 
263
 
 
264
out:
 
265
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
266
        return ret;
 
267
}
 
268
 
 
269
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
 
270
                                struct sleep_params *sp)
 
271
{
 
272
        struct cmd_ds_802_11_sleep_params cmd;
 
273
        int ret;
 
274
 
 
275
        lbs_deb_enter(LBS_DEB_CMD);
 
276
 
 
277
        if (cmd_action == CMD_ACT_GET) {
 
278
                memset(&cmd, 0, sizeof(cmd));
 
279
        } else {
 
280
                cmd.error = cpu_to_le16(sp->sp_error);
 
281
                cmd.offset = cpu_to_le16(sp->sp_offset);
 
282
                cmd.stabletime = cpu_to_le16(sp->sp_stabletime);
 
283
                cmd.calcontrol = sp->sp_calcontrol;
 
284
                cmd.externalsleepclk = sp->sp_extsleepclk;
 
285
                cmd.reserved = cpu_to_le16(sp->sp_reserved);
 
286
        }
 
287
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
288
        cmd.action = cpu_to_le16(cmd_action);
 
289
 
 
290
        ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd);
 
291
 
 
292
        if (!ret) {
 
293
                lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
 
294
                            "calcontrol 0x%x extsleepclk 0x%x\n",
 
295
                            le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
 
296
                            le16_to_cpu(cmd.stabletime), cmd.calcontrol,
 
297
                            cmd.externalsleepclk);
 
298
 
 
299
                sp->sp_error = le16_to_cpu(cmd.error);
 
300
                sp->sp_offset = le16_to_cpu(cmd.offset);
 
301
                sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
 
302
                sp->sp_calcontrol = cmd.calcontrol;
 
303
                sp->sp_extsleepclk = cmd.externalsleepclk;
 
304
                sp->sp_reserved = le16_to_cpu(cmd.reserved);
 
305
        }
 
306
 
 
307
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
308
        return 0;
 
309
}
 
310
 
 
311
static int lbs_wait_for_ds_awake(struct lbs_private *priv)
 
312
{
 
313
        int ret = 0;
 
314
 
 
315
        lbs_deb_enter(LBS_DEB_CMD);
 
316
 
 
317
        if (priv->is_deep_sleep) {
 
318
                if (!wait_event_interruptible_timeout(priv->ds_awake_q,
 
319
                                        !priv->is_deep_sleep, (10 * HZ))) {
 
320
                        netdev_err(priv->dev, "ds_awake_q: timer expired\n");
 
321
                        ret = -1;
 
322
                }
 
323
        }
 
324
 
 
325
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
326
        return ret;
 
327
}
 
328
 
 
329
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
 
330
{
 
331
        int ret =  0;
 
332
 
 
333
        lbs_deb_enter(LBS_DEB_CMD);
 
334
 
 
335
        if (deep_sleep) {
 
336
                if (priv->is_deep_sleep != 1) {
 
337
                        lbs_deb_cmd("deep sleep: sleep\n");
 
338
                        BUG_ON(!priv->enter_deep_sleep);
 
339
                        ret = priv->enter_deep_sleep(priv);
 
340
                        if (!ret) {
 
341
                                netif_stop_queue(priv->dev);
 
342
                                netif_carrier_off(priv->dev);
 
343
                        }
 
344
                } else {
 
345
                        netdev_err(priv->dev, "deep sleep: already enabled\n");
 
346
                }
 
347
        } else {
 
348
                if (priv->is_deep_sleep) {
 
349
                        lbs_deb_cmd("deep sleep: wakeup\n");
 
350
                        BUG_ON(!priv->exit_deep_sleep);
 
351
                        ret = priv->exit_deep_sleep(priv);
 
352
                        if (!ret) {
 
353
                                ret = lbs_wait_for_ds_awake(priv);
 
354
                                if (ret)
 
355
                                        netdev_err(priv->dev,
 
356
                                                   "deep sleep: wakeup failed\n");
 
357
                        }
 
358
                }
 
359
        }
 
360
 
 
361
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
362
        return ret;
 
363
}
 
364
 
 
365
static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
 
366
                unsigned long dummy,
 
367
                struct cmd_header *cmd)
 
368
{
 
369
        lbs_deb_enter(LBS_DEB_FW);
 
370
        priv->is_host_sleep_activated = 1;
 
371
        wake_up_interruptible(&priv->host_sleep_q);
 
372
        lbs_deb_leave(LBS_DEB_FW);
 
373
        return 0;
 
374
}
 
375
 
 
376
int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)
 
377
{
 
378
        struct cmd_header cmd;
 
379
        int ret = 0;
 
380
        uint32_t criteria = EHS_REMOVE_WAKEUP;
 
381
 
 
382
        lbs_deb_enter(LBS_DEB_CMD);
 
383
 
 
384
        if (host_sleep) {
 
385
                if (priv->is_host_sleep_activated != 1) {
 
386
                        memset(&cmd, 0, sizeof(cmd));
 
387
                        ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
 
388
                                        (struct wol_config *)NULL);
 
389
                        if (ret) {
 
390
                                netdev_info(priv->dev,
 
391
                                            "Host sleep configuration failed: %d\n",
 
392
                                            ret);
 
393
                                return ret;
 
394
                        }
 
395
                        if (priv->psstate == PS_STATE_FULL_POWER) {
 
396
                                ret = __lbs_cmd(priv,
 
397
                                                CMD_802_11_HOST_SLEEP_ACTIVATE,
 
398
                                                &cmd,
 
399
                                                sizeof(cmd),
 
400
                                                lbs_ret_host_sleep_activate, 0);
 
401
                                if (ret)
 
402
                                        netdev_info(priv->dev,
 
403
                                                    "HOST_SLEEP_ACTIVATE failed: %d\n",
 
404
                                                    ret);
 
405
                        }
 
406
 
 
407
                        if (!wait_event_interruptible_timeout(
 
408
                                                priv->host_sleep_q,
 
409
                                                priv->is_host_sleep_activated,
 
410
                                                (10 * HZ))) {
 
411
                                netdev_err(priv->dev,
 
412
                                           "host_sleep_q: timer expired\n");
 
413
                                ret = -1;
 
414
                        }
 
415
                } else {
 
416
                        netdev_err(priv->dev, "host sleep: already enabled\n");
 
417
                }
 
418
        } else {
 
419
                if (priv->is_host_sleep_activated)
 
420
                        ret = lbs_host_sleep_cfg(priv, criteria,
 
421
                                        (struct wol_config *)NULL);
 
422
        }
 
423
 
 
424
        return ret;
 
425
}
 
426
 
 
427
/**
 
428
 *  lbs_set_snmp_mib - Set an SNMP MIB value
 
429
 *
 
430
 *  @priv:      A pointer to &struct lbs_private structure
 
431
 *  @oid:       The OID to set in the firmware
 
432
 *  @val:       Value to set the OID to
 
433
 *
 
434
 *  returns:            0 on success, error on failure
 
435
 */
 
436
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
 
437
{
 
438
        struct cmd_ds_802_11_snmp_mib cmd;
 
439
        int ret;
 
440
 
 
441
        lbs_deb_enter(LBS_DEB_CMD);
 
442
 
 
443
        memset(&cmd, 0, sizeof (cmd));
 
444
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
445
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
446
        cmd.oid = cpu_to_le16((u16) oid);
 
447
 
 
448
        switch (oid) {
 
449
        case SNMP_MIB_OID_BSS_TYPE:
 
450
                cmd.bufsize = cpu_to_le16(sizeof(u8));
 
451
                cmd.value[0] = val;
 
452
                break;
 
453
        case SNMP_MIB_OID_11D_ENABLE:
 
454
        case SNMP_MIB_OID_FRAG_THRESHOLD:
 
455
        case SNMP_MIB_OID_RTS_THRESHOLD:
 
456
        case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
 
457
        case SNMP_MIB_OID_LONG_RETRY_LIMIT:
 
458
                cmd.bufsize = cpu_to_le16(sizeof(u16));
 
459
                *((__le16 *)(&cmd.value)) = cpu_to_le16(val);
 
460
                break;
 
461
        default:
 
462
                lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
 
463
                ret = -EINVAL;
 
464
                goto out;
 
465
        }
 
466
 
 
467
        lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
 
468
                    le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
 
469
 
 
470
        ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
 
471
 
 
472
out:
 
473
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
474
        return ret;
 
475
}
 
476
 
 
477
/**
 
478
 *  lbs_get_snmp_mib - Get an SNMP MIB value
 
479
 *
 
480
 *  @priv:      A pointer to &struct lbs_private structure
 
481
 *  @oid:       The OID to retrieve from the firmware
 
482
 *  @out_val:   Location for the returned value
 
483
 *
 
484
 *  returns:    0 on success, error on failure
 
485
 */
 
486
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
 
487
{
 
488
        struct cmd_ds_802_11_snmp_mib cmd;
 
489
        int ret;
 
490
 
 
491
        lbs_deb_enter(LBS_DEB_CMD);
 
492
 
 
493
        memset(&cmd, 0, sizeof (cmd));
 
494
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
495
        cmd.action = cpu_to_le16(CMD_ACT_GET);
 
496
        cmd.oid = cpu_to_le16(oid);
 
497
 
 
498
        ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
 
499
        if (ret)
 
500
                goto out;
 
501
 
 
502
        switch (le16_to_cpu(cmd.bufsize)) {
 
503
        case sizeof(u8):
 
504
                *out_val = cmd.value[0];
 
505
                break;
 
506
        case sizeof(u16):
 
507
                *out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
 
508
                break;
 
509
        default:
 
510
                lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
 
511
                            oid, le16_to_cpu(cmd.bufsize));
 
512
                break;
 
513
        }
 
514
 
 
515
out:
 
516
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
517
        return ret;
 
518
}
 
519
 
 
520
/**
 
521
 *  lbs_get_tx_power - Get the min, max, and current TX power
 
522
 *
 
523
 *  @priv:      A pointer to &struct lbs_private structure
 
524
 *  @curlevel:  Current power level in dBm
 
525
 *  @minlevel:  Minimum supported power level in dBm (optional)
 
526
 *  @maxlevel:  Maximum supported power level in dBm (optional)
 
527
 *
 
528
 *  returns:    0 on success, error on failure
 
529
 */
 
530
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
 
531
                     s16 *maxlevel)
 
532
{
 
533
        struct cmd_ds_802_11_rf_tx_power cmd;
 
534
        int ret;
 
535
 
 
536
        lbs_deb_enter(LBS_DEB_CMD);
 
537
 
 
538
        memset(&cmd, 0, sizeof(cmd));
 
539
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
540
        cmd.action = cpu_to_le16(CMD_ACT_GET);
 
541
 
 
542
        ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
 
543
        if (ret == 0) {
 
544
                *curlevel = le16_to_cpu(cmd.curlevel);
 
545
                if (minlevel)
 
546
                        *minlevel = cmd.minlevel;
 
547
                if (maxlevel)
 
548
                        *maxlevel = cmd.maxlevel;
 
549
        }
 
550
 
 
551
        lbs_deb_leave(LBS_DEB_CMD);
 
552
        return ret;
 
553
}
 
554
 
 
555
/**
 
556
 *  lbs_set_tx_power - Set the TX power
 
557
 *
 
558
 *  @priv:      A pointer to &struct lbs_private structure
 
559
 *  @dbm:       The desired power level in dBm
 
560
 *
 
561
 *  returns:            0 on success, error on failure
 
562
 */
 
563
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
 
564
{
 
565
        struct cmd_ds_802_11_rf_tx_power cmd;
 
566
        int ret;
 
567
 
 
568
        lbs_deb_enter(LBS_DEB_CMD);
 
569
 
 
570
        memset(&cmd, 0, sizeof(cmd));
 
571
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
572
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
573
        cmd.curlevel = cpu_to_le16(dbm);
 
574
 
 
575
        lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
 
576
 
 
577
        ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
 
578
 
 
579
        lbs_deb_leave(LBS_DEB_CMD);
 
580
        return ret;
 
581
}
 
582
 
 
583
/**
 
584
 *  lbs_set_monitor_mode - Enable or disable monitor mode
 
585
 *  (only implemented on OLPC usb8388 FW)
 
586
 *
 
587
 *  @priv:      A pointer to &struct lbs_private structure
 
588
 *  @enable:    1 to enable monitor mode, 0 to disable
 
589
 *
 
590
 *  returns:    0 on success, error on failure
 
591
 */
 
592
int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
 
593
{
 
594
        struct cmd_ds_802_11_monitor_mode cmd;
 
595
        int ret;
 
596
 
 
597
        memset(&cmd, 0, sizeof(cmd));
 
598
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
599
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
600
        if (enable)
 
601
                cmd.mode = cpu_to_le16(0x1);
 
602
 
 
603
        lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable);
 
604
 
 
605
        ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
 
606
        if (ret == 0) {
 
607
                priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP :
 
608
                                                ARPHRD_ETHER;
 
609
        }
 
610
 
 
611
        lbs_deb_leave(LBS_DEB_CMD);
 
612
        return ret;
 
613
}
 
614
 
 
615
/**
 
616
 *  lbs_get_channel - Get the radio channel
 
617
 *
 
618
 *  @priv:      A pointer to &struct lbs_private structure
 
619
 *
 
620
 *  returns:    The channel on success, error on failure
 
621
 */
 
622
static int lbs_get_channel(struct lbs_private *priv)
 
623
{
 
624
        struct cmd_ds_802_11_rf_channel cmd;
 
625
        int ret = 0;
 
626
 
 
627
        lbs_deb_enter(LBS_DEB_CMD);
 
628
 
 
629
        memset(&cmd, 0, sizeof(cmd));
 
630
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
631
        cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
 
632
 
 
633
        ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
 
634
        if (ret)
 
635
                goto out;
 
636
 
 
637
        ret = le16_to_cpu(cmd.channel);
 
638
        lbs_deb_cmd("current radio channel is %d\n", ret);
 
639
 
 
640
out:
 
641
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
642
        return ret;
 
643
}
 
644
 
 
645
int lbs_update_channel(struct lbs_private *priv)
 
646
{
 
647
        int ret;
 
648
 
 
649
        /* the channel in f/w could be out of sync; get the current channel */
 
650
        lbs_deb_enter(LBS_DEB_ASSOC);
 
651
 
 
652
        ret = lbs_get_channel(priv);
 
653
        if (ret > 0) {
 
654
                priv->channel = ret;
 
655
                ret = 0;
 
656
        }
 
657
        lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 
658
        return ret;
 
659
}
 
660
 
 
661
/**
 
662
 *  lbs_set_channel - Set the radio channel
 
663
 *
 
664
 *  @priv:      A pointer to &struct lbs_private structure
 
665
 *  @channel:   The desired channel, or 0 to clear a locked channel
 
666
 *
 
667
 *  returns:    0 on success, error on failure
 
668
 */
 
669
int lbs_set_channel(struct lbs_private *priv, u8 channel)
 
670
{
 
671
        struct cmd_ds_802_11_rf_channel cmd;
 
672
#ifdef DEBUG
 
673
        u8 old_channel = priv->channel;
 
674
#endif
 
675
        int ret = 0;
 
676
 
 
677
        lbs_deb_enter(LBS_DEB_CMD);
 
678
 
 
679
        memset(&cmd, 0, sizeof(cmd));
 
680
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
681
        cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
 
682
        cmd.channel = cpu_to_le16(channel);
 
683
 
 
684
        ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
 
685
        if (ret)
 
686
                goto out;
 
687
 
 
688
        priv->channel = (uint8_t) le16_to_cpu(cmd.channel);
 
689
        lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
 
690
                priv->channel);
 
691
 
 
692
out:
 
693
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
694
        return ret;
 
695
}
 
696
 
 
697
/**
 
698
 * lbs_get_rssi - Get current RSSI and noise floor
 
699
 *
 
700
 * @priv:       A pointer to &struct lbs_private structure
 
701
 * @rssi:       On successful return, signal level in mBm
 
702
 * @nf:         On successful return, Noise floor
 
703
 *
 
704
 * returns:     The channel on success, error on failure
 
705
 */
 
706
int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
 
707
{
 
708
        struct cmd_ds_802_11_rssi cmd;
 
709
        int ret = 0;
 
710
 
 
711
        lbs_deb_enter(LBS_DEB_CMD);
 
712
 
 
713
        BUG_ON(rssi == NULL);
 
714
        BUG_ON(nf == NULL);
 
715
 
 
716
        memset(&cmd, 0, sizeof(cmd));
 
717
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
718
        /* Average SNR over last 8 beacons */
 
719
        cmd.n_or_snr = cpu_to_le16(8);
 
720
 
 
721
        ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
 
722
        if (ret == 0) {
 
723
                *nf = CAL_NF(le16_to_cpu(cmd.nf));
 
724
                *rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
 
725
        }
 
726
 
 
727
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
728
        return ret;
 
729
}
 
730
 
 
731
/**
 
732
 *  lbs_set_11d_domain_info - Send regulatory and 802.11d domain information
 
733
 *  to the firmware
 
734
 *
 
735
 *  @priv:      pointer to &struct lbs_private
 
736
 *  @request:   cfg80211 regulatory request structure
 
737
 *  @bands:     the device's supported bands and channels
 
738
 *
 
739
 *  returns:    0 on success, error code on failure
 
740
*/
 
741
int lbs_set_11d_domain_info(struct lbs_private *priv,
 
742
                            struct regulatory_request *request,
 
743
                            struct ieee80211_supported_band **bands)
 
744
{
 
745
        struct cmd_ds_802_11d_domain_info cmd;
 
746
        struct mrvl_ie_domain_param_set *domain = &cmd.domain;
 
747
        struct ieee80211_country_ie_triplet *t;
 
748
        enum ieee80211_band band;
 
749
        struct ieee80211_channel *ch;
 
750
        u8 num_triplet = 0;
 
751
        u8 num_parsed_chan = 0;
 
752
        u8 first_channel = 0, next_chan = 0, max_pwr = 0;
 
753
        u8 i, flag = 0;
 
754
        size_t triplet_size;
 
755
        int ret;
 
756
 
 
757
        lbs_deb_enter(LBS_DEB_11D);
 
758
 
 
759
        memset(&cmd, 0, sizeof(cmd));
 
760
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
761
 
 
762
        lbs_deb_11d("Setting country code '%c%c'\n",
 
763
                    request->alpha2[0], request->alpha2[1]);
 
764
 
 
765
        domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
 
766
 
 
767
        /* Set country code */
 
768
        domain->country_code[0] = request->alpha2[0];
 
769
        domain->country_code[1] = request->alpha2[1];
 
770
        domain->country_code[2] = ' ';
 
771
 
 
772
        /* Now set up the channel triplets; firmware is somewhat picky here
 
773
         * and doesn't validate channel numbers and spans; hence it would
 
774
         * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39.  Since
 
775
         * the last 3 aren't valid channels, the driver is responsible for
 
776
         * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20)
 
777
         * etc.
 
778
         */
 
779
        for (band = 0;
 
780
             (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS);
 
781
             band++) {
 
782
 
 
783
                if (!bands[band])
 
784
                        continue;
 
785
 
 
786
                for (i = 0;
 
787
                     (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS);
 
788
                     i++) {
 
789
                        ch = &bands[band]->channels[i];
 
790
                        if (ch->flags & IEEE80211_CHAN_DISABLED)
 
791
                                continue;
 
792
 
 
793
                        if (!flag) {
 
794
                                flag = 1;
 
795
                                next_chan = first_channel = (u32) ch->hw_value;
 
796
                                max_pwr = ch->max_power;
 
797
                                num_parsed_chan = 1;
 
798
                                continue;
 
799
                        }
 
800
 
 
801
                        if ((ch->hw_value == next_chan + 1) &&
 
802
                                        (ch->max_power == max_pwr)) {
 
803
                                /* Consolidate adjacent channels */
 
804
                                next_chan++;
 
805
                                num_parsed_chan++;
 
806
                        } else {
 
807
                                /* Add this triplet */
 
808
                                lbs_deb_11d("11D triplet (%d, %d, %d)\n",
 
809
                                        first_channel, num_parsed_chan,
 
810
                                        max_pwr);
 
811
                                t = &domain->triplet[num_triplet];
 
812
                                t->chans.first_channel = first_channel;
 
813
                                t->chans.num_channels = num_parsed_chan;
 
814
                                t->chans.max_power = max_pwr;
 
815
                                num_triplet++;
 
816
                                flag = 0;
 
817
                        }
 
818
                }
 
819
 
 
820
                if (flag) {
 
821
                        /* Add last triplet */
 
822
                        lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel,
 
823
                                num_parsed_chan, max_pwr);
 
824
                        t = &domain->triplet[num_triplet];
 
825
                        t->chans.first_channel = first_channel;
 
826
                        t->chans.num_channels = num_parsed_chan;
 
827
                        t->chans.max_power = max_pwr;
 
828
                        num_triplet++;
 
829
                }
 
830
        }
 
831
 
 
832
        lbs_deb_11d("# triplets %d\n", num_triplet);
 
833
 
 
834
        /* Set command header sizes */
 
835
        triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet);
 
836
        domain->header.len = cpu_to_le16(sizeof(domain->country_code) +
 
837
                                        triplet_size);
 
838
 
 
839
        lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set",
 
840
                        (u8 *) &cmd.domain.country_code,
 
841
                        le16_to_cpu(domain->header.len));
 
842
 
 
843
        cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) +
 
844
                                   sizeof(cmd.action) +
 
845
                                   sizeof(cmd.domain.header) +
 
846
                                   sizeof(cmd.domain.country_code) +
 
847
                                   triplet_size);
 
848
 
 
849
        ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
 
850
 
 
851
        lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
 
852
        return ret;
 
853
}
 
854
 
 
855
/**
 
856
 *  lbs_get_reg - Read a MAC, Baseband, or RF register
 
857
 *
 
858
 *  @priv:      pointer to &struct lbs_private
 
859
 *  @reg:       register command, one of CMD_MAC_REG_ACCESS,
 
860
 *              CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
 
861
 *  @offset:    byte offset of the register to get
 
862
 *  @value:     on success, the value of the register at 'offset'
 
863
 *
 
864
 *  returns:    0 on success, error code on failure
 
865
*/
 
866
int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
 
867
{
 
868
        struct cmd_ds_reg_access cmd;
 
869
        int ret = 0;
 
870
 
 
871
        lbs_deb_enter(LBS_DEB_CMD);
 
872
 
 
873
        BUG_ON(value == NULL);
 
874
 
 
875
        memset(&cmd, 0, sizeof(cmd));
 
876
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
877
        cmd.action = cpu_to_le16(CMD_ACT_GET);
 
878
        cmd.offset = cpu_to_le16(offset);
 
879
 
 
880
        if (reg != CMD_MAC_REG_ACCESS &&
 
881
            reg != CMD_BBP_REG_ACCESS &&
 
882
            reg != CMD_RF_REG_ACCESS) {
 
883
                ret = -EINVAL;
 
884
                goto out;
 
885
        }
 
886
 
 
887
        ret = lbs_cmd_with_response(priv, reg, &cmd);
 
888
        if (!ret) {
 
889
                if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
 
890
                        *value = cmd.value.bbp_rf;
 
891
                else if (reg == CMD_MAC_REG_ACCESS)
 
892
                        *value = le32_to_cpu(cmd.value.mac);
 
893
        }
 
894
 
 
895
out:
 
896
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
897
        return ret;
 
898
}
 
899
 
 
900
/**
 
901
 *  lbs_set_reg - Write a MAC, Baseband, or RF register
 
902
 *
 
903
 *  @priv:      pointer to &struct lbs_private
 
904
 *  @reg:       register command, one of CMD_MAC_REG_ACCESS,
 
905
 *              CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
 
906
 *  @offset:    byte offset of the register to set
 
907
 *  @value:     the value to write to the register at 'offset'
 
908
 *
 
909
 *  returns:    0 on success, error code on failure
 
910
*/
 
911
int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
 
912
{
 
913
        struct cmd_ds_reg_access cmd;
 
914
        int ret = 0;
 
915
 
 
916
        lbs_deb_enter(LBS_DEB_CMD);
 
917
 
 
918
        memset(&cmd, 0, sizeof(cmd));
 
919
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
920
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
921
        cmd.offset = cpu_to_le16(offset);
 
922
 
 
923
        if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
 
924
                cmd.value.bbp_rf = (u8) (value & 0xFF);
 
925
        else if (reg == CMD_MAC_REG_ACCESS)
 
926
                cmd.value.mac = cpu_to_le32(value);
 
927
        else {
 
928
                ret = -EINVAL;
 
929
                goto out;
 
930
        }
 
931
 
 
932
        ret = lbs_cmd_with_response(priv, reg, &cmd);
 
933
 
 
934
out:
 
935
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
936
        return ret;
 
937
}
 
938
 
 
939
static void lbs_queue_cmd(struct lbs_private *priv,
 
940
                          struct cmd_ctrl_node *cmdnode)
 
941
{
 
942
        unsigned long flags;
 
943
        int addtail = 1;
 
944
 
 
945
        lbs_deb_enter(LBS_DEB_HOST);
 
946
 
 
947
        if (!cmdnode) {
 
948
                lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
 
949
                goto done;
 
950
        }
 
951
        if (!cmdnode->cmdbuf->size) {
 
952
                lbs_deb_host("DNLD_CMD: cmd size is zero\n");
 
953
                goto done;
 
954
        }
 
955
        cmdnode->result = 0;
 
956
 
 
957
        /* Exit_PS command needs to be queued in the header always. */
 
958
        if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
 
959
                struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf;
 
960
 
 
961
                if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 
962
                        if (priv->psstate != PS_STATE_FULL_POWER)
 
963
                                addtail = 0;
 
964
                }
 
965
        }
 
966
 
 
967
        if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM)
 
968
                addtail = 0;
 
969
 
 
970
        spin_lock_irqsave(&priv->driver_lock, flags);
 
971
 
 
972
        if (addtail)
 
973
                list_add_tail(&cmdnode->list, &priv->cmdpendingq);
 
974
        else
 
975
                list_add(&cmdnode->list, &priv->cmdpendingq);
 
976
 
 
977
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
978
 
 
979
        lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
 
980
                     le16_to_cpu(cmdnode->cmdbuf->command));
 
981
 
 
982
done:
 
983
        lbs_deb_leave(LBS_DEB_HOST);
 
984
}
 
985
 
 
986
static void lbs_submit_command(struct lbs_private *priv,
 
987
                               struct cmd_ctrl_node *cmdnode)
 
988
{
 
989
        unsigned long flags;
 
990
        struct cmd_header *cmd;
 
991
        uint16_t cmdsize;
 
992
        uint16_t command;
 
993
        int timeo = 3 * HZ;
 
994
        int ret;
 
995
 
 
996
        lbs_deb_enter(LBS_DEB_HOST);
 
997
 
 
998
        cmd = cmdnode->cmdbuf;
 
999
 
 
1000
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1001
        priv->seqnum++;
 
1002
        cmd->seqnum = cpu_to_le16(priv->seqnum);
 
1003
        priv->cur_cmd = cmdnode;
 
1004
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1005
 
 
1006
        cmdsize = le16_to_cpu(cmd->size);
 
1007
        command = le16_to_cpu(cmd->command);
 
1008
 
 
1009
        /* These commands take longer */
 
1010
        if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE)
 
1011
                timeo = 5 * HZ;
 
1012
 
 
1013
        lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
 
1014
                     command, le16_to_cpu(cmd->seqnum), cmdsize);
 
1015
        lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
 
1016
 
 
1017
        ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
 
1018
 
 
1019
        if (ret) {
 
1020
                netdev_info(priv->dev, "DNLD_CMD: hw_host_to_card failed: %d\n",
 
1021
                            ret);
 
1022
                /* Let the timer kick in and retry, and potentially reset
 
1023
                   the whole thing if the condition persists */
 
1024
                timeo = HZ/4;
 
1025
        }
 
1026
 
 
1027
        if (command == CMD_802_11_DEEP_SLEEP) {
 
1028
                if (priv->is_auto_deep_sleep_enabled) {
 
1029
                        priv->wakeup_dev_required = 1;
 
1030
                        priv->dnld_sent = 0;
 
1031
                }
 
1032
                priv->is_deep_sleep = 1;
 
1033
                lbs_complete_command(priv, cmdnode, 0);
 
1034
        } else {
 
1035
                /* Setup the timer after transmit command */
 
1036
                mod_timer(&priv->command_timer, jiffies + timeo);
 
1037
        }
 
1038
 
 
1039
        lbs_deb_leave(LBS_DEB_HOST);
 
1040
}
 
1041
 
 
1042
/*
 
1043
 *  This function inserts command node to cmdfreeq
 
1044
 *  after cleans it. Requires priv->driver_lock held.
 
1045
 */
 
1046
static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
 
1047
                                         struct cmd_ctrl_node *cmdnode)
 
1048
{
 
1049
        lbs_deb_enter(LBS_DEB_HOST);
 
1050
 
 
1051
        if (!cmdnode)
 
1052
                goto out;
 
1053
 
 
1054
        cmdnode->callback = NULL;
 
1055
        cmdnode->callback_arg = 0;
 
1056
 
 
1057
        memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
 
1058
 
 
1059
        list_add_tail(&cmdnode->list, &priv->cmdfreeq);
 
1060
 out:
 
1061
        lbs_deb_leave(LBS_DEB_HOST);
 
1062
}
 
1063
 
 
1064
static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
 
1065
        struct cmd_ctrl_node *ptempcmd)
 
1066
{
 
1067
        unsigned long flags;
 
1068
 
 
1069
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1070
        __lbs_cleanup_and_insert_cmd(priv, ptempcmd);
 
1071
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1072
}
 
1073
 
 
1074
void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
 
1075
                            int result)
 
1076
{
 
1077
        /*
 
1078
         * Normally, commands are removed from cmdpendingq before being
 
1079
         * submitted. However, we can arrive here on alternative codepaths
 
1080
         * where the command is still pending. Make sure the command really
 
1081
         * isn't part of a list at this point.
 
1082
         */
 
1083
        list_del_init(&cmd->list);
 
1084
 
 
1085
        cmd->result = result;
 
1086
        cmd->cmdwaitqwoken = 1;
 
1087
        wake_up(&cmd->cmdwait_q);
 
1088
 
 
1089
        if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
 
1090
                __lbs_cleanup_and_insert_cmd(priv, cmd);
 
1091
        priv->cur_cmd = NULL;
 
1092
        wake_up(&priv->waitq);
 
1093
}
 
1094
 
 
1095
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
 
1096
                          int result)
 
1097
{
 
1098
        unsigned long flags;
 
1099
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1100
        __lbs_complete_command(priv, cmd, result);
 
1101
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1102
}
 
1103
 
 
1104
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
 
1105
{
 
1106
        struct cmd_ds_802_11_radio_control cmd;
 
1107
        int ret = -EINVAL;
 
1108
 
 
1109
        lbs_deb_enter(LBS_DEB_CMD);
 
1110
 
 
1111
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
1112
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
1113
 
 
1114
        /* Only v8 and below support setting the preamble */
 
1115
        if (priv->fwrelease < 0x09000000) {
 
1116
                switch (preamble) {
 
1117
                case RADIO_PREAMBLE_SHORT:
 
1118
                case RADIO_PREAMBLE_AUTO:
 
1119
                case RADIO_PREAMBLE_LONG:
 
1120
                        cmd.control = cpu_to_le16(preamble);
 
1121
                        break;
 
1122
                default:
 
1123
                        goto out;
 
1124
                }
 
1125
        }
 
1126
 
 
1127
        if (radio_on)
 
1128
                cmd.control |= cpu_to_le16(0x1);
 
1129
        else {
 
1130
                cmd.control &= cpu_to_le16(~0x1);
 
1131
                priv->txpower_cur = 0;
 
1132
        }
 
1133
 
 
1134
        lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
 
1135
                    radio_on ? "ON" : "OFF", preamble);
 
1136
 
 
1137
        priv->radio_on = radio_on;
 
1138
 
 
1139
        ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
 
1140
 
 
1141
out:
 
1142
        lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 
1143
        return ret;
 
1144
}
 
1145
 
 
1146
void lbs_set_mac_control(struct lbs_private *priv)
 
1147
{
 
1148
        struct cmd_ds_mac_control cmd;
 
1149
 
 
1150
        lbs_deb_enter(LBS_DEB_CMD);
 
1151
 
 
1152
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
1153
        cmd.action = cpu_to_le16(priv->mac_control);
 
1154
        cmd.reserved = 0;
 
1155
 
 
1156
        lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
 
1157
 
 
1158
        lbs_deb_leave(LBS_DEB_CMD);
 
1159
}
 
1160
 
 
1161
/**
 
1162
 *  lbs_allocate_cmd_buffer - allocates the command buffer and links
 
1163
 *  it to command free queue
 
1164
 *
 
1165
 *  @priv:      A pointer to &struct lbs_private structure
 
1166
 *
 
1167
 *  returns:    0 for success or -1 on error
 
1168
 */
 
1169
int lbs_allocate_cmd_buffer(struct lbs_private *priv)
 
1170
{
 
1171
        int ret = 0;
 
1172
        u32 bufsize;
 
1173
        u32 i;
 
1174
        struct cmd_ctrl_node *cmdarray;
 
1175
 
 
1176
        lbs_deb_enter(LBS_DEB_HOST);
 
1177
 
 
1178
        /* Allocate and initialize the command array */
 
1179
        bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
 
1180
        if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
 
1181
                lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
 
1182
                ret = -1;
 
1183
                goto done;
 
1184
        }
 
1185
        priv->cmd_array = cmdarray;
 
1186
 
 
1187
        /* Allocate and initialize each command buffer in the command array */
 
1188
        for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 
1189
                cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
 
1190
                if (!cmdarray[i].cmdbuf) {
 
1191
                        lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
 
1192
                        ret = -1;
 
1193
                        goto done;
 
1194
                }
 
1195
        }
 
1196
 
 
1197
        for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 
1198
                init_waitqueue_head(&cmdarray[i].cmdwait_q);
 
1199
                lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
 
1200
        }
 
1201
        ret = 0;
 
1202
 
 
1203
done:
 
1204
        lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
 
1205
        return ret;
 
1206
}
 
1207
 
 
1208
/**
 
1209
 *  lbs_free_cmd_buffer - free the command buffer
 
1210
 *
 
1211
 *  @priv:      A pointer to &struct lbs_private structure
 
1212
 *
 
1213
 *  returns:    0 for success
 
1214
 */
 
1215
int lbs_free_cmd_buffer(struct lbs_private *priv)
 
1216
{
 
1217
        struct cmd_ctrl_node *cmdarray;
 
1218
        unsigned int i;
 
1219
 
 
1220
        lbs_deb_enter(LBS_DEB_HOST);
 
1221
 
 
1222
        /* need to check if cmd array is allocated or not */
 
1223
        if (priv->cmd_array == NULL) {
 
1224
                lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
 
1225
                goto done;
 
1226
        }
 
1227
 
 
1228
        cmdarray = priv->cmd_array;
 
1229
 
 
1230
        /* Release shared memory buffers */
 
1231
        for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 
1232
                if (cmdarray[i].cmdbuf) {
 
1233
                        kfree(cmdarray[i].cmdbuf);
 
1234
                        cmdarray[i].cmdbuf = NULL;
 
1235
                }
 
1236
        }
 
1237
 
 
1238
        /* Release cmd_ctrl_node */
 
1239
        if (priv->cmd_array) {
 
1240
                kfree(priv->cmd_array);
 
1241
                priv->cmd_array = NULL;
 
1242
        }
 
1243
 
 
1244
done:
 
1245
        lbs_deb_leave(LBS_DEB_HOST);
 
1246
        return 0;
 
1247
}
 
1248
 
 
1249
/**
 
1250
 *  lbs_get_free_cmd_node - gets a free command node if available in
 
1251
 *  command free queue
 
1252
 *
 
1253
 *  @priv:      A pointer to &struct lbs_private structure
 
1254
 *
 
1255
 *  returns:    A pointer to &cmd_ctrl_node structure on success
 
1256
 *              or %NULL on error
 
1257
 */
 
1258
static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
 
1259
{
 
1260
        struct cmd_ctrl_node *tempnode;
 
1261
        unsigned long flags;
 
1262
 
 
1263
        lbs_deb_enter(LBS_DEB_HOST);
 
1264
 
 
1265
        if (!priv)
 
1266
                return NULL;
 
1267
 
 
1268
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1269
 
 
1270
        if (!list_empty(&priv->cmdfreeq)) {
 
1271
                tempnode = list_first_entry(&priv->cmdfreeq,
 
1272
                                            struct cmd_ctrl_node, list);
 
1273
                list_del_init(&tempnode->list);
 
1274
        } else {
 
1275
                lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
 
1276
                tempnode = NULL;
 
1277
        }
 
1278
 
 
1279
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1280
 
 
1281
        lbs_deb_leave(LBS_DEB_HOST);
 
1282
        return tempnode;
 
1283
}
 
1284
 
 
1285
/**
 
1286
 *  lbs_execute_next_command - execute next command in command
 
1287
 *  pending queue. Will put firmware back to PS mode if applicable.
 
1288
 *
 
1289
 *  @priv:      A pointer to &struct lbs_private structure
 
1290
 *
 
1291
 *  returns:    0 on success or -1 on error
 
1292
 */
 
1293
int lbs_execute_next_command(struct lbs_private *priv)
 
1294
{
 
1295
        struct cmd_ctrl_node *cmdnode = NULL;
 
1296
        struct cmd_header *cmd;
 
1297
        unsigned long flags;
 
1298
        int ret = 0;
 
1299
 
 
1300
        /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
 
1301
         * only caller to us is lbs_thread() and we get even when a
 
1302
         * data packet is received */
 
1303
        lbs_deb_enter(LBS_DEB_THREAD);
 
1304
 
 
1305
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1306
 
 
1307
        if (priv->cur_cmd) {
 
1308
                netdev_alert(priv->dev,
 
1309
                             "EXEC_NEXT_CMD: already processing command!\n");
 
1310
                spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1311
                ret = -1;
 
1312
                goto done;
 
1313
        }
 
1314
 
 
1315
        if (!list_empty(&priv->cmdpendingq)) {
 
1316
                cmdnode = list_first_entry(&priv->cmdpendingq,
 
1317
                                           struct cmd_ctrl_node, list);
 
1318
        }
 
1319
 
 
1320
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1321
 
 
1322
        if (cmdnode) {
 
1323
                cmd = cmdnode->cmdbuf;
 
1324
 
 
1325
                if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
 
1326
                        if ((priv->psstate == PS_STATE_SLEEP) ||
 
1327
                            (priv->psstate == PS_STATE_PRE_SLEEP)) {
 
1328
                                lbs_deb_host(
 
1329
                                       "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
 
1330
                                       le16_to_cpu(cmd->command),
 
1331
                                       priv->psstate);
 
1332
                                ret = -1;
 
1333
                                goto done;
 
1334
                        }
 
1335
                        lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
 
1336
                                     "0x%04x in psstate %d\n",
 
1337
                                     le16_to_cpu(cmd->command), priv->psstate);
 
1338
                } else if (priv->psstate != PS_STATE_FULL_POWER) {
 
1339
                        /*
 
1340
                         * 1. Non-PS command:
 
1341
                         * Queue it. set needtowakeup to TRUE if current state
 
1342
                         * is SLEEP, otherwise call send EXIT_PS.
 
1343
                         * 2. PS command but not EXIT_PS:
 
1344
                         * Ignore it.
 
1345
                         * 3. PS command EXIT_PS:
 
1346
                         * Set needtowakeup to TRUE if current state is SLEEP,
 
1347
                         * otherwise send this command down to firmware
 
1348
                         * immediately.
 
1349
                         */
 
1350
                        if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) {
 
1351
                                /*  Prepare to send Exit PS,
 
1352
                                 *  this non PS command will be sent later */
 
1353
                                if ((priv->psstate == PS_STATE_SLEEP)
 
1354
                                    || (priv->psstate == PS_STATE_PRE_SLEEP)
 
1355
                                    ) {
 
1356
                                        /* w/ new scheme, it will not reach here.
 
1357
                                           since it is blocked in main_thread. */
 
1358
                                        priv->needtowakeup = 1;
 
1359
                                } else {
 
1360
                                        lbs_set_ps_mode(priv,
 
1361
                                                        PS_MODE_ACTION_EXIT_PS,
 
1362
                                                        false);
 
1363
                                }
 
1364
 
 
1365
                                ret = 0;
 
1366
                                goto done;
 
1367
                        } else {
 
1368
                                /*
 
1369
                                 * PS command. Ignore it if it is not Exit_PS.
 
1370
                                 * otherwise send it down immediately.
 
1371
                                 */
 
1372
                                struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1];
 
1373
 
 
1374
                                lbs_deb_host(
 
1375
                                       "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
 
1376
                                       psm->action);
 
1377
                                if (psm->action !=
 
1378
                                    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 
1379
                                        lbs_deb_host(
 
1380
                                               "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
 
1381
                                        lbs_complete_command(priv, cmdnode, 0);
 
1382
 
 
1383
                                        ret = 0;
 
1384
                                        goto done;
 
1385
                                }
 
1386
 
 
1387
                                if ((priv->psstate == PS_STATE_SLEEP) ||
 
1388
                                    (priv->psstate == PS_STATE_PRE_SLEEP)) {
 
1389
                                        lbs_deb_host(
 
1390
                                               "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
 
1391
                                        lbs_complete_command(priv, cmdnode, 0);
 
1392
                                        priv->needtowakeup = 1;
 
1393
 
 
1394
                                        ret = 0;
 
1395
                                        goto done;
 
1396
                                }
 
1397
 
 
1398
                                lbs_deb_host(
 
1399
                                       "EXEC_NEXT_CMD: sending EXIT_PS\n");
 
1400
                        }
 
1401
                }
 
1402
                spin_lock_irqsave(&priv->driver_lock, flags);
 
1403
                list_del_init(&cmdnode->list);
 
1404
                spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1405
                lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
 
1406
                            le16_to_cpu(cmd->command));
 
1407
                lbs_submit_command(priv, cmdnode);
 
1408
        } else {
 
1409
                /*
 
1410
                 * check if in power save mode, if yes, put the device back
 
1411
                 * to PS mode
 
1412
                 */
 
1413
#ifdef TODO
 
1414
                /*
 
1415
                 * This was the old code for libertas+wext. Someone that
 
1416
                 * understands this beast should re-code it in a sane way.
 
1417
                 *
 
1418
                 * I actually don't understand why this is related to WPA
 
1419
                 * and to connection status, shouldn't powering should be
 
1420
                 * independ of such things?
 
1421
                 */
 
1422
                if ((priv->psmode != LBS802_11POWERMODECAM) &&
 
1423
                    (priv->psstate == PS_STATE_FULL_POWER) &&
 
1424
                    ((priv->connect_status == LBS_CONNECTED) ||
 
1425
                    lbs_mesh_connected(priv))) {
 
1426
                        if (priv->secinfo.WPAenabled ||
 
1427
                            priv->secinfo.WPA2enabled) {
 
1428
                                /* check for valid WPA group keys */
 
1429
                                if (priv->wpa_mcast_key.len ||
 
1430
                                    priv->wpa_unicast_key.len) {
 
1431
                                        lbs_deb_host(
 
1432
                                               "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
 
1433
                                               " go back to PS_SLEEP");
 
1434
                                        lbs_set_ps_mode(priv,
 
1435
                                                        PS_MODE_ACTION_ENTER_PS,
 
1436
                                                        false);
 
1437
                                }
 
1438
                        } else {
 
1439
                                lbs_deb_host(
 
1440
                                       "EXEC_NEXT_CMD: cmdpendingq empty, "
 
1441
                                       "go back to PS_SLEEP");
 
1442
                                lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS,
 
1443
                                                false);
 
1444
                        }
 
1445
                }
 
1446
#endif
 
1447
        }
 
1448
 
 
1449
        ret = 0;
 
1450
done:
 
1451
        lbs_deb_leave(LBS_DEB_THREAD);
 
1452
        return ret;
 
1453
}
 
1454
 
 
1455
static void lbs_send_confirmsleep(struct lbs_private *priv)
 
1456
{
 
1457
        unsigned long flags;
 
1458
        int ret;
 
1459
 
 
1460
        lbs_deb_enter(LBS_DEB_HOST);
 
1461
        lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
 
1462
                sizeof(confirm_sleep));
 
1463
 
 
1464
        ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
 
1465
                sizeof(confirm_sleep));
 
1466
        if (ret) {
 
1467
                netdev_alert(priv->dev, "confirm_sleep failed\n");
 
1468
                goto out;
 
1469
        }
 
1470
 
 
1471
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1472
 
 
1473
        /* We don't get a response on the sleep-confirmation */
 
1474
        priv->dnld_sent = DNLD_RES_RECEIVED;
 
1475
 
 
1476
        if (priv->is_host_sleep_configured) {
 
1477
                priv->is_host_sleep_activated = 1;
 
1478
                wake_up_interruptible(&priv->host_sleep_q);
 
1479
        }
 
1480
 
 
1481
        /* If nothing to do, go back to sleep (?) */
 
1482
        if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
 
1483
                priv->psstate = PS_STATE_SLEEP;
 
1484
 
 
1485
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1486
 
 
1487
out:
 
1488
        lbs_deb_leave(LBS_DEB_HOST);
 
1489
}
 
1490
 
 
1491
/**
 
1492
 * lbs_ps_confirm_sleep - checks condition and prepares to
 
1493
 * send sleep confirm command to firmware if ok
 
1494
 *
 
1495
 * @priv:       A pointer to &struct lbs_private structure
 
1496
 *
 
1497
 * returns:     n/a
 
1498
 */
 
1499
void lbs_ps_confirm_sleep(struct lbs_private *priv)
 
1500
{
 
1501
        unsigned long flags =0;
 
1502
        int allowed = 1;
 
1503
 
 
1504
        lbs_deb_enter(LBS_DEB_HOST);
 
1505
 
 
1506
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1507
        if (priv->dnld_sent) {
 
1508
                allowed = 0;
 
1509
                lbs_deb_host("dnld_sent was set\n");
 
1510
        }
 
1511
 
 
1512
        /* In-progress command? */
 
1513
        if (priv->cur_cmd) {
 
1514
                allowed = 0;
 
1515
                lbs_deb_host("cur_cmd was set\n");
 
1516
        }
 
1517
 
 
1518
        /* Pending events or command responses? */
 
1519
        if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
 
1520
                allowed = 0;
 
1521
                lbs_deb_host("pending events or command responses\n");
 
1522
        }
 
1523
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1524
 
 
1525
        if (allowed) {
 
1526
                lbs_deb_host("sending lbs_ps_confirm_sleep\n");
 
1527
                lbs_send_confirmsleep(priv);
 
1528
        } else {
 
1529
                lbs_deb_host("sleep confirm has been delayed\n");
 
1530
        }
 
1531
 
 
1532
        lbs_deb_leave(LBS_DEB_HOST);
 
1533
}
 
1534
 
 
1535
 
 
1536
/**
 
1537
 * lbs_set_tpc_cfg - Configures the transmission power control functionality
 
1538
 *
 
1539
 * @priv:       A pointer to &struct lbs_private structure
 
1540
 * @enable:     Transmission power control enable
 
1541
 * @p0:         Power level when link quality is good (dBm).
 
1542
 * @p1:         Power level when link quality is fair (dBm).
 
1543
 * @p2:         Power level when link quality is poor (dBm).
 
1544
 * @usesnr:     Use Signal to Noise Ratio in TPC
 
1545
 *
 
1546
 * returns:     0 on success
 
1547
 */
 
1548
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
 
1549
                int8_t p2, int usesnr)
 
1550
{
 
1551
        struct cmd_ds_802_11_tpc_cfg cmd;
 
1552
        int ret;
 
1553
 
 
1554
        memset(&cmd, 0, sizeof(cmd));
 
1555
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
1556
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
1557
        cmd.enable = !!enable;
 
1558
        cmd.usesnr = !!usesnr;
 
1559
        cmd.P0 = p0;
 
1560
        cmd.P1 = p1;
 
1561
        cmd.P2 = p2;
 
1562
 
 
1563
        ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);
 
1564
 
 
1565
        return ret;
 
1566
}
 
1567
 
 
1568
/**
 
1569
 * lbs_set_power_adapt_cfg - Configures the power adaptation settings
 
1570
 *
 
1571
 * @priv:       A pointer to &struct lbs_private structure
 
1572
 * @enable:     Power adaptation enable
 
1573
 * @p0:         Power level for 1, 2, 5.5 and 11 Mbps (dBm).
 
1574
 * @p1:         Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
 
1575
 * @p2:         Power level for 48 and 54 Mbps (dBm).
 
1576
 *
 
1577
 * returns:     0 on Success
 
1578
 */
 
1579
 
 
1580
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
 
1581
                int8_t p1, int8_t p2)
 
1582
{
 
1583
        struct cmd_ds_802_11_pa_cfg cmd;
 
1584
        int ret;
 
1585
 
 
1586
        memset(&cmd, 0, sizeof(cmd));
 
1587
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 
1588
        cmd.action = cpu_to_le16(CMD_ACT_SET);
 
1589
        cmd.enable = !!enable;
 
1590
        cmd.P0 = p0;
 
1591
        cmd.P1 = p1;
 
1592
        cmd.P2 = p2;
 
1593
 
 
1594
        ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);
 
1595
 
 
1596
        return ret;
 
1597
}
 
1598
 
 
1599
 
 
1600
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
 
1601
        uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
 
1602
        int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
 
1603
        unsigned long callback_arg)
 
1604
{
 
1605
        struct cmd_ctrl_node *cmdnode;
 
1606
 
 
1607
        lbs_deb_enter(LBS_DEB_HOST);
 
1608
 
 
1609
        if (priv->surpriseremoved) {
 
1610
                lbs_deb_host("PREP_CMD: card removed\n");
 
1611
                cmdnode = ERR_PTR(-ENOENT);
 
1612
                goto done;
 
1613
        }
 
1614
 
 
1615
        /* No commands are allowed in Deep Sleep until we toggle the GPIO
 
1616
         * to wake up the card and it has signaled that it's ready.
 
1617
         */
 
1618
        if (!priv->is_auto_deep_sleep_enabled) {
 
1619
                if (priv->is_deep_sleep) {
 
1620
                        lbs_deb_cmd("command not allowed in deep sleep\n");
 
1621
                        cmdnode = ERR_PTR(-EBUSY);
 
1622
                        goto done;
 
1623
                }
 
1624
        }
 
1625
 
 
1626
        cmdnode = lbs_get_free_cmd_node(priv);
 
1627
        if (cmdnode == NULL) {
 
1628
                lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
 
1629
 
 
1630
                /* Wake up main thread to execute next command */
 
1631
                wake_up(&priv->waitq);
 
1632
                cmdnode = ERR_PTR(-ENOBUFS);
 
1633
                goto done;
 
1634
        }
 
1635
 
 
1636
        cmdnode->callback = callback;
 
1637
        cmdnode->callback_arg = callback_arg;
 
1638
 
 
1639
        /* Copy the incoming command to the buffer */
 
1640
        memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
 
1641
 
 
1642
        /* Set command, clean result, move to buffer */
 
1643
        cmdnode->cmdbuf->command = cpu_to_le16(command);
 
1644
        cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
 
1645
        cmdnode->cmdbuf->result  = 0;
 
1646
 
 
1647
        lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
 
1648
 
 
1649
        cmdnode->cmdwaitqwoken = 0;
 
1650
        lbs_queue_cmd(priv, cmdnode);
 
1651
        wake_up(&priv->waitq);
 
1652
 
 
1653
 done:
 
1654
        lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
 
1655
        return cmdnode;
 
1656
}
 
1657
 
 
1658
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
 
1659
        struct cmd_header *in_cmd, int in_cmd_size)
 
1660
{
 
1661
        lbs_deb_enter(LBS_DEB_CMD);
 
1662
        __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
 
1663
                lbs_cmd_async_callback, 0);
 
1664
        lbs_deb_leave(LBS_DEB_CMD);
 
1665
}
 
1666
 
 
1667
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
 
1668
              struct cmd_header *in_cmd, int in_cmd_size,
 
1669
              int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
 
1670
              unsigned long callback_arg)
 
1671
{
 
1672
        struct cmd_ctrl_node *cmdnode;
 
1673
        unsigned long flags;
 
1674
        int ret = 0;
 
1675
 
 
1676
        lbs_deb_enter(LBS_DEB_HOST);
 
1677
 
 
1678
        cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
 
1679
                                  callback, callback_arg);
 
1680
        if (IS_ERR(cmdnode)) {
 
1681
                ret = PTR_ERR(cmdnode);
 
1682
                goto done;
 
1683
        }
 
1684
 
 
1685
        might_sleep();
 
1686
 
 
1687
        /*
 
1688
         * Be careful with signals here. A signal may be received as the system
 
1689
         * goes into suspend or resume. We do not want this to interrupt the
 
1690
         * command, so we perform an uninterruptible sleep.
 
1691
         */
 
1692
        wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
 
1693
 
 
1694
        spin_lock_irqsave(&priv->driver_lock, flags);
 
1695
        ret = cmdnode->result;
 
1696
        if (ret)
 
1697
                netdev_info(priv->dev, "PREP_CMD: command 0x%04x failed: %d\n",
 
1698
                            command, ret);
 
1699
 
 
1700
        __lbs_cleanup_and_insert_cmd(priv, cmdnode);
 
1701
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
1702
 
 
1703
done:
 
1704
        lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
 
1705
        return ret;
 
1706
}
 
1707
EXPORT_SYMBOL_GPL(__lbs_cmd);