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