From 8c4e758a8b99514885eddd5cddea1ca8ce154349 Mon Sep 17 00:00:00 2001
From: Sam Leffler <sam@FreeBSD.org>
Date: Tue, 24 Mar 2009 17:57:48 +0000
Subject: [PATCH] add linker sets for get/set ioctl handlers so optional
 net80211 code is isolated

---
 sys/net80211/ieee80211_freebsd.h | 11 +++++
 sys/net80211/ieee80211_ioctl.c   | 71 ++++++++++++++++++++++----------
 sys/net80211/ieee80211_tdma.c    | 16 +++----
 sys/net80211/ieee80211_tdma.h    |  5 ---
 4 files changed, 69 insertions(+), 34 deletions(-)

diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index 519e37d938fa..41cc19025ca6 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -393,6 +393,17 @@ alg##_modevent(int type)						\
 TEXT_SET(rate##_set, alg##_modevent)
 #endif /* _KERNEL */
 
+struct ieee80211req;
+typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *,
+    struct ieee80211req *);
+SET_DECLARE(ieee80211_ioctl_getset, ieee80211_ioctl_getfunc);
+#define	IEEE80211_IOCTL_GET(_name, _get) TEXT_SET(ieee80211_ioctl_getset, _get)
+
+typedef int ieee80211_ioctl_setfunc(struct ieee80211vap *,
+    struct ieee80211req *);
+SET_DECLARE(ieee80211_ioctl_setset, ieee80211_ioctl_setfunc);
+#define	IEEE80211_IOCTL_SET(_name, _set) TEXT_SET(ieee80211_ioctl_setset, _set)
+
 /* XXX this stuff belongs elsewhere */
 /*
  * Message formats for messages from the net80211 layer to user
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 21d563788592..ce6de08183f1 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -63,9 +63,6 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_ioctl.h>
 #include <net80211/ieee80211_regdomain.h>
 #include <net80211/ieee80211_input.h>
-#ifdef IEEE80211_SUPPORT_TDMA
-#include <net80211/ieee80211_tdma.h>
-#endif
 
 #define	IS_UP_AUTO(_vap) \
 	(IFNET_IS_UP_RUNNING(vap->iv_ifp) && \
@@ -751,6 +748,30 @@ ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
 	return error;
 }
 
+/*
+ * Dummy ioctl get handler so the linker set is defined.
+ */
+static int
+dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+	return ENOSYS;
+}
+IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get);
+
+static int
+ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+	ieee80211_ioctl_getfunc * const *get;
+	int error;
+
+	SET_FOREACH(get, ieee80211_ioctl_getset) {
+		error = (*get)(vap, ireq);
+		if (error != ENOSYS)
+			return error;
+	}
+	return EINVAL;
+}
+
 /*
  * When building the kernel with -O2 on the i386 architecture, gcc
  * seems to want to inline this function into ieee80211_ioctl()
@@ -1104,16 +1125,8 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
 			ireq->i_val =
 			    (vap->iv_flags_ext & IEEE80211_FEXT_RIFS) != 0;
 		break;
-#ifdef IEEE80211_SUPPORT_TDMA
-	case IEEE80211_IOC_TDMA_SLOT:
-	case IEEE80211_IOC_TDMA_SLOTCNT:
-	case IEEE80211_IOC_TDMA_SLOTLEN:
-	case IEEE80211_IOC_TDMA_BINTERVAL:
-		error = ieee80211_tdma_ioctl_get80211(vap, ireq);
-		break;
-#endif
 	default:
-		error = EINVAL;
+		error = ieee80211_ioctl_getdefault(vap, ireq);
 		break;
 	}
 	return error;
@@ -2476,6 +2489,30 @@ isvapht(const struct ieee80211vap *vap)
 	    IEEE80211_IS_CHAN_HT(bss->ni_chan);
 }
 
+/*
+ * Dummy ioctl set handler so the linker set is defined.
+ */
+static int
+dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+	return ENOSYS;
+}
+IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set);
+
+static int
+ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+	ieee80211_ioctl_setfunc * const *set;
+	int error;
+
+	SET_FOREACH(set, ieee80211_ioctl_setset) {
+		error = (*set)(vap, ireq);
+		if (error != ENOSYS)
+			return error;
+	}
+	return EINVAL;
+}
+
 static __noinline int
 ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq)
 {
@@ -3131,16 +3168,8 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
 		if (isvapht(vap))
 			error = ERESTART;
 		break;
-#ifdef IEEE80211_SUPPORT_TDMA
-	case IEEE80211_IOC_TDMA_SLOT:
-	case IEEE80211_IOC_TDMA_SLOTCNT:
-	case IEEE80211_IOC_TDMA_SLOTLEN:
-	case IEEE80211_IOC_TDMA_BINTERVAL:
-		error = ieee80211_tdma_ioctl_set80211(vap, ireq);
-		break;
-#endif
 	default:
-		error = EINVAL;
+		error = ieee80211_ioctl_setdefault(vap, ireq);
 		break;
 	}
 	/*
diff --git a/sys/net80211/ieee80211_tdma.c b/sys/net80211/ieee80211_tdma.c
index 6c5e1ac01c13..5c08c9e231f6 100644
--- a/sys/net80211/ieee80211_tdma.c
+++ b/sys/net80211/ieee80211_tdma.c
@@ -705,9 +705,8 @@ ieee80211_tdma_update_beacon(struct ieee80211vap *vap,
 		ts->tdma_count--;
 }
 
-int
-ieee80211_tdma_ioctl_get80211(struct ieee80211vap *vap,
-	struct ieee80211req *ireq)
+static int
+tdma_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
 	struct ieee80211_tdma_state *ts = vap->iv_tdma;
 
@@ -728,14 +727,14 @@ ieee80211_tdma_ioctl_get80211(struct ieee80211vap *vap,
 		ireq->i_val = ts->tdma_bintval;
 		break;
 	default:
-		return EINVAL;
+		return ENOSYS;
 	}
 	return 0;
 }
+IEEE80211_IOCTL_GET(tdma, tdma_ioctl_get80211);
 
-int
-ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
-	struct ieee80211req *ireq)
+static int
+tdma_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
 	struct ieee80211_tdma_state *ts = vap->iv_tdma;
 
@@ -782,7 +781,8 @@ ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
 		}
 		break;
 	default:
-		return EINVAL;
+		return ENOSYS;
 	}
 	return 0;
 }
+IEEE80211_IOCTL_SET(tdma, tdma_ioctl_set80211);
diff --git a/sys/net80211/ieee80211_tdma.h b/sys/net80211/ieee80211_tdma.h
index 4d07524f4a23..22d14c308241 100644
--- a/sys/net80211/ieee80211_tdma.h
+++ b/sys/net80211/ieee80211_tdma.h
@@ -65,9 +65,4 @@ uint8_t *ieee80211_add_tdma(uint8_t *frm, struct ieee80211vap *vap);
 struct ieee80211_beacon_offsets;
 void	ieee80211_tdma_update_beacon(struct ieee80211vap *vap,
 	    struct ieee80211_beacon_offsets *bo);
-struct ieee80211req;
-int	ieee80211_tdma_ioctl_get80211(struct ieee80211vap *vap,
-	    struct ieee80211req *ireq);
-int	ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
-	    struct ieee80211req *ireq);
 #endif /* !_NET80211_IEEE80211_TDMA_H_ */