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