From 3d08e8c2cc5b41ac21ec9eebca1043e939aeaae6 Mon Sep 17 00:00:00 2001
From: Guido van Rooij <guido@FreeBSD.org>
Date: Wed, 4 Feb 1998 20:19:39 +0000
Subject: [PATCH] This seems to fix my problem that after resume/suspend,
 sometimes pccard claims that the driver is already allocated. It works around
 a race when pccardd gets woken up too late after a resume.

This is a 2.2.6 candidate.
Reviewed by:	nate@freebsd.org
---
 usr.sbin/pccard/pccardd/cardd.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/usr.sbin/pccard/pccardd/cardd.c b/usr.sbin/pccard/pccardd/cardd.c
index a631615d399d..17dd99d72e3e 100644
--- a/usr.sbin/pccard/pccardd/cardd.c
+++ b/usr.sbin/pccard/pccardd/cardd.c
@@ -26,7 +26,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-	"$Id: cardd.c,v 1.22 1997/11/25 19:15:59 nate Exp $";
+	"$Id: cardd.c,v 1.23 1997/12/08 06:35:07 nate Exp $";
 #endif /* not lint */
 
 #include <fcntl.h>
@@ -220,19 +220,31 @@ slot_change(struct slot *sp)
 	if (state.state == sp->state)
 		logmsg("State same as before, continuing anyway");
 #endif
-	sp->state = state.state;
-	switch (sp->state) {
+	switch (state.state) {
 	case empty:
 	case noslot:
 		card_removed(sp);
 		break;
 	case filled:
+		/*
+		 * If state was already filled, fake a removal first to get
+		 * our state in sync with the kernel. This happens when the
+		 * systems resumes and we only get to process the state 
+		 * change from suspend to empty after inserted() has run.
+		 * In that case the kernel state is perfectly normal.
+		 *
+		 * The reason for not doing nothing is that the kernel
+		 * has to be informed again about IRQ and IO window.
+		 */
+		if (state.state == sp->state)
+			card_removed(sp);
 		card_inserted(sp);
 		break;
 	case suspend:
 		/* ignored */
 		break;
 	}
+	sp->state = state.state;
 }
 
 /*