This option enables the hardware independent IEEE 802.11
          networking stack.
 
-config MAC80211_RC_DEFAULT_CHOICE
-       bool "Choose default rate control algorithm" if EMBEDDED
-       default y
-       depends on MAC80211
-       ---help---
-         This options enables selection of a default rate control
-         algorithm to be built into the mac80211 module.  Alternate
-         rate control algorithms might be built into the mac80211
-         module as well.
+menu "Rate control algorithm selection"
+       depends on MAC80211 != n
 
 choice
        prompt "Default rate control algorithm"
        default MAC80211_RC_DEFAULT_PID
-       depends on MAC80211 && MAC80211_RC_DEFAULT_CHOICE
        ---help---
          This option selects the default rate control algorithm
          mac80211 will use. Note that this default can still be
          overriden through the ieee80211_default_rc_algo module
-         parameter.
+         parameter if different algorithms are available.
 
 config MAC80211_RC_DEFAULT_PID
        bool "PID controller based rate control algorithm"
          dumb algorithm. You should choose the PID rate control
          instead.
 
+config MAC80211_RC_DEFAULT_NONE
+       bool "No default algorithm"
+       depends on EMBEDDED
+       help
+         Selecting this option will select no default algorithm
+         and allow you to not build any. Do not choose this
+         option unless you know your driver comes with another
+         suitable algorithm.
 endchoice
 
+comment "Selecting 'y' for an algorithm will"
+comment "build the algorithm into mac80211."
+
 config MAC80211_RC_DEFAULT
        string
-       depends on MAC80211
        default "pid" if MAC80211_RC_DEFAULT_PID
        default "simple" if MAC80211_RC_DEFAULT_SIMPLE
        default ""
 
 config MAC80211_RC_PID
-       bool "PID controller based rate control algorithm"
-       default y
-       depends on MAC80211
+       tristate "PID controller based rate control algorithm"
        ---help---
          This option enables a TX rate control algorithm for
          mac80211 that uses a PID controller to select the TX
          different rate control algorithm.
 
 config MAC80211_RC_SIMPLE
-       bool "Simple rate control algorithm (DEPRECATED)"
-       default n
-       depends on MAC80211
+       tristate "Simple rate control algorithm (DEPRECATED)"
        ---help---
          This option enables a very simple, non-responsive TX
          rate control algorithm. This algorithm is deprecated
-         and will be removed from the kernel in near future.
+         and will be removed from the kernel in the near future.
          It has been replaced by the PID algorithm.
 
          Say N unless you know what you are doing.
+endmenu
 
 config MAC80211_LEDS
        bool "Enable LED triggers"
 
 obj-$(CONFIG_MAC80211) += mac80211.o
 
-mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
-mac80211-objs-$(CONFIG_NET_SCHED) += wme.o
-mac80211-objs-$(CONFIG_MAC80211_RC_SIMPLE) += rc80211_simple.o
-mac80211-objs-$(CONFIG_MAC80211_RC_PID) += rc80211_pid_algo.o
+# objects for PID algorithm
+rc80211_pid-y := rc80211_pid_algo.o
+rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
 
-mac80211-debugfs-objs-$(CONFIG_MAC80211_RC_PID) += rc80211_pid_debugfs.o
-mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += \
-       debugfs.o \
-       debugfs_sta.o \
-       debugfs_netdev.o \
-       debugfs_key.o \
-       $(mac80211-debugfs-objs-y)
+# build helper for PID algorithm
+rc-pid-y := $(rc80211_pid-y)
+rc-pid-m := rc80211_pid.o
 
-mac80211-objs := \
+# mac80211 objects
+mac80211-y := \
        ieee80211.o \
        ieee80211_ioctl.o \
        sta_info.o \
        tx.o \
        key.o \
        util.o \
-       event.o \
-       $(mac80211-objs-y)
+       event.o
+
+mac80211-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
+mac80211-$(CONFIG_NET_SCHED) += wme.o
+mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
+       debugfs.o \
+       debugfs_sta.o \
+       debugfs_netdev.o \
+       debugfs_key.o
+
+
+# Build rate control algorithm(s)
+CFLAGS_rc80211_simple.o += -DRC80211_SIMPLE_COMPILE
+CFLAGS_rc80211_pid_algo.o += -DRC80211_PID_COMPILE
+mac80211-$(CONFIG_MAC80211_RC_SIMPLE) += rc80211_simple.o
+mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc-pid-$(CONFIG_MAC80211_RC_PID))
+
+# Modular rate algorithms are assigned to mac80211-m - make separate modules
+obj-m += $(mac80211-m)
 
 
        BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
 
-#ifdef CONFIG_MAC80211_RC_SIMPLE
-       ret = ieee80211_rate_control_register(&mac80211_rcsimple);
+       ret = rc80211_simple_init();
        if (ret)
                goto fail;
-#endif
 
-#ifdef CONFIG_MAC80211_RC_PID
-       ret = ieee80211_rate_control_register(&mac80211_rcpid);
+       ret = rc80211_pid_init();
        if (ret)
