Skip to content

Commit

Permalink
ath10k: Support sending individual beacons at specific tx rates.
Browse files Browse the repository at this point in the history
Might be useful for some more exotic scenarios.

Signed-off-by: Ben Greear <greearb@candelatech.com>
  • Loading branch information
greearb committed Apr 16, 2019
1 parent 9cd701a commit fb57af0
Show file tree
Hide file tree
Showing 21 changed files with 330 additions and 228 deletions.
1 change: 1 addition & 0 deletions ath10k-4.16/core.c
Expand Up @@ -540,6 +540,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_TXRATE2_CT] = "txrate2-CT",
[ATH10K_FW_FEATURE_BEACON_TX_CB_CT] = "beacon-cb-CT",
[ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT] = "wmi-block-ack-CT",
[ATH10K_FW_FEATURE_HAS_BCN_RC_CT] = "wmi-bcn-rc-CT",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
Expand Down
3 changes: 3 additions & 0 deletions ath10k-4.16/core.h
Expand Up @@ -488,6 +488,7 @@ struct ath10k_vif {
/* TX Rate overrides, CT FW only at this time, and only wave-2 has full support */
bool txo_active;
u8 txo_tpc;
u8 txo_sgi;
u8 txo_mcs;
u8 txo_nss;
u8 txo_pream;
Expand Down Expand Up @@ -829,6 +830,8 @@ enum ath10k_fw_features {

ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT = 52, /* firmware can accept decrypted rx block-ack over WMI */

ATH10K_FW_FEATURE_HAS_BCN_RC_CT = 53, /* firmware can accept ppdu (tx-rate) info in beacon-tx-by-ref wmi cmd */

/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
Expand Down
15 changes: 8 additions & 7 deletions ath10k-4.16/debug.c
Expand Up @@ -56,7 +56,7 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
{
const struct firmware *firmware;
char fw_features[256] = {};
char fw_features[360] = {};
u32 crc = 0;

ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
Expand Down Expand Up @@ -1488,10 +1488,10 @@ static ssize_t ath10k_read_set_rate_override(struct file *file,
"Only wave-2 CT firmware has full support. Wave-1 CT firmware has at least\n"
"some support (rix mostly). Wave-2 does not use rix.\n"
"To set a value, you specify the dev-name and key-value pairs:\n"
"tpc=10 mcs=x nss=x pream=x retries=x dynbw=0|1 bw=x rix=x enable=0|1\n"
"tpc=10 sgi=1 mcs=x nss=x pream=x retries=x dynbw=0|1 bw=x rix=x enable=0|1\n"
"pream: 0=ofdm, 1=cck, 2=HT, 3=VHT\n"
"tpc is in 1db increments, 255 means use defaults, bw is 0-3 for 20-160\n"
" For example, wlan0: echo \"wlan0 tpc=255 mcs=0 nss=1 pream=3 retries=1 dynbw=0 bw=0 active=1\" > ...ath10k/set_rate_override\n";
" For example, wlan0: echo \"wlan0 tpc=255 sgi=1 mcs=0 nss=1 pream=3 retries=1 dynbw=0 bw=0 active=1\" > ...ath10k/set_rate_override\n";

buf2 = kzalloc(size, GFP_KERNEL);
if (buf2 == NULL)
Expand All @@ -1507,9 +1507,9 @@ static ssize_t ath10k_read_set_rate_override(struct file *file,
continue;

sofar += scnprintf(buf2 + sofar, size - sofar,
"vdev %i(%s) active=%d tpc=%d mcs=%d nss=%d pream=%d retries=%d dynbw=%d bw=%d rix=%d\n",
"vdev %i(%s) active=%d tpc=%d sgi=%d mcs=%d nss=%d pream=%d retries=%d dynbw=%d bw=%d rix=%d\n",
arvif->vdev_id, wdev->netdev->name,
arvif->txo_active, arvif->txo_tpc, arvif->txo_mcs,
arvif->txo_active, arvif->txo_tpc, arvif->txo_sgi, arvif->txo_mcs,
arvif->txo_nss, arvif->txo_pream, arvif->txo_retries, arvif->txo_dynbw,
arvif->txo_bw, arvif->txo_rix);
if (sofar >= size)
Expand Down Expand Up @@ -1599,6 +1599,7 @@ static ssize_t ath10k_write_set_rate_override(struct file *file,
}

ATH10K_PARSE_LTOK(tpc);
ATH10K_PARSE_LTOK(sgi);
ATH10K_PARSE_LTOK(mcs);
ATH10K_PARSE_LTOK(nss);
ATH10K_PARSE_LTOK(pream);
Expand All @@ -1608,9 +1609,9 @@ static ssize_t ath10k_write_set_rate_override(struct file *file,
ATH10K_PARSE_LTOK(rix);
ATH10K_PARSE_LTOK(active);

ath10k_warn(ar, "set-rate-overrides, vdev %i(%s) active=%d tpc=%d mcs=%d nss=%d pream=%d retries=%d dynbw=%d bw=%d rix=%d\n",
ath10k_warn(ar, "set-rate-overrides, vdev %i(%s) active=%d tpc=%d sgi=%d mcs=%d nss=%d pream=%d retries=%d dynbw=%d bw=%d rix=%d\n",
arvif->vdev_id, dev_name_match,
arvif->txo_active, arvif->txo_tpc, arvif->txo_mcs,
arvif->txo_active, arvif->txo_tpc, arvif->txo_sgi, arvif->txo_mcs,
arvif->txo_nss, arvif->txo_pream, arvif->txo_retries, arvif->txo_dynbw,
arvif->txo_bw, arvif->txo_rix);

Expand Down
76 changes: 5 additions & 71 deletions ath10k-4.16/htt_tx.c
Expand Up @@ -1146,74 +1146,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
return res;
}

/* Create a rate-info object that (some) 10.4 CT firmware
* can understand.
*/
u32 ath10k_convert_hw_rate_to_rate_info(u8 tpc, u8 mcs, u8 nss, u8 pream_type,
u8 num_retries, u8 bw, u8 dyn_bw)
{

/* Re-use logic from 10.4 firmware */
struct __ath10k_rate_info {
u32 power : 8, /* units of the power field is dbm */
mcs : 4, /* mcs = 0 ~ 9 */
nss : 2, /* 0 = 1 nss, 1 = 2 nss, 2 = 3 nss, 3 = 4 nss */
pream_type : 2, /* 0 = WIFI_RATECODE_PREAM_OFDM,
1 = WIFI_RATECODE_PREAM_CCK,
2 = WIFI_RATECODE_PREAM_HT ,
3 = WIFI_RATECODE_PREAM_VHT */
num_retries : 4, /* 0 ~ 15: 0 means no-ack */
dyn_bw : 1, /* 0 = static bw, 1 = dynamic bw */
bw : 3, /* valid only if dyn_bw == 0 (static bw).
(0 = 20 mhz, 1 = 40 mhz, 2 = 80 mhz, 3 = 160 mhz , 4 = 80+80mhz) */
valid_power : 1, /* power info field has valid power. */
valid_rate : 1, /* mcs,nss,pream_type fields have valid rates. */
valid_num_retries : 1, /* num_retries field has valid value */
valid_dyn_bw : 1, /* dyn_bw field has valid value */
valid_bw : 1, /* bw field has valid value */

any_valid : 1, /* 1 : htt_tx_msdu_desc_t contains valid tx meta data */
key_id : 2; /* key index 0 to 3 for per packet key rotation */
};

struct __ath10k_rate_info ri;
u32 *rvi = (u32*)(&ri);
rvi[0] = 0;

if (tpc != 0xFF) {
ri.power = tpc;
ri.valid_power = 1;
ri.any_valid = 1;
}

if (mcs != 0xFF) {
ri.mcs = mcs;
ri.nss = nss;
ri.pream_type = pream_type;
ri.valid_rate = 1;
ri.any_valid = 1;
}

if (num_retries != 0xFF) {
ri.num_retries = num_retries;
ri.valid_num_retries = 1;
ri.any_valid = 1;
}

if (dyn_bw != 0xFF) {
ri.dyn_bw = dyn_bw;
ri.valid_dyn_bw = 1;
if (ri.dyn_bw == 0) {
ri.bw = bw;
ri.valid_bw = 1;
}
ri.any_valid = 1;
}

/* leave key-id set to zero for now */
return rvi[0];
}

static int ath10k_htt_tx_32(struct ath10k_htt *htt,
struct ieee80211_vif *vif,
enum ath10k_hw_txrx_mode txmode,
Expand Down Expand Up @@ -1274,6 +1206,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
enum nl80211_band band = info->band;
const struct ieee80211_supported_band *sband;
u8 tpc = 0xFF; /* don't need to set this */
u8 sgi = 0;
u8 mcs = 0;
u8 nss = 0;
u8 pream_type;
Expand Down Expand Up @@ -1307,6 +1240,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
(!(ieee80211_is_qos_nullfunc(fc) || ieee80211_is_nullfunc(fc)))) {
if (arvif && arvif->txo_active) {
tpc = arvif->txo_tpc;
sgi = arvif->txo_sgi;
mcs = arvif->txo_mcs;
nss = arvif->txo_nss;
pream_type = arvif->txo_pream;
Expand Down Expand Up @@ -1352,11 +1286,11 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
}

/* wave-2 supports this API */
peer_id = ath10k_convert_hw_rate_to_rate_info(tpc, mcs, nss, pream_type, num_retries, bw, dyn_bw);
peer_id = ath10k_convert_hw_rate_to_rate_info(tpc, mcs, sgi, nss, pream_type, num_retries, bw, dyn_bw);

if (ar->eeprom_overrides.tx_debug & 0x3)
ath10k_warn(ar, "wave-2 vdev-id: %d msdu: %p peer_id: 0x%x tpc: %d mcs: %d nss: %d pream_type: %d num_retries: %d bw: %d dyn_bw: %d\n",
(int)(vdev_id), msdu, peer_id, tpc, mcs, nss, pream_type, num_retries, bw, dyn_bw);
ath10k_warn(ar, "wave-2 vdev-id: %d msdu: %p peer_id: 0x%x tpc: %d sgi: %d mcs: %d nss: %d pream_type: %d num_retries: %d bw: %d dyn_bw: %d\n",
(int)(vdev_id), msdu, peer_id, tpc, sgi, mcs, nss, pream_type, num_retries, bw, dyn_bw);
}
}
}
Expand Down
71 changes: 71 additions & 0 deletions ath10k-4.16/mac.c
Expand Up @@ -154,6 +154,77 @@ u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
return 0;
}

/* Create a rate-info object that (some) 10.4 CT firmware
* can understand.
*/
u32 ath10k_convert_hw_rate_to_rate_info(u8 tpc, u8 mcs, u8 sgi, u8 nss, u8 pream_type,
u8 num_retries, u8 bw, u8 dyn_bw)
{

/* Re-use logic from 10.4 firmware */
struct __ath10k_rate_info {
u32 power : 6, /* units of the power field is dbm */
unused : 1, /* Room for growth */
sgi : 1, /* Enable SGI or not, checked when valid_rate is enabled. */
mcs : 4, /* mcs = 0 ~ 9 */
nss : 2, /* 0 = 1 nss, 1 = 2 nss, 2 = 3 nss, 3 = 4 nss */
pream_type : 2, /* 0 = WIFI_RATECODE_PREAM_OFDM,
1 = WIFI_RATECODE_PREAM_CCK,
2 = WIFI_RATECODE_PREAM_HT ,
3 = WIFI_RATECODE_PREAM_VHT */
num_retries : 4, /* 0 ~ 15: 0 means no-ack */
dyn_bw : 1, /* 0 = static bw, 1 = dynamic bw */
bw : 3, /* valid only if dyn_bw == 0 (static bw).
(0 = 20 mhz, 1 = 40 mhz, 2 = 80 mhz, 3 = 160 mhz , 4 = 80+80mhz) */
valid_power : 1, /* power info field has valid power. */
valid_rate : 1, /* mcs,nss,pream_type fields have valid rates. */
valid_num_retries : 1, /* num_retries field has valid value */
valid_dyn_bw : 1, /* dyn_bw field has valid value */
valid_bw : 1, /* bw field has valid value */

any_valid : 1, /* 1 : htt_tx_msdu_desc_t contains valid tx meta data */
key_id : 2; /* key index 0 to 3 for per packet key rotation */
};

struct __ath10k_rate_info ri;
u32 *rvi = (u32*)(&ri);
rvi[0] = 0;

if (tpc != 0xFF) {
ri.power = tpc;
ri.valid_power = 1;
ri.any_valid = 1;
}

if (mcs != 0xFF) {
ri.mcs = mcs;
ri.nss = nss;
ri.pream_type = pream_type;
ri.sgi = sgi;
ri.valid_rate = 1;
ri.any_valid = 1;
}

if (num_retries != 0xFF) {
ri.num_retries = num_retries;
ri.valid_num_retries = 1;
ri.any_valid = 1;
}

if (dyn_bw != 0xFF) {
ri.dyn_bw = dyn_bw;
ri.valid_dyn_bw = 1;
if (ri.dyn_bw == 0) {
ri.bw = bw;
ri.valid_bw = 1;
}
ri.any_valid = 1;
}

/* leave key-id set to zero for now */
return rvi[0];
}

static int ath10k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
{
switch ((mcs_map >> (2 * nss)) & 0x3) {
Expand Down
2 changes: 2 additions & 0 deletions ath10k-4.16/mac.h
Expand Up @@ -80,6 +80,8 @@ u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
u8 hw_rate, bool cck);
u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
u32 bitrate);
u32 ath10k_convert_hw_rate_to_rate_info(u8 tpc, u8 mcs, u8 sgi, u8 nss, u8 pream_type,
u8 num_retries, u8 bw, u8 dyn_bw);

void ath10k_mac_tx_lock(struct ath10k *ar, int reason);
void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
Expand Down
29 changes: 27 additions & 2 deletions ath10k-4.16/wmi.c
Expand Up @@ -8001,6 +8001,7 @@ ath10k_wmi_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, const void *bcn,
struct wmi_bcn_tx_ref_cmd *cmd;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
u32 ppdu_info = 0;
u16 fc;

skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
Expand All @@ -8010,9 +8011,33 @@ ath10k_wmi_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, const void *bcn,
hdr = (struct ieee80211_hdr *)bcn;
fc = le16_to_cpu(hdr->frame_control);

if (test_bit(ATH10K_FW_FEATURE_HAS_BCN_RC_CT,
ar->running_fw->fw_file.fw_features)) {
#if 0
/* Left as an exercise to the user: If you want to TX beacons at different
* rates, power, etc. Then adjust these variables below accordingly.
* --Ben
*/
u8 tpc = 0xFF; /* ff means don't set */
u8 sgi = 0;
u8 mcs = 3; // 6Mbps (if ofdm)
u8 nss = 0;
u8 pream_type = 0; /* ofdm */
u8 num_retries = 0; /* no ack */
u8 dyn_bw = 0;
u8 bw = 0;

tpc = 1; /* BEN: Not sure this currently has an effect. */
pream_type = 2; /* HT */
mcs = 4; /* 54Mbps, if ofdm, 39Mbps if HT, for test purposes */

ppdu_info = ath10k_convert_hw_rate_to_rate_info(tpc, mcs, sgi, nss, pream_type, num_retries, bw, dyn_bw);
#endif
}

cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->data_len = __cpu_to_le32(bcn_len);
cmd->vdev_id = __cpu_to_le32(vdev_id | (ppdu_info << 8));
cmd->data_len = __cpu_to_le32(bcn_len | (ppdu_info & 0xFF000000));
cmd->data_ptr = __cpu_to_le32(bcn_paddr);
cmd->msdu_id = 0;
cmd->frame_control = __cpu_to_le32(fc);
Expand Down
2 changes: 2 additions & 0 deletions ath10k-4.19/core.c
Expand Up @@ -593,6 +593,8 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_CT_STA] = "CT-STA",
[ATH10K_FW_FEATURE_TXRATE2_CT] = "txrate2-CT",
[ATH10K_FW_FEATURE_BEACON_TX_CB_CT] = "beacon-cb-CT",
[ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT] = "wmi-block-ack-CT",
[ATH10K_FW_FEATURE_HAS_BCN_RC_CT] = "wmi-bcn-rc-CT",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
Expand Down
6 changes: 6 additions & 0 deletions ath10k-4.19/core.h
Expand Up @@ -937,6 +937,12 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_BEACON_TX_CB_CT = 50,

ATH10K_FW_FEATURE_RESERVED_CT = 51, /* reserved by out-of-tree feature */

ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT = 52, /* firmware can accept decrypted rx block-ack over WMI */

ATH10K_FW_FEATURE_HAS_BCN_RC_CT = 53, /* firmware can accept ppdu (tx-rate) info in beacon-tx-by-ref wmi cmd */

/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
Expand Down
2 changes: 1 addition & 1 deletion ath10k-4.19/debug.c
Expand Up @@ -56,7 +56,7 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
{
const struct firmware *firmware;
char fw_features[256] = {};
char fw_features[360] = {};
u32 crc = 0;

ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
Expand Down

0 comments on commit fb57af0

Please sign in to comment.