diff e23bb0103b46e73f9ce8d69abb19a3726135fff3 uncommitted --- a/sys/src/9/port/sdnvme.c +++ b/sys/src/9/port/sdnvme.c @@ -208,9 +208,8 @@ SQ *sq = ws->queue; Ctlr *ctlr = sq->ctlr; - if(e != nil) { + if(e != nil) dmaflush(1, e, 64); - } coherence(); ctlr->reg[DBell + ((sq-ctlr->sq)*2+0 << ctlr->dstrd)] = sq->tail & sq->mask; if(sq > ctlr->sq) { @@ -270,9 +269,8 @@ count -= n; lba += n; } - if(!write) { + if(!write) dmaflush(0, a, p - (uchar*)a); - } return p - (uchar*)a; } @@ -344,6 +342,83 @@ } static int +nvmewctl(SDunit *u, Cmdbuf *cmd) +{ + u8int *data, *psd; + int i, r, n, en; + u32int *q, a; + Ctlr *ctlr; + WS ws; + + if((ctlr = u->dev->ctlr) == nil || ctlr->ident == nil){ + cmderror(cmd, Ebadctl); + return 0; + } + if(cmd->nf != 2){ +badarg: + cmderror(cmd, Ebadarg); + return 0; + } + en = atoi(cmd->f[1]); + + if(strcmp(cmd->f[0], "apst") == 0 && (ctlr->ident[265] & 1) != 0){ + if((data = mallocalign(0x1000, ctlr->mps, 0, 0)) == nil){ + cmderror(cmd, Enomem); + return 0; + } + q = qcmd(&ws, ctlr, 1, 0x0a, 0, data, 256); + q[10] = 0x0c; + if((r = wcmd(&ws, q)) == 0 && en != (ws.cdw0 & 1)){ + if((n = ctlr->ident[263]) > 31) /* npss */ + n = 0; + memset(data, 0, sizeof(data)); + for(a = 0, i = n; i >= 0; i--){ + if(a != 0){ + data[i*8+0] = a; + data[i*8+1] = a>>8; + data[i*8+2] = a>>16; + data[i*8+3] = a>>24; + } + psd = (uchar*)ctlr->ident + 2048 + i*32; + if((psd[3] & 1) == 0) /* nops only */ + continue; + a = psd[8] | psd[9]<<8 | psd[10]<<16 | psd[11]<<24; /* exlat */ + a += psd[4] | psd[5]<<8 | psd[6]<<16 | psd[7]<<24; /* enlat */ + if(a > (1<<(32-8))-1) + a = (1<<(32-8))-1; + a = (a+19)/20; + a = a<<8 | i<<3; + } + q = qcmd(&ws, ctlr, 1, 0x09, 0, data, 256); + q[10] = 0x0c; + q[11] = en != 0; + r = wcmd(&ws, q); + } + free(data); + }else if(strcmp(cmd->f[0], "workload") == 0){ + q = qcmd(&ws, ctlr, 1, 0x0a, 0, nil, 0); + q[10] = 2; + if((r = wcmd(&ws, q)) == 0){ + u32int ps = ws.cdw0 & 0x0f; + q = qcmd(&ws, ctlr, 1, 0x09, 0, nil, 0); + q[10] = 0x02; + q[11] = en<<5 | ps; + r = wcmd(&ws, q); + } + }else if(strcmp(cmd->f[0], "noppme") == 0){ + q = qcmd(&ws, ctlr, 1, 0x09, 0, nil, 0); + q[10] = 0x11; + q[11] = en != 0; + r = wcmd(&ws, q); + }else + goto badarg; + + if(r != 0) + cmderror(cmd, "failed"); + return 0; +} + +static int nvmerctl(SDunit *u, char *p, int l) { Ctlr *ctlr; @@ -521,9 +596,16 @@ ctlr->reg[IntMs] = ~ctlr->ints; iunlock(&ctlr->intr); + /* notify normal power off */ + ctlr->reg[CCfg] = (ctlr->reg[CCfg] & ~(3<<14)) | 1<<14; + for(i = 0; i < 30; i++){ + if((ctlr->reg[CSts] & 0xc) == 0x8) + break; + tsleep(&up->sleep, return0, nil, 100); + } + /* disable controller */ ctlr->reg[CCfg] = 0; - for(i = 0; i < 10; i++){ if((ctlr->reg[CSts] & 1) == 0) break; @@ -720,7 +802,7 @@ nvmeonline, /* online */ nvmerio, /* rio */ nvmerctl, /* rctl */ - nil, /* wctl */ + nvmewctl, /* wctl */ nvmebio, /* bio */ nil, /* probe */