struct crypto_alg *alg;
        struct crypto_alg *q;
        LIST_HEAD(list);
+       bool best;
 
        down_write(&crypto_alg_sem);
        list_for_each_entry(q, &crypto_alg_list, cra_list) {
 
        alg->cra_flags |= CRYPTO_ALG_TESTED;
 
+       /* Only satisfy larval waiters if we are the best. */
+       best = true;
+       list_for_each_entry(q, &crypto_alg_list, cra_list) {
+               if (crypto_is_moribund(q) || !crypto_is_larval(q))
+                       continue;
+
+               if (strcmp(alg->cra_name, q->cra_name))
+                       continue;
+
+               if (q->cra_priority > alg->cra_priority) {
+                       best = false;
+                       break;
+               }
+       }
+
        list_for_each_entry(q, &crypto_alg_list, cra_list) {
                if (q == alg)
                        continue;
                                continue;
                        if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
                                continue;
-                       if (!crypto_mod_get(alg))
-                               continue;
 
-                       larval->adult = alg;
+                       if (best && crypto_mod_get(alg))
+                               larval->adult = alg;
+                       else
+                               larval->adult = ERR_PTR(-EAGAIN);
+
                        continue;
                }
 
 
        struct crypto_larval *larval = (void *)alg;
 
        BUG_ON(!crypto_is_larval(alg));
-       if (larval->adult)
+       if (!IS_ERR_OR_NULL(larval->adult))
                crypto_mod_put(larval->adult);
        kfree(larval);
 }
                alg = ERR_PTR(-ETIMEDOUT);
        else if (!alg)
                alg = ERR_PTR(-ENOENT);
+       else if (IS_ERR(alg))
+               ;
        else if (crypto_is_test_larval(larval) &&
                 !(alg->cra_flags & CRYPTO_ALG_TESTED))
                alg = ERR_PTR(-EAGAIN);