2 * This file is part of wl1271
4 * Copyright (C) 2009 Nokia Corporation
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 #include <linux/module.h>
25 #include <linux/platform_device.h>
26 #include <linux/crc7.h>
27 #include <linux/spi/spi.h>
28 #include <linux/etherdevice.h>
31 #include "wl1271_reg.h"
32 #include "wl1271_spi.h"
33 #include "wl1271_acx.h"
34 #include "wl12xx_80211.h"
35 #include "wl1271_cmd.h"
38 * send command to firmware
42 * @buf: buffer containing the command, must work with dma
43 * @len: length of the buffer
45 int wl1271_cmd_send(struct wl1271
*wl
, u16 id
, void *buf
, size_t len
)
47 struct wl1271_cmd_header
*cmd
;
48 unsigned long timeout
;
56 WARN_ON(len
% 4 != 0);
58 wl1271_spi_write(wl
, wl
->cmd_box_addr
, buf
, len
, false);
60 wl1271_spi_write32(wl
, ACX_REG_INTERRUPT_TRIG
, INTR_TRIG_CMD
);
62 timeout
= jiffies
+ msecs_to_jiffies(WL1271_COMMAND_TIMEOUT
);
64 intr
= wl1271_spi_read32(wl
, ACX_REG_INTERRUPT_NO_CLEAR
);
65 while (!(intr
& WL1271_ACX_INTR_CMD_COMPLETE
)) {
66 if (time_after(jiffies
, timeout
)) {
67 wl1271_error("command complete timeout");
74 intr
= wl1271_spi_read32(wl
, ACX_REG_INTERRUPT_NO_CLEAR
);
77 wl1271_spi_write32(wl
, ACX_REG_INTERRUPT_ACK
,
78 WL1271_ACX_INTR_CMD_COMPLETE
);
84 int wl1271_cmd_cal_channel_tune(struct wl1271
*wl
)
86 struct wl1271_cmd_cal_channel_tune
*cmd
;
89 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
93 cmd
->test
.id
= TEST_CMD_CHANNEL_TUNE
;
95 cmd
->band
= WL1271_CHANNEL_TUNE_BAND_2_4
;
96 /* set up any channel, 7 is in the middle of the range */
99 ret
= wl1271_cmd_test(wl
, cmd
, sizeof(*cmd
), 0);
101 wl1271_warning("TEST_CMD_CHANNEL_TUNE failed");
107 int wl1271_cmd_cal_update_ref_point(struct wl1271
*wl
)
109 struct wl1271_cmd_cal_update_ref_point
*cmd
;
112 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
116 cmd
->test
.id
= TEST_CMD_UPDATE_PD_REFERENCE_POINT
;
118 /* FIXME: still waiting for the correct values */
120 cmd
->ref_detector
= 0;
122 cmd
->sub_band
= WL1271_PD_REFERENCE_POINT_BAND_B_G
;
124 ret
= wl1271_cmd_test(wl
, cmd
, sizeof(*cmd
), 0);
126 wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed");
132 int wl1271_cmd_cal_p2g(struct wl1271
*wl
)
134 struct wl1271_cmd_cal_p2g
*cmd
;
137 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
141 cmd
->test
.id
= TEST_CMD_P2G_CAL
;
143 cmd
->sub_band_mask
= WL1271_CAL_P2G_BAND_B_G
;
145 ret
= wl1271_cmd_test(wl
, cmd
, sizeof(*cmd
), 0);
147 wl1271_warning("TEST_CMD_P2G_CAL failed");
153 int wl1271_cmd_cal(struct wl1271
*wl
)
156 * FIXME: we must make sure that we're not sleeping when calibration
161 wl1271_notice("performing tx calibration");
163 ret
= wl1271_cmd_cal_channel_tune(wl
);
167 ret
= wl1271_cmd_cal_update_ref_point(wl
);
171 ret
= wl1271_cmd_cal_p2g(wl
);
178 int wl1271_cmd_join(struct wl1271
*wl
)
180 static bool do_cal
= true;
181 struct wl1271_cmd_join
*join
;
185 /* FIXME: remove when we get calibration from the factory */
187 ret
= wl1271_cmd_cal(wl
);
189 wl1271_warning("couldn't calibrate");
194 /* FIXME: This is a workaround, because with the current stack, we
195 * cannot know when we have disassociated. So, if we have already
196 * joined, we disconnect before joining again. */
198 ret
= wl1271_cmd_disconnect(wl
);
200 wl1271_error("failed to disconnect before rejoining");
207 join
= kzalloc(sizeof(*join
), GFP_KERNEL
);
213 wl1271_debug(DEBUG_CMD
, "cmd join");
215 /* Reverse order BSSID */
216 bssid
= (u8
*) &join
->bssid_lsb
;
217 for (i
= 0; i
< ETH_ALEN
; i
++)
218 bssid
[i
] = wl
->bssid
[ETH_ALEN
- i
- 1];
220 join
->rx_config_options
= wl
->rx_config
;
221 join
->rx_filter_options
= wl
->rx_filter
;
224 * FIXME: disable temporarily all filters because after commit
225 * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
226 * association. The filter logic needs to be implemented properly
227 * and once that is done, this hack can be removed.
229 join
->rx_config_options
= 0;
230 join
->rx_filter_options
= WL1271_DEFAULT_RX_FILTER
;
232 join
->basic_rate_set
= RATE_MASK_1MBPS
| RATE_MASK_2MBPS
|
233 RATE_MASK_5_5MBPS
| RATE_MASK_11MBPS
;
235 join
->beacon_interval
= WL1271_DEFAULT_BEACON_INT
;
236 join
->dtim_interval
= WL1271_DEFAULT_DTIM_PERIOD
;
237 join
->bss_type
= wl
->bss_type
;
238 join
->channel
= wl
->channel
;
239 join
->ssid_len
= wl
->ssid_len
;
240 memcpy(join
->ssid
, wl
->ssid
, wl
->ssid_len
);
241 join
->ctrl
= WL1271_JOIN_CMD_CTRL_TX_FLUSH
;
243 /* increment the session counter */
244 wl
->session_counter
++;
245 if (wl
->session_counter
>= SESSION_COUNTER_MAX
)
246 wl
->session_counter
= 0;
248 join
->ctrl
|= wl
->session_counter
<< WL1271_JOIN_CMD_TX_SESSION_OFFSET
;
250 /* reset TX security counters */
251 wl
->tx_security_last_seq
= 0;
252 wl
->tx_security_seq_16
= 0;
253 wl
->tx_security_seq_32
= 0;
255 ret
= wl1271_cmd_send(wl
, CMD_START_JOIN
, join
, sizeof(*join
));
257 wl1271_error("failed to initiate cmd join");
264 * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
265 * simplify locking we just sleep instead, for now
277 * send test command to firmware
280 * @buf: buffer containing the command, with all headers, must work with dma
281 * @len: length of the buffer
282 * @answer: is answer needed
284 int wl1271_cmd_test(struct wl1271
*wl
, void *buf
, size_t buf_len
, u8 answer
)
288 wl1271_debug(DEBUG_CMD
, "cmd test");
290 ret
= wl1271_cmd_send(wl
, CMD_TEST
, buf
, buf_len
);
293 wl1271_warning("TEST command failed");
298 struct wl1271_command
*cmd_answer
;
301 * The test command got in, we can read the answer.
302 * The answer would be a wl1271_command, where the
303 * parameter array contains the actual answer.
305 wl1271_spi_read(wl
, wl
->cmd_box_addr
, buf
, buf_len
, false);
309 if (cmd_answer
->header
.status
!= CMD_STATUS_SUCCESS
)
310 wl1271_error("TEST command answer error: %d",
311 cmd_answer
->header
.status
);
318 * read acx from firmware
322 * @buf: buffer for the response, including all headers, must work with dma
323 * @len: lenght of buf
325 int wl1271_cmd_interrogate(struct wl1271
*wl
, u16 id
, void *buf
, size_t len
)
327 struct acx_header
*acx
= buf
;
330 wl1271_debug(DEBUG_CMD
, "cmd interrogate");
334 /* payload length, does not include any headers */
335 acx
->len
= len
- sizeof(*acx
);
337 ret
= wl1271_cmd_send(wl
, CMD_INTERROGATE
, acx
, sizeof(*acx
));
339 wl1271_error("INTERROGATE command failed");
343 /* the interrogate command got in, we can read the answer */
344 wl1271_spi_read(wl
, wl
->cmd_box_addr
, buf
, len
, false);
347 if (acx
->cmd
.status
!= CMD_STATUS_SUCCESS
)
348 wl1271_error("INTERROGATE command error: %d",
356 * write acx value to firmware
360 * @buf: buffer containing acx, including all headers, must work with dma
361 * @len: length of buf
363 int wl1271_cmd_configure(struct wl1271
*wl
, u16 id
, void *buf
, size_t len
)
365 struct acx_header
*acx
= buf
;
368 wl1271_debug(DEBUG_CMD
, "cmd configure");
372 /* payload length, does not include any headers */
373 acx
->len
= len
- sizeof(*acx
);
375 ret
= wl1271_cmd_send(wl
, CMD_CONFIGURE
, acx
, len
);
377 wl1271_warning("CONFIGURE command NOK");
384 int wl1271_cmd_data_path(struct wl1271
*wl
, u8 channel
, bool enable
)
386 struct cmd_enabledisable_path
*cmd
;
390 wl1271_debug(DEBUG_CMD
, "cmd data path");
392 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
398 cmd
->channel
= channel
;
401 cmd_rx
= CMD_ENABLE_RX
;
402 cmd_tx
= CMD_ENABLE_TX
;
404 cmd_rx
= CMD_DISABLE_RX
;
405 cmd_tx
= CMD_DISABLE_TX
;
408 ret
= wl1271_cmd_send(wl
, cmd_rx
, cmd
, sizeof(*cmd
));
410 wl1271_error("rx %s cmd for channel %d failed",
411 enable
? "start" : "stop", channel
);
415 wl1271_debug(DEBUG_BOOT
, "rx %s cmd channel %d",
416 enable
? "start" : "stop", channel
);
418 ret
= wl1271_cmd_send(wl
, cmd_tx
, cmd
, sizeof(*cmd
));
420 wl1271_error("tx %s cmd for channel %d failed",
421 enable
? "start" : "stop", channel
);
425 wl1271_debug(DEBUG_BOOT
, "tx %s cmd channel %d",
426 enable
? "start" : "stop", channel
);
433 int wl1271_cmd_ps_mode(struct wl1271
*wl
, u8 ps_mode
)
435 struct wl1271_cmd_ps_params
*ps_params
= NULL
;
438 /* FIXME: this should be in ps.c */
439 ret
= wl1271_acx_wake_up_conditions(wl
, WAKE_UP_EVENT_DTIM_BITMAP
,
442 wl1271_error("couldn't set wake up conditions");
446 wl1271_debug(DEBUG_CMD
, "cmd set ps mode");
448 ps_params
= kzalloc(sizeof(*ps_params
), GFP_KERNEL
);
454 ps_params
->ps_mode
= ps_mode
;
455 ps_params
->send_null_data
= 1;
456 ps_params
->retries
= 5;
457 ps_params
->hang_over_period
= 128;
458 ps_params
->null_data_rate
= 1; /* 1 Mbps */
460 ret
= wl1271_cmd_send(wl
, CMD_SET_PS_MODE
, ps_params
,
463 wl1271_error("cmd set_ps_mode failed");
472 int wl1271_cmd_read_memory(struct wl1271
*wl
, u32 addr
, void *answer
,
475 struct cmd_read_write_memory
*cmd
;
478 wl1271_debug(DEBUG_CMD
, "cmd read memory");
480 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
486 WARN_ON(len
> MAX_READ_SIZE
);
487 len
= min_t(size_t, len
, MAX_READ_SIZE
);
492 ret
= wl1271_cmd_send(wl
, CMD_READ_MEMORY
, cmd
, sizeof(*cmd
));
494 wl1271_error("read memory command failed: %d", ret
);
498 /* the read command got in, we can now read the answer */
499 wl1271_spi_read(wl
, wl
->cmd_box_addr
, cmd
, sizeof(*cmd
), false);
501 if (cmd
->header
.status
!= CMD_STATUS_SUCCESS
)
502 wl1271_error("error in read command result: %d",
505 memcpy(answer
, cmd
->value
, len
);
512 int wl1271_cmd_scan(struct wl1271
*wl
, u8
*ssid
, size_t len
,
513 u8 active_scan
, u8 high_prio
, u8 num_channels
,
517 struct wl1271_cmd_trigger_scan_to
*trigger
= NULL
;
518 struct wl1271_cmd_scan
*params
= NULL
;
520 u16 scan_options
= 0;
525 params
= kzalloc(sizeof(*params
), GFP_KERNEL
);
529 params
->params
.rx_config_options
= cpu_to_le32(CFG_RX_ALL_GOOD
);
530 params
->params
.rx_filter_options
=
531 cpu_to_le32(CFG_RX_PRSP_EN
| CFG_RX_MGMT_EN
| CFG_RX_BCN_EN
);
534 scan_options
|= WL1271_SCAN_OPT_PASSIVE
;
536 scan_options
|= WL1271_SCAN_OPT_PRIORITY_HIGH
;
537 params
->params
.scan_options
= scan_options
;
539 params
->params
.num_channels
= num_channels
;
540 params
->params
.num_probe_requests
= probe_requests
;
541 params
->params
.tx_rate
= cpu_to_le32(RATE_MASK_2MBPS
);
542 params
->params
.tid_trigger
= 0;
543 params
->params
.scan_tag
= WL1271_SCAN_DEFAULT_TAG
;
545 for (i
= 0; i
< num_channels
; i
++) {
546 params
->channels
[i
].min_duration
=
547 cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION
);
548 params
->channels
[i
].max_duration
=
549 cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION
);
550 memset(¶ms
->channels
[i
].bssid_lsb
, 0xff, 4);
551 memset(¶ms
->channels
[i
].bssid_msb
, 0xff, 2);
552 params
->channels
[i
].early_termination
= 0;
553 params
->channels
[i
].tx_power_att
= WL1271_SCAN_CURRENT_TX_PWR
;
554 params
->channels
[i
].channel
= i
+ 1;
558 params
->params
.ssid_len
= len
;
559 memcpy(params
->params
.ssid
, ssid
, len
);
562 ret
= wl1271_cmd_build_probe_req(wl
, ssid
, len
);
564 wl1271_error("PROBE request template failed");
568 trigger
= kzalloc(sizeof(*trigger
), GFP_KERNEL
);
574 /* disable the timeout */
575 trigger
->timeout
= 0;
577 ret
= wl1271_cmd_send(wl
, CMD_TRIGGER_SCAN_TO
, trigger
,
580 wl1271_error("trigger scan to failed for hw scan");
584 wl1271_dump(DEBUG_SCAN
, "SCAN: ", params
, sizeof(*params
));
588 ret
= wl1271_cmd_send(wl
, CMD_SCAN
, params
, sizeof(*params
));
590 wl1271_error("SCAN failed");
594 wl1271_spi_read(wl
, wl
->cmd_box_addr
, params
, sizeof(*params
),
597 if (params
->header
.status
!= CMD_STATUS_SUCCESS
) {
598 wl1271_error("Scan command error: %d",
599 params
->header
.status
);
600 wl
->scanning
= false;
610 int wl1271_cmd_template_set(struct wl1271
*wl
, u16 template_id
,
611 void *buf
, size_t buf_len
)
613 struct wl1271_cmd_template_set
*cmd
;
616 wl1271_debug(DEBUG_CMD
, "cmd template_set %d", template_id
);
618 WARN_ON(buf_len
> WL1271_CMD_TEMPL_MAX_SIZE
);
619 buf_len
= min_t(size_t, buf_len
, WL1271_CMD_TEMPL_MAX_SIZE
);
621 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
627 cmd
->len
= cpu_to_le16(buf_len
);
628 cmd
->template_type
= template_id
;
629 cmd
->enabled_rates
= ACX_RATE_MASK_UNSPECIFIED
;
630 cmd
->short_retry_limit
= ACX_RATE_RETRY_LIMIT
;
631 cmd
->long_retry_limit
= ACX_RATE_RETRY_LIMIT
;
634 memcpy(cmd
->template_data
, buf
, buf_len
);
636 ret
= wl1271_cmd_send(wl
, CMD_SET_TEMPLATE
, cmd
, sizeof(*cmd
));
638 wl1271_warning("cmd set_template failed: %d", ret
);
649 static int wl1271_build_basic_rates(char *rates
)
653 rates
[index
++] = IEEE80211_BASIC_RATE_MASK
| IEEE80211_CCK_RATE_1MB
;
654 rates
[index
++] = IEEE80211_BASIC_RATE_MASK
| IEEE80211_CCK_RATE_2MB
;
655 rates
[index
++] = IEEE80211_BASIC_RATE_MASK
| IEEE80211_CCK_RATE_5MB
;
656 rates
[index
++] = IEEE80211_BASIC_RATE_MASK
| IEEE80211_CCK_RATE_11MB
;
661 static int wl1271_build_extended_rates(char *rates
)
665 rates
[index
++] = IEEE80211_OFDM_RATE_6MB
;
666 rates
[index
++] = IEEE80211_OFDM_RATE_9MB
;
667 rates
[index
++] = IEEE80211_OFDM_RATE_12MB
;
668 rates
[index
++] = IEEE80211_OFDM_RATE_18MB
;
669 rates
[index
++] = IEEE80211_OFDM_RATE_24MB
;
670 rates
[index
++] = IEEE80211_OFDM_RATE_36MB
;
671 rates
[index
++] = IEEE80211_OFDM_RATE_48MB
;
672 rates
[index
++] = IEEE80211_OFDM_RATE_54MB
;
677 int wl1271_cmd_build_null_data(struct wl1271
*wl
)
679 struct wl12xx_null_data_template
template;
681 if (!is_zero_ether_addr(wl
->bssid
)) {
682 memcpy(template.header
.da
, wl
->bssid
, ETH_ALEN
);
683 memcpy(template.header
.bssid
, wl
->bssid
, ETH_ALEN
);
685 memset(template.header
.da
, 0xff, ETH_ALEN
);
686 memset(template.header
.bssid
, 0xff, ETH_ALEN
);
689 memcpy(template.header
.sa
, wl
->mac_addr
, ETH_ALEN
);
690 template.header
.frame_ctl
= cpu_to_le16(IEEE80211_FTYPE_DATA
|
691 IEEE80211_STYPE_NULLFUNC
);
693 return wl1271_cmd_template_set(wl
, CMD_TEMPL_NULL_DATA
, &template,
698 int wl1271_cmd_build_ps_poll(struct wl1271
*wl
, u16 aid
)
700 struct wl12xx_ps_poll_template
template;
702 memcpy(template.bssid
, wl
->bssid
, ETH_ALEN
);
703 memcpy(template.ta
, wl
->mac_addr
, ETH_ALEN
);
705 /* aid in PS-Poll has its two MSBs each set to 1 */
706 template.aid
= cpu_to_le16(1 << 15 | 1 << 14 | aid
);
708 template.fc
= cpu_to_le16(IEEE80211_FTYPE_CTL
| IEEE80211_STYPE_PSPOLL
);
710 return wl1271_cmd_template_set(wl
, CMD_TEMPL_PS_POLL
, &template,
715 int wl1271_cmd_build_probe_req(struct wl1271
*wl
, u8
*ssid
, size_t ssid_len
)
717 struct wl12xx_probe_req_template
template;
718 struct wl12xx_ie_rates
*rates
;
722 ptr
= (char *)&template;
723 size
= sizeof(struct ieee80211_header
);
725 memset(template.header
.da
, 0xff, ETH_ALEN
);
726 memset(template.header
.bssid
, 0xff, ETH_ALEN
);
727 memcpy(template.header
.sa
, wl
->mac_addr
, ETH_ALEN
);
728 template.header
.frame_ctl
= cpu_to_le16(IEEE80211_STYPE_PROBE_REQ
);
732 template.ssid
.header
.id
= WLAN_EID_SSID
;
733 template.ssid
.header
.len
= ssid_len
;
734 if (ssid_len
&& ssid
)
735 memcpy(template.ssid
.ssid
, ssid
, ssid_len
);
736 size
+= sizeof(struct wl12xx_ie_header
) + ssid_len
;
740 rates
= (struct wl12xx_ie_rates
*)ptr
;
741 rates
->header
.id
= WLAN_EID_SUPP_RATES
;
742 rates
->header
.len
= wl1271_build_basic_rates(rates
->rates
);
743 size
+= sizeof(struct wl12xx_ie_header
) + rates
->header
.len
;
744 ptr
+= sizeof(struct wl12xx_ie_header
) + rates
->header
.len
;
747 rates
= (struct wl12xx_ie_rates
*)ptr
;
748 rates
->header
.id
= WLAN_EID_EXT_SUPP_RATES
;
749 rates
->header
.len
= wl1271_build_extended_rates(rates
->rates
);
750 size
+= sizeof(struct wl12xx_ie_header
) + rates
->header
.len
;
752 wl1271_dump(DEBUG_SCAN
, "PROBE REQ: ", &template, size
);
754 return wl1271_cmd_template_set(wl
, CMD_TEMPL_CFG_PROBE_REQ_2_4
,
758 int wl1271_cmd_set_default_wep_key(struct wl1271
*wl
, u8 id
)
760 struct wl1271_cmd_set_keys
*cmd
;
763 wl1271_debug(DEBUG_CMD
, "cmd set_default_wep_key %d", id
);
765 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
772 cmd
->key_action
= KEY_SET_ID
;
773 cmd
->key_type
= KEY_WEP
;
775 ret
= wl1271_cmd_send(wl
, CMD_SET_KEYS
, cmd
, sizeof(*cmd
));
777 wl1271_warning("cmd set_default_wep_key failed: %d", ret
);
787 int wl1271_cmd_set_key(struct wl1271
*wl
, u16 action
, u8 id
, u8 key_type
,
788 u8 key_size
, const u8
*key
, const u8
*addr
,
789 u32 tx_seq_32
, u16 tx_seq_16
)
791 struct wl1271_cmd_set_keys
*cmd
;
794 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
800 if (key_type
!= KEY_WEP
)
801 memcpy(cmd
->addr
, addr
, ETH_ALEN
);
803 cmd
->key_action
= action
;
804 cmd
->key_size
= key_size
;
805 cmd
->key_type
= key_type
;
807 cmd
->ac_seq_num16
[0] = tx_seq_16
;
808 cmd
->ac_seq_num32
[0] = tx_seq_32
;
810 /* we have only one SSID profile */
811 cmd
->ssid_profile
= 0;
815 if (key_type
== KEY_TKIP
) {
817 * We get the key in the following form:
818 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
819 * but the target is expecting:
820 * TKIP - RX MIC - TX MIC
822 memcpy(cmd
->key
, key
, 16);
823 memcpy(cmd
->key
+ 16, key
+ 24, 8);
824 memcpy(cmd
->key
+ 24, key
+ 16, 8);
827 memcpy(cmd
->key
, key
, key_size
);
830 wl1271_dump(DEBUG_CRYPT
, "TARGET KEY: ", cmd
, sizeof(*cmd
));
832 ret
= wl1271_cmd_send(wl
, CMD_SET_KEYS
, cmd
, sizeof(*cmd
));
834 wl1271_warning("could not set keys");
844 int wl1271_cmd_disconnect(struct wl1271
*wl
)
846 struct wl1271_cmd_disconnect
*cmd
;
849 wl1271_debug(DEBUG_CMD
, "cmd disconnect");
851 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
857 cmd
->rx_config_options
= wl
->rx_config
;
858 cmd
->rx_filter_options
= wl
->rx_filter
;
859 /* disconnect reason is not used in immediate disconnections */
860 cmd
->type
= DISCONNECT_IMMEDIATE
;
862 ret
= wl1271_cmd_send(wl
, CMD_DISCONNECT
, cmd
, sizeof(*cmd
));
864 wl1271_error("failed to send disconnect command");