1 /* $NetBSD: nvmevar.h,v 1.21 2020/07/28 09:36:05 jdolecek Exp $ */ 2 /* $OpenBSD: nvmevar.h,v 1.8 2016/04/14 11:18:32 dlg Exp $ */ 3 4 /* 5 * Copyright (c) 2014 David Gwynne <dlg@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/bus.h> 21 #include <sys/cpu.h> 22 #include <sys/device.h> 23 #include <sys/mutex.h> 24 #include <sys/pool.h> 25 #include <sys/queue.h> 26 #include <sys/buf.h> 27 28 struct nvme_dmamem { 29 bus_dmamap_t ndm_map; 30 bus_dma_segment_t ndm_seg; 31 size_t ndm_size; 32 void *ndm_kva; 33 }; 34 #define NVME_DMA_MAP(_ndm) ((_ndm)->ndm_map) 35 #define NVME_DMA_LEN(_ndm) ((_ndm)->ndm_map->dm_segs[0].ds_len) 36 #define NVME_DMA_DVA(_ndm) ((uint64_t)(_ndm)->ndm_map->dm_segs[0].ds_addr) 37 #define NVME_DMA_KVA(_ndm) ((void *)(_ndm)->ndm_kva) 38 39 struct nvme_softc; 40 struct nvme_queue; 41 42 typedef void (*nvme_nnc_done)(void *, struct buf *, uint16_t, uint32_t); 43 44 struct nvme_ccb { 45 SIMPLEQ_ENTRY(nvme_ccb) ccb_entry; 46 47 /* DMA handles */ 48 bus_dmamap_t ccb_dmamap; 49 50 bus_addr_t ccb_prpl_off; 51 uint64_t ccb_prpl_dva; 52 uint64_t *ccb_prpl; 53 54 /* command context */ 55 uint16_t ccb_id; 56 void *ccb_cookie; 57 #define NVME_CCB_FREE 0xbeefdeed 58 void (*ccb_done)(struct nvme_queue *, 59 struct nvme_ccb *, struct nvme_cqe *); 60 61 /* namespace context */ 62 void *nnc_cookie; 63 nvme_nnc_done nnc_done; 64 uint16_t nnc_nsid; 65 uint16_t nnc_flags; 66 #define NVME_NS_CTX_F_READ __BIT(0) 67 #define NVME_NS_CTX_F_POLL __BIT(1) 68 #define NVME_NS_CTX_F_FUA __BIT(2) 69 70 struct buf *nnc_buf; 71 daddr_t nnc_blkno; 72 size_t nnc_datasize; 73 int nnc_secsize; 74 }; 75 76 struct nvme_queue { 77 struct nvme_softc *q_sc; 78 kmutex_t q_sq_mtx; 79 kmutex_t q_cq_mtx; 80 struct nvme_dmamem *q_sq_dmamem; 81 struct nvme_dmamem *q_cq_dmamem; 82 bus_size_t q_sqtdbl; /* submission queue tail doorbell */ 83 bus_size_t q_cqhdbl; /* completion queue head doorbell */ 84 uint16_t q_id; 85 uint32_t q_entries; 86 uint32_t q_sq_tail; 87 uint32_t q_cq_head; 88 uint16_t q_cq_phase; 89 90 kmutex_t q_ccb_mtx; 91 kcondvar_t q_ccb_wait; /* wait for ccb avail/finish */ 92 bool q_ccb_waiting; /* whether there are waiters */ 93 uint16_t q_nccbs; /* total number of ccbs */ 94 struct nvme_ccb *q_ccbs; 95 SIMPLEQ_HEAD(, nvme_ccb) q_ccb_list; 96 struct nvme_dmamem *q_ccb_prpls; 97 }; 98 99 struct nvme_namespace { 100 struct nvm_identify_namespace *ident; 101 device_t dev; 102 uint32_t flags; 103 #define NVME_NS_F_OPEN __BIT(0) 104 }; 105 106 struct nvme_softc { 107 device_t sc_dev; 108 109 bus_space_tag_t sc_iot; 110 bus_space_handle_t sc_ioh; 111 bus_size_t sc_ios; 112 bus_dma_tag_t sc_dmat; 113 114 int (*sc_intr_establish)(struct nvme_softc *, 115 uint16_t qid, struct nvme_queue *); 116 int (*sc_intr_disestablish)(struct nvme_softc *, 117 uint16_t qid); 118 void **sc_ih; /* interrupt handlers */ 119 void **sc_softih; /* softintr handlers */ 120 121 u_int sc_rdy_to; /* RDY timeout */ 122 size_t sc_mps; /* memory page size */ 123 size_t sc_mdts; /* max data trasfer size */ 124 u_int sc_max_sgl; /* max S/G segments */ 125 126 struct nvm_identify_controller 127 sc_identify; 128 129 u_int sc_nn; /* namespace count */ 130 struct nvme_namespace *sc_namespaces; 131 132 bool sc_use_mq; 133 u_int sc_nq; /* # of io queue (sc_q) */ 134 struct nvme_queue *sc_admin_q; 135 struct nvme_queue **sc_q; 136 137 uint32_t sc_flags; 138 #define NVME_F_ATTACHED __BIT(0) 139 #define NVME_F_OPEN __BIT(1) 140 141 uint32_t sc_quirks; 142 #define NVME_QUIRK_DELAY_B4_CHK_RDY __BIT(0) 143 #define NVME_QUIRK_NOMSI __BIT(1) 144 145 char sc_modelname[81]; 146 }; 147 148 #define lemtoh16(p) le16toh(*((uint16_t *)(p))) 149 #define lemtoh32(p) le32toh(*((uint32_t *)(p))) 150 #define lemtoh64(p) le64toh(*((uint64_t *)(p))) 151 #define htolem16(p, x) (*((uint16_t *)(p)) = htole16(x)) 152 #define htolem32(p, x) (*((uint32_t *)(p)) = htole32(x)) 153 #define htolem64(p, x) (*((uint64_t *)(p)) = htole64(x)) 154 155 struct nvme_attach_args { 156 uint16_t naa_nsid; 157 uint32_t naa_qentries; /* total number of queue slots */ 158 uint32_t naa_maxphys; /* maximum device transfer size */ 159 const char *naa_typename; /* identifier */ 160 }; 161 162 int nvme_attach(struct nvme_softc *); 163 int nvme_detach(struct nvme_softc *, int flags); 164 int nvme_rescan(device_t, const char *, const int *); 165 void nvme_childdet(device_t, device_t); 166 int nvme_intr(void *); 167 void nvme_softintr_intx(void *); 168 int nvme_intr_msi(void *); 169 void nvme_softintr_msi(void *); 170 171 static __inline struct nvme_queue * 172 nvme_get_q(struct nvme_softc *sc, struct buf *bp, bool waitok) 173 { 174 struct cpu_info *ci = (bp && bp->b_ci) ? bp->b_ci : curcpu(); 175 176 /* 177 * Find a queue with available ccbs, preferring the originating CPU's queue. 178 */ 179 180 for (u_int qoff = 0; qoff < sc->sc_nq; qoff++) { 181 struct nvme_queue *q = sc->sc_q[(cpu_index(ci) + qoff) % sc->sc_nq]; 182 if (!SIMPLEQ_EMPTY(&q->q_ccb_list) || waitok) 183 return q; 184 } 185 return NULL; 186 } 187 188 /* 189 * namespace 190 */ 191 static __inline struct nvme_namespace * 192 nvme_ns_get(struct nvme_softc *sc, uint16_t nsid) 193 { 194 if (nsid == 0 || nsid - 1 >= sc->sc_nn) 195 return NULL; 196 return &sc->sc_namespaces[nsid - 1]; 197 } 198 199 int nvme_ns_identify(struct nvme_softc *, uint16_t); 200 void nvme_ns_free(struct nvme_softc *, uint16_t); 201 int nvme_ns_dobio(struct nvme_softc *, uint16_t, void *, 202 struct buf *, void *, size_t, int, daddr_t, int, nvme_nnc_done); 203 int nvme_ns_sync(struct nvme_softc *, uint16_t, int); 204 int nvme_admin_getcache(struct nvme_softc *, int *); 205 int nvme_admin_setcache(struct nvme_softc *, int); 206