diff options
Diffstat (limited to 'package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch')
-rw-r--r-- | package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch b/package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch new file mode 100644 index 0000000000..62fdd8d745 --- /dev/null +++ b/package/kernel/mac80211/patches/370-0003-brcmfmac-Fix-set-and-get-tx-power-functions.patch @@ -0,0 +1,218 @@ +From: Hante Meuleman <meuleman@broadcom.com> +Date: Fri, 18 Sep 2015 22:08:06 +0200 +Subject: [PATCH] brcmfmac: Fix set and get tx-power functions. + +Implementation of tx-power (get and set) related functions are +still assuming mW interface. This is wrong as functions use dbm +(or mbm) nowadays. As a result a tx power configuration could +result in wrong power configuration. + +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Hante Meuleman <meuleman@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +@@ -236,89 +236,6 @@ static int brcmf_roamoff; + module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); + MODULE_PARM_DESC(roamoff, "do not use internal roaming engine"); + +-/* Quarter dBm units to mW +- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 +- * Table is offset so the last entry is largest mW value that fits in +- * a u16. +- */ +- +-#define QDBM_OFFSET 153 /* Offset for first entry */ +-#define QDBM_TABLE_LEN 40 /* Table size */ +- +-/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. +- * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 +- */ +-#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ +- +-/* Largest mW value that will round down to the last table entry, +- * QDBM_OFFSET + QDBM_TABLE_LEN-1. +- * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + +- * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. +- */ +-#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ +- +-static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { +-/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ +-/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, +-/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, +-/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, +-/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, +-/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 +-}; +- +-static u16 brcmf_qdbm_to_mw(u8 qdbm) +-{ +- uint factor = 1; +- int idx = qdbm - QDBM_OFFSET; +- +- if (idx >= QDBM_TABLE_LEN) +- /* clamp to max u16 mW value */ +- return 0xFFFF; +- +- /* scale the qdBm index up to the range of the table 0-40 +- * where an offset of 40 qdBm equals a factor of 10 mW. +- */ +- while (idx < 0) { +- idx += 40; +- factor *= 10; +- } +- +- /* return the mW value scaled down to the correct factor of 10, +- * adding in factor/2 to get proper rounding. +- */ +- return (nqdBm_to_mW_map[idx] + factor / 2) / factor; +-} +- +-static u8 brcmf_mw_to_qdbm(u16 mw) +-{ +- u8 qdbm; +- int offset; +- uint mw_uint = mw; +- uint boundary; +- +- /* handle boundary case */ +- if (mw_uint <= 1) +- return 0; +- +- offset = QDBM_OFFSET; +- +- /* move mw into the range of the table */ +- while (mw_uint < QDBM_TABLE_LOW_BOUND) { +- mw_uint *= 10; +- offset -= 40; +- } +- +- for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) { +- boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - +- nqdBm_to_mW_map[qdbm]) / 2; +- if (mw_uint < boundary) +- break; +- } +- +- qdbm += (u8) offset; +- +- return qdbm; +-} + + static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, + struct cfg80211_chan_def *ch) +@@ -2016,16 +1933,14 @@ static s32 + brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, s32 mbm) + { +- + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_if *ifp = netdev_priv(ndev); +- u16 txpwrmw; +- s32 err = 0; +- s32 disable = 0; +- s32 dbm = MBM_TO_DBM(mbm); ++ s32 err; ++ s32 disable; ++ u32 qdbm = 127; + +- brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm); + if (!check_vif_up(ifp->vif)) + return -EIO; + +@@ -2034,12 +1949,20 @@ brcmf_cfg80211_set_tx_power(struct wiphy + break; + case NL80211_TX_POWER_LIMITED: + case NL80211_TX_POWER_FIXED: +- if (dbm < 0) { ++ if (mbm < 0) { + brcmf_err("TX_POWER_FIXED - dbm is negative\n"); + err = -EINVAL; + goto done; + } ++ qdbm = MBM_TO_DBM(4 * mbm); ++ if (qdbm > 127) ++ qdbm = 127; ++ qdbm |= WL_TXPWR_OVERRIDE; + break; ++ default: ++ brcmf_err("Unsupported type %d\n", type); ++ err = -EINVAL; ++ goto done; + } + /* Make sure radio is off or on as far as software is concerned */ + disable = WL_RADIO_SW_DISABLE << 16; +@@ -2047,52 +1970,44 @@ brcmf_cfg80211_set_tx_power(struct wiphy + if (err) + brcmf_err("WLC_SET_RADIO error (%d)\n", err); + +- if (dbm > 0xffff) +- txpwrmw = 0xffff; +- else +- txpwrmw = (u16) dbm; +- err = brcmf_fil_iovar_int_set(ifp, "qtxpower", +- (s32)brcmf_mw_to_qdbm(txpwrmw)); ++ err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm); + if (err) + brcmf_err("qtxpower error (%d)\n", err); +- cfg->conf->tx_power = dbm; + + done: +- brcmf_dbg(TRACE, "Exit\n"); ++ brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE); + return err; + } + +-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- s32 *dbm) ++static s32 ++brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, ++ s32 *dbm) + { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); +- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); +- s32 txpwrdbm; +- u8 result; +- s32 err = 0; ++ struct net_device *ndev = cfg_to_ndev(cfg); ++ struct brcmf_if *ifp = netdev_priv(ndev); ++ s32 qdbm = 0; ++ s32 err; + + brcmf_dbg(TRACE, "Enter\n"); + if (!check_vif_up(ifp->vif)) + return -EIO; + +- err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm); ++ err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm); + if (err) { + brcmf_err("error (%d)\n", err); + goto done; + } +- +- result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); +- *dbm = (s32) brcmf_qdbm_to_mw(result); ++ *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4; + + done: +- brcmf_dbg(TRACE, "Exit\n"); ++ brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm); + return err; + } + + static s32 + brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, +- u8 key_idx, bool unicast, bool multicast) ++ u8 key_idx, bool unicast, bool multicast) + { + struct brcmf_if *ifp = netdev_priv(ndev); + u32 index; |