-               goto fail;
-#endif
+               goto fail_simple;
 
        ret = ieee80211_wme_register();
        if (ret) {
                printk(KERN_DEBUG "ieee80211_init: failed to "
                       "initialize WME (err=%d)\n", ret);
-               goto fail;
+               goto fail_pid;
        }
 
        ieee80211_debugfs_netdev_init();
 
        return 0;
 
-fail:
-
-#ifdef CONFIG_MAC80211_RC_SIMPLE
-       ieee80211_rate_control_unregister(&mac80211_rcsimple);
-#endif
-#ifdef CONFIG_MAC80211_RC_PID
-       ieee80211_rate_control_unregister(&mac80211_rcpid);
-#endif
-
+ fail_pid:
+       rc80211_simple_exit();
+ fail_simple:
+       rc80211_pid_exit();
+ fail:
        return ret;
 }
 
 static void __exit ieee80211_exit(void)
 {
-#ifdef CONFIG_MAC80211_RC_SIMPLE
-       ieee80211_rate_control_unregister(&mac80211_rcsimple);
-#endif
-#ifdef CONFIG_MAC80211_RC_PID
-       ieee80211_rate_control_unregister(&mac80211_rcpid);
-#endif
+       rc80211_simple_exit();
+       rc80211_pid_exit();
 
        ieee80211_wme_unregister();
        ieee80211_debugfs_netdev_exit();
 
                /* try default if specific alg requested but not found */
                ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
 
+       /* try built-in one if specific alg requested but not found */
+       if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
+               ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
+
        return ops;
 }
 
 
        struct kref kref;
 };
 
-/* default 'simple' algorithm */
-extern struct rate_control_ops mac80211_rcsimple;
-
-/* 'PID' algorithm */
-extern struct rate_control_ops mac80211_rcpid;
-
 int ieee80211_rate_control_register(struct rate_control_ops *ops);
 void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
 
                                 const char *name);
 void rate_control_deinitialize(struct ieee80211_local *local);
 
+
+/* Rate control algorithms */
+#if defined(RC80211_SIMPLE_COMPILE) || \
+       (defined(CONFIG_MAC80211_RC_SIMPLE) && \
+        !defined(CONFIG_MAC80211_RC_SIMPLE_MODULE))
+extern int rc80211_simple_init(void);
+extern void rc80211_simple_exit(void);
+#else
+static inline int rc80211_simple_init(void)
+{
+       return 0;
+}
+static inline void rc80211_simple_exit(void)
+{
+}
+#endif
+
+#if defined(RC80211_PID_COMPILE) || \
+       (defined(CONFIG_MAC80211_RC_PID) && \
+        !defined(CONFIG_MAC80211_RC_PID_MODULE))
+extern int rc80211_pid_init(void);
+extern void rc80211_pid_exit(void);
+#else
+static inline int rc80211_pid_init(void)
+{
+       return 0;
+}
+static inline void rc80211_pid_exit(void)
+{
+}
+#endif
+
 #endif /* IEEE80211_RATE_H */
 
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
-
+#include <linux/debugfs.h>
 #include <net/mac80211.h>
 #include "ieee80211_rate.h"
 
        kfree(spinfo);
 }
 
-struct rate_control_ops mac80211_rcpid = {
+static struct rate_control_ops mac80211_rcpid = {
        .name = "pid",
        .tx_status = rate_control_pid_tx_status,
        .get_rate = rate_control_pid_get_rate,
        .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs,
 #endif
 };
+
+MODULE_DESCRIPTION("PID controller based rate control algorithm");
+MODULE_AUTHOR("Stefano Brivio");
+MODULE_AUTHOR("Mattias Nissler");
+MODULE_LICENSE("GPL");
+
+int __init rc80211_pid_init(void)
+{
+       return ieee80211_rate_control_register(&mac80211_rcpid);
+}
+
+void __exit rc80211_pid_exit(void)
+{
+       ieee80211_rate_control_unregister(&mac80211_rcpid);
+}
+
+#ifdef CONFIG_MAC80211_RC_PID_MODULE
+module_init(rc80211_pid_init);
+module_exit(rc80211_pid_exit);
+#endif
 
 #include <linux/slab.h>
 #include <linux/skbuff.h>
 #include <linux/compiler.h>
+#include <linux/module.h>
 
 #include <net/mac80211.h>
 #include "ieee80211_i.h"
 }
 #endif
 
-struct rate_control_ops mac80211_rcsimple = {
+static struct rate_control_ops mac80211_rcsimple = {
        .name = "simple",
        .tx_status = rate_control_simple_tx_status,
        .get_rate = rate_control_simple_get_rate,
        .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
 #endif
 };
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simple rate control algorithm");
+
+int __init rc80211_simple_init(void)
+{
+       return ieee80211_rate_control_register(&mac80211_rcsimple);
+}
+
+void __exit rc80211_simple_exit(void)
+{
+       ieee80211_rate_control_unregister(&mac80211_rcsimple);
+}
+
+#ifdef CONFIG_MAC80211_RC_SIMPLE_MODULE
+module_init(rc80211_simple_init);
+module_exit(rc80211_simple_exit);
+#endif