--- /dev/null
+Patch to fix busybox MODPROBE_SMALL from upstream:
+http://busybox.net/downloads/fixes-1.23.1/busybox-1.23.1-modprobe-small.patch
+
+Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
+
+--- busybox-1.23.1/modutils/modprobe-small.c
++++ busybox-1.23.1-modprobe-small/modutils/modprobe-small.c
+@@ -552,9 +552,23 @@ static int already_loaded(const char *na
+ return ret;
+ }
+ #else
+-#define already_loaded(name) is_rmmod
++#define already_loaded(name) 0
+ #endif
+
++static int rmmod(const char *filename)
++{
++ int r;
++ char modname[MODULE_NAME_LEN];
++
++ filename2modname(filename, modname);
++ r = delete_module(modname, O_NONBLOCK | O_EXCL);
++ dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
++ if (r != 0 && !(option_mask32 & OPT_q)) {
++ bb_perror_msg("remove '%s'", modname);
++ }
++ return r;
++}
++
+ /*
+ * Given modules definition and module name (or alias, or symbol)
+ * load/remove the module respecting dependencies.
+@@ -571,26 +585,36 @@ static void process_module(char *name, c
+ module_info **infovec;
+ module_info *info;
+ int infoidx;
+- int is_rmmod = (option_mask32 & OPT_r) != 0;
++ int is_remove = (option_mask32 & OPT_r) != 0;
+
+ dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
+
+ replace(name, '-', '_');
+
+- dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod);
++ dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove);
++
++ if (applet_name[0] == 'r') {
++ /* rmmod.
++ * Does not remove dependencies, no need to scan, just remove.
++ * (compat note: this allows and strips .ko suffix)
++ */
++ rmmod(name);
++ return;
++ }
++
+ /*
+- * We used to have "is_rmmod != already_loaded(name)" check here, but
++ * We used to have "is_remove != already_loaded(name)" check here, but
+ * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80
+ * won't unload modules (there are more than one)
+ * which have this alias.
+ */
+- if (!is_rmmod && already_loaded(name)) {
++ if (!is_remove && already_loaded(name)) {
+ dbg1_error_msg("nothing to do for '%s'", name);
+ return;
+ }
+
+ options = NULL;
+- if (!is_rmmod) {
++ if (!is_remove) {
+ char *opt_filename = xasprintf("/etc/modules/%s", name);
+ options = xmalloc_open_read_close(opt_filename, NULL);
+ if (options)
+@@ -624,7 +648,7 @@ static void process_module(char *name, c
+ 0 /* depth */
+ );
+ dbg1_error_msg("dirscan complete");
+- /* Module was not found, or load failed, or is_rmmod */
++ /* Module was not found, or load failed, or is_remove */
+ if (module_found_idx >= 0) { /* module was found */
+ infovec = xzalloc(2 * sizeof(infovec[0]));
+ infovec[0] = &modinfo[module_found_idx];
+@@ -637,7 +661,7 @@ static void process_module(char *name, c
+
+ if (!infovec) {
+ /* both dirscan and find_alias found nothing */
+- if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
++ if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
+ bb_error_msg("module '%s' not found", name);
+ //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
+ goto ret;
+@@ -651,29 +675,15 @@ static void process_module(char *name, c
+ * a *list* of modinfo pointers from find_alias().
+ */
+
+- /* rmmod or modprobe -r? unload module(s) */
+- if (is_rmmod) {
++ /* modprobe -r? unload module(s) */
++ if (is_remove) {
+ infoidx = 0;
+ while ((info = infovec[infoidx++]) != NULL) {
+- int r;
+- char modname[MODULE_NAME_LEN];
+-
+- filename2modname(
+- bb_get_last_path_component_nostrip(info->pathname), modname);
+- r = delete_module(modname, O_NONBLOCK | O_EXCL);
+- dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
++ int r = rmmod(bb_get_last_path_component_nostrip(info->pathname));
+ if (r != 0) {
+- if (!(option_mask32 & OPT_q))
+- bb_perror_msg("remove '%s'", modname);
+- goto ret;
++ goto ret; /* error */
+ }
+ }
+-
+- if (applet_name[0] == 'r') {
+- /* rmmod: do not remove dependencies, exit */
+- goto ret;
+- }
+-
+ /* modprobe -r: we do not stop here -
+ * continue to unload modules on which the module depends:
+ * "-r --remove: option causes modprobe to remove a module.
+@@ -694,7 +704,7 @@ static void process_module(char *name, c
+ }
+ free(deps);
+
+- if (is_rmmod)
++ if (is_remove)
+ continue;
+
+ /* We are modprobe: load it */
+@@ -897,10 +907,10 @@ int modprobe_main(int argc UNUSED_PARAM,
+ }
+
+ #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
+- /* If not rmmod, parse possible module options given on command line.
++ /* If not rmmod/-r, parse possible module options given on command line.
+ * insmod/modprobe takes one module name, the rest are parameters. */
+ options = NULL;
+- if ('r' != applet0) {
++ if (!(option_mask32 & OPT_r)) {
+ char **arg = argv;
+ while (*++arg) {
+ /* Enclose options in quotes */
+@@ -911,7 +921,7 @@ int modprobe_main(int argc UNUSED_PARAM,
+ }
+ }
+ #else
+- if ('r' != applet0)
++ if (!(option_mask32 & OPT_r))
+ argv[1] = NULL;
+ #endif
+
+@@ -935,10 +945,11 @@ int modprobe_main(int argc UNUSED_PARAM,
+ }
+
+ /* Try to load modprobe.dep.bb */
+- load_dep_bb();
++ if ('r' != applet0) /* not rmmod */
++ load_dep_bb();
+
+ /* Load/remove modules.
+- * Only rmmod loops here, modprobe has only argv[0] */
++ * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */
+ do {
+ process_module(*argv, options);
+ } while (*++argv);