The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2 
    3   Broadcom B43 wireless driver
    4   IEEE 802.11n PHY data tables
    5 
    6   Copyright (c) 2008 Michael Buesch <m@bues.ch>
    7   Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
    8 
    9   This program is free software; you can redistribute it and/or modify
   10   it under the terms of the GNU General Public License as published by
   11   the Free Software Foundation; either version 2 of the License, or
   12   (at your option) any later version.
   13 
   14   This program is distributed in the hope that it will be useful,
   15   but WITHOUT ANY WARRANTY; without even the implied warranty of
   16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17   GNU General Public License for more details.
   18 
   19   You should have received a copy of the GNU General Public License
   20   along with this program; see the file COPYING.  If not, write to
   21   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
   22   Boston, MA 02110-1301, USA.
   23 
   24 */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 /*
   30  * The Broadcom Wireless LAN controller driver.
   31  */
   32 #include "opt_wlan.h"
   33 #include "opt_bwn.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 #include <sys/module.h>
   40 #include <sys/endian.h>
   41 #include <sys/errno.h>
   42 #include <sys/firmware.h>
   43 #include <sys/lock.h>
   44 #include <sys/mutex.h>
   45 #include <machine/bus.h>
   46 #include <machine/resource.h>
   47 #include <sys/bus.h>
   48 #include <sys/rman.h>
   49 #include <sys/socket.h>
   50 #include <sys/sockio.h>
   51 
   52 #include <net/ethernet.h>
   53 #include <net/if.h>
   54 #include <net/if_var.h>
   55 #include <net/if_arp.h>
   56 #include <net/if_dl.h>
   57 #include <net/if_llc.h>
   58 #include <net/if_media.h>
   59 #include <net/if_types.h>
   60 
   61 #include <dev/pci/pcivar.h>
   62 #include <dev/pci/pcireg.h>
   63 
   64 #include <net80211/ieee80211_var.h>
   65 #include <net80211/ieee80211_radiotap.h>
   66 #include <net80211/ieee80211_regdomain.h>
   67 #include <net80211/ieee80211_phy.h>
   68 #include <net80211/ieee80211_ratectl.h>
   69 
   70 #include <dev/bhnd/bhnd.h>
   71 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
   72 
   73 #include <dev/bwn/if_bwnreg.h>
   74 #include <dev/bwn/if_bwnvar.h>
   75 #include <dev/bwn/if_bwn_debug.h>
   76 #include <dev/bwn/if_bwn_util.h>
   77 #include <dev/bwn/if_bwn_phy_common.h>
   78 
   79 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h>
   80 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_sprom.h>
   81 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h>
   82 
   83 #include "bhnd_nvram_map.h"
   84 
   85 #define ppr_for_each_entry(ppr, i, entry)                               \
   86         for (i = 0, entry = &(ppr)->__all_rates[i];                     \
   87              i < BWN_PPR_RATES_NUM;                                     \
   88              i++, entry++)
   89 
   90 void bwn_ppr_clear(struct bwn_mac *mac, struct bwn_ppr *ppr)
   91 {
   92         memset(ppr, 0, sizeof(*ppr));
   93 
   94         /* Compile-time PPR check */
   95         CTASSERT(sizeof(struct bwn_ppr) == BWN_PPR_RATES_NUM * sizeof(uint8_t));
   96 }
   97 
   98 void bwn_ppr_add(struct bwn_mac *mac, struct bwn_ppr *ppr, int diff)
   99 {
  100         int i;
  101         uint8_t *rate;
  102 
  103         ppr_for_each_entry(ppr, i, rate) {
  104                 *rate = bwn_clamp_val(*rate + diff, 0, 127);
  105         }
  106 }
  107 
  108 void bwn_ppr_apply_max(struct bwn_mac *mac, struct bwn_ppr *ppr, uint8_t max)
  109 {
  110         int i;
  111         uint8_t *rate;
  112 
  113         ppr_for_each_entry(ppr, i, rate) {
  114                 *rate = min(*rate, max);
  115         }
  116 }
  117 
  118 void bwn_ppr_apply_min(struct bwn_mac *mac, struct bwn_ppr *ppr, uint8_t min)
  119 {
  120         int i;
  121         uint8_t *rate;
  122 
  123         ppr_for_each_entry(ppr, i, rate) {
  124                 *rate = max(*rate, min);
  125         }
  126 }
  127 
  128 uint8_t bwn_ppr_get_max(struct bwn_mac *mac, struct bwn_ppr *ppr)
  129 {
  130         uint8_t res = 0;
  131         int i;
  132         uint8_t *rate;
  133 
  134         ppr_for_each_entry(ppr, i, rate) {
  135                 res = max(*rate, res);
  136         }
  137 
  138         return res;
  139 }
  140 
  141 bool bwn_ppr_load_max_from_sprom(struct bwn_mac *mac, struct bwn_ppr *ppr,
  142                                  bwn_phy_band_t band)
  143 {
  144         struct bwn_softc *sc = mac->mac_sc;
  145         struct bwn_phy_n_core_pwr_info core_pwr_info[4];
  146         struct bwn_ppr_rates *rates = &ppr->rates;
  147         struct bwn_phy *phy = &mac->mac_phy;
  148         const char *var_ofdmgpo, *var_mcsgpo_prefix;
  149         uint8_t maxpwr, off;
  150         uint32_t sprom_ofdm_po;
  151         uint16_t sprom_mcs_po[8];
  152         uint16_t cddpo, stbcpo;
  153         uint8_t extra_cdd_po, extra_stbc_po;
  154         int error;
  155         int i;
  156 
  157         for (i = 0; i < 4; i++) {
  158                 bzero(&core_pwr_info[i], sizeof(core_pwr_info[i]));
  159                 if (bwn_nphy_get_core_power_info(mac, i,
  160                     &core_pwr_info[i]) != 0) {
  161                         BWN_ERRPRINTF(mac->mac_sc,
  162                             "%s: failed to get core_pwr_info for core %d\n",
  163                             __func__,
  164                             i);
  165                 }
  166         }
  167 
  168         error = bhnd_nvram_getvar_uint16(sc->sc_dev, BHND_NVAR_CDDPO, &cddpo);
  169         if (error) {
  170                 BWN_ERRPRINTF(mac->mac_sc, "NVRAM variable %s unreadable: %d\n",
  171                      BHND_NVAR_CDDPO, error);
  172                 return (false);
  173         }
  174 
  175         error = bhnd_nvram_getvar_uint16(sc->sc_dev, BHND_NVAR_STBCPO, &stbcpo);
  176         if (error) {
  177                 BWN_ERRPRINTF(mac->mac_sc, "NVRAM variable %s unreadable: %d\n",
  178                      BHND_NVAR_STBCPO, error);
  179                 return (false);
  180         }
  181 
  182         switch (band) {
  183         case BWN_PHY_BAND_2G:
  184                 maxpwr = min(core_pwr_info[0].maxpwr_2g,
  185                              core_pwr_info[1].maxpwr_2g);
  186 
  187                 var_ofdmgpo = BHND_NVAR_OFDM2GPO;
  188                 var_mcsgpo_prefix = "mcs2gpo";
  189                 extra_cdd_po = (cddpo >> 0) & 0xf;
  190                 extra_stbc_po = (stbcpo >> 0) & 0xf;
  191                 break;
  192         case BWN_PHY_BAND_5G_LO:
  193                 maxpwr = min(core_pwr_info[0].maxpwr_5gl,
  194                              core_pwr_info[1].maxpwr_5gl);
  195                 var_ofdmgpo = BHND_NVAR_OFDM5GLPO;
  196                 var_mcsgpo_prefix = "mcs5glpo";
  197                 extra_cdd_po = (cddpo >> 8) & 0xf;
  198                 extra_stbc_po = (stbcpo >> 8) & 0xf;
  199                 break;
  200         case BWN_PHY_BAND_5G_MI:
  201                 maxpwr = min(core_pwr_info[0].maxpwr_5g,
  202                              core_pwr_info[1].maxpwr_5g);
  203                 var_ofdmgpo = BHND_NVAR_OFDM5GPO;
  204                 var_mcsgpo_prefix = "mcs5gpo";
  205                 extra_cdd_po = (cddpo >> 4) & 0xf;
  206                 extra_stbc_po = (stbcpo >> 4) & 0xf;
  207                 break;
  208         case BWN_PHY_BAND_5G_HI:
  209                 maxpwr = min(core_pwr_info[0].maxpwr_5gh,
  210                              core_pwr_info[1].maxpwr_5gh);
  211                 var_ofdmgpo = BHND_NVAR_OFDM5GHPO;
  212                 var_mcsgpo_prefix = "mcs5ghpo";
  213                 extra_cdd_po = (cddpo >> 12) & 0xf;
  214                 extra_stbc_po = (stbcpo >> 12) & 0xf;
  215                 break;
  216         default:
  217                 device_printf(mac->mac_sc->sc_dev, "%s: invalid band (%d)\n",
  218                     __func__,
  219                     band);
  220                 return false;
  221         }
  222 
  223         error = bhnd_nvram_getvar_uint32(sc->sc_dev, var_ofdmgpo,
  224             &sprom_ofdm_po);
  225         if (error) {
  226                 device_printf(sc->sc_dev, "NVRAM variable %s unreadable: %d\n",
  227                      var_ofdmgpo, error);
  228                 return (false);
  229         }
  230 
  231         for (size_t i = 0; i < nitems(sprom_mcs_po); i++) {
  232                 char    var[strlen(var_mcsgpo_prefix) + sizeof("XX")];
  233                 int     ret;
  234 
  235                 /* mcs[25]g[lh]?po[0-9] */
  236                 ret = snprintf(var, sizeof(var), "%s%zu", var_mcsgpo_prefix, i);
  237                 if (ret >= sizeof(var)) {
  238                         device_printf(sc->sc_dev, "buffer too small for "
  239                             "%s%zu\n", var_mcsgpo_prefix, i);
  240                         return (false);
  241                 }
  242 
  243                 error = bhnd_nvram_getvar_uint16(sc->sc_dev, var,
  244                     &sprom_mcs_po[i]);
  245                 if (error) {
  246                         device_printf(sc->sc_dev, "NVRAM variable %s "
  247                             "unreadable: %d\n", var, error);
  248                         return (false);
  249                 }
  250         }
  251 
  252         if (band == BWN_BAND_2G) {
  253                 uint16_t ck2gpo;
  254 
  255                 error = bhnd_nvram_getvar_uint16(sc->sc_dev, BHND_NVAR_CCK2GPO,
  256                     &ck2gpo);
  257                 if (error) {
  258                         device_printf(sc->sc_dev, "NVRAM variable %s "
  259                             "unreadable: %d\n", BHND_NVAR_CCK2GPO, error);
  260                         return (false);
  261                 }
  262 
  263                 for (i = 0; i < 4; i++) {
  264                         off = ((ck2gpo >> (i * 4)) & 0xf) * 2;
  265                         rates->cck[i] = maxpwr - off;
  266                 }
  267         }
  268 
  269         /* OFDM */
  270         for (i = 0; i < 8; i++) {
  271                 off = ((sprom_ofdm_po >> (i * 4)) & 0xf) * 2;
  272                 rates->ofdm[i] = maxpwr - off;
  273         }
  274 
  275         /* MCS 20 SISO */
  276         rates->mcs_20[0] = rates->ofdm[0];
  277         rates->mcs_20[1] = rates->ofdm[2];
  278         rates->mcs_20[2] = rates->ofdm[3];
  279         rates->mcs_20[3] = rates->ofdm[4];
  280         rates->mcs_20[4] = rates->ofdm[5];
  281         rates->mcs_20[5] = rates->ofdm[6];
  282         rates->mcs_20[6] = rates->ofdm[7];
  283         rates->mcs_20[7] = rates->ofdm[7];
  284 
  285         /* MCS 20 CDD */
  286         for (i = 0; i < 4; i++) {
  287                 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
  288                 rates->mcs_20_cdd[i] = maxpwr - off;
  289                 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3)
  290                         rates->mcs_20_cdd[i] -= extra_cdd_po;
  291         }
  292         for (i = 0; i < 4; i++) {
  293                 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
  294                 rates->mcs_20_cdd[4 + i] = maxpwr - off;
  295                 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3)
  296                         rates->mcs_20_cdd[4 + i] -= extra_cdd_po;
  297         }
  298 
  299         /* OFDM 20 CDD */
  300         rates->ofdm_20_cdd[0] = rates->mcs_20_cdd[0];
  301         rates->ofdm_20_cdd[1] = rates->mcs_20_cdd[0];
  302         rates->ofdm_20_cdd[2] = rates->mcs_20_cdd[1];
  303         rates->ofdm_20_cdd[3] = rates->mcs_20_cdd[2];
  304         rates->ofdm_20_cdd[4] = rates->mcs_20_cdd[3];
  305         rates->ofdm_20_cdd[5] = rates->mcs_20_cdd[4];
  306         rates->ofdm_20_cdd[6] = rates->mcs_20_cdd[5];
  307         rates->ofdm_20_cdd[7] = rates->mcs_20_cdd[6];
  308 
  309         /* MCS 20 STBC */
  310         for (i = 0; i < 4; i++) {
  311                 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
  312                 rates->mcs_20_stbc[i] = maxpwr - off;
  313                 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3)
  314                         rates->mcs_20_stbc[i] -= extra_stbc_po;
  315         }
  316         for (i = 0; i < 4; i++) {
  317                 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
  318                 rates->mcs_20_stbc[4 + i] = maxpwr - off;
  319                 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3)
  320                         rates->mcs_20_stbc[4 + i] -= extra_stbc_po;
  321         }
  322 
  323         /* MCS 20 SDM */
  324         for (i = 0; i < 4; i++) {
  325                 off = ((sprom_mcs_po[2] >> (i * 4)) & 0xf) * 2;
  326                 rates->mcs_20_sdm[i] = maxpwr - off;
  327         }
  328         for (i = 0; i < 4; i++) {
  329                 off = ((sprom_mcs_po[3] >> (i * 4)) & 0xf) * 2;
  330                 rates->mcs_20_sdm[4 + i] = maxpwr - off;
  331         }
  332 
  333         return true;
  334 }

Cache object: af12cbad772b85c227e7035f128f86b8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.