1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * nxpwifi: HW/FW initialization 4 * 5 * Copyright 2011-2024 NXP 6 */ 7 8 #include "cfg.h" 9 #include "util.h" 10 #include "fw.h" 11 #include "main.h" 12 #include "cmdevt.h" 13 #include "wmm.h" 14 #include "11n.h" 15 16 /* Add a BSS priority node to the adapter list. */ 17 static int nxpwifi_add_bss_prio_tbl(struct nxpwifi_private *priv) 18 { 19 struct nxpwifi_adapter *adapter = priv->adapter; 20 struct nxpwifi_bss_prio_node *bss_prio; 21 struct nxpwifi_bss_prio_tbl *tbl = adapter->bss_prio_tbl; 22 23 bss_prio = kzalloc_obj(*bss_prio, GFP_KERNEL); 24 if (!bss_prio) 25 return -ENOMEM; 26 27 bss_prio->priv = priv; 28 INIT_LIST_HEAD(&bss_prio->list); 29 30 spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock); 31 list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head); 32 spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock); 33 34 return 0; 35 } 36 37 static void wakeup_timer_fn(struct timer_list *t) 38 { 39 struct nxpwifi_adapter *adapter = timer_container_of(adapter, t, wakeup_timer); 40 41 nxpwifi_dbg(adapter, ERROR, "Firmware wakeup failed\n"); 42 adapter->hw_status = NXPWIFI_HW_STATUS_RESET; 43 nxpwifi_cancel_all_pending_cmd(adapter); 44 45 if (adapter->if_ops.card_reset) 46 adapter->if_ops.card_reset(adapter); 47 } 48 49 /* Initialize priv defaults and lists. */ 50 int nxpwifi_init_priv(struct nxpwifi_private *priv) 51 { 52 u32 i; 53 54 priv->media_connected = false; 55 eth_broadcast_addr(priv->curr_addr); 56 priv->port_open = false; 57 priv->usb_port = NXPWIFI_USB_EP_DATA; 58 priv->pkt_tx_ctrl = 0; 59 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; 60 priv->data_rate = 0; /* Initially indicate the rate as auto */ 61 priv->is_data_rate_auto = true; 62 priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; 63 priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; 64 65 priv->auth_flag = 0; 66 priv->auth_alg = WLAN_AUTH_NONE; 67 68 priv->sec_info.wep_enabled = 0; 69 priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; 70 priv->sec_info.encryption_mode = 0; 71 for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) 72 memset(&priv->wep_key[i], 0, sizeof(struct nxpwifi_wep_key)); 73 priv->wep_key_curr_index = 0; 74 priv->curr_pkt_filter = HOST_ACT_MAC_DYNAMIC_BW_ENABLE | 75 HOST_ACT_MAC_RX_ON | HOST_ACT_MAC_TX_ON | 76 HOST_ACT_MAC_ETHERNETII_ENABLE; 77 78 priv->beacon_period = 100; /* beacon interval */ 79 priv->attempted_bss_desc = NULL; 80 memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params)); 81 priv->listen_interval = NXPWIFI_DEFAULT_LISTEN_INTERVAL; 82 83 memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid)); 84 memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid)); 85 memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); 86 priv->assoc_rsp_size = 0; 87 priv->atim_window = 0; 88 priv->tx_power_level = 0; 89 priv->max_tx_power_level = 0; 90 priv->min_tx_power_level = 0; 91 priv->tx_ant = 0; 92 priv->rx_ant = 0; 93 priv->tx_rate = 0; 94 priv->rxpd_htinfo = 0; 95 priv->rxpd_rate = 0; 96 priv->rate_bitmap = 0; 97 priv->data_rssi_last = 0; 98 priv->data_rssi_avg = 0; 99 priv->data_nf_avg = 0; 100 priv->data_nf_last = 0; 101 priv->bcn_rssi_last = 0; 102 priv->bcn_rssi_avg = 0; 103 priv->bcn_nf_avg = 0; 104 priv->bcn_nf_last = 0; 105 memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie)); 106 memset(&priv->aes_key, 0, sizeof(priv->aes_key)); 107 priv->wpa_ie_len = 0; 108 priv->wpa_is_gtk_set = false; 109 110 memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf)); 111 priv->assoc_tlv_buf_len = 0; 112 memset(&priv->wps, 0, sizeof(priv->wps)); 113 memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); 114 priv->gen_ie_buf_len = 0; 115 memset(priv->vs_ie, 0, sizeof(priv->vs_ie)); 116 117 priv->wmm_required = true; 118 priv->wmm_enabled = false; 119 priv->wmm_qosinfo = 0; 120 priv->curr_bcn_buf = NULL; 121 priv->curr_bcn_size = 0; 122 priv->wps_ie = NULL; 123 priv->wps_ie_len = 0; 124 priv->ap_11n_enabled = 0; 125 memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); 126 127 priv->scan_block = false; 128 129 priv->csa_chan = 0; 130 priv->csa_expire_time = 0; 131 priv->del_list_idx = 0; 132 priv->hs2_enabled = false; 133 nxpwifi_wmm_init_tos_to_tid_inv(priv); 134 135 nxpwifi_init_11h_params(priv); 136 137 return nxpwifi_add_bss_prio_tbl(priv); 138 } 139 140 /* Allocate command buffer and sleep-confirm skb. */ 141 static int nxpwifi_allocate_adapter(struct nxpwifi_adapter *adapter) 142 { 143 int ret; 144 145 /* Allocate command buffer */ 146 ret = nxpwifi_alloc_cmd_buffer(adapter); 147 if (ret) { 148 nxpwifi_dbg(adapter, ERROR, 149 "%s: failed to alloc cmd buffer\n", 150 __func__); 151 return ret; 152 } 153 154 adapter->sleep_cfm = 155 dev_alloc_skb(sizeof(struct nxpwifi_opt_sleep_confirm) 156 + INTF_HEADER_LEN); 157 158 if (!adapter->sleep_cfm) { 159 nxpwifi_dbg(adapter, ERROR, 160 "%s: failed to alloc sleep cfm\t" 161 " cmd buffer\n", __func__); 162 return -ENOMEM; 163 } 164 skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN); 165 166 return 0; 167 } 168 169 /* Initialize adapter defaults and WMM parameters. */ 170 static void nxpwifi_init_adapter(struct nxpwifi_adapter *adapter) 171 { 172 struct nxpwifi_opt_sleep_confirm *sleep_cfm_buf = NULL; 173 174 skb_put(adapter->sleep_cfm, sizeof(struct nxpwifi_opt_sleep_confirm)); 175 176 adapter->cmd_sent = false; 177 adapter->data_sent = true; 178 179 adapter->intf_hdr_len = INTF_HEADER_LEN; 180 181 adapter->cmd_resp_received = false; 182 adapter->event_received = false; 183 adapter->data_received = false; 184 adapter->assoc_resp_received = false; 185 adapter->priv_link_lost = NULL; 186 adapter->host_mlme_link_lost = false; 187 188 clear_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags); 189 190 adapter->hw_status = NXPWIFI_HW_STATUS_INITIALIZING; 191 192 adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_CAM; 193 adapter->ps_state = PS_STATE_AWAKE; 194 adapter->need_to_wakeup = false; 195 196 adapter->scan_mode = HOST_BSS_MODE_ANY; 197 adapter->specific_scan_time = NXPWIFI_SPECIFIC_SCAN_CHAN_TIME; 198 adapter->active_scan_time = NXPWIFI_ACTIVE_SCAN_CHAN_TIME; 199 adapter->passive_scan_time = NXPWIFI_PASSIVE_SCAN_CHAN_TIME; 200 adapter->scan_chan_gap_time = NXPWIFI_DEF_SCAN_CHAN_GAP_TIME; 201 202 adapter->scan_probes = 1; 203 204 adapter->multiple_dtim = 1; 205 206 /* default value in firmware will be used */ 207 adapter->local_listen_interval = 0; 208 209 adapter->is_deep_sleep = false; 210 211 adapter->delay_null_pkt = false; 212 adapter->delay_to_ps = 1000; 213 adapter->enhanced_ps_mode = PS_MODE_AUTO; 214 215 /* Disable NULL Pkg generation by default */ 216 adapter->gen_null_pkt = false; 217 /* Disable pps/uapsd mode by default */ 218 adapter->pps_uapsd_mode = false; 219 adapter->pm_wakeup_card_req = false; 220 221 adapter->pm_wakeup_fw_try = false; 222 223 adapter->curr_tx_buf_size = NXPWIFI_TX_DATA_BUF_SIZE_2K; 224 225 clear_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); 226 adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF); 227 adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF; 228 adapter->hs_cfg.gap = HS_CFG_GAP_DEF; 229 adapter->hs_activated = false; 230 231 memset(adapter->event_body, 0, sizeof(adapter->event_body)); 232 adapter->hw_dot_11n_dev_cap = 0; 233 adapter->hw_dev_mcs_support = 0; 234 adapter->sec_chan_offset = 0; 235 236 nxpwifi_wmm_init(adapter); 237 atomic_set(&adapter->tx_hw_pending, 0); 238 239 sleep_cfm_buf = (struct nxpwifi_opt_sleep_confirm *) 240 adapter->sleep_cfm->data; 241 memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); 242 sleep_cfm_buf->command = cpu_to_le16(HOST_CMD_802_11_PS_MODE_ENH); 243 sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len); 244 sleep_cfm_buf->result = 0; 245 sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); 246 sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); 247 248 memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); 249 adapter->tx_lock_flag = false; 250 adapter->null_pkt_interval = 0; 251 adapter->fw_bands = 0; 252 adapter->fw_release_number = 0; 253 adapter->fw_cap_info = 0; 254 memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); 255 adapter->event_cause = 0; 256 adapter->region_code = 0; 257 adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; 258 memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); 259 adapter->arp_filter_size = 0; 260 adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; 261 adapter->key_api_major_ver = 0; 262 adapter->key_api_minor_ver = 0; 263 eth_broadcast_addr(adapter->perm_addr); 264 adapter->iface_limit.sta_intf = NXPWIFI_MAX_STA_NUM; 265 adapter->iface_limit.uap_intf = NXPWIFI_MAX_UAP_NUM; 266 adapter->active_scan_triggered = false; 267 timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0); 268 adapter->devdump_len = 0; 269 memset(&adapter->vdll_ctrl, 0, sizeof(adapter->vdll_ctrl)); 270 adapter->vdll_ctrl.skb = dev_alloc_skb(NXPWIFI_SIZE_OF_CMD_BUFFER); 271 atomic_set(&adapter->iface_changing, 0); 272 } 273 274 /* Update trans_start for each Tx queue. */ 275 void nxpwifi_set_trans_start(struct net_device *dev) 276 { 277 int i; 278 279 for (i = 0; i < dev->num_tx_queues; i++) 280 txq_trans_cond_update(netdev_get_tx_queue(dev, i)); 281 282 netif_trans_update(dev); 283 } 284 285 /* Wake all netdev Tx queues. */ 286 void nxpwifi_wake_up_net_dev_queue(struct net_device *netdev, 287 struct nxpwifi_adapter *adapter) 288 { 289 spin_lock_bh(&adapter->queue_lock); 290 netif_tx_wake_all_queues(netdev); 291 spin_unlock_bh(&adapter->queue_lock); 292 } 293 294 /* Stop all netdev Tx queues. */ 295 void nxpwifi_stop_net_dev_queue(struct net_device *netdev, 296 struct nxpwifi_adapter *adapter) 297 { 298 spin_lock_bh(&adapter->queue_lock); 299 netif_tx_stop_all_queues(netdev); 300 spin_unlock_bh(&adapter->queue_lock); 301 } 302 303 /* Invalidate list heads. */ 304 static void nxpwifi_invalidate_lists(struct nxpwifi_adapter *adapter) 305 { 306 struct nxpwifi_private *priv; 307 s32 i, j; 308 309 list_del(&adapter->cmd_free_q); 310 list_del(&adapter->cmd_pending_q); 311 list_del(&adapter->scan_pending_q); 312 313 for (i = 0; i < adapter->priv_num; i++) 314 list_del(&adapter->bss_prio_tbl[i].bss_prio_head); 315 316 for (i = 0; i < adapter->priv_num; i++) { 317 priv = adapter->priv[i]; 318 for (j = 0; j < MAX_NUM_TID; ++j) { 319 list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); 320 list_del(&priv->tx_ba_stream_tbl_ptr[j]); 321 list_del(&priv->rx_reorder_tbl_ptr[j]); 322 } 323 list_del(&priv->sta_list); 324 } 325 } 326 327 /* Cancel pending work, stop timers, and free adapter buffers. */ 328 static void 329 nxpwifi_adapter_cleanup(struct nxpwifi_adapter *adapter) 330 { 331 timer_delete(&adapter->wakeup_timer); 332 nxpwifi_cancel_all_pending_cmd(adapter); 333 wake_up_interruptible(&adapter->cmd_wait_q.wait); 334 wake_up_interruptible(&adapter->hs_activate_wait_q); 335 if (adapter->vdll_ctrl.vdll_mem) { 336 vfree(adapter->vdll_ctrl.vdll_mem); 337 adapter->vdll_ctrl.vdll_mem = NULL; 338 adapter->vdll_ctrl.vdll_len = 0; 339 } 340 if (adapter->vdll_ctrl.skb) { 341 dev_kfree_skb_any(adapter->vdll_ctrl.skb); 342 adapter->vdll_ctrl.skb = NULL; 343 } 344 } 345 346 void nxpwifi_free_cmd_buffers(struct nxpwifi_adapter *adapter) 347 { 348 nxpwifi_invalidate_lists(adapter); 349 350 /* Free command buffer */ 351 nxpwifi_dbg(adapter, INFO, "info: free cmd buffer\n"); 352 nxpwifi_free_cmd_buffer(adapter); 353 354 if (adapter->sleep_cfm) 355 dev_kfree_skb_any(adapter->sleep_cfm); 356 } 357 358 /* Initialize locks and list heads. */ 359 void nxpwifi_init_lock_list(struct nxpwifi_adapter *adapter) 360 { 361 struct nxpwifi_private *priv; 362 s32 i, j; 363 364 spin_lock_init(&adapter->int_lock); 365 spin_lock_init(&adapter->nxpwifi_cmd_lock); 366 spin_lock_init(&adapter->queue_lock); 367 for (i = 0; i < adapter->priv_num; i++) { 368 priv = adapter->priv[i]; 369 spin_lock_init(&priv->wmm.ra_list_spinlock); 370 spin_lock_init(&priv->curr_bcn_buf_lock); 371 spin_lock_init(&priv->sta_list_spinlock); 372 } 373 374 /* Initialize cmd_free_q */ 375 INIT_LIST_HEAD(&adapter->cmd_free_q); 376 /* Initialize cmd_pending_q */ 377 INIT_LIST_HEAD(&adapter->cmd_pending_q); 378 /* Initialize scan_pending_q */ 379 INIT_LIST_HEAD(&adapter->scan_pending_q); 380 381 spin_lock_init(&adapter->cmd_free_q_lock); 382 spin_lock_init(&adapter->cmd_pending_q_lock); 383 spin_lock_init(&adapter->scan_pending_q_lock); 384 385 skb_queue_head_init(&adapter->rx_mlme_q); 386 skb_queue_head_init(&adapter->rx_data_q); 387 skb_queue_head_init(&adapter->tx_data_q); 388 389 for (i = 0; i < adapter->priv_num; ++i) { 390 INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); 391 spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); 392 } 393 394 for (i = 0; i < adapter->priv_num; i++) { 395 priv = adapter->priv[i]; 396 for (j = 0; j < MAX_NUM_TID; ++j) { 397 INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); 398 INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr[j]); 399 INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr[j]); 400 spin_lock_init(&priv->tx_ba_stream_tbl_lock[j]); 401 spin_lock_init(&priv->rx_reorder_tbl_lock[j]); 402 } 403 INIT_LIST_HEAD(&priv->sta_list); 404 skb_queue_head_init(&priv->bypass_txq); 405 406 spin_lock_init(&priv->ack_status_lock); 407 xa_init_flags(&priv->ack_status_frames, XA_FLAGS_ALLOC); 408 } 409 } 410 411 /* Init firmware: alloc resources, init adapter/privs, send STA init. */ 412 int nxpwifi_init_fw(struct nxpwifi_adapter *adapter) 413 { 414 int ret; 415 struct nxpwifi_private *priv; 416 u8 i; 417 bool first_sta = true; 418 419 adapter->hw_status = NXPWIFI_HW_STATUS_INITIALIZING; 420 421 /* Allocate memory for member of adapter structure */ 422 ret = nxpwifi_allocate_adapter(adapter); 423 if (ret) 424 return ret; 425 426 /* Initialize adapter structure */ 427 nxpwifi_init_adapter(adapter); 428 429 for (i = 0; i < adapter->priv_num; i++) { 430 priv = adapter->priv[i]; 431 432 /* Initialize private structure */ 433 ret = nxpwifi_init_priv(priv); 434 if (ret) 435 return ret; 436 } 437 438 for (i = 0; i < adapter->priv_num; i++) { 439 ret = nxpwifi_sta_init_cmd(adapter->priv[i], 440 first_sta, true); 441 if (ret) 442 return ret; 443 444 first_sta = false; 445 } 446 spin_lock_bh(&adapter->cmd_pending_q_lock); 447 WARN_ON(!list_empty(&adapter->cmd_pending_q)); 448 spin_unlock_bh(&adapter->cmd_pending_q_lock); 449 adapter->hw_status = NXPWIFI_HW_STATUS_READY; 450 451 return 0; 452 } 453 454 /* Remove all BSS priority nodes for this priv. */ 455 static void nxpwifi_delete_bss_prio_tbl(struct nxpwifi_private *priv) 456 { 457 int i; 458 struct nxpwifi_adapter *adapter = priv->adapter; 459 struct nxpwifi_bss_prio_node *bssprio_node, *tmp_node; 460 struct list_head *head; 461 spinlock_t *lock; /* bss priority lock */ 462 463 for (i = 0; i < adapter->priv_num; ++i) { 464 head = &adapter->bss_prio_tbl[i].bss_prio_head; 465 lock = &adapter->bss_prio_tbl[i].bss_prio_lock; 466 nxpwifi_dbg(adapter, INFO, 467 "info: delete BSS priority table,\t" 468 "bss_type = %d, bss_num = %d, i = %d,\t" 469 "head = %p\n", 470 priv->bss_type, priv->bss_num, i, head); 471 472 { 473 spin_lock_bh(lock); 474 list_for_each_entry_safe(bssprio_node, tmp_node, head, 475 list) { 476 if (bssprio_node->priv == priv) { 477 nxpwifi_dbg(adapter, INFO, 478 "info: Delete\t" 479 "node %p, next = %p\n", 480 bssprio_node, tmp_node); 481 list_del(&bssprio_node->list); 482 kfree(bssprio_node); 483 } 484 } 485 spin_unlock_bh(lock); 486 } 487 } 488 } 489 490 /* Free per-priv resources and BSS priority entries. */ 491 void nxpwifi_free_priv(struct nxpwifi_private *priv) 492 { 493 nxpwifi_clean_txrx(priv); 494 nxpwifi_delete_bss_prio_tbl(priv); 495 nxpwifi_free_curr_bcn(priv); 496 } 497 498 /* Shutdown driver: stop work, drain queues, free resources. */ 499 void 500 nxpwifi_shutdown_drv(struct nxpwifi_adapter *adapter) 501 { 502 struct nxpwifi_private *priv; 503 s32 i; 504 struct sk_buff *skb; 505 506 /* nxpwifi already shutdown */ 507 if (adapter->hw_status == NXPWIFI_HW_STATUS_NOT_READY) 508 return; 509 510 /* cancel current command */ 511 if (adapter->curr_cmd) { 512 nxpwifi_dbg(adapter, WARN, 513 "curr_cmd is still in processing\n"); 514 timer_delete_sync(&adapter->cmd_timer); 515 nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); 516 adapter->curr_cmd = NULL; 517 } 518 519 /* shut down nxpwifi */ 520 nxpwifi_dbg(adapter, MSG, 521 "info: shutdown nxpwifi...\n"); 522 523 /* Clean up Tx/Rx queues and delete BSS priority table */ 524 for (i = 0; i < adapter->priv_num; i++) { 525 priv = adapter->priv[i]; 526 527 nxpwifi_abort_cac(priv); 528 nxpwifi_free_priv(priv); 529 } 530 531 atomic_set(&adapter->tx_queued, 0); 532 while ((skb = skb_dequeue(&adapter->tx_data_q))) 533 nxpwifi_write_data_complete(adapter, skb, 0, 0); 534 535 while ((skb = skb_dequeue(&adapter->rx_mlme_q))) 536 dev_kfree_skb_any(skb); 537 538 while ((skb = skb_dequeue(&adapter->rx_data_q))) { 539 struct nxpwifi_rxinfo *rx_info = NXPWIFI_SKB_RXCB(skb); 540 541 atomic_dec(&adapter->rx_pending); 542 priv = adapter->priv[rx_info->bss_num]; 543 if (priv) 544 priv->stats.rx_dropped++; 545 546 dev_kfree_skb_any(skb); 547 } 548 549 nxpwifi_adapter_cleanup(adapter); 550 551 adapter->hw_status = NXPWIFI_HW_STATUS_NOT_READY; 552 } 553 554 /* Download FW if needed; check winner and wait until ready. */ 555 int nxpwifi_dnld_fw(struct nxpwifi_adapter *adapter, 556 struct nxpwifi_fw_image *pmfw) 557 { 558 int ret; 559 u32 poll_num = 1; 560 561 /* check if firmware is already running */ 562 ret = adapter->if_ops.check_fw_status(adapter, poll_num); 563 if (!ret) { 564 nxpwifi_dbg(adapter, MSG, 565 "WLAN FW already running! Skip FW dnld\n"); 566 return 0; 567 } 568 569 /* check if we are the winner for downloading FW */ 570 if (adapter->if_ops.check_winner_status) { 571 adapter->winner = 0; 572 ret = adapter->if_ops.check_winner_status(adapter); 573 574 poll_num = MAX_FIRMWARE_POLL_TRIES; 575 if (ret) { 576 nxpwifi_dbg(adapter, MSG, 577 "WLAN read winner status failed!\n"); 578 return ret; 579 } 580 581 if (!adapter->winner) { 582 nxpwifi_dbg(adapter, MSG, 583 "WLAN is not the winner! Skip FW dnld\n"); 584 goto poll_fw; 585 } 586 } 587 588 if (pmfw) { 589 /* Download firmware with helper */ 590 ret = adapter->if_ops.prog_fw(adapter, pmfw); 591 if (ret) { 592 nxpwifi_dbg(adapter, ERROR, 593 "prog_fw failed ret=%#x\n", ret); 594 return ret; 595 } 596 } 597 598 poll_fw: 599 /* Check if the firmware is downloaded successfully or not */ 600 ret = adapter->if_ops.check_fw_status(adapter, poll_num); 601 if (ret) 602 nxpwifi_dbg(adapter, ERROR, 603 "FW failed to be active in time\n"); 604 605 return ret; 606 } 607 EXPORT_SYMBOL_GPL(nxpwifi_dnld_fw); 608