git: 9front

Download patch

ref: f568f31c3fb6e41bcdde45e892ccea7656a89c5e
parent: 110645af6c17500034abafc29d4d2526e514aa22
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Nov 7 12:41:57 EST 2021

sdmmc: do card init in a background process after the first try

Some mmc controllers have no card detect pin, so the only
way to detect card presence is to issue the ACMD41 which will
fail after a pretty long timeout.

To avoid mmconline() blocking, we only try to initialize the
card synchronous once, and then retry in a background process,
while returning immediately from mmconline() while the retry
is in progress.

This speeds up network boot times significantly on a raspi
without a sdcard inserted.

--- a/sys/src/9/port/sdmmc.c
+++ b/sys/src/9/port/sdmmc.c
@@ -79,6 +79,8 @@
 	u32int	ocr;
 	u32int	cid[4];
 	u32int	csd[4];
+
+	int	retry;
 };
 
 extern SDifc sdmmcifc;
@@ -197,26 +199,12 @@
 }
 
 static int
-mmconline(SDunit *unit)
+cardinit(Ctlr *ctl)
 {
-	int hcs, i;
 	u32int r[4];
-	Ctlr *ctl;
-	SDio *io;
+	int hcs, i;
+	SDio *io = ctl->io;
 
-	ctl = unit->dev->ctlr;
-	io = ctl->io;
-	assert(unit->subno == 0);
-
-	if(waserror()){
-		unit->sectors = 0;
-		return 0;
-	}
-	if(unit->sectors != 0){
-		io->cmd(SEND_STATUS, ctl->rca<<Rcashift, r);
-		poperror();
-		return 1;
-	}
 	io->cmd(GO_IDLE_STATE, 0, r);
 	hcs = 0;
 	if(!waserror()){
@@ -226,17 +214,14 @@
 		poperror();
 	}
 	for(i = 0; i < Inittimeout; i++){
-		delay(100);
+		tsleep(&up->sleep, return0, nil, 100);
 		io->cmd(APP_CMD, 0, r);
 		io->cmd(SD_SEND_OP_COND, hcs|V3_3, r);
 		if(r[0] & Powerup)
 			break;
 	}
-	if(i == Inittimeout){
-		print("sdmmc: card won't power up\n");
-		poperror();
+	if(i == Inittimeout)
 		return 2;
-	}
 	ctl->ocr = r[0];
 	io->cmd(ALL_SEND_CID, 0, r);
 	memmove(ctl->cid, r, sizeof ctl->cid);
@@ -244,6 +229,52 @@
 	ctl->rca = r[0]>>16;
 	io->cmd(SEND_CSD, ctl->rca<<Rcashift, r);
 	memmove(ctl->csd, r, sizeof ctl->csd);
+	return 1;
+}
+
+static void
+retryproc(void *arg)
+{
+	Ctlr *ctl = arg;
+	int i = 0;
+
+	while(waserror())
+		;
+	if(i++ < ctl->retry)
+		cardinit(ctl);
+	USED(i);
+	ctl->retry = 0;
+	pexit("", 1);
+}
+
+static int
+mmconline(SDunit *unit)
+{
+	u32int r[4];
+	Ctlr *ctl;
+	SDio *io;
+
+	assert(unit->subno == 0);
+	ctl = unit->dev->ctlr;
+	io = ctl->io;
+
+	if(ctl->retry)
+		return 0;
+	if(waserror()){
+		unit->sectors = 0;
+		if(ctl->retry++ == 0)
+			kproc(unit->name, retryproc, ctl);
+		return 0;
+	}
+	if(unit->sectors != 0){
+		io->cmd(SEND_STATUS, ctl->rca<<Rcashift, r);
+		poperror();
+		return 1;
+	}
+	if(cardinit(ctl) != 1){
+		poperror();
+		return 2;
+	}
 	identify(unit, ctl->csd);
 	io->cmd(SELECT_CARD, ctl->rca<<Rcashift, r);
 	io->cmd(SET_BLOCKLEN, unit->secsize, r);
@@ -265,7 +296,6 @@
 	Ctlr *ctl;
 	int i, n;
 
-	ctl = unit->dev->ctlr;
 	assert(unit->subno == 0);
 	if(unit->sectors == 0){
 		mmconline(unit);
@@ -272,6 +302,7 @@
 		if(unit->sectors == 0)
 			return 0;
 	}
+	ctl = unit->dev->ctlr;
 	n = snprint(p, l, "rca %4.4ux ocr %8.8ux\ncid ", ctl->rca, ctl->ocr);
 	for(i = nelem(ctl->cid)-1; i >= 0; i--)
 		n += snprint(p+n, l-n, "%8.8ux", ctl->cid[i]);
--