On Sat, Mar 25, 2017 at 02:49:20AM +0000, Adrian Chadd wrote:
> 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);
> +


cc -target x86_64-unknown-freebsd12.0 
--sysroot=/home/dchagin/obj/home/git/head/tmp 
-B/home/dchagin/obj/home/git/head/tmp/usr/bin -c -O2 -pipe -fno-strict-aliasing 
 -g -nostdinc  -I. -I/home/git/head/sys -I/home/git/head/sys/contrib/libfdt 
-D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h  
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -MD  
-MF.depend.if_iwm_scan.o -MTif_iwm_scan.o -mcmodel=kernel -mno-red-zone 
-mno-mmx -mno-sse -msoft-float  -fno-asynchronous-unwind-tables -ffreestanding 
-fwrapv -fstack-protector -gdwarf-2 -Wall -Wredundant-decls -Wnested-externs 
-Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual 
-Wundef -Wno-pointer-sign -D__printf__=__freebsd_kprintf__ 
-Wmissing-include-dirs -fdiagnostics-show-option -Wno-unknown-pragmas 
-Wno-error-tautological-compare -Wno-error-empty-body 
-Wno-error-parentheses-equality -Wno-error-unused-function 
-Wno-error-pointer-sign -Wno-error-shift-negative-value 
-Wno-error-address-of-packed-membe
 r  -mno-aes -mno-avx  -std=iso9899:1999 -Werror  
/home/git/head/sys/dev/iwm/if_iwm_scan.c
/home/git/head/sys/dev/iwm/if_iwm_scan.c:224:12: error: unused variable 
'aborted' [-Werror,-Wunused-variable]
        boolean_t aborted = (scan_notif->status == IWM_SCAN_OFFLOAD_ABORTED);
                  ^
/home/git/head/sys/dev/iwm/if_iwm_scan.c:252:12: error: unused variable 
'aborted' [-Werror,-Wunused-variable]
        boolean_t aborted = (notif->status == IWM_SCAN_OFFLOAD_ABORTED);
                  ^
/home/git/head/sys/dev/iwm/if_iwm_scan.c:251:11: error: unused variable 'uid' 
[-Werror,-Wunused-variable]
        uint32_t uid = le32toh(notif->uid);
                 ^
3 errors generated.










> +     /* 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) \

-- 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to