1240616Sjimharris/*- 2240616Sjimharris * Copyright (C) 2012 Intel Corporation 3240616Sjimharris * All rights reserved. 4240616Sjimharris * 5240616Sjimharris * Redistribution and use in source and binary forms, with or without 6240616Sjimharris * modification, are permitted provided that the following conditions 7240616Sjimharris * are met: 8240616Sjimharris * 1. Redistributions of source code must retain the above copyright 9240616Sjimharris * notice, this list of conditions and the following disclaimer. 10240616Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 11240616Sjimharris * notice, this list of conditions and the following disclaimer in the 12240616Sjimharris * documentation and/or other materials provided with the distribution. 13240616Sjimharris * 14240616Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15240616Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16240616Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17240616Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18240616Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240616Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20240616Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21240616Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22240616Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23240616Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24240616Sjimharris * SUCH DAMAGE. 25240616Sjimharris */ 26240616Sjimharris 27240616Sjimharris#include <sys/cdefs.h> 28240616Sjimharris__FBSDID("$FreeBSD: stable/11/sys/dev/nvme/nvme_ns_cmd.c 328664 2018-02-01 15:27:47Z mav $"); 29240616Sjimharris 30240616Sjimharris#include "nvme_private.h" 31240616Sjimharris 32241657Sjimharrisint 33240616Sjimharrisnvme_ns_cmd_read(struct nvme_namespace *ns, void *payload, uint64_t lba, 34240616Sjimharris uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg) 35240616Sjimharris{ 36241659Sjimharris struct nvme_request *req; 37240616Sjimharris 38253474Sjimharris req = nvme_allocate_request_vaddr(payload, 39253474Sjimharris lba_count*nvme_ns_get_sector_size(ns), cb_fn, cb_arg); 40240616Sjimharris 41241660Sjimharris if (req == NULL) 42241657Sjimharris return (ENOMEM); 43240616Sjimharris 44301778Simp nvme_ns_read_cmd(&req->cmd, ns->id, lba, lba_count); 45240616Sjimharris 46241660Sjimharris nvme_ctrlr_submit_io_request(ns->ctrlr, req); 47240616Sjimharris 48241657Sjimharris return (0); 49240616Sjimharris} 50240616Sjimharris 51241657Sjimharrisint 52248977Sjimharrisnvme_ns_cmd_read_bio(struct nvme_namespace *ns, struct bio *bp, 53248977Sjimharris nvme_cb_fn_t cb_fn, void *cb_arg) 54248977Sjimharris{ 55248977Sjimharris struct nvme_request *req; 56248977Sjimharris uint64_t lba; 57248977Sjimharris uint64_t lba_count; 58248977Sjimharris 59248977Sjimharris req = nvme_allocate_request_bio(bp, cb_fn, cb_arg); 60248977Sjimharris 61248977Sjimharris if (req == NULL) 62248977Sjimharris return (ENOMEM); 63248977Sjimharris 64248977Sjimharris lba = bp->bio_offset / nvme_ns_get_sector_size(ns); 65248977Sjimharris lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns); 66301778Simp nvme_ns_read_cmd(&req->cmd, ns->id, lba, lba_count); 67248977Sjimharris 68248977Sjimharris nvme_ctrlr_submit_io_request(ns->ctrlr, req); 69248977Sjimharris 70248977Sjimharris return (0); 71248977Sjimharris} 72248977Sjimharris 73248977Sjimharrisint 74240616Sjimharrisnvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, uint64_t lba, 75240616Sjimharris uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg) 76240616Sjimharris{ 77241659Sjimharris struct nvme_request *req; 78240616Sjimharris 79253474Sjimharris req = nvme_allocate_request_vaddr(payload, 80253474Sjimharris lba_count*nvme_ns_get_sector_size(ns), cb_fn, cb_arg); 81240616Sjimharris 82241660Sjimharris if (req == NULL) 83241657Sjimharris return (ENOMEM); 84241657Sjimharris 85301778Simp nvme_ns_write_cmd(&req->cmd, ns->id, lba, lba_count); 86240616Sjimharris 87241660Sjimharris nvme_ctrlr_submit_io_request(ns->ctrlr, req); 88240616Sjimharris 89241657Sjimharris return (0); 90240616Sjimharris} 91240616Sjimharris 92241657Sjimharrisint 93248977Sjimharrisnvme_ns_cmd_write_bio(struct nvme_namespace *ns, struct bio *bp, 94248977Sjimharris nvme_cb_fn_t cb_fn, void *cb_arg) 95248977Sjimharris{ 96248977Sjimharris struct nvme_request *req; 97248977Sjimharris uint64_t lba; 98248977Sjimharris uint64_t lba_count; 99248977Sjimharris 100248977Sjimharris req = nvme_allocate_request_bio(bp, cb_fn, cb_arg); 101248977Sjimharris 102248977Sjimharris if (req == NULL) 103248977Sjimharris return (ENOMEM); 104248977Sjimharris lba = bp->bio_offset / nvme_ns_get_sector_size(ns); 105248977Sjimharris lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns); 106301778Simp nvme_ns_write_cmd(&req->cmd, ns->id, lba, lba_count); 107248977Sjimharris 108248977Sjimharris nvme_ctrlr_submit_io_request(ns->ctrlr, req); 109248977Sjimharris 110248977Sjimharris return (0); 111248977Sjimharris} 112248977Sjimharris 113248977Sjimharrisint 114240616Sjimharrisnvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, 115240616Sjimharris uint8_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg) 116240616Sjimharris{ 117241659Sjimharris struct nvme_request *req; 118240616Sjimharris struct nvme_command *cmd; 119240616Sjimharris 120248913Sjimharris req = nvme_allocate_request_vaddr(payload, 121241659Sjimharris num_ranges * sizeof(struct nvme_dsm_range), cb_fn, cb_arg); 122240616Sjimharris 123241660Sjimharris if (req == NULL) 124241657Sjimharris return (ENOMEM); 125241657Sjimharris 126241659Sjimharris cmd = &req->cmd; 127240616Sjimharris cmd->opc = NVME_OPC_DATASET_MANAGEMENT; 128240616Sjimharris cmd->nsid = ns->id; 129240616Sjimharris 130240616Sjimharris /* TODO: create a delete command data structure */ 131248730Sjimharris cmd->cdw10 = num_ranges - 1; 132240616Sjimharris cmd->cdw11 = NVME_DSM_ATTR_DEALLOCATE; 133240616Sjimharris 134241660Sjimharris nvme_ctrlr_submit_io_request(ns->ctrlr, req); 135240616Sjimharris 136241657Sjimharris return (0); 137240616Sjimharris} 138240616Sjimharris 139241657Sjimharrisint 140240616Sjimharrisnvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn, void *cb_arg) 141240616Sjimharris{ 142241659Sjimharris struct nvme_request *req; 143240616Sjimharris 144248913Sjimharris req = nvme_allocate_request_null(cb_fn, cb_arg); 145240616Sjimharris 146241660Sjimharris if (req == NULL) 147241657Sjimharris return (ENOMEM); 148241657Sjimharris 149301778Simp nvme_ns_flush_cmd(&req->cmd, ns->id); 150241660Sjimharris nvme_ctrlr_submit_io_request(ns->ctrlr, req); 151241657Sjimharris 152241657Sjimharris return (0); 153240616Sjimharris} 154328663Smav 155328663Smav/* Timeout = 1 sec */ 156328664Smav#define NVD_DUMP_TIMEOUT 200000 157328663Smav 158328663Smavint 159328663Smavnvme_ns_dump(struct nvme_namespace *ns, void *virt, off_t offset, size_t len) 160328663Smav{ 161328663Smav struct nvme_completion_poll_status status; 162328663Smav struct nvme_request *req; 163328663Smav struct nvme_command *cmd; 164328663Smav uint64_t lba, lba_count; 165328663Smav int i; 166328663Smav 167328663Smav status.done = FALSE; 168328663Smav req = nvme_allocate_request_vaddr(virt, len, nvme_completion_poll_cb, 169328663Smav &status); 170328663Smav if (req == NULL) 171328663Smav return (ENOMEM); 172328663Smav 173328663Smav cmd = &req->cmd; 174328663Smav 175328664Smav if (len > 0) { 176328664Smav lba = offset / nvme_ns_get_sector_size(ns); 177328664Smav lba_count = len / nvme_ns_get_sector_size(ns); 178328664Smav nvme_ns_write_cmd(cmd, ns->id, lba, lba_count); 179328664Smav } else 180328664Smav nvme_ns_flush_cmd(cmd, ns->id); 181328663Smav 182328663Smav nvme_ctrlr_submit_io_request(ns->ctrlr, req); 183328663Smav if (req->qpair == NULL) 184328663Smav return (ENXIO); 185328663Smav 186328663Smav i = 0; 187328663Smav while ((i++ < NVD_DUMP_TIMEOUT) && (status.done == FALSE)) { 188328664Smav DELAY(5); 189328663Smav nvme_qpair_process_completions(req->qpair); 190328663Smav } 191328663Smav 192328663Smav if (status.done == FALSE) 193328663Smav return (ETIMEDOUT); 194328663Smav 195328663Smav return (0); 196328663Smav} 197