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