Mercurial > unleashed > wips
changeset 20583:25546b3a75d0
9846 nvme driver shouldn't panic from userland commands
Reviewed by: Mike Gerdts <mike.gerdts@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Approved by: Richard Lowe <richlowe@richlowe.net>
author | Robert Mustacchi <rm@joyent.com> |
---|---|
date | Fri, 17 Aug 2018 16:50:24 +0000 |
parents | 9143794e1de8 |
children | 098b1b31b21d |
files | usr/src/uts/common/io/nvme/nvme.c |
diffstat | 1 files changed, 51 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/nvme/nvme.c Thu Jul 26 17:41:45 2018 +0000 +++ b/usr/src/uts/common/io/nvme/nvme.c Fri Aug 17 16:50:24 2018 +0000 @@ -324,13 +324,14 @@ static int nvme_abort_cmd(nvme_cmd_t *, uint_t); static void nvme_async_event(nvme_t *); -static int nvme_format_nvm(nvme_t *, uint32_t, uint8_t, boolean_t, uint8_t, - boolean_t, uint8_t); -static int nvme_get_logpage(nvme_t *, void **, size_t *, uint8_t, ...); -static int nvme_identify(nvme_t *, uint32_t, void **); -static int nvme_set_features(nvme_t *, uint32_t, uint8_t, uint32_t, +static int nvme_format_nvm(nvme_t *, boolean_t, uint32_t, uint8_t, boolean_t, + uint8_t, boolean_t, uint8_t); +static int nvme_get_logpage(nvme_t *, boolean_t, void **, size_t *, uint8_t, + ...); +static int nvme_identify(nvme_t *, boolean_t, uint32_t, void **); +static int nvme_set_features(nvme_t *, boolean_t, uint32_t, uint8_t, uint32_t, uint32_t *); -static int nvme_get_features(nvme_t *, uint32_t, uint8_t, uint32_t *, +static int nvme_get_features(nvme_t *, boolean_t, uint32_t, uint8_t, uint32_t *, void **, size_t *); static int nvme_write_cache_set(nvme_t *, boolean_t); static int nvme_set_nqueues(nvme_t *, uint16_t *); @@ -1494,8 +1495,8 @@ switch (event.b.ae_type) { case NVME_ASYNC_TYPE_ERROR: if (event.b.ae_logpage == NVME_LOGPAGE_ERROR) { - (void) nvme_get_logpage(nvme, (void **)&error_log, - &logsize, event.b.ae_logpage); + (void) nvme_get_logpage(nvme, B_FALSE, + (void **)&error_log, &logsize, event.b.ae_logpage); } else { dev_err(nvme->n_dip, CE_WARN, "!wrong logpage in " "async event reply: %d", event.b.ae_logpage); @@ -1545,8 +1546,9 @@ case NVME_ASYNC_TYPE_HEALTH: if (event.b.ae_logpage == NVME_LOGPAGE_HEALTH) { - (void) nvme_get_logpage(nvme, (void **)&health_log, - &logsize, event.b.ae_logpage, -1); + (void) nvme_get_logpage(nvme, B_FALSE, + (void **)&health_log, &logsize, event.b.ae_logpage, + -1); } else { dev_err(nvme->n_dip, CE_WARN, "!wrong logpage in " "async event reply: %d", event.b.ae_logpage); @@ -1623,8 +1625,8 @@ } static int -nvme_format_nvm(nvme_t *nvme, uint32_t nsid, uint8_t lbaf, boolean_t ms, - uint8_t pi, boolean_t pil, uint8_t ses) +nvme_format_nvm(nvme_t *nvme, boolean_t user, uint32_t nsid, uint8_t lbaf, + boolean_t ms, uint8_t pi, boolean_t pil, uint8_t ses) { nvme_cmd_t *cmd = nvme_alloc_cmd(nvme, KM_SLEEP); nvme_format_nvm_t format_nvm = { 0 }; @@ -1648,6 +1650,12 @@ */ if (nsid == (uint32_t)-1) cmd->nc_dontpanic = B_TRUE; + /* + * If this format request was initiated by the user, then don't allow a + * programmer error to panic the system. + */ + if (user) + cmd->nc_dontpanic = B_TRUE; nvme_admin_cmd(cmd, nvme_format_cmd_timeout); @@ -1662,8 +1670,8 @@ } static int -nvme_get_logpage(nvme_t *nvme, void **buf, size_t *bufsize, uint8_t logpage, - ...) +nvme_get_logpage(nvme_t *nvme, boolean_t user, void **buf, size_t *bufsize, + uint8_t logpage, ...) { nvme_cmd_t *cmd = nvme_alloc_cmd(nvme, KM_SLEEP); nvme_getlogpage_t getlogpage = { 0 }; @@ -1676,6 +1684,9 @@ cmd->nc_callback = nvme_wakeup_cmd; cmd->nc_sqe.sqe_opc = NVME_OPC_GET_LOG_PAGE; + if (user) + cmd->nc_dontpanic = B_TRUE; + getlogpage.b.lp_lid = logpage; switch (logpage) { @@ -1756,7 +1767,7 @@ } static int -nvme_identify(nvme_t *nvme, uint32_t nsid, void **buf) +nvme_identify(nvme_t *nvme, boolean_t user, uint32_t nsid, void **buf) { nvme_cmd_t *cmd = nvme_alloc_cmd(nvme, KM_SLEEP); int ret; @@ -1794,6 +1805,9 @@ cmd->nc_dma->nd_cookie.dmac_laddress; } + if (user) + cmd->nc_dontpanic = B_TRUE; + nvme_admin_cmd(cmd, nvme_admin_cmd_timeout); if ((ret = nvme_check_cmd_status(cmd)) != 0) { @@ -1813,8 +1827,8 @@ } static int -nvme_set_features(nvme_t *nvme, uint32_t nsid, uint8_t feature, uint32_t val, - uint32_t *res) +nvme_set_features(nvme_t *nvme, boolean_t user, uint32_t nsid, uint8_t feature, + uint32_t val, uint32_t *res) { _NOTE(ARGUNUSED(nsid)); nvme_cmd_t *cmd = nvme_alloc_cmd(nvme, KM_SLEEP); @@ -1828,6 +1842,9 @@ cmd->nc_sqe.sqe_cdw10 = feature; cmd->nc_sqe.sqe_cdw11 = val; + if (user) + cmd->nc_dontpanic = B_TRUE; + switch (feature) { case NVME_FEAT_WRITE_CACHE: if (!nvme->n_write_cache_present) @@ -1859,8 +1876,8 @@ } static int -nvme_get_features(nvme_t *nvme, uint32_t nsid, uint8_t feature, uint32_t *res, - void **buf, size_t *bufsize) +nvme_get_features(nvme_t *nvme, boolean_t user, uint32_t nsid, uint8_t feature, + uint32_t *res, void **buf, size_t *bufsize) { nvme_cmd_t *cmd = nvme_alloc_cmd(nvme, KM_SLEEP); int ret = EINVAL; @@ -1929,6 +1946,9 @@ goto fail; } + if (user) + cmd->nc_dontpanic = B_TRUE; + if (bufsize != NULL && *bufsize != 0) { if (nvme_zalloc_dma(nvme, *bufsize, DDI_DMA_READ, &nvme->n_prp_dma_attr, &cmd->nc_dma) != DDI_SUCCESS) { @@ -2011,8 +2031,8 @@ if (enable) nwc.b.wc_wce = 1; - return (nvme_set_features(nvme, 0, NVME_FEAT_WRITE_CACHE, nwc.r, - &nwc.r)); + return (nvme_set_features(nvme, B_FALSE, 0, NVME_FEAT_WRITE_CACHE, + nwc.r, &nwc.r)); } static int @@ -2023,7 +2043,8 @@ nq.b.nq_nsq = nq.b.nq_ncq = *nqueues - 1; - ret = nvme_set_features(nvme, 0, NVME_FEAT_NQUEUES, nq.r, &nq.r); + ret = nvme_set_features(nvme, B_FALSE, 0, NVME_FEAT_NQUEUES, nq.r, + &nq.r); if (ret == 0) { /* @@ -2188,7 +2209,7 @@ ns->ns_nvme = nvme; - if (nvme_identify(nvme, nsid, (void **)&idns) != 0) { + if (nvme_identify(nvme, B_FALSE, nsid, (void **)&idns) != 0) { dev_err(nvme->n_dip, CE_WARN, "!failed to identify namespace %d", nsid); return (DDI_FAILURE); @@ -2444,7 +2465,7 @@ /* * Identify Controller */ - if (nvme_identify(nvme, 0, (void **)&nvme->n_idctl) != 0) { + if (nvme_identify(nvme, B_FALSE, 0, (void **)&nvme->n_idctl) != 0) { dev_err(nvme->n_dip, CE_WARN, "!failed to identify controller"); goto fail; @@ -3544,7 +3565,7 @@ if (nioc->n_len < NVME_IDENTIFY_BUFSIZE) return (EINVAL); - if ((rv = nvme_identify(nvme, nsid, (void **)&idctl)) != 0) + if ((rv = nvme_identify(nvme, B_TRUE, nsid, (void **)&idctl)) != 0) return (rv); if (ddi_copyout(idctl, (void *)nioc->n_buf, NVME_IDENTIFY_BUFSIZE, mode) @@ -3620,7 +3641,7 @@ return (EINVAL); } - if (nvme_get_logpage(nvme, &log, &bufsize, nioc->n_arg, nsid) + if (nvme_get_logpage(nvme, B_TRUE, &log, &bufsize, nioc->n_arg, nsid) != DDI_SUCCESS) return (EIO); @@ -3712,7 +3733,8 @@ return (EINVAL); } - rv = nvme_get_features(nvme, nsid, feature, &res, &buf, &bufsize); + rv = nvme_get_features(nvme, B_TRUE, nsid, feature, &res, &buf, + &bufsize); if (rv != 0) return (rv); @@ -3819,8 +3841,8 @@ if (nsid == 0) nsid = (uint32_t)-1; - return (nvme_format_nvm(nvme, nsid, frmt.b.fm_lbaf, B_FALSE, 0, B_FALSE, - frmt.b.fm_ses)); + return (nvme_format_nvm(nvme, B_TRUE, nsid, frmt.b.fm_lbaf, B_FALSE, 0, + B_FALSE, frmt.b.fm_ses)); } static int