/* * PHY module Power-per-rate API. Provides interface functions and definitions for opaque * ppr structure for use containing regulatory and board limits and tx power targets. * * Copyright (C) 2015, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; * the contents of this file may not be disclosed to third parties, copied * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * * $Id: $ */ #ifndef _wlc_ppr_h_ #define _wlc_ppr_h_ #include #include #ifdef BCMDRIVER #include #else #define osl_t void #endif /* Helper macro */ #define PPR_CHSPEC_BW(x) (CHSPEC_IS80(x) ? WL_TX_BW_80 : \ (CHSPEC_IS40(x) ? WL_TX_BW_40 : WL_TX_BW_20)) #ifndef BCMPHYCORENUM #define PPR_MAX_TX_CHAINS 3 #else #if (BCMPHYCORENUM < 1) || (BCMPHYCORENUM > 3) #error Invalid number of PHY cores #endif /* BCMPHYCORENUM < 1 || BCMPHYCORENUM > 3 */ #define PPR_MAX_TX_CHAINS (BCMPHYCORENUM) #endif /* !defined(BCMPHYCORENUM) */ /* Opaque PPR data - it keeps its structure to itself */ typedef struct ppr ppr_t; /* Power values for DSSS 1, 2, 5.5, 11 */ typedef struct ppr_dsss_rateset { int8 pwr[WL_RATESET_SZ_DSSS]; } ppr_dsss_rateset_t; /* Power values for OFDM 6, 9, 12... 54 */ typedef struct ppr_ofdm_rateset { int8 pwr[WL_RATESET_SZ_OFDM]; } ppr_ofdm_rateset_t; /* Power values one set of 8 HT MCS values (0-7, 8-15, etc) */ typedef struct ppr_ht_mcs_rateset { int8 pwr[WL_RATESET_SZ_HT_MCS]; } ppr_ht_mcs_rateset_t; /* Power values one set of 10 VHT MCS values (0-9) */ typedef struct ppr_vht_mcs_rateset { int8 pwr[WL_RATESET_SZ_VHT_MCS]; } ppr_vht_mcs_rateset_t; /* API Routines */ /* Initialization routine for opaque PPR struct */ void ppr_init(ppr_t* pprptr, wl_tx_bw_t bw); /* Reinitialization routine for opaque PPR struct */ void ppr_clear(ppr_t* pprptr); /* Size routine for user alloc/dealloc */ uint32 ppr_size(wl_tx_bw_t bw); /* Size routine for user serialization alloc */ uint32 ppr_ser_size(const ppr_t* pprptr); /* Size routine for user serialization alloc for a given bw */ uint32 ppr_ser_size_by_bw(wl_tx_bw_t bw); /* Init allocated memory with a ppr serialization head * This function must be called if serialization side has different * compilation conditions (e.g PPR_MAX_TX_CHAINS, WL_BEAMFORMING etc.) */ int ppr_init_ser_mem_by_bw(uint8* pbuf, wl_tx_bw_t bw, uint32 len); /* Init allocated memory with a ppr serialization head for the given ppr pointer * This function must be called if serialization side has different * compilation conditions (e.g PPR_MAX_TX_CHAINS, WL_BEAMFORMING etc.) */ int ppr_init_ser_mem(uint8* pbuf, ppr_t * ppr, uint32 len); /* Constructor routine for opaque PPR struct */ ppr_t* ppr_create(osl_t *osh, wl_tx_bw_t bw); /* Destructor routine for opaque PPR struct */ void ppr_delete(osl_t *osh, ppr_t* pprptr); /* Type routine for inferring opaque structure size */ wl_tx_bw_t ppr_get_ch_bw(const ppr_t* pprptr); /* Type routine to get ppr supported maximum bw */ wl_tx_bw_t ppr_get_max_bw(void); /* Get the DSSS values for the given number of tx_chains and 20, 20in40, etc. */ int ppr_get_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, ppr_dsss_rateset_t* dsss); /* Get the OFDM values for the given number of tx_chains and 20, 20in40, etc. */ int ppr_get_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, ppr_ofdm_rateset_t* ofdm); /* Get the HT MCS values for the group specified by Nss, with the given bw and tx chains */ int ppr_get_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, ppr_ht_mcs_rateset_t* mcs); /* Get the VHT MCS values for the group specified by Nss, with the given bw and tx chains */ int ppr_get_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, ppr_vht_mcs_rateset_t* mcs); /* Routines to set target powers per rate for a whole rate set */ /* Set the DSSS values for the given number of tx_chains and 20, 20in40, etc. */ int ppr_set_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, const ppr_dsss_rateset_t* dsss); /* Set the OFDM values for the given number of tx_chains and 20, 20in40, etc. */ int ppr_set_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, const ppr_ofdm_rateset_t* ofdm); /* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */ int ppr_set_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, const ppr_ht_mcs_rateset_t* mcs); /* Set the VHT MCS values for the group specified by Nss, with the given bw and tx chains */ int ppr_set_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, const ppr_vht_mcs_rateset_t* mcs); /* Routines to set a whole rate set to a single target value */ /* Set the DSSS values for the given number of tx_chains and 20, 20in40, etc. */ int ppr_set_same_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, const int8 power); /* Set the OFDM values for the given number of tx_chains and 20, 20in40, etc. */ int ppr_set_same_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, const int8 power); /* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */ int ppr_set_same_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, const int8 power); /* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */ int ppr_set_same_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains, const int8 power); /* Helper routines to operate on the entire ppr set */ /* Ensure no rate limit is greater than the specified maximum */ uint ppr_apply_max(ppr_t* pprptr, int8 max); /* * Reduce total transmitted power to level of constraint. * For two chain rates, the per-antenna power must be halved. * For three chain rates, it must be a third of the constraint. */ uint ppr_apply_constraint_total_tx(ppr_t* pprptr, int8 constraint); /* Ensure no rate limit is lower than the specified minimum */ uint ppr_apply_min(ppr_t* pprptr, int8 min); /* Ensure no rate limit in this ppr set is greater than the corresponding limit in ppr_cap */ uint ppr_apply_vector_ceiling(ppr_t* pprptr, const ppr_t* ppr_cap); /* Ensure no rate limit in this ppr set is lower than the corresponding limit in ppr_min */ uint ppr_apply_vector_floor(ppr_t* pprptr, const ppr_t* ppr_min); /* Get the maximum power in the ppr set */ int8 ppr_get_max(ppr_t* pprptr); /* * Get the minimum power in the ppr set excluding disallowed * rates and powers set to the minimum for the phy */ int8 ppr_get_min(ppr_t* pprptr, int8 floor); /* Get the maximum power for a given bandwidth in the ppr set */ int8 ppr_get_max_for_bw(ppr_t* pprptr, wl_tx_bw_t bw); /* Get the minimum power for a given bandwidth in the ppr set */ int8 ppr_get_min_for_bw(ppr_t* pprptr, wl_tx_bw_t bw); typedef void (*ppr_mapfn_t)(void *context, uint8 *a, uint8 *b); /* Map the given function with its context value over the two power vectors */ void ppr_map_vec_dsss(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_chains_t tx_chains); /* Map the given function with its context value over the two power vectors */ void ppr_map_vec_ofdm(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains); /* Map the given function with its context value over the two power vectors */ void ppr_map_vec_ht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains); /* Map the given function with its context value over the two power vectors */ void ppr_map_vec_vht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t tx_chains); /* Map the given function with its context value over the two power vectors */ void ppr_map_vec_all(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2); /* Get the first index that is larger than a given power level */ int16 ppr_get_idx(ppr_t* pprptr, int8 pwr); /* Set PPR struct to a certain power level */ void ppr_set_cmn_val(ppr_t* pprptr, int8 val); /* Make an identical copy of a ppr structure (for ppr_bw==all case) */ void ppr_copy_struct(ppr_t* pprptr_s, ppr_t* pprptr_d); /* Subtract each power from a common value and re-store */ void ppr_cmn_val_minus(ppr_t* pprptr, int8 val); /* Compare two ppr variables p1 and p2, save the min. value of each * contents to variable p1 */ void ppr_compare_min(ppr_t* p1, ppr_t* p2); /* compare two ppr variables p1 and p2, save the max. value of each * contents to variable p1 */ void ppr_compare_max(ppr_t* p1, ppr_t* p2); /* Serialize the contents of the opaque ppr struct. * Writes number of bytes copied, zero on error. * Returns error code, BCME_OK if successful. */ int ppr_serialize(const ppr_t* pprptr, uint8* buf, uint buflen, uint* bytes_copied); /* Deserialize the contents of a buffer into an existing opaque ppr struct. * The ppr struct *must* be of the same type as the one that was serialized. * Returns error code, BCME_OK if successful. */ int ppr_deserialize(ppr_t* pprptr, const uint8* buf, uint buflen); /* Deserialize the contents of a buffer into a new opaque ppr struct. * Creates an opaque structure referenced by *pptrptr, NULL on error. * Returns error code, BCME_OK if successful. */ int ppr_deserialize_create(osl_t *osh, const uint8* buf, uint buflen, ppr_t** pprptr); /* Subtract a common value from each power and re-store */ void ppr_minus_cmn_val(ppr_t* pprptr, int8 val); /* Add a common value to the given bw struct components */ void ppr_plus_cmn_val(ppr_t* pprptr, int8 val); /* Multiply a percentage */ void ppr_multiply_percentage(ppr_t* pprptr, uint8 val); #ifdef WLTXPWR_CACHE /** * Usage of the WLTXPWR_CACHE API: * 1. Reserve one or more entries in the cache for a specific chanspec: * wlc_phy_txpwr_setup_entry(chanspec1); * wlc_phy_txpwr_setup_entry(chanspec2); * 2. Use any of the getter/setter functions. Note that they may return an error on a chanspec * that was not reserved. For setter functions, for pointer type arguments (e.g. ppr_t), the * cache maintains a reference to the caller provided object rather than copying it. * 3. Use wlc_phy_txpwr_cache_clear() or wlc_phy_txpwr_cache_invalidate() to get rid of cache * entries. Note that this clears, amongst others, ppr_t structs. * * For non-BMAC builds, only the cache is allowed to delete the ppr_t object, and the driver code is * not allowed to reuse it for another channel as it can when the cache is not being used. * * For BMAC builds, the cache has to be made to release the stf offsets object to avoid some nasty * race conditions. * * Mike thinks when this is reimplemented for trunk he would consider having a reference count * associated with each object to make this cleaner. * * Note that the functions start with wlc_phy_* despite not residing in the PHY code. This is * probably for historical reasons. */ enum txpwr_cache_info_type { TXPWR_CACHE_STF_OFFSETS, /* PPR offsets for stf */ TXPWR_CACHE_POWER_OFFSETS, /* PPR offsets for phy */ TXPWR_CACHE_NUM_TYPES, /* How many types of pwr info */ }; #define TXPWR_STF_PWR_MIN_INVALID 0x80 #define TXPWR_STF_TARGET_PWR_MIN_INVALID 0x40 #define TXPWR_STF_TARGET_PWR_NOT_CACHED 0x20 extern ppr_t* wlc_phy_get_cached_pwr(chanspec_t chanspec, uint pwr_type); extern int wlc_phy_set_cached_pwr(osl_t *osh, chanspec_t chanspec, uint pwr_type, ppr_t* pwrptr); extern uint8 wlc_phy_get_cached_pwr_max(chanspec_t chanspec, uint core); extern int wlc_phy_set_cached_pwr_max(chanspec_t chanspec, uint core, uint8 max_pwr); extern uint8 wlc_phy_get_cached_pwr_min(chanspec_t chanspec, uint core); extern int wlc_phy_set_cached_pwr_min(chanspec_t chanspec, uint core, uint8 min_pwr); extern int wlc_phy_get_cached_stf_target_pwr_min(chanspec_t chanspec); extern int wlc_phy_set_cached_stf_target_pwr_min(chanspec_t chanspec, int min_pwr); extern int8 wlc_phy_get_cached_txchain_offsets(chanspec_t chanspec, uint core); extern int wlc_phy_set_cached_txchain_offsets(chanspec_t chanspec, uint core, int8 offset); extern bool wlc_phy_txpwr_cache_is_cached(chanspec_t chanspec); extern bool wlc_phy_is_pwr_cached(uint pwr_type, ppr_t* pwrptr); extern void wlc_phy_uncache_pwr(uint pwr_type, ppr_t* pwrptr); extern void wlc_phy_uncache_pwr(uint pwr_type, ppr_t* pwrptr); extern chanspec_t wlc_phy_txpwr_cache_find_other_cached_chanspec(chanspec_t chanspec); extern void wlc_phy_txpwr_cache_clear(osl_t *osh, chanspec_t chanspec); extern void wlc_phy_txpwr_cache_invalidate(void); extern void wlc_phy_txpwr_cache_close(osl_t *osh); extern int wlc_phy_txpwr_setup_entry(chanspec_t chanspec); extern bool wlc_phy_get_stf_ppr_cached(chanspec_t chanspec); extern void wlc_phy_set_stf_ppr_cached(chanspec_t chanspec, bool bcached); #endif /* WLTXPWR_CACHE */ #endif /* _wlc_ppr_h_ */