Commit 8b9754b2 authored by Bitterblue Smith's avatar Bitterblue Smith Committed by Kalle Valo

wifi: rtl8xxxu: Add rate control code for RTL8188EU

Copied from the newer vendor driver, v5.2.2.4.
Signed-off-by: default avatarBitterblue Smith <rtl8821cerfe2@gmail.com>
Reviewed-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/5acc1e5d-62d6-3a6a-0f9e-cbc8b809b1d7@gmail.com
parent 3dfb8e84
......@@ -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;
......
......@@ -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,38 +5885,45 @@ 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;
if (rx_desc->rpt_sel) {
skb_queue_tail(&priv->c2hcmd_queue, skb);
schedule_work(&priv->c2hcmd_work);
} else {
phy_stats = (struct rtl8723au_phy_stats *)skb->data;
skb_pull(skb, drvinfo_sz + desc_shift);
skb_pull(skb, drvinfo_sz + desc_shift);
skb_trim(skb, pkt_len);
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);
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;
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->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;
}
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;
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
ieee80211_rx_irqsafe(hw, skb);
ieee80211_rx_irqsafe(hw, skb);
}
skb = next_skb;
if (skb)
......@@ -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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment