wifi: rtl8xxxu: Add rate control code for RTL8188EU

Copied from the newer vendor driver, v5.2.2.4.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/5acc1e5d-62d6-3a6a-0f9e-cbc8b809b1d7@gmail.com
This commit is contained in:
Bitterblue Smith 2022-12-17 16:21:59 +02:00 committed by Kalle Valo
parent 3dfb8e844f
commit 8b9754b28f
3 changed files with 735 additions and 36 deletions

View File

@ -531,6 +531,7 @@ struct rtl8xxxu_txdesc40 {
#define TXDESC32_CTS_SELF_ENABLE BIT(11)
#define TXDESC32_RTS_CTS_ENABLE BIT(12)
#define TXDESC32_HW_RTS_ENABLE BIT(13)
#define TXDESC32_PT_STAGE_MASK GENMASK(17, 15)
#define TXDESC_PRIME_CH_OFF_LOWER BIT(20)
#define TXDESC_PRIME_CH_OFF_UPPER BIT(21)
#define TXDESC32_SHORT_PREAMBLE BIT(24)
@ -1376,6 +1377,39 @@ struct rtl8xxxu_ra_report {
u8 desc_rate;
};
struct rtl8xxxu_ra_info {
u8 rate_id;
u32 rate_mask;
u32 ra_use_rate;
u8 rate_sgi;
u8 rssi_sta_ra; /* Percentage */
u8 pre_rssi_sta_ra;
u8 sgi_enable;
u8 decision_rate;
u8 pre_rate;
u8 highest_rate;
u8 lowest_rate;
u32 nsc_up;
u32 nsc_down;
u32 total;
u16 retry[5];
u16 drop;
u16 rpt_time;
u16 pre_min_rpt_time;
u8 dynamic_tx_rpt_timing_counter;
u8 ra_waiting_counter;
u8 ra_pending_counter;
u8 ra_drop_after_down;
u8 pt_try_state; /* 0 trying state, 1 for decision state */
u8 pt_stage; /* 0~6 */
u8 pt_stop_count; /* Stop PT counter */
u8 pt_pre_rate; /* if rate change do PT */
u8 pt_pre_rssi; /* if RSSI change 5% do PT */
u8 pt_mode_ss; /* decide which rate should do PT */
u8 ra_stage; /* StageRA, decide how many times RA will be done between PT */
u8 pt_smooth_factor;
};
#define CFO_TH_XTAL_HIGH 20 /* kHz */
#define CFO_TH_XTAL_LOW 10 /* kHz */
#define CFO_TH_ATC 80 /* kHz */
@ -1509,6 +1543,7 @@ struct rtl8xxxu_priv {
struct rtl8xxxu_btcoex bt_coex;
struct rtl8xxxu_ra_report ra_report;
struct rtl8xxxu_cfo_tracking cfo_tracking;
struct rtl8xxxu_ra_info ra_info;
};
struct rtl8xxxu_rx_urb {
@ -1684,6 +1719,10 @@ void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
u8 rate, u8 sgi, u8 bw);
void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra);
void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
extern struct rtl8xxxu_fileops rtl8188fu_fops;
extern struct rtl8xxxu_fileops rtl8188eu_fops;

View File

@ -280,6 +280,123 @@ static const struct rtl8xxxu_rfregval rtl8188eu_radioa_init_table[] = {
{0xff, 0xffffffff}
};
#define PERENTRY 23
#define RETRYSIZE 5
#define RATESIZE 28
#define TX_RPT2_ITEM_SIZE 8
static const u8 retry_penalty[PERENTRY][RETRYSIZE + 1] = {
{5, 4, 3, 2, 0, 3}, /* 92 , idx=0 */
{6, 5, 4, 3, 0, 4}, /* 86 , idx=1 */
{6, 5, 4, 2, 0, 4}, /* 81 , idx=2 */
{8, 7, 6, 4, 0, 6}, /* 75 , idx=3 */
{10, 9, 8, 6, 0, 8}, /* 71 , idx=4 */
{10, 9, 8, 4, 0, 8}, /* 66 , idx=5 */
{10, 9, 8, 2, 0, 8}, /* 62 , idx=6 */
{10, 9, 8, 0, 0, 8}, /* 59 , idx=7 */
{18, 17, 16, 8, 0, 16}, /* 53 , idx=8 */
{26, 25, 24, 16, 0, 24}, /* 50 , idx=9 */
{34, 33, 32, 24, 0, 32}, /* 47 , idx=0x0a */
{34, 31, 28, 20, 0, 32}, /* 43 , idx=0x0b */
{34, 31, 27, 18, 0, 32}, /* 40 , idx=0x0c */
{34, 31, 26, 16, 0, 32}, /* 37 , idx=0x0d */
{34, 30, 22, 16, 0, 32}, /* 32 , idx=0x0e */
{34, 30, 24, 16, 0, 32}, /* 26 , idx=0x0f */
{49, 46, 40, 16, 0, 48}, /* 20 , idx=0x10 */
{49, 45, 32, 0, 0, 48}, /* 17 , idx=0x11 */
{49, 45, 22, 18, 0, 48}, /* 15 , idx=0x12 */
{49, 40, 24, 16, 0, 48}, /* 12 , idx=0x13 */
{49, 32, 18, 12, 0, 48}, /* 9 , idx=0x14 */
{49, 22, 18, 14, 0, 48}, /* 6 , idx=0x15 */
{49, 16, 16, 0, 0, 48} /* 3, idx=0x16 */
};
static const u8 pt_penalty[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32};
static const u8 retry_penalty_idx_normal[2][RATESIZE] = {
{ /* RSSI>TH */
4, 4, 4, 5,
4, 4, 5, 7, 7, 7, 8, 0x0a,
4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f
},
{ /* RSSI<TH */
0x0a, 0x0a, 0x0b, 0x0c,
0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x13,
9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13
}
};
static const u8 retry_penalty_idx_cut_i[2][RATESIZE] = {
{ /* RSSI>TH */
4, 4, 4, 5,
4, 4, 5, 7, 7, 7, 8, 0x0a,
4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f
},
{ /* RSSI<TH */
0x0a, 0x0a, 0x0b, 0x0c,
0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13,
0x06, 0x07, 0x08, 0x0d, 0x0e, 0x11, 0x11, 0x11,
9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13
}
};
static const u8 retry_penalty_up_idx_normal[RATESIZE] = {
0x0c, 0x0d, 0x0d, 0x0f,
0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14,
0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15,
0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15
};
static const u8 retry_penalty_up_idx_cut_i[RATESIZE] = {
0x0c, 0x0d, 0x0d, 0x0f,
0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14,
0x0b, 0x0b, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12,
0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15
};
static const u8 rssi_threshold[RATESIZE] = {
0, 0, 0, 0,
0, 0, 0, 0, 0, 0x24, 0x26, 0x2a,
0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a,
0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c
};
static const u16 n_threshold_high[RATESIZE] = {
4, 4, 8, 16,
24, 36, 48, 72, 96, 144, 192, 216,
60, 80, 100, 160, 240, 400, 600, 800,
300, 320, 480, 720, 1000, 1200, 1600, 2000
};
static const u16 n_threshold_low[RATESIZE] = {
2, 2, 4, 8,
12, 18, 24, 36, 48, 72, 96, 108,
30, 40, 50, 80, 120, 200, 300, 400,
150, 160, 240, 360, 500, 600, 800, 1000
};
static const u8 dropping_necessary[RATESIZE] = {
1, 1, 1, 1,
1, 2, 3, 4, 5, 6, 7, 8,
1, 2, 3, 4, 5, 6, 7, 8,
5, 6, 7, 8, 9, 10, 11, 12
};
static const u8 pending_for_rate_up_fail[5] = {2, 10, 24, 40, 60};
static const u16 dynamic_tx_rpt_timing[6] = {
0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c /* 200ms-1200ms */
};
enum rtl8188e_tx_rpt_timing {
DEFAULT_TIMING = 0,
INCREASE_TIMING,
DECREASE_TIMING
};
static int rtl8188eu_identify_chip(struct rtl8xxxu_priv *priv)
{
struct device *dev = &priv->udev->dev;
@ -1233,6 +1350,477 @@ static s8 rtl8188e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
return rx_pwr_all;
}
static void rtl8188e_set_tx_rpt_timing(struct rtl8xxxu_ra_info *ra, u8 timing)
{
u8 idx;
for (idx = 0; idx < 5; idx++)
if (dynamic_tx_rpt_timing[idx] == ra->rpt_time)
break;
if (timing == DEFAULT_TIMING) {
idx = 0; /* 200ms */
} else if (timing == INCREASE_TIMING) {
if (idx < 5)
idx++;
} else if (timing == DECREASE_TIMING) {
if (idx > 0)
idx--;
}
ra->rpt_time = dynamic_tx_rpt_timing[idx];
}
static void rtl8188e_rate_down(struct rtl8xxxu_ra_info *ra)
{
u8 rate_id = ra->pre_rate;
u8 lowest_rate = ra->lowest_rate;
u8 highest_rate = ra->highest_rate;
s8 i;
if (rate_id > highest_rate) {
rate_id = highest_rate;
} else if (ra->rate_sgi) {
ra->rate_sgi = 0;
} else if (rate_id > lowest_rate) {
if (rate_id > 0) {
for (i = rate_id - 1; i >= lowest_rate; i--) {
if (ra->ra_use_rate & BIT(i)) {
rate_id = i;
goto rate_down_finish;
}
}
}
} else if (rate_id <= lowest_rate) {
rate_id = lowest_rate;
}
rate_down_finish:
if (ra->ra_waiting_counter == 1) {
ra->ra_waiting_counter++;
ra->ra_pending_counter++;
} else if (ra->ra_waiting_counter > 1) {
ra->ra_waiting_counter = 0;
ra->ra_pending_counter = 0;
}
if (ra->ra_pending_counter >= 4)
ra->ra_pending_counter = 4;
ra->ra_drop_after_down = 1;
ra->decision_rate = rate_id;
rtl8188e_set_tx_rpt_timing(ra, DECREASE_TIMING);
}
static void rtl8188e_rate_up(struct rtl8xxxu_ra_info *ra)
{
u8 rate_id = ra->pre_rate;
u8 highest_rate = ra->highest_rate;
u8 i;
if (ra->ra_waiting_counter == 1) {
ra->ra_waiting_counter = 0;
ra->ra_pending_counter = 0;
} else if (ra->ra_waiting_counter > 1) {
ra->pre_rssi_sta_ra = ra->rssi_sta_ra;
goto rate_up_finish;
}
rtl8188e_set_tx_rpt_timing(ra, DEFAULT_TIMING);
if (rate_id < highest_rate) {
for (i = rate_id + 1; i <= highest_rate; i++) {
if (ra->ra_use_rate & BIT(i)) {
rate_id = i;
goto rate_up_finish;
}
}
} else if (rate_id == highest_rate) {
if (ra->sgi_enable && !ra->rate_sgi)
ra->rate_sgi = 1;
else if (!ra->sgi_enable)
ra->rate_sgi = 0;
} else { /* rate_id > ra->highest_rate */
rate_id = highest_rate;
}
rate_up_finish:
if (ra->ra_waiting_counter == (4 + pending_for_rate_up_fail[ra->ra_pending_counter]))
ra->ra_waiting_counter = 0;
else
ra->ra_waiting_counter++;
ra->decision_rate = rate_id;
}
static void rtl8188e_reset_ra_counter(struct rtl8xxxu_ra_info *ra)
{
u8 rate_id = ra->decision_rate;
ra->nsc_up = (n_threshold_high[rate_id] + n_threshold_low[rate_id]) >> 1;
ra->nsc_down = (n_threshold_high[rate_id] + n_threshold_low[rate_id]) >> 1;
}
static void rtl8188e_rate_decision(struct rtl8xxxu_ra_info *ra)
{
struct rtl8xxxu_priv *priv = container_of(ra, struct rtl8xxxu_priv, ra_info);
const u8 *retry_penalty_idx_0;
const u8 *retry_penalty_idx_1;
const u8 *retry_penalty_up_idx;
u8 rate_id, penalty_id1, penalty_id2;
int i;
if (ra->total == 0)
return;
if (ra->ra_drop_after_down) {
ra->ra_drop_after_down--;
rtl8188e_reset_ra_counter(ra);
return;
}
if (priv->chip_cut == 8) { /* cut I */
retry_penalty_idx_0 = retry_penalty_idx_cut_i[0];
retry_penalty_idx_1 = retry_penalty_idx_cut_i[1];
retry_penalty_up_idx = retry_penalty_up_idx_cut_i;
} else {
retry_penalty_idx_0 = retry_penalty_idx_normal[0];
retry_penalty_idx_1 = retry_penalty_idx_normal[1];
retry_penalty_up_idx = retry_penalty_up_idx_normal;
}
if (ra->rssi_sta_ra < (ra->pre_rssi_sta_ra - 3) ||
ra->rssi_sta_ra > (ra->pre_rssi_sta_ra + 3)) {
ra->pre_rssi_sta_ra = ra->rssi_sta_ra;
ra->ra_waiting_counter = 0;
ra->ra_pending_counter = 0;
}
/* Start RA decision */
if (ra->pre_rate > ra->highest_rate)
rate_id = ra->highest_rate;
else
rate_id = ra->pre_rate;
/* rate down */
if (ra->rssi_sta_ra > rssi_threshold[rate_id])
penalty_id1 = retry_penalty_idx_0[rate_id];
else
penalty_id1 = retry_penalty_idx_1[rate_id];
for (i = 0; i < 5; i++)
ra->nsc_down += ra->retry[i] * retry_penalty[penalty_id1][i];
if (ra->nsc_down > (ra->total * retry_penalty[penalty_id1][5]))
ra->nsc_down -= ra->total * retry_penalty[penalty_id1][5];
else
ra->nsc_down = 0;
/* rate up */
penalty_id2 = retry_penalty_up_idx[rate_id];
for (i = 0; i < 5; i++)
ra->nsc_up += ra->retry[i] * retry_penalty[penalty_id2][i];
if (ra->nsc_up > (ra->total * retry_penalty[penalty_id2][5]))
ra->nsc_up -= ra->total * retry_penalty[penalty_id2][5];
else
ra->nsc_up = 0;
if (ra->nsc_down < n_threshold_low[rate_id] ||
ra->drop > dropping_necessary[rate_id]) {
rtl8188e_rate_down(ra);
rtl8xxxu_update_ra_report(&priv->ra_report, ra->decision_rate,
ra->rate_sgi, priv->ra_report.txrate.bw);
} else if (ra->nsc_up > n_threshold_high[rate_id]) {
rtl8188e_rate_up(ra);
rtl8xxxu_update_ra_report(&priv->ra_report, ra->decision_rate,
ra->rate_sgi, priv->ra_report.txrate.bw);
}
if (ra->decision_rate == ra->pre_rate)
ra->dynamic_tx_rpt_timing_counter++;
else
ra->dynamic_tx_rpt_timing_counter = 0;
if (ra->dynamic_tx_rpt_timing_counter >= 4) {
/* Rate didn't change 4 times, extend RPT timing */
rtl8188e_set_tx_rpt_timing(ra, INCREASE_TIMING);
ra->dynamic_tx_rpt_timing_counter = 0;
}
ra->pre_rate = ra->decision_rate;
rtl8188e_reset_ra_counter(ra);
}
static void rtl8188e_power_training_try_state(struct rtl8xxxu_ra_info *ra)
{
ra->pt_try_state = 0;
switch (ra->pt_mode_ss) {
case 3:
if (ra->decision_rate >= DESC_RATE_MCS13)
ra->pt_try_state = 1;
break;
case 2:
if (ra->decision_rate >= DESC_RATE_MCS5)
ra->pt_try_state = 1;
break;
case 1:
if (ra->decision_rate >= DESC_RATE_48M)
ra->pt_try_state = 1;
break;
case 0:
if (ra->decision_rate >= DESC_RATE_11M)
ra->pt_try_state = 1;
break;
default:
break;
}
if (ra->rssi_sta_ra < 48) {
ra->pt_stage = 0;
} else if (ra->pt_try_state == 1) {
if ((ra->pt_stop_count >= 10) ||
(ra->pt_pre_rssi > ra->rssi_sta_ra + 5) ||
(ra->pt_pre_rssi < ra->rssi_sta_ra - 5) ||
(ra->decision_rate != ra->pt_pre_rate)) {
if (ra->pt_stage == 0)
ra->pt_stage = 1;
else if (ra->pt_stage == 1)
ra->pt_stage = 3;
else
ra->pt_stage = 5;
ra->pt_pre_rssi = ra->rssi_sta_ra;
ra->pt_stop_count = 0;
} else {
ra->ra_stage = 0;
ra->pt_stop_count++;
}
} else {
ra->pt_stage = 0;
ra->ra_stage = 0;
}
ra->pt_pre_rate = ra->decision_rate;
/* TODO: implement the "false alarm" statistics for this */
/* Disable power training when noisy environment */
/* if (p_dm_odm->is_disable_power_training) { */
if (1) {
ra->pt_stage = 0;
ra->ra_stage = 0;
ra->pt_stop_count = 0;
}
}
static void rtl8188e_power_training_decision(struct rtl8xxxu_ra_info *ra)
{
u8 temp_stage;
u32 numsc;
u32 num_total;
u8 stage_id;
u8 j;
numsc = 0;
num_total = ra->total * pt_penalty[5];
for (j = 0; j <= 4; j++) {
numsc += ra->retry[j] * pt_penalty[j];
if (numsc > num_total)
break;
}
j >>= 1;
temp_stage = (ra->pt_stage + 1) >> 1;
if (temp_stage > j)
stage_id = temp_stage - j;
else
stage_id = 0;
ra->pt_smooth_factor = (ra->pt_smooth_factor >> 1) +
(ra->pt_smooth_factor >> 2) +
stage_id * 16 + 2;
if (ra->pt_smooth_factor > 192)
ra->pt_smooth_factor = 192;
stage_id = ra->pt_smooth_factor >> 6;
temp_stage = stage_id * 2;
if (temp_stage != 0)
temp_stage--;
if (ra->drop > 3)
temp_stage = 0;
ra->pt_stage = temp_stage;
}
void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
{
u32 *_rx_desc = (u32 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16));
struct rtl8xxxu_rxdesc16 *rx_desc = (struct rtl8xxxu_rxdesc16 *)_rx_desc;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
u32 tx_rpt_len = rx_desc->pktlen & 0x3ff;
u32 items = tx_rpt_len / TX_RPT2_ITEM_SIZE;
u64 macid_valid = ((u64)_rx_desc[5] << 32) | _rx_desc[4];
u32 macid;
u8 *rpt = skb->data;
bool valid;
u16 min_rpt_time = 0x927c;
dev_dbg(dev, "%s: len: %d items: %d\n", __func__, tx_rpt_len, items);
for (macid = 0; macid < items; macid++) {
valid = false;
if (macid < 64)
valid = macid_valid & BIT(macid);
if (valid) {
ra->retry[0] = le16_to_cpu(*(__le16 *)rpt);
ra->retry[1] = rpt[2];
ra->retry[2] = rpt[3];
ra->retry[3] = rpt[4];
ra->retry[4] = rpt[5];
ra->drop = rpt[6];
ra->total = ra->retry[0] + ra->retry[1] + ra->retry[2] +
ra->retry[3] + ra->retry[4] + ra->drop;
if (ra->total > 0) {
if (ra->ra_stage < 5)
rtl8188e_rate_decision(ra);
else if (ra->ra_stage == 5)
rtl8188e_power_training_try_state(ra);
else /* ra->ra_stage == 6 */
rtl8188e_power_training_decision(ra);
if (ra->ra_stage <= 5)
ra->ra_stage++;
else
ra->ra_stage = 0;
}
} else if (macid == 0) {
dev_warn(dev, "%s: TX report item 0 not valid\n", __func__);
}
dev_dbg(dev, "%s: valid: %d retry: %d %d %d %d %d drop: %d\n",
__func__, valid,
ra->retry[0], ra->retry[1], ra->retry[2],
ra->retry[3], ra->retry[4], ra->drop);
if (min_rpt_time > ra->rpt_time)
min_rpt_time = ra->rpt_time;
rpt += TX_RPT2_ITEM_SIZE;
/*
* We only use macid 0, so only the first item is relevant.
* AP mode will use more of them if it's ever implemented.
*/
break;
}
if (min_rpt_time != ra->pre_min_rpt_time) {
rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, min_rpt_time);
ra->pre_min_rpt_time = min_rpt_time;
}
}
static void rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info *ra)
{
s8 i;
ra->ra_use_rate = ra->rate_mask;
/* Highest rate */
if (ra->ra_use_rate) {
for (i = RATESIZE; i >= 0; i--) {
if (ra->ra_use_rate & BIT(i)) {
ra->highest_rate = i;
break;
}
}
} else {
ra->highest_rate = 0;
}
/* Lowest rate */
if (ra->ra_use_rate) {
for (i = 0; i < RATESIZE; i++) {
if (ra->ra_use_rate & BIT(i)) {
ra->lowest_rate = i;
break;
}
}
} else {
ra->lowest_rate = 0;
}
if (ra->highest_rate > DESC_RATE_MCS7)
ra->pt_mode_ss = 3;
else if (ra->highest_rate > DESC_RATE_54M)
ra->pt_mode_ss = 2;
else if (ra->highest_rate > DESC_RATE_11M)
ra->pt_mode_ss = 1;
else
ra->pt_mode_ss = 0;
}
static void
rtl8188e_update_rate_mask(struct rtl8xxxu_priv *priv,
u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
{
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
ra->rate_id = rateid;
ra->rate_mask = ramask;
ra->sgi_enable = sgi;
rtl8188e_arfb_refresh(ra);
}
void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra)
{
ra->decision_rate = DESC_RATE_MCS7;
ra->pre_rate = DESC_RATE_MCS7;
ra->highest_rate = DESC_RATE_MCS7;
ra->lowest_rate = 0;
ra->rate_id = 0;
ra->rate_mask = 0xfffff;
ra->rssi_sta_ra = 0;
ra->pre_rssi_sta_ra = 0;
ra->sgi_enable = 0;
ra->ra_use_rate = 0xfffff;
ra->nsc_down = (n_threshold_high[DESC_RATE_MCS7] + n_threshold_low[DESC_RATE_MCS7]) / 2;
ra->nsc_up = (n_threshold_high[DESC_RATE_MCS7] + n_threshold_low[DESC_RATE_MCS7]) / 2;
ra->rate_sgi = 0;
ra->rpt_time = 0x927c;
ra->drop = 0;
ra->retry[0] = 0;
ra->retry[1] = 0;
ra->retry[2] = 0;
ra->retry[3] = 0;
ra->retry[4] = 0;
ra->total = 0;
ra->ra_waiting_counter = 0;
ra->ra_pending_counter = 0;
ra->ra_drop_after_down = 0;
ra->pt_try_state = 0;
ra->pt_stage = 5;
ra->pt_smooth_factor = 192;
ra->pt_stop_count = 0;
ra->pt_pre_rate = 0;
ra->pt_pre_rssi = 0;
ra->pt_mode_ss = 0;
ra->ra_stage = 0;
}
struct rtl8xxxu_fileops rtl8188eu_fops = {
.identify_chip = rtl8188eu_identify_chip,
.parse_efuse = rtl8188eu_parse_efuse,
@ -1252,7 +1840,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = {
.disable_rf = rtl8188e_disable_rf,
.usb_quirks = rtl8188e_usb_quirks,
.set_tx_power = rtl8188f_set_tx_power,
.update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
.update_rate_mask = rtl8188e_update_rate_mask,
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v3,
.set_crystal_cap = rtl8188f_set_crystal_cap,

View File

@ -3981,7 +3981,25 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
* Enable TX report and TX report timer for 8723bu/8188eu/...
*/
if (fops->has_tx_report) {
/*
* The RTL8188EU has two types of TX reports:
* rpt_sel=1:
* One report for one frame. We can use this for frames
* with IEEE80211_TX_CTL_REQ_TX_STATUS.
* rpt_sel=2:
* One report for many frames transmitted over a period
* of time. (This is what REG_TX_REPORT_TIME is for.) The
* report includes the number of frames transmitted
* successfully, and the number of unsuccessful
* transmissions. We use this for software rate control.
*
* Bit 0 of REG_TX_REPORT_CTRL is required for both types.
* Bit 1 (TX_REPORT_CTRL_TIMER_ENABLE) is required for
* type 2.
*/
val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
if (priv->rtl_chip == RTL8188E)
val8 |= BIT(0);
val8 |= TX_REPORT_CTRL_TIMER_ENABLE;
rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
/* Set MAX RPT MACID */
@ -4274,6 +4292,9 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
priv->cfo_tracking.crystal_cap = priv->default_crystal_cap;
}
if (priv->rtl_chip == RTL8188E)
rtl8188e_ra_info_init_all(&priv->ra_info);
exit:
return ret;
}
@ -4637,8 +4658,8 @@ static void rtl8xxxu_set_aifs(struct rtl8xxxu_priv *priv, u8 slot_time)
}
}
static void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
u8 rate, u8 sgi, u8 bw)
void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
u8 rate, u8 sgi, u8 bw)
{
u8 mcs, nss;
@ -5122,6 +5143,7 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
u32 rate;
@ -5137,9 +5159,10 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
if (ieee80211_is_data(hdr->frame_control)) {
rate = DESC_RATE_MCS7; /* TODO: software rate control */
rate = ra->decision_rate;
tx_desc->txdw5 = cpu_to_le32(rate);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE);
tx_desc->txdw4 |= le32_encode_bits(ra->pt_stage, TXDESC32_PT_STAGE_MASK);
/* Data/RTS rate FB limit */
tx_desc->txdw5 |= cpu_to_le32(0x0001ff00);
}
@ -5178,7 +5201,7 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
if (short_preamble)
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_SHORT_PREAMBLE);
if (sgi)
if (sgi && ra->rate_sgi)
tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI);
/*
@ -5769,6 +5792,44 @@ static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv,
schedule_work(&priv->c2hcmd_work);
}
static void rtl8188e_c2hcmd_callback(struct work_struct *work)
{
struct rtl8xxxu_priv *priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work);
struct device *dev = &priv->udev->dev;
struct sk_buff *skb = NULL;
struct rtl8xxxu_rxdesc16 *rx_desc;
while (!skb_queue_empty(&priv->c2hcmd_queue)) {
skb = skb_dequeue(&priv->c2hcmd_queue);
rx_desc = (struct rtl8xxxu_rxdesc16 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16));
switch (rx_desc->rpt_sel) {
case 1:
dev_dbg(dev, "C2H TX report type 1\n");
break;
case 2:
dev_dbg(dev, "C2H TX report type 2\n");
rtl8188e_handle_ra_tx_report2(priv, skb);
break;
case 3:
dev_dbg(dev, "C2H USB interrupt report\n");
break;
default:
dev_warn(dev, "%s: rpt_sel should not be %d\n",
__func__, rx_desc->rpt_sel);
break;
}
dev_kfree_skb(skb);
}
}
int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
{
struct ieee80211_hw *hw = priv->hw;
@ -5824,39 +5885,46 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc16));
phy_stats = (struct rtl8723au_phy_stats *)skb->data;
skb_pull(skb, drvinfo_sz + desc_shift);
skb_trim(skb, pkt_len);
if (rx_desc->phy_stats)
rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats,
rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data,
rx_desc->crc32 || rx_desc->icverr);
rx_status->mactime = rx_desc->tsfl;
rx_status->flag |= RX_FLAG_MACTIME_START;
if (!rx_desc->swdec)
rx_status->flag |= RX_FLAG_DECRYPTED;
if (rx_desc->crc32)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (rx_desc->bw)
rx_status->bw = RATE_INFO_BW_40;
if (rx_desc->rxht) {
rx_status->encoding = RX_ENC_HT;
rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
if (rx_desc->rpt_sel) {
skb_queue_tail(&priv->c2hcmd_queue, skb);
schedule_work(&priv->c2hcmd_work);
} else {
rx_status->rate_idx = rx_desc->rxmcs;
phy_stats = (struct rtl8723au_phy_stats *)skb->data;
skb_pull(skb, drvinfo_sz + desc_shift);
skb_trim(skb, pkt_len);
if (rx_desc->phy_stats)
rtl8xxxu_rx_parse_phystats(
priv, rx_status, phy_stats,
rx_desc->rxmcs,
(struct ieee80211_hdr *)skb->data,
rx_desc->crc32 || rx_desc->icverr);
rx_status->mactime = rx_desc->tsfl;
rx_status->flag |= RX_FLAG_MACTIME_START;
if (!rx_desc->swdec)
rx_status->flag |= RX_FLAG_DECRYPTED;
if (rx_desc->crc32)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (rx_desc->bw)
rx_status->bw = RATE_INFO_BW_40;
if (rx_desc->rxht) {
rx_status->encoding = RX_ENC_HT;
rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
} else {
rx_status->rate_idx = rx_desc->rxmcs;
}
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
ieee80211_rx_irqsafe(hw, skb);
}
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
ieee80211_rx_irqsafe(hw, skb);
skb = next_skb;
if (skb)
skb_pull(next_skb, pkt_offset);
@ -6942,7 +7010,6 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
spin_lock_init(&priv->rx_urb_lock);
INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback);
INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback);
skb_queue_head_init(&priv->c2hcmd_queue);
usb_set_intfdata(interface, hw);
@ -6960,6 +7027,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
hw->wiphy->available_antennas_tx = BIT(priv->tx_paths) - 1;
hw->wiphy->available_antennas_rx = BIT(priv->rx_paths) - 1;
if (priv->rtl_chip == RTL8188E)
INIT_WORK(&priv->c2hcmd_work, rtl8188e_c2hcmd_callback);
else
INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback);
ret = rtl8xxxu_read_efuse(priv);
if (ret) {
dev_err(&udev->dev, "Fatal - failed to read EFuse\n");