From owner-svn-src-head@FreeBSD.ORG Mon Apr 1 16:23:36 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 5AAFAE54; Mon, 1 Apr 2013 16:23:36 +0000 (UTC) (envelope-from jimharris@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 3C080110; Mon, 1 Apr 2013 16:23:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r31GNamX029064; Mon, 1 Apr 2013 16:23:36 GMT (envelope-from jimharris@svn.freebsd.org) Received: (from jimharris@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r31GNZaq029055; Mon, 1 Apr 2013 16:23:35 GMT (envelope-from jimharris@svn.freebsd.org) Message-Id: <201304011623.r31GNZaq029055@svn.freebsd.org> From: Jim Harris Date: Mon, 1 Apr 2013 16:23:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r248977 - in head/sys/dev: nvd nvme X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Apr 2013 16:23:36 -0000 Author: jimharris Date: Mon Apr 1 16:23:34 2013 New Revision: 248977 URL: http://svnweb.freebsd.org/changeset/base/248977 Log: Add unmapped bio support to nvme(4) and nvd(4). Sponsored by: Intel Modified: head/sys/dev/nvd/nvd.c head/sys/dev/nvme/nvme.h head/sys/dev/nvme/nvme_ns.c head/sys/dev/nvme/nvme_ns_cmd.c head/sys/dev/nvme/nvme_private.h head/sys/dev/nvme/nvme_qpair.c Modified: head/sys/dev/nvd/nvd.c ============================================================================== --- head/sys/dev/nvd/nvd.c Mon Apr 1 16:14:57 2013 (r248976) +++ head/sys/dev/nvd/nvd.c Mon Apr 1 16:23:34 2013 (r248977) @@ -301,6 +301,11 @@ nvd_new_disk(struct nvme_namespace *ns, if (nvme_ns_get_flags(ns) & NVME_NS_FLUSH_SUPPORTED) disk->d_flags |= DISKFLAG_CANFLUSHCACHE; +/* ifdef used here to ease porting to stable branches at a later point. */ +#ifdef DISKFLAG_UNMAPPED_BIO + disk->d_flags |= DISKFLAG_UNMAPPED_BIO; +#endif + strlcpy(disk->d_ident, nvme_ns_get_serial_number(ns), sizeof(disk->d_ident)); Modified: head/sys/dev/nvme/nvme.h ============================================================================== --- head/sys/dev/nvme/nvme.h Mon Apr 1 16:14:57 2013 (r248976) +++ head/sys/dev/nvme/nvme.h Mon Apr 1 16:23:34 2013 (r248977) @@ -758,9 +758,13 @@ void nvme_ctrlr_cmd_get_log_page(struct int nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg); +int nvme_ns_cmd_write_bio(struct nvme_namespace *ns, struct bio *bp, + nvme_cb_fn_t cb_fn, void *cb_arg); int nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload, uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg); +int nvme_ns_cmd_read_bio(struct nvme_namespace *ns, struct bio *bp, + nvme_cb_fn_t cb_fn, void *cb_arg); int nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, uint8_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg); Modified: head/sys/dev/nvme/nvme_ns.c ============================================================================== --- head/sys/dev/nvme/nvme_ns.c Mon Apr 1 16:14:57 2013 (r248976) +++ head/sys/dev/nvme/nvme_ns.c Mon Apr 1 16:23:34 2013 (r248977) @@ -150,11 +150,17 @@ nvme_ns_strategy(struct bio *bp) static struct cdevsw nvme_ns_cdevsw = { .d_version = D_VERSION, +#ifdef NVME_UNMAPPED_BIO_SUPPORT + .d_flags = D_DISK | D_UNMAPPED_IO, + .d_read = physread, + .d_write = physwrite, +#else .d_flags = D_DISK, - .d_open = nvme_ns_open, - .d_close = nvme_ns_close, .d_read = nvme_ns_physio, .d_write = nvme_ns_physio, +#endif + .d_open = nvme_ns_open, + .d_close = nvme_ns_close, .d_strategy = nvme_ns_strategy, .d_ioctl = nvme_ns_ioctl }; @@ -233,16 +239,10 @@ nvme_ns_bio_process(struct nvme_namespac switch (bp->bio_cmd) { case BIO_READ: - err = nvme_ns_cmd_read(ns, bp->bio_data, - bp->bio_offset/nvme_ns_get_sector_size(ns), - bp->bio_bcount/nvme_ns_get_sector_size(ns), - nvme_ns_bio_done, bp); + err = nvme_ns_cmd_read_bio(ns, bp, nvme_ns_bio_done, bp); break; case BIO_WRITE: - err = nvme_ns_cmd_write(ns, bp->bio_data, - bp->bio_offset/nvme_ns_get_sector_size(ns), - bp->bio_bcount/nvme_ns_get_sector_size(ns), - nvme_ns_bio_done, bp); + err = nvme_ns_cmd_write_bio(ns, bp, nvme_ns_bio_done, bp); break; case BIO_FLUSH: err = nvme_ns_cmd_flush(ns, nvme_ns_bio_done, bp); Modified: head/sys/dev/nvme/nvme_ns_cmd.c ============================================================================== --- head/sys/dev/nvme/nvme_ns_cmd.c Mon Apr 1 16:14:57 2013 (r248976) +++ head/sys/dev/nvme/nvme_ns_cmd.c Mon Apr 1 16:23:34 2013 (r248977) @@ -54,6 +54,35 @@ nvme_ns_cmd_read(struct nvme_namespace * } int +nvme_ns_cmd_read_bio(struct nvme_namespace *ns, struct bio *bp, + nvme_cb_fn_t cb_fn, void *cb_arg) +{ + struct nvme_request *req; + struct nvme_command *cmd; + uint64_t lba; + uint64_t lba_count; + + req = nvme_allocate_request_bio(bp, cb_fn, cb_arg); + + if (req == NULL) + return (ENOMEM); + cmd = &req->cmd; + cmd->opc = NVME_OPC_READ; + cmd->nsid = ns->id; + + lba = bp->bio_offset / nvme_ns_get_sector_size(ns); + lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns); + + /* TODO: create a read command data structure */ + *(uint64_t *)&cmd->cdw10 = lba; + cmd->cdw12 = lba_count-1; + + nvme_ctrlr_submit_io_request(ns->ctrlr, req); + + return (0); +} + +int nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg) { @@ -80,6 +109,35 @@ nvme_ns_cmd_write(struct nvme_namespace } int +nvme_ns_cmd_write_bio(struct nvme_namespace *ns, struct bio *bp, + nvme_cb_fn_t cb_fn, void *cb_arg) +{ + struct nvme_request *req; + struct nvme_command *cmd; + uint64_t lba; + uint64_t lba_count; + + req = nvme_allocate_request_bio(bp, cb_fn, cb_arg); + + if (req == NULL) + return (ENOMEM); + cmd = &req->cmd; + cmd->opc = NVME_OPC_WRITE; + cmd->nsid = ns->id; + + lba = bp->bio_offset / nvme_ns_get_sector_size(ns); + lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns); + + /* TODO: create a write command data structure */ + *(uint64_t *)&cmd->cdw10 = lba; + cmd->cdw12 = lba_count-1; + + nvme_ctrlr_submit_io_request(ns->ctrlr, req); + + return (0); +} + +int nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, uint8_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg) { Modified: head/sys/dev/nvme/nvme_private.h ============================================================================== --- head/sys/dev/nvme/nvme_private.h Mon Apr 1 16:14:57 2013 (r248976) +++ head/sys/dev/nvme/nvme_private.h Mon Apr 1 16:23:34 2013 (r248977) @@ -30,6 +30,7 @@ #define __NVME_PRIVATE_H__ #include +#include #include #include #include @@ -114,6 +115,16 @@ MALLOC_DECLARE(M_NVME); #define CACHE_LINE_SIZE (64) #endif +/* + * Use presence of the BIO_UNMAPPED flag to determine whether unmapped I/O + * support and the bus_dmamap_load_bio API are available on the target + * kernel. This will ease porting back to earlier stable branches at a + * later point. + */ +#ifdef BIO_UNMAPPED +#define NVME_UNMAPPED_BIO_SUPPORT +#endif + extern uma_zone_t nvme_request_zone; extern int32_t nvme_retry_count; @@ -126,6 +137,9 @@ struct nvme_completion_poll_status { #define NVME_REQUEST_VADDR 1 #define NVME_REQUEST_NULL 2 /* For requests with no payload. */ #define NVME_REQUEST_UIO 3 +#ifdef NVME_UNMAPPED_BIO_SUPPORT +#define NVME_REQUEST_BIO 4 +#endif struct nvme_request { @@ -134,6 +148,7 @@ struct nvme_request { union { void *payload; struct uio *uio; + struct bio *bio; } u; uint32_t type; uint32_t payload_size; @@ -527,6 +542,25 @@ nvme_allocate_request_uio(struct uio *ui return (req); } +static __inline struct nvme_request * +nvme_allocate_request_bio(struct bio *bio, nvme_cb_fn_t cb_fn, void *cb_arg) +{ + struct nvme_request *req; + + req = _nvme_allocate_request(cb_fn, cb_arg); + if (req != NULL) { +#ifdef NVME_UNMAPPED_BIO_SUPPORT + req->type = NVME_REQUEST_BIO; + req->u.bio = bio; +#else + req->type = NVME_REQUEST_VADDR; + req->u.payload = bio->bio_data; + req->payload_size = bio->bio_bcount; +#endif + } + return (req); +} + #define nvme_free_request(req) uma_zfree(nvme_request_zone, req) void nvme_notify_async_consumers(struct nvme_controller *ctrlr, Modified: head/sys/dev/nvme/nvme_qpair.c ============================================================================== --- head/sys/dev/nvme/nvme_qpair.c Mon Apr 1 16:14:57 2013 (r248976) +++ head/sys/dev/nvme/nvme_qpair.c Mon Apr 1 16:23:34 2013 (r248977) @@ -757,6 +757,14 @@ _nvme_qpair_submit_request(struct nvme_q if (err != 0) panic("bus_dmamap_load_uio returned non-zero!\n"); break; +#ifdef NVME_UNMAPPED_BIO_SUPPORT + case NVME_REQUEST_BIO: + err = bus_dmamap_load_bio(tr->qpair->dma_tag, + tr->payload_dma_map, req->u.bio, nvme_payload_map, tr, 0); + if (err != 0) + panic("bus_dmamap_load_bio returned non-zero!\n"); + break; +#endif default: panic("unknown nvme request type 0x%x\n", req->type); break;