#852: madwifi HAL does not do binary exponential backoff
-----------------------------------+----------------------------------------
      Reporter:  [EMAIL PROTECTED]  |       Owner:       
          Type:  defect            |      Status:  new  
      Priority:  major             |   Milestone:       
     Component:  madwifi: HAL      |     Version:  trunk
    Resolution:                    |    Keywords:  beb  
Patch_attached:  1                 |  
-----------------------------------+----------------------------------------
Changes (by mrenzmann):

  * version:  => trunk

Old description:

> A simple experiment shows beb (binary exponential backoff) is not done in
> the madwifi HAL. I use a netgear wag311 card and a single computer
> sending out 1500 b frames. I add a simple DPRINTF to see at what time the
> function ath_tx_processq is called. I make sure that in one experiment
> txs_longretry of ath_tx_status struct is 11. In another experiement I
> make sure it is 1. I use a valid but unreachable ethernet address. I
> observe that ath_tx_processq is called at intervals ~10 times larger when
> txs_longretry=11 than when txs_longretry=1. My cwmin is 31, and cwmax is
> 1023. I then perform a different experiment where I send out 1500 b
> frames with longretry=1 and perform beb in the driver by doubling
> relevant cwmin up to 9 retries when ath_tx_processq is called. The time
> intervals at which ath_tx_processq is called are what you would expect
> (i.e. exponentially increasing along with the cwmin) s.t. the overall
> time for 10 retries is much larger than the 10x I would see in the
> previous experiment.
>
> If interested in a patch that enables the functionality I mention above:
> {{{
> Index: ath/if_ath.c
> ===================================================================
> --- ath/if_ath.c        (revision 1705)
> +++ ath/if_ath.c        (working copy)
> @@ -255,6 +255,7 @@
>  static int countrycode = -1;
>  static int outdoor = -1;
>  static int xchanmode = -1;
> +static int ieeemode = -1;                      /* select channels by
> IEEE mode */
>
>  static const char *hal_status_desc[] = {
>         "No error",
> @@ -285,6 +286,7 @@
>  MODULE_PARM(xchanmode, "i");
>  MODULE_PARM(rfkill, "i");
>  MODULE_PARM(autocreate, "s");
> +MODULE_PARM(ieeemode, "i");
>  #else
>  #include <linux/moduleparam.h>
>  module_param(countrycode, int, 0);
> @@ -292,13 +294,17 @@
>  module_param(xchanmode, int, 0);
>  module_param(rfkill, int, 0);
>  module_param(autocreate, charp, 0);
> +module_param(ieeemode, int, 0);
>  #endif
>  MODULE_PARM_DESC(countrycode, "Override default country code");
>  MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use");
>  MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode");
>  MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability");
>  MODULE_PARM_DESC(autocreate, "Create ath device in
> [sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use 'none' to
> disable");
> +MODULE_PARM_DESC(ieeemode, "Restrict 80211 mode ");
>
> +static int     firstdevice = 1; // set to 0 as soon as one device
> initialized
> +
>  static int     ath_debug = 0;
>  #ifdef AR_DEBUG
>  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
> @@ -335,12 +341,19 @@
>         ATH_DEBUG_TURBO         = 0x00400000,   /* turbo/dynamice turbo
> */
>         ATH_DEBUG_UAPSD         = 0x00800000,   /* uapsd */
>         ATH_DEBUG_DOTH          = 0x01000000,   /* 11.h */
> +       ATH_DEBUG_TIME          = 0x20000000,   /* use CURRENT_TIME on
> all debug printouts! */
> +        ATH_DEBUG_SZYM          = 0x40000000,   /* szym routines */
>         ATH_DEBUG_FATAL         = 0x80000000,   /* fatal errors */
>         ATH_DEBUG_ANY           = 0xffffffff
>  };
>  #define        DPRINTF(sc, _m, _fmt, ...) do {                         \
> -       if (sc->sc_debug & (_m))                                \
> +       if (sc->sc_debug & (_m)) {                              \
> +               if (sc->sc_debug & ATH_DEBUG_TIME) {            \
> +                       struct timespec ct = CURRENT_TIME;      \
> +                       printk("%ld.%09ld ", ct.tv_sec, ct.tv_nsec);    \
> +               }                                               \
>                 printk(_fmt, __VA_ARGS__);                      \
> +       }                                                       \
>  } while (0)
>  #define        KEYPRINTF(sc, ix, hk, mac) do {                         \
>         if (sc->sc_debug & ATH_DEBUG_KEYCACHE)                  \
> @@ -390,6 +403,18 @@
>         int autocreatemode = IEEE80211_M_STA;
>         u_int8_t csz;
>
> +       if(firstdevice == 0) {
> +               printk("%s 0x%x: not first device...\n", dev->name,
> devid);
> +               if(countrycode == 0x1ff) {
> +                       printk("%s 0x%x: Countrycode 0x1ff forbidden for
> non first devices!\n", dev->name, devid);
> +                       countrycode = 0x0;
> +               }
> +       }
> +       if(countrycode != 0x1ff && ieeemode != -1) {
> +               printk("%s 0x%x: ieeemode makes no sense for non-debug
> countrycode\n", dev->name, devid);
> +               ieeemode = -1;
> +       }
> +
>         sc->devid = devid;
>         sc->sc_debug = ath_debug;
>         DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
> @@ -902,6 +927,8 @@
>                                 dev->name, error);
>         }
>
> +       firstdevice = 0;
> +
>         return 0;
>  bad3:
>         ieee80211_ifdetach(ic);
> @@ -5469,7 +5496,7 @@
>                          * allow through packets that have crypto
> problems).
>                          */
>                         if ((ds->ds_rxstat.rs_status &~
> -                               (HAL_RXERR_DECRYPT|HAL_RXERR_MIC)) ||
> +
> (HAL_RXERR_DECRYPT|HAL_RXERR_MIC|HAL_RXERR_CRC)) ||
>                             sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
>                                 goto rx_next;
>                 }
> @@ -7008,6 +7035,94 @@
>  #undef MIN
>  }
>
> +static uint16_t
> +szym_get_cw(struct ath_softc *sc, int get_min) {
> +        struct ath_hal *ah = sc->sc_ah;
> +        HAL_TXQ_INFO qi;
> +        u_int qnum = sc->sc_ac2q[WME_AC_BE]->axq_qnum;
> +
> +        ath_hal_gettxqueueprops(ah, qnum, &qi);
> +        if (get_min) {
> +                return qi.tqi_cwmin;
> +        } else {
> +                return qi.tqi_cwmax;
> +        }
> +}
> +
> +static void
> +szym_set_cw(struct ath_softc *sc, int set_min, uint16_t cw) {
> +        struct ath_hal *ah = sc->sc_ah;
> +        HAL_TXQ_INFO qi;
> +        u_int qnum = sc->sc_ac2q[WME_AC_BE]->axq_qnum;
> +
> +        ath_hal_gettxqueueprops(ah, qnum, &qi);
> +        if (set_min && cw <= qi.tqi_cwmax) {
> +               DPRINTF(sc, ATH_DEBUG_SZYM, "szym cwmin %d\n", cw);
> +                qi.tqi_cwmin = cw;
> +        } else if(cw >= qi.tqi_cwmin) {
> +               DPRINTF(sc, ATH_DEBUG_SZYM, "szym cwmax %d\n", cw);
> +                qi.tqi_cwmax = cw;
> +        }
> +        if (!ath_hal_settxqueueprops(ah, qnum, &qi)) {
> +                printk("SZYM: unable to update hardware queue "
> +                                "paramers!\n");
> +        } else {
> +                ath_hal_resettxqueue(ah, qnum); /* push to h/w */
> +        }
> +}
> +
> +
> +static void
> +szym_tx_updatecw(struct ath_softc *sc, struct ath_txq *txq, struct
> ath_tx_status *txs) {
> +        struct ath_hal *ah = sc->sc_ah;
> +        HAL_TXQ_INFO qi;
> +
> +        struct timespec ct = CURRENT_TIME;
> +
> +       u_int32_t tsf = 0;
> +
> +       // XXX
> +        if (sc->sc_szym_cw == -1)
> +                return;
> +
> +       tsf = ath_hal_gettsf32(sc->sc_ah);
> +       if ((tsf & 0x7fff) < txs->ts_tstamp)
> +               tsf -= 0x8000;
> +       tsf = txs->ts_tstamp | (tsf &~ 0x7fff);
> +
> +       ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
> +
> +        DPRINTF(sc, ATH_DEBUG_SZYM, "szym %ld.%09ld ts %u txs %d srty %d
> lrty %d cwmin %d cwmax %d myrty %d\n",
> +                        ct.tv_sec, ct.tv_nsec,
> +                        tsf,
> +                        txs->ts_status, txs->ts_shortretry,
> txs->ts_longretry,
> +                        qi.tqi_cwmin, qi.tqi_cwmax,
> sc->sc_szym_retries);
> +
> +        if (sc->sc_szym_cw == 0 || txq != sc->sc_ac2q[WME_AC_BE])
> +                return;
> +
> +        if (txs->ts_status == 0 || sc->sc_szym_retries >=
> sc->sc_szym_max_retries) {
> +                /* the frame was successful (or no ACK needed or max
> retries hit), reset cwmin here */
> +                qi.tqi_cwmin = (1<<(sc->sc_ic.ic_wme.wme_chanParams.
> +                                cap_wmeParams[WME_AC_BE].wmep_logcwmin))
> - 1;
> +                sc->sc_szym_retries = 0;
> +        } else {
> +                /* the frame failed, double cwmin */
> +                if ((qi.tqi_cwmin<<1) < qi.tqi_cwmax) {
> +                        qi.tqi_cwmin = (qi.tqi_cwmin<<1) + 1;
> +                }
> +               if(sc->sc_szym_cw > 1)
> +                    ++sc->sc_szym_retries;
> +        }
> +        if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) {
> +                printk("SZYM: unable to update hardware queue "
> +                                "parameters\n");
> +        } else {
> +                if(1) ath_hal_resettxqueue(ah, txq->axq_qnum); /* push
> to h/w */
> +        }
> +//        ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
> +}
> +
>  /*
>   * Process completed xmit descriptors from the specified queue.
>   * Should only be called from tasklet context
> @@ -7138,6 +7253,7 @@
>                          */
>                          ieee80211_free_node(ni);
>                 }
> +               szym_tx_updatecw(sc, txq, &(ds->ds_txstat));
>
>                 bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
>                                   bf->bf_skb->len, BUS_DMA_TODEVICE);
> @@ -8388,15 +8504,21 @@
>         struct ath_hal *ah = sc->sc_ah;
>         HAL_CHANNEL *chans;
>         int i, nchan;
> +       u_int mode = HAL_MODE_ALL;
>
>         chans = kmalloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL),
> GFP_KERNEL);
>         if (chans == NULL) {
>                 printk("%s: unable to allocate channel table\n",
> dev->name);
>                 return -ENOMEM;
>         }
> +
> +       if(ieeemode != -1) {
> +               mode = ieeemode;
> +       }
> +
>         if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
>             ic->ic_regclassids, IEEE80211_REGCLASSIDS_MAX,
> &ic->ic_nregclass,
> -           cc, HAL_MODE_ALL, outdoor, xchanmode)) {
> +           cc, mode, outdoor, xchanmode)) {
>                 u_int32_t rd;
>
>                 ath_hal_getregdomain(ah, &rd);
> @@ -9072,6 +9194,11 @@
>         ATH_XR_POLL_PERIOD      = 20,
>         ATH_XR_POLL_COUNT       = 21,
>         ATH_ACKRATE             = 22,
> +       ATH_SZYM_CW             = 23,
> +        ATH_SZYM_CWMIN         = 24,
> +        ATH_SZYM_CWMAX         = 25,
> +        ATH_SZYM_CWMIND        = 26,
> +       ATH_SZYM_MAX_RETRIES    = 27,
>  };
>
>  static int
> @@ -9201,6 +9328,22 @@
>                                 sc->sc_ackrate = val;
>                                 ath_set_ack_bitrate(sc, sc->sc_ackrate);
>                                 break;
> +                       case ATH_SZYM_CW:
> +                               sc->sc_szym_cw = val;
> +                               DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s:
> szym_cw = %d", __func__, val);
> +                               break;
> +                        case ATH_SZYM_CWMIN: case ATH_SZYM_CWMAX:
> +                                szym_set_cw(sc, ctl->ctl_name ==
> ATH_SZYM_CWMIN, val);
> +                                break;
> +                        case ATH_SZYM_CWMIND:
> +                                sc->sc_ic.ic_wme.wme_chanParams.
> +
> cap_wmeParams[WME_AC_BE].wmep_logcwmin = val;
> +                               DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s:
> szym_cwmind = %d", __func__, val);
> +                                break;
> +                       case ATH_SZYM_MAX_RETRIES:
> +                               sc->sc_szym_max_retries = val;
> +                               DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s:
> szym_max_retries = %d", __func__, val);
> +                                break;
>                         default:
>                                 return -EINVAL;
>                         }
> @@ -9260,6 +9403,19 @@
>                 case ATH_ACKRATE:
>                         val = sc->sc_ackrate;
>                         break;
> +               case ATH_SZYM_CW:
> +                       val = sc->sc_szym_cw;
> +                       break;
> +                case ATH_SZYM_CWMIN: case ATH_SZYM_CWMAX:
> +                        val = szym_get_cw(sc, ctl->ctl_name ==
> ATH_SZYM_CWMIN);
> +                        break;
> +                case ATH_SZYM_CWMIND:
> +                        val = sc->sc_ic.ic_wme.wme_chanParams.
> +                                cap_wmeParams[WME_AC_BE].wmep_logcwmin;
> +                        break;
> +                case ATH_SZYM_MAX_RETRIES:
> +                        val = sc->sc_szym_max_retries;
> +                        break;
>                 default:
>                         return -EINVAL;
>                 }
> @@ -9363,6 +9519,31 @@
>           .mode         = 0644,
>           .proc_handler = ath_sysctl_halparam
>         },
> +       { .ctl_name     = ATH_SZYM_CW,
> +       .procname       = "szym_cw",
> +       .mode           = 0644,
> +       .proc_handler   = ath_sysctl_halparam
> +       },
> +        { .ctl_name     = ATH_SZYM_CWMIN,
> +          .procname     = "szym_cwmin",  /* FIXME: currently only for
> the BE queue */
> +          .mode         = 0644,
> +          .proc_handler = ath_sysctl_halparam
> +        },
> +        { .ctl_name     = ATH_SZYM_CWMAX,
> +          .procname     = "szym_cwmax",
> +          .mode         = 0644,
> +          .proc_handler = ath_sysctl_halparam
> +        },
> +        { .ctl_name     = ATH_SZYM_CWMIND,
> +          .procname     = "szym_cwmind",
> +          .mode         = 0644,
> +          .proc_handler = ath_sysctl_halparam
> +        },
> +        { .ctl_name     = ATH_SZYM_MAX_RETRIES,
> +          .procname     = "szym_retries",
> +          .mode         = 0644,
> +          .proc_handler = ath_sysctl_halparam
> +        },
>         { 0 }
>  };
>

> Index: ath/if_athvar.h
> ===================================================================
> --- ath/if_athvar.h     (revision 1705)
> +++ ath/if_athvar.h     (working copy)
> @@ -673,6 +673,11 @@
>         u_int32_t sc_dturbo_bw_turbo;           /* bandwidth threshold */
>  #endif
>         u_int sc_slottimeconf;                  /* manual override for
> slottime */
> +
> +
> +       u_int sc_szym_cw;                       /* enable
> szym_tx_updatecw */
> +       u_int sc_szym_retries;                  /* current retry count */
> +       u_int sc_szym_max_retries;              /* max retry count */
>  };
>
>  typedef void (*ath_callback) (struct ath_softc *);
>

> }}}

New description:

 A simple experiment shows beb (binary exponential backoff) is not done in
 the madwifi HAL. I use a netgear wag311 card and a single computer sending
 out 1500 b frames. I add a simple DPRINTF to see at what time the function
 ath_tx_processq is called. I make sure that in one experiment
 txs_longretry of ath_tx_status struct is 11. In another experiement I make
 sure it is 1. I use a valid but unreachable ethernet address. I observe
 that ath_tx_processq is called at intervals ~10 times larger when
 txs_longretry=11 than when txs_longretry=1. My cwmin is 31, and cwmax is
 1023. I then perform a different experiment where I send out 1500 b frames
 with longretry=1 and perform beb in the driver by doubling relevant cwmin
 up to 9 retries when ath_tx_processq is called. The time intervals at
 which ath_tx_processq is called are what you would expect (i.e.
 exponentially increasing along with the cwmin) s.t. the overall time for
 10 retries is much larger than the 10x I would see in the previous
 experiment.

 If interested in a patch that enables the functionality I mention above:
 {{{
 Index: ath/if_ath.c
 ===================================================================
 --- ath/if_ath.c        (revision 1705)
 +++ ath/if_ath.c        (working copy)
 @@ -255,6 +255,7 @@
  static int countrycode = -1;
  static int outdoor = -1;
  static int xchanmode = -1;
 +static int ieeemode = -1;                      /* select channels by IEEE
 mode */

  static const char *hal_status_desc[] = {
         "No error",
 @@ -285,6 +286,7 @@
  MODULE_PARM(xchanmode, "i");
  MODULE_PARM(rfkill, "i");
  MODULE_PARM(autocreate, "s");
 +MODULE_PARM(ieeemode, "i");
  #else
  #include <linux/moduleparam.h>
  module_param(countrycode, int, 0);
 @@ -292,13 +294,17 @@
  module_param(xchanmode, int, 0);
  module_param(rfkill, int, 0);
  module_param(autocreate, charp, 0);
 +module_param(ieeemode, int, 0);
  #endif
  MODULE_PARM_DESC(countrycode, "Override default country code");
  MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use");
  MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode");
  MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability");
  MODULE_PARM_DESC(autocreate, "Create ath device in
 [sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use 'none' to
 disable");
 +MODULE_PARM_DESC(ieeemode, "Restrict 80211 mode ");

 +static int     firstdevice = 1; // set to 0 as soon as one device
 initialized
 +
  static int     ath_debug = 0;
  #ifdef AR_DEBUG
  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
 @@ -335,12 +341,19 @@
         ATH_DEBUG_TURBO         = 0x00400000,   /* turbo/dynamice turbo */
         ATH_DEBUG_UAPSD         = 0x00800000,   /* uapsd */
         ATH_DEBUG_DOTH          = 0x01000000,   /* 11.h */
 +       ATH_DEBUG_TIME          = 0x20000000,   /* use CURRENT_TIME on all
 debug printouts! */
 +        ATH_DEBUG_SZYM          = 0x40000000,   /* szym routines */
         ATH_DEBUG_FATAL         = 0x80000000,   /* fatal errors */
         ATH_DEBUG_ANY           = 0xffffffff
  };
  #define        DPRINTF(sc, _m, _fmt, ...) do {                         \
 -       if (sc->sc_debug & (_m))                                \
 +       if (sc->sc_debug & (_m)) {                              \
 +               if (sc->sc_debug & ATH_DEBUG_TIME) {            \
 +                       struct timespec ct = CURRENT_TIME;      \
 +                       printk("%ld.%09ld ", ct.tv_sec, ct.tv_nsec);    \
 +               }                                               \
                 printk(_fmt, __VA_ARGS__);                      \
 +       }                                                       \
  } while (0)
  #define        KEYPRINTF(sc, ix, hk, mac) do {                         \
         if (sc->sc_debug & ATH_DEBUG_KEYCACHE)                  \
 @@ -390,6 +403,18 @@
         int autocreatemode = IEEE80211_M_STA;
         u_int8_t csz;

 +       if(firstdevice == 0) {
 +               printk("%s 0x%x: not first device...\n", dev->name,
 devid);
 +               if(countrycode == 0x1ff) {
 +                       printk("%s 0x%x: Countrycode 0x1ff forbidden for
 non first devices!\n", dev->name, devid);
 +                       countrycode = 0x0;
 +               }
 +       }
 +       if(countrycode != 0x1ff && ieeemode != -1) {
 +               printk("%s 0x%x: ieeemode makes no sense for non-debug
 countrycode\n", dev->name, devid);
 +               ieeemode = -1;
 +       }
 +
         sc->devid = devid;
         sc->sc_debug = ath_debug;
         DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
 @@ -902,6 +927,8 @@
                                 dev->name, error);
         }

 +       firstdevice = 0;
 +
         return 0;
  bad3:
         ieee80211_ifdetach(ic);
 @@ -5469,7 +5496,7 @@
                          * allow through packets that have crypto
 problems).
                          */
                         if ((ds->ds_rxstat.rs_status &~
 -                               (HAL_RXERR_DECRYPT|HAL_RXERR_MIC)) ||
 +
 (HAL_RXERR_DECRYPT|HAL_RXERR_MIC|HAL_RXERR_CRC)) ||
                             sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
                                 goto rx_next;
                 }
 @@ -7008,6 +7035,94 @@
  #undef MIN
  }

 +static uint16_t
 +szym_get_cw(struct ath_softc *sc, int get_min) {
 +        struct ath_hal *ah = sc->sc_ah;
 +        HAL_TXQ_INFO qi;
 +        u_int qnum = sc->sc_ac2q[WME_AC_BE]->axq_qnum;
 +
 +        ath_hal_gettxqueueprops(ah, qnum, &qi);
 +        if (get_min) {
 +                return qi.tqi_cwmin;
 +        } else {
 +                return qi.tqi_cwmax;
 +        }
 +}
 +
 +static void
 +szym_set_cw(struct ath_softc *sc, int set_min, uint16_t cw) {
 +        struct ath_hal *ah = sc->sc_ah;
 +        HAL_TXQ_INFO qi;
 +        u_int qnum = sc->sc_ac2q[WME_AC_BE]->axq_qnum;
 +
 +        ath_hal_gettxqueueprops(ah, qnum, &qi);
 +        if (set_min && cw <= qi.tqi_cwmax) {
 +               DPRINTF(sc, ATH_DEBUG_SZYM, "szym cwmin %d\n", cw);
 +                qi.tqi_cwmin = cw;
 +        } else if(cw >= qi.tqi_cwmin) {
 +               DPRINTF(sc, ATH_DEBUG_SZYM, "szym cwmax %d\n", cw);
 +                qi.tqi_cwmax = cw;
 +        }
 +        if (!ath_hal_settxqueueprops(ah, qnum, &qi)) {
 +                printk("SZYM: unable to update hardware queue "
 +                                "paramers!\n");
 +        } else {
 +                ath_hal_resettxqueue(ah, qnum); /* push to h/w */
 +        }
 +}
 +
 +
 +static void
 +szym_tx_updatecw(struct ath_softc *sc, struct ath_txq *txq, struct
 ath_tx_status *txs) {
 +        struct ath_hal *ah = sc->sc_ah;
 +        HAL_TXQ_INFO qi;
 +
 +        struct timespec ct = CURRENT_TIME;
 +
 +       u_int32_t tsf = 0;
 +
 +       // XXX
 +        if (sc->sc_szym_cw == -1)
 +                return;
 +
 +       tsf = ath_hal_gettsf32(sc->sc_ah);
 +       if ((tsf & 0x7fff) < txs->ts_tstamp)
 +               tsf -= 0x8000;
 +       tsf = txs->ts_tstamp | (tsf &~ 0x7fff);
 +
 +       ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
 +
 +        DPRINTF(sc, ATH_DEBUG_SZYM, "szym %ld.%09ld ts %u txs %d srty %d
 lrty %d cwmin %d cwmax %d myrty %d\n",
 +                        ct.tv_sec, ct.tv_nsec,
 +                        tsf,
 +                        txs->ts_status, txs->ts_shortretry,
 txs->ts_longretry,
 +                        qi.tqi_cwmin, qi.tqi_cwmax, sc->sc_szym_retries);
 +
 +        if (sc->sc_szym_cw == 0 || txq != sc->sc_ac2q[WME_AC_BE])
 +                return;
 +
 +        if (txs->ts_status == 0 || sc->sc_szym_retries >=
 sc->sc_szym_max_retries) {
 +                /* the frame was successful (or no ACK needed or max
 retries hit), reset cwmin here */
 +                qi.tqi_cwmin = (1<<(sc->sc_ic.ic_wme.wme_chanParams.
 +                                cap_wmeParams[WME_AC_BE].wmep_logcwmin))
 - 1;
 +                sc->sc_szym_retries = 0;
 +        } else {
 +                /* the frame failed, double cwmin */
 +                if ((qi.tqi_cwmin<<1) < qi.tqi_cwmax) {
 +                        qi.tqi_cwmin = (qi.tqi_cwmin<<1) + 1;
 +                }
 +               if(sc->sc_szym_cw > 1)
 +                    ++sc->sc_szym_retries;
 +        }
 +        if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) {
 +                printk("SZYM: unable to update hardware queue "
 +                                "parameters\n");
 +        } else {
 +                if(1) ath_hal_resettxqueue(ah, txq->axq_qnum); /* push to
 h/w */
 +        }
 +//        ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
 +}
 +
  /*
   * Process completed xmit descriptors from the specified queue.
   * Should only be called from tasklet context
 @@ -7138,6 +7253,7 @@
                          */
                          ieee80211_free_node(ni);
                 }
 +               szym_tx_updatecw(sc, txq, &(ds->ds_txstat));

                 bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
                                   bf->bf_skb->len, BUS_DMA_TODEVICE);
 @@ -8388,15 +8504,21 @@
         struct ath_hal *ah = sc->sc_ah;
         HAL_CHANNEL *chans;
         int i, nchan;
 +       u_int mode = HAL_MODE_ALL;

         chans = kmalloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL),
 GFP_KERNEL);
         if (chans == NULL) {
                 printk("%s: unable to allocate channel table\n",
 dev->name);

                 return -ENOMEM;
         }
 +
 +       if(ieeemode != -1) {
 +               mode = ieeemode;
 +       }
 +
         if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
             ic->ic_regclassids, IEEE80211_REGCLASSIDS_MAX,
 &ic->ic_nregclass,
 -           cc, HAL_MODE_ALL, outdoor, xchanmode)) {
 +           cc, mode, outdoor, xchanmode)) {
                 u_int32_t rd;

                 ath_hal_getregdomain(ah, &rd);
 @@ -9072,6 +9194,11 @@
         ATH_XR_POLL_PERIOD      = 20,
         ATH_XR_POLL_COUNT       = 21,
         ATH_ACKRATE             = 22,
 +       ATH_SZYM_CW             = 23,
 +        ATH_SZYM_CWMIN         = 24,
 +        ATH_SZYM_CWMAX         = 25,
 +        ATH_SZYM_CWMIND        = 26,
 +       ATH_SZYM_MAX_RETRIES    = 27,
  };

  static int
 @@ -9201,6 +9328,22 @@
                                 sc->sc_ackrate = val;
                                 ath_set_ack_bitrate(sc, sc->sc_ackrate);
                                 break;
 +                       case ATH_SZYM_CW:
 +                               sc->sc_szym_cw = val;
 +                               DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s:
 szym_cw = %d", __func__, val);
 +                               break;
 +                        case ATH_SZYM_CWMIN: case ATH_SZYM_CWMAX:
 +                                szym_set_cw(sc, ctl->ctl_name ==
 ATH_SZYM_CWMIN, val);
 +                                break;
 +                        case ATH_SZYM_CWMIND:
 +                                sc->sc_ic.ic_wme.wme_chanParams.
 +
 cap_wmeParams[WME_AC_BE].wmep_logcwmin = val;
 +                               DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s:
 szym_cwmind = %d", __func__, val);
 +                                break;
 +                       case ATH_SZYM_MAX_RETRIES:
 +                               sc->sc_szym_max_retries = val;
 +                               DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s:
 szym_max_retries = %d", __func__, val);
 +                                break;
                         default:
                                 return -EINVAL;
                         }
 @@ -9260,6 +9403,19 @@
                 case ATH_ACKRATE:
                         val = sc->sc_ackrate;
                         break;
 +               case ATH_SZYM_CW:
 +                       val = sc->sc_szym_cw;
 +                       break;
 +                case ATH_SZYM_CWMIN: case ATH_SZYM_CWMAX:
 +                        val = szym_get_cw(sc, ctl->ctl_name ==
 ATH_SZYM_CWMIN);
 +                        break;
 +                case ATH_SZYM_CWMIND:
 +                        val = sc->sc_ic.ic_wme.wme_chanParams.
 +                                cap_wmeParams[WME_AC_BE].wmep_logcwmin;
 +                        break;
 +                case ATH_SZYM_MAX_RETRIES:
 +                        val = sc->sc_szym_max_retries;
 +                        break;
                 default:
                         return -EINVAL;
                 }
 @@ -9363,6 +9519,31 @@
           .mode         = 0644,
           .proc_handler = ath_sysctl_halparam
         },
 +       { .ctl_name     = ATH_SZYM_CW,
 +       .procname       = "szym_cw",
 +       .mode           = 0644,
 +       .proc_handler   = ath_sysctl_halparam
 +       },
 +        { .ctl_name     = ATH_SZYM_CWMIN,
 +          .procname     = "szym_cwmin",  /* FIXME: currently only for the
 BE queue */
 +          .mode         = 0644,
 +          .proc_handler = ath_sysctl_halparam
 +        },
 +        { .ctl_name     = ATH_SZYM_CWMAX,
 +          .procname     = "szym_cwmax",
 +          .mode         = 0644,
 +          .proc_handler = ath_sysctl_halparam
 +        },
 +        { .ctl_name     = ATH_SZYM_CWMIND,
 +          .procname     = "szym_cwmind",
 +          .mode         = 0644,
 +          .proc_handler = ath_sysctl_halparam
 +        },
 +        { .ctl_name     = ATH_SZYM_MAX_RETRIES,
 +          .procname     = "szym_retries",
 +          .mode         = 0644,
 +          .proc_handler = ath_sysctl_halparam
 +        },
         { 0 }
  };


 Index: ath/if_athvar.h
 ===================================================================
 --- ath/if_athvar.h     (revision 1705)
 +++ ath/if_athvar.h     (working copy)
 @@ -673,6 +673,11 @@
         u_int32_t sc_dturbo_bw_turbo;           /* bandwidth threshold */
  #endif
         u_int sc_slottimeconf;                  /* manual override for
 slottime */
 +
 +
 +       u_int sc_szym_cw;                       /* enable szym_tx_updatecw
 */
 +       u_int sc_szym_retries;                  /* current retry count */
 +       u_int sc_szym_max_retries;              /* max retry count */
  };

  typedef void (*ath_callback) (struct ath_softc *);


 }}}

-- 
Ticket URL: <http://madwifi.org/ticket/852>
MadWifi <http://madwifi.org/>
Multiband Atheros Driver for Wireless Fidelity
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Madwifi-tickets mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/madwifi-tickets

Reply via email to