Move slot-time, CTS/RTS, and ACK timeout calculations into the driver. Corrected logic for the relationships between slot time and cts timeout and ack timeout have been added and the athctrl now delegates to the driver instead.

You can override:
- slottime
- ctstimeout
- acktimeout

acktimeout and ctstimeout will be selected from the first available of: 

1) the explicitly specified override value [if present]
2) a value derived from an explicitly specified slottime [if present]
3) the HALs default behavior / standard settings for the PHY mode

Setting the distance is shorthand for updating the slottime, and both cts and ack timeout values based upon the usual equations for air propagation, speed of light, etc..etc..



git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3508 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
mtaylor 2008-04-10 03:46:54 +00:00
parent cee1c3f7f9
commit afadc9b41d
3 changed files with 225 additions and 17 deletions

View File

@ -148,6 +148,8 @@ static void ath_key_update_begin(struct ieee80211vap *);
static void ath_key_update_end(struct ieee80211vap *); static void ath_key_update_end(struct ieee80211vap *);
static void ath_mode_init(struct net_device *); static void ath_mode_init(struct net_device *);
static void ath_setslottime(struct ath_softc *); static void ath_setslottime(struct ath_softc *);
static void ath_setctstimeout(struct ath_softc *);
static void ath_setacktimeout(struct ath_softc *);
static void ath_updateslot(struct net_device *); static void ath_updateslot(struct net_device *);
static int ath_beaconq_setup(struct ath_softc *); static int ath_beaconq_setup(struct ath_softc *);
static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *); static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *);
@ -4231,10 +4233,61 @@ ath_mode_init(struct net_device *dev)
rfilt, mfilt[0], mfilt[1]); rfilt, mfilt[0], mfilt[1]);
} }
static inline int
ath_slottime2timeout(struct ath_softc *sc, int slottime)
{
/* HAL seems to use a constant of 8 for OFDM overhead and 18 for
* CCK overhead.
*
* XXX: Update based on emperical evidence (potentially save 15us per timeout)
*/
if (((sc->sc_curchan.channelFlags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) ||
(((sc->sc_curchan.channelFlags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G) &&
(sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT)))
{
/* short slot time - 802.11a, and 802.11g turbo in turbo mode with short slot time */
return (slottime * 2) + 8;
}
/* constant for CCK mib processing time */
return (slottime * 2) + 18;
}
#ifndef MAX
# define MAX(a, b) (((a) > (b))? (a) : (b))
#endif
static inline int
ath_default_ctsack_timeout(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
int slottime = sc->sc_slottimeconf;
if (slottime <= 0)
slottime = ath_hal_getslottime(ah);
return ath_slottime2timeout(sc, slottime);
}
static inline int
ath_getslottime(struct ath_softc *sc) {
return ath_hal_getslottime(sc->sc_ah);
}
static inline int
ath_getacktimeout(struct ath_softc *sc) {
return ath_hal_getacktimeout(sc->sc_ah);
}
static inline int
ath_getctstimeout(struct ath_softc *sc) {
return ath_hal_getctstimeout(sc->sc_ah);
}
/* /*
* Set the slot time based on the current setting. * Set the slot time based on the current setting.
*/ */
static void static inline void
ath_setslottime(struct ath_softc *sc) ath_setslottime(struct ath_softc *sc)
{ {
struct ieee80211com *ic = &sc->sc_ic; struct ieee80211com *ic = &sc->sc_ic;
@ -4242,11 +4295,43 @@ ath_setslottime(struct ath_softc *sc)
if (sc->sc_slottimeconf > 0) /* manual override */ if (sc->sc_slottimeconf > 0) /* manual override */
ath_hal_setslottime(ah, sc->sc_slottimeconf); ath_hal_setslottime(ah, sc->sc_slottimeconf);
else if (sc->sc_dturbo || (sc->sc_curchan.privFlags & CHANNEL_ST))
ath_hal_setslottime(ah, HAL_SLOT_TIME_6);
else if (ic->ic_flags & IEEE80211_F_SHSLOT) else if (ic->ic_flags & IEEE80211_F_SHSLOT)
ath_hal_setslottime(ah, HAL_SLOT_TIME_9); ath_hal_setslottime(ah, HAL_SLOT_TIME_9);
else else
ath_hal_setslottime(ah, HAL_SLOT_TIME_20); ath_hal_setslottime(ah, HAL_SLOT_TIME_20);
sc->sc_updateslot = OK; sc->sc_updateslot = OK;
ath_setacktimeout(sc);
ath_setctstimeout(sc);
}
/*
* Set the ACK timeout based on the current setting.
*/
static void
ath_setacktimeout(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
if (sc->sc_acktimeoutconf > 0) /* manual override */
ath_hal_setacktimeout(ah, sc->sc_acktimeoutconf);
else
ath_hal_setacktimeout(ah, ath_default_ctsack_timeout(sc));
}
/*
* Set the CTS timeout based on the current setting.
*/
static void
ath_setctstimeout(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
if (sc->sc_ctstimeoutconf > 0) /* manual override */
ath_hal_setctstimeout(ah, sc->sc_ctstimeoutconf);
else
ath_hal_setctstimeout(ah, ath_default_ctsack_timeout(sc));
} }
/* /*
@ -10545,8 +10630,71 @@ enum {
ATH_RADAR_IGNORED = 25, ATH_RADAR_IGNORED = 25,
ATH_MAXVAPS = 26, ATH_MAXVAPS = 26,
ATH_INTMIT = 27, ATH_INTMIT = 27,
ATH_DISTANCE = 28,
}; };
static inline int
ath_ccatime(struct ath_softc *sc)
{
if (((sc->sc_curchan.channelFlags & IEEE80211_CHAN_PUREG) ==
IEEE80211_CHAN_PUREG) &&
(sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT))
return CCA_PUREG;
if ((sc->sc_curchan.channelFlags & IEEE80211_CHAN_A) ==
IEEE80211_CHAN_A)
return CCA_A;
return CCA_BG;
}
static inline int
ath_estimate_max_distance(struct ath_softc *sc)
{
/* Prefer overrided, ask HAL if not overridden */
int slottime = sc->sc_slottimeconf;
if (slottime <= 0)
slottime = ath_hal_getslottime(sc->sc_ah);
/* NB: We ignore MAC overhead. this function is reverse operation of
* ath_distance2slottime, and assumes slottime is CCA + 2x air propagation. */
return (slottime - ath_ccatime(sc)) * 150;
}
static inline int
ath_distance2slottime(struct ath_softc *sc, int distance)
{
/* Allowance for air propagation (roundtrip time) should be at least
* 5us per the standards.
*
* So let's set a minimum distance to accomodate this:
*
* roundtrip time = ( ( distance / speed_of_light ) * 2 )
*
* distance = ( (time * 300 ) / 2) or ((5 * 300) / 2) = 750 m
*/
int rtdist = distance * 2;
int aAirPropagation = (rtdist / 300) + !!(rtdist % 300);
if (aAirPropagation < 5) {
aAirPropagation = 5;
}
/* NB: We ignore MAC processing delays... no clue */
return ath_ccatime(sc) + aAirPropagation;
}
static inline int
ath_distance2timeout(struct ath_softc *sc, int distance)
{
/* HAL uses a constant of twice slot time plus 18us.
* The 18us covers rxtx turnaround, MIB processing, etc.
* but the athctrl used to return 2slot+3 so the extra 15us of
* timeout is probably just being very careful or taking something into
* account that I can't find in the specs.
*
* XXX: Update based on emperical evidence (potentially save 15us per timeout)
*/
return ath_slottime2timeout(sc, ath_distance2slottime(sc, distance));
}
static int static int
ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos) ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
{ {
@ -10575,25 +10723,75 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
lenp, ppos); lenp, ppos);
if (ret == 0) { if (ret == 0) {
switch ((long)ctl->extra2) { switch ((long)ctl->extra2) {
case ATH_DISTANCE:
if(val > 0) {
sc->sc_slottimeconf = ath_distance2slottime(sc, val);
sc->sc_acktimeoutconf = ath_distance2timeout(sc, val);
sc->sc_ctstimeoutconf = ath_distance2timeout(sc, val);
ath_setslottime(sc);
}
else {
/* disable manual overrides */
sc->sc_slottimeconf = 0;
sc->sc_ctstimeoutconf = 0;
sc->sc_acktimeoutconf = 0;
ath_setslottime(sc);
}
/* Likely changed by the function */
val = ath_estimate_max_distance(sc);
break;
case ATH_SLOTTIME: case ATH_SLOTTIME:
if (val > 0) { if (val > 0) {
if (!ath_hal_setslottime(ah, val)) if (!ath_hal_setslottime(ah, val))
ret = -EINVAL; ret = -EINVAL;
else else {
int old = sc->sc_slottimeconf;
sc->sc_slottimeconf = val; sc->sc_slottimeconf = val;
/* overridden slot time invalidates
* previous overridden ack/cts
* timeouts if it is longer! */
if (old && old < sc->sc_slottimeconf) {
sc->sc_ctstimeoutconf = 0;
sc->sc_acktimeoutconf = 0;
ath_setacktimeout(sc);
ath_setctstimeout(sc);
}
}
} else { } else {
/* disable manual override */ /* disable manual override */
sc->sc_slottimeconf = 0; sc->sc_slottimeconf = 0;
ath_setslottime(sc); ath_setslottime(sc);
} }
/* Likely changed by the function */
val = ath_getslottime(sc);
break; break;
case ATH_ACKTIMEOUT: case ATH_ACKTIMEOUT:
if (val > 0) {
if (!ath_hal_setacktimeout(ah, val)) if (!ath_hal_setacktimeout(ah, val))
ret = -EINVAL; ret = -EINVAL;
else
sc->sc_acktimeoutconf = val;
} else {
/* disable manual overrider */
sc->sc_acktimeoutconf = 0;
ath_setacktimeout(sc);
}
/* Likely changed by the function */
val = ath_getacktimeout(sc);
break; break;
case ATH_CTSTIMEOUT: case ATH_CTSTIMEOUT:
if (val > 0) {
if (!ath_hal_setctstimeout(ah, val)) if (!ath_hal_setctstimeout(ah, val))
ret = -EINVAL; ret = -EINVAL;
else
sc->sc_ctstimeoutconf = val;
} else {
/* disable manual overrides */
sc->sc_ctstimeoutconf = 0;
ath_setctstimeout(sc);
}
/* Likely changed by the function */
val = ath_getctstimeout(sc);
break; break;
case ATH_SOFTLED: case ATH_SOFTLED:
if (val != sc->sc_softled) { if (val != sc->sc_softled) {
@ -10757,14 +10955,17 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
} }
} else { } else {
switch ((long)ctl->extra2) { switch ((long)ctl->extra2) {
case ATH_DISTANCE:
val = ath_estimate_max_distance(sc);
break;
case ATH_SLOTTIME: case ATH_SLOTTIME:
val = ath_hal_getslottime(ah); val = ath_getslottime(sc);
break; break;
case ATH_ACKTIMEOUT: case ATH_ACKTIMEOUT:
val = ath_hal_getacktimeout(ah); val = ath_getacktimeout(sc);
break; break;
case ATH_CTSTIMEOUT: case ATH_CTSTIMEOUT:
val = ath_hal_getctstimeout(ah); val = ath_getctstimeout(sc);
break; break;
case ATH_SOFTLED: case ATH_SOFTLED:
val = sc->sc_softled; val = sc->sc_softled;
@ -10836,6 +11037,12 @@ static int mincalibrate = 1; /* once a second */
static int maxint = 0x7fffffff; /* 32-bit big */ static int maxint = 0x7fffffff; /* 32-bit big */
static const ctl_table ath_sysctl_template[] = { static const ctl_table ath_sysctl_template[] = {
{ .ctl_name = CTL_AUTO,
.procname = "distance",
.mode = 0644,
.proc_handler = ath_sysctl_halparam,
.extra2 = (void *)ATH_DISTANCE,
},
{ .ctl_name = CTL_AUTO, { .ctl_name = CTL_AUTO,
.procname = "slottime", .procname = "slottime",
.mode = 0644, .mode = 0644,

View File

@ -295,6 +295,12 @@ static inline struct net_device *_alloc_netdev(int sizeof_priv, const char *mask
#define GRP_POLL_PERIOD_NO_XR_STA_MAX 100 #define GRP_POLL_PERIOD_NO_XR_STA_MAX 100
#define GRP_POLL_PERIOD_XR_STA_MAX 30 #define GRP_POLL_PERIOD_XR_STA_MAX 30
enum {
CCA_BG = 15,
CCA_A = 4,
CCA_PUREG = 4, /* pure G */
};
/* /*
* Percentage of the configured poll periodicity * Percentage of the configured poll periodicity
*/ */
@ -335,7 +341,6 @@ static inline struct net_device *_alloc_netdev(int sizeof_priv, const char *mask
#define MIN_REGISTER_ADDRESS 0x0000 /* PCI register addresses are taken as releative to the appropriate BAR */ #define MIN_REGISTER_ADDRESS 0x0000 /* PCI register addresses are taken as releative to the appropriate BAR */
#define MAX_REGISTER_ADDRESS 0xc000 /* AR5212/AR5213 seems to have a 48k address range */ #define MAX_REGISTER_ADDRESS 0xc000 /* AR5212/AR5213 seems to have a 48k address range */
#define MAX_REGISTER_NAME_LEN 32 /* Maximum length of register nicknames in debug output */ #define MAX_REGISTER_NAME_LEN 32 /* Maximum length of register nicknames in debug output */
#define UNKNOWN_NAME "(unknown)" /* Name used when reading/listing undocumented registers */
#endif /* #ifdef ATH_REVERSE_ENGINEERING */ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
/* /*
* Convert from net80211 layer values to Ath layer values. Hopefully this will * Convert from net80211 layer values to Ath layer values. Hopefully this will
@ -800,6 +805,8 @@ struct ath_softc {
u_int32_t sc_dturbo_bw_turbo; /* bandwidth threshold */ u_int32_t sc_dturbo_bw_turbo; /* bandwidth threshold */
#endif #endif
u_int sc_slottimeconf; /* manual override for slottime */ u_int sc_slottimeconf; /* manual override for slottime */
u_int sc_acktimeoutconf; /* manual override for ack timeout */
u_int sc_ctstimeoutconf; /* manual override for cts timeout */
struct timer_list sc_dfs_excl_timer; /* mark expiration timer task */ struct timer_list sc_dfs_excl_timer; /* mark expiration timer task */
struct timer_list sc_dfs_cac_timer; /* dfs wait timer */ struct timer_list sc_dfs_cac_timer; /* dfs wait timer */

View File

@ -117,15 +117,9 @@ main(int argc, char *argv[])
} }
if (distance >= 0) { if (distance >= 0) {
int slottime = 9 + (distance / 300) + ((distance % 300) ? 1 : 0);
int acktimeout = slottime * 2 + 3;
int ctstimeout = slottime * 2 + 3;
printf("Setting distance on interface %s to %i meters\n", printf("Setting distance on interface %s to %i meters\n",
device, distance); device, distance);
setsysctrl(device, "slottime", slottime); setsysctrl(device, "distance", distance);
setsysctrl(device, "acktimeout", acktimeout);
setsysctrl(device, "ctstimeout", ctstimeout);
} else } else
usage(); usage();
return 0; return 0;