void wl1271_scan_complete_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; int ret; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, scan_complete_work); wl1271_debug(DEBUG_SCAN, "Scanning complete"); mutex_lock(&wl->mutex); if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; if (wl->scan.state == WL1271_SCAN_STATE_IDLE) goto out; vif = wl->scan_vif; wlvif = wl12xx_vif_to_data(vif); /* * Rearm the tx watchdog just before idling scan. This * prevents just-finished scans from triggering the watchdog */ wl12xx_rearm_tx_watchdog_locked(wl); wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; wl->scan_vif = NULL; ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { /* restore hardware connection monitoring template */ wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); } wl1271_ps_elp_sleep(wl); if (wl->scan.failed) { wl1271_info("Scan completed due to error."); wl12xx_queue_recovery_work(wl); } wlcore_cmd_regdomain_config_locked(wl); ieee80211_scan_completed(wl->hw, false); out: mutex_unlock(&wl->mutex); }
int wl1271_hw_init(struct wl1271 *wl) { int ret; /* Chip-specific hw init */ ret = wl->ops->hw_init(wl); if (ret < 0) return ret; /* Init templates */ ret = wl1271_init_templates_config(wl); if (ret < 0) return ret; ret = wl12xx_acx_mem_cfg(wl); if (ret < 0) return ret; /* Configure the FW logger */ ret = wl12xx_init_fwlog(wl); if (ret < 0) return ret; ret = wlcore_cmd_regdomain_config_locked(wl); if (ret < 0) return ret; /* Bluetooth WLAN coexistence */ ret = wl1271_init_pta(wl); if (ret < 0) return ret; /* Default memory configuration */ ret = wl1271_acx_init_mem_config(wl); if (ret < 0) return ret; /* RX config */ ret = wl12xx_init_rx_config(wl); if (ret < 0) goto out_free_memmap; ret = wl1271_acx_dco_itrim_params(wl); if (ret < 0) goto out_free_memmap; /* Configure TX patch complete interrupt behavior */ ret = wl1271_acx_tx_config_options(wl); if (ret < 0) goto out_free_memmap; /* RX complete interrupt pacing */ ret = wl1271_acx_init_rx_interrupt(wl); if (ret < 0) goto out_free_memmap; /* Energy detection */ ret = wl1271_init_energy_detection(wl); if (ret < 0) goto out_free_memmap; /* Default fragmentation threshold */ ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold); if (ret < 0) goto out_free_memmap; /* Enable data path */ ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) goto out_free_memmap; /* configure PM */ ret = wl1271_acx_pm_config(wl); if (ret < 0) goto out_free_memmap; ret = wl12xx_acx_set_rate_mgmt_params(wl); if (ret < 0) goto out_free_memmap; /* configure hangover */ ret = wl12xx_acx_config_hangover(wl); if (ret < 0) goto out_free_memmap; return 0; out_free_memmap: kfree(wl->target_mem_map); wl->target_mem_map = NULL; return ret; }