Retry fix

This enables modifying retry limits on madwifi via Wext. While the
implementation on the ioctl adds support (ieee80211_wireless.c) for
short retry, long retry and even retry lifetime the HAL only allows us
currently to modify one simple retry limit.

Signed-Off by: Luis Rodriguez <mcgrof@winlab.rutgers.edu>

diff -Naurp madwifi-3366.orig/ath/if_ath.c madwifi-3366/ath/if_ath.c
--- madwifi-3366.orig/ath/if_ath.c	2008-02-23 09:13:09.000000000 -0500
+++ madwifi-3366/ath/if_ath.c	2008-02-29 19:52:23.000000000 -0500
@@ -7635,6 +7635,12 @@ ath_tx_start(struct net_device *dev, str
 			sc->sc_rc->ops->findrate(sc, an, shortPreamble, skb->len,
 				&rix, &try0, &txrate);
 
+			/* Note: HAL does not support distinguishing between short
+			* and long retry. These both are set via try0 here then.
+			* In the openhal we'll fix this ;) */
+			if (vap->iv_flags & IEEE80211_F_SWRETRY && vap->iv_txmax != try0)
+				try0 = vap->iv_txmax;
+
 			/* Ratecontrol sometimes returns invalid rate index */
 			if (rix != 0xff)
 				an->an_prevdatarix = rix;
diff -Naurp madwifi-3366.orig/net80211/ieee80211.c madwifi-3366/net80211/ieee80211.c
--- madwifi-3366.orig/net80211/ieee80211.c	2008-01-30 18:50:16.000000000 -0500
+++ madwifi-3366/net80211/ieee80211.c	2008-02-29 19:54:42.000000000 -0500
@@ -451,14 +451,18 @@ ieee80211_vap_setup(struct ieee80211com 
 #endif
 
 	vap->iv_caps = ic->ic_caps &~ IEEE80211_C_OPMODE;
+	/* Means its unset yet via WE SIOCSIWRETRY ioctl */
+	vap->iv_flags &= ~IEEE80211_F_SWRETRY;
+
 	switch (opmode) {
 	case IEEE80211_M_STA:
 		/* WDS/Repeater */
 		if (flags & IEEE80211_NO_STABEACONS)
 			vap->iv_flags_ext |= IEEE80211_FEXT_SWBMISS;
+		vap->iv_caps |= IEEE80211_C_SWRETRY;
 		break;
 	case IEEE80211_M_IBSS:
-		vap->iv_caps |= IEEE80211_C_IBSS;
+		vap->iv_caps |= IEEE80211_C_IBSS | IEEE80211_C_SWRETRY;
 		vap->iv_ath_cap &= ~IEEE80211_ATHC_XR;
 		break;
 	case IEEE80211_M_AHDEMO:
diff -Naurp madwifi-3366.orig/net80211/ieee80211_wireless.c madwifi-3366/net80211/ieee80211_wireless.c
--- madwifi-3366.orig/net80211/ieee80211_wireless.c	2008-01-30 22:42:51.000000000 -0500
+++ madwifi-3366/net80211/ieee80211_wireless.c	2008-02-29 20:00:18.000000000 -0500
@@ -1299,6 +1299,19 @@ ieee80211_ioctl_giwpower(struct net_devi
 	return 0;
 }
 
+/* WE-21 added support for IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers 
+ * Note: IW_RETRY_SHORT/IW_RETRY_LONG was just a userspace improvement so
+ * we can just add the defines required for its support here and a user
+ * with an older kernel but new WE will still be able to benefit from this */
+#if WIRELESS_EXT < 21
+/* Retry limits and lifetime flags available */
+#ifndef IW_RETRY_LIFETIME /* Can't pinpoint when this guy was introduced */
+#define IW_RETRY_LIFETIME       0x2000  /* Maximum duration of retries in us */
+#endif /* IW_RETRY_LIFETIME */
+#define IW_RETRY_SHORT          0x0010  /* Value is for short packets  */
+#define IW_RETRY_LONG           0x0020  /* Value is for long packets */
+#endif /* WIRELESS_EXT < 21 */
+
 static int
 ieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,
 	struct iw_param *rrq, char *extra)
@@ -1311,24 +1324,33 @@ ieee80211_ioctl_siwretry(struct net_devi
 			vap->iv_flags &= ~IEEE80211_F_SWRETRY;
 			goto done;
 		}
+		/* Already disabled in iv_flags, nothing to do */
 		return 0;
 	}
 
 	if ((vap->iv_caps & IEEE80211_C_SWRETRY) == 0)
 		return -EOPNOTSUPP;
+	if (rrq->value < 0)
+		return -EINVAL;
 	if (rrq->flags == IW_RETRY_LIMIT) {
 		if (rrq->value >= 0) {
-			vap->iv_txmin = rrq->value;
-			vap->iv_txmax = rrq->value;	/* XXX */
-			vap->iv_txlifetime = 0;		/* XXX */
+			if (rrq->flags & IW_RETRY_SHORT)
+				vap->iv_txmin = rrq->value;
+			else if (rrq->flags & IW_RETRY_LONG)
+				vap->iv_txmax = rrq->value;
+			else {
+				vap->iv_txmin = rrq->value;
+				vap->iv_txmax = rrq->value;
+			}
 			vap->iv_flags |= IEEE80211_F_SWRETRY;
 		} else {
 			vap->iv_flags &= ~IEEE80211_F_SWRETRY;
 		}
-		return 0;
 	}
+	if (rrq->flags & IW_RETRY_LIFETIME)
+		vap->iv_txlifetime = 0;
 done:
-	return IS_UP(vap->iv_dev) ? ic->ic_reset(vap->iv_dev) : 0;
+	return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;
 }
 
 static int
