aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/fw.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-24 08:25:36 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-01 05:27:15 -0500
commit8ca151b568b67a7b72dcfc6ee6ea7c107ddd795c (patch)
treedac0236038f3791140e9f864c5db2be873c568f0 /drivers/net/wireless/iwlwifi/mvm/fw.c
parentb1e1adfa7d30cd0e8ad9a5c6a89e8c45ebe084f4 (diff)
iwlwifi: add the MVM driver
Newer firmware revisions have a completely new firmware API. This is the new driver for this new API. I've listed the people who directly contributed code, but many others from various teams have contributed in other ways. Cc: Alexander Bondar <alexander.bondar@intel.com> Cc: Amit Beka <amit.beka@intel.com> Cc: Amnon Paz <amnonx.paz@intel.com> Cc: Assaf Krauss <assaf.krauss@intel.com> Cc: David Spinadel <david.spinadel@intel.com> Cc: Dor Shaish <dor.shaish@intel.com> Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Cc: Eytan Lifshitz <eytan.lifshitz@intel.com> Cc: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/fw.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c644
1 files changed, 644 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
new file mode 100644
index 000000000000..90473c2ba1c7
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -0,0 +1,644 @@
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 *
8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
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
25 * in the file called LICENSE.GPL.
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 *
33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
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
81/* Default calibration values for WkP - set to INIT image w/o running */
82static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
83 0x00, 0x18, 0x00 };
84static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
85 0x7f, 0x7f, 0x7f };
86static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
87static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
88 0x00 };
89static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
90static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
91static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
92static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
93
94struct iwl_calib_default_data {
95 u16 size;
96 void *data;
97};
98
99#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
100
101static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
102 [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
103 [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
104 [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
105 [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
106 [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
107 [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
108 [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
109};
110
111struct iwl_mvm_alive_data {
112 bool valid;
113 u32 scd_base_addr;
114};
115
116static inline const struct fw_img *
117iwl_get_ucode_image(struct iwl_mvm *mvm, enum iwl_ucode_type ucode_type)
118{
119 if (ucode_type >= IWL_UCODE_TYPE_MAX)
120 return NULL;
121
122 return &mvm->fw->img[ucode_type];
123}
124
125static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
126{
127 struct iwl_tx_ant_cfg_cmd tx_ant_cmd = {
128 .valid = cpu_to_le32(valid_tx_ant),
129 };
130
131 IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant);
132 return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
133 sizeof(tx_ant_cmd), &tx_ant_cmd);
134}
135
136static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
137 struct iwl_rx_packet *pkt, void *data)
138{
139 struct iwl_mvm *mvm =
140 container_of(notif_wait, struct iwl_mvm, notif_wait);
141 struct iwl_mvm_alive_data *alive_data = data;
142 struct mvm_alive_resp *palive;
143
144 palive = (void *)pkt->data;
145
146 mvm->error_event_table = le32_to_cpu(palive->error_event_table_ptr);
147 mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr);
148 alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
149
150 alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
151 IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
152 le16_to_cpu(palive->status), palive->ver_type,
153 palive->ver_subtype);
154
155 return true;
156}
157
158static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
159 struct iwl_rx_packet *pkt, void *data)
160{
161 struct iwl_phy_db *phy_db = data;
162
163 if (pkt->hdr.cmd != CALIB_RES_NOTIF_PHY_DB) {
164 WARN_ON(pkt->hdr.cmd != INIT_COMPLETE_NOTIF);
165 return true;
166 }
167
168 WARN_ON(iwl_phy_db_set_section(phy_db, pkt, GFP_ATOMIC));
169
170 return false;
171}
172
173static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
174 enum iwl_ucode_type ucode_type)
175{
176 struct iwl_notification_wait alive_wait;
177 struct iwl_mvm_alive_data alive_data;
178 const struct fw_img *fw;
179 int ret, i;
180 enum iwl_ucode_type old_type = mvm->cur_ucode;
181 static const u8 alive_cmd[] = { MVM_ALIVE };
182
183 mvm->cur_ucode = ucode_type;
184 fw = iwl_get_ucode_image(mvm, ucode_type);
185
186 mvm->ucode_loaded = false;
187
188 if (!fw)
189 return -EINVAL;
190
191 iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
192 alive_cmd, ARRAY_SIZE(alive_cmd),
193 iwl_alive_fn, &alive_data);
194
195 ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
196 if (ret) {
197 mvm->cur_ucode = old_type;
198 iwl_remove_notification(&mvm->notif_wait, &alive_wait);
199 return ret;
200 }
201
202 /*
203 * Some things may run in the background now, but we
204 * just wait for the ALIVE notification here.
205 */
206 ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
207 MVM_UCODE_ALIVE_TIMEOUT);
208 if (ret) {
209 mvm->cur_ucode = old_type;
210 return ret;
211 }
212
213 if (!alive_data.valid) {
214 IWL_ERR(mvm, "Loaded ucode is not valid!\n");
215 mvm->cur_ucode = old_type;
216 return -EIO;
217 }
218
219 iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
220
221 /*
222 * Note: all the queues are enabled as part of the interface
223 * initialization, but in firmware restart scenarios they
224 * could be stopped, so wake them up. In firmware restart,
225 * mac80211 will have the queues stopped as well until the
226 * reconfiguration completes. During normal startup, they
227 * will be empty.
228 */
229
230 for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
231 if (i < IWL_MVM_FIRST_AGG_QUEUE && i != IWL_MVM_CMD_QUEUE)
232 mvm->queue_to_mac80211[i] = i;
233 else
234 mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
235 atomic_set(&mvm->queue_stop_count[i], 0);
236 }
237
238 mvm->transport_queue_stop = 0;
239
240 mvm->ucode_loaded = true;
241
242 return 0;
243}
244#define IWL_HW_REV_ID_RAINBOW 0x2
245#define IWL_PROJ_TYPE_LHP 0x5
246
247static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
248{
249 struct iwl_nvm_data *data = mvm->nvm_data;
250 /* Temp calls to static definitions, will be changed to CSR calls */
251 u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
252 u8 project_type = IWL_PROJ_TYPE_LHP;
253
254 return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
255 (hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
256 (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
257}
258
259static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
260{
261 struct iwl_phy_cfg_cmd phy_cfg_cmd;
262 enum iwl_ucode_type ucode_type = mvm->cur_ucode;
263
264 /* Set parameters */
265 phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
266 phy_cfg_cmd.calib_control.event_trigger =
267 mvm->fw->default_calib[ucode_type].event_trigger;
268 phy_cfg_cmd.calib_control.flow_trigger =
269 mvm->fw->default_calib[ucode_type].flow_trigger;
270
271 IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
272 phy_cfg_cmd.phy_cfg);
273
274 return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, CMD_SYNC,
275 sizeof(phy_cfg_cmd), &phy_cfg_cmd);
276}
277
278/* Starting with the new PHY DB implementation - New calibs are enabled */
279/* Value - 0x405e7 */
280#define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\
281 IWL_CALIB_CFG_TEMPERATURE_IDX |\
282 IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
283 IWL_CALIB_CFG_DC_IDX |\
284 IWL_CALIB_CFG_BB_FILTER_IDX |\
285 IWL_CALIB_CFG_LO_LEAKAGE_IDX |\
286 IWL_CALIB_CFG_TX_IQ_IDX |\
287 IWL_CALIB_CFG_RX_IQ_IDX |\
288 IWL_CALIB_CFG_AGC_IDX)
289
290#define IWL_CALIB_DEFAULT_EVENT_INIT 0x0
291
292/* Value 0x41567 */
293#define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\
294 IWL_CALIB_CFG_TEMPERATURE_IDX |\
295 IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
296 IWL_CALIB_CFG_BB_FILTER_IDX |\
297 IWL_CALIB_CFG_DC_IDX |\
298 IWL_CALIB_CFG_TX_IQ_IDX |\
299 IWL_CALIB_CFG_RX_IQ_IDX |\
300 IWL_CALIB_CFG_SENSITIVITY_IDX |\
301 IWL_CALIB_CFG_AGC_IDX)
302
303#define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\
304 IWL_CALIB_CFG_TEMPERATURE_IDX |\
305 IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
306 IWL_CALIB_CFG_TX_PWR_IDX |\
307 IWL_CALIB_CFG_DC_IDX |\
308 IWL_CALIB_CFG_TX_IQ_IDX |\
309 IWL_CALIB_CFG_SENSITIVITY_IDX)
310
311/*
312 * Sets the calibrations trigger values that will be sent to the FW for runtime
313 * and init calibrations.
314 * The ones given in the FW TLV are not correct.
315 */
316static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
317{
318 struct iwl_tlv_calib_ctrl default_calib;
319
320 /*
321 * WkP FW TLV calib bits are wrong, overwrite them.
322 * This defines the dynamic calibrations which are implemented in the
323 * uCode both for init(flow) calculation and event driven calibs.
324 */
325
326 /* Init Image */
327 default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
328 default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
329
330 if (default_calib.event_trigger !=
331 mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
332 IWL_ERR(mvm,
333 "Updating the event calib for INIT image: 0x%x -> 0x%x\n",
334 mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
335 default_calib.event_trigger);
336 if (default_calib.flow_trigger !=
337 mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
338 IWL_ERR(mvm,
339 "Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
340 mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
341 default_calib.flow_trigger);
342
343 memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
344 &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
345 IWL_ERR(mvm,
346 "Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
347 default_calib.event_trigger,
348 default_calib.flow_trigger);
349
350 /* Run time image */
351 default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
352 default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
353
354 if (default_calib.event_trigger !=
355 mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
356 IWL_ERR(mvm,
357 "Updating the event calib for RT image: 0x%x -> 0x%x\n",
358 mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
359 default_calib.event_trigger);
360 if (default_calib.flow_trigger !=
361 mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
362 IWL_ERR(mvm,
363 "Updating the flow calib for RT image: 0x%x -> 0x%x\n",
364 mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
365 default_calib.flow_trigger);
366
367 memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
368 &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
369 IWL_ERR(mvm,
370 "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
371 default_calib.event_trigger,
372 default_calib.flow_trigger);
373}
374
375static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
376{
377 u8 cmd_raw[16]; /* holds the variable size commands */
378 struct iwl_set_calib_default_cmd *cmd =
379 (struct iwl_set_calib_default_cmd *)cmd_raw;
380 int ret, i;
381
382 /* Setting default values for calibrations we don't run */
383 for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
384 u16 cmd_len;
385
386 if (wkp_calib_default_data[i].size == 0)
387 continue;
388
389 memset(cmd_raw, 0, sizeof(cmd_raw));
390 cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
391 cmd->calib_index = cpu_to_le16(i);
392 cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
393 if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
394 "Need to enlarge cmd_raw to %d\n", cmd_len))
395 break;
396 memcpy(cmd->data, wkp_calib_default_data[i].data,
397 wkp_calib_default_data[i].size);
398 ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
399 sizeof(*cmd) +
400 wkp_calib_default_data[i].size,
401 cmd);
402 if (ret)
403 return ret;
404 }
405
406 return 0;
407}
408
409int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
410{
411 struct iwl_notification_wait calib_wait;
412 static const u8 init_complete[] = {
413 INIT_COMPLETE_NOTIF,
414 CALIB_RES_NOTIF_PHY_DB
415 };
416 int ret;
417
418 lockdep_assert_held(&mvm->mutex);
419
420 if (mvm->init_ucode_run)
421 return 0;
422
423 iwl_init_notification_wait(&mvm->notif_wait,
424 &calib_wait,
425 init_complete,
426 ARRAY_SIZE(init_complete),
427 iwl_wait_phy_db_entry,
428 mvm->phy_db);
429
430 /* Will also start the device */
431 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_INIT);
432 if (ret) {
433 IWL_ERR(mvm, "Failed to start INIT ucode: %d\n", ret);
434 goto error;
435 }
436
437 if (read_nvm) {
438 /* Read nvm */
439 ret = iwl_nvm_init(mvm);
440 if (ret) {
441 IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
442 goto error;
443 }
444 }
445
446 ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
447 WARN_ON(ret);
448
449 /* Override the calibrations from TLV and the const of fw */
450 iwl_set_default_calib_trigger(mvm);
451
452 /* WkP doesn't have all calibrations, need to set default values */
453 if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
454 ret = iwl_set_default_calibrations(mvm);
455 if (ret)
456 goto error;
457 }
458
459 /*
460 * Send phy configurations command to init uCode
461 * to start the 16.0 uCode init image internal calibrations.
462 */
463 ret = iwl_send_phy_cfg_cmd(mvm);
464 if (ret) {
465 IWL_ERR(mvm, "Failed to run INIT calibrations: %d\n",
466 ret);
467 goto error;
468 }
469
470 /*
471 * Some things may run in the background now, but we
472 * just wait for the calibration complete notification.
473 */
474 ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
475 MVM_UCODE_CALIB_TIMEOUT);
476 if (!ret)
477 mvm->init_ucode_run = true;
478 goto out;
479
480error:
481 iwl_remove_notification(&mvm->notif_wait, &calib_wait);
482out:
483 if (!iwlmvm_mod_params.init_dbg) {
484 iwl_trans_stop_device(mvm->trans);
485 } else if (!mvm->nvm_data) {
486 /* we want to debug INIT and we have no NVM - fake */
487 mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
488 sizeof(struct ieee80211_channel) +
489 sizeof(struct ieee80211_rate),
490 GFP_KERNEL);
491 if (!mvm->nvm_data)
492 return -ENOMEM;
493 mvm->nvm_data->valid_rx_ant = 1;
494 mvm->nvm_data->valid_tx_ant = 1;
495 mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels;
496 mvm->nvm_data->bands[0].n_channels = 1;
497 mvm->nvm_data->bands[0].n_bitrates = 1;
498 mvm->nvm_data->bands[0].bitrates =
499 (void *)mvm->nvm_data->channels + 1;
500 mvm->nvm_data->bands[0].bitrates->hw_value = 10;
501 }
502
503 return ret;
504}
505
506#define UCODE_CALIB_TIMEOUT (2*HZ)
507
508int iwl_mvm_up(struct iwl_mvm *mvm)
509{
510 int ret, i;
511
512 lockdep_assert_held(&mvm->mutex);
513
514 ret = iwl_trans_start_hw(mvm->trans);
515 if (ret)
516 return ret;
517
518 /* If we were in RFKILL during module loading, load init ucode now */
519 if (!mvm->init_ucode_run) {
520 ret = iwl_run_init_mvm_ucode(mvm, false);
521 if (ret && !iwlmvm_mod_params.init_dbg) {
522 IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
523 goto error;
524 }
525 }
526
527 if (iwlmvm_mod_params.init_dbg)
528 return 0;
529
530 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
531 if (ret) {
532 IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
533 goto error;
534 }
535
536 ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
537 if (ret)
538 goto error;
539
540 /* Send phy db control command and then phy db calibration*/
541 ret = iwl_send_phy_db_data(mvm->phy_db);
542 if (ret)
543 goto error;
544
545 ret = iwl_send_phy_cfg_cmd(mvm);
546 if (ret)
547 goto error;
548
549 /* init the fw <-> mac80211 STA mapping */
550 for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
551 RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
552
553 /* Add auxiliary station for scanning */
554 ret = iwl_mvm_add_aux_sta(mvm);
555 if (ret)
556 goto error;
557
558 IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
559
560 return 0;
561 error:
562 iwl_trans_stop_device(mvm->trans);
563 return ret;
564}
565
566int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
567{
568 int ret, i;
569
570 lockdep_assert_held(&mvm->mutex);
571
572 ret = iwl_trans_start_hw(mvm->trans);
573 if (ret)
574 return ret;
575
576 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_WOWLAN);
577 if (ret) {
578 IWL_ERR(mvm, "Failed to start WoWLAN firmware: %d\n", ret);
579 goto error;
580 }
581
582 ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
583 if (ret)
584 goto error;
585
586 /* Send phy db control command and then phy db calibration*/
587 ret = iwl_send_phy_db_data(mvm->phy_db);
588 if (ret)
589 goto error;
590
591 ret = iwl_send_phy_cfg_cmd(mvm);
592 if (ret)
593 goto error;
594
595 /* init the fw <-> mac80211 STA mapping */
596 for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
597 RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
598
599 /* Add auxiliary station for scanning */
600 ret = iwl_mvm_add_aux_sta(mvm);
601 if (ret)
602 goto error;
603
604 return 0;
605 error:
606 iwl_trans_stop_device(mvm->trans);
607 return ret;
608}
609
610int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
611 struct iwl_rx_cmd_buffer *rxb,
612 struct iwl_device_cmd *cmd)
613{
614 struct iwl_rx_packet *pkt = rxb_addr(rxb);
615 struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
616 u32 flags = le32_to_cpu(card_state_notif->flags);
617
618 IWL_DEBUG_RF_KILL(mvm, "Card state received: HW:%s SW:%s CT:%s\n",
619 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
620 (flags & SW_CARD_DISABLED) ? "Kill" : "On",
621 (flags & CT_KILL_CARD_DISABLED) ?
622 "Reached" : "Not reached");
623
624 if (flags & CARD_DISABLED_MSK)
625 iwl_write32(mvm->trans, CSR_UCODE_DRV_GP1_SET,
626 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
627
628 return 0;
629}
630
631int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
632 struct iwl_device_cmd *cmd)
633{
634 struct iwl_rx_packet *pkt = rxb_addr(rxb);
635 struct iwl_radio_version_notif *radio_version = (void *)pkt->data;
636
637 /* TODO: what to do with that? */
638 IWL_DEBUG_INFO(mvm,
639 "Radio version: flavor: 0x%08x, step 0x%08x, dash 0x%08x\n",
640 le32_to_cpu(radio_version->radio_flavor),
641 le32_to_cpu(radio_version->radio_step),
642 le32_to_cpu(radio_version->radio_dash));
643 return 0;
644}