rtl8180: make *IFS and CW tunable by mac80211, and set them in the proper place
authorAndrea Merello <andrea.merello@gmail.com>
Sat, 15 Mar 2014 17:29:37 +0000 (18:29 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 17 Mar 2014 17:44:15 +0000 (13:44 -0400)
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>
drivers/net/wireless/rtl818x/rtl8180/dev.c
drivers/net/wireless/rtl818x/rtl8180/rtl8180.h
drivers/net/wireless/rtl818x/rtl8180/rtl8225.c

index ede8fee1333241eb64d304e93c32eb0bd844a973..9ee68fdc05353d44b14db02ee7574ec5aee5e235 100644 (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,
index c2f1c9d5a3bb4779ae9daa8c558c8fc99c06b303..7014bf0051a3ef9eb75f3cf2ad592221523d495f 100644 (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,
index d60a5f399022447c81130e7edc9e60d45d59a3c0..1c0fe238d995326b81d026abe69bd1f251b8ae3e 100644 (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)