Pull block driver updates from Jens Axboe: "Here are the block driver changes for 4.4. This pull request contains: - NVMe: - Refactor and moving of code to prepare for proper target support. From Christoph and Jay. - 32-bit nvme warning fix from Arnd. - Error initialization fix from me. - Proper namespace removal and reference counting support from Keith. - Device resume fix on IO failure, also from Keith. - Dependency fix from Keith, now that nvme isn't under the umbrella of the block anymore. - Target location and maintainers update from Jay. - From Ming Lei, the long awaited DIO/AIO support for loop. - Enable BD-RE writeable opens, from Georgios" * 'for-4.4/drivers' of git://git.kernel.dk/linux-block: (24 commits) Update target repo for nvme patch contributions NVMe: initialize error to '0' nvme: use an integer value to Linux errno values nvme: fix 32-bit build warning NVMe: Add explicit block config dependency nvme: include <linux/types.ĥ> in <linux/nvme.h> nvme: move to a new drivers/nvme/host directory nvme.h: add missing nvme_id_ctrl endianess annotations nvme: move hardware structures out of the uapi version of nvme.h nvme: add a local nvme.h header nvme: properly handle partially initialized queues in nvme_create_io_queues nvme: merge nvme_dev_start, nvme_dev_resume and nvme_async_probe nvme: factor reset code into a common helper nvme: merge nvme_dev_reset into nvme_reset_failed_dev nvme: delete dev from dev_list in nvme_reset NVMe: Simplify device resume on io queue failure NVMe: Namespace removal simplifications NVMe: Reference count open namespaces cdrom: Random writing support for BD-RE media block: loop: support DIO & AIO ...
Unified · Split
| @@ -7486,11 +7486,13 @@ F: drivers/video/fbdev/riva/ · 7485 unmodified lines | ||
| 7486 | 7486 | F: drivers/video/fbdev/nvidia/ |
| 7487 | 7487 | |
| 7488 | 7488 | NVM EXPRESS DRIVER |
| 7489 | −M: Matthew Wilcox <willy@linux.intel.com> | |
| 7489 | +M: Keith Busch <keith.busch@intel.com> | |
| 7490 | +M: Jens Axboe <axboe@fb.com> | |
| 7490 | 7491 | L: linux-nvme@lists.infradead.org |
| 7491 | −T: git git://git.infradead.org/users/willy/linux-nvme.git | |
| 7492 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git | |
| 7493 | +W: https://kernel.googlesource.com/pub/scm/linux/kernel/git/axboe/linux-block/ | |
| 7492 | 7494 | S: Supported |
| 7493 | −F: drivers/block/nvme* | |
| 7495 | +F: drivers/nvme/host/ | |
| 7494 | 7496 | F: include/linux/nvme.h |
| 7495 | 7497 | |
| 7496 | 7498 | NVMEM FRAMEWORK |
| @@ -18,6 +18,8 @@ source "drivers/pnp/Kconfig" · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | source "drivers/block/Kconfig" |
| 20 | 20 | |
| 21 | +source "drivers/nvme/Kconfig" | |
| 22 | + | |
| 21 | 23 | # misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4 |
| 22 | 24 | |
| 23 | 25 | source "drivers/misc/Kconfig" |
| @@ -70,6 +70,7 @@ obj-$(CONFIG_NUBUS) += nubus/ · 69 unmodified lines | ||
| 70 | 70 | obj-y += macintosh/ |
| 71 | 71 | obj-$(CONFIG_IDE) += ide/ |
| 72 | 72 | obj-$(CONFIG_SCSI) += scsi/ |
| 73 | +obj-y += nvme/ | |
| 73 | 74 | obj-$(CONFIG_ATA) += ata/ |
| 74 | 75 | obj-$(CONFIG_TARGET_CORE) += target/ |
| 75 | 76 | obj-$(CONFIG_MTD) += mtd/ |
| @@ -310,17 +310,6 @@ config BLK_DEV_NBD · 309 unmodified lines | ||
| 310 | 310 | |
| 311 | 311 | If unsure, say N. |
| 312 | 312 | |
| 313 | −config BLK_DEV_NVME | |
| 314 | − tristate "NVM Express block device" | |
| 315 | − depends on PCI | |
| 316 | − ---help--- | |
| 317 | − The NVM Express driver is for solid state drives directly | |
| 318 | − connected to the PCI or PCI Express bus. If you know you | |
| 319 | − don't have one of these, it is safe to answer N. | |
| 320 | − | |
| 321 | − To compile this driver as a module, choose M here: the | |
| 322 | − module will be called nvme. | |
| 323 | − | |
| 324 | 313 | config BLK_DEV_SKD |
| 325 | 314 | tristate "STEC S1120 Block Driver" |
| 326 | 315 | depends on PCI |
| @@ -22,7 +22,6 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o · 21 unmodified lines | ||
| 22 | 22 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o |
| 23 | 23 | obj-$(CONFIG_MG_DISK) += mg_disk.o |
| 24 | 24 | obj-$(CONFIG_SUNVDC) += sunvdc.o |
| 25 | −obj-$(CONFIG_BLK_DEV_NVME) += nvme.o | |
| 26 | 25 | obj-$(CONFIG_BLK_DEV_SKD) += skd.o |
| 27 | 26 | obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o |
| 28 | 27 | |
| @@ -44,6 +43,5 @@ obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/ · 15 unmodified lines | ||
| 44 | 43 | obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_blk.o |
| 45 | 44 | obj-$(CONFIG_ZRAM) += zram/ |
| 46 | 45 | |
| 47 | −nvme-y := nvme-core.o nvme-scsi.o | |
| 48 | 46 | skd-y := skd_main.o |
| 49 | 47 | swim_mod-y := swim.o swim_asm.o |
| @@ -164,6 +164,62 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file) · 163 unmodified lines | ||
| 164 | 164 | return get_size(lo->lo_offset, lo->lo_sizelimit, file); |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | +static void __loop_update_dio(struct loop_device *lo, bool dio) | |
| 168 | +{ | |
| 169 | + struct file *file = lo->lo_backing_file; | |
| 170 | + struct address_space *mapping = file->f_mapping; | |
| 171 | + struct inode *inode = mapping->host; | |
| 172 | + unsigned short sb_bsize = 0; | |
| 173 | + unsigned dio_align = 0; | |
| 174 | + bool use_dio; | |
| 175 | + | |
| 176 | + if (inode->i_sb->s_bdev) { | |
| 177 | + sb_bsize = bdev_logical_block_size(inode->i_sb->s_bdev); | |
| 178 | + dio_align = sb_bsize - 1; | |
| 179 | + } | |
| 180 | + | |
| 181 | + /* | |
| 182 | + * We support direct I/O only if lo_offset is aligned with the | |
| 183 | + * logical I/O size of backing device, and the logical block | |
| 184 | + * size of loop is bigger than the backing device's and the loop | |
| 185 | + * needn't transform transfer. | |
| 186 | + * | |
| 187 | + * TODO: the above condition may be loosed in the future, and | |
| 188 | + * direct I/O may be switched runtime at that time because most | |
| 189 | + * of requests in sane appplications should be PAGE_SIZE algined | |
| 190 | + */ | |
| 191 | + if (dio) { | |
| 192 | + if (queue_logical_block_size(lo->lo_queue) >= sb_bsize && | |
| 193 | + !(lo->lo_offset & dio_align) && | |
| 194 | + mapping->a_ops->direct_IO && | |
| 195 | + !lo->transfer) | |
| 196 | + use_dio = true; | |
| 197 | + else | |
| 198 | + use_dio = false; | |
| 199 | + } else { | |
| 200 | + use_dio = false; | |
| 201 | + } | |
| 202 | + | |
| 203 | + if (lo->use_dio == use_dio) | |
| 204 | + return; | |
| 205 | + | |
| 206 | + /* flush dirty pages before changing direct IO */ | |
| 207 | + vfs_fsync(file, 0); | |
| 208 | + | |
| 209 | + /* | |
| 210 | + * The flag of LO_FLAGS_DIRECT_IO is handled similarly with | |
| 211 | + * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup | |
| 212 | + * will get updated by ioctl(LOOP_GET_STATUS) | |
| 213 | + */ | |
| 214 | + blk_mq_freeze_queue(lo->lo_queue); | |
| 215 | + lo->use_dio = use_dio; | |
| 216 | + if (use_dio) | |
| 217 | + lo->lo_flags |= LO_FLAGS_DIRECT_IO; | |
| 218 | + else | |
| 219 | + lo->lo_flags &= ~LO_FLAGS_DIRECT_IO; | |
| 220 | + blk_mq_unfreeze_queue(lo->lo_queue); | |
| 221 | +} | |
| 222 | + | |
| 167 | 223 | static int |
| 168 | 224 | figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) |
| 169 | 225 | { |
| @@ -389,6 +445,89 @@ static int lo_req_flush(struct loop_device *lo, struct request *rq) · 219 unmodified lines | ||
| 389 | 445 | return ret; |
| 390 | 446 | } |
| 391 | 447 | |
| 448 | +static inline void handle_partial_read(struct loop_cmd *cmd, long bytes) | |
| 449 | +{ | |
| 450 | + if (bytes < 0 || (cmd->rq->cmd_flags & REQ_WRITE)) | |
| 451 | + return; | |
| 452 | + | |
| 453 | + if (unlikely(bytes < blk_rq_bytes(cmd->rq))) { | |
| 454 | + struct bio *bio = cmd->rq->bio; | |
| 455 | + | |
| 456 | + bio_advance(bio, bytes); | |
| 457 | + zero_fill_bio(bio); | |
| 458 | + } | |
| 459 | +} | |
| 460 | + | |
| 461 | +static void lo_rw_aio_complete(struct kiocb *iocb, long ret, long ret2) | |
| 462 | +{ | |
| 463 | + struct loop_cmd *cmd = container_of(iocb, struct loop_cmd, iocb); | |
| 464 | + struct request *rq = cmd->rq; | |
| 465 | + | |
| 466 | + handle_partial_read(cmd, ret); | |
| 467 | + | |
| 468 | + if (ret > 0) | |
| 469 | + ret = 0; | |
| 470 | + else if (ret < 0) | |
| 471 | + ret = -EIO; | |
| 472 | + | |
| 473 | + blk_mq_complete_request(rq, ret); | |
| 474 | +} | |
| 475 | + | |
| 476 | +static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, | |
| 477 | + loff_t pos, bool rw) | |
| 478 | +{ | |
| 479 | + struct iov_iter iter; | |
| 480 | + struct bio_vec *bvec; | |
| 481 | + struct bio *bio = cmd->rq->bio; | |
| 482 | + struct file *file = lo->lo_backing_file; | |
| 483 | + int ret; | |
| 484 | + | |
| 485 | + /* nomerge for loop request queue */ | |
| 486 | + WARN_ON(cmd->rq->bio != cmd->rq->biotail); | |
| 487 | + | |
| 488 | + bvec = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); | |
| 489 | + iov_iter_bvec(&iter, ITER_BVEC | rw, bvec, | |
| 490 | + bio_segments(bio), blk_rq_bytes(cmd->rq)); | |
| 491 | + | |
| 492 | + cmd->iocb.ki_pos = pos; | |
| 493 | + cmd->iocb.ki_filp = file; | |
| 494 | + cmd->iocb.ki_complete = lo_rw_aio_complete; | |
| 495 | + cmd->iocb.ki_flags = IOCB_DIRECT; | |
| 496 | + | |
| 497 | + if (rw == WRITE) | |
| 498 | + ret = file->f_op->write_iter(&cmd->iocb, &iter); | |
| 499 | + else | |
| 500 | + ret = file->f_op->read_iter(&cmd->iocb, &iter); | |
| 501 | + | |
| 502 | + if (ret != -EIOCBQUEUED) | |
| 503 | + cmd->iocb.ki_complete(&cmd->iocb, ret, 0); | |
| 504 | + return 0; | |
| 505 | +} | |
| 506 | + | |
| 507 | + | |
| 508 | +static inline int lo_rw_simple(struct loop_device *lo, | |
| 509 | + struct request *rq, loff_t pos, bool rw) | |
| 510 | +{ | |
| 511 | + struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq); | |
| 512 | + | |
| 513 | + if (cmd->use_aio) | |
| 514 | + return lo_rw_aio(lo, cmd, pos, rw); | |
| 515 | + | |
| 516 | + /* | |
| 517 | + * lo_write_simple and lo_read_simple should have been covered | |
| 518 | + * by io submit style function like lo_rw_aio(), one blocker | |
| 519 | + * is that lo_read_simple() need to call flush_dcache_page after | |
| 520 | + * the page is written from kernel, and it isn't easy to handle | |
| 521 | + * this in io submit style function which submits all segments | |
| 522 | + * of the req at one time. And direct read IO doesn't need to | |
| 523 | + * run flush_dcache_page(). | |
| 524 | + */ | |
| 525 | + if (rw == WRITE) | |
| 526 | + return lo_write_simple(lo, rq, pos); | |
| 527 | + else | |
| 528 | + return lo_read_simple(lo, rq, pos); | |
| 529 | +} | |
| 530 | + | |
| 392 | 531 | static int do_req_filebacked(struct loop_device *lo, struct request *rq) |
| 393 | 532 | { |
| 394 | 533 | loff_t pos; |
| @@ -404,13 +543,13 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) · 9 unmodified lines | ||
| 404 | 543 | else if (lo->transfer) |
| 405 | 544 | ret = lo_write_transfer(lo, rq, pos); |
| 406 | 545 | else |
| 407 | − ret = lo_write_simple(lo, rq, pos); | |
| 546 | + ret = lo_rw_simple(lo, rq, pos, WRITE); | |
| 408 | 547 | |
| 409 | 548 | } else { |
| 410 | 549 | if (lo->transfer) |
| 411 | 550 | ret = lo_read_transfer(lo, rq, pos); |
| 412 | 551 | else |
| 413 | − ret = lo_read_simple(lo, rq, pos); | |
| 552 | + ret = lo_rw_simple(lo, rq, pos, READ); | |
| 414 | 553 | } |
| 415 | 554 | |
| 416 | 555 | return ret; |
| @@ -421,6 +560,12 @@ struct switch_request { · 4 unmodified lines | ||
| 421 | 560 | struct completion wait; |
| 422 | 561 | }; |
| 423 | 562 | |
| 563 | +static inline void loop_update_dio(struct loop_device *lo) | |
| 564 | +{ | |
| 565 | + __loop_update_dio(lo, io_is_direct(lo->lo_backing_file) | | |
| 566 | + lo->use_dio); | |
| 567 | +} | |
| 568 | + | |
| 424 | 569 | /* |
| 425 | 570 | * Do the actual switch; called from the BIO completion routine |
| 426 | 571 | */ |
| @@ -441,6 +586,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) · 14 unmodified lines | ||
| 441 | 586 | mapping->host->i_bdev->bd_block_size : PAGE_SIZE; |
| 442 | 587 | lo->old_gfp_mask = mapping_gfp_mask(mapping); |
| 443 | 588 | mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); |
| 589 | + loop_update_dio(lo); | |
| 444 | 590 | } |
| 445 | 591 | |
| 446 | 592 | /* |
| @@ -627,11 +773,19 @@ static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf) · 180 unmodified lines | ||
| 627 | 773 | return sprintf(buf, "%s\n", partscan ? "1" : "0"); |
| 628 | 774 | } |
| 629 | 775 | |
| 776 | +static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf) | |
| 777 | +{ | |
| 778 | + int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO); | |
| 779 | + | |
| 780 | + return sprintf(buf, "%s\n", dio ? "1" : "0"); | |
| 781 | +} | |
| 782 | + | |
| 630 | 783 | LOOP_ATTR_RO(backing_file); |
| 631 | 784 | LOOP_ATTR_RO(offset); |
| 632 | 785 | LOOP_ATTR_RO(sizelimit); |
| 633 | 786 | LOOP_ATTR_RO(autoclear); |
| 634 | 787 | LOOP_ATTR_RO(partscan); |
| 788 | +LOOP_ATTR_RO(dio); | |
| 635 | 789 | |
| 636 | 790 | static struct attribute *loop_attrs[] = { |
| 637 | 791 | &loop_attr_backing_file.attr, |
| @@ -639,6 +793,7 @@ static struct attribute *loop_attrs[] = { · 1 unmodified line | ||
| 639 | 793 | &loop_attr_sizelimit.attr, |
| 640 | 794 | &loop_attr_autoclear.attr, |
| 641 | 795 | &loop_attr_partscan.attr, |
| 796 | + &loop_attr_dio.attr, | |
| 642 | 797 | NULL, |
| 643 | 798 | }; |
| 644 | 799 | |
| @@ -688,6 +843,23 @@ static void loop_config_discard(struct loop_device *lo) · 43 unmodified lines | ||
| 688 | 843 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); |
| 689 | 844 | } |
| 690 | 845 | |
| 846 | +static void loop_unprepare_queue(struct loop_device *lo) | |
| 847 | +{ | |
| 848 | + flush_kthread_worker(&lo->worker); | |
| 849 | + kthread_stop(lo->worker_task); | |
| 850 | +} | |
| 851 | + | |
| 852 | +static int loop_prepare_queue(struct loop_device *lo) | |
| 853 | +{ | |
| 854 | + init_kthread_worker(&lo->worker); | |
| 855 | + lo->worker_task = kthread_run(kthread_worker_fn, | |
| 856 | + &lo->worker, "loop%d", lo->lo_number); | |
| 857 | + if (IS_ERR(lo->worker_task)) | |
| 858 | + return -ENOMEM; | |
| 859 | + set_user_nice(lo->worker_task, MIN_NICE); | |
| 860 | + return 0; | |
| 861 | +} | |
| 862 | + | |
| 691 | 863 | static int loop_set_fd(struct loop_device *lo, fmode_t mode, |
| 692 | 864 | struct block_device *bdev, unsigned int arg) |
| 693 | 865 | { |
| @@ -745,17 +917,15 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, · 51 unmodified lines | ||
| 745 | 917 | size = get_loop_size(lo, file); |
| 746 | 918 | if ((loff_t)(sector_t)size != size) |
| 747 | 919 | goto out_putf; |
| 748 | − error = -ENOMEM; | |
| 749 | − lo->wq = alloc_workqueue("kloopd%d", | |
| 750 | − WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16, | |
| 751 | − lo->lo_number); | |
| 752 | − if (!lo->wq) | |
| 920 | + error = loop_prepare_queue(lo); | |
| 921 | + if (error) | |
| 753 | 922 | goto out_putf; |
| 754 | 923 | |
| 755 | 924 | error = 0; |
| 756 | 925 | |
| 757 | 926 | set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0); |
| 758 | 927 | |
| 928 | + lo->use_dio = false; | |
| 759 | 929 | lo->lo_blocksize = lo_blocksize; |
| 760 | 930 | lo->lo_device = bdev; |
| 761 | 931 | lo->lo_flags = lo_flags; |
| @@ -769,6 +939,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, · 7 unmodified lines | ||
| 769 | 939 | if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) |
| 770 | 940 | blk_queue_flush(lo->lo_queue, REQ_FLUSH); |
| 771 | 941 | |
| 942 | + loop_update_dio(lo); | |
| 772 | 943 | set_capacity(lo->lo_disk, size); |
| 773 | 944 | bd_set_size(bdev, size << 9); |
| 774 | 945 | loop_sysfs_init(lo); |
| @@ -903,8 +1074,7 @@ static int loop_clr_fd(struct loop_device *lo) · 128 unmodified lines | ||
| 903 | 1074 | lo->lo_flags = 0; |
| 904 | 1075 | if (!part_shift) |
| 905 | 1076 | lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN; |
| 906 | − destroy_workqueue(lo->wq); | |
| 907 | − lo->wq = NULL; | |
| 1077 | + loop_unprepare_queue(lo); | |
| 908 | 1078 | mutex_unlock(&lo->lo_ctl_mutex); |
| 909 | 1079 | /* |
| 910 | 1080 | * Need not hold lo_ctl_mutex to fput backing file. |
| @@ -988,6 +1158,9 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) · 77 unmodified lines | ||
| 988 | 1158 | lo->lo_key_owner = uid; |
| 989 | 1159 | } |
| 990 | 1160 | |
| 1161 | + /* update dio if lo_offset or transfer is changed */ | |
| 1162 | + __loop_update_dio(lo, lo->use_dio); | |
| 1163 | + | |
| 991 | 1164 | return 0; |
| 992 | 1165 | } |
| 993 | 1166 | |
| @@ -1138,6 +1311,20 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev) · 144 unmodified lines | ||
| 1138 | 1311 | return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); |
| 1139 | 1312 | } |
| 1140 | 1313 | |
| 1314 | +static int loop_set_dio(struct loop_device *lo, unsigned long arg) | |
| 1315 | +{ | |
| 1316 | + int error = -ENXIO; | |
| 1317 | + if (lo->lo_state != Lo_bound) | |
| 1318 | + goto out; | |
| 1319 | + | |
| 1320 | + __loop_update_dio(lo, !!arg); | |
| 1321 | + if (lo->use_dio == !!arg) | |
| 1322 | + return 0; | |
| 1323 | + error = -EINVAL; | |
| 1324 | + out: | |
| 1325 | + return error; | |
| 1326 | +} | |
| 1327 | + | |
| 1141 | 1328 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, |
| 1142 | 1329 | unsigned int cmd, unsigned long arg) |
| 1143 | 1330 | { |
| @@ -1181,6 +1368,11 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, · 37 unmodified lines | ||
| 1181 | 1368 | if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) |
| 1182 | 1369 | err = loop_set_capacity(lo, bdev); |
| 1183 | 1370 | break; |
| 1371 | + case LOOP_SET_DIRECT_IO: | |
| 1372 | + err = -EPERM; | |
| 1373 | + if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) | |
| 1374 | + err = loop_set_dio(lo, arg); | |
| 1375 | + break; | |
| 1184 | 1376 | default: |
| 1185 | 1377 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; |
| 1186 | 1378 | } |
| @@ -1461,23 +1653,13 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx, · 274 unmodified lines | ||
| 1461 | 1653 | if (lo->lo_state != Lo_bound) |
| 1462 | 1654 | return -EIO; |
| 1463 | 1655 | |
| 1464 | − if (cmd->rq->cmd_flags & REQ_WRITE) { | |
| 1465 | − struct loop_device *lo = cmd->rq->q->queuedata; | |
| 1466 | − bool need_sched = true; | |
| 1467 | − | |
| 1468 | − spin_lock_irq(&lo->lo_lock); | |
| 1469 | − if (lo->write_started) | |
| 1470 | − need_sched = false; | |
| 1471 | − else | |
| 1472 | − lo->write_started = true; | |
| 1473 | − list_add_tail(&cmd->list, &lo->write_cmd_head); | |
| 1474 | − spin_unlock_irq(&lo->lo_lock); | |
| 1656 | + if (lo->use_dio && !(cmd->rq->cmd_flags & (REQ_FLUSH | | |
| 1657 | + REQ_DISCARD))) | |
| 1658 | + cmd->use_aio = true; | |
| 1659 | + else | |
| 1660 | + cmd->use_aio = false; | |
| 1475 | 1661 | |
| 1476 | − if (need_sched) | |
| 1477 | − queue_work(lo->wq, &lo->write_work); | |
| 1478 | − } else { | |
| 1479 | − queue_work(lo->wq, &cmd->read_work); | |
| 1480 | − } | |
| 1662 | + queue_kthread_work(&lo->worker, &cmd->work); | |
| 1481 | 1663 | |
| 1482 | 1664 | return BLK_MQ_RQ_QUEUE_OK; |
| 1483 | 1665 | } |
| @@ -1495,38 +1677,15 @@ static void loop_handle_cmd(struct loop_cmd *cmd) · 11 unmodified lines | ||
| 1495 | 1677 | |
| 1496 | 1678 | ret = do_req_filebacked(lo, cmd->rq); |
| 1497 | 1679 | failed: |
| 1498 | − blk_mq_complete_request(cmd->rq, ret ? -EIO : 0); | |
| 1680 | + /* complete non-aio request */ | |
| 1681 | + if (!cmd->use_aio || ret) | |
| 1682 | + blk_mq_complete_request(cmd->rq, ret ? -EIO : 0); | |
| 1499 | 1683 | } |
| 1500 | 1684 | |
| 1501 | −static void loop_queue_write_work(struct work_struct *work) | |
| 1502 | −{ | |
| 1503 | − struct loop_device *lo = | |
| 1504 | − container_of(work, struct loop_device, write_work); | |
| 1505 | − LIST_HEAD(cmd_list); | |
| 1506 | − | |
| 1507 | − spin_lock_irq(&lo->lo_lock); | |
| 1508 | − repeat: | |
| 1509 | − list_splice_init(&lo->write_cmd_head, &cmd_list); | |
| 1510 | − spin_unlock_irq(&lo->lo_lock); | |
| 1511 | − | |
| 1512 | − while (!list_empty(&cmd_list)) { | |
| 1513 | − struct loop_cmd *cmd = list_first_entry(&cmd_list, | |
| 1514 | − struct loop_cmd, list); | |
| 1515 | − list_del_init(&cmd->list); | |
| 1516 | − loop_handle_cmd(cmd); | |
| 1517 | − } | |
| 1518 | − | |
| 1519 | − spin_lock_irq(&lo->lo_lock); | |
| 1520 | − if (!list_empty(&lo->write_cmd_head)) | |
| 1521 | − goto repeat; | |
| 1522 | − lo->write_started = false; | |
| 1523 | − spin_unlock_irq(&lo->lo_lock); | |
| 1524 | −} | |
| 1525 | − | |
| 1526 | −static void loop_queue_read_work(struct work_struct *work) | |
| 1685 | +static void loop_queue_work(struct kthread_work *work) | |
| 1527 | 1686 | { |
| 1528 | 1687 | struct loop_cmd *cmd = |
| 1529 | − container_of(work, struct loop_cmd, read_work); | |
| 1688 | + container_of(work, struct loop_cmd, work); | |
| 1530 | 1689 | |
| 1531 | 1690 | loop_handle_cmd(cmd); |
| 1532 | 1691 | } |
| @@ -1538,7 +1697,7 @@ static int loop_init_request(void *data, struct request *rq, · 5 unmodified lines | ||
| 1538 | 1697 | struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq); |
| 1539 | 1698 | |
| 1540 | 1699 | cmd->rq = rq; |
| 1541 | − INIT_WORK(&cmd->read_work, loop_queue_read_work); | |
| 1700 | + init_kthread_work(&cmd->work, loop_queue_work); | |
| 1542 | 1701 | |
| 1543 | 1702 | return 0; |
| 1544 | 1703 | } |
| @@ -1594,8 +1753,11 @@ static int loop_add(struct loop_device **l, int i) · 49 unmodified lines | ||
| 1594 | 1753 | } |
| 1595 | 1754 | lo->lo_queue->queuedata = lo; |
| 1596 | 1755 | |
| 1597 | − INIT_LIST_HEAD(&lo->write_cmd_head); | |
| 1598 | − INIT_WORK(&lo->write_work, loop_queue_write_work); | |
| 1756 | + /* | |
| 1757 | + * It doesn't make sense to enable merge because the I/O | |
| 1758 | + * submitted to backing file is handled page by page. | |
| 1759 | + */ | |
| 1760 | + queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue); | |
| 1599 | 1761 | |
| 1600 | 1762 | disk = lo->lo_disk = alloc_disk(1 << part_shift); |
| 1601 | 1763 | if (!disk) |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/blk-mq.h> |
| 15 | 15 | #include <linux/spinlock.h> |
| 16 | 16 | #include <linux/mutex.h> |
| 17 | −#include <linux/workqueue.h> | |
| 17 | +#include <linux/kthread.h> | |
| 18 | 18 | #include <uapi/linux/loop.h> |
| 19 | 19 | |
| 20 | 20 | /* Possible states of device */ |
| @@ -54,12 +54,11 @@ struct loop_device { · 33 unmodified lines | ||
| 54 | 54 | gfp_t old_gfp_mask; |
| 55 | 55 | |
| 56 | 56 | spinlock_t lo_lock; |
| 57 | − struct workqueue_struct *wq; | |
| 58 | − struct list_head write_cmd_head; | |
| 59 | − struct work_struct write_work; | |
| 60 | − bool write_started; | |
| 61 | 57 | int lo_state; |
| 62 | 58 | struct mutex lo_ctl_mutex; |
| 59 | + struct kthread_worker worker; | |
| 60 | + struct task_struct *worker_task; | |
| 61 | + bool use_dio; | |
| 63 | 62 | |
| 64 | 63 | struct request_queue *lo_queue; |
| 65 | 64 | struct blk_mq_tag_set tag_set; |
| @@ -67,9 +66,11 @@ struct loop_device { · 1 unmodified line | ||
| 67 | 66 | }; |
| 68 | 67 | |
| 69 | 68 | struct loop_cmd { |
| 70 | − struct work_struct read_work; | |
| 69 | + struct kthread_work work; | |
| 71 | 70 | struct request *rq; |
| 72 | 71 | struct list_head list; |
| 72 | + bool use_aio; /* use AIO interface to handle I/O */ | |
| 73 | + struct kiocb iocb; | |
| 73 | 74 | }; |
| 74 | 75 | |
| 75 | 76 | /* Support for loadable transfer modules */ |
| @@ -885,6 +885,7 @@ static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi) · 884 unmodified lines | ||
| 885 | 885 | switch (cdi->mmc3_profile) { |
| 886 | 886 | case 0x12: /* DVD-RAM */ |
| 887 | 887 | case 0x1A: /* DVD+RW */ |
| 888 | + case 0x43: /* BD-RE */ | |
| 888 | 889 | return 0; |
| 889 | 890 | default: |
| 890 | 891 | return 1; |
| @@ -0,0 +1 @@ | ||
| 1 | +source "drivers/nvme/host/Kconfig" | |
| @@ -0,0 +1,2 @@ | ||
| 1 | + | |
| 2 | +obj-y += host/ | |
| @@ -0,0 +1,10 @@ | ||
| 1 | +config BLK_DEV_NVME | |
| 2 | + tristate "NVM Express block device" | |
| 3 | + depends on PCI && BLOCK | |
| 4 | + ---help--- | |
| 5 | + The NVM Express driver is for solid state drives directly | |
| 6 | + connected to the PCI or PCI Express bus. If you know you | |
| 7 | + don't have one of these, it is safe to answer N. | |
| 8 | + | |
| 9 | + To compile this driver as a module, choose M here: the | |
| 10 | + module will be called nvme. | |
| @@ -0,0 +1,4 @@ | ||
| 1 | + | |
| 2 | +obj-$(CONFIG_BLK_DEV_NVME) += nvme.o | |
| 3 | + | |
| 4 | +nvme-y += pci.o scsi.o | |
| @@ -0,0 +1,133 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2011-2014, Intel Corporation. | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms and conditions of the GNU General Public License, | |
| 6 | + * version 2, as published by the Free Software Foundation. | |
| 7 | + * | |
| 8 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
| 9 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 10 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 11 | + * more details. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#ifndef _NVME_H | |
| 15 | +#define _NVME_H | |
| 16 | + | |
| 17 | +#include <linux/nvme.h> | |
| 18 | +#include <linux/pci.h> | |
| 19 | +#include <linux/kref.h> | |
| 20 | +#include <linux/blk-mq.h> | |
| 21 | + | |
| 22 | +extern unsigned char nvme_io_timeout; | |
| 23 | +#define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * Represents an NVM Express device. Each nvme_dev is a PCI function. | |
| 27 | + */ | |
| 28 | +struct nvme_dev { | |
| 29 | + struct list_head node; | |
| 30 | + struct nvme_queue **queues; | |
| 31 | + struct request_queue *admin_q; | |
| 32 | + struct blk_mq_tag_set tagset; | |
| 33 | + struct blk_mq_tag_set admin_tagset; | |
| 34 | + u32 __iomem *dbs; | |
| 35 | + struct device *dev; | |
| 36 | + struct dma_pool *prp_page_pool; | |
| 37 | + struct dma_pool *prp_small_pool; | |
| 38 | + int instance; | |
| 39 | + unsigned queue_count; | |
| 40 | + unsigned online_queues; | |
| 41 | + unsigned max_qid; | |
| 42 | + int q_depth; | |
| 43 | + u32 db_stride; | |
| 44 | + u32 ctrl_config; | |
| 45 | + struct msix_entry *entry; | |
| 46 | + struct nvme_bar __iomem *bar; | |
| 47 | + struct list_head namespaces; | |
| 48 | + struct kref kref; | |
| 49 | + struct device *device; | |
| 50 | + struct work_struct reset_work; | |
| 51 | + struct work_struct probe_work; | |
| 52 | + struct work_struct scan_work; | |
| 53 | + char name[12]; | |
| 54 | + char serial[20]; | |
| 55 | + char model[40]; | |
| 56 | + char firmware_rev[8]; | |
| 57 | + bool subsystem; | |
| 58 | + u32 max_hw_sectors; | |
| 59 | + u32 stripe_size; | |
| 60 | + u32 page_size; | |
| 61 | + void __iomem *cmb; | |
| 62 | + dma_addr_t cmb_dma_addr; | |
| 63 | + u64 cmb_size; | |
| 64 | + u32 cmbsz; | |
| 65 | + u16 oncs; | |
| 66 | + u16 abort_limit; | |
| 67 | + u8 event_limit; | |
| 68 | + u8 vwc; | |
| 69 | +}; | |
| 70 | + | |
| 71 | +/* | |
| 72 | + * An NVM Express namespace is equivalent to a SCSI LUN | |
| 73 | + */ | |
| 74 | +struct nvme_ns { | |
| 75 | + struct list_head list; | |
| 76 | + | |
| 77 | + struct nvme_dev *dev; | |
| 78 | + struct request_queue *queue; | |
| 79 | + struct gendisk *disk; | |
| 80 | + struct kref kref; | |
| 81 | + | |
| 82 | + unsigned ns_id; | |
| 83 | + int lba_shift; | |
| 84 | + u16 ms; | |
| 85 | + bool ext; | |
| 86 | + u8 pi_type; | |
| 87 | + u64 mode_select_num_blocks; | |
| 88 | + u32 mode_select_block_len; | |
| 89 | +}; | |
| 90 | + | |
| 91 | +/* | |
| 92 | + * The nvme_iod describes the data in an I/O, including the list of PRP | |
| 93 | + * entries. You can't see it in this data structure because C doesn't let | |
| 94 | + * me express that. Use nvme_alloc_iod to ensure there's enough space | |
| 95 | + * allocated to store the PRP list. | |
| 96 | + */ | |
| 97 | +struct nvme_iod { | |
| 98 | + unsigned long private; /* For the use of the submitter of the I/O */ | |
| 99 | + int npages; /* In the PRP list. 0 means small pool in use */ | |
| 100 | + int offset; /* Of PRP list */ | |
| 101 | + int nents; /* Used in scatterlist */ | |
| 102 | + int length; /* Of data, in bytes */ | |
| 103 | + dma_addr_t first_dma; | |
| 104 | + struct scatterlist meta_sg[1]; /* metadata requires single contiguous buffer */ | |
| 105 | + struct scatterlist sg[0]; | |
| 106 | +}; | |
| 107 | + | |
| 108 | +static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector) | |
| 109 | +{ | |
| 110 | + return (sector >> (ns->lba_shift - 9)); | |
| 111 | +} | |
| 112 | + | |
| 113 | +int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, | |
| 114 | + void *buf, unsigned bufflen); | |
| 115 | +int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, | |
| 116 | + void *buffer, void __user *ubuffer, unsigned bufflen, | |
| 117 | + u32 *result, unsigned timeout); | |
| 118 | +int nvme_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl **id); | |
| 119 | +int nvme_identify_ns(struct nvme_dev *dev, unsigned nsid, | |
| 120 | + struct nvme_id_ns **id); | |
| 121 | +int nvme_get_log_page(struct nvme_dev *dev, struct nvme_smart_log **log); | |
| 122 | +int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, | |
| 123 | + dma_addr_t dma_addr, u32 *result); | |
| 124 | +int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, | |
| 125 | + dma_addr_t dma_addr, u32 *result); | |
| 126 | + | |
| 127 | +struct sg_io_hdr; | |
| 128 | + | |
| 129 | +int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr); | |
| 130 | +int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg); | |
| 131 | +int nvme_sg_get_version_num(int __user *ip); | |
| 132 | + | |
| 133 | +#endif /* _NVME_H */ | |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | * more details. |
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | −#include <linux/nvme.h> | |
| 16 | 15 | #include <linux/bitops.h> |
| 17 | 16 | #include <linux/blkdev.h> |
| 18 | 17 | #include <linux/blk-mq.h> |
| @@ -43,6 +42,9 @@ · 24 unmodified lines | ||
| 43 | 42 | #include <scsi/sg.h> |
| 44 | 43 | #include <asm-generic/io-64-nonatomic-lo-hi.h> |
| 45 | 44 | |
| 45 | +#include <uapi/linux/nvme_ioctl.h> | |
| 46 | +#include "nvme.h" | |
| 47 | + | |
| 46 | 48 | #define NVME_MINORS (1U << MINORBITS) |
| 47 | 49 | #define NVME_Q_DEPTH 1024 |
| 48 | 50 | #define NVME_AQ_DEPTH 256 |
| @@ -84,9 +86,10 @@ static wait_queue_head_t nvme_kthread_wait; · 35 unmodified lines | ||
| 84 | 86 | |
| 85 | 87 | static struct class *nvme_class; |
| 86 | 88 | |
| 87 | −static void nvme_reset_failed_dev(struct work_struct *ws); | |
| 89 | +static int __nvme_reset(struct nvme_dev *dev); | |
| 88 | 90 | static int nvme_reset(struct nvme_dev *dev); |
| 89 | 91 | static int nvme_process_cq(struct nvme_queue *nvmeq); |
| 92 | +static void nvme_dead_ctrl(struct nvme_dev *dev); | |
| 90 | 93 | |
| 91 | 94 | struct async_cmd_info { |
| 92 | 95 | struct kthread_work work; |
| @@ -1283,18 +1286,13 @@ static void nvme_abort_req(struct request *req) · 1190 unmodified lines | ||
| 1283 | 1286 | struct nvme_command cmd; |
| 1284 | 1287 | |
| 1285 | 1288 | if (!nvmeq->qid || cmd_rq->aborted) { |
| 1286 | − unsigned long flags; | |
| 1287 | − | |
| 1288 | − spin_lock_irqsave(&dev_list_lock, flags); | |
| 1289 | − if (work_busy(&dev->reset_work)) | |
| 1290 | − goto out; | |
| 1291 | − list_del_init(&dev->node); | |
| 1292 | − dev_warn(dev->dev, "I/O %d QID %d timeout, reset controller\n", | |
| 1293 | − req->tag, nvmeq->qid); | |
| 1294 | − dev->reset_workfn = nvme_reset_failed_dev; | |
| 1295 | − queue_work(nvme_workq, &dev->reset_work); | |
| 1296 | − out: | |
| 1297 | − spin_unlock_irqrestore(&dev_list_lock, flags); | |
| 1289 | + spin_lock(&dev_list_lock); | |
| 1290 | + if (!__nvme_reset(dev)) { | |
| 1291 | + dev_warn(dev->dev, | |
| 1292 | + "I/O %d QID %d timeout, reset controller\n", | |
| 1293 | + req->tag, nvmeq->qid); | |
| 1294 | + } | |
| 1295 | + spin_unlock(&dev_list_lock); | |
| 1298 | 1296 | return; |
| 1299 | 1297 | } |
| 1300 | 1298 | |
| @@ -1949,6 +1947,20 @@ static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode, · 648 unmodified lines | ||
| 1949 | 1947 | #define nvme_compat_ioctl NULL |
| 1950 | 1948 | #endif |
| 1951 | 1949 | |
| 1950 | +static void nvme_free_dev(struct kref *kref); | |
| 1951 | +static void nvme_free_ns(struct kref *kref) | |
| 1952 | +{ | |
| 1953 | + struct nvme_ns *ns = container_of(kref, struct nvme_ns, kref); | |
| 1954 | + | |
| 1955 | + spin_lock(&dev_list_lock); | |
| 1956 | + ns->disk->private_data = NULL; | |
| 1957 | + spin_unlock(&dev_list_lock); | |
| 1958 | + | |
| 1959 | + kref_put(&ns->dev->kref, nvme_free_dev); | |
| 1960 | + put_disk(ns->disk); | |
| 1961 | + kfree(ns); | |
| 1962 | +} | |
| 1963 | + | |
| 1952 | 1964 | static int nvme_open(struct block_device *bdev, fmode_t mode) |
| 1953 | 1965 | { |
| 1954 | 1966 | int ret = 0; |
| @@ -1958,21 +1970,17 @@ static int nvme_open(struct block_device *bdev, fmode_t mode) · 3 unmodified lines | ||
| 1958 | 1970 | ns = bdev->bd_disk->private_data; |
| 1959 | 1971 | if (!ns) |
| 1960 | 1972 | ret = -ENXIO; |
| 1961 | − else if (!kref_get_unless_zero(&ns->dev->kref)) | |
| 1973 | + else if (!kref_get_unless_zero(&ns->kref)) | |
| 1962 | 1974 | ret = -ENXIO; |
| 1963 | 1975 | spin_unlock(&dev_list_lock); |
| 1964 | 1976 | |
| 1965 | 1977 | return ret; |
| 1966 | 1978 | } |
| 1967 | 1979 | |
| 1968 | −static void nvme_free_dev(struct kref *kref); | |
| 1969 | − | |
| 1970 | 1980 | static void nvme_release(struct gendisk *disk, fmode_t mode) |
| 1971 | 1981 | { |
| 1972 | 1982 | struct nvme_ns *ns = disk->private_data; |
| 1973 | − struct nvme_dev *dev = ns->dev; | |
| 1974 | − | |
| 1975 | − kref_put(&dev->kref, nvme_free_dev); | |
| 1983 | + kref_put(&ns->kref, nvme_free_ns); | |
| 1976 | 1984 | } |
| 1977 | 1985 | |
| 1978 | 1986 | static int nvme_getgeo(struct block_device *bd, struct hd_geometry *geo) |
| @@ -2079,14 +2087,11 @@ static int nvme_kthread(void *data) · 100 unmodified lines | ||
| 2079 | 2087 | |
| 2080 | 2088 | if ((dev->subsystem && (csts & NVME_CSTS_NSSRO)) || |
| 2081 | 2089 | csts & NVME_CSTS_CFS) { |
| 2082 | − if (work_busy(&dev->reset_work)) | |
| 2083 | − continue; | |
| 2084 | − list_del_init(&dev->node); | |
| 2085 | − dev_warn(dev->dev, | |
| 2086 | − "Failed status: %x, reset controller\n", | |
| 2087 | − readl(&dev->bar->csts)); | |
| 2088 | − dev->reset_workfn = nvme_reset_failed_dev; | |
| 2089 | − queue_work(nvme_workq, &dev->reset_work); | |
| 2090 | + if (!__nvme_reset(dev)) { | |
| 2091 | + dev_warn(dev->dev, | |
| 2092 | + "Failed status: %x, reset controller\n", | |
| 2093 | + readl(&dev->bar->csts)); | |
| 2094 | + } | |
| 2090 | 2095 | continue; |
| 2091 | 2096 | } |
| 2092 | 2097 | for (i = 0; i < dev->queue_count; i++) { |
| @@ -2132,6 +2137,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid) · 39 unmodified lines | ||
| 2132 | 2137 | if (!disk) |
| 2133 | 2138 | goto out_free_queue; |
| 2134 | 2139 | |
| 2140 | + kref_init(&ns->kref); | |
| 2135 | 2141 | ns->ns_id = nsid; |
| 2136 | 2142 | ns->disk = disk; |
| 2137 | 2143 | ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */ |
| @@ -2168,6 +2174,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid) · 30 unmodified lines | ||
| 2168 | 2174 | if (nvme_revalidate_disk(ns->disk)) |
| 2169 | 2175 | goto out_free_disk; |
| 2170 | 2176 | |
| 2177 | + kref_get(&dev->kref); | |
| 2171 | 2178 | add_disk(ns->disk); |
| 2172 | 2179 | if (ns->ms) { |
| 2173 | 2180 | struct block_device *bd = bdget_disk(ns->disk, 0); |
| @@ -2190,6 +2197,13 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid) · 16 unmodified lines | ||
| 2190 | 2197 | kfree(ns); |
| 2191 | 2198 | } |
| 2192 | 2199 | |
| 2200 | +/* | |
| 2201 | + * Create I/O queues. Failing to create an I/O queue is not an issue, | |
| 2202 | + * we can continue with less than the desired amount of queues, and | |
| 2203 | + * even a controller without I/O queues an still be used to issue | |
| 2204 | + * admin commands. This might be useful to upgrade a buggy firmware | |
| 2205 | + * for example. | |
| 2206 | + */ | |
| 2193 | 2207 | static void nvme_create_io_queues(struct nvme_dev *dev) |
| 2194 | 2208 | { |
| 2195 | 2209 | unsigned i; |
| @@ -2199,8 +2213,10 @@ static void nvme_create_io_queues(struct nvme_dev *dev) · 3 unmodified lines | ||
| 2199 | 2213 | break; |
| 2200 | 2214 | |
| 2201 | 2215 | for (i = dev->online_queues; i <= dev->queue_count - 1; i++) |
| 2202 | − if (nvme_create_queue(dev->queues[i], i)) | |
| 2216 | + if (nvme_create_queue(dev->queues[i], i)) { | |
| 2217 | + nvme_free_queues(dev, i); | |
| 2203 | 2218 | break; |
| 2219 | + } | |
| 2204 | 2220 | } |
| 2205 | 2221 | |
| 2206 | 2222 | static int set_queue_count(struct nvme_dev *dev, int count) |
| @@ -2363,18 +2379,6 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) · 156 unmodified lines | ||
| 2363 | 2379 | return result; |
| 2364 | 2380 | } |
| 2365 | 2381 | |
| 2366 | −static void nvme_free_namespace(struct nvme_ns *ns) | |
| 2367 | −{ | |
| 2368 | − list_del(&ns->list); | |
| 2369 | − | |
| 2370 | − spin_lock(&dev_list_lock); | |
| 2371 | − ns->disk->private_data = NULL; | |
| 2372 | − spin_unlock(&dev_list_lock); | |
| 2373 | − | |
| 2374 | − put_disk(ns->disk); | |
| 2375 | − kfree(ns); | |
| 2376 | −} | |
| 2377 | − | |
| 2378 | 2382 | static int ns_cmp(void *priv, struct list_head *a, struct list_head *b) |
| 2379 | 2383 | { |
| 2380 | 2384 | struct nvme_ns *nsa = container_of(a, struct nvme_ns, list); |
| @@ -2416,7 +2420,9 @@ static void nvme_ns_remove(struct nvme_ns *ns) · 35 unmodified lines | ||
| 2416 | 2420 | if (kill || !blk_queue_dying(ns->queue)) { |
| 2417 | 2421 | blk_mq_abort_requeue_list(ns->queue); |
| 2418 | 2422 | blk_cleanup_queue(ns->queue); |
| 2419 | − } | |
| 2423 | + } | |
| 2424 | + list_del_init(&ns->list); | |
| 2425 | + kref_put(&ns->kref, nvme_free_ns); | |
| 2420 | 2426 | } |
| 2421 | 2427 | |
| 2422 | 2428 | static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn) |
| @@ -2427,18 +2433,14 @@ static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn) · 4 unmodified lines | ||
| 2427 | 2433 | for (i = 1; i <= nn; i++) { |
| 2428 | 2434 | ns = nvme_find_ns(dev, i); |
| 2429 | 2435 | if (ns) { |
| 2430 | − if (revalidate_disk(ns->disk)) { | |
| 2436 | + if (revalidate_disk(ns->disk)) | |
| 2431 | 2437 | nvme_ns_remove(ns); |
| 2432 | − nvme_free_namespace(ns); | |
| 2433 | − } | |
| 2434 | 2438 | } else |
| 2435 | 2439 | nvme_alloc_ns(dev, i); |
| 2436 | 2440 | } |
| 2437 | 2441 | list_for_each_entry_safe(ns, next, &dev->namespaces, list) { |
| 2438 | − if (ns->ns_id > nn) { | |
| 2442 | + if (ns->ns_id > nn) | |
| 2439 | 2443 | nvme_ns_remove(ns); |
| 2440 | − nvme_free_namespace(ns); | |
| 2441 | − } | |
| 2442 | 2444 | } |
| 2443 | 2445 | list_sort(NULL, &dev->namespaces, ns_cmp); |
| 2444 | 2446 | } |
| @@ -2828,9 +2830,9 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) · 383 unmodified lines | ||
| 2828 | 2830 | |
| 2829 | 2831 | static void nvme_dev_remove(struct nvme_dev *dev) |
| 2830 | 2832 | { |
| 2831 | − struct nvme_ns *ns; | |
| 2833 | + struct nvme_ns *ns, *next; | |
| 2832 | 2834 | |
| 2833 | − list_for_each_entry(ns, &dev->namespaces, list) | |
| 2835 | + list_for_each_entry_safe(ns, next, &dev->namespaces, list) | |
| 2834 | 2836 | nvme_ns_remove(ns); |
| 2835 | 2837 | } |
| 2836 | 2838 | |
| @@ -2886,21 +2888,12 @@ static void nvme_release_instance(struct nvme_dev *dev) · 49 unmodified lines | ||
| 2886 | 2888 | spin_unlock(&dev_list_lock); |
| 2887 | 2889 | } |
| 2888 | 2890 | |
| 2889 | −static void nvme_free_namespaces(struct nvme_dev *dev) | |
| 2890 | −{ | |
| 2891 | − struct nvme_ns *ns, *next; | |
| 2892 | − | |
| 2893 | − list_for_each_entry_safe(ns, next, &dev->namespaces, list) | |
| 2894 | − nvme_free_namespace(ns); | |
| 2895 | −} | |
| 2896 | − | |
| 2897 | 2891 | static void nvme_free_dev(struct kref *kref) |
| 2898 | 2892 | { |
| 2899 | 2893 | struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); |
| 2900 | 2894 | |
| 2901 | 2895 | put_device(dev->dev); |
| 2902 | 2896 | put_device(dev->device); |
| 2903 | − nvme_free_namespaces(dev); | |
| 2904 | 2897 | nvme_release_instance(dev); |
| 2905 | 2898 | if (dev->tagset.tags) |
| 2906 | 2899 | blk_mq_free_tag_set(&dev->tagset); |
| @@ -2974,14 +2967,15 @@ static const struct file_operations nvme_dev_fops = { · 67 unmodified lines | ||
| 2974 | 2967 | .compat_ioctl = nvme_dev_ioctl, |
| 2975 | 2968 | }; |
| 2976 | 2969 | |
| 2977 | −static int nvme_dev_start(struct nvme_dev *dev) | |
| 2970 | +static void nvme_probe_work(struct work_struct *work) | |
| 2978 | 2971 | { |
| 2979 | − int result; | |
| 2972 | + struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work); | |
| 2980 | 2973 | bool start_thread = false; |
| 2974 | + int result; | |
| 2981 | 2975 | |
| 2982 | 2976 | result = nvme_dev_map(dev); |
| 2983 | 2977 | if (result) |
| 2984 | − return result; | |
| 2978 | + goto out; | |
| 2985 | 2979 | |
| 2986 | 2980 | result = nvme_configure_admin_queue(dev); |
| 2987 | 2981 | if (result) |
| @@ -3016,7 +3010,20 @@ static int nvme_dev_start(struct nvme_dev *dev) · 28 unmodified lines | ||
| 3016 | 3010 | goto free_tags; |
| 3017 | 3011 | |
| 3018 | 3012 | dev->event_limit = 1; |
| 3019 | − return result; | |
| 3013 | + | |
| 3014 | + /* | |
| 3015 | + * Keep the controller around but remove all namespaces if we don't have | |
| 3016 | + * any working I/O queue. | |
| 3017 | + */ | |
| 3018 | + if (dev->online_queues < 2) { | |
| 3019 | + dev_warn(dev->dev, "IO queues not created\n"); | |
| 3020 | + nvme_dev_remove(dev); | |
| 3021 | + } else { | |
| 3022 | + nvme_unfreeze_queues(dev); | |
| 3023 | + nvme_dev_add(dev); | |
| 3024 | + } | |
| 3025 | + | |
| 3026 | + return; | |
| 3020 | 3027 | |
| 3021 | 3028 | free_tags: |
| 3022 | 3029 | nvme_dev_remove_admin(dev); |
| @@ -3028,7 +3035,9 @@ static int nvme_dev_start(struct nvme_dev *dev) · 5 unmodified lines | ||
| 3028 | 3035 | nvme_dev_list_remove(dev); |
| 3029 | 3036 | unmap: |
| 3030 | 3037 | nvme_dev_unmap(dev); |
| 3031 | − return result; | |
| 3038 | + out: | |
| 3039 | + if (!work_busy(&dev->reset_work)) | |
| 3040 | + nvme_dead_ctrl(dev); | |
| 3032 | 3041 | } |
| 3033 | 3042 | |
| 3034 | 3043 | static int nvme_remove_dead_ctrl(void *arg) |
| @@ -3042,33 +3051,6 @@ static int nvme_remove_dead_ctrl(void *arg) · 7 unmodified lines | ||
| 3042 | 3051 | return 0; |
| 3043 | 3052 | } |
| 3044 | 3053 | |
| 3045 | −static void nvme_remove_disks(struct work_struct *ws) | |
| 3046 | −{ | |
| 3047 | − struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); | |
| 3048 | − | |
| 3049 | − nvme_free_queues(dev, 1); | |
| 3050 | − nvme_dev_remove(dev); | |
| 3051 | −} | |
| 3052 | − | |
| 3053 | −static int nvme_dev_resume(struct nvme_dev *dev) | |
| 3054 | −{ | |
| 3055 | − int ret; | |
| 3056 | − | |
| 3057 | − ret = nvme_dev_start(dev); | |
| 3058 | − if (ret) | |
| 3059 | − return ret; | |
| 3060 | − if (dev->online_queues < 2) { | |
| 3061 | − spin_lock(&dev_list_lock); | |
| 3062 | − dev->reset_workfn = nvme_remove_disks; | |
| 3063 | − queue_work(nvme_workq, &dev->reset_work); | |
| 3064 | − spin_unlock(&dev_list_lock); | |
| 3065 | − } else { | |
| 3066 | − nvme_unfreeze_queues(dev); | |
| 3067 | − nvme_dev_add(dev); | |
| 3068 | − } | |
| 3069 | − return 0; | |
| 3070 | −} | |
| 3071 | − | |
| 3072 | 3054 | static void nvme_dead_ctrl(struct nvme_dev *dev) |
| 3073 | 3055 | { |
| 3074 | 3056 | dev_warn(dev->dev, "Device failed to resume\n"); |
| @@ -3081,8 +3063,9 @@ static void nvme_dead_ctrl(struct nvme_dev *dev) · 6 unmodified lines | ||
| 3081 | 3063 | } |
| 3082 | 3064 | } |
| 3083 | 3065 | |
| 3084 | −static void nvme_dev_reset(struct nvme_dev *dev) | |
| 3066 | +static void nvme_reset_work(struct work_struct *ws) | |
| 3085 | 3067 | { |
| 3068 | + struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); | |
| 3086 | 3069 | bool in_probe = work_busy(&dev->probe_work); |
| 3087 | 3070 | |
| 3088 | 3071 | nvme_dev_shutdown(dev); |
| @@ -3102,31 +3085,24 @@ static void nvme_dev_reset(struct nvme_dev *dev) · 13 unmodified lines | ||
| 3102 | 3085 | schedule_work(&dev->probe_work); |
| 3103 | 3086 | } |
| 3104 | 3087 | |
| 3105 | −static void nvme_reset_failed_dev(struct work_struct *ws) | |
| 3106 | −{ | |
| 3107 | − struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); | |
| 3108 | − nvme_dev_reset(dev); | |
| 3109 | −} | |
| 3110 | − | |
| 3111 | −static void nvme_reset_workfn(struct work_struct *work) | |
| 3088 | +static int __nvme_reset(struct nvme_dev *dev) | |
| 3112 | 3089 | { |
| 3113 | − struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work); | |
| 3114 | − dev->reset_workfn(work); | |
| 3090 | + if (work_pending(&dev->reset_work)) | |
| 3091 | + return -EBUSY; | |
| 3092 | + list_del_init(&dev->node); | |
| 3093 | + queue_work(nvme_workq, &dev->reset_work); | |
| 3094 | + return 0; | |
| 3115 | 3095 | } |
| 3116 | 3096 | |
| 3117 | 3097 | static int nvme_reset(struct nvme_dev *dev) |
| 3118 | 3098 | { |
| 3119 | − int ret = -EBUSY; | |
| 3099 | + int ret; | |
| 3120 | 3100 | |
| 3121 | 3101 | if (!dev->admin_q || blk_queue_dying(dev->admin_q)) |
| 3122 | 3102 | return -ENODEV; |
| 3123 | 3103 | |
| 3124 | 3104 | spin_lock(&dev_list_lock); |
| 3125 | − if (!work_pending(&dev->reset_work)) { | |
| 3126 | − dev->reset_workfn = nvme_reset_failed_dev; | |
| 3127 | − queue_work(nvme_workq, &dev->reset_work); | |
| 3128 | − ret = 0; | |
| 3129 | − } | |
| 3105 | + ret = __nvme_reset(dev); | |
| 3130 | 3106 | spin_unlock(&dev_list_lock); |
| 3131 | 3107 | |
| 3132 | 3108 | if (!ret) { |
| @@ -3153,7 +3129,6 @@ static ssize_t nvme_sysfs_reset(struct device *dev, · 20 unmodified lines | ||
| 3153 | 3129 | } |
| 3154 | 3130 | static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset); |
| 3155 | 3131 | |
| 3156 | −static void nvme_async_probe(struct work_struct *work); | |
| 3157 | 3132 | static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 3158 | 3133 | { |
| 3159 | 3134 | int node, result = -ENOMEM; |
| @@ -3176,8 +3151,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 16 unmodified lines | ||
| 3176 | 3151 | goto free; |
| 3177 | 3152 | |
| 3178 | 3153 | INIT_LIST_HEAD(&dev->namespaces); |
| 3179 | − dev->reset_workfn = nvme_reset_failed_dev; | |
| 3180 | − INIT_WORK(&dev->reset_work, nvme_reset_workfn); | |
| 3154 | + INIT_WORK(&dev->reset_work, nvme_reset_work); | |
| 3181 | 3155 | dev->dev = get_device(&pdev->dev); |
| 3182 | 3156 | pci_set_drvdata(pdev, dev); |
| 3183 | 3157 | result = nvme_set_instance(dev); |
| @@ -3205,7 +3179,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 21 unmodified lines | ||
| 3205 | 3179 | |
| 3206 | 3180 | INIT_LIST_HEAD(&dev->node); |
| 3207 | 3181 | INIT_WORK(&dev->scan_work, nvme_dev_scan); |
| 3208 | − INIT_WORK(&dev->probe_work, nvme_async_probe); | |
| 3182 | + INIT_WORK(&dev->probe_work, nvme_probe_work); | |
| 3209 | 3183 | schedule_work(&dev->probe_work); |
| 3210 | 3184 | return 0; |
| 3211 | 3185 | |
| @@ -3225,14 +3199,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 13 unmodified lines | ||
| 3225 | 3199 | return result; |
| 3226 | 3200 | } |
| 3227 | 3201 | |
| 3228 | −static void nvme_async_probe(struct work_struct *work) | |
| 3229 | −{ | |
| 3230 | − struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work); | |
| 3231 | − | |
| 3232 | − if (nvme_dev_resume(dev) && !work_busy(&dev->reset_work)) | |
| 3233 | − nvme_dead_ctrl(dev); | |
| 3234 | −} | |
| 3235 | − | |
| 3236 | 3202 | static void nvme_reset_notify(struct pci_dev *pdev, bool prepare) |
| 3237 | 3203 | { |
| 3238 | 3204 | struct nvme_dev *dev = pci_get_drvdata(pdev); |
| @@ -3240,7 +3206,7 @@ static void nvme_reset_notify(struct pci_dev *pdev, bool prepare) · 1 unmodified line | ||
| 3240 | 3206 | if (prepare) |
| 3241 | 3207 | nvme_dev_shutdown(dev); |
| 3242 | 3208 | else |
| 3243 | − nvme_dev_resume(dev); | |
| 3209 | + schedule_work(&dev->probe_work); | |
| 3244 | 3210 | } |
| 3245 | 3211 | |
| 3246 | 3212 | static void nvme_shutdown(struct pci_dev *pdev) |
| @@ -3294,10 +3260,7 @@ static int nvme_resume(struct device *dev) · 47 unmodified lines | ||
| 3294 | 3260 | struct pci_dev *pdev = to_pci_dev(dev); |
| 3295 | 3261 | struct nvme_dev *ndev = pci_get_drvdata(pdev); |
| 3296 | 3262 | |
| 3297 | − if (nvme_dev_resume(ndev) && !work_busy(&ndev->reset_work)) { | |
| 3298 | − ndev->reset_workfn = nvme_reset_failed_dev; | |
| 3299 | − queue_work(nvme_workq, &ndev->reset_work); | |
| 3300 | − } | |
| 3263 | + schedule_work(&ndev->probe_work); | |
| 3301 | 3264 | return 0; |
| 3302 | 3265 | } |
| 3303 | 3266 | #endif |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | * each command is translated. |
| 18 | 18 | */ |
| 19 | 19 | |
| 20 | −#include <linux/nvme.h> | |
| 21 | 20 | #include <linux/bio.h> |
| 22 | 21 | #include <linux/bitops.h> |
| 23 | 22 | #include <linux/blkdev.h> |
| @@ -45,6 +44,7 @@ · 21 unmodified lines | ||
| 45 | 44 | #include <scsi/sg.h> |
| 46 | 45 | #include <scsi/scsi.h> |
| 47 | 46 | |
| 47 | +#include "nvme.h" | |
| 48 | 48 | |
| 49 | 49 | static int sg_version_num = 30534; /* 2 digits for each component */ |
| 50 | 50 | |
| @@ -15,10 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #ifndef _LINUX_NVME_H |
| 16 | 16 | #define _LINUX_NVME_H |
| 17 | 17 | |
| 18 | −#include <uapi/linux/nvme.h> | |
| 19 | −#include <linux/pci.h> | |
| 20 | −#include <linux/kref.h> | |
| 21 | −#include <linux/blk-mq.h> | |
| 18 | +#include <linux/types.h> | |
| 22 | 19 | |
| 23 | 20 | struct nvme_bar { |
| 24 | 21 | __u64 cap; /* Controller Capabilities */ |
| @@ -76,115 +73,528 @@ enum { · 51 unmodified lines | ||
| 76 | 73 | NVME_CSTS_SHST_MASK = 3 << 2, |
| 77 | 74 | }; |
| 78 | 75 | |
| 79 | −extern unsigned char nvme_io_timeout; | |
| 80 | −#define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) | |
| 76 | +struct nvme_id_power_state { | |
| 77 | + __le16 max_power; /* centiwatts */ | |
| 78 | + __u8 rsvd2; | |
| 79 | + __u8 flags; | |
| 80 | + __le32 entry_lat; /* microseconds */ | |
| 81 | + __le32 exit_lat; /* microseconds */ | |
| 82 | + __u8 read_tput; | |
| 83 | + __u8 read_lat; | |
| 84 | + __u8 write_tput; | |
| 85 | + __u8 write_lat; | |
| 86 | + __le16 idle_power; | |
| 87 | + __u8 idle_scale; | |
| 88 | + __u8 rsvd19; | |
| 89 | + __le16 active_power; | |
| 90 | + __u8 active_work_scale; | |
| 91 | + __u8 rsvd23[9]; | |
| 92 | +}; | |
| 81 | 93 | |
| 82 | −/* | |
| 83 | − * Represents an NVM Express device. Each nvme_dev is a PCI function. | |
| 84 | − */ | |
| 85 | −struct nvme_dev { | |
| 86 | − struct list_head node; | |
| 87 | − struct nvme_queue **queues; | |
| 88 | − struct request_queue *admin_q; | |
| 89 | − struct blk_mq_tag_set tagset; | |
| 90 | − struct blk_mq_tag_set admin_tagset; | |
| 91 | − u32 __iomem *dbs; | |
| 92 | − struct device *dev; | |
| 93 | − struct dma_pool *prp_page_pool; | |
| 94 | − struct dma_pool *prp_small_pool; | |
| 95 | − int instance; | |
| 96 | − unsigned queue_count; | |
| 97 | − unsigned online_queues; | |
| 98 | − unsigned max_qid; | |
| 99 | − int q_depth; | |
| 100 | − u32 db_stride; | |
| 101 | − u32 ctrl_config; | |
| 102 | − struct msix_entry *entry; | |
| 103 | − struct nvme_bar __iomem *bar; | |
| 104 | − struct list_head namespaces; | |
| 105 | − struct kref kref; | |
| 106 | − struct device *device; | |
| 107 | − work_func_t reset_workfn; | |
| 108 | − struct work_struct reset_work; | |
| 109 | − struct work_struct probe_work; | |
| 110 | − struct work_struct scan_work; | |
| 111 | − char name[12]; | |
| 112 | − char serial[20]; | |
| 113 | − char model[40]; | |
| 114 | − char firmware_rev[8]; | |
| 115 | − bool subsystem; | |
| 116 | − u32 max_hw_sectors; | |
| 117 | − u32 stripe_size; | |
| 118 | − u32 page_size; | |
| 119 | − void __iomem *cmb; | |
| 120 | − dma_addr_t cmb_dma_addr; | |
| 121 | − u64 cmb_size; | |
| 122 | − u32 cmbsz; | |
| 123 | − u16 oncs; | |
| 124 | − u16 abort_limit; | |
| 125 | − u8 event_limit; | |
| 126 | − u8 vwc; | |
| 94 | +enum { | |
| 95 | + NVME_PS_FLAGS_MAX_POWER_SCALE = 1 << 0, | |
| 96 | + NVME_PS_FLAGS_NON_OP_STATE = 1 << 1, | |
| 127 | 97 | }; |
| 128 | 98 | |
| 129 | −/* | |
| 130 | − * An NVM Express namespace is equivalent to a SCSI LUN | |
| 131 | − */ | |
| 132 | −struct nvme_ns { | |
| 133 | − struct list_head list; | |
| 99 | +struct nvme_id_ctrl { | |
| 100 | + __le16 vid; | |
| 101 | + __le16 ssvid; | |
| 102 | + char sn[20]; | |
| 103 | + char mn[40]; | |
| 104 | + char fr[8]; | |
| 105 | + __u8 rab; | |
| 106 | + __u8 ieee[3]; | |
| 107 | + __u8 mic; | |
| 108 | + __u8 mdts; | |
| 109 | + __le16 cntlid; | |
| 110 | + __le32 ver; | |
| 111 | + __u8 rsvd84[172]; | |
| 112 | + __le16 oacs; | |
| 113 | + __u8 acl; | |
| 114 | + __u8 aerl; | |
| 115 | + __u8 frmw; | |
| 116 | + __u8 lpa; | |
| 117 | + __u8 elpe; | |
| 118 | + __u8 npss; | |
| 119 | + __u8 avscc; | |
| 120 | + __u8 apsta; | |
| 121 | + __le16 wctemp; | |
| 122 | + __le16 cctemp; | |
| 123 | + __u8 rsvd270[242]; | |
| 124 | + __u8 sqes; | |
| 125 | + __u8 cqes; | |
| 126 | + __u8 rsvd514[2]; | |
| 127 | + __le32 nn; | |
| 128 | + __le16 oncs; | |
| 129 | + __le16 fuses; | |
| 130 | + __u8 fna; | |
| 131 | + __u8 vwc; | |
| 132 | + __le16 awun; | |
| 133 | + __le16 awupf; | |
| 134 | + __u8 nvscc; | |
| 135 | + __u8 rsvd531; | |
| 136 | + __le16 acwu; | |
| 137 | + __u8 rsvd534[2]; | |
| 138 | + __le32 sgls; | |
| 139 | + __u8 rsvd540[1508]; | |
| 140 | + struct nvme_id_power_state psd[32]; | |
| 141 | + __u8 vs[1024]; | |
| 142 | +}; | |
| 134 | 143 | |
| 135 | − struct nvme_dev *dev; | |
| 136 | − struct request_queue *queue; | |
| 137 | − struct gendisk *disk; | |
| 144 | +enum { | |
| 145 | + NVME_CTRL_ONCS_COMPARE = 1 << 0, | |
| 146 | + NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1, | |
| 147 | + NVME_CTRL_ONCS_DSM = 1 << 2, | |
| 148 | + NVME_CTRL_VWC_PRESENT = 1 << 0, | |
| 149 | +}; | |
| 138 | 150 | |
| 139 | − unsigned ns_id; | |
| 140 | − int lba_shift; | |
| 141 | − u16 ms; | |
| 142 | − bool ext; | |
| 143 | − u8 pi_type; | |
| 144 | − u64 mode_select_num_blocks; | |
| 145 | − u32 mode_select_block_len; | |
| 151 | +struct nvme_lbaf { | |
| 152 | + __le16 ms; | |
| 153 | + __u8 ds; | |
| 154 | + __u8 rp; | |
| 146 | 155 | }; |
| 147 | 156 | |
| 148 | −/* | |
| 149 | − * The nvme_iod describes the data in an I/O, including the list of PRP | |
| 150 | − * entries. You can't see it in this data structure because C doesn't let | |
| 151 | − * me express that. Use nvme_alloc_iod to ensure there's enough space | |
| 152 | − * allocated to store the PRP list. | |
| 153 | − */ | |
| 154 | −struct nvme_iod { | |
| 155 | − unsigned long private; /* For the use of the submitter of the I/O */ | |
| 156 | − int npages; /* In the PRP list. 0 means small pool in use */ | |
| 157 | − int offset; /* Of PRP list */ | |
| 158 | − int nents; /* Used in scatterlist */ | |
| 159 | − int length; /* Of data, in bytes */ | |
| 160 | − dma_addr_t first_dma; | |
| 161 | − struct scatterlist meta_sg[1]; /* metadata requires single contiguous buffer */ | |
| 162 | − struct scatterlist sg[0]; | |
| 163 | −}; | |
| 164 | − | |
| 165 | −static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector) | |
| 166 | −{ | |
| 167 | − return (sector >> (ns->lba_shift - 9)); | |
| 168 | −} | |
| 169 | − | |
| 170 | −int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, | |
| 171 | − void *buf, unsigned bufflen); | |
| 172 | −int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, | |
| 173 | − void *buffer, void __user *ubuffer, unsigned bufflen, | |
| 174 | − u32 *result, unsigned timeout); | |
| 175 | −int nvme_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl **id); | |
| 176 | −int nvme_identify_ns(struct nvme_dev *dev, unsigned nsid, | |
| 177 | − struct nvme_id_ns **id); | |
| 178 | −int nvme_get_log_page(struct nvme_dev *dev, struct nvme_smart_log **log); | |
| 179 | −int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, | |
| 180 | − dma_addr_t dma_addr, u32 *result); | |
| 181 | −int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, | |
| 182 | − dma_addr_t dma_addr, u32 *result); | |
| 183 | − | |
| 184 | −struct sg_io_hdr; | |
| 185 | − | |
| 186 | −int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr); | |
| 187 | −int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg); | |
| 188 | −int nvme_sg_get_version_num(int __user *ip); | |
| 157 | +struct nvme_id_ns { | |
| 158 | + __le64 nsze; | |
| 159 | + __le64 ncap; | |
| 160 | + __le64 nuse; | |
| 161 | + __u8 nsfeat; | |
| 162 | + __u8 nlbaf; | |
| 163 | + __u8 flbas; | |
| 164 | + __u8 mc; | |
| 165 | + __u8 dpc; | |
| 166 | + __u8 dps; | |
| 167 | + __u8 nmic; | |
| 168 | + __u8 rescap; | |
| 169 | + __u8 fpi; | |
| 170 | + __u8 rsvd33; | |
| 171 | + __le16 nawun; | |
| 172 | + __le16 nawupf; | |
| 173 | + __le16 nacwu; | |
| 174 | + __le16 nabsn; | |
| 175 | + __le16 nabo; | |
| 176 | + __le16 nabspf; | |
| 177 | + __u16 rsvd46; | |
| 178 | + __le64 nvmcap[2]; | |
| 179 | + __u8 rsvd64[40]; | |
| 180 | + __u8 nguid[16]; | |
| 181 | + __u8 eui64[8]; | |
| 182 | + struct nvme_lbaf lbaf[16]; | |
| 183 | + __u8 rsvd192[192]; | |
| 184 | + __u8 vs[3712]; | |
| 185 | +}; | |
| 186 | + | |
| 187 | +enum { | |
| 188 | + NVME_NS_FEAT_THIN = 1 << 0, | |
| 189 | + NVME_NS_FLBAS_LBA_MASK = 0xf, | |
| 190 | + NVME_NS_FLBAS_META_EXT = 0x10, | |
| 191 | + NVME_LBAF_RP_BEST = 0, | |
| 192 | + NVME_LBAF_RP_BETTER = 1, | |
| 193 | + NVME_LBAF_RP_GOOD = 2, | |
| 194 | + NVME_LBAF_RP_DEGRADED = 3, | |
| 195 | + NVME_NS_DPC_PI_LAST = 1 << 4, | |
| 196 | + NVME_NS_DPC_PI_FIRST = 1 << 3, | |
| 197 | + NVME_NS_DPC_PI_TYPE3 = 1 << 2, | |
| 198 | + NVME_NS_DPC_PI_TYPE2 = 1 << 1, | |
| 199 | + NVME_NS_DPC_PI_TYPE1 = 1 << 0, | |
| 200 | + NVME_NS_DPS_PI_FIRST = 1 << 3, | |
| 201 | + NVME_NS_DPS_PI_MASK = 0x7, | |
| 202 | + NVME_NS_DPS_PI_TYPE1 = 1, | |
| 203 | + NVME_NS_DPS_PI_TYPE2 = 2, | |
| 204 | + NVME_NS_DPS_PI_TYPE3 = 3, | |
| 205 | +}; | |
| 206 | + | |
| 207 | +struct nvme_smart_log { | |
| 208 | + __u8 critical_warning; | |
| 209 | + __u8 temperature[2]; | |
| 210 | + __u8 avail_spare; | |
| 211 | + __u8 spare_thresh; | |
| 212 | + __u8 percent_used; | |
| 213 | + __u8 rsvd6[26]; | |
| 214 | + __u8 data_units_read[16]; | |
| 215 | + __u8 data_units_written[16]; | |
| 216 | + __u8 host_reads[16]; | |
| 217 | + __u8 host_writes[16]; | |
| 218 | + __u8 ctrl_busy_time[16]; | |
| 219 | + __u8 power_cycles[16]; | |
| 220 | + __u8 power_on_hours[16]; | |
| 221 | + __u8 unsafe_shutdowns[16]; | |
| 222 | + __u8 media_errors[16]; | |
| 223 | + __u8 num_err_log_entries[16]; | |
| 224 | + __le32 warning_temp_time; | |
| 225 | + __le32 critical_comp_time; | |
| 226 | + __le16 temp_sensor[8]; | |
| 227 | + __u8 rsvd216[296]; | |
| 228 | +}; | |
| 229 | + | |
| 230 | +enum { | |
| 231 | + NVME_SMART_CRIT_SPARE = 1 << 0, | |
| 232 | + NVME_SMART_CRIT_TEMPERATURE = 1 << 1, | |
| 233 | + NVME_SMART_CRIT_RELIABILITY = 1 << 2, | |
| 234 | + NVME_SMART_CRIT_MEDIA = 1 << 3, | |
| 235 | + NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4, | |
| 236 | +}; | |
| 237 | + | |
| 238 | +enum { | |
| 239 | + NVME_AER_NOTICE_NS_CHANGED = 0x0002, | |
| 240 | +}; | |
| 241 | + | |
| 242 | +struct nvme_lba_range_type { | |
| 243 | + __u8 type; | |
| 244 | + __u8 attributes; | |
| 245 | + __u8 rsvd2[14]; | |
| 246 | + __u64 slba; | |
| 247 | + __u64 nlb; | |
| 248 | + __u8 guid[16]; | |
| 249 | + __u8 rsvd48[16]; | |
| 250 | +}; | |
| 251 | + | |
| 252 | +enum { | |
| 253 | + NVME_LBART_TYPE_FS = 0x01, | |
| 254 | + NVME_LBART_TYPE_RAID = 0x02, | |
| 255 | + NVME_LBART_TYPE_CACHE = 0x03, | |
| 256 | + NVME_LBART_TYPE_SWAP = 0x04, | |
| 257 | + | |
| 258 | + NVME_LBART_ATTRIB_TEMP = 1 << 0, | |
| 259 | + NVME_LBART_ATTRIB_HIDE = 1 << 1, | |
| 260 | +}; | |
| 261 | + | |
| 262 | +struct nvme_reservation_status { | |
| 263 | + __le32 gen; | |
| 264 | + __u8 rtype; | |
| 265 | + __u8 regctl[2]; | |
| 266 | + __u8 resv5[2]; | |
| 267 | + __u8 ptpls; | |
| 268 | + __u8 resv10[13]; | |
| 269 | + struct { | |
| 270 | + __le16 cntlid; | |
| 271 | + __u8 rcsts; | |
| 272 | + __u8 resv3[5]; | |
| 273 | + __le64 hostid; | |
| 274 | + __le64 rkey; | |
| 275 | + } regctl_ds[]; | |
| 276 | +}; | |
| 277 | + | |
| 278 | +/* I/O commands */ | |
| 279 | + | |
| 280 | +enum nvme_opcode { | |
| 281 | + nvme_cmd_flush = 0x00, | |
| 282 | + nvme_cmd_write = 0x01, | |
| 283 | + nvme_cmd_read = 0x02, | |
| 284 | + nvme_cmd_write_uncor = 0x04, | |
| 285 | + nvme_cmd_compare = 0x05, | |
| 286 | + nvme_cmd_write_zeroes = 0x08, | |
| 287 | + nvme_cmd_dsm = 0x09, | |
| 288 | + nvme_cmd_resv_register = 0x0d, | |
| 289 | + nvme_cmd_resv_report = 0x0e, | |
| 290 | + nvme_cmd_resv_acquire = 0x11, | |
| 291 | + nvme_cmd_resv_release = 0x15, | |
| 292 | +}; | |
| 293 | + | |
| 294 | +struct nvme_common_command { | |
| 295 | + __u8 opcode; | |
| 296 | + __u8 flags; | |
| 297 | + __u16 command_id; | |
| 298 | + __le32 nsid; | |
| 299 | + __le32 cdw2[2]; | |
| 300 | + __le64 metadata; | |
| 301 | + __le64 prp1; | |
| 302 | + __le64 prp2; | |
| 303 | + __le32 cdw10[6]; | |
| 304 | +}; | |
| 305 | + | |
| 306 | +struct nvme_rw_command { | |
| 307 | + __u8 opcode; | |
| 308 | + __u8 flags; | |
| 309 | + __u16 command_id; | |
| 310 | + __le32 nsid; | |
| 311 | + __u64 rsvd2; | |
| 312 | + __le64 metadata; | |
| 313 | + __le64 prp1; | |
| 314 | + __le64 prp2; | |
| 315 | + __le64 slba; | |
| 316 | + __le16 length; | |
| 317 | + __le16 control; | |
| 318 | + __le32 dsmgmt; | |
| 319 | + __le32 reftag; | |
| 320 | + __le16 apptag; | |
| 321 | + __le16 appmask; | |
| 322 | +}; | |
| 323 | + | |
| 324 | +enum { | |
| 325 | + NVME_RW_LR = 1 << 15, | |
| 326 | + NVME_RW_FUA = 1 << 14, | |
| 327 | + NVME_RW_DSM_FREQ_UNSPEC = 0, | |
| 328 | + NVME_RW_DSM_FREQ_TYPICAL = 1, | |
| 329 | + NVME_RW_DSM_FREQ_RARE = 2, | |
| 330 | + NVME_RW_DSM_FREQ_READS = 3, | |
| 331 | + NVME_RW_DSM_FREQ_WRITES = 4, | |
| 332 | + NVME_RW_DSM_FREQ_RW = 5, | |
| 333 | + NVME_RW_DSM_FREQ_ONCE = 6, | |
| 334 | + NVME_RW_DSM_FREQ_PREFETCH = 7, | |
| 335 | + NVME_RW_DSM_FREQ_TEMP = 8, | |
| 336 | + NVME_RW_DSM_LATENCY_NONE = 0 << 4, | |
| 337 | + NVME_RW_DSM_LATENCY_IDLE = 1 << 4, | |
| 338 | + NVME_RW_DSM_LATENCY_NORM = 2 << 4, | |
| 339 | + NVME_RW_DSM_LATENCY_LOW = 3 << 4, | |
| 340 | + NVME_RW_DSM_SEQ_REQ = 1 << 6, | |
| 341 | + NVME_RW_DSM_COMPRESSED = 1 << 7, | |
| 342 | + NVME_RW_PRINFO_PRCHK_REF = 1 << 10, | |
| 343 | + NVME_RW_PRINFO_PRCHK_APP = 1 << 11, | |
| 344 | + NVME_RW_PRINFO_PRCHK_GUARD = 1 << 12, | |
| 345 | + NVME_RW_PRINFO_PRACT = 1 << 13, | |
| 346 | +}; | |
| 347 | + | |
| 348 | +struct nvme_dsm_cmd { | |
| 349 | + __u8 opcode; | |
| 350 | + __u8 flags; | |
| 351 | + __u16 command_id; | |
| 352 | + __le32 nsid; | |
| 353 | + __u64 rsvd2[2]; | |
| 354 | + __le64 prp1; | |
| 355 | + __le64 prp2; | |
| 356 | + __le32 nr; | |
| 357 | + __le32 attributes; | |
| 358 | + __u32 rsvd12[4]; | |
| 359 | +}; | |
| 360 | + | |
| 361 | +enum { | |
| 362 | + NVME_DSMGMT_IDR = 1 << 0, | |
| 363 | + NVME_DSMGMT_IDW = 1 << 1, | |
| 364 | + NVME_DSMGMT_AD = 1 << 2, | |
| 365 | +}; | |
| 366 | + | |
| 367 | +struct nvme_dsm_range { | |
| 368 | + __le32 cattr; | |
| 369 | + __le32 nlb; | |
| 370 | + __le64 slba; | |
| 371 | +}; | |
| 372 | + | |
| 373 | +/* Admin commands */ | |
| 374 | + | |
| 375 | +enum nvme_admin_opcode { | |
| 376 | + nvme_admin_delete_sq = 0x00, | |
| 377 | + nvme_admin_create_sq = 0x01, | |
| 378 | + nvme_admin_get_log_page = 0x02, | |
| 379 | + nvme_admin_delete_cq = 0x04, | |
| 380 | + nvme_admin_create_cq = 0x05, | |
| 381 | + nvme_admin_identify = 0x06, | |
| 382 | + nvme_admin_abort_cmd = 0x08, | |
| 383 | + nvme_admin_set_features = 0x09, | |
| 384 | + nvme_admin_get_features = 0x0a, | |
| 385 | + nvme_admin_async_event = 0x0c, | |
| 386 | + nvme_admin_activate_fw = 0x10, | |
| 387 | + nvme_admin_download_fw = 0x11, | |
| 388 | + nvme_admin_format_nvm = 0x80, | |
| 389 | + nvme_admin_security_send = 0x81, | |
| 390 | + nvme_admin_security_recv = 0x82, | |
| 391 | +}; | |
| 392 | + | |
| 393 | +enum { | |
| 394 | + NVME_QUEUE_PHYS_CONTIG = (1 << 0), | |
| 395 | + NVME_CQ_IRQ_ENABLED = (1 << 1), | |
| 396 | + NVME_SQ_PRIO_URGENT = (0 << 1), | |
| 397 | + NVME_SQ_PRIO_HIGH = (1 << 1), | |
| 398 | + NVME_SQ_PRIO_MEDIUM = (2 << 1), | |
| 399 | + NVME_SQ_PRIO_LOW = (3 << 1), | |
| 400 | + NVME_FEAT_ARBITRATION = 0x01, | |
| 401 | + NVME_FEAT_POWER_MGMT = 0x02, | |
| 402 | + NVME_FEAT_LBA_RANGE = 0x03, | |
| 403 | + NVME_FEAT_TEMP_THRESH = 0x04, | |
| 404 | + NVME_FEAT_ERR_RECOVERY = 0x05, | |
| 405 | + NVME_FEAT_VOLATILE_WC = 0x06, | |
| 406 | + NVME_FEAT_NUM_QUEUES = 0x07, | |
| 407 | + NVME_FEAT_IRQ_COALESCE = 0x08, | |
| 408 | + NVME_FEAT_IRQ_CONFIG = 0x09, | |
| 409 | + NVME_FEAT_WRITE_ATOMIC = 0x0a, | |
| 410 | + NVME_FEAT_ASYNC_EVENT = 0x0b, | |
| 411 | + NVME_FEAT_AUTO_PST = 0x0c, | |
| 412 | + NVME_FEAT_SW_PROGRESS = 0x80, | |
| 413 | + NVME_FEAT_HOST_ID = 0x81, | |
| 414 | + NVME_FEAT_RESV_MASK = 0x82, | |
| 415 | + NVME_FEAT_RESV_PERSIST = 0x83, | |
| 416 | + NVME_LOG_ERROR = 0x01, | |
| 417 | + NVME_LOG_SMART = 0x02, | |
| 418 | + NVME_LOG_FW_SLOT = 0x03, | |
| 419 | + NVME_LOG_RESERVATION = 0x80, | |
| 420 | + NVME_FWACT_REPL = (0 << 3), | |
| 421 | + NVME_FWACT_REPL_ACTV = (1 << 3), | |
| 422 | + NVME_FWACT_ACTV = (2 << 3), | |
| 423 | +}; | |
| 424 | + | |
| 425 | +struct nvme_identify { | |
| 426 | + __u8 opcode; | |
| 427 | + __u8 flags; | |
| 428 | + __u16 command_id; | |
| 429 | + __le32 nsid; | |
| 430 | + __u64 rsvd2[2]; | |
| 431 | + __le64 prp1; | |
| 432 | + __le64 prp2; | |
| 433 | + __le32 cns; | |
| 434 | + __u32 rsvd11[5]; | |
| 435 | +}; | |
| 436 | + | |
| 437 | +struct nvme_features { | |
| 438 | + __u8 opcode; | |
| 439 | + __u8 flags; | |
| 440 | + __u16 command_id; | |
| 441 | + __le32 nsid; | |
| 442 | + __u64 rsvd2[2]; | |
| 443 | + __le64 prp1; | |
| 444 | + __le64 prp2; | |
| 445 | + __le32 fid; | |
| 446 | + __le32 dword11; | |
| 447 | + __u32 rsvd12[4]; | |
| 448 | +}; | |
| 449 | + | |
| 450 | +struct nvme_create_cq { | |
| 451 | + __u8 opcode; | |
| 452 | + __u8 flags; | |
| 453 | + __u16 command_id; | |
| 454 | + __u32 rsvd1[5]; | |
| 455 | + __le64 prp1; | |
| 456 | + __u64 rsvd8; | |
| 457 | + __le16 cqid; | |
| 458 | + __le16 qsize; | |
| 459 | + __le16 cq_flags; | |
| 460 | + __le16 irq_vector; | |
| 461 | + __u32 rsvd12[4]; | |
| 462 | +}; | |
| 463 | + | |
| 464 | +struct nvme_create_sq { | |
| 465 | + __u8 opcode; | |
| 466 | + __u8 flags; | |
| 467 | + __u16 command_id; | |
| 468 | + __u32 rsvd1[5]; | |
| 469 | + __le64 prp1; | |
| 470 | + __u64 rsvd8; | |
| 471 | + __le16 sqid; | |
| 472 | + __le16 qsize; | |
| 473 | + __le16 sq_flags; | |
| 474 | + __le16 cqid; | |
| 475 | + __u32 rsvd12[4]; | |
| 476 | +}; | |
| 477 | + | |
| 478 | +struct nvme_delete_queue { | |
| 479 | + __u8 opcode; | |
| 480 | + __u8 flags; | |
| 481 | + __u16 command_id; | |
| 482 | + __u32 rsvd1[9]; | |
| 483 | + __le16 qid; | |
| 484 | + __u16 rsvd10; | |
| 485 | + __u32 rsvd11[5]; | |
| 486 | +}; | |
| 487 | + | |
| 488 | +struct nvme_abort_cmd { | |
| 489 | + __u8 opcode; | |
| 490 | + __u8 flags; | |
| 491 | + __u16 command_id; | |
| 492 | + __u32 rsvd1[9]; | |
| 493 | + __le16 sqid; | |
| 494 | + __u16 cid; | |
| 495 | + __u32 rsvd11[5]; | |
| 496 | +}; | |
| 497 | + | |
| 498 | +struct nvme_download_firmware { | |
| 499 | + __u8 opcode; | |
| 500 | + __u8 flags; | |
| 501 | + __u16 command_id; | |
| 502 | + __u32 rsvd1[5]; | |
| 503 | + __le64 prp1; | |
| 504 | + __le64 prp2; | |
| 505 | + __le32 numd; | |
| 506 | + __le32 offset; | |
| 507 | + __u32 rsvd12[4]; | |
| 508 | +}; | |
| 509 | + | |
| 510 | +struct nvme_format_cmd { | |
| 511 | + __u8 opcode; | |
| 512 | + __u8 flags; | |
| 513 | + __u16 command_id; | |
| 514 | + __le32 nsid; | |
| 515 | + __u64 rsvd2[4]; | |
| 516 | + __le32 cdw10; | |
| 517 | + __u32 rsvd11[5]; | |
| 518 | +}; | |
| 519 | + | |
| 520 | +struct nvme_command { | |
| 521 | + union { | |
| 522 | + struct nvme_common_command common; | |
| 523 | + struct nvme_rw_command rw; | |
| 524 | + struct nvme_identify identify; | |
| 525 | + struct nvme_features features; | |
| 526 | + struct nvme_create_cq create_cq; | |
| 527 | + struct nvme_create_sq create_sq; | |
| 528 | + struct nvme_delete_queue delete_queue; | |
| 529 | + struct nvme_download_firmware dlfw; | |
| 530 | + struct nvme_format_cmd format; | |
| 531 | + struct nvme_dsm_cmd dsm; | |
| 532 | + struct nvme_abort_cmd abort; | |
| 533 | + }; | |
| 534 | +}; | |
| 535 | + | |
| 536 | +enum { | |
| 537 | + NVME_SC_SUCCESS = 0x0, | |
| 538 | + NVME_SC_INVALID_OPCODE = 0x1, | |
| 539 | + NVME_SC_INVALID_FIELD = 0x2, | |
| 540 | + NVME_SC_CMDID_CONFLICT = 0x3, | |
| 541 | + NVME_SC_DATA_XFER_ERROR = 0x4, | |
| 542 | + NVME_SC_POWER_LOSS = 0x5, | |
| 543 | + NVME_SC_INTERNAL = 0x6, | |
| 544 | + NVME_SC_ABORT_REQ = 0x7, | |
| 545 | + NVME_SC_ABORT_QUEUE = 0x8, | |
| 546 | + NVME_SC_FUSED_FAIL = 0x9, | |
| 547 | + NVME_SC_FUSED_MISSING = 0xa, | |
| 548 | + NVME_SC_INVALID_NS = 0xb, | |
| 549 | + NVME_SC_CMD_SEQ_ERROR = 0xc, | |
| 550 | + NVME_SC_SGL_INVALID_LAST = 0xd, | |
| 551 | + NVME_SC_SGL_INVALID_COUNT = 0xe, | |
| 552 | + NVME_SC_SGL_INVALID_DATA = 0xf, | |
| 553 | + NVME_SC_SGL_INVALID_METADATA = 0x10, | |
| 554 | + NVME_SC_SGL_INVALID_TYPE = 0x11, | |
| 555 | + NVME_SC_LBA_RANGE = 0x80, | |
| 556 | + NVME_SC_CAP_EXCEEDED = 0x81, | |
| 557 | + NVME_SC_NS_NOT_READY = 0x82, | |
| 558 | + NVME_SC_RESERVATION_CONFLICT = 0x83, | |
| 559 | + NVME_SC_CQ_INVALID = 0x100, | |
| 560 | + NVME_SC_QID_INVALID = 0x101, | |
| 561 | + NVME_SC_QUEUE_SIZE = 0x102, | |
| 562 | + NVME_SC_ABORT_LIMIT = 0x103, | |
| 563 | + NVME_SC_ABORT_MISSING = 0x104, | |
| 564 | + NVME_SC_ASYNC_LIMIT = 0x105, | |
| 565 | + NVME_SC_FIRMWARE_SLOT = 0x106, | |
| 566 | + NVME_SC_FIRMWARE_IMAGE = 0x107, | |
| 567 | + NVME_SC_INVALID_VECTOR = 0x108, | |
| 568 | + NVME_SC_INVALID_LOG_PAGE = 0x109, | |
| 569 | + NVME_SC_INVALID_FORMAT = 0x10a, | |
| 570 | + NVME_SC_FIRMWARE_NEEDS_RESET = 0x10b, | |
| 571 | + NVME_SC_INVALID_QUEUE = 0x10c, | |
| 572 | + NVME_SC_FEATURE_NOT_SAVEABLE = 0x10d, | |
| 573 | + NVME_SC_FEATURE_NOT_CHANGEABLE = 0x10e, | |
| 574 | + NVME_SC_FEATURE_NOT_PER_NS = 0x10f, | |
| 575 | + NVME_SC_FW_NEEDS_RESET_SUBSYS = 0x110, | |
| 576 | + NVME_SC_BAD_ATTRIBUTES = 0x180, | |
| 577 | + NVME_SC_INVALID_PI = 0x181, | |
| 578 | + NVME_SC_READ_ONLY = 0x182, | |
| 579 | + NVME_SC_WRITE_FAULT = 0x280, | |
| 580 | + NVME_SC_READ_ERROR = 0x281, | |
| 581 | + NVME_SC_GUARD_CHECK = 0x282, | |
| 582 | + NVME_SC_APPTAG_CHECK = 0x283, | |
| 583 | + NVME_SC_REFTAG_CHECK = 0x284, | |
| 584 | + NVME_SC_COMPARE_FAILED = 0x285, | |
| 585 | + NVME_SC_ACCESS_DENIED = 0x286, | |
| 586 | + NVME_SC_DNR = 0x4000, | |
| 587 | +}; | |
| 588 | + | |
| 589 | +struct nvme_completion { | |
| 590 | + __le32 result; /* Used by admin commands to return data */ | |
| 591 | + __u32 rsvd; | |
| 592 | + __le16 sq_head; /* how much of this queue may be reclaimed */ | |
| 593 | + __le16 sq_id; /* submission queue that generated this entry */ | |
| 594 | + __u16 command_id; /* of the command which completed */ | |
| 595 | + __le16 status; /* did the command fail, and if so, why? */ | |
| 596 | +}; | |
| 597 | + | |
| 598 | +#define NVME_VS(major, minor) (((major) << 16) | ((minor) << 8)) | |
| 189 | 599 | |
| 190 | 600 | #endif /* _LINUX_NVME_H */ |
| @@ -21,6 +21,7 @@ enum { · 20 unmodified lines | ||
| 21 | 21 | LO_FLAGS_READ_ONLY = 1, |
| 22 | 22 | LO_FLAGS_AUTOCLEAR = 4, |
| 23 | 23 | LO_FLAGS_PARTSCAN = 8, |
| 24 | + LO_FLAGS_DIRECT_IO = 16, | |
| 24 | 25 | }; |
| 25 | 26 | |
| 26 | 27 | #include <asm/posix_types.h> /* for __kernel_old_dev_t */ |
| @@ -86,6 +87,7 @@ struct loop_info64 { · 59 unmodified lines | ||
| 86 | 87 | #define LOOP_GET_STATUS64 0x4C05 |
| 87 | 88 | #define LOOP_CHANGE_FD 0x4C06 |
| 88 | 89 | #define LOOP_SET_CAPACITY 0x4C07 |
| 90 | +#define LOOP_SET_DIRECT_IO 0x4C08 | |
| 89 | 91 | |
| 90 | 92 | /* /dev/loop-control interface */ |
| 91 | 93 | #define LOOP_CTL_ADD 0x4C80 |
| @@ -1,589 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Definitions for the NVM Express interface | |
| 3 | − * Copyright (c) 2011-2014, Intel Corporation. | |
| 4 | − * | |
| 5 | − * This program is free software; you can redistribute it and/or modify it | |
| 6 | − * under the terms and conditions of the GNU General Public License, | |
| 7 | − * version 2, as published by the Free Software Foundation. | |
| 8 | − * | |
| 9 | − * This program is distributed in the hope it will be useful, but WITHOUT | |
| 10 | − * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 11 | − * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 12 | − * more details. | |
| 13 | − */ | |
| 14 | − | |
| 15 | −#ifndef _UAPI_LINUX_NVME_H | |
| 16 | −#define _UAPI_LINUX_NVME_H | |
| 17 | − | |
| 18 | −#include <linux/types.h> | |
| 19 | − | |
| 20 | −struct nvme_id_power_state { | |
| 21 | − __le16 max_power; /* centiwatts */ | |
| 22 | − __u8 rsvd2; | |
| 23 | − __u8 flags; | |
| 24 | − __le32 entry_lat; /* microseconds */ | |
| 25 | − __le32 exit_lat; /* microseconds */ | |
| 26 | − __u8 read_tput; | |
| 27 | − __u8 read_lat; | |
| 28 | − __u8 write_tput; | |
| 29 | − __u8 write_lat; | |
| 30 | − __le16 idle_power; | |
| 31 | − __u8 idle_scale; | |
| 32 | − __u8 rsvd19; | |
| 33 | − __le16 active_power; | |
| 34 | − __u8 active_work_scale; | |
| 35 | − __u8 rsvd23[9]; | |
| 36 | −}; | |
| 37 | − | |
| 38 | −enum { | |
| 39 | − NVME_PS_FLAGS_MAX_POWER_SCALE = 1 << 0, | |
| 40 | − NVME_PS_FLAGS_NON_OP_STATE = 1 << 1, | |
| 41 | −}; | |
| 42 | − | |
| 43 | −struct nvme_id_ctrl { | |
| 44 | − __le16 vid; | |
| 45 | − __le16 ssvid; | |
| 46 | − char sn[20]; | |
| 47 | − char mn[40]; | |
| 48 | − char fr[8]; | |
| 49 | − __u8 rab; | |
| 50 | − __u8 ieee[3]; | |
| 51 | − __u8 mic; | |
| 52 | − __u8 mdts; | |
| 53 | − __u16 cntlid; | |
| 54 | − __u32 ver; | |
| 55 | − __u8 rsvd84[172]; | |
| 56 | − __le16 oacs; | |
| 57 | − __u8 acl; | |
| 58 | − __u8 aerl; | |
| 59 | − __u8 frmw; | |
| 60 | − __u8 lpa; | |
| 61 | − __u8 elpe; | |
| 62 | − __u8 npss; | |
| 63 | − __u8 avscc; | |
| 64 | − __u8 apsta; | |
| 65 | − __le16 wctemp; | |
| 66 | − __le16 cctemp; | |
| 67 | − __u8 rsvd270[242]; | |
| 68 | − __u8 sqes; | |
| 69 | − __u8 cqes; | |
| 70 | − __u8 rsvd514[2]; | |
| 71 | − __le32 nn; | |
| 72 | − __le16 oncs; | |
| 73 | − __le16 fuses; | |
| 74 | − __u8 fna; | |
| 75 | − __u8 vwc; | |
| 76 | − __le16 awun; | |
| 77 | − __le16 awupf; | |
| 78 | − __u8 nvscc; | |
| 79 | − __u8 rsvd531; | |
| 80 | − __le16 acwu; | |
| 81 | − __u8 rsvd534[2]; | |
| 82 | − __le32 sgls; | |
| 83 | − __u8 rsvd540[1508]; | |
| 84 | − struct nvme_id_power_state psd[32]; | |
| 85 | − __u8 vs[1024]; | |
| 86 | −}; | |
| 87 | − | |
| 88 | −enum { | |
| 89 | − NVME_CTRL_ONCS_COMPARE = 1 << 0, | |
| 90 | − NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1, | |
| 91 | − NVME_CTRL_ONCS_DSM = 1 << 2, | |
| 92 | − NVME_CTRL_VWC_PRESENT = 1 << 0, | |
| 93 | −}; | |
| 94 | − | |
| 95 | −struct nvme_lbaf { | |
| 96 | − __le16 ms; | |
| 97 | − __u8 ds; | |
| 98 | − __u8 rp; | |
| 99 | −}; | |
| 100 | − | |
| 101 | −struct nvme_id_ns { | |
| 102 | − __le64 nsze; | |
| 103 | − __le64 ncap; | |
| 104 | − __le64 nuse; | |
| 105 | − __u8 nsfeat; | |
| 106 | − __u8 nlbaf; | |
| 107 | − __u8 flbas; | |
| 108 | − __u8 mc; | |
| 109 | − __u8 dpc; | |
| 110 | − __u8 dps; | |
| 111 | − __u8 nmic; | |
| 112 | − __u8 rescap; | |
| 113 | − __u8 fpi; | |
| 114 | − __u8 rsvd33; | |
| 115 | − __le16 nawun; | |
| 116 | − __le16 nawupf; | |
| 117 | − __le16 nacwu; | |
| 118 | − __le16 nabsn; | |
| 119 | − __le16 nabo; | |
| 120 | − __le16 nabspf; | |
| 121 | − __u16 rsvd46; | |
| 122 | − __le64 nvmcap[2]; | |
| 123 | − __u8 rsvd64[40]; | |
| 124 | − __u8 nguid[16]; | |
| 125 | − __u8 eui64[8]; | |
| 126 | − struct nvme_lbaf lbaf[16]; | |
| 127 | − __u8 rsvd192[192]; | |
| 128 | − __u8 vs[3712]; | |
| 129 | −}; | |
| 130 | − | |
| 131 | −enum { | |
| 132 | − NVME_NS_FEAT_THIN = 1 << 0, | |
| 133 | − NVME_NS_FLBAS_LBA_MASK = 0xf, | |
| 134 | − NVME_NS_FLBAS_META_EXT = 0x10, | |
| 135 | − NVME_LBAF_RP_BEST = 0, | |
| 136 | − NVME_LBAF_RP_BETTER = 1, | |
| 137 | − NVME_LBAF_RP_GOOD = 2, | |
| 138 | − NVME_LBAF_RP_DEGRADED = 3, | |
| 139 | − NVME_NS_DPC_PI_LAST = 1 << 4, | |
| 140 | − NVME_NS_DPC_PI_FIRST = 1 << 3, | |
| 141 | − NVME_NS_DPC_PI_TYPE3 = 1 << 2, | |
| 142 | − NVME_NS_DPC_PI_TYPE2 = 1 << 1, | |
| 143 | − NVME_NS_DPC_PI_TYPE1 = 1 << 0, | |
| 144 | − NVME_NS_DPS_PI_FIRST = 1 << 3, | |
| 145 | − NVME_NS_DPS_PI_MASK = 0x7, | |
| 146 | − NVME_NS_DPS_PI_TYPE1 = 1, | |
| 147 | − NVME_NS_DPS_PI_TYPE2 = 2, | |
| 148 | − NVME_NS_DPS_PI_TYPE3 = 3, | |
| 149 | −}; | |
| 150 | − | |
| 151 | −struct nvme_smart_log { | |
| 152 | − __u8 critical_warning; | |
| 153 | − __u8 temperature[2]; | |
| 154 | − __u8 avail_spare; | |
| 155 | − __u8 spare_thresh; | |
| 156 | − __u8 percent_used; | |
| 157 | − __u8 rsvd6[26]; | |
| 158 | − __u8 data_units_read[16]; | |
| 159 | − __u8 data_units_written[16]; | |
| 160 | − __u8 host_reads[16]; | |
| 161 | − __u8 host_writes[16]; | |
| 162 | − __u8 ctrl_busy_time[16]; | |
| 163 | − __u8 power_cycles[16]; | |
| 164 | − __u8 power_on_hours[16]; | |
| 165 | − __u8 unsafe_shutdowns[16]; | |
| 166 | − __u8 media_errors[16]; | |
| 167 | − __u8 num_err_log_entries[16]; | |
| 168 | − __le32 warning_temp_time; | |
| 169 | − __le32 critical_comp_time; | |
| 170 | − __le16 temp_sensor[8]; | |
| 171 | − __u8 rsvd216[296]; | |
| 172 | −}; | |
| 173 | − | |
| 174 | −enum { | |
| 175 | − NVME_SMART_CRIT_SPARE = 1 << 0, | |
| 176 | − NVME_SMART_CRIT_TEMPERATURE = 1 << 1, | |
| 177 | − NVME_SMART_CRIT_RELIABILITY = 1 << 2, | |
| 178 | − NVME_SMART_CRIT_MEDIA = 1 << 3, | |
| 179 | − NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4, | |
| 180 | −}; | |
| 181 | − | |
| 182 | −enum { | |
| 183 | − NVME_AER_NOTICE_NS_CHANGED = 0x0002, | |
| 184 | −}; | |
| 185 | − | |
| 186 | −struct nvme_lba_range_type { | |
| 187 | − __u8 type; | |
| 188 | − __u8 attributes; | |
| 189 | − __u8 rsvd2[14]; | |
| 190 | − __u64 slba; | |
| 191 | − __u64 nlb; | |
| 192 | − __u8 guid[16]; | |
| 193 | − __u8 rsvd48[16]; | |
| 194 | −}; | |
| 195 | − | |
| 196 | −enum { | |
| 197 | − NVME_LBART_TYPE_FS = 0x01, | |
| 198 | − NVME_LBART_TYPE_RAID = 0x02, | |
| 199 | − NVME_LBART_TYPE_CACHE = 0x03, | |
| 200 | − NVME_LBART_TYPE_SWAP = 0x04, | |
| 201 | − | |
| 202 | − NVME_LBART_ATTRIB_TEMP = 1 << 0, | |
| 203 | − NVME_LBART_ATTRIB_HIDE = 1 << 1, | |
| 204 | −}; | |
| 205 | − | |
| 206 | −struct nvme_reservation_status { | |
| 207 | − __le32 gen; | |
| 208 | − __u8 rtype; | |
| 209 | − __u8 regctl[2]; | |
| 210 | − __u8 resv5[2]; | |
| 211 | − __u8 ptpls; | |
| 212 | − __u8 resv10[13]; | |
| 213 | − struct { | |
| 214 | − __le16 cntlid; | |
| 215 | − __u8 rcsts; | |
| 216 | − __u8 resv3[5]; | |
| 217 | − __le64 hostid; | |
| 218 | − __le64 rkey; | |
| 219 | − } regctl_ds[]; | |
| 220 | −}; | |
| 221 | − | |
| 222 | −/* I/O commands */ | |
| 223 | − | |
| 224 | −enum nvme_opcode { | |
| 225 | − nvme_cmd_flush = 0x00, | |
| 226 | − nvme_cmd_write = 0x01, | |
| 227 | − nvme_cmd_read = 0x02, | |
| 228 | − nvme_cmd_write_uncor = 0x04, | |
| 229 | − nvme_cmd_compare = 0x05, | |
| 230 | − nvme_cmd_write_zeroes = 0x08, | |
| 231 | − nvme_cmd_dsm = 0x09, | |
| 232 | − nvme_cmd_resv_register = 0x0d, | |
| 233 | − nvme_cmd_resv_report = 0x0e, | |
| 234 | − nvme_cmd_resv_acquire = 0x11, | |
| 235 | − nvme_cmd_resv_release = 0x15, | |
| 236 | −}; | |
| 237 | − | |
| 238 | −struct nvme_common_command { | |
| 239 | − __u8 opcode; | |
| 240 | − __u8 flags; | |
| 241 | − __u16 command_id; | |
| 242 | − __le32 nsid; | |
| 243 | − __le32 cdw2[2]; | |
| 244 | − __le64 metadata; | |
| 245 | − __le64 prp1; | |
| 246 | − __le64 prp2; | |
| 247 | − __le32 cdw10[6]; | |
| 248 | −}; | |
| 249 | − | |
| 250 | −struct nvme_rw_command { | |
| 251 | − __u8 opcode; | |
| 252 | − __u8 flags; | |
| 253 | − __u16 command_id; | |
| 254 | − __le32 nsid; | |
| 255 | − __u64 rsvd2; | |
| 256 | − __le64 metadata; | |
| 257 | − __le64 prp1; | |
| 258 | − __le64 prp2; | |
| 259 | − __le64 slba; | |
| 260 | − __le16 length; | |
| 261 | − __le16 control; | |
| 262 | − __le32 dsmgmt; | |
| 263 | − __le32 reftag; | |
| 264 | − __le16 apptag; | |
| 265 | − __le16 appmask; | |
| 266 | −}; | |
| 267 | − | |
| 268 | −enum { | |
| 269 | − NVME_RW_LR = 1 << 15, | |
| 270 | − NVME_RW_FUA = 1 << 14, | |
| 271 | − NVME_RW_DSM_FREQ_UNSPEC = 0, | |
| 272 | − NVME_RW_DSM_FREQ_TYPICAL = 1, | |
| 273 | − NVME_RW_DSM_FREQ_RARE = 2, | |
| 274 | − NVME_RW_DSM_FREQ_READS = 3, | |
| 275 | − NVME_RW_DSM_FREQ_WRITES = 4, | |
| 276 | − NVME_RW_DSM_FREQ_RW = 5, | |
| 277 | − NVME_RW_DSM_FREQ_ONCE = 6, | |
| 278 | − NVME_RW_DSM_FREQ_PREFETCH = 7, | |
| 279 | − NVME_RW_DSM_FREQ_TEMP = 8, | |
| 280 | − NVME_RW_DSM_LATENCY_NONE = 0 << 4, | |
| 281 | − NVME_RW_DSM_LATENCY_IDLE = 1 << 4, | |
| 282 | − NVME_RW_DSM_LATENCY_NORM = 2 << 4, | |
| 283 | − NVME_RW_DSM_LATENCY_LOW = 3 << 4, | |
| 284 | − NVME_RW_DSM_SEQ_REQ = 1 << 6, | |
| 285 | − NVME_RW_DSM_COMPRESSED = 1 << 7, | |
| 286 | − NVME_RW_PRINFO_PRCHK_REF = 1 << 10, | |
| 287 | − NVME_RW_PRINFO_PRCHK_APP = 1 << 11, | |
| 288 | − NVME_RW_PRINFO_PRCHK_GUARD = 1 << 12, | |
| 289 | − NVME_RW_PRINFO_PRACT = 1 << 13, | |
| 290 | −}; | |
| 291 | − | |
| 292 | −struct nvme_dsm_cmd { | |
| 293 | − __u8 opcode; | |
| 294 | − __u8 flags; | |
| 295 | − __u16 command_id; | |
| 296 | − __le32 nsid; | |
| 297 | − __u64 rsvd2[2]; | |
| 298 | − __le64 prp1; | |
| 299 | − __le64 prp2; | |
| 300 | − __le32 nr; | |
| 301 | − __le32 attributes; | |
| 302 | − __u32 rsvd12[4]; | |
| 303 | −}; | |
| 304 | − | |
| 305 | −enum { | |
| 306 | − NVME_DSMGMT_IDR = 1 << 0, | |
| 307 | − NVME_DSMGMT_IDW = 1 << 1, | |
| 308 | − NVME_DSMGMT_AD = 1 << 2, | |
| 309 | −}; | |
| 310 | − | |
| 311 | −struct nvme_dsm_range { | |
| 312 | − __le32 cattr; | |
| 313 | − __le32 nlb; | |
| 314 | − __le64 slba; | |
| 315 | −}; | |
| 316 | − | |
| 317 | −/* Admin commands */ | |
| 318 | − | |
| 319 | −enum nvme_admin_opcode { | |
| 320 | − nvme_admin_delete_sq = 0x00, | |
| 321 | − nvme_admin_create_sq = 0x01, | |
| 322 | − nvme_admin_get_log_page = 0x02, | |
| 323 | − nvme_admin_delete_cq = 0x04, | |
| 324 | − nvme_admin_create_cq = 0x05, | |
| 325 | − nvme_admin_identify = 0x06, | |
| 326 | − nvme_admin_abort_cmd = 0x08, | |
| 327 | − nvme_admin_set_features = 0x09, | |
| 328 | − nvme_admin_get_features = 0x0a, | |
| 329 | − nvme_admin_async_event = 0x0c, | |
| 330 | − nvme_admin_activate_fw = 0x10, | |
| 331 | − nvme_admin_download_fw = 0x11, | |
| 332 | − nvme_admin_format_nvm = 0x80, | |
| 333 | − nvme_admin_security_send = 0x81, | |
| 334 | − nvme_admin_security_recv = 0x82, | |
| 335 | −}; | |
| 336 | − | |
| 337 | −enum { | |
| 338 | − NVME_QUEUE_PHYS_CONTIG = (1 << 0), | |
| 339 | − NVME_CQ_IRQ_ENABLED = (1 << 1), | |
| 340 | − NVME_SQ_PRIO_URGENT = (0 << 1), | |
| 341 | − NVME_SQ_PRIO_HIGH = (1 << 1), | |
| 342 | − NVME_SQ_PRIO_MEDIUM = (2 << 1), | |
| 343 | − NVME_SQ_PRIO_LOW = (3 << 1), | |
| 344 | − NVME_FEAT_ARBITRATION = 0x01, | |
| 345 | − NVME_FEAT_POWER_MGMT = 0x02, | |
| 346 | − NVME_FEAT_LBA_RANGE = 0x03, | |
| 347 | − NVME_FEAT_TEMP_THRESH = 0x04, | |
| 348 | − NVME_FEAT_ERR_RECOVERY = 0x05, | |
| 349 | − NVME_FEAT_VOLATILE_WC = 0x06, | |
| 350 | − NVME_FEAT_NUM_QUEUES = 0x07, | |
| 351 | − NVME_FEAT_IRQ_COALESCE = 0x08, | |
| 352 | − NVME_FEAT_IRQ_CONFIG = 0x09, | |
| 353 | − NVME_FEAT_WRITE_ATOMIC = 0x0a, | |
| 354 | − NVME_FEAT_ASYNC_EVENT = 0x0b, | |
| 355 | − NVME_FEAT_AUTO_PST = 0x0c, | |
| 356 | − NVME_FEAT_SW_PROGRESS = 0x80, | |
| 357 | − NVME_FEAT_HOST_ID = 0x81, | |
| 358 | − NVME_FEAT_RESV_MASK = 0x82, | |
| 359 | − NVME_FEAT_RESV_PERSIST = 0x83, | |
| 360 | − NVME_LOG_ERROR = 0x01, | |
| 361 | − NVME_LOG_SMART = 0x02, | |
| 362 | − NVME_LOG_FW_SLOT = 0x03, | |
| 363 | − NVME_LOG_RESERVATION = 0x80, | |
| 364 | − NVME_FWACT_REPL = (0 << 3), | |
| 365 | − NVME_FWACT_REPL_ACTV = (1 << 3), | |
| 366 | − NVME_FWACT_ACTV = (2 << 3), | |
| 367 | −}; | |
| 368 | − | |
| 369 | −struct nvme_identify { | |
| 370 | − __u8 opcode; | |
| 371 | − __u8 flags; | |
| 372 | − __u16 command_id; | |
| 373 | − __le32 nsid; | |
| 374 | − __u64 rsvd2[2]; | |
| 375 | − __le64 prp1; | |
| 376 | − __le64 prp2; | |
| 377 | − __le32 cns; | |
| 378 | − __u32 rsvd11[5]; | |
| 379 | −}; | |
| 380 | − | |
| 381 | −struct nvme_features { | |
| 382 | − __u8 opcode; | |
| 383 | − __u8 flags; | |
| 384 | − __u16 command_id; | |
| 385 | − __le32 nsid; | |
| 386 | − __u64 rsvd2[2]; | |
| 387 | − __le64 prp1; | |
| 388 | − __le64 prp2; | |
| 389 | − __le32 fid; | |
| 390 | − __le32 dword11; | |
| 391 | − __u32 rsvd12[4]; | |
| 392 | −}; | |
| 393 | − | |
| 394 | −struct nvme_create_cq { | |
| 395 | − __u8 opcode; | |
| 396 | − __u8 flags; | |
| 397 | − __u16 command_id; | |
| 398 | − __u32 rsvd1[5]; | |
| 399 | − __le64 prp1; | |
| 400 | − __u64 rsvd8; | |
| 401 | − __le16 cqid; | |
| 402 | − __le16 qsize; | |
| 403 | − __le16 cq_flags; | |
| 404 | − __le16 irq_vector; | |
| 405 | − __u32 rsvd12[4]; | |
| 406 | −}; | |
| 407 | − | |
| 408 | −struct nvme_create_sq { | |
| 409 | − __u8 opcode; | |
| 410 | − __u8 flags; | |
| 411 | − __u16 command_id; | |
| 412 | − __u32 rsvd1[5]; | |
| 413 | − __le64 prp1; | |
| 414 | − __u64 rsvd8; | |
| 415 | − __le16 sqid; | |
| 416 | − __le16 qsize; | |
| 417 | − __le16 sq_flags; | |
| 418 | − __le16 cqid; | |
| 419 | − __u32 rsvd12[4]; | |
| 420 | −}; | |
| 421 | − | |
| 422 | −struct nvme_delete_queue { | |
| 423 | − __u8 opcode; | |
| 424 | − __u8 flags; | |
| 425 | − __u16 command_id; | |
| 426 | − __u32 rsvd1[9]; | |
| 427 | − __le16 qid; | |
| 428 | − __u16 rsvd10; | |
| 429 | − __u32 rsvd11[5]; | |
| 430 | −}; | |
| 431 | − | |
| 432 | −struct nvme_abort_cmd { | |
| 433 | − __u8 opcode; | |
| 434 | − __u8 flags; | |
| 435 | − __u16 command_id; | |
| 436 | − __u32 rsvd1[9]; | |
| 437 | − __le16 sqid; | |
| 438 | − __u16 cid; | |
| 439 | − __u32 rsvd11[5]; | |
| 440 | −}; | |
| 441 | − | |
| 442 | −struct nvme_download_firmware { | |
| 443 | − __u8 opcode; | |
| 444 | − __u8 flags; | |
| 445 | − __u16 command_id; | |
| 446 | − __u32 rsvd1[5]; | |
| 447 | − __le64 prp1; | |
| 448 | − __le64 prp2; | |
| 449 | − __le32 numd; | |
| 450 | − __le32 offset; | |
| 451 | − __u32 rsvd12[4]; | |
| 452 | −}; | |
| 453 | − | |
| 454 | −struct nvme_format_cmd { | |
| 455 | − __u8 opcode; | |
| 456 | − __u8 flags; | |
| 457 | − __u16 command_id; | |
| 458 | − __le32 nsid; | |
| 459 | − __u64 rsvd2[4]; | |
| 460 | − __le32 cdw10; | |
| 461 | − __u32 rsvd11[5]; | |
| 462 | −}; | |
| 463 | − | |
| 464 | −struct nvme_command { | |
| 465 | − union { | |
| 466 | − struct nvme_common_command common; | |
| 467 | − struct nvme_rw_command rw; | |
| 468 | − struct nvme_identify identify; | |
| 469 | − struct nvme_features features; | |
| 470 | − struct nvme_create_cq create_cq; | |
| 471 | − struct nvme_create_sq create_sq; | |
| 472 | − struct nvme_delete_queue delete_queue; | |
| 473 | − struct nvme_download_firmware dlfw; | |
| 474 | − struct nvme_format_cmd format; | |
| 475 | − struct nvme_dsm_cmd dsm; | |
| 476 | − struct nvme_abort_cmd abort; | |
| 477 | − }; | |
| 478 | −}; | |
| 479 | − | |
| 480 | −enum { | |
| 481 | − NVME_SC_SUCCESS = 0x0, | |
| 482 | − NVME_SC_INVALID_OPCODE = 0x1, | |
| 483 | − NVME_SC_INVALID_FIELD = 0x2, | |
| 484 | − NVME_SC_CMDID_CONFLICT = 0x3, | |
| 485 | − NVME_SC_DATA_XFER_ERROR = 0x4, | |
| 486 | − NVME_SC_POWER_LOSS = 0x5, | |
| 487 | − NVME_SC_INTERNAL = 0x6, | |
| 488 | − NVME_SC_ABORT_REQ = 0x7, | |
| 489 | − NVME_SC_ABORT_QUEUE = 0x8, | |
| 490 | − NVME_SC_FUSED_FAIL = 0x9, | |
| 491 | − NVME_SC_FUSED_MISSING = 0xa, | |
| 492 | − NVME_SC_INVALID_NS = 0xb, | |
| 493 | − NVME_SC_CMD_SEQ_ERROR = 0xc, | |
| 494 | − NVME_SC_SGL_INVALID_LAST = 0xd, | |
| 495 | − NVME_SC_SGL_INVALID_COUNT = 0xe, | |
| 496 | − NVME_SC_SGL_INVALID_DATA = 0xf, | |
| 497 | − NVME_SC_SGL_INVALID_METADATA = 0x10, | |
| 498 | − NVME_SC_SGL_INVALID_TYPE = 0x11, | |
| 499 | − NVME_SC_LBA_RANGE = 0x80, | |
| 500 | − NVME_SC_CAP_EXCEEDED = 0x81, | |
| 501 | − NVME_SC_NS_NOT_READY = 0x82, | |
| 502 | − NVME_SC_RESERVATION_CONFLICT = 0x83, | |
| 503 | − NVME_SC_CQ_INVALID = 0x100, | |
| 504 | − NVME_SC_QID_INVALID = 0x101, | |
| 505 | − NVME_SC_QUEUE_SIZE = 0x102, | |
| 506 | − NVME_SC_ABORT_LIMIT = 0x103, | |
| 507 | − NVME_SC_ABORT_MISSING = 0x104, | |
| 508 | − NVME_SC_ASYNC_LIMIT = 0x105, | |
| 509 | − NVME_SC_FIRMWARE_SLOT = 0x106, | |
| 510 | − NVME_SC_FIRMWARE_IMAGE = 0x107, | |
| 511 | − NVME_SC_INVALID_VECTOR = 0x108, | |
| 512 | − NVME_SC_INVALID_LOG_PAGE = 0x109, | |
| 513 | − NVME_SC_INVALID_FORMAT = 0x10a, | |
| 514 | − NVME_SC_FIRMWARE_NEEDS_RESET = 0x10b, | |
| 515 | − NVME_SC_INVALID_QUEUE = 0x10c, | |
| 516 | − NVME_SC_FEATURE_NOT_SAVEABLE = 0x10d, | |
| 517 | − NVME_SC_FEATURE_NOT_CHANGEABLE = 0x10e, | |
| 518 | − NVME_SC_FEATURE_NOT_PER_NS = 0x10f, | |
| 519 | − NVME_SC_FW_NEEDS_RESET_SUBSYS = 0x110, | |
| 520 | − NVME_SC_BAD_ATTRIBUTES = 0x180, | |
| 521 | − NVME_SC_INVALID_PI = 0x181, | |
| 522 | − NVME_SC_READ_ONLY = 0x182, | |
| 523 | − NVME_SC_WRITE_FAULT = 0x280, | |
| 524 | − NVME_SC_READ_ERROR = 0x281, | |
| 525 | − NVME_SC_GUARD_CHECK = 0x282, | |
| 526 | − NVME_SC_APPTAG_CHECK = 0x283, | |
| 527 | − NVME_SC_REFTAG_CHECK = 0x284, | |
| 528 | − NVME_SC_COMPARE_FAILED = 0x285, | |
| 529 | − NVME_SC_ACCESS_DENIED = 0x286, | |
| 530 | − NVME_SC_DNR = 0x4000, | |
| 531 | −}; | |
| 532 | − | |
| 533 | −struct nvme_completion { | |
| 534 | − __le32 result; /* Used by admin commands to return data */ | |
| 535 | − __u32 rsvd; | |
| 536 | − __le16 sq_head; /* how much of this queue may be reclaimed */ | |
| 537 | − __le16 sq_id; /* submission queue that generated this entry */ | |
| 538 | − __u16 command_id; /* of the command which completed */ | |
| 539 | − __le16 status; /* did the command fail, and if so, why? */ | |
| 540 | −}; | |
| 541 | − | |
| 542 | −struct nvme_user_io { | |
| 543 | − __u8 opcode; | |
| 544 | − __u8 flags; | |
| 545 | − __u16 control; | |
| 546 | − __u16 nblocks; | |
| 547 | − __u16 rsvd; | |
| 548 | − __u64 metadata; | |
| 549 | − __u64 addr; | |
| 550 | − __u64 slba; | |
| 551 | − __u32 dsmgmt; | |
| 552 | − __u32 reftag; | |
| 553 | − __u16 apptag; | |
| 554 | − __u16 appmask; | |
| 555 | −}; | |
| 556 | − | |
| 557 | −struct nvme_passthru_cmd { | |
| 558 | − __u8 opcode; | |
| 559 | − __u8 flags; | |
| 560 | − __u16 rsvd1; | |
| 561 | − __u32 nsid; | |
| 562 | − __u32 cdw2; | |
| 563 | − __u32 cdw3; | |
| 564 | − __u64 metadata; | |
| 565 | − __u64 addr; | |
| 566 | − __u32 metadata_len; | |
| 567 | − __u32 data_len; | |
| 568 | − __u32 cdw10; | |
| 569 | − __u32 cdw11; | |
| 570 | − __u32 cdw12; | |
| 571 | − __u32 cdw13; | |
| 572 | − __u32 cdw14; | |
| 573 | − __u32 cdw15; | |
| 574 | − __u32 timeout_ms; | |
| 575 | − __u32 result; | |
| 576 | −}; | |
| 577 | − | |
| 578 | −#define NVME_VS(major, minor) (((major) << 16) | ((minor) << 8)) | |
| 579 | − | |
| 580 | −#define nvme_admin_cmd nvme_passthru_cmd | |
| 581 | − | |
| 582 | −#define NVME_IOCTL_ID _IO('N', 0x40) | |
| 583 | −#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) | |
| 584 | −#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) | |
| 585 | −#define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct nvme_passthru_cmd) | |
| 586 | −#define NVME_IOCTL_RESET _IO('N', 0x44) | |
| 587 | −#define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) | |
| 588 | − | |
| 589 | −#endif /* _UAPI_LINUX_NVME_H */ | |
| @@ -0,0 +1,65 @@ | ||
| 1 | +/* | |
| 2 | + * Definitions for the NVM Express ioctl interface | |
| 3 | + * Copyright (c) 2011-2014, Intel Corporation. | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms and conditions of the GNU General Public License, | |
| 7 | + * version 2, as published by the Free Software Foundation. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
| 10 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 11 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 12 | + * more details. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#ifndef _UAPI_LINUX_NVME_IOCTL_H | |
| 16 | +#define _UAPI_LINUX_NVME_IOCTL_H | |
| 17 | + | |
| 18 | +#include <linux/types.h> | |
| 19 | + | |
| 20 | +struct nvme_user_io { | |
| 21 | + __u8 opcode; | |
| 22 | + __u8 flags; | |
| 23 | + __u16 control; | |
| 24 | + __u16 nblocks; | |
| 25 | + __u16 rsvd; | |
| 26 | + __u64 metadata; | |
| 27 | + __u64 addr; | |
| 28 | + __u64 slba; | |
| 29 | + __u32 dsmgmt; | |
| 30 | + __u32 reftag; | |
| 31 | + __u16 apptag; | |
| 32 | + __u16 appmask; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +struct nvme_passthru_cmd { | |
| 36 | + __u8 opcode; | |
| 37 | + __u8 flags; | |
| 38 | + __u16 rsvd1; | |
| 39 | + __u32 nsid; | |
| 40 | + __u32 cdw2; | |
| 41 | + __u32 cdw3; | |
| 42 | + __u64 metadata; | |
| 43 | + __u64 addr; | |
| 44 | + __u32 metadata_len; | |
| 45 | + __u32 data_len; | |
| 46 | + __u32 cdw10; | |
| 47 | + __u32 cdw11; | |
| 48 | + __u32 cdw12; | |
| 49 | + __u32 cdw13; | |
| 50 | + __u32 cdw14; | |
| 51 | + __u32 cdw15; | |
| 52 | + __u32 timeout_ms; | |
| 53 | + __u32 result; | |
| 54 | +}; | |
| 55 | + | |
| 56 | +#define nvme_admin_cmd nvme_passthru_cmd | |
| 57 | + | |
| 58 | +#define NVME_IOCTL_ID _IO('N', 0x40) | |
| 59 | +#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) | |
| 60 | +#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) | |
| 61 | +#define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct nvme_passthru_cmd) | |
| 62 | +#define NVME_IOCTL_RESET _IO('N', 0x44) | |
| 63 | +#define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) | |
| 64 | + | |
| 65 | +#endif /* _UAPI_LINUX_NVME_IOCTL_H */ | |