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 167 nvmft_port_ref(struct nvmft_port *np) 168 { 169 refcount_acquire(&np->refs); 170 } 171 172 static __inline void 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