1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (C) 2012-2014 Intel Corporation 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/bus.h> 31 #include <sys/conf.h> 32 #include <sys/module.h> 33 34 #include <vm/uma.h> 35 36 #include "nvme_private.h" 37 #include "nvme_if.h" 38 39 int32_t nvme_retry_count; 40 41 MALLOC_DEFINE(M_NVME, "nvme", "nvme(4) memory allocations"); 42 43 int 44 nvme_shutdown(device_t dev) 45 { 46 struct nvme_controller *ctrlr; 47 uint32_t csts; 48 49 ctrlr = DEVICE2SOFTC(dev); 50 51 csts = nvme_mmio_read_4(ctrlr, csts); 52 if (ctrlr->is_initialized && !ctrlr->is_failed && csts != NVME_GONE) 53 nvme_ctrlr_delete_qpairs(ctrlr); 54 nvme_ctrlr_shutdown(ctrlr); 55 56 return (0); 57 } 58 59 int 60 nvme_attach(device_t dev) 61 { 62 struct nvme_controller *ctrlr = DEVICE2SOFTC(dev); 63 int status; 64 65 status = nvme_ctrlr_construct(ctrlr, dev); 66 if (status != 0) { 67 nvme_ctrlr_destruct(ctrlr, dev); 68 return (status); 69 } 70 71 ctrlr->config_hook.ich_func = nvme_ctrlr_start_config_hook; 72 ctrlr->config_hook.ich_arg = ctrlr; 73 74 if (config_intrhook_establish(&ctrlr->config_hook) != 0) 75 return (ENOMEM); 76 77 return (0); 78 } 79 80 int 81 nvme_detach(device_t dev) 82 { 83 struct nvme_controller *ctrlr = DEVICE2SOFTC(dev); 84 int error; 85 86 config_intrhook_drain(&ctrlr->config_hook); 87 88 error = bus_generic_detach(dev); 89 if (error) 90 return (error); 91 92 nvme_ctrlr_destruct(ctrlr, dev); 93 return (0); 94 } 95 96 void 97 nvme_notify_async(struct nvme_controller *ctrlr, 98 const struct nvme_completion *async_cpl, 99 uint32_t log_page_id, void *log_page_buffer, uint32_t log_page_size) 100 { 101 device_t *children; 102 int n_children; 103 104 if (device_get_children(ctrlr->dev, &children, &n_children) != 0) 105 return; 106 107 for (int i = 0; i < n_children; i++) 108 NVME_HANDLE_AEN(children[i], async_cpl, log_page_id, 109 log_page_buffer, log_page_size); 110 111 free(children, M_TEMP); 112 } 113 114 void 115 nvme_notify_fail(struct nvme_controller *ctrlr) 116 { 117 device_t *children; 118 int n_children; 119 120 /* 121 * This controller failed during initialization (i.e. IDENTIFY 122 * command failed or timed out). Do not notify any nvme 123 * consumers of the failure here, since the consumer does not 124 * even know about the controller yet. 125 */ 126 if (!ctrlr->is_initialized) 127 return; 128 129 if (device_get_children(ctrlr->dev, &children, &n_children) != 0) 130 return; 131 132 for (int i = 0; i < n_children; i++) 133 NVME_CONTROLLER_FAILED(children[i]); 134 135 free(children, M_TEMP); 136 } 137 138 void 139 nvme_completion_poll_cb(void *arg, const struct nvme_completion *cpl) 140 { 141 struct nvme_completion_poll_status *status = arg; 142 143 /* 144 * Copy status into the argument passed by the caller, so that 145 * the caller can check the status to determine if the 146 * the request passed or failed. 147 */ 148 memcpy(&status->cpl, cpl, sizeof(*cpl)); 149 atomic_store_rel_int(&status->done, 1); 150 } 151 152 static int 153 nvme_modevent(module_t mod __unused, int type __unused, void *argp __unused) 154 { 155 return (0); 156 } 157 158 static moduledata_t nvme_mod = { 159 "nvme", 160 nvme_modevent, 161 0 162 }; 163 164 DECLARE_MODULE(nvme, nvme_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 165 MODULE_VERSION(nvme, 1); 166 MODULE_DEPEND(nvme, cam, 1, 1, 1); 167