1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2023-2024 Chelsio Communications, Inc.
5 * Written by: John Baldwin <jhb@FreeBSD.org>
6 */
7
8#ifndef __NVMFT_VAR_H__
9#define	__NVMFT_VAR_H__
10
11#include <sys/_callout.h>
12#include <sys/refcount.h>
13#include <sys/taskqueue.h>
14
15#include <dev/nvmf/nvmf_proto.h>
16
17#include <cam/ctl/ctl.h>
18#include <cam/ctl/ctl_io.h>
19#include <cam/ctl/ctl_frontend.h>
20
21struct nvmf_capsule;
22struct nvmft_controller;
23struct nvmft_qpair;
24
25#define	NVMFT_NUM_AER		16
26
27struct nvmft_port {
28	TAILQ_ENTRY(nvmft_port) link;
29	u_int	refs;
30	struct ctl_port port;
31	struct nvme_controller_data cdata;
32	struct nvme_firmware_page fp;
33	uint64_t cap;
34	uint32_t max_io_qsize;
35	bool	online;
36
37	struct sx lock;
38
39	struct unrhdr *ids;
40	TAILQ_HEAD(, nvmft_controller) controllers;
41
42	uint32_t *active_ns;
43	u_int	num_ns;
44};
45
46struct nvmft_io_qpair {
47	struct nvmft_qpair *qp;
48
49	bool shutdown;
50};
51
52struct nvmft_controller {
53	struct nvmft_qpair *admin;
54	struct nvmft_io_qpair *io_qpairs;
55	u_int	num_io_queues;
56	bool	shutdown;
57	bool	admin_closed;
58	uint16_t cntlid;
59	uint32_t cc;
60	uint32_t csts;
61
62	struct nvmft_port *np;
63	struct mtx lock;
64
65	struct nvme_controller_data cdata;
66	struct nvme_health_information_page hip;
67	sbintime_t create_time;
68	sbintime_t start_busy;
69	sbintime_t busy_total;
70	uint16_t partial_dur;
71	uint16_t partial_duw;
72
73	uint8_t	hostid[16];
74	uint8_t	hostnqn[NVME_NQN_FIELD_SIZE];
75	u_int	trtype;
76
77	TAILQ_ENTRY(nvmft_controller) link;
78
79	/*
80	 * Each queue can have at most UINT16_MAX commands, so the total
81	 * across all queues will fit in a uint32_t.
82	 */
83	uint32_t pending_commands;
84
85	volatile int ka_active_traffic;
86	struct callout ka_timer;
87	sbintime_t ka_sbt;
88
89	/* AER fields. */
90	uint32_t aer_mask;
91	uint16_t aer_cids[NVMFT_NUM_AER];
92	uint8_t aer_pending;
93	uint8_t aer_cidx;
94	uint8_t aer_pidx;
95
96	/* Changed namespace IDs. */
97	struct nvme_ns_list *changed_ns;
98	bool	changed_ns_reported;
99
100	struct task shutdown_task;
101	struct timeout_task terminate_task;
102};
103
104MALLOC_DECLARE(M_NVMFT);
105
106/* ctl_frontend_nvmf.c */
107void	nvmft_port_free(struct nvmft_port *np);
108void	nvmft_populate_active_nslist(struct nvmft_port *np, uint32_t nsid,
109    struct nvme_ns_list *nslist);
110void	nvmft_dispatch_command(struct nvmft_qpair *qp,
111    struct nvmf_capsule *nc, bool admin);
112void	nvmft_terminate_commands(struct nvmft_controller *ctrlr);
113
114/* nvmft_controller.c */
115void	nvmft_controller_error(struct nvmft_controller *ctrlr,
116    struct nvmft_qpair *qp, int error);
117void	nvmft_controller_lun_changed(struct nvmft_controller *ctrlr,
118    int lun_id);
119void	nvmft_handle_admin_command(struct nvmft_controller *ctrlr,
120    struct nvmf_capsule *nc);
121void	nvmft_handle_io_command(struct nvmft_qpair *qp, uint16_t qid,
122    struct nvmf_capsule *nc);
123int	nvmft_handoff_admin_queue(struct nvmft_port *np,
124    const struct nvmf_handoff_controller_qpair *handoff,
125    const struct nvmf_fabric_connect_cmd *cmd,
126    const struct nvmf_fabric_connect_data *data);
127int	nvmft_handoff_io_queue(struct nvmft_port *np,
128    const struct nvmf_handoff_controller_qpair *handoff,
129    const struct nvmf_fabric_connect_cmd *cmd,
130    const struct nvmf_fabric_connect_data *data);
131int	nvmft_printf(struct nvmft_controller *ctrlr, const char *fmt, ...)
132    __printflike(2, 3);
133
134/* nvmft_qpair.c */
135struct nvmft_qpair *nvmft_qpair_init(enum nvmf_trtype trtype,
136    const struct nvmf_handoff_qpair_params *handoff, uint16_t qid,
137    const char *name);
138void	nvmft_qpair_shutdown(struct nvmft_qpair *qp);
139void	nvmft_qpair_destroy(struct nvmft_qpair *qp);
140struct nvmft_controller *nvmft_qpair_ctrlr(struct nvmft_qpair *qp);
141uint16_t nvmft_qpair_id(struct nvmft_qpair *qp);
142const char *nvmft_qpair_name(struct nvmft_qpair *qp);
143void	nvmft_command_completed(struct nvmft_qpair *qp,
144    struct nvmf_capsule *nc);
145int	nvmft_send_response(struct nvmft_qpair *qp, const void *cqe);
146void	nvmft_init_cqe(void *cqe, struct nvmf_capsule *nc, uint16_t status);
147int	nvmft_send_error(struct nvmft_qpair *qp, struct nvmf_capsule *nc,
148    uint8_t sc_type, uint8_t sc_status);
149int	nvmft_send_generic_error(struct nvmft_qpair *qp,
150    struct nvmf_capsule *nc, uint8_t sc_status);
151int	nvmft_send_success(struct nvmft_qpair *qp,
152    struct nvmf_capsule *nc);
153void	nvmft_connect_error(struct nvmft_qpair *qp,
154    const struct nvmf_fabric_connect_cmd *cmd, uint8_t sc_type,
155    uint8_t sc_status);
156void	nvmft_connect_invalid_parameters(struct nvmft_qpair *qp,
157    const struct nvmf_fabric_connect_cmd *cmd, bool data, uint16_t offset);
158int	nvmft_finish_accept(struct nvmft_qpair *qp,
159    const struct nvmf_fabric_connect_cmd *cmd, struct nvmft_controller *ctrlr);
160
161static __inline void
162nvmft_port_ref(struct nvmft_port *np)
163{
164	refcount_acquire(&np->refs);
165}
166
167static __inline void
168nvmft_port_rele(struct nvmft_port *np)
169{
170	if (refcount_release(&np->refs))
171		nvmft_port_free(np);
172}
173
174#endif	/* !__NVMFT_VAR_H__ */
175