diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 131bbc1bd44627136f9d7d4a8ff600b4faed9dd4..316105e30064f08d39341e7078908547689545ab 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -767,6 +767,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 		.type		= PSMOUSE_LIFEBOOK,
 		.name		= "LBPS/2",
 		.alias		= "lifebook",
+		.detect		= lifebook_detect,
 		.init		= lifebook_init,
 	},
 #endif
@@ -844,7 +845,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 	},
 };
 
-static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type)
+static const struct psmouse_protocol *__psmouse_protocol_by_type(enum psmouse_type type)
 {
 	int i;
 
@@ -852,6 +853,17 @@ static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type
 		if (psmouse_protocols[i].type == type)
 			return &psmouse_protocols[i];
 
+	return NULL;
+}
+
+static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type)
+{
+	const struct psmouse_protocol *proto;
+
+	proto = __psmouse_protocol_by_type(type);
+	if (proto)
+		return proto;
+
 	WARN_ON(1);
 	return &psmouse_protocols[0];
 }
@@ -910,18 +922,37 @@ static void psmouse_apply_defaults(struct psmouse *psmouse)
 	psmouse->pt_deactivate = NULL;
 }
 
-/*
- * Apply default settings to the psmouse structure and call specified
- * protocol detection or initialization routine.
- */
-static int psmouse_do_detect(int (*detect)(struct psmouse *psmouse,
-					   bool set_properties),
-			     struct psmouse *psmouse, bool set_properties)
+static bool psmouse_try_protocol(struct psmouse *psmouse,
+				 enum psmouse_type type,
+				 unsigned int *max_proto,
+				 bool set_properties, bool init_allowed)
 {
+	const struct psmouse_protocol *proto;
+
+	proto = __psmouse_protocol_by_type(type);
+	if (!proto)
+		return false;
+
 	if (set_properties)
 		psmouse_apply_defaults(psmouse);
 
-	return detect(psmouse, set_properties);
+	if (proto->detect(psmouse, set_properties) != 0)
+		return false;
+
+	if (set_properties && proto->init && init_allowed) {
+		if (proto->init(psmouse) != 0) {
+			/*
+			 * We detected device, but init failed. Adjust
+			 * max_proto so we only try standard protocols.
+			 */
+			if (*max_proto > PSMOUSE_IMEX)
+				*max_proto = PSMOUSE_IMEX;
+
+			return false;
+		}
+	}
+
+	return true;
 }
 
 /*
@@ -937,12 +968,12 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	 * Always check for focaltech, this is safe as it uses pnp-id
 	 * matching.
 	 */
-	if (psmouse_do_detect(focaltech_detect, psmouse, set_properties) == 0) {
-		if (max_proto > PSMOUSE_IMEX) {
-			if (IS_ENABLED(CONFIG_MOUSE_PS2_FOCALTECH) &&
-			    (!set_properties || focaltech_init(psmouse) == 0)) {
-				return PSMOUSE_FOCALTECH;
-			}
+	if (psmouse_try_protocol(psmouse, PSMOUSE_FOCALTECH,
+				 &max_proto, set_properties, false)) {
+		if (max_proto > PSMOUSE_IMEX &&
+		    IS_ENABLED(CONFIG_MOUSE_PS2_FOCALTECH) &&
+		    (!set_properties || focaltech_init(psmouse) == 0)) {
+			return PSMOUSE_FOCALTECH;
 		}
 		/*
 		 * Restrict psmouse_max_proto so that psmouse_initialize()
@@ -959,26 +990,21 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	 * We always check for LifeBook because it does not disturb mouse
 	 * (it only checks DMI information).
 	 */
-	if (psmouse_do_detect(lifebook_detect, psmouse, set_properties) == 0) {
-		if (max_proto > PSMOUSE_IMEX) {
-			if (!set_properties || lifebook_init(psmouse) == 0)
-				return PSMOUSE_LIFEBOOK;
-		}
-	}
+	if (psmouse_try_protocol(psmouse, PSMOUSE_LIFEBOOK, &max_proto,
+				 set_properties, max_proto > PSMOUSE_IMEX))
+		return PSMOUSE_LIFEBOOK;
 
-	if (psmouse_do_detect(vmmouse_detect, psmouse, set_properties) == 0) {
-		if (max_proto > PSMOUSE_IMEX) {
-			if (!set_properties || vmmouse_init(psmouse) == 0)
-				return PSMOUSE_VMMOUSE;
-		}
-	}
+	if (psmouse_try_protocol(psmouse, PSMOUSE_VMMOUSE, &max_proto,
+				 set_properties, max_proto > PSMOUSE_IMEX))
+		return PSMOUSE_VMMOUSE;
 
 	/*
 	 * Try Kensington ThinkingMouse (we try first, because Synaptics
 	 * probe upsets the ThinkingMouse).
 	 */
 	if (max_proto > PSMOUSE_IMEX &&
-	    psmouse_do_detect(thinking_detect, psmouse, set_properties) == 0) {
+	    psmouse_try_protocol(psmouse, PSMOUSE_THINKPS, &max_proto,
+				 set_properties, true)) {
 		return PSMOUSE_THINKPS;
 	}
 
@@ -989,7 +1015,8 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	 * probing for IntelliMouse.
 	 */
 	if (max_proto > PSMOUSE_PS2 &&
-	    psmouse_do_detect(synaptics_detect, psmouse, set_properties) == 0) {
+	    psmouse_try_protocol(psmouse, PSMOUSE_SYNAPTICS, &max_proto,
+				 set_properties, false)) {
 		synaptics_hardware = true;
 
 		if (max_proto > PSMOUSE_IMEX) {
@@ -1025,64 +1052,48 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	 * Trackpads.
 	 */
 	if (max_proto > PSMOUSE_IMEX &&
-	    psmouse_do_detect(cypress_detect, psmouse, set_properties) == 0) {
-		if (!set_properties || cypress_init(psmouse) == 0)
-			return PSMOUSE_CYPRESS;
-
-		/*
-		 * Finger Sensing Pad probe upsets some modules of
-		 * Cypress Trackpad, must avoid Finger Sensing Pad
-		 * probe if Cypress Trackpad device detected.
-		 */
-		max_proto = PSMOUSE_IMEX;
+	    psmouse_try_protocol(psmouse, PSMOUSE_CYPRESS, &max_proto,
+				 set_properties, true)) {
+		return PSMOUSE_CYPRESS;
 	}
 
 	/* Try ALPS TouchPad */
 	if (max_proto > PSMOUSE_IMEX) {
 		ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
-		if (psmouse_do_detect(alps_detect,
-				      psmouse, set_properties) == 0) {
-			if (!set_properties || alps_init(psmouse) == 0)
-				return PSMOUSE_ALPS;
-
-			/* Init failed, try basic relative protocols */
-			max_proto = PSMOUSE_IMEX;
-		}
+		if (psmouse_try_protocol(psmouse, PSMOUSE_ALPS,
+					 &max_proto, set_properties, true))
+			return PSMOUSE_ALPS;
 	}
 
 	/* Try OLPC HGPK touchpad */
 	if (max_proto > PSMOUSE_IMEX &&
-	    psmouse_do_detect(hgpk_detect, psmouse, set_properties) == 0) {
-		if (!set_properties || hgpk_init(psmouse) == 0)
-			return PSMOUSE_HGPK;
-			/* Init failed, try basic relative protocols */
-		max_proto = PSMOUSE_IMEX;
+	    psmouse_try_protocol(psmouse, PSMOUSE_HGPK, &max_proto,
+				 set_properties, true)) {
+		return PSMOUSE_HGPK;
 	}
 
 	/* Try Elantech touchpad */
 	if (max_proto > PSMOUSE_IMEX &&
-	    psmouse_do_detect(elantech_detect, psmouse, set_properties) == 0) {
-		if (!set_properties || elantech_init(psmouse) == 0)
-			return PSMOUSE_ELANTECH;
-		/* Init failed, try basic relative protocols */
-		max_proto = PSMOUSE_IMEX;
+	    psmouse_try_protocol(psmouse, PSMOUSE_ELANTECH,
+				 &max_proto, set_properties, true)) {
+		return PSMOUSE_ELANTECH;
 	}
 
 	if (max_proto > PSMOUSE_IMEX) {
-		if (psmouse_do_detect(genius_detect,
-				      psmouse, set_properties) == 0)
+		if (psmouse_try_protocol(psmouse, PSMOUSE_GENPS,
+					 &max_proto, set_properties, true))
 			return PSMOUSE_GENPS;
 
-		if (psmouse_do_detect(ps2pp_init,
-				      psmouse, set_properties) == 0)
+		if (psmouse_try_protocol(psmouse, PSMOUSE_PS2PP,
+					 &max_proto, set_properties, true))
 			return PSMOUSE_PS2PP;
 
-		if (psmouse_do_detect(trackpoint_detect,
-				      psmouse, set_properties) == 0)
+		if (psmouse_try_protocol(psmouse, PSMOUSE_TRACKPOINT,
+					 &max_proto, set_properties, true))
 			return PSMOUSE_TRACKPOINT;
 
-		if (psmouse_do_detect(touchkit_ps2_detect,
-				      psmouse, set_properties) == 0)
+		if (psmouse_try_protocol(psmouse, PSMOUSE_TOUCHKIT_PS2,
+					 &max_proto, set_properties, true))
 			return PSMOUSE_TOUCHKIT_PS2;
 	}
 
@@ -1090,14 +1101,10 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	 * Try Finger Sensing Pad. We do it here because its probe upsets
 	 * Trackpoint devices (causing TP_READ_ID command to time out).
 	 */
-	if (max_proto > PSMOUSE_IMEX) {
-		if (psmouse_do_detect(fsp_detect,
-				      psmouse, set_properties) == 0) {
-			if (!set_properties || fsp_init(psmouse) == 0)
-				return PSMOUSE_FSP;
-			/* Init failed, try basic relative protocols */
-			max_proto = PSMOUSE_IMEX;
-		}
+	if (max_proto > PSMOUSE_IMEX &&
+	    psmouse_try_protocol(psmouse, PSMOUSE_FSP,
+				 &max_proto, set_properties, true)) {
+		return PSMOUSE_FSP;
 	}
 
 	/*
@@ -1109,14 +1116,14 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	psmouse_reset(psmouse);
 
 	if (max_proto >= PSMOUSE_IMEX &&
-	    psmouse_do_detect(im_explorer_detect,
-			      psmouse, set_properties) == 0) {
+	    psmouse_try_protocol(psmouse, PSMOUSE_IMEX,
+				 &max_proto, set_properties, true)) {
 		return PSMOUSE_IMEX;
 	}
 
 	if (max_proto >= PSMOUSE_IMPS &&
-	    psmouse_do_detect(intellimouse_detect,
-			      psmouse, set_properties) == 0) {
+	    psmouse_try_protocol(psmouse, PSMOUSE_IMPS,
+				 &max_proto, set_properties, true)) {
 		return PSMOUSE_IMPS;
 	}
 
@@ -1124,7 +1131,8 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	 * Okay, all failed, we have a standard mouse here. The number of
 	 * the buttons is still a question, though. We assume 3.
 	 */
-	psmouse_do_detect(ps2bare_detect, psmouse, set_properties);
+	psmouse_try_protocol(psmouse, PSMOUSE_PS2,
+			     &max_proto, set_properties, true);
 
 	if (synaptics_hardware) {
 		/*