struct nvme_controller * nvme_attach(void *devhandle) { struct nvme_controller *ctrlr; int status; uint64_t phys_addr = 0; ctrlr = nvme_malloc("nvme_ctrlr", sizeof(struct nvme_controller), 64, &phys_addr); if (ctrlr == NULL) { nvme_printf(NULL, "could not allocate ctrlr\n"); return NULL; } status = nvme_ctrlr_construct(ctrlr, devhandle); if (status != 0) { nvme_free(ctrlr); return NULL; } if (nvme_ctrlr_start(ctrlr) != 0) { nvme_ctrlr_destruct(ctrlr); nvme_free(ctrlr); return NULL; } return ctrlr; }
/** * Allocate a request as well as a physically contiguous buffer to copy to/from the user's buffer. * * This is intended for use in non-fast-path functions (admin commands, reservations, etc.) * where the overhead of a copy is not a problem. */ struct nvme_request * nvme_allocate_request_user_copy(void *buffer, uint32_t payload_size, spdk_nvme_cmd_cb cb_fn, void *cb_arg, bool host_to_controller) { struct nvme_request *req; void *contig_buffer = NULL; uint64_t phys_addr; if (buffer && payload_size) { contig_buffer = nvme_malloc(payload_size, 4096, &phys_addr); if (!contig_buffer) { return NULL; } if (host_to_controller) { memcpy(contig_buffer, buffer, payload_size); } } req = nvme_allocate_request_contig(contig_buffer, payload_size, nvme_user_copy_cmd_complete, NULL); if (!req) { nvme_free(buffer); return NULL; } req->user_cb_fn = cb_fn; req->user_cb_arg = cb_arg; req->user_buffer = buffer; req->cb_arg = req; return req; }
int nvme_detach(struct nvme_controller *ctrlr) { nvme_ctrlr_destruct(ctrlr); nvme_free(ctrlr); return 0; }
int spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr) { pthread_mutex_lock(&g_spdk_nvme_driver->lock); nvme_ctrlr_destruct(ctrlr); TAILQ_REMOVE(&g_spdk_nvme_driver->attached_ctrlrs, ctrlr, tailq); nvme_free(ctrlr); pthread_mutex_unlock(&g_spdk_nvme_driver->lock); return 0; }
static void nvme_user_copy_cmd_complete(void *arg, const struct spdk_nvme_cpl *cpl) { struct nvme_request *req = arg; enum spdk_nvme_data_transfer xfer; if (req->user_buffer && req->payload_size) { /* Copy back to the user buffer and free the contig buffer */ assert(req->payload.type == NVME_PAYLOAD_TYPE_CONTIG); xfer = spdk_nvme_opc_get_data_transfer(req->cmd.opc); if (xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST || xfer == SPDK_NVME_DATA_BIDIRECTIONAL) { memcpy(req->user_buffer, req->payload.u.contig, req->payload_size); } nvme_free(req->payload.u.contig); } /* Call the user's original callback now that the buffer has been copied */ req->user_cb_fn(req->user_cb_arg, cpl); }
static struct spdk_nvme_ctrlr * nvme_attach(void *devhandle) { struct spdk_nvme_ctrlr *ctrlr; int status; uint64_t phys_addr = 0; ctrlr = nvme_malloc(sizeof(struct spdk_nvme_ctrlr), 64, &phys_addr); if (ctrlr == NULL) { SPDK_ERRLOG("could not allocate ctrlr\n"); return NULL; } status = nvme_ctrlr_construct(ctrlr, devhandle); if (status != 0) { nvme_free(ctrlr); return NULL; } return ctrlr; }