1a1eda741SJohn Baldwin /*- 2a1eda741SJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause 3a1eda741SJohn Baldwin * 4a1eda741SJohn Baldwin * Copyright (c) 2023-2024 Chelsio Communications, Inc. 5a1eda741SJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 6a1eda741SJohn Baldwin */ 7a1eda741SJohn Baldwin 8a1eda741SJohn Baldwin #ifndef __NVMF_VAR_H__ 9a1eda741SJohn Baldwin #define __NVMF_VAR_H__ 10a1eda741SJohn Baldwin 11a1eda741SJohn Baldwin #include <sys/_callout.h> 12f46d4971SJohn Baldwin #include <sys/_eventhandler.h> 13a1eda741SJohn Baldwin #include <sys/_lock.h> 14a1eda741SJohn Baldwin #include <sys/_mutex.h> 15365b89e8SJohn Baldwin //#include <sys/_nv.h> 16a1eda741SJohn Baldwin #include <sys/_sx.h> 17a1eda741SJohn Baldwin #include <sys/_task.h> 183ff90d91SJohn Baldwin #include <sys/smp.h> 19a1eda741SJohn Baldwin #include <sys/queue.h> 20a1eda741SJohn Baldwin #include <dev/nvme/nvme.h> 21a1eda741SJohn Baldwin #include <dev/nvmf/nvmf_transport.h> 22a1eda741SJohn Baldwin 23a1eda741SJohn Baldwin struct nvmf_aer; 24a1eda741SJohn Baldwin struct nvmf_capsule; 25a1eda741SJohn Baldwin struct nvmf_host_qpair; 26a1eda741SJohn Baldwin struct nvmf_namespace; 27931dd5feSJohn Baldwin struct sysctl_oid_list; 28a1eda741SJohn Baldwin 29a1eda741SJohn Baldwin typedef void nvmf_request_complete_t(void *, const struct nvme_completion *); 30a1eda741SJohn Baldwin 31a1eda741SJohn Baldwin struct nvmf_softc { 32a1eda741SJohn Baldwin device_t dev; 33a1eda741SJohn Baldwin 34a1eda741SJohn Baldwin struct nvmf_host_qpair *admin; 35a1eda741SJohn Baldwin struct nvmf_host_qpair **io; 36a1eda741SJohn Baldwin u_int num_io_queues; 37a1eda741SJohn Baldwin enum nvmf_trtype trtype; 38a1eda741SJohn Baldwin 39a1eda741SJohn Baldwin struct cam_sim *sim; 40a1eda741SJohn Baldwin struct cam_path *path; 41a1eda741SJohn Baldwin struct mtx sim_mtx; 42a1eda741SJohn Baldwin bool sim_disconnected; 43f46d4971SJohn Baldwin bool sim_shutdown; 44a1eda741SJohn Baldwin 45a1eda741SJohn Baldwin struct nvmf_namespace **ns; 46a1eda741SJohn Baldwin 47a1eda741SJohn Baldwin struct nvme_controller_data *cdata; 48a1eda741SJohn Baldwin uint64_t cap; 49a1eda741SJohn Baldwin uint32_t vs; 50a1eda741SJohn Baldwin u_int max_pending_io; 51a1eda741SJohn Baldwin u_long max_xfer_size; 52a1eda741SJohn Baldwin 53a1eda741SJohn Baldwin struct cdev *cdev; 54a1eda741SJohn Baldwin 55a1eda741SJohn Baldwin /* 56a1eda741SJohn Baldwin * Keep Alive support depends on two timers. The 'tx' timer 57a1eda741SJohn Baldwin * is responsible for sending KeepAlive commands and runs at 58a1eda741SJohn Baldwin * half the timeout interval. The 'rx' timer is responsible 59a1eda741SJohn Baldwin * for detecting an actual timeout. 60a1eda741SJohn Baldwin * 61a1eda741SJohn Baldwin * For efficient support of TKAS, the host does not reschedule 62a1eda741SJohn Baldwin * these timers every time new commands are scheduled. 63a1eda741SJohn Baldwin * Instead, the host sets the *_traffic flags when commands 64a1eda741SJohn Baldwin * are sent and received. The timeout handlers check and 65a1eda741SJohn Baldwin * clear these flags. This does mean it can take up to twice 66a1eda741SJohn Baldwin * the timeout time to detect an AWOL controller. 67a1eda741SJohn Baldwin */ 68a1eda741SJohn Baldwin bool ka_traffic; /* Using TKAS? */ 69a1eda741SJohn Baldwin 70a1eda741SJohn Baldwin volatile int ka_active_tx_traffic; 71a1eda741SJohn Baldwin struct callout ka_tx_timer; 72a1eda741SJohn Baldwin sbintime_t ka_tx_sbt; 73a1eda741SJohn Baldwin 74a1eda741SJohn Baldwin volatile int ka_active_rx_traffic; 75a1eda741SJohn Baldwin struct callout ka_rx_timer; 76a1eda741SJohn Baldwin sbintime_t ka_rx_sbt; 77a1eda741SJohn Baldwin 78a1eda741SJohn Baldwin struct sx connection_lock; 79a1eda741SJohn Baldwin struct task disconnect_task; 80a1eda741SJohn Baldwin bool detaching; 81a1eda741SJohn Baldwin 82a1eda741SJohn Baldwin u_int num_aer; 83a1eda741SJohn Baldwin struct nvmf_aer *aer; 84f46d4971SJohn Baldwin 85931dd5feSJohn Baldwin struct sysctl_oid_list *ioq_oid_list; 86931dd5feSJohn Baldwin 87*8bba2c0fSJohn Baldwin nvlist_t *rparams; 88*8bba2c0fSJohn Baldwin 89f46d4971SJohn Baldwin eventhandler_tag shutdown_pre_sync_eh; 90f46d4971SJohn Baldwin eventhandler_tag shutdown_post_sync_eh; 91a1eda741SJohn Baldwin }; 92a1eda741SJohn Baldwin 93a1eda741SJohn Baldwin struct nvmf_request { 94a1eda741SJohn Baldwin struct nvmf_host_qpair *qp; 95a1eda741SJohn Baldwin struct nvmf_capsule *nc; 96a1eda741SJohn Baldwin nvmf_request_complete_t *cb; 97a1eda741SJohn Baldwin void *cb_arg; 98a1eda741SJohn Baldwin bool aer; 99a1eda741SJohn Baldwin 100a1eda741SJohn Baldwin STAILQ_ENTRY(nvmf_request) link; 101a1eda741SJohn Baldwin }; 102a1eda741SJohn Baldwin 103a1eda741SJohn Baldwin struct nvmf_completion_status { 104a1eda741SJohn Baldwin struct nvme_completion cqe; 105a1eda741SJohn Baldwin bool done; 106a1eda741SJohn Baldwin bool io_done; 107a1eda741SJohn Baldwin int io_error; 108a1eda741SJohn Baldwin }; 109a1eda741SJohn Baldwin 110a1eda741SJohn Baldwin static __inline struct nvmf_host_qpair * 111a1eda741SJohn Baldwin nvmf_select_io_queue(struct nvmf_softc *sc) 112a1eda741SJohn Baldwin { 1133ff90d91SJohn Baldwin u_int idx = curcpu * sc->num_io_queues / (mp_maxid + 1); 1143ff90d91SJohn Baldwin return (sc->io[idx]); 115a1eda741SJohn Baldwin } 116a1eda741SJohn Baldwin 117a1eda741SJohn Baldwin static __inline bool 118a1eda741SJohn Baldwin nvmf_cqe_aborted(const struct nvme_completion *cqe) 119a1eda741SJohn Baldwin { 120a1eda741SJohn Baldwin uint16_t status; 121a1eda741SJohn Baldwin 122a1eda741SJohn Baldwin status = le16toh(cqe->status); 123a1eda741SJohn Baldwin return (NVME_STATUS_GET_SCT(status) == NVME_SCT_PATH_RELATED && 124a1eda741SJohn Baldwin NVME_STATUS_GET_SC(status) == NVME_SC_COMMAND_ABORTED_BY_HOST); 125a1eda741SJohn Baldwin } 126a1eda741SJohn Baldwin 127a1eda741SJohn Baldwin static __inline void 128a1eda741SJohn Baldwin nvmf_status_init(struct nvmf_completion_status *status) 129a1eda741SJohn Baldwin { 130a1eda741SJohn Baldwin status->done = false; 131a1eda741SJohn Baldwin status->io_done = true; 132a1eda741SJohn Baldwin status->io_error = 0; 133a1eda741SJohn Baldwin } 134a1eda741SJohn Baldwin 135a1eda741SJohn Baldwin static __inline void 136a1eda741SJohn Baldwin nvmf_status_wait_io(struct nvmf_completion_status *status) 137a1eda741SJohn Baldwin { 138a1eda741SJohn Baldwin status->io_done = false; 139a1eda741SJohn Baldwin } 140a1eda741SJohn Baldwin 141a1eda741SJohn Baldwin #ifdef DRIVER_MODULE 142a1eda741SJohn Baldwin extern driver_t nvme_nvmf_driver; 143a1eda741SJohn Baldwin #endif 144a1eda741SJohn Baldwin 145a1eda741SJohn Baldwin #ifdef MALLOC_DECLARE 146a1eda741SJohn Baldwin MALLOC_DECLARE(M_NVMF); 147a1eda741SJohn Baldwin #endif 148a1eda741SJohn Baldwin 149aacaeeeeSJohn Baldwin /* If true, I/O requests will fail while the host is disconnected. */ 150aacaeeeeSJohn Baldwin extern bool nvmf_fail_disconnect; 151aacaeeeeSJohn Baldwin 152a1eda741SJohn Baldwin /* nvmf.c */ 153a1eda741SJohn Baldwin void nvmf_complete(void *arg, const struct nvme_completion *cqe); 154a1eda741SJohn Baldwin void nvmf_io_complete(void *arg, size_t xfered, int error); 155a1eda741SJohn Baldwin void nvmf_wait_for_reply(struct nvmf_completion_status *status); 156365b89e8SJohn Baldwin int nvmf_copyin_handoff(const struct nvmf_ioc_nv *nv, nvlist_t **nvlp); 157a1eda741SJohn Baldwin void nvmf_disconnect(struct nvmf_softc *sc); 158a1eda741SJohn Baldwin void nvmf_rescan_ns(struct nvmf_softc *sc, uint32_t nsid); 159f6d434f1SJohn Baldwin void nvmf_rescan_all_ns(struct nvmf_softc *sc); 160a1eda741SJohn Baldwin int nvmf_passthrough_cmd(struct nvmf_softc *sc, struct nvme_pt_command *pt, 161a1eda741SJohn Baldwin bool admin); 162a1eda741SJohn Baldwin 163a1eda741SJohn Baldwin /* nvmf_aer.c */ 164a1eda741SJohn Baldwin void nvmf_init_aer(struct nvmf_softc *sc); 165a1eda741SJohn Baldwin int nvmf_start_aer(struct nvmf_softc *sc); 166a1eda741SJohn Baldwin void nvmf_destroy_aer(struct nvmf_softc *sc); 167a1eda741SJohn Baldwin 168a1eda741SJohn Baldwin /* nvmf_cmd.c */ 169a1eda741SJohn Baldwin bool nvmf_cmd_get_property(struct nvmf_softc *sc, uint32_t offset, 170a1eda741SJohn Baldwin uint8_t size, nvmf_request_complete_t *cb, void *cb_arg, int how); 171a1eda741SJohn Baldwin bool nvmf_cmd_set_property(struct nvmf_softc *sc, uint32_t offset, 172a1eda741SJohn Baldwin uint8_t size, uint64_t value, nvmf_request_complete_t *cb, void *cb_arg, 173a1eda741SJohn Baldwin int how); 174a1eda741SJohn Baldwin bool nvmf_cmd_keep_alive(struct nvmf_softc *sc, nvmf_request_complete_t *cb, 175a1eda741SJohn Baldwin void *cb_arg, int how); 176a1eda741SJohn Baldwin bool nvmf_cmd_identify_active_namespaces(struct nvmf_softc *sc, uint32_t id, 177a1eda741SJohn Baldwin struct nvme_ns_list *nslist, nvmf_request_complete_t *req_cb, 178a1eda741SJohn Baldwin void *req_cb_arg, nvmf_io_complete_t *io_cb, void *io_cb_arg, int how); 179a1eda741SJohn Baldwin bool nvmf_cmd_identify_namespace(struct nvmf_softc *sc, uint32_t id, 180a1eda741SJohn Baldwin struct nvme_namespace_data *nsdata, nvmf_request_complete_t *req_cb, 181a1eda741SJohn Baldwin void *req_cb_arg, nvmf_io_complete_t *io_cb, void *io_cb_arg, int how); 182a1eda741SJohn Baldwin bool nvmf_cmd_get_log_page(struct nvmf_softc *sc, uint32_t nsid, uint8_t lid, 183a1eda741SJohn Baldwin uint64_t offset, void *buf, size_t len, nvmf_request_complete_t *req_cb, 184a1eda741SJohn Baldwin void *req_cb_arg, nvmf_io_complete_t *io_cb, void *io_cb_arg, int how); 185a1eda741SJohn Baldwin 186a1eda741SJohn Baldwin /* nvmf_ctldev.c */ 187a1eda741SJohn Baldwin int nvmf_ctl_load(void); 188a1eda741SJohn Baldwin void nvmf_ctl_unload(void); 189a1eda741SJohn Baldwin 190a1eda741SJohn Baldwin /* nvmf_ns.c */ 191a1eda741SJohn Baldwin struct nvmf_namespace *nvmf_init_ns(struct nvmf_softc *sc, uint32_t id, 192bed59babSJohn Baldwin const struct nvme_namespace_data *data); 193a1eda741SJohn Baldwin void nvmf_disconnect_ns(struct nvmf_namespace *ns); 194a1eda741SJohn Baldwin void nvmf_reconnect_ns(struct nvmf_namespace *ns); 195f46d4971SJohn Baldwin void nvmf_shutdown_ns(struct nvmf_namespace *ns); 196a1eda741SJohn Baldwin void nvmf_destroy_ns(struct nvmf_namespace *ns); 197a1eda741SJohn Baldwin bool nvmf_update_ns(struct nvmf_namespace *ns, 198bed59babSJohn Baldwin const struct nvme_namespace_data *data); 199a1eda741SJohn Baldwin 200a1eda741SJohn Baldwin /* nvmf_qpair.c */ 201a1eda741SJohn Baldwin struct nvmf_host_qpair *nvmf_init_qp(struct nvmf_softc *sc, 202365b89e8SJohn Baldwin enum nvmf_trtype trtype, const nvlist_t *nvl, const char *name, u_int qid); 203a1eda741SJohn Baldwin void nvmf_shutdown_qp(struct nvmf_host_qpair *qp); 204a1eda741SJohn Baldwin void nvmf_destroy_qp(struct nvmf_host_qpair *qp); 205a1eda741SJohn Baldwin struct nvmf_request *nvmf_allocate_request(struct nvmf_host_qpair *qp, 206a1eda741SJohn Baldwin void *sqe, nvmf_request_complete_t *cb, void *cb_arg, int how); 207a1eda741SJohn Baldwin void nvmf_submit_request(struct nvmf_request *req); 208a1eda741SJohn Baldwin void nvmf_free_request(struct nvmf_request *req); 209a1eda741SJohn Baldwin 210a1eda741SJohn Baldwin /* nvmf_sim.c */ 211a1eda741SJohn Baldwin int nvmf_init_sim(struct nvmf_softc *sc); 212a1eda741SJohn Baldwin void nvmf_disconnect_sim(struct nvmf_softc *sc); 213a1eda741SJohn Baldwin void nvmf_reconnect_sim(struct nvmf_softc *sc); 214f46d4971SJohn Baldwin void nvmf_shutdown_sim(struct nvmf_softc *sc); 215a1eda741SJohn Baldwin void nvmf_destroy_sim(struct nvmf_softc *sc); 216a1eda741SJohn Baldwin void nvmf_sim_rescan_ns(struct nvmf_softc *sc, uint32_t id); 217a1eda741SJohn Baldwin 218a1eda741SJohn Baldwin #endif /* !__NVMF_VAR_H__ */ 219