diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index bfc5fb27953949edc244f0b8228701b8f047917c..2647798b72c7621123bcaa7ce394408624b1e6e0 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -110,6 +110,7 @@ struct rpc_authops {
 
 struct rpc_credops {
 	const char *		cr_name;	/* Name of the auth flavour */
+	int			(*cr_init)(struct rpc_auth *, struct rpc_cred *);
 	void			(*crdestroy)(struct rpc_cred *);
 
 	int			(*crmatch)(struct auth_cred *, struct rpc_cred *, int);
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 1ca89c36da7abaa629e5485b0b04ca25afe42a69..8d6f1a176b159f9ee1a989dd0803fc0d5eb5d2d0 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -232,6 +232,14 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
 			goto retry;
 		} else
 			cred = new;
+	} else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
+			&& cred->cr_ops->cr_init != NULL
+			&& !(flags & RPCAUTH_LOOKUP_NEW)) {
+		int res = cred->cr_ops->cr_init(auth, cred);
+		if (res < 0) {
+			put_rpccred(cred);
+			cred = ERR_PTR(res);
+		}
 	}
 
 	return (struct rpc_cred *) cred;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 03affcbf6292b69dfe821cbea0998de2841a9a12..bb46efd92e5723475b3dd1c1cbf38f78c2af7c82 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -788,15 +788,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 	cred->gc_base.cr_ops = &gss_credops;
 	cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
 	cred->gc_service = gss_auth->service;
-	/* Is the caller prepared to initialise the credential? */
-	if (flags & RPCAUTH_LOOKUP_NEW)
-		goto out;
-	do {
-		err = gss_create_upcall(gss_auth, cred);
-	} while (err == -EAGAIN);
-	if (err < 0)
-		goto out_err;
-out:
 	return &cred->gc_base;
 
 out_err:
@@ -805,6 +796,19 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 	return ERR_PTR(err);
 }
 
+static int
+gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred)
+{
+	struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
+	struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base);
+	int err;
+
+	do {
+		err = gss_create_upcall(gss_auth, gss_cred);
+	} while (err == -EAGAIN);
+	return err;
+}
+
 static int
 gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
 {
@@ -1254,6 +1258,7 @@ static struct rpc_authops authgss_ops = {
 static struct rpc_credops gss_credops = {
 	.cr_name	= "AUTH_GSS",
 	.crdestroy	= gss_destroy_cred,
+	.cr_init	= gss_cred_init,
 	.crmatch	= gss_match,
 	.crmarshal	= gss_marshal,
 	.crrefresh	= gss_refresh,