1240616Sjimharris/*-
2265565Sjimharris * Copyright (C) 2012-2014 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 * $FreeBSD$
27240616Sjimharris */
28240616Sjimharris
29240616Sjimharris#ifndef __NVME_PRIVATE_H__
30240616Sjimharris#define __NVME_PRIVATE_H__
31240616Sjimharris
32240616Sjimharris#include <sys/param.h>
33252222Sjimharris#include <sys/bio.h>
34252222Sjimharris#include <sys/bus.h>
35240616Sjimharris#include <sys/kernel.h>
36240616Sjimharris#include <sys/lock.h>
37240616Sjimharris#include <sys/malloc.h>
38240616Sjimharris#include <sys/mutex.h>
39240616Sjimharris#include <sys/rman.h>
40240616Sjimharris#include <sys/systm.h>
41240616Sjimharris#include <sys/taskqueue.h>
42240616Sjimharris
43252222Sjimharris#include <vm/uma.h>
44252222Sjimharris
45240616Sjimharris#include <machine/bus.h>
46240616Sjimharris
47240616Sjimharris#include "nvme.h"
48240616Sjimharris
49240616Sjimharris#define DEVICE2SOFTC(dev) ((struct nvme_controller *) device_get_softc(dev))
50240616Sjimharris
51240616SjimharrisMALLOC_DECLARE(M_NVME);
52240616Sjimharris
53240616Sjimharris#define CHATHAM2
54240616Sjimharris
55240616Sjimharris#ifdef CHATHAM2
56240616Sjimharris#define CHATHAM_PCI_ID		0x20118086
57240616Sjimharris#define CHATHAM_CONTROL_BAR	0
58240616Sjimharris#endif
59240616Sjimharris
60252222Sjimharris#define IDT32_PCI_ID		0x80d0111d /* 32 channel board */
61252222Sjimharris#define IDT8_PCI_ID		0x80d2111d /* 8 channel board */
62240616Sjimharris
63240616Sjimharris/*
64240616Sjimharris * For commands requiring more than 2 PRP entries, one PRP will be
65240616Sjimharris *  embedded in the command (prp1), and the rest of the PRP entries
66240616Sjimharris *  will be in a list pointed to by the command (prp2).  This means
67252222Sjimharris *  that real max number of PRP entries we support is 32+1, which
68252222Sjimharris *  results in a max xfer size of 32*PAGE_SIZE.
69240616Sjimharris */
70252664Sjimharris#define NVME_MAX_PRP_LIST_ENTRIES	(NVME_MAX_XFER_SIZE / PAGE_SIZE)
71240616Sjimharris
72252222Sjimharris#define NVME_ADMIN_TRACKERS	(16)
73240616Sjimharris#define NVME_ADMIN_ENTRIES	(128)
74240616Sjimharris/* min and max are defined in admin queue attributes section of spec */
75240616Sjimharris#define NVME_MIN_ADMIN_ENTRIES	(2)
76240616Sjimharris#define NVME_MAX_ADMIN_ENTRIES	(4096)
77240616Sjimharris
78240616Sjimharris/*
79252222Sjimharris * NVME_IO_ENTRIES defines the size of an I/O qpair's submission and completion
80252222Sjimharris *  queues, while NVME_IO_TRACKERS defines the maximum number of I/O that we
81252222Sjimharris *  will allow outstanding on an I/O qpair at any time.  The only advantage in
82252222Sjimharris *  having IO_ENTRIES > IO_TRACKERS is for debugging purposes - when dumping
83252222Sjimharris *  the contents of the submission and completion queues, it will show a longer
84252222Sjimharris *  history of data.
85252222Sjimharris */
86252222Sjimharris#define NVME_IO_ENTRIES		(256)
87252222Sjimharris#define NVME_IO_TRACKERS	(128)
88252222Sjimharris#define NVME_MIN_IO_TRACKERS	(4)
89252222Sjimharris#define NVME_MAX_IO_TRACKERS	(1024)
90252222Sjimharris
91252222Sjimharris/*
92240616Sjimharris * NVME_MAX_IO_ENTRIES is not defined, since it is specified in CC.MQES
93240616Sjimharris *  for each controller.
94240616Sjimharris */
95240616Sjimharris
96240616Sjimharris#define NVME_INT_COAL_TIME	(0)	/* disabled */
97240616Sjimharris#define NVME_INT_COAL_THRESHOLD (0)	/* 0-based */
98240616Sjimharris
99240616Sjimharris#define NVME_MAX_NAMESPACES	(16)
100240616Sjimharris#define NVME_MAX_CONSUMERS	(2)
101252222Sjimharris#define NVME_MAX_ASYNC_EVENTS	(8)
102240616Sjimharris
103252222Sjimharris#define NVME_DEFAULT_TIMEOUT_PERIOD	(30)    /* in seconds */
104252222Sjimharris#define NVME_MIN_TIMEOUT_PERIOD		(5)
105252222Sjimharris#define NVME_MAX_TIMEOUT_PERIOD		(120)
106240616Sjimharris
107252222Sjimharris#define NVME_DEFAULT_RETRY_COUNT	(4)
108252222Sjimharris
109252222Sjimharris/* Maximum log page size to fetch for AERs. */
110252222Sjimharris#define NVME_MAX_AER_LOG_SIZE		(4096)
111252222Sjimharris
112253297Sjimharris/*
113253297Sjimharris * Define CACHE_LINE_SIZE here for older FreeBSD versions that do not define
114253297Sjimharris *  it.
115253297Sjimharris */
116252222Sjimharris#ifndef CACHE_LINE_SIZE
117252222Sjimharris#define CACHE_LINE_SIZE		(64)
118252222Sjimharris#endif
119252222Sjimharris
120252222Sjimharris/*
121252222Sjimharris * Use presence of the BIO_UNMAPPED flag to determine whether unmapped I/O
122252222Sjimharris *  support and the bus_dmamap_load_bio API are available on the target
123252222Sjimharris *  kernel.  This will ease porting back to earlier stable branches at a
124252222Sjimharris *  later point.
125252222Sjimharris */
126252222Sjimharris#ifdef BIO_UNMAPPED
127252222Sjimharris#define NVME_UNMAPPED_BIO_SUPPORT
128252222Sjimharris#endif
129252222Sjimharris
130252222Sjimharrisextern uma_zone_t	nvme_request_zone;
131252222Sjimharrisextern int32_t		nvme_retry_count;
132252222Sjimharris
133252222Sjimharrisstruct nvme_completion_poll_status {
134252222Sjimharris
135252222Sjimharris	struct nvme_completion	cpl;
136252222Sjimharris	boolean_t		done;
137240616Sjimharris};
138240616Sjimharris
139252222Sjimharris#define NVME_REQUEST_VADDR	1
140252222Sjimharris#define NVME_REQUEST_NULL	2 /* For requests with no payload. */
141252222Sjimharris#define NVME_REQUEST_UIO	3
142252222Sjimharris#ifdef NVME_UNMAPPED_BIO_SUPPORT
143252222Sjimharris#define NVME_REQUEST_BIO	4
144252222Sjimharris#endif
145252222Sjimharris
146252222Sjimharrisstruct nvme_request {
147252222Sjimharris
148252222Sjimharris	struct nvme_command		cmd;
149252222Sjimharris	struct nvme_qpair		*qpair;
150252222Sjimharris	union {
151252222Sjimharris		void			*payload;
152252222Sjimharris		struct bio		*bio;
153252222Sjimharris	} u;
154252222Sjimharris	uint32_t			type;
155252222Sjimharris	uint32_t			payload_size;
156252222Sjimharris	boolean_t			timeout;
157252222Sjimharris	nvme_cb_fn_t			cb_fn;
158252222Sjimharris	void				*cb_arg;
159252222Sjimharris	int32_t				retries;
160252222Sjimharris	STAILQ_ENTRY(nvme_request)	stailq;
161252222Sjimharris};
162252222Sjimharris
163252222Sjimharrisstruct nvme_async_event_request {
164252222Sjimharris
165252222Sjimharris	struct nvme_controller		*ctrlr;
166252222Sjimharris	struct nvme_request		*req;
167252222Sjimharris	struct nvme_completion		cpl;
168252222Sjimharris	uint32_t			log_page_id;
169252222Sjimharris	uint32_t			log_page_size;
170252222Sjimharris	uint8_t				log_page_buffer[NVME_MAX_AER_LOG_SIZE];
171252222Sjimharris};
172252222Sjimharris
173240616Sjimharrisstruct nvme_tracker {
174240616Sjimharris
175252222Sjimharris	TAILQ_ENTRY(nvme_tracker)	tailq;
176252222Sjimharris	struct nvme_request		*req;
177240616Sjimharris	struct nvme_qpair		*qpair;
178240616Sjimharris	struct callout			timer;
179252222Sjimharris	bus_dmamap_t			payload_dma_map;
180240616Sjimharris	uint16_t			cid;
181252222Sjimharris
182252222Sjimharris	uint64_t			prp[NVME_MAX_PRP_LIST_ENTRIES];
183252222Sjimharris	bus_addr_t			prp_bus_addr;
184252222Sjimharris	bus_dmamap_t			prp_dma_map;
185240616Sjimharris};
186240616Sjimharris
187240616Sjimharrisstruct nvme_qpair {
188240616Sjimharris
189240616Sjimharris	struct nvme_controller	*ctrlr;
190240616Sjimharris	uint32_t		id;
191240616Sjimharris	uint32_t		phase;
192240616Sjimharris
193240616Sjimharris	uint16_t		vector;
194240616Sjimharris	int			rid;
195240616Sjimharris	struct resource		*res;
196240616Sjimharris	void 			*tag;
197240616Sjimharris
198240616Sjimharris	uint32_t		num_entries;
199252222Sjimharris	uint32_t		num_trackers;
200240616Sjimharris	uint32_t		sq_tdbl_off;
201240616Sjimharris	uint32_t		cq_hdbl_off;
202240616Sjimharris
203240616Sjimharris	uint32_t		sq_head;
204240616Sjimharris	uint32_t		sq_tail;
205240616Sjimharris	uint32_t		cq_head;
206240616Sjimharris
207240616Sjimharris	int64_t			num_cmds;
208252222Sjimharris	int64_t			num_intr_handler_calls;
209240616Sjimharris
210240616Sjimharris	struct nvme_command	*cmd;
211240616Sjimharris	struct nvme_completion	*cpl;
212240616Sjimharris
213240616Sjimharris	bus_dma_tag_t		dma_tag;
214240616Sjimharris
215240616Sjimharris	bus_dmamap_t		cmd_dma_map;
216240616Sjimharris	uint64_t		cmd_bus_addr;
217240616Sjimharris
218240616Sjimharris	bus_dmamap_t		cpl_dma_map;
219240616Sjimharris	uint64_t		cpl_bus_addr;
220240616Sjimharris
221252222Sjimharris	TAILQ_HEAD(, nvme_tracker)	free_tr;
222252222Sjimharris	TAILQ_HEAD(, nvme_tracker)	outstanding_tr;
223252222Sjimharris	STAILQ_HEAD(, nvme_request)	queued_req;
224240616Sjimharris
225240616Sjimharris	struct nvme_tracker	**act_tr;
226240616Sjimharris
227252222Sjimharris	boolean_t		is_enabled;
228240616Sjimharris
229252222Sjimharris	struct mtx		lock __aligned(CACHE_LINE_SIZE);
230252222Sjimharris
231252222Sjimharris} __aligned(CACHE_LINE_SIZE);
232252222Sjimharris
233240616Sjimharrisstruct nvme_namespace {
234240616Sjimharris
235240616Sjimharris	struct nvme_controller		*ctrlr;
236240616Sjimharris	struct nvme_namespace_data	data;
237240616Sjimharris	uint16_t			id;
238240616Sjimharris	uint16_t			flags;
239240616Sjimharris	struct cdev			*cdev;
240252222Sjimharris	void				*cons_cookie[NVME_MAX_CONSUMERS];
241257587Sjimharris	uint32_t			stripesize;
242252222Sjimharris	struct mtx			lock;
243240616Sjimharris};
244240616Sjimharris
245240616Sjimharris/*
246240616Sjimharris * One of these per allocated PCI device.
247240616Sjimharris */
248240616Sjimharrisstruct nvme_controller {
249240616Sjimharris
250240616Sjimharris	device_t		dev;
251240616Sjimharris
252252222Sjimharris	struct mtx		lock;
253252222Sjimharris
254240616Sjimharris	uint32_t		ready_timeout_in_ms;
255240616Sjimharris
256240616Sjimharris	bus_space_tag_t		bus_tag;
257240616Sjimharris	bus_space_handle_t	bus_handle;
258240616Sjimharris	int			resource_id;
259240616Sjimharris	struct resource		*resource;
260240616Sjimharris
261252222Sjimharris	/*
262252222Sjimharris	 * The NVMe spec allows for the MSI-X table to be placed in BAR 4/5,
263252222Sjimharris	 *  separate from the control registers which are in BAR 0/1.  These
264252222Sjimharris	 *  members track the mapping of BAR 4/5 for that reason.
265252222Sjimharris	 */
266252222Sjimharris	int			bar4_resource_id;
267252222Sjimharris	struct resource		*bar4_resource;
268252222Sjimharris
269240616Sjimharris#ifdef CHATHAM2
270240616Sjimharris	bus_space_tag_t		chatham_bus_tag;
271240616Sjimharris	bus_space_handle_t	chatham_bus_handle;
272240616Sjimharris	int			chatham_resource_id;
273240616Sjimharris	struct resource		*chatham_resource;
274240616Sjimharris#endif
275240616Sjimharris
276240616Sjimharris	uint32_t		msix_enabled;
277240616Sjimharris	uint32_t		force_intx;
278252222Sjimharris	uint32_t		enable_aborts;
279240616Sjimharris
280240616Sjimharris	uint32_t		num_io_queues;
281240616Sjimharris	boolean_t		per_cpu_io_queues;
282240616Sjimharris
283240616Sjimharris	/* Fields for tracking progress during controller initialization. */
284240616Sjimharris	struct intr_config_hook	config_hook;
285240616Sjimharris	uint32_t		ns_identified;
286240616Sjimharris	uint32_t		queues_created;
287240616Sjimharris
288252222Sjimharris	struct task		reset_task;
289252222Sjimharris	struct task		fail_req_task;
290252222Sjimharris	struct taskqueue	*taskqueue;
291252222Sjimharris
292265566Sjimharris	struct resource		*msi_res[MAXCPU + 1];
293265566Sjimharris
294240616Sjimharris	/* For shared legacy interrupt. */
295240616Sjimharris	int			rid;
296240616Sjimharris	struct resource		*res;
297240616Sjimharris	void			*tag;
298240616Sjimharris
299240616Sjimharris	bus_dma_tag_t		hw_desc_tag;
300240616Sjimharris	bus_dmamap_t		hw_desc_map;
301240616Sjimharris
302240616Sjimharris	/** maximum i/o size in bytes */
303240616Sjimharris	uint32_t		max_xfer_size;
304240616Sjimharris
305252222Sjimharris	/** minimum page size supported by this controller in bytes */
306252222Sjimharris	uint32_t		min_page_size;
307252222Sjimharris
308240616Sjimharris	/** interrupt coalescing time period (in microseconds) */
309240616Sjimharris	uint32_t		int_coal_time;
310240616Sjimharris
311240616Sjimharris	/** interrupt coalescing threshold */
312240616Sjimharris	uint32_t		int_coal_threshold;
313240616Sjimharris
314252222Sjimharris	/** timeout period in seconds */
315252222Sjimharris	uint32_t		timeout_period;
316252222Sjimharris
317240616Sjimharris	struct nvme_qpair	adminq;
318240616Sjimharris	struct nvme_qpair	*ioq;
319240616Sjimharris
320240616Sjimharris	struct nvme_registers		*regs;
321240616Sjimharris
322240616Sjimharris	struct nvme_controller_data	cdata;
323240616Sjimharris	struct nvme_namespace		ns[NVME_MAX_NAMESPACES];
324240616Sjimharris
325240616Sjimharris	struct cdev			*cdev;
326240616Sjimharris
327257590Sjimharris	/** bit mask of warning types currently enabled for async events */
328257590Sjimharris	union nvme_critical_warning_state	async_event_config;
329257590Sjimharris
330252222Sjimharris	uint32_t			num_aers;
331252222Sjimharris	struct nvme_async_event_request	aer[NVME_MAX_ASYNC_EVENTS];
332240616Sjimharris
333252222Sjimharris	void				*cons_cookie[NVME_MAX_CONSUMERS];
334252222Sjimharris
335265565Sjimharris	uint32_t			is_resetting;
336265565Sjimharris	uint32_t			is_initialized;
337265565Sjimharris	uint32_t			notification_sent;
338252222Sjimharris
339252222Sjimharris	boolean_t			is_failed;
340252222Sjimharris	STAILQ_HEAD(, nvme_request)	fail_req;
341252222Sjimharris
342240616Sjimharris#ifdef CHATHAM2
343240616Sjimharris	uint64_t		chatham_size;
344240616Sjimharris	uint64_t		chatham_lbas;
345240616Sjimharris#endif
346240616Sjimharris};
347240616Sjimharris
348240616Sjimharris#define nvme_mmio_offsetof(reg)						       \
349240616Sjimharris	offsetof(struct nvme_registers, reg)
350240616Sjimharris
351240616Sjimharris#define nvme_mmio_read_4(sc, reg)					       \
352240616Sjimharris	bus_space_read_4((sc)->bus_tag, (sc)->bus_handle,		       \
353240616Sjimharris	    nvme_mmio_offsetof(reg))
354240616Sjimharris
355240616Sjimharris#define nvme_mmio_write_4(sc, reg, val)					       \
356240616Sjimharris	bus_space_write_4((sc)->bus_tag, (sc)->bus_handle,		       \
357240616Sjimharris	    nvme_mmio_offsetof(reg), val)
358240616Sjimharris
359240616Sjimharris#define nvme_mmio_write_8(sc, reg, val) \
360240616Sjimharris	do {								       \
361240616Sjimharris		bus_space_write_4((sc)->bus_tag, (sc)->bus_handle,	       \
362240616Sjimharris		    nvme_mmio_offsetof(reg), val & 0xFFFFFFFF); 	       \
363240616Sjimharris		bus_space_write_4((sc)->bus_tag, (sc)->bus_handle,	       \
364240616Sjimharris		    nvme_mmio_offsetof(reg)+4,				       \
365240616Sjimharris		    (val & 0xFFFFFFFF00000000UL) >> 32);		       \
366240616Sjimharris	} while (0);
367240616Sjimharris
368240616Sjimharris#ifdef CHATHAM2
369240616Sjimharris#define chatham_read_4(softc, reg) \
370240616Sjimharris	bus_space_read_4((softc)->chatham_bus_tag,			       \
371240616Sjimharris	    (softc)->chatham_bus_handle, reg)
372240616Sjimharris
373240616Sjimharris#define chatham_write_8(sc, reg, val)					       \
374240616Sjimharris	do {								       \
375240616Sjimharris		bus_space_write_4((sc)->chatham_bus_tag,		       \
376240616Sjimharris		    (sc)->chatham_bus_handle, reg, val & 0xffffffff);	       \
377240616Sjimharris		bus_space_write_4((sc)->chatham_bus_tag,		       \
378240616Sjimharris		    (sc)->chatham_bus_handle, reg+4,			       \
379240616Sjimharris		    (val & 0xFFFFFFFF00000000UL) >> 32);		       \
380240616Sjimharris	} while (0);
381240616Sjimharris
382240616Sjimharris#endif /* CHATHAM2 */
383240616Sjimharris
384240616Sjimharris#if __FreeBSD_version < 800054
385240616Sjimharris#define wmb()	__asm volatile("sfence" ::: "memory")
386240616Sjimharris#define mb()	__asm volatile("mfence" ::: "memory")
387240616Sjimharris#endif
388240616Sjimharris
389252222Sjimharris#define nvme_printf(ctrlr, fmt, args...)	\
390252222Sjimharris    device_printf(ctrlr->dev, fmt, ##args)
391252222Sjimharris
392240616Sjimharrisvoid	nvme_ns_test(struct nvme_namespace *ns, u_long cmd, caddr_t arg);
393240616Sjimharris
394240616Sjimharrisvoid	nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr,
395240616Sjimharris					   void *payload,
396240616Sjimharris					   nvme_cb_fn_t cb_fn, void *cb_arg);
397240616Sjimharrisvoid	nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr,
398240616Sjimharris					  uint16_t nsid, void *payload,
399240616Sjimharris					  nvme_cb_fn_t cb_fn, void *cb_arg);
400240616Sjimharrisvoid	nvme_ctrlr_cmd_set_interrupt_coalescing(struct nvme_controller *ctrlr,
401240616Sjimharris						uint32_t microseconds,
402240616Sjimharris						uint32_t threshold,
403240616Sjimharris						nvme_cb_fn_t cb_fn,
404240616Sjimharris						void *cb_arg);
405252222Sjimharrisvoid	nvme_ctrlr_cmd_get_error_page(struct nvme_controller *ctrlr,
406252222Sjimharris				      struct nvme_error_information_entry *payload,
407252222Sjimharris				      uint32_t num_entries, /* 0 = max */
408252222Sjimharris				      nvme_cb_fn_t cb_fn,
409252222Sjimharris				      void *cb_arg);
410240616Sjimharrisvoid	nvme_ctrlr_cmd_get_health_information_page(struct nvme_controller *ctrlr,
411240616Sjimharris						   uint32_t nsid,
412240616Sjimharris						   struct nvme_health_information_page *payload,
413240616Sjimharris						   nvme_cb_fn_t cb_fn,
414240616Sjimharris						   void *cb_arg);
415252222Sjimharrisvoid	nvme_ctrlr_cmd_get_firmware_page(struct nvme_controller *ctrlr,
416252222Sjimharris					 struct nvme_firmware_page *payload,
417252222Sjimharris					 nvme_cb_fn_t cb_fn,
418252222Sjimharris					 void *cb_arg);
419240616Sjimharrisvoid	nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
420240616Sjimharris				    struct nvme_qpair *io_que, uint16_t vector,
421240616Sjimharris				    nvme_cb_fn_t cb_fn, void *cb_arg);
422240616Sjimharrisvoid	nvme_ctrlr_cmd_create_io_sq(struct nvme_controller *ctrlr,
423240616Sjimharris				    struct nvme_qpair *io_que,
424240616Sjimharris				    nvme_cb_fn_t cb_fn, void *cb_arg);
425240616Sjimharrisvoid	nvme_ctrlr_cmd_delete_io_cq(struct nvme_controller *ctrlr,
426240616Sjimharris				    struct nvme_qpair *io_que,
427240616Sjimharris				    nvme_cb_fn_t cb_fn, void *cb_arg);
428240616Sjimharrisvoid	nvme_ctrlr_cmd_delete_io_sq(struct nvme_controller *ctrlr,
429240616Sjimharris				    struct nvme_qpair *io_que,
430240616Sjimharris				    nvme_cb_fn_t cb_fn, void *cb_arg);
431240616Sjimharrisvoid	nvme_ctrlr_cmd_set_num_queues(struct nvme_controller *ctrlr,
432240616Sjimharris				      uint32_t num_queues, nvme_cb_fn_t cb_fn,
433240616Sjimharris				      void *cb_arg);
434252222Sjimharrisvoid	nvme_ctrlr_cmd_set_async_event_config(struct nvme_controller *ctrlr,
435252222Sjimharris					      union nvme_critical_warning_state state,
436252222Sjimharris					      nvme_cb_fn_t cb_fn, void *cb_arg);
437252222Sjimharrisvoid	nvme_ctrlr_cmd_abort(struct nvme_controller *ctrlr, uint16_t cid,
438252222Sjimharris			     uint16_t sqid, nvme_cb_fn_t cb_fn, void *cb_arg);
439240616Sjimharris
440252222Sjimharrisvoid	nvme_completion_poll_cb(void *arg, const struct nvme_completion *cpl);
441240616Sjimharris
442240616Sjimharrisint	nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev);
443252222Sjimharrisvoid	nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev);
444263273Sjimharrisvoid	nvme_ctrlr_shutdown(struct nvme_controller *ctrlr);
445252222Sjimharrisint	nvme_ctrlr_hw_reset(struct nvme_controller *ctrlr);
446252222Sjimharrisvoid	nvme_ctrlr_reset(struct nvme_controller *ctrlr);
447240616Sjimharris/* ctrlr defined as void * to allow use with config_intrhook. */
448252222Sjimharrisvoid	nvme_ctrlr_start_config_hook(void *ctrlr_arg);
449252222Sjimharrisvoid	nvme_ctrlr_submit_admin_request(struct nvme_controller *ctrlr,
450252222Sjimharris					struct nvme_request *req);
451252222Sjimharrisvoid	nvme_ctrlr_submit_io_request(struct nvme_controller *ctrlr,
452252222Sjimharris				     struct nvme_request *req);
453252222Sjimharrisvoid	nvme_ctrlr_post_failed_request(struct nvme_controller *ctrlr,
454252222Sjimharris				       struct nvme_request *req);
455240616Sjimharris
456240616Sjimharrisvoid	nvme_qpair_construct(struct nvme_qpair *qpair, uint32_t id,
457240616Sjimharris			     uint16_t vector, uint32_t num_entries,
458252664Sjimharris			     uint32_t num_trackers,
459240616Sjimharris			     struct nvme_controller *ctrlr);
460252222Sjimharrisvoid	nvme_qpair_submit_tracker(struct nvme_qpair *qpair,
461252222Sjimharris				  struct nvme_tracker *tr);
462240616Sjimharrisvoid	nvme_qpair_process_completions(struct nvme_qpair *qpair);
463252222Sjimharrisvoid	nvme_qpair_submit_request(struct nvme_qpair *qpair,
464252222Sjimharris				  struct nvme_request *req);
465252222Sjimharrisvoid	nvme_qpair_reset(struct nvme_qpair *qpair);
466252222Sjimharrisvoid	nvme_qpair_fail(struct nvme_qpair *qpair);
467252222Sjimharrisvoid	nvme_qpair_manual_complete_request(struct nvme_qpair *qpair,
468252222Sjimharris					   struct nvme_request *req,
469252222Sjimharris					   uint32_t sct, uint32_t sc,
470252222Sjimharris					   boolean_t print_on_error);
471240616Sjimharris
472252222Sjimharrisvoid	nvme_admin_qpair_enable(struct nvme_qpair *qpair);
473252222Sjimharrisvoid	nvme_admin_qpair_disable(struct nvme_qpair *qpair);
474240616Sjimharrisvoid	nvme_admin_qpair_destroy(struct nvme_qpair *qpair);
475240616Sjimharris
476252222Sjimharrisvoid	nvme_io_qpair_enable(struct nvme_qpair *qpair);
477252222Sjimharrisvoid	nvme_io_qpair_disable(struct nvme_qpair *qpair);
478240616Sjimharrisvoid	nvme_io_qpair_destroy(struct nvme_qpair *qpair);
479240616Sjimharris
480240616Sjimharrisint	nvme_ns_construct(struct nvme_namespace *ns, uint16_t id,
481240616Sjimharris			  struct nvme_controller *ctrlr);
482252222Sjimharrisvoid	nvme_ns_destruct(struct nvme_namespace *ns);
483240616Sjimharris
484240616Sjimharrisvoid	nvme_sysctl_initialize_ctrlr(struct nvme_controller *ctrlr);
485240616Sjimharris
486240616Sjimharrisvoid	nvme_dump_command(struct nvme_command *cmd);
487240616Sjimharrisvoid	nvme_dump_completion(struct nvme_completion *cpl);
488240616Sjimharris
489240616Sjimharrisstatic __inline void
490240616Sjimharrisnvme_single_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
491240616Sjimharris{
492240616Sjimharris	uint64_t *bus_addr = (uint64_t *)arg;
493240616Sjimharris
494240616Sjimharris	*bus_addr = seg[0].ds_addr;
495240616Sjimharris}
496240616Sjimharris
497252222Sjimharrisstatic __inline struct nvme_request *
498252222Sjimharris_nvme_allocate_request(nvme_cb_fn_t cb_fn, void *cb_arg)
499252222Sjimharris{
500252222Sjimharris	struct nvme_request *req;
501252222Sjimharris
502252222Sjimharris	req = uma_zalloc(nvme_request_zone, M_NOWAIT | M_ZERO);
503252222Sjimharris	if (req != NULL) {
504252222Sjimharris		req->cb_fn = cb_fn;
505252222Sjimharris		req->cb_arg = cb_arg;
506252222Sjimharris		req->timeout = TRUE;
507252222Sjimharris	}
508252222Sjimharris	return (req);
509252222Sjimharris}
510252222Sjimharris
511252222Sjimharrisstatic __inline struct nvme_request *
512252222Sjimharrisnvme_allocate_request_vaddr(void *payload, uint32_t payload_size,
513252222Sjimharris    nvme_cb_fn_t cb_fn, void *cb_arg)
514252222Sjimharris{
515252222Sjimharris	struct nvme_request *req;
516252222Sjimharris
517252222Sjimharris	req = _nvme_allocate_request(cb_fn, cb_arg);
518252222Sjimharris	if (req != NULL) {
519252222Sjimharris		req->type = NVME_REQUEST_VADDR;
520252222Sjimharris		req->u.payload = payload;
521252222Sjimharris		req->payload_size = payload_size;
522252222Sjimharris	}
523252222Sjimharris	return (req);
524252222Sjimharris}
525252222Sjimharris
526252222Sjimharrisstatic __inline struct nvme_request *
527252222Sjimharrisnvme_allocate_request_null(nvme_cb_fn_t cb_fn, void *cb_arg)
528252222Sjimharris{
529252222Sjimharris	struct nvme_request *req;
530252222Sjimharris
531252222Sjimharris	req = _nvme_allocate_request(cb_fn, cb_arg);
532252222Sjimharris	if (req != NULL)
533252222Sjimharris		req->type = NVME_REQUEST_NULL;
534252222Sjimharris	return (req);
535252222Sjimharris}
536252222Sjimharris
537252222Sjimharrisstatic __inline struct nvme_request *
538252222Sjimharrisnvme_allocate_request_bio(struct bio *bio, nvme_cb_fn_t cb_fn, void *cb_arg)
539252222Sjimharris{
540252222Sjimharris	struct nvme_request *req;
541252222Sjimharris
542252222Sjimharris	req = _nvme_allocate_request(cb_fn, cb_arg);
543252222Sjimharris	if (req != NULL) {
544252222Sjimharris#ifdef NVME_UNMAPPED_BIO_SUPPORT
545252222Sjimharris		req->type = NVME_REQUEST_BIO;
546252222Sjimharris		req->u.bio = bio;
547252222Sjimharris#else
548252222Sjimharris		req->type = NVME_REQUEST_VADDR;
549252222Sjimharris		req->u.payload = bio->bio_data;
550252222Sjimharris		req->payload_size = bio->bio_bcount;
551252222Sjimharris#endif
552252222Sjimharris	}
553252222Sjimharris	return (req);
554252222Sjimharris}
555252222Sjimharris
556252222Sjimharris#define nvme_free_request(req)	uma_zfree(nvme_request_zone, req)
557252222Sjimharris
558252222Sjimharrisvoid	nvme_notify_async_consumers(struct nvme_controller *ctrlr,
559252222Sjimharris				    const struct nvme_completion *async_cpl,
560252222Sjimharris				    uint32_t log_page_id, void *log_page_buffer,
561252222Sjimharris				    uint32_t log_page_size);
562252222Sjimharrisvoid	nvme_notify_fail_consumers(struct nvme_controller *ctrlr);
563265565Sjimharrisvoid	nvme_notify_new_controller(struct nvme_controller *ctrlr);
564252222Sjimharris
565240616Sjimharris#endif /* __NVME_PRIVATE_H__ */
566