Date: Tue, 8 Oct 2013 19:07:48 +0000 (UTC) From: Mark Murray <markm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r256162 - in projects/random_number_generator: sbin/nvmecontrol sbin/route sys/cddl/contrib/opensolaris/uts/common/dtrace sys/cddl/dev/dtrace sys/dev/ath/ath_hal/ar5212 sys/dev/nvd sys/... Message-ID: <201310081907.r98J7mwu003458@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markm Date: Tue Oct 8 19:07:48 2013 New Revision: 256162 URL: http://svnweb.freebsd.org/changeset/base/256162 Log: MFC - tracking commit. Modified: projects/random_number_generator/sbin/nvmecontrol/perftest.c projects/random_number_generator/sbin/route/route.c projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_load.c projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_unload.c projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212.h projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c projects/random_number_generator/sys/dev/nvd/nvd.c projects/random_number_generator/sys/dev/nvme/nvme.c projects/random_number_generator/sys/dev/nvme/nvme.h projects/random_number_generator/sys/dev/nvme/nvme_ctrlr.c projects/random_number_generator/sys/dev/nvme/nvme_ns.c projects/random_number_generator/sys/dev/nvme/nvme_private.h projects/random_number_generator/sys/dev/nvme/nvme_test.c projects/random_number_generator/sys/dev/random/ivy.c projects/random_number_generator/usr.sbin/bhyve/bhyverun.c projects/random_number_generator/usr.sbin/bhyve/dbgport.h Directory Properties: projects/random_number_generator/ (props changed) projects/random_number_generator/sbin/ (props changed) projects/random_number_generator/sys/ (props changed) projects/random_number_generator/sys/cddl/contrib/opensolaris/ (props changed) projects/random_number_generator/usr.sbin/bhyve/ (props changed) Modified: projects/random_number_generator/sbin/nvmecontrol/perftest.c ============================================================================== --- projects/random_number_generator/sbin/nvmecontrol/perftest.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sbin/nvmecontrol/perftest.c Tue Oct 8 19:07:48 2013 (r256162) @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <ctype.h> #include <err.h> #include <fcntl.h> +#include <inttypes.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> @@ -45,7 +46,8 @@ __FBSDID("$FreeBSD$"); static void print_perftest(struct nvme_io_test *io_test, bool perthread) { - uint32_t i, io_completed = 0, iops, mbps; + uint64_t io_completed = 0, iops, mbps; + uint32_t i; for (i = 0; i < io_test->num_threads; i++) io_completed += io_test->io_completed[i]; @@ -53,15 +55,15 @@ print_perftest(struct nvme_io_test *io_t iops = io_completed/io_test->time; mbps = iops * io_test->size / (1024*1024); - printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n", + printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7ju MB/s: %4ju\n", io_test->num_threads, io_test->size, io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", - io_test->time, iops, mbps); + io_test->time, (uintmax_t)iops, (uintmax_t)mbps); if (perthread) for (i = 0; i < io_test->num_threads; i++) - printf("\t%3d: %8d IO/s\n", i, - io_test->io_completed[i]/io_test->time); + printf("\t%3d: %8ju IO/s\n", i, + (uintmax_t)io_test->io_completed[i]/io_test->time); exit(1); } Modified: projects/random_number_generator/sbin/route/route.c ============================================================================== --- projects/random_number_generator/sbin/route/route.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sbin/route/route.c Tue Oct 8 19:07:48 2013 (r256162) @@ -928,6 +928,11 @@ newroute(int argc, char **argv) } } + if (so[RTAX_DST].ss_len == 0) { + warnx("destination parameter required"); + usage(NULL); + } + if (nrflags & F_FORCEHOST) { nrflags |= F_ISHOST; #ifdef INET6 Modified: projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c ============================================================================== --- projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c Tue Oct 8 19:07:48 2013 (r256162) @@ -15751,10 +15751,6 @@ dtrace_open(struct cdev *dev, int oflags #else devfs_set_cdevpriv(state, dtrace_dtr); #endif - /* This code actually belongs in dtrace_attach() */ - if (dtrace_opens == 1) - dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, - 1, INT_MAX, 0); #endif mutex_exit(&cpu_lock); @@ -15842,11 +15838,6 @@ dtrace_dtr(void *data) (void) kdi_dtrace_set(KDI_DTSET_DTRACE_DEACTIVATE); #else --dtrace_opens; - /* This code actually belongs in dtrace_detach() */ - if ((dtrace_opens == 0) && (dtrace_taskq != NULL)) { - taskq_destroy(dtrace_taskq); - dtrace_taskq = NULL; - } #endif mutex_exit(&dtrace_lock); Modified: projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_load.c ============================================================================== --- projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_load.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_load.c Tue Oct 8 19:07:48 2013 (r256162) @@ -56,6 +56,8 @@ dtrace_load(void *dummy) /* Hang our hook for exceptions. */ dtrace_invop_init(); + dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 0, 0, 0); + /* Register callbacks for linker file load and unload events. */ dtrace_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, dtrace_kld_load, NULL, EVENTHANDLER_PRI_ANY); Modified: projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_unload.c ============================================================================== --- projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_unload.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/cddl/dev/dtrace/dtrace_unload.c Tue Oct 8 19:07:48 2013 (r256162) @@ -127,6 +127,8 @@ dtrace_unload() mutex_destroy(&dtrace_errlock); #endif + taskq_destroy(dtrace_taskq); + /* Reset our hook for exceptions. */ dtrace_invop_uninit(); Modified: projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212.h ============================================================================== --- projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212.h Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212.h Tue Oct 8 19:07:48 2013 (r256162) @@ -335,6 +335,16 @@ struct ath_hal_5212 { uint8_t ah_txTrigLev; /* current Tx trigger level */ uint8_t ah_maxTxTrigLev; /* max tx trigger level */ + + /* + * Channel Tx, Rx, Rx Clear State + */ + uint32_t ah_cycleCount; + uint32_t ah_ctlBusy; + uint32_t ah_rxBusy; + uint32_t ah_txBusy; + uint32_t ah_rx_chainmask; + uint32_t ah_tx_chainmask; }; #define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) Modified: projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c ============================================================================== --- projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c Tue Oct 8 19:07:48 2013 (r256162) @@ -865,16 +865,40 @@ static int32_t ar5212AniGetListenTime(struct ath_hal *ah) { struct ath_hal_5212 *ahp = AH5212(ah); - struct ar5212AniState *aniState; - uint32_t txFrameCount, rxFrameCount, cycleCount; - int32_t listenTime; + struct ar5212AniState *aniState = NULL; + int32_t listenTime = 0; + int good; + HAL_SURVEY_SAMPLE hs; + HAL_CHANNEL_SURVEY *cs = AH_NULL; + + /* + * We shouldn't see ah_curchan be NULL, but just in case.. + */ + if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) { + ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__); + return (0); + } - txFrameCount = OS_REG_READ(ah, AR_TFCNT); - rxFrameCount = OS_REG_READ(ah, AR_RFCNT); - cycleCount = OS_REG_READ(ah, AR_CCCNT); + cs = &ahp->ah_chansurvey; + + /* + * Fetch the current statistics, squirrel away the current + * sample, bump the sequence/sample counter. + */ + OS_MEMZERO(&hs, sizeof(hs)); + good = ar5212GetMibCycleCounts(ah, &hs); + if (cs != AH_NULL) { + OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs)); + cs->samples[cs->cur_sample].seq_num = cs->cur_seq; + cs->cur_sample = + (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT; + cs->cur_seq++; + } - aniState = ahp->ah_curani; - if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { + if (ANI_ENA(ah)) + aniState = ahp->ah_curani; + + if (good == AH_FALSE) { /* * Cycle counter wrap (or initial call); it's not possible * to accurately calculate a value because the registers @@ -882,15 +906,29 @@ ar5212AniGetListenTime(struct ath_hal *a */ listenTime = 0; ahp->ah_stats.ast_ani_lzero++; - } else { - int32_t ccdelta = cycleCount - aniState->cycleCount; - int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; - int32_t tfdelta = txFrameCount - aniState->txFrameCount; + } else if (ANI_ENA(ah)) { + /* + * Only calculate and update the cycle count if we have + * an ANI state. + */ + int32_t ccdelta = + AH5212(ah)->ah_cycleCount - aniState->cycleCount; + int32_t rfdelta = + AH5212(ah)->ah_rxBusy - aniState->rxFrameCount; + int32_t tfdelta = + AH5212(ah)->ah_txBusy - aniState->txFrameCount; listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; } - aniState->cycleCount = cycleCount; - aniState->txFrameCount = txFrameCount; - aniState->rxFrameCount = rxFrameCount; + + /* + * Again, only update ANI state if we have it. + */ + if (ANI_ENA(ah)) { + aniState->cycleCount = AH5212(ah)->ah_cycleCount; + aniState->rxFrameCount = AH5212(ah)->ah_rxBusy; + aniState->txFrameCount = AH5212(ah)->ah_txBusy; + } + return listenTime; } @@ -956,13 +994,15 @@ ar5212AniPoll(struct ath_hal *ah, const const struct ar5212AniParams *params; int32_t listenTime; + /* Always update from the MIB, for statistics gathering */ + listenTime = ar5212AniGetListenTime(ah); + /* XXX can aniState be null? */ if (aniState == AH_NULL) return; if (!ANI_ENA(ah)) return; - listenTime = ar5212AniGetListenTime(ah); if (listenTime < 0) { ahp->ah_stats.ast_ani_lneg++; /* restart ANI period if listenTime is invalid */ Modified: projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c ============================================================================== --- projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c Tue Oct 8 19:07:48 2013 (r256162) @@ -1405,13 +1405,47 @@ ar5212Get11nExtBusy(struct ath_hal *ah) } /* - * There's no channel survey support for the AR5212. + * Channel survey support. */ HAL_BOOL ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) { + struct ath_hal_5212 *ahp = AH5212(ah); + u_int32_t good = AH_TRUE; - return (AH_FALSE); + /* XXX freeze/unfreeze mib counters */ + uint32_t rc = OS_REG_READ(ah, AR_RCCNT); + uint32_t rf = OS_REG_READ(ah, AR_RFCNT); + uint32_t tf = OS_REG_READ(ah, AR_TFCNT); + uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ + + if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cycle counter wrap. ExtBusy = 0\n", __func__); + good = AH_FALSE; + } else { + hsample->cycle_count = cc - ahp->ah_cycleCount; + hsample->chan_busy = rc - ahp->ah_ctlBusy; + hsample->ext_chan_busy = 0; + hsample->rx_busy = rf - ahp->ah_rxBusy; + hsample->tx_busy = tf - ahp->ah_txBusy; + } + + /* + * Keep a copy of the MIB results so the next sample has something + * to work from. + */ + ahp->ah_cycleCount = cc; + ahp->ah_rxBusy = rf; + ahp->ah_ctlBusy = rc; + ahp->ah_txBusy = tf; + + return (good); } void Modified: projects/random_number_generator/sys/dev/nvd/nvd.c ============================================================================== --- projects/random_number_generator/sys/dev/nvd/nvd.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvd/nvd.c Tue Oct 8 19:07:48 2013 (r256162) @@ -187,17 +187,6 @@ nvd_done(void *arg, const struct nvme_co atomic_add_int(&ndisk->cur_depth, -1); - /* - * TODO: add more extensive translation of NVMe status codes - * to different bio error codes (i.e. EIO, EINVAL, etc.) - */ - if (nvme_completion_is_error(cpl)) { - bp->bio_error = EIO; - bp->bio_flags |= BIO_ERROR; - bp->bio_resid = bp->bio_bcount; - } else - bp->bio_resid = 0; - biodone(bp); } Modified: projects/random_number_generator/sys/dev/nvme/nvme.c ============================================================================== --- projects/random_number_generator/sys/dev/nvme/nvme.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvme/nvme.c Tue Oct 8 19:07:48 2013 (r256162) @@ -221,8 +221,10 @@ nvme_attach(device_t dev) status = nvme_ctrlr_construct(ctrlr, dev); - if (status != 0) + if (status != 0) { + nvme_ctrlr_destruct(ctrlr, dev); return (status); + } /* * Reset controller twice to ensure we do a transition from cc.en==1 @@ -230,12 +232,16 @@ nvme_attach(device_t dev) * the controller was left in when boot handed off to OS. */ status = nvme_ctrlr_hw_reset(ctrlr); - if (status != 0) + if (status != 0) { + nvme_ctrlr_destruct(ctrlr, dev); return (status); + } status = nvme_ctrlr_hw_reset(ctrlr); - if (status != 0) + if (status != 0) { + nvme_ctrlr_destruct(ctrlr, dev); return (status); + } nvme_sysctl_initialize_ctrlr(ctrlr); Modified: projects/random_number_generator/sys/dev/nvme/nvme.h ============================================================================== --- projects/random_number_generator/sys/dev/nvme/nvme.h Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvme/nvme.h Tue Oct 8 19:07:48 2013 (r256162) @@ -535,7 +535,7 @@ struct nvme_controller_data { uint8_t reserved6[1024]; /* bytes 3072-4095: vendor specific */ - uint8_t reserved7[1024]; + uint8_t vs[1024]; } __packed __aligned(4); struct nvme_namespace_data { @@ -720,7 +720,7 @@ struct nvme_io_test { uint32_t time; /* in seconds */ uint32_t num_threads; uint32_t flags; - uint32_t io_completed[NVME_TEST_MAX_THREADS]; + uint64_t io_completed[NVME_TEST_MAX_THREADS]; }; enum nvme_io_test_flags { Modified: projects/random_number_generator/sys/dev/nvme/nvme_ctrlr.c ============================================================================== --- projects/random_number_generator/sys/dev/nvme/nvme_ctrlr.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvme/nvme_ctrlr.c Tue Oct 8 19:07:48 2013 (r256162) @@ -617,9 +617,35 @@ nvme_ctrlr_get_log_page_size(struct nvme } static void +nvme_ctrlr_log_critical_warnings(struct nvme_controller *ctrlr, + union nvme_critical_warning_state state) +{ + + if (state.bits.available_spare == 1) + nvme_printf(ctrlr, "available spare space below threshold\n"); + + if (state.bits.temperature == 1) + nvme_printf(ctrlr, "temperature above threshold\n"); + + if (state.bits.device_reliability == 1) + nvme_printf(ctrlr, "device reliability degraded\n"); + + if (state.bits.read_only == 1) + nvme_printf(ctrlr, "media placed in read only mode\n"); + + if (state.bits.volatile_memory_backup == 1) + nvme_printf(ctrlr, "volatile memory backup device failed\n"); + + if (state.bits.reserved != 0) + nvme_printf(ctrlr, + "unknown critical warning(s): state = 0x%02x\n", state.raw); +} + +static void nvme_ctrlr_async_event_log_page_cb(void *arg, const struct nvme_completion *cpl) { - struct nvme_async_event_request *aer = arg; + struct nvme_async_event_request *aer = arg; + struct nvme_health_information_page *health_info; /* * If the log page fetch for some reason completed with an error, @@ -629,13 +655,33 @@ nvme_ctrlr_async_event_log_page_cb(void if (nvme_completion_is_error(cpl)) nvme_notify_async_consumers(aer->ctrlr, &aer->cpl, aer->log_page_id, NULL, 0); - else + else { + if (aer->log_page_id == NVME_LOG_HEALTH_INFORMATION) { + health_info = (struct nvme_health_information_page *) + aer->log_page_buffer; + nvme_ctrlr_log_critical_warnings(aer->ctrlr, + health_info->critical_warning); + /* + * Critical warnings reported through the + * SMART/health log page are persistent, so + * clear the associated bits in the async event + * config so that we do not receive repeated + * notifications for the same event. + */ + aer->ctrlr->async_event_config.raw &= + ~health_info->critical_warning.raw; + nvme_ctrlr_cmd_set_async_event_config(aer->ctrlr, + aer->ctrlr->async_event_config, NULL, NULL); + } + + /* * Pass the cpl data from the original async event completion, * not the log page fetch. */ nvme_notify_async_consumers(aer->ctrlr, &aer->cpl, aer->log_page_id, aer->log_page_buffer, aer->log_page_size); + } /* * Repost another asynchronous event request to replace the one @@ -708,13 +754,27 @@ nvme_ctrlr_construct_and_submit_aer(stru static void nvme_ctrlr_configure_aer(struct nvme_controller *ctrlr) { - union nvme_critical_warning_state state; + struct nvme_completion_poll_status status; struct nvme_async_event_request *aer; uint32_t i; - state.raw = 0xFF; - state.bits.reserved = 0; - nvme_ctrlr_cmd_set_async_event_config(ctrlr, state, NULL, NULL); + ctrlr->async_event_config.raw = 0xFF; + ctrlr->async_event_config.bits.reserved = 0; + + status.done = FALSE; + nvme_ctrlr_cmd_get_feature(ctrlr, NVME_FEAT_TEMPERATURE_THRESHOLD, + 0, NULL, 0, nvme_completion_poll_cb, &status); + while (status.done == FALSE) + pause("nvme", 1); + if (nvme_completion_is_error(&status.cpl) || + (status.cpl.cdw0 & 0xFFFF) == 0xFFFF || + (status.cpl.cdw0 & 0xFFFF) == 0x0000) { + nvme_printf(ctrlr, "temperature threshold not supported\n"); + ctrlr->async_event_config.bits.temperature = 0; + } + + nvme_ctrlr_cmd_set_async_event_config(ctrlr, + ctrlr->async_event_config, NULL, NULL); /* aerl is a zero-based value, so we need to add 1 here. */ ctrlr->num_aers = min(NVME_MAX_ASYNC_EVENTS, (ctrlr->cdata.aerl+1)); Modified: projects/random_number_generator/sys/dev/nvme/nvme_ns.c ============================================================================== --- projects/random_number_generator/sys/dev/nvme/nvme_ns.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvme/nvme_ns.c Tue Oct 8 19:07:48 2013 (r256162) @@ -34,13 +34,31 @@ __FBSDID("$FreeBSD$"); #include <sys/disk.h> #include <sys/fcntl.h> #include <sys/ioccom.h> +#include <sys/malloc.h> #include <sys/module.h> #include <sys/proc.h> #include <dev/pci/pcivar.h> +#include <geom/geom.h> + #include "nvme_private.h" +static void nvme_bio_child_inbed(struct bio *parent, int bio_error); +static void nvme_bio_child_done(void *arg, + const struct nvme_completion *cpl); +static uint32_t nvme_get_num_segments(uint64_t addr, uint64_t size, + uint32_t alignment); +static void nvme_free_child_bios(int num_bios, + struct bio **child_bios); +static struct bio ** nvme_allocate_child_bios(int num_bios); +static struct bio ** nvme_construct_child_bios(struct bio *bp, + uint32_t alignment, + int *num_bios); +static int nvme_ns_split_bio(struct nvme_namespace *ns, + struct bio *bp, + uint32_t alignment); + static int nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag, struct thread *td) @@ -202,18 +220,218 @@ nvme_ns_bio_done(void *arg, const struct if (bp->bio_driver2) free(bp->bio_driver2, M_NVME); + if (nvme_completion_is_error(status)) { + bp->bio_flags |= BIO_ERROR; + if (bp->bio_error == 0) + bp->bio_error = EIO; + } + + if ((bp->bio_flags & BIO_ERROR) == 0) + bp->bio_resid = 0; + else + bp->bio_resid = bp->bio_bcount; + bp_cb_fn(bp, status); } +static void +nvme_bio_child_inbed(struct bio *parent, int bio_error) +{ + struct nvme_completion parent_cpl; + int inbed; + + if (bio_error != 0) { + parent->bio_flags |= BIO_ERROR; + parent->bio_error = bio_error; + } + + /* + * atomic_fetchadd will return value before adding 1, so we still + * must add 1 to get the updated inbed number. + */ + inbed = atomic_fetchadd_int(&parent->bio_inbed, 1) + 1; + if (inbed == parent->bio_children) { + bzero(&parent_cpl, sizeof(parent_cpl)); + if (parent->bio_flags & BIO_ERROR) + parent_cpl.status.sc = NVME_SC_DATA_TRANSFER_ERROR; + nvme_ns_bio_done(parent, &parent_cpl); + } +} + +static void +nvme_bio_child_done(void *arg, const struct nvme_completion *cpl) +{ + struct bio *child = arg; + struct bio *parent; + int bio_error; + + parent = child->bio_parent; + g_destroy_bio(child); + bio_error = nvme_completion_is_error(cpl) ? EIO : 0; + nvme_bio_child_inbed(parent, bio_error); +} + +static uint32_t +nvme_get_num_segments(uint64_t addr, uint64_t size, uint32_t align) +{ + uint32_t num_segs, offset, remainder; + + if (align == 0) + return (1); + + KASSERT((align & (align - 1)) == 0, ("alignment not power of 2\n")); + + num_segs = size / align; + remainder = size & (align - 1); + offset = addr & (align - 1); + if (remainder > 0 || offset > 0) + num_segs += 1 + (remainder + offset - 1) / align; + return (num_segs); +} + +static void +nvme_free_child_bios(int num_bios, struct bio **child_bios) +{ + int i; + + for (i = 0; i < num_bios; i++) { + if (child_bios[i] != NULL) + g_destroy_bio(child_bios[i]); + } + + free(child_bios, M_NVME); +} + +static struct bio ** +nvme_allocate_child_bios(int num_bios) +{ + struct bio **child_bios; + int err = 0, i; + + child_bios = malloc(num_bios * sizeof(struct bio *), M_NVME, M_NOWAIT); + if (child_bios == NULL) + return (NULL); + + for (i = 0; i < num_bios; i++) { + child_bios[i] = g_new_bio(); + if (child_bios[i] == NULL) + err = ENOMEM; + } + + if (err == ENOMEM) { + nvme_free_child_bios(num_bios, child_bios); + return (NULL); + } + + return (child_bios); +} + +static struct bio ** +nvme_construct_child_bios(struct bio *bp, uint32_t alignment, int *num_bios) +{ + struct bio **child_bios; + struct bio *child; + uint64_t cur_offset; + caddr_t data; + uint32_t rem_bcount; + int i; +#ifdef NVME_UNMAPPED_BIO_SUPPORT + struct vm_page **ma; + uint32_t ma_offset; +#endif + + *num_bios = nvme_get_num_segments(bp->bio_offset, bp->bio_bcount, + alignment); + child_bios = nvme_allocate_child_bios(*num_bios); + if (child_bios == NULL) + return (NULL); + + bp->bio_children = *num_bios; + bp->bio_inbed = 0; + cur_offset = bp->bio_offset; + rem_bcount = bp->bio_bcount; + data = bp->bio_data; +#ifdef NVME_UNMAPPED_BIO_SUPPORT + ma_offset = bp->bio_ma_offset; + ma = bp->bio_ma; +#endif + + for (i = 0; i < *num_bios; i++) { + child = child_bios[i]; + child->bio_parent = bp; + child->bio_cmd = bp->bio_cmd; + child->bio_offset = cur_offset; + child->bio_bcount = min(rem_bcount, + alignment - (cur_offset & (alignment - 1))); + child->bio_flags = bp->bio_flags; +#ifdef NVME_UNMAPPED_BIO_SUPPORT + if (bp->bio_flags & BIO_UNMAPPED) { + child->bio_ma_offset = ma_offset; + child->bio_ma = ma; + child->bio_ma_n = + nvme_get_num_segments(child->bio_ma_offset, + child->bio_bcount, PAGE_SIZE); + ma_offset = (ma_offset + child->bio_bcount) & + PAGE_MASK; + ma += child->bio_ma_n; + if (ma_offset != 0) + ma -= 1; + } else +#endif + { + child->bio_data = data; + data += child->bio_bcount; + } + cur_offset += child->bio_bcount; + rem_bcount -= child->bio_bcount; + } + + return (child_bios); +} + +static int +nvme_ns_split_bio(struct nvme_namespace *ns, struct bio *bp, + uint32_t alignment) +{ + struct bio *child; + struct bio **child_bios; + int err, i, num_bios; + + child_bios = nvme_construct_child_bios(bp, alignment, &num_bios); + if (child_bios == NULL) + return (ENOMEM); + + for (i = 0; i < num_bios; i++) { + child = child_bios[i]; + err = nvme_ns_bio_process(ns, child, nvme_bio_child_done); + if (err != 0) { + nvme_bio_child_inbed(bp, err); + g_destroy_bio(child); + } + } + + free(child_bios, M_NVME); + return (0); +} + int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp, nvme_cb_fn_t cb_fn) { struct nvme_dsm_range *dsm_range; + uint32_t num_bios; int err; bp->bio_driver1 = cb_fn; + if (ns->stripesize > 0 && + (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE)) { + num_bios = nvme_get_num_segments(bp->bio_offset, + bp->bio_bcount, ns->stripesize); + if (num_bios > 1) + return (nvme_ns_split_bio(ns, bp, ns->stripesize)); + } + switch (bp->bio_cmd) { case BIO_READ: err = nvme_ns_cmd_read_bio(ns, bp, nvme_ns_bio_done, bp); @@ -276,6 +494,11 @@ nvme_ns_construct(struct nvme_namespace ns->ctrlr = ctrlr; ns->id = id; + ns->stripesize = 0; + + if (pci_get_devid(ctrlr->dev) == 0x09538086 && ctrlr->cdata.vs[3] != 0) + ns->stripesize = + (1 << ctrlr->cdata.vs[3]) * ctrlr->min_page_size; /* * Namespaces are reconstructed after a controller reset, so check Modified: projects/random_number_generator/sys/dev/nvme/nvme_private.h ============================================================================== --- projects/random_number_generator/sys/dev/nvme/nvme_private.h Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvme/nvme_private.h Tue Oct 8 19:07:48 2013 (r256162) @@ -238,6 +238,7 @@ struct nvme_namespace { uint16_t flags; struct cdev *cdev; void *cons_cookie[NVME_MAX_CONSUMERS]; + uint32_t stripesize; struct mtx lock; }; @@ -321,6 +322,9 @@ struct nvme_controller { struct cdev *cdev; + /** bit mask of warning types currently enabled for async events */ + union nvme_critical_warning_state async_event_config; + uint32_t num_aers; struct nvme_async_event_request aer[NVME_MAX_ASYNC_EVENTS]; Modified: projects/random_number_generator/sys/dev/nvme/nvme_test.c ============================================================================== --- projects/random_number_generator/sys/dev/nvme/nvme_test.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/nvme/nvme_test.c Tue Oct 8 19:07:48 2013 (r256162) @@ -53,7 +53,7 @@ struct nvme_io_test_thread { void *buf; uint32_t size; uint32_t time; - uint32_t io_completed; + uint64_t io_completed; }; struct nvme_io_test_internal { @@ -66,7 +66,7 @@ struct nvme_io_test_internal { uint32_t td_active; uint32_t td_idx; uint32_t flags; - uint32_t io_completed[NVME_TEST_MAX_THREADS]; + uint64_t io_completed[NVME_TEST_MAX_THREADS]; }; static void @@ -90,8 +90,8 @@ nvme_ns_bio_test(void *arg) struct cdev *dev; void *buf; struct timeval t; - uint64_t offset; - uint32_t idx, io_completed = 0; + uint64_t io_completed = 0, offset; + uint32_t idx; #if __FreeBSD_version >= 900017 int ref; #endif Modified: projects/random_number_generator/sys/dev/random/ivy.c ============================================================================== --- projects/random_number_generator/sys/dev/random/ivy.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/sys/dev/random/ivy.c Tue Oct 8 19:07:48 2013 (r256162) @@ -74,12 +74,12 @@ ivy_rng_store(uint64_t *tmp) __asm __volatile( #ifdef __amd64__ - ".byte\t0x48,0x0f,0xc7,0xf0\n\t" /* rdrand %rax */ + "rdrand\t%%rax\n\t" "jnc\t1f\n\t" "movq\t%%rax,%1\n\t" "movl\t$8,%%eax\n" #else /* i386 */ - ".byte\t0x0f,0xc7,0xf0\n\t" /* rdrand %eax */ + "rdrand\t%%eax\n\t" "jnc\t1f\n\t" "movl\t%%eax,%1\n\t" "movl\t$4,%%eax\n" Modified: projects/random_number_generator/usr.sbin/bhyve/bhyverun.c ============================================================================== --- projects/random_number_generator/usr.sbin/bhyve/bhyverun.c Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/usr.sbin/bhyve/bhyverun.c Tue Oct 8 19:07:48 2013 (r256162) @@ -123,7 +123,7 @@ usage(int code) " <vmname>\n" " -a: local apic is in XAPIC mode (default is X2APIC)\n" " -A: create an ACPI table\n" - " -g: gdb port (default is %d and 0 means don't open)\n" + " -g: gdb port\n" " -c: # cpus (default 1)\n" " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n" " -H: vmexit from the guest on hlt\n" @@ -134,7 +134,7 @@ usage(int code) " -s: <slot,driver,configinfo> PCI slot config\n" " -S: <slot,driver,configinfo> legacy PCI slot config\n" " -m: memory size in MB\n", - progname, DEFAULT_GDB_PORT); + progname); exit(code); } @@ -217,17 +217,6 @@ fbsdrun_addcpu(struct vmctx *ctx, int vc } static int -fbsdrun_get_next_cpu(int curcpu) -{ - - /* - * Get the next available CPU. Assumes they arrive - * in ascending order with no gaps. - */ - return ((curcpu + 1) % foundcpus); -} - -static int vmexit_catch_reset(void) { stats.io_reset++; @@ -504,7 +493,7 @@ main(int argc, char *argv[]) bvmcons = 0; progname = basename(argv[0]); - gdb_port = DEFAULT_GDB_PORT; + gdb_port = 0; guest_ncpus = 1; ioapic = 0; memsize = 256 * MB; Modified: projects/random_number_generator/usr.sbin/bhyve/dbgport.h ============================================================================== --- projects/random_number_generator/usr.sbin/bhyve/dbgport.h Tue Oct 8 18:59:41 2013 (r256161) +++ projects/random_number_generator/usr.sbin/bhyve/dbgport.h Tue Oct 8 19:07:48 2013 (r256162) @@ -29,8 +29,6 @@ #ifndef _DBGPORT_H_ #define _DBGPORT_H_ -#define DEFAULT_GDB_PORT 6466 - void init_dbgport(int port); #endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310081907.r98J7mwu003458>