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
21 struct nvmf_capsule;
22 struct nvmft_controller;
23 struct nvmft_qpair;
24
25 #define NVMFT_NUM_AER 16
26
27 struct 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
46 struct nvmft_io_qpair {
47 struct nvmft_qpair *qp;
48
49 bool shutdown;
50 };
51
52 struct 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
104 MALLOC_DECLARE(M_NVMFT);
105
106 /* ctl_frontend_nvmf.c */
107 void nvmft_port_free(struct nvmft_port *np);
108 void nvmft_populate_active_nslist(struct nvmft_port *np, uint32_t nsid,
109 struct nvme_ns_list *nslist);
110 void nvmft_dispatch_command(struct nvmft_qpair *qp,
111 struct nvmf_capsule *nc, bool admin);
112 void nvmft_terminate_commands(struct nvmft_controller *ctrlr);
113 void nvmft_abort_datamove(union ctl_io *io);
114 void nvmft_handle_datamove(union ctl_io *io);
115 void nvmft_drain_task(struct task *task);
116 void nvmft_enqueue_task(struct task *task);
117
118 /* nvmft_controller.c */
119 void nvmft_controller_error(struct nvmft_controller *ctrlr,
120 struct nvmft_qpair *qp, int error);
121 void nvmft_controller_lun_changed(struct nvmft_controller *ctrlr,
122 int lun_id);
123 void nvmft_handle_admin_command(struct nvmft_controller *ctrlr,
124 struct nvmf_capsule *nc);
125 void nvmft_handle_io_command(struct nvmft_qpair *qp, uint16_t qid,
126 struct nvmf_capsule *nc);
127 int nvmft_handoff_admin_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);
131 int nvmft_handoff_io_queue(struct nvmft_port *np,
132 const struct nvmf_handoff_controller_qpair *handoff,
133 const struct nvmf_fabric_connect_cmd *cmd,
134 const struct nvmf_fabric_connect_data *data);
135 int nvmft_printf(struct nvmft_controller *ctrlr, const char *fmt, ...)
136 __printflike(2, 3);
137
138 /* nvmft_qpair.c */
139 struct nvmft_qpair *nvmft_qpair_init(enum nvmf_trtype trtype,
140 const struct nvmf_handoff_qpair_params *handoff, uint16_t qid,
141 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