SA-11xx PCMCIA can't detect cards present on boot

Rafal Boni <[email protected]> Mon, 14 Apr 2008 10:49:59 -0400
Newsgroups gmane.os.netbsd.ports.hpcarm,gmane.os.netbsd.devel.kernel,gmane.os.netbsd.ports.arm
Message-ID <[email protected]>
Folks:
	It looks like the vmlocking merge borked the SA-11xx PCMCIA driver's
	ability to detect cards that are present on boot, which is key 
	to at least the hpcarm port's ability to with root on a CF card.

	Looking at the changes in sys/arch/arm/sa11x0/sa11x1_pcic.c, the
	initial card-attachment (and card-event thread creation) was at
	one point done via a kthread... the vmlocking merge in rev. 1.14
	changed it to be called directly from sacpcic_attach_common().
	What this means in practical terms is that cards present at boot
	don't attach presumably because other socket state (like power,
	etc.) hasn't yet been set up.  When card detection is deferred
	until later, all works as before.

	The create-one-kthread-to-spawn-another code is somewhat silly,
	so I've replaced it that with socket attach finalization via
	config_interrupts() instead... 

	Anyone have any objections to the patch below?  I know the code
	needs whacking to fix the device_t usage, but I don't want to
	mix that up with the bugfix..

Thanks,
--rafal

-- 
  Time is an illusion; lunchtime, doubly so.     |/\/\|           Rafal Boni
                   -- Ford Prefect               |\/\/|      [email protected]
sa11xx_pcmcia_attach.diff (text/plain, 2.6 KB)
Index: sa11x1_pcic.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/sa11x0/sa11x1_pcic.c,v
retrieving revision 1.16
diff -u -p -r1.16 sa11x1_pcic.c
--- sa11x1_pcic.c	17 Oct 2007 19:53:43 -0000	1.16
+++ sa11x1_pcic.c	14 Apr 2008 03:11:40 -0000
@@ -64,6 +64,7 @@ __KERNEL_RCSID(0, "$NetBSD: sa11x1_pcic.
 #include "sacpcic.h"
 
 static int	sacpcic_print(void *, const char *);
+static void	sacpcic_config_intr(struct device *self);
 
 void
 sacpcic_attach_common(struct sacc_softc *psc, struct sacpcic_softc *sc,
@@ -99,17 +100,35 @@ sacpcic_attach_common(struct sacc_softc 
 		    config_found_ia(&sc->sc_pc.sc_dev, "pcmciabus", &paa,
 				    sacpcic_print);
 
-		sacc_intr_establish((sacc_chipset_tag_t)psc,
-				    i ? IRQ_S1_CDVALID : IRQ_S0_CDVALID,
-				    IST_EDGE_RAISE, IPL_BIO, sapcic_intr,
-				    &sc->sc_socket[i]);
-
 		/* create kthread */
 		sapcic_kthread_create(&sc->sc_socket[i]);
-#if 0 /* XXX */
-		/* establish_intr should be after creating the kthread */
-		config_interrupt(&sc->sc_socket[i], sapcic_config_intr);
-#endif
+	}
+
+	config_interrupts(&sc->sc_pc.sc_dev, sacpcic_config_intr);
+}
+
+void
+sacpcic_config_intr(struct device *self)
+{
+	struct sacpcic_softc *sc = (struct sacpcic_softc *) self;
+
+	int i;
+	for (i = 0; i < 2; i++) {
+		sacc_intr_establish(
+		    (sacc_chipset_tag_t)sc->sc_socket[i].pcictag_cookie,
+		    i ? IRQ_S1_CDVALID : IRQ_S0_CDVALID,
+		    IST_EDGE_RAISE, IPL_BIO, sapcic_intr,
+		    &sc->sc_socket[i]);
+
+		sc->sc_socket[i].laststatus = 
+		    (sc->sc_socket[i].pcictag->read)(&sc->sc_socket[i], 
+						     SAPCIC_STATUS_CARD);
+		if (sc->sc_socket[i].laststatus == SAPCIC_CARD_VALID) {
+			printf("%s: card present\n",
+			       sc->sc_socket[i].sc->sc_dev.dv_xname);
+
+			pcmcia_card_attach(sc->sc_socket[i].pcmcia);
+		}
 	}
 }
 
Index: sa11xx_pcic.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/sa11x0/sa11xx_pcic.c,v
retrieving revision 1.11
diff -u -p -r1.11 sa11xx_pcic.c
--- sa11xx_pcic.c	6 Dec 2007 17:00:31 -0000	1.11
+++ sa11xx_pcic.c	14 Apr 2008 03:11:40 -0000
@@ -124,14 +124,6 @@ sapcic_kthread_create(void *arg)
 
 	mutex_init(&so->sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
 
-	so->laststatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
-	if (so->laststatus == SAPCIC_CARD_VALID) {
-		printf("%s: card present\n",
-		       so->sc->sc_dev.dv_xname);
-
-		pcmcia_card_attach(so->pcmcia);
-	}
-
 	if (kthread_create(PRI_NONE, 0, NULL, sapcic_event_thread, so,
 	    &so->event_thread, "%s,%d", so->sc->sc_dev.dv_xname, so->socket)) {
 		printf("%s: unable to create event thread for socket %d\n",