rtl8180: make *IFS and CW tunable by mac80211, and set them in the proper place

SLOT, SIFS, DIFS, EIFS, CW and ACK-timeout registers are set in an
RF-code callback and their values are fixed.

This patch moves this off the rf-code, and introduce two new functions
that calculate these values depending by slot time and CW values
requested by mac80211.

This seems to improve performances on my setup.

Currently the ack and slot time values could be stored in a local
variable, but this patch stores it in the driver "priv" structure
because it will be useful for rtl8187se support that will be added
(hopefully) soon.

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Andrea Merello 2014-03-15 18:29:37 +01:00 committed by John W. Linville
parent 516a093019
commit 9069af794e
3 changed files with 83 additions and 24 deletions

View File

@ -866,6 +866,72 @@ static int rtl8180_config(struct ieee80211_hw *dev, u32 changed)
return 0;
}
static int rtl8180_conf_tx(struct ieee80211_hw *dev,
struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct rtl8180_priv *priv = dev->priv;
u8 cw_min, cw_max;
/* nothing to do ? */
if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180)
return 0;
cw_min = fls(params->cw_min);
cw_max = fls(params->cw_max);
rtl818x_iowrite8(priv, &priv->map->CW_VAL, (cw_max << 4) | cw_min);
return 0;
}
static void rtl8180_conf_erp(struct ieee80211_hw *dev,
struct ieee80211_bss_conf *info)
{
struct rtl8180_priv *priv = dev->priv;
u8 sifs, difs;
int eifs;
u8 hw_eifs;
/* TODO: should we do something ? */
if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180)
return;
/* I _hope_ this means 10uS for the HW.
* In reference code it is 0x22 for
* both rtl8187L and rtl8187SE
*/
sifs = 0x22;
if (info->use_short_slot)
priv->slot_time = 9;
else
priv->slot_time = 20;
/* 10 is SIFS time in uS */
difs = 10 + 2 * priv->slot_time;
eifs = 10 + difs + priv->ack_time;
/* HW should use 4uS units for EIFS (I'm sure for rtl8185)*/
hw_eifs = DIV_ROUND_UP(eifs, 4);
rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time);
rtl818x_iowrite8(priv, &priv->map->SIFS, sifs);
rtl818x_iowrite8(priv, &priv->map->DIFS, difs);
/* from reference code. set ack timeout reg = eifs reg */
rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, hw_eifs);
/* rtl8187/rtl8185 HW bug. After EIFS is elapsed,
* the HW still wait for DIFS.
* HW uses 4uS units for EIFS.
*/
hw_eifs = DIV_ROUND_UP(eifs - difs, 4);
rtl818x_iowrite8(priv, &priv->map->EIFS, hw_eifs);
}
static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@ -896,8 +962,20 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
if (changed & BSS_CHANGED_BASIC_RATES)
rtl8180_conf_basic_rates(dev, info->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
priv->rf->conf_erp(dev, info);
if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) {
/* when preamble changes, acktime duration changes, and erp must
* be recalculated. ACK time is calculated at lowest rate.
* Since mac80211 include SIFS time we remove it (-10)
*/
priv->ack_time =
le16_to_cpu(ieee80211_generic_frame_duration(dev,
priv->vif,
IEEE80211_BAND_2GHZ, 10,
&priv->rates[0])) - 10;
rtl8180_conf_erp(dev, info);
}
if (changed & BSS_CHANGED_BEACON_ENABLED)
vif_priv->enable_beacon = info->enable_beacon;
@ -955,6 +1033,7 @@ static const struct ieee80211_ops rtl8180_ops = {
.remove_interface = rtl8180_remove_interface,
.config = rtl8180_config,
.bss_info_changed = rtl8180_bss_info_changed,
.conf_tx = rtl8180_conf_tx,
.prepare_multicast = rtl8180_prepare_multicast,
.configure_filter = rtl8180_configure_filter,
.get_tsf = rtl8180_get_tsf,

View File

@ -81,6 +81,8 @@ struct rtl8180_priv {
struct ieee80211_supported_band band;
struct pci_dev *pdev;
u32 rx_conf;
u8 slot_time;
u16 ack_time;
enum {
RTL818X_CHIP_FAMILY_RTL8180,

View File

@ -730,32 +730,11 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
msleep(10);
}
static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
struct ieee80211_bss_conf *info)
{
struct rtl8180_priv *priv = dev->priv;
if (info->use_short_slot) {
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
} else {
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44);
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
}
}
static const struct rtl818x_rf_ops rtl8225_ops = {
.name = "rtl8225",
.init = rtl8225_rf_init,
.stop = rtl8225_rf_stop,
.set_chan = rtl8225_rf_set_channel,
.conf_erp = rtl8225_rf_conf_erp,
};
static const struct rtl818x_rf_ops rtl8225z2_ops = {
@ -763,7 +742,6 @@ static const struct rtl818x_rf_ops rtl8225z2_ops = {
.init = rtl8225z2_rf_init,
.stop = rtl8225_rf_stop,
.set_chan = rtl8225_rf_set_channel,
.conf_erp = rtl8225_rf_conf_erp,
};
const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)