1 /*- 2 * Copyright (C) 2012 Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/bio.h> 32 #include <sys/bus.h> 33 #include <sys/conf.h> 34 #include <sys/disk.h> 35 #include <sys/fcntl.h> 36 #include <sys/ioccom.h> 37 #include <sys/module.h> 38 #include <sys/proc.h> 39 40 #include <dev/pci/pcivar.h> 41 42 #include "nvme_private.h" 43 44 static void 45 nvme_ns_cb(void *arg, const struct nvme_completion *status) 46 { 47 struct nvme_completion *cpl = arg; 48 struct mtx *mtx; 49 50 /* 51 * Copy status into the argument passed by the caller, so that 52 * the caller can check the status to determine if the 53 * the request passed or failed. 54 */ 55 memcpy(cpl, status, sizeof(*cpl)); 56 mtx = mtx_pool_find(mtxpool_sleep, cpl); 57 mtx_lock(mtx); 58 wakeup(cpl); 59 mtx_unlock(mtx); 60 } 61 62 static int 63 nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag, 64 struct thread *td) 65 { 66 struct nvme_namespace *ns; 67 struct nvme_controller *ctrlr; 68 struct nvme_completion cpl; 69 struct mtx *mtx; 70 71 ns = cdev->si_drv1; 72 ctrlr = ns->ctrlr; 73 74 switch (cmd) { 75 case NVME_IDENTIFY_NAMESPACE: 76 #ifdef CHATHAM2 77 /* 78 * Don't refresh data on Chatham, since Chatham returns 79 * garbage on IDENTIFY anyways. 80 */ 81 if (pci_get_devid(ctrlr->dev) == CHATHAM_PCI_ID) { 82 memcpy(arg, &ns->data, sizeof(ns->data)); 83 break; 84 } 85 #endif 86 /* Refresh data before returning to user. */ 87 mtx = mtx_pool_find(mtxpool_sleep, &cpl); 88 mtx_lock(mtx); 89 nvme_ctrlr_cmd_identify_namespace(ctrlr, ns->id, &ns->data, 90 nvme_ns_cb, &cpl); 91 msleep(&cpl, mtx, PRIBIO, "nvme_ioctl", 0); 92 mtx_unlock(mtx); 93 if (cpl.sf_sc || cpl.sf_sct) 94 return (ENXIO); 95 memcpy(arg, &ns->data, sizeof(ns->data)); 96 break; 97 case NVME_IO_TEST: 98 case NVME_BIO_TEST: 99 nvme_ns_test(ns, cmd, arg); 100 break; 101 case DIOCGMEDIASIZE: 102 *(off_t *)arg = (off_t)nvme_ns_get_size(ns); 103 break; 104 case DIOCGSECTORSIZE: 105 *(u_int *)arg = nvme_ns_get_sector_size(ns); 106 break; 107 default: 108 return (ENOTTY); 109 } 110 111 return (0); 112 } 113 114 static int 115 nvme_ns_open(struct cdev *dev __unused, int flags, int fmt __unused, 116 struct thread *td) 117 { 118 int error = 0; 119 120 if (flags & FWRITE) 121 error = securelevel_gt(td->td_ucred, 0); 122 123 return (error); 124 } 125 126 static int 127 nvme_ns_close(struct cdev *dev __unused, int flags, int fmt __unused, 128 struct thread *td) 129 { 130 131 return (0); 132 } 133 134 static void 135 nvme_ns_strategy_done(void *arg, const struct nvme_completion *status) 136 { 137 struct bio *bp = arg; 138 139 /* 140 * TODO: add more extensive translation of NVMe status codes 141 * to different bio error codes (i.e. EIO, EINVAL, etc.) 142 */ 143 if (status->sf_sc || status->sf_sct) { 144 bp->bio_error = EIO; 145 bp->bio_flags |= BIO_ERROR; 146 bp->bio_resid = bp->bio_bcount; 147 } else 148 bp->bio_resid = 0; 149 150 biodone(bp); 151 } 152 153 static void 154 nvme_ns_strategy(struct bio *bp) 155 { 156 struct nvme_namespace *ns; 157 int err; 158 159 ns = bp->bio_dev->si_drv1; 160 err = nvme_ns_bio_process(ns, bp, nvme_ns_strategy_done); 161 162 if (err) { 163 bp->bio_error = err; 164 bp->bio_flags |= BIO_ERROR; 165 bp->bio_resid = bp->bio_bcount; 166 biodone(bp); 167 } 168 169 } 170 171 static struct cdevsw nvme_ns_cdevsw = { 172 .d_version = D_VERSION, 173 .d_flags = D_DISK, 174 .d_open = nvme_ns_open, 175 .d_close = nvme_ns_close, 176 .d_read = nvme_ns_physio, 177 .d_write = nvme_ns_physio, 178 .d_strategy = nvme_ns_strategy, 179 .d_ioctl = nvme_ns_ioctl 180 }; 181 182 uint32_t 183 nvme_ns_get_max_io_xfer_size(struct nvme_namespace *ns) 184 { 185 return ns->ctrlr->max_xfer_size; 186 } 187 188 uint32_t 189 nvme_ns_get_sector_size(struct nvme_namespace *ns) 190 { 191 return (1 << ns->data.lbaf[0].lbads); 192 } 193 194 uint64_t 195 nvme_ns_get_num_sectors(struct nvme_namespace *ns) 196 { 197 return (ns->data.nsze); 198 } 199 200 uint64_t 201 nvme_ns_get_size(struct nvme_namespace *ns) 202 { 203 return (nvme_ns_get_num_sectors(ns) * nvme_ns_get_sector_size(ns)); 204 } 205 206 uint32_t 207 nvme_ns_get_flags(struct nvme_namespace *ns) 208 { 209 return (ns->flags); 210 } 211 212 const char * 213 nvme_ns_get_serial_number(struct nvme_namespace *ns) 214 { 215 return ((const char *)ns->ctrlr->cdata.sn); 216 } 217 218 const char * 219 nvme_ns_get_model_number(struct nvme_namespace *ns) 220 { 221 return ((const char *)ns->ctrlr->cdata.mn); 222 } 223 224 static void 225 nvme_ns_bio_done(void *arg, const struct nvme_completion *status) 226 { 227 struct bio *bp = arg; 228 nvme_cb_fn_t bp_cb_fn; 229 230 bp_cb_fn = bp->bio_driver1; 231 232 if (bp->bio_driver2) 233 free(bp->bio_driver2, M_NVME); 234 235 bp_cb_fn(bp, status); 236 } 237 238 int 239 nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp, 240 nvme_cb_fn_t cb_fn) 241 { 242 struct nvme_dsm_range *dsm_range; 243 int err; 244 245 bp->bio_driver1 = cb_fn; 246 247 switch (bp->bio_cmd) { 248 case BIO_READ: 249 err = nvme_ns_cmd_read(ns, bp->bio_data, 250 bp->bio_offset/nvme_ns_get_sector_size(ns), 251 bp->bio_bcount/nvme_ns_get_sector_size(ns), 252 nvme_ns_bio_done, bp); 253 break; 254 case BIO_WRITE: 255 err = nvme_ns_cmd_write(ns, bp->bio_data, 256 bp->bio_offset/nvme_ns_get_sector_size(ns), 257 bp->bio_bcount/nvme_ns_get_sector_size(ns), 258 nvme_ns_bio_done, bp); 259 break; 260 case BIO_FLUSH: 261 err = nvme_ns_cmd_flush(ns, nvme_ns_bio_done, bp); 262 break; 263 case BIO_DELETE: 264 /* 265 * Note: Chatham2 doesn't support DSM, so this code 266 * can't be fully tested yet. 267 */ 268 dsm_range = 269 malloc(sizeof(struct nvme_dsm_range), M_NVME, 270 M_ZERO | M_NOWAIT); 271 dsm_range->length = 272 bp->bio_bcount/nvme_ns_get_sector_size(ns); 273 dsm_range->starting_lba = 274 bp->bio_offset/nvme_ns_get_sector_size(ns); 275 bp->bio_driver2 = dsm_range; 276 err = nvme_ns_cmd_deallocate(ns, dsm_range, 1, 277 nvme_ns_bio_done, bp); 278 if (err != 0) 279 free(dsm_range, M_NVME); 280 break; 281 default: 282 err = EIO; 283 break; 284 } 285 286 return (err); 287 } 288 289 #ifdef CHATHAM2 290 static void 291 nvme_ns_populate_chatham_data(struct nvme_namespace *ns) 292 { 293 struct nvme_controller *ctrlr; 294 struct nvme_namespace_data *nsdata; 295 296 ctrlr = ns->ctrlr; 297 nsdata = &ns->data; 298 299 nsdata->nsze = ctrlr->chatham_lbas; 300 nsdata->ncap = ctrlr->chatham_lbas; 301 nsdata->nuse = ctrlr->chatham_lbas; 302 303 /* Chatham2 doesn't support thin provisioning. */ 304 nsdata->nsfeat.thin_prov = 0; 305 306 /* Set LBA size to 512 bytes. */ 307 nsdata->lbaf[0].lbads = 9; 308 } 309 #endif /* CHATHAM2 */ 310 311 int 312 nvme_ns_construct(struct nvme_namespace *ns, uint16_t id, 313 struct nvme_controller *ctrlr) 314 { 315 struct nvme_completion cpl; 316 struct mtx *mtx; 317 int status; 318 319 ns->ctrlr = ctrlr; 320 ns->id = id; 321 322 #ifdef CHATHAM2 323 if (pci_get_devid(ctrlr->dev) == CHATHAM_PCI_ID) 324 nvme_ns_populate_chatham_data(ns); 325 else { 326 #endif 327 mtx = mtx_pool_find(mtxpool_sleep, &cpl); 328 329 mtx_lock(mtx); 330 nvme_ctrlr_cmd_identify_namespace(ctrlr, id, &ns->data, 331 nvme_ns_cb, &cpl); 332 status = msleep(&cpl, mtx, PRIBIO, "nvme_start", hz*5); 333 mtx_unlock(mtx); 334 if ((status != 0) || cpl.sf_sc || cpl.sf_sct) { 335 printf("nvme_identify_namespace failed!\n"); 336 return (ENXIO); 337 } 338 #ifdef CHATHAM2 339 } 340 #endif 341 342 if (ctrlr->cdata.oncs.dsm && ns->data.nsfeat.thin_prov) 343 ns->flags |= NVME_NS_DEALLOCATE_SUPPORTED; 344 345 if (ctrlr->cdata.vwc.present) 346 ns->flags |= NVME_NS_FLUSH_SUPPORTED; 347 348 /* 349 * MAKEDEV_ETERNAL was added in r210923, for cdevs that will never 350 * be destroyed. This avoids refcounting on the cdev object. 351 * That should be OK case here, as long as we're not supporting PCIe 352 * surprise removal nor namespace deletion. 353 */ 354 #ifdef MAKEDEV_ETERNAL_KLD 355 ns->cdev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &nvme_ns_cdevsw, 0, 356 NULL, UID_ROOT, GID_WHEEL, 0600, "nvme%dns%d", 357 device_get_unit(ctrlr->dev), ns->id); 358 #else 359 ns->cdev = make_dev_credf(0, &nvme_ns_cdevsw, 0, 360 NULL, UID_ROOT, GID_WHEEL, 0600, "nvme%dns%d", 361 device_get_unit(ctrlr->dev), ns->id); 362 #endif 363 364 if (ns->cdev) { 365 ns->cdev->si_drv1 = ns; 366 } 367 368 return (0); 369 } 370