Index: sys/dev/nvme/nvme.c =================================================================== --- sys/dev/nvme/nvme.c +++ sys/dev/nvme/nvme.c @@ -452,5 +452,6 @@ */ memcpy(&status->cpl, cpl, sizeof(*cpl)); wmb(); - status->done = TRUE; + if (status != NULL) + status->done = TRUE; } Index: sys/dev/nvme/nvme_ns_cmd.c =================================================================== --- sys/dev/nvme/nvme_ns_cmd.c +++ sys/dev/nvme/nvme_ns_cmd.c @@ -158,17 +158,25 @@ int nvme_ns_dump(struct nvme_namespace *ns, void *virt, off_t offset, size_t len) { - struct nvme_completion_poll_status status; + struct nvme_completion_poll_status *status, cbarg; struct nvme_request *req; struct nvme_command *cmd; uint64_t lba, lba_count; int i; - status.done = FALSE; - req = nvme_allocate_request_vaddr(virt, len, nvme_completion_poll_cb, - &status); - if (req == NULL) - return (ENOMEM); + if (len > 0) { + status = &cbarg; + status->done = FALSE; + } else + status = NULL; + + for (i = 0; i < NVD_DUMP_TIMEOUT; i++) { + req = nvme_allocate_request_vaddr(virt, len, + nvme_completion_poll_cb, &status); + if (req != NULL) + break; + nvme_qpair_process_completions(req->qpair); + } cmd = &req->cmd; @@ -183,13 +191,17 @@ if (req->qpair == NULL) return (ENXIO); - i = 0; - while ((i++ < NVD_DUMP_TIMEOUT) && (status.done == FALSE)) { + if (len > 0) + return (0); + + for (i = 0; i < NVD_DUMP_TIMEOUT; i++) { DELAY(5); nvme_qpair_process_completions(req->qpair); + if (status->done == TRUE) + break; } - if (status.done == FALSE) + if (status->done == FALSE) return (ETIMEDOUT); return (0);