Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_nvme.c
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
/* TODO: | /* TODO: | ||||
- create async event for smart and log | - create async event for smart and log | ||||
- intr coalesce | - intr coalesce | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/errno.h> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <net/ieee_oui.h> | #include <net/ieee_oui.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <pthread.h> | #include <pthread.h> | ||||
#include <semaphore.h> | #include <semaphore.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
▲ Show 20 Lines • Show All 1,313 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct pci_nvme_ioreq *req = br->br_param; | struct pci_nvme_ioreq *req = br->br_param; | ||||
DPRINTF("%s error %d %s", __func__, err, strerror(err)); | DPRINTF("%s error %d %s", __func__, err, strerror(err)); | ||||
pthread_cond_signal(&req->cv); | pthread_cond_signal(&req->cv); | ||||
} | } | ||||
/* | |||||
* Implements the Flush command. The specification states: | |||||
* If a volatile write cache is not present, Flush commands complete | |||||
* successfully and have no effect | |||||
* in the description of the Volatile Write Cache (VWC) field of the Identify | |||||
* Controller data. Therefore, set status to Success if the command is | |||||
* not supported (i.e. RAM or as indicated by the blockif). | |||||
*/ | |||||
static bool | static bool | ||||
nvme_opc_flush(struct pci_nvme_softc *sc, | |||||
struct nvme_command *cmd, | |||||
struct pci_nvme_blockstore *nvstore, | |||||
struct pci_nvme_ioreq *req, | |||||
uint16_t *status) | |||||
{ | |||||
bool pending = false; | |||||
if (nvstore->type == NVME_STOR_RAM) { | |||||
pci_nvme_status_genc(status, NVME_SC_SUCCESS); | |||||
} else { | |||||
int err; | |||||
req->io_req.br_callback = pci_nvme_io_done; | |||||
err = blockif_flush(nvstore->ctx, &req->io_req); | |||||
switch (err) { | |||||
case 0: | |||||
pending = true; | |||||
break; | |||||
case EOPNOTSUPP: | |||||
pci_nvme_status_genc(status, NVME_SC_SUCCESS); | |||||
break; | |||||
default: | |||||
pci_nvme_status_genc(status, NVME_SC_INTERNAL_DEVICE_ERROR); | |||||
} | |||||
} | |||||
return (pending); | |||||
} | |||||
static bool | |||||
nvme_opc_write_read(struct pci_nvme_softc *sc, | nvme_opc_write_read(struct pci_nvme_softc *sc, | ||||
struct nvme_command *cmd, | struct nvme_command *cmd, | ||||
struct pci_nvme_blockstore *nvstore, | struct pci_nvme_blockstore *nvstore, | ||||
struct pci_nvme_ioreq *req, | struct pci_nvme_ioreq *req, | ||||
uint16_t *status) | uint16_t *status) | ||||
{ | { | ||||
uint64_t lba, nblocks, bytes; | uint64_t lba, nblocks, bytes; | ||||
size_t offset; | size_t offset; | ||||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | while (sqhead != atomic_load_acq_short(&sq->tail)) { | ||||
req->nvme_sq = sq; | req->nvme_sq = sq; | ||||
req->sqid = idx; | req->sqid = idx; | ||||
req->opc = cmd->opc; | req->opc = cmd->opc; | ||||
req->cid = cmd->cid; | req->cid = cmd->cid; | ||||
req->nsid = cmd->nsid; | req->nsid = cmd->nsid; | ||||
switch (cmd->opc) { | switch (cmd->opc) { | ||||
case NVME_OPC_FLUSH: | case NVME_OPC_FLUSH: | ||||
pci_nvme_status_genc(&status, NVME_SC_SUCCESS); | pending = nvme_opc_flush(sc, cmd, &sc->nvstore, | ||||
req, &status); | |||||
break; | break; | ||||
case NVME_OPC_WRITE: | case NVME_OPC_WRITE: | ||||
case NVME_OPC_READ: | case NVME_OPC_READ: | ||||
pending = nvme_opc_write_read(sc, cmd, &sc->nvstore, | pending = nvme_opc_write_read(sc, cmd, &sc->nvstore, | ||||
req, &status); | req, &status); | ||||
break; | break; | ||||
case NVME_OPC_WRITE_ZEROES: | case NVME_OPC_WRITE_ZEROES: | ||||
/* TODO: write zeroes | /* TODO: write zeroes | ||||
▲ Show 20 Lines • Show All 525 Lines • Show Last 20 Lines |