]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/iwlwifi/mvm/fw.c
mac80211: support more than one band in scan request
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / iwlwifi / mvm / fw.c
CommitLineData
8ca151b5
JB
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
51368bf7 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8ca151b5
JB
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
410dc5aa 25 * in the file called COPYING.
8ca151b5
JB
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
51368bf7 33 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8ca151b5
JB
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63#include <net/mac80211.h>
64
65#include "iwl-trans.h"
66#include "iwl-op-mode.h"
67#include "iwl-fw.h"
68#include "iwl-debug.h"
69#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
70#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
71#include "iwl-eeprom-parse.h"
72
73#include "mvm.h"
74#include "iwl-phy-db.h"
75
76#define MVM_UCODE_ALIVE_TIMEOUT HZ
77#define MVM_UCODE_CALIB_TIMEOUT (2*HZ)
78
79#define UCODE_VALID_OK cpu_to_le32(0x1)
80
8ca151b5
JB
81struct iwl_mvm_alive_data {
82 bool valid;
83 u32 scd_base_addr;
84};
85
86static inline const struct fw_img *
87iwl_get_ucode_image(struct iwl_mvm *mvm, enum iwl_ucode_type ucode_type)
88{
89 if (ucode_type >= IWL_UCODE_TYPE_MAX)
90 return NULL;
91
92 return &mvm->fw->img[ucode_type];
93}
94
95static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
96{
97 struct iwl_tx_ant_cfg_cmd tx_ant_cmd = {
98 .valid = cpu_to_le32(valid_tx_ant),
99 };
100
33223542 101 IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant);
a1022927 102 return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, 0,
8ca151b5
JB
103 sizeof(tx_ant_cmd), &tx_ant_cmd);
104}
105
106static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
107 struct iwl_rx_packet *pkt, void *data)
108{
109 struct iwl_mvm *mvm =
110 container_of(notif_wait, struct iwl_mvm, notif_wait);
111 struct iwl_mvm_alive_data *alive_data = data;
112 struct mvm_alive_resp *palive;
01a9ca51
EH
113 struct mvm_alive_resp_ver2 *palive2;
114
115 if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
116 palive = (void *)pkt->data;
117
118 mvm->support_umac_log = false;
119 mvm->error_event_table =
120 le32_to_cpu(palive->error_event_table_ptr);
121 mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr);
122 alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
123
124 alive_data->valid = le16_to_cpu(palive->status) ==
125 IWL_ALIVE_STATUS_OK;
126 IWL_DEBUG_FW(mvm,
127 "Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
128 le16_to_cpu(palive->status), palive->ver_type,
129 palive->ver_subtype, palive->flags);
130 } else {
131 palive2 = (void *)pkt->data;
132
01a9ca51
EH
133 mvm->error_event_table =
134 le32_to_cpu(palive2->error_event_table_ptr);
135 mvm->log_event_table =
136 le32_to_cpu(palive2->log_event_table_ptr);
137 alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr);
138 mvm->umac_error_event_table =
139 le32_to_cpu(palive2->error_info_addr);
91479b64
EH
140 mvm->sf_space.addr = le32_to_cpu(palive2->st_fwrd_addr);
141 mvm->sf_space.size = le32_to_cpu(palive2->st_fwrd_size);
01a9ca51
EH
142
143 alive_data->valid = le16_to_cpu(palive2->status) ==
144 IWL_ALIVE_STATUS_OK;
ffa70264
EG
145 if (mvm->umac_error_event_table)
146 mvm->support_umac_log = true;
147
01a9ca51
EH
148 IWL_DEBUG_FW(mvm,
149 "Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
150 le16_to_cpu(palive2->status), palive2->ver_type,
151 palive2->ver_subtype, palive2->flags);
152
153 IWL_DEBUG_FW(mvm,
154 "UMAC version: Major - 0x%x, Minor - 0x%x\n",
155 palive2->umac_major, palive2->umac_minor);
156 }
8ca151b5
JB
157
158 return true;
159}
160
161static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
162 struct iwl_rx_packet *pkt, void *data)
163{
164 struct iwl_phy_db *phy_db = data;
165
166 if (pkt->hdr.cmd != CALIB_RES_NOTIF_PHY_DB) {
167 WARN_ON(pkt->hdr.cmd != INIT_COMPLETE_NOTIF);
168 return true;
169 }
170
171 WARN_ON(iwl_phy_db_set_section(phy_db, pkt, GFP_ATOMIC));
172
173 return false;
174}
175
176static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
177 enum iwl_ucode_type ucode_type)
178{
179 struct iwl_notification_wait alive_wait;
180 struct iwl_mvm_alive_data alive_data;
181 const struct fw_img *fw;
182 int ret, i;
183 enum iwl_ucode_type old_type = mvm->cur_ucode;
184 static const u8 alive_cmd[] = { MVM_ALIVE };
91479b64 185 struct iwl_sf_region st_fwrd_space;
8ca151b5 186
8ca151b5 187 fw = iwl_get_ucode_image(mvm, ucode_type);
befe9b6f 188 if (WARN_ON(!fw))
8ca151b5 189 return -EINVAL;
befe9b6f
JB
190 mvm->cur_ucode = ucode_type;
191 mvm->ucode_loaded = false;
8ca151b5
JB
192
193 iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
194 alive_cmd, ARRAY_SIZE(alive_cmd),
195 iwl_alive_fn, &alive_data);
196
197 ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
198 if (ret) {
199 mvm->cur_ucode = old_type;
200 iwl_remove_notification(&mvm->notif_wait, &alive_wait);
201 return ret;
202 }
203
204 /*
205 * Some things may run in the background now, but we
206 * just wait for the ALIVE notification here.
207 */
208 ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
209 MVM_UCODE_ALIVE_TIMEOUT);
210 if (ret) {
211 mvm->cur_ucode = old_type;
212 return ret;
213 }
214
215 if (!alive_data.valid) {
216 IWL_ERR(mvm, "Loaded ucode is not valid!\n");
217 mvm->cur_ucode = old_type;
218 return -EIO;
219 }
220
91479b64
EH
221 /*
222 * update the sdio allocation according to the pointer we get in the
223 * alive notification.
224 */
225 st_fwrd_space.addr = mvm->sf_space.addr;
226 st_fwrd_space.size = mvm->sf_space.size;
227 ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);
228
8ca151b5
JB
229 iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
230
231 /*
232 * Note: all the queues are enabled as part of the interface
233 * initialization, but in firmware restart scenarios they
234 * could be stopped, so wake them up. In firmware restart,
235 * mac80211 will have the queues stopped as well until the
236 * reconfiguration completes. During normal startup, they
237 * will be empty.
238 */
239
240 for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
19e737c9 241 if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE)
8ca151b5
JB
242 mvm->queue_to_mac80211[i] = i;
243 else
244 mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
245 atomic_set(&mvm->queue_stop_count[i], 0);
246 }
247
248 mvm->transport_queue_stop = 0;
249
250 mvm->ucode_loaded = true;
251
252 return 0;
253}
8ca151b5
JB
254
255static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
256{
257 struct iwl_phy_cfg_cmd phy_cfg_cmd;
258 enum iwl_ucode_type ucode_type = mvm->cur_ucode;
259
260 /* Set parameters */
6221d47c 261 phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config);
8ca151b5
JB
262 phy_cfg_cmd.calib_control.event_trigger =
263 mvm->fw->default_calib[ucode_type].event_trigger;
264 phy_cfg_cmd.calib_control.flow_trigger =
265 mvm->fw->default_calib[ucode_type].flow_trigger;
266
267 IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
268 phy_cfg_cmd.phy_cfg);
269
a1022927 270 return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0,
8ca151b5
JB
271 sizeof(phy_cfg_cmd), &phy_cfg_cmd);
272}
273
8ca151b5
JB
274int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
275{
276 struct iwl_notification_wait calib_wait;
277 static const u8 init_complete[] = {
278 INIT_COMPLETE_NOTIF,
279 CALIB_RES_NOTIF_PHY_DB
280 };
281 int ret;
282
283 lockdep_assert_held(&mvm->mutex);
284
a4082843 285 if (WARN_ON_ONCE(mvm->init_ucode_complete))
8ca151b5
JB
286 return 0;
287
288 iwl_init_notification_wait(&mvm->notif_wait,
289 &calib_wait,
290 init_complete,
291 ARRAY_SIZE(init_complete),
292 iwl_wait_phy_db_entry,
293 mvm->phy_db);
294
295 /* Will also start the device */
296 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_INIT);
297 if (ret) {
298 IWL_ERR(mvm, "Failed to start INIT ucode: %d\n", ret);
299 goto error;
300 }
301
ae397472 302 ret = iwl_send_bt_init_conf(mvm);
931d4160
EG
303 if (ret)
304 goto error;
305
81a67e32 306 /* Read the NVM only at driver load time, no need to do this twice */
8ca151b5
JB
307 if (read_nvm) {
308 /* Read nvm */
14b485f0 309 ret = iwl_nvm_init(mvm, true);
8ca151b5
JB
310 if (ret) {
311 IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
312 goto error;
313 }
314 }
315
81a67e32 316 /* In case we read the NVM from external file, load it to the NIC */
e02a9d60 317 if (mvm->nvm_file_name)
81a67e32
EL
318 iwl_mvm_load_nvm_to_nic(mvm);
319
8ca151b5
JB
320 ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
321 WARN_ON(ret);
322
4f59334b
EH
323 /*
324 * abort after reading the nvm in case RF Kill is on, we will complete
325 * the init seq later when RF kill will switch to off
326 */
9ee718aa 327 if (iwl_mvm_is_radio_killed(mvm)) {
4f59334b
EH
328 IWL_DEBUG_RF_KILL(mvm,
329 "jump over all phy activities due to RF kill\n");
330 iwl_remove_notification(&mvm->notif_wait, &calib_wait);
a4082843
AN
331 ret = 1;
332 goto out;
4f59334b
EH
333 }
334
e07cbb53 335 /* Send TX valid antennas before triggering calibrations */
4ed735e7 336 ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
e07cbb53
DS
337 if (ret)
338 goto error;
339
8ca151b5
JB
340 /*
341 * Send phy configurations command to init uCode
342 * to start the 16.0 uCode init image internal calibrations.
343 */
344 ret = iwl_send_phy_cfg_cmd(mvm);
345 if (ret) {
346 IWL_ERR(mvm, "Failed to run INIT calibrations: %d\n",
347 ret);
348 goto error;
349 }
350
351 /*
352 * Some things may run in the background now, but we
353 * just wait for the calibration complete notification.
354 */
355 ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
356 MVM_UCODE_CALIB_TIMEOUT);
357 if (!ret)
ff116373 358 mvm->init_ucode_complete = true;
8ca151b5
JB
359 goto out;
360
361error:
362 iwl_remove_notification(&mvm->notif_wait, &calib_wait);
363out:
a4082843 364 if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
8ca151b5
JB
365 /* we want to debug INIT and we have no NVM - fake */
366 mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
367 sizeof(struct ieee80211_channel) +
368 sizeof(struct ieee80211_rate),
369 GFP_KERNEL);
370 if (!mvm->nvm_data)
371 return -ENOMEM;
8ca151b5
JB
372 mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels;
373 mvm->nvm_data->bands[0].n_channels = 1;
374 mvm->nvm_data->bands[0].n_bitrates = 1;
375 mvm->nvm_data->bands[0].bitrates =
376 (void *)mvm->nvm_data->channels + 1;
377 mvm->nvm_data->bands[0].bitrates->hw_value = 10;
378 }
379
380 return ret;
381}
382
8ca151b5
JB
383int iwl_mvm_up(struct iwl_mvm *mvm)
384{
385 int ret, i;
53a9d61e
IP
386 struct ieee80211_channel *chan;
387 struct cfg80211_chan_def chandef;
8ca151b5
JB
388
389 lockdep_assert_held(&mvm->mutex);
390
391 ret = iwl_trans_start_hw(mvm->trans);
392 if (ret)
393 return ret;
394
ff116373
EL
395 /*
396 * If we haven't completed the run of the init ucode during
397 * module loading, load init ucode now
398 * (for example, if we were in RFKILL)
399 */
400 if (!mvm->init_ucode_complete) {
8ca151b5
JB
401 ret = iwl_run_init_mvm_ucode(mvm, false);
402 if (ret && !iwlmvm_mod_params.init_dbg) {
403 IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
4f59334b
EH
404 /* this can't happen */
405 if (WARN_ON(ret > 0))
406 ret = -ERFKILL;
8ca151b5
JB
407 goto error;
408 }
a4082843
AN
409 if (!iwlmvm_mod_params.init_dbg) {
410 /*
411 * should stop and start HW since that INIT
412 * image just loaded
413 */
414 iwl_trans_stop_device(mvm->trans);
415 ret = iwl_trans_start_hw(mvm->trans);
416 if (ret)
417 return ret;
418 }
8ca151b5
JB
419 }
420
421 if (iwlmvm_mod_params.init_dbg)
422 return 0;
423
424 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
425 if (ret) {
426 IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
427 goto error;
428 }
429
1f3b0ff8
LE
430 ret = iwl_mvm_sf_update(mvm, NULL, false);
431 if (ret)
432 IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
433
4ed735e7 434 ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
8ca151b5
JB
435 if (ret)
436 goto error;
437
931d4160
EG
438 ret = iwl_send_bt_init_conf(mvm);
439 if (ret)
440 goto error;
441
8ca151b5
JB
442 /* Send phy db control command and then phy db calibration*/
443 ret = iwl_send_phy_db_data(mvm->phy_db);
444 if (ret)
445 goto error;
446
447 ret = iwl_send_phy_cfg_cmd(mvm);
448 if (ret)
449 goto error;
450
451 /* init the fw <-> mac80211 STA mapping */
452 for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
453 RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
454
455 /* Add auxiliary station for scanning */
456 ret = iwl_mvm_add_aux_sta(mvm);
457 if (ret)
458 goto error;
459
53a9d61e
IP
460 /* Add all the PHY contexts */
461 chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0];
462 cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
463 for (i = 0; i < NUM_PHY_CTX; i++) {
464 /*
465 * The channel used here isn't relevant as it's
466 * going to be overwritten in the other flows.
467 * For now use the first channel we have.
468 */
469 ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i],
470 &chandef, 1, 1);
471 if (ret)
472 goto error;
473 }
8ca151b5 474
0c0e2c71
IY
475 /* Initialize tx backoffs to the minimal possible */
476 iwl_mvm_tt_tx_backoff(mvm, 0);
477
c1cb92fc 478 ret = iwl_mvm_power_update_device(mvm);
64b928c4
AB
479 if (ret)
480 goto error;
481
7498cf4c
EP
482 /* allow FW/transport low power modes if not during restart */
483 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
484 iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
485
53a9d61e 486 IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
8ca151b5
JB
487 return 0;
488 error:
489 iwl_trans_stop_device(mvm->trans);
490 return ret;
491}
492
493int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
494{
495 int ret, i;
496
497 lockdep_assert_held(&mvm->mutex);
498
499 ret = iwl_trans_start_hw(mvm->trans);
500 if (ret)
501 return ret;
502
503 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_WOWLAN);
504 if (ret) {
505 IWL_ERR(mvm, "Failed to start WoWLAN firmware: %d\n", ret);
506 goto error;
507 }
508
4ed735e7 509 ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
8ca151b5
JB
510 if (ret)
511 goto error;
512
513 /* Send phy db control command and then phy db calibration*/
514 ret = iwl_send_phy_db_data(mvm->phy_db);
515 if (ret)
516 goto error;
517
518 ret = iwl_send_phy_cfg_cmd(mvm);
519 if (ret)
520 goto error;
521
522 /* init the fw <-> mac80211 STA mapping */
523 for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
524 RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
525
526 /* Add auxiliary station for scanning */
527 ret = iwl_mvm_add_aux_sta(mvm);
528 if (ret)
529 goto error;
530
531 return 0;
532 error:
533 iwl_trans_stop_device(mvm->trans);
534 return ret;
535}
536
537int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
538 struct iwl_rx_cmd_buffer *rxb,
539 struct iwl_device_cmd *cmd)
540{
541 struct iwl_rx_packet *pkt = rxb_addr(rxb);
542 struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
543 u32 flags = le32_to_cpu(card_state_notif->flags);
544
545 IWL_DEBUG_RF_KILL(mvm, "Card state received: HW:%s SW:%s CT:%s\n",
546 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
547 (flags & SW_CARD_DISABLED) ? "Kill" : "On",
548 (flags & CT_KILL_CARD_DISABLED) ?
549 "Reached" : "Not reached");
550
8ca151b5
JB
551 return 0;
552}
553
554int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
555 struct iwl_device_cmd *cmd)
556{
557 struct iwl_rx_packet *pkt = rxb_addr(rxb);
558 struct iwl_radio_version_notif *radio_version = (void *)pkt->data;
559
560 /* TODO: what to do with that? */
561 IWL_DEBUG_INFO(mvm,
562 "Radio version: flavor: 0x%08x, step 0x%08x, dash 0x%08x\n",
563 le32_to_cpu(radio_version->radio_flavor),
564 le32_to_cpu(radio_version->radio_step),
565 le32_to_cpu(radio_version->radio_dash));
566 return 0;
567}