changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: sdiahci: implement reset timeout for ahciencreset(), make blink() never block, fix map[] access in ledkproc()

changeset 7436: 42c10e6101f2
parent 7435: 874554781a81
child 7437: f9127e08a6a5
author: cinap_lenrek@felloff.net
date: Sun, 17 Nov 2019 21:19:55 +0100
files: sys/src/9/pc/sdiahci.c
description: sdiahci: implement reset timeout for ahciencreset(), make blink() never block, fix map[] access in ledkproc()

Ori_B reports that his controller gets stuck in the ahciencreset()
wait loop. so we implement a 1000 ms timeout. we replace delay()
with esleep() as we are always called from the ledkproc().

blink() could enter infinite delay loop as well, so instead of
waiting for the message to get transmitted we exit making it
non-blocking (we will get called again anyway).

the access to the controller map[] was wrong in ledkproc(). the
index is the controller number, not the drive number!
     1.1--- a/sys/src/9/pc/sdiahci.c
     1.2+++ b/sys/src/9/pc/sdiahci.c
     1.3@@ -1215,14 +1215,19 @@ static int
     1.4 ahciencreset(Ctlr *c)
     1.5 {
     1.6 	Ahba *h;
     1.7+	int i;
     1.8 
     1.9 	if(c->enctype == Eesb)
    1.10 		return 0;
    1.11 	h = c->hba;
    1.12 	h->emctl |= Emrst;
    1.13-	while(h->emctl & Emrst)
    1.14-		delay(1);
    1.15-	return 0;
    1.16+	for(i = 0; i < 1000; i++){
    1.17+		if((h->emctl & Emrst) == 0)
    1.18+			return 0;
    1.19+		esleep(1);
    1.20+	}
    1.21+	print("%s: ahciencreset: hung ctlr\n", Tname(c));
    1.22+	return -1;
    1.23 }
    1.24 
    1.25 /*
    1.26@@ -1301,9 +1306,11 @@ blink(Drive *d, ulong t)
    1.27 		return 0;
    1.28 	c = d->ctlr;
    1.29 	h = c->hba;
    1.30+
    1.31 	/* ensure last message has been transmitted */
    1.32-	while(h->emctl & Tmsg)
    1.33-		microdelay(1);
    1.34+	if(h->emctl & Tmsg)
    1.35+		return -1;
    1.36+
    1.37 	switch(c->enctype){
    1.38 	default:
    1.39 		panic("%s: bad led type %d", dnam(d), c->enctype);
    1.40@@ -1403,30 +1410,34 @@ ledkproc(void*)
    1.41 	memset(map, 0, sizeof map);
    1.42 	for(i = 0; i < niactlr; i++)
    1.43 		if(iactlr[i].enctype != 0){
    1.44-			ahciencreset(iactlr + i);
    1.45+			if(ahciencreset(iactlr + i) == -1)
    1.46+				continue;
    1.47 			map[i] = 1;
    1.48 			j++;
    1.49 		}
    1.50 	if(j == 0)
    1.51 		pexit("no work", 1);
    1.52 	for(i = 0; i < niadrive; i++){
    1.53-		iadrive[i]->nled = 3;		/* hardcoded */
    1.54-		if(iadrive[i]->ctlr->enctype == Eesb)
    1.55-			iadrive[i]->nled = 3;
    1.56-		iadrive[i]->ledbits = -1;
    1.57+		d = iadrive[i];
    1.58+		d->nled = 3;		/* hardcoded */
    1.59+		if(d->ctlr->enctype == Eesb)
    1.60+			d->nled = 3;
    1.61+		d->ledbits = -1;
    1.62 	}
    1.63 	for(i = 0; ; i++){
    1.64 		t0 = Ticks;
    1.65 		for(j = 0; j < niadrive; ){
    1.66-			c = iadrive[j]->ctlr;
    1.67-			if(map[j] == 0)
    1.68-				j += c->enctype;
    1.69-			else if(c->enctype == Eesb){
    1.70+			d = iadrive[j];
    1.71+			c = d->ctlr;
    1.72+			if(map[c - iactlr] == 0)
    1.73+				j++;
    1.74+			else
    1.75+			if(c->enctype == Eesb){
    1.76 				blinkesb(c, i);
    1.77 				j += c->ndrive;
    1.78 			}else{
    1.79-				d = iadrive[j++];
    1.80 				blink(d, i);
    1.81+				j++;
    1.82 			}
    1.83 		}
    1.84 		t1 = Ticks;