Date: Sat, 25 Mar 2017 02:49:20 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315925 - head/sys/dev/iwm Message-ID: <201703250249.v2P2nKJW038546@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Sat Mar 25 02:49:20 2017 New Revision: 315925 URL: https://svnweb.freebsd.org/changeset/base/315925 Log: [iwm] Enable Energy Based Scan (EBS). This can significantly reduce scan duration thus saving time and power. EBS failure reported by FW disables EBS for current connection. It is re-enabled upon new connection attempt on any WLAN interface. Obtained from: dragonflybsd.git 89f579e9823a5c446ca172cf82bbc210d6a054a4 Modified: head/sys/dev/iwm/if_iwm.c head/sys/dev/iwm/if_iwm_scan.c head/sys/dev/iwm/if_iwm_scan.h head/sys/dev/iwm/if_iwmreg.h head/sys/dev/iwm/if_iwmvar.h Modified: head/sys/dev/iwm/if_iwm.c ============================================================================== --- head/sys/dev/iwm/if_iwm.c Sat Mar 25 02:44:25 2017 (r315924) +++ head/sys/dev/iwm/if_iwm.c Sat Mar 25 02:49:20 2017 (r315925) @@ -4518,6 +4518,11 @@ iwm_newstate(struct ieee80211vap *vap, e break; case IEEE80211_S_ASSOC: + /* + * EBS may be disabled due to previous failures reported by FW. + * Reset EBS status here assuming environment has been changed. + */ + sc->last_ebs_successful = TRUE; if ((error = iwm_assoc(vap, sc)) != 0) { device_printf(sc->sc_dev, "%s: failed to associate: %d\n", __func__, @@ -5525,36 +5530,27 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_INIT_COMPLETE_NOTIF: break; - case IWM_SCAN_OFFLOAD_COMPLETE: { - struct iwm_periodic_scan_complete *notif; - notif = (void *)pkt->data; + case IWM_SCAN_OFFLOAD_COMPLETE: + iwm_mvm_rx_lmac_scan_complete_notif(sc, pkt); if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) { sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING; ieee80211_runtask(ic, &sc->sc_es_task); } break; - } case IWM_SCAN_ITERATION_COMPLETE: { struct iwm_lmac_scan_complete_notif *notif; notif = (void *)pkt->data; - ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task); - break; + break; } - - case IWM_SCAN_COMPLETE_UMAC: { - struct iwm_umac_scan_complete *notif; - notif = (void *)pkt->data; - IWM_DPRINTF(sc, IWM_DEBUG_SCAN, - "UMAC scan complete, status=0x%x\n", - notif->status); + case IWM_SCAN_COMPLETE_UMAC: + iwm_mvm_rx_umac_scan_complete_notif(sc, pkt); if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) { sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING; ieee80211_runtask(ic, &sc->sc_es_task); } break; - } case IWM_SCAN_ITERATION_COMPLETE_UMAC: { struct iwm_umac_scan_iter_complete_notif *notif; @@ -5563,7 +5559,6 @@ iwm_notif_intr(struct iwm_softc *sc) IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "UMAC scan iteration " "complete, status=0x%x, %d channels scanned\n", notif->status, notif->scanned_channels); - ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task); break; } @@ -5967,6 +5962,9 @@ iwm_attach(device_t dev) goto fail; } + /* Set EBS as successful as long as not stated otherwise by the FW. */ + sc->last_ebs_successful = TRUE; + /* PCI attach */ error = iwm_pci_attach(dev); if (error != 0) Modified: head/sys/dev/iwm/if_iwm_scan.c ============================================================================== --- head/sys/dev/iwm/if_iwm_scan.c Sat Mar 25 02:44:25 2017 (r315924) +++ head/sys/dev/iwm/if_iwm_scan.c Sat Mar 25 02:49:20 2017 (r315925) @@ -161,6 +161,9 @@ __FBSDID("$FreeBSD$"); * BEGIN mvm/scan.c */ +#define IWM_DENSE_EBS_SCAN_RATIO 5 +#define IWM_SPARSE_EBS_SCAN_RATIO 1 + static uint16_t iwm_mvm_scan_rx_chain(struct iwm_softc *sc) { @@ -198,6 +201,67 @@ iwm_mvm_scan_rate_n_flags(struct iwm_sof return htole32(IWM_RATE_6M_PLCP | tx_ant); } +static const char * +iwm_mvm_ebs_status_str(enum iwm_scan_ebs_status status) +{ + switch (status) { + case IWM_SCAN_EBS_SUCCESS: + return "successful"; + case IWM_SCAN_EBS_INACTIVE: + return "inactive"; + case IWM_SCAN_EBS_FAILED: + case IWM_SCAN_EBS_CHAN_NOT_FOUND: + default: + return "failed"; + } +} + +void +iwm_mvm_rx_lmac_scan_complete_notif(struct iwm_softc *sc, + struct iwm_rx_packet *pkt) +{ + struct iwm_periodic_scan_complete *scan_notif = (void *)pkt->data; + boolean_t aborted = (scan_notif->status == IWM_SCAN_OFFLOAD_ABORTED); + + /* If this happens, the firmware has mistakenly sent an LMAC + * notification during UMAC scans -- warn and ignore it. + */ + if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) { + device_printf(sc->sc_dev, + "%s: Mistakenly got LMAC notification during UMAC scan\n", + __func__); + return; + } + + IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Regular scan %s, EBS status %s (FW)\n", + aborted ? "aborted" : "completed", + iwm_mvm_ebs_status_str(scan_notif->ebs_status)); + + sc->last_ebs_successful = + scan_notif->ebs_status == IWM_SCAN_EBS_SUCCESS || + scan_notif->ebs_status == IWM_SCAN_EBS_INACTIVE; + +} + +void +iwm_mvm_rx_umac_scan_complete_notif(struct iwm_softc *sc, + struct iwm_rx_packet *pkt) +{ + struct iwm_umac_scan_complete *notif = (void *)pkt->data; + uint32_t uid = le32toh(notif->uid); + boolean_t aborted = (notif->status == IWM_SCAN_OFFLOAD_ABORTED); + + IWM_DPRINTF(sc, IWM_DEBUG_SCAN, + "Scan completed, uid %u, status %s, EBS status %s\n", + uid, + aborted ? "aborted" : "completed", + iwm_mvm_ebs_status_str(notif->ebs_status)); + + if (notif->ebs_status != IWM_SCAN_EBS_SUCCESS && + notif->ebs_status != IWM_SCAN_EBS_INACTIVE) + sc->last_ebs_successful = FALSE; +} + static int iwm_mvm_scan_skip_channel(struct ieee80211_channel *c) { @@ -480,6 +544,21 @@ iwm_mvm_config_umac_scan(struct iwm_soft return ret; } +static boolean_t +iwm_mvm_scan_use_ebs(struct iwm_softc *sc) +{ + const struct iwm_ucode_capabilities *capa = &sc->ucode_capa; + + /* We can only use EBS if: + * 1. the feature is supported; + * 2. the last EBS was successful; + * 3. if only single scan, the single scan EBS API is supported; + * 4. it's not a p2p find operation. + */ + return ((capa->flags & IWM_UCODE_TLV_FLAGS_EBS_SUPPORT) && + sc->last_ebs_successful); +} + int iwm_mvm_umac_scan(struct iwm_softc *sc) { @@ -549,6 +628,11 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) } else req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE); + if (iwm_mvm_scan_use_ebs(sc)) + req->channel_flags = IWM_SCAN_CHANNEL_FLAG_EBS | + IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE | + IWM_SCAN_CHANNEL_FLAG_CACHE_ADD; + if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) req->general_flags |= @@ -674,9 +758,20 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc) req->schedule[0].iterations = 1; req->schedule[0].full_scan_mul = 1; - /* Disable EBS. */ - req->channel_opt[0].non_ebs_ratio = 1; - req->channel_opt[1].non_ebs_ratio = 1; + if (iwm_mvm_scan_use_ebs(sc)) { + req->channel_opt[0].flags = + htole16(IWM_SCAN_CHANNEL_FLAG_EBS | + IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE | + IWM_SCAN_CHANNEL_FLAG_CACHE_ADD); + req->channel_opt[0].non_ebs_ratio = + htole16(IWM_DENSE_EBS_SCAN_RATIO); + req->channel_opt[1].flags = + htole16(IWM_SCAN_CHANNEL_FLAG_EBS | + IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE | + IWM_SCAN_CHANNEL_FLAG_CACHE_ADD); + req->channel_opt[1].non_ebs_ratio = + htole16(IWM_SPARSE_EBS_SCAN_RATIO); + } ret = iwm_send_cmd(sc, &hcmd); if (!ret) { Modified: head/sys/dev/iwm/if_iwm_scan.h ============================================================================== --- head/sys/dev/iwm/if_iwm_scan.h Sat Mar 25 02:44:25 2017 (r315924) +++ head/sys/dev/iwm/if_iwm_scan.h Sat Mar 25 02:49:20 2017 (r315925) @@ -106,9 +106,13 @@ #ifndef __IF_IWN_SCAN_H__ #define __IF_IWN_SCAN_H__ -extern int iwm_mvm_lmac_scan(struct iwm_softc *sc); +extern int iwm_mvm_lmac_scan(struct iwm_softc *); extern int iwm_mvm_config_umac_scan(struct iwm_softc *); extern int iwm_mvm_umac_scan(struct iwm_softc *); -extern int iwm_mvm_scan_stop_wait(struct iwm_softc *sc); +extern int iwm_mvm_scan_stop_wait(struct iwm_softc *); +extern void iwm_mvm_rx_lmac_scan_complete_notif(struct iwm_softc *, + struct iwm_rx_packet *); +extern void iwm_mvm_rx_umac_scan_complete_notif(struct iwm_softc *, + struct iwm_rx_packet *); #endif /* __IF_IWN_SCAN_H__ */ Modified: head/sys/dev/iwm/if_iwmreg.h ============================================================================== --- head/sys/dev/iwm/if_iwmreg.h Sat Mar 25 02:44:25 2017 (r315924) +++ head/sys/dev/iwm/if_iwmreg.h Sat Mar 25 02:49:20 2017 (r315925) @@ -5076,6 +5076,13 @@ enum iwm_scan_offload_complete_status { IWM_SCAN_OFFLOAD_ABORTED = 2, }; +enum iwm_scan_ebs_status { + IWM_SCAN_EBS_SUCCESS, + IWM_SCAN_EBS_FAILED, + IWM_SCAN_EBS_CHAN_NOT_FOUND, + IWM_SCAN_EBS_INACTIVE, +}; + /** * struct iwm_lmac_scan_complete_notif - notifies end of scanning (all channels) * SCAN_COMPLETE_NTF_API_S_VER_3 Modified: head/sys/dev/iwm/if_iwmvar.h ============================================================================== --- head/sys/dev/iwm/if_iwmvar.h Sat Mar 25 02:44:25 2017 (r315924) +++ head/sys/dev/iwm/if_iwmvar.h Sat Mar 25 02:49:20 2017 (r315925) @@ -536,6 +536,8 @@ struct iwm_softc { struct iwm_fw_paging fw_paging_db[IWM_NUM_OF_FW_PAGING_BLOCKS]; uint16_t num_of_paging_blk; uint16_t num_of_pages_in_last_blk; + + boolean_t last_ebs_successful; }; #define IWM_LOCK_INIT(_sc) \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703250249.v2P2nKJW038546>