1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * BSD LICENSE 5 * 6 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <dev/isci/isci.h> 37 38 #include <sys/sysctl.h> 39 40 #include <dev/isci/scil/scif_controller.h> 41 #include <dev/isci/scil/scic_phy.h> 42 43 static int 44 isci_sysctl_coalesce_timeout(SYSCTL_HANDLER_ARGS) 45 { 46 struct isci_softc *isci = (struct isci_softc *)arg1; 47 int error = sysctl_handle_int(oidp, &isci->coalesce_timeout, 0, req); 48 int i; 49 50 if (error) 51 return (error); 52 53 for (i = 0; i < isci->controller_count; i++) 54 scif_controller_set_interrupt_coalescence( 55 isci->controllers[i].scif_controller_handle, 56 isci->coalesce_number, isci->coalesce_timeout); 57 58 return (0); 59 } 60 61 static int 62 isci_sysctl_coalesce_number(SYSCTL_HANDLER_ARGS) 63 { 64 struct isci_softc *isci = (struct isci_softc *)arg1; 65 int error = sysctl_handle_int(oidp, &isci->coalesce_number, 0, req); 66 int i; 67 68 if (error) 69 return (error); 70 71 for (i = 0; i < isci->controller_count; i++) 72 scif_controller_set_interrupt_coalescence( 73 isci->controllers[i].scif_controller_handle, 74 isci->coalesce_number, isci->coalesce_timeout); 75 76 return (0); 77 } 78 79 static void 80 isci_sysctl_reset_remote_devices(struct ISCI_CONTROLLER *controller, 81 uint32_t remote_devices_to_be_reset) 82 { 83 uint32_t i = 0; 84 85 while (remote_devices_to_be_reset != 0) { 86 if (remote_devices_to_be_reset & 0x1) { 87 struct ISCI_REMOTE_DEVICE *remote_device = 88 controller->remote_device[i]; 89 90 if (remote_device != NULL) { 91 mtx_lock(&controller->lock); 92 isci_remote_device_reset(remote_device, NULL); 93 mtx_unlock(&controller->lock); 94 } 95 } 96 remote_devices_to_be_reset >>= 1; 97 i++; 98 } 99 } 100 101 static int 102 isci_sysctl_reset_remote_device_on_controller0(SYSCTL_HANDLER_ARGS) 103 { 104 struct isci_softc *isci = (struct isci_softc *)arg1; 105 uint32_t remote_devices_to_be_reset = 0; 106 struct ISCI_CONTROLLER *controller = &isci->controllers[0]; 107 int error = sysctl_handle_int(oidp, &remote_devices_to_be_reset, 0, req); 108 109 if (error || remote_devices_to_be_reset == 0) 110 return (error); 111 112 isci_sysctl_reset_remote_devices(controller, remote_devices_to_be_reset); 113 114 return (0); 115 } 116 117 static int 118 isci_sysctl_reset_remote_device_on_controller1(SYSCTL_HANDLER_ARGS) 119 { 120 struct isci_softc *isci = (struct isci_softc *)arg1; 121 uint32_t remote_devices_to_be_reset = 0; 122 struct ISCI_CONTROLLER *controller = &isci->controllers[1]; 123 int error = 124 sysctl_handle_int(oidp, &remote_devices_to_be_reset, 0, req); 125 126 if (error || remote_devices_to_be_reset == 0) 127 return (error); 128 129 isci_sysctl_reset_remote_devices(controller, 130 remote_devices_to_be_reset); 131 132 return (0); 133 } 134 135 static void 136 isci_sysctl_stop(struct ISCI_CONTROLLER *controller, uint32_t phy_to_be_stopped) 137 { 138 SCI_PHY_HANDLE_T phy_handle = NULL; 139 140 scic_controller_get_phy_handle( 141 scif_controller_get_scic_handle(controller->scif_controller_handle), 142 phy_to_be_stopped, &phy_handle); 143 144 scic_phy_stop(phy_handle); 145 } 146 147 static int 148 isci_sysctl_stop_phy(SYSCTL_HANDLER_ARGS) 149 { 150 struct isci_softc *isci = (struct isci_softc *)arg1; 151 uint32_t phy_to_be_stopped = 0xff; 152 uint32_t controller_index, phy_index; 153 int error = sysctl_handle_int(oidp, &phy_to_be_stopped, 0, req); 154 155 controller_index = phy_to_be_stopped / SCI_MAX_PHYS; 156 phy_index = phy_to_be_stopped % SCI_MAX_PHYS; 157 158 if(error || controller_index >= isci->controller_count) 159 return (error); 160 161 isci_sysctl_stop(&isci->controllers[controller_index], phy_index); 162 163 return (0); 164 } 165 166 static void 167 isci_sysctl_start(struct ISCI_CONTROLLER *controller, 168 uint32_t phy_to_be_started) 169 { 170 SCI_PHY_HANDLE_T phy_handle = NULL; 171 172 scic_controller_get_phy_handle( 173 scif_controller_get_scic_handle(controller->scif_controller_handle), 174 phy_to_be_started, &phy_handle); 175 176 scic_phy_start(phy_handle); 177 } 178 179 static int 180 isci_sysctl_start_phy(SYSCTL_HANDLER_ARGS) 181 { 182 struct isci_softc *isci = (struct isci_softc *)arg1; 183 uint32_t phy_to_be_started = 0xff; 184 uint32_t controller_index, phy_index; 185 int error = sysctl_handle_int(oidp, &phy_to_be_started, 0, req); 186 187 controller_index = phy_to_be_started / SCI_MAX_PHYS; 188 phy_index = phy_to_be_started % SCI_MAX_PHYS; 189 190 if(error || controller_index >= isci->controller_count) 191 return error; 192 193 isci_sysctl_start(&isci->controllers[controller_index], phy_index); 194 195 return 0; 196 } 197 198 static int 199 isci_sysctl_log_frozen_lun_masks(SYSCTL_HANDLER_ARGS) 200 { 201 struct isci_softc *isci = (struct isci_softc *)arg1; 202 struct ISCI_REMOTE_DEVICE *device; 203 int32_t log_frozen_devices = 0; 204 int error, i, j; 205 206 error = sysctl_handle_int(oidp, &log_frozen_devices, 0, req); 207 208 if (error || log_frozen_devices == 0) 209 return (error); 210 211 for (i = 0; i < isci->controller_count; i++) { 212 for (j = 0; j < SCI_MAX_REMOTE_DEVICES; j++) { 213 device = isci->controllers[i].remote_device[j]; 214 215 if (device == NULL) 216 continue; 217 218 device_printf(isci->device, 219 "controller %d device %3d frozen_lun_mask 0x%02x\n", 220 i, j, device->frozen_lun_mask); 221 } 222 } 223 224 return (0); 225 } 226 227 static int 228 isci_sysctl_fail_on_task_timeout(SYSCTL_HANDLER_ARGS) 229 { 230 struct isci_softc *isci = (struct isci_softc *)arg1; 231 int32_t fail_on_timeout; 232 int error, i; 233 234 fail_on_timeout = isci->controllers[0].fail_on_task_timeout; 235 error = sysctl_handle_int(oidp, &fail_on_timeout, 0, req); 236 237 if (error || req->newptr == NULL) 238 return (error); 239 240 for (i = 0; i < isci->controller_count; i++) 241 isci->controllers[i].fail_on_task_timeout = fail_on_timeout; 242 243 return (0); 244 } 245 246 void isci_sysctl_initialize(struct isci_softc *isci) 247 { 248 struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(isci->device); 249 struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(isci->device); 250 251 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 252 "coalesce_timeout", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 253 isci, 0, isci_sysctl_coalesce_timeout, "IU", 254 "Interrupt coalescing timeout (in microseconds)"); 255 256 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 257 "coalesce_number", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 258 isci, 0, isci_sysctl_coalesce_number, "IU", 259 "Interrupt coalescing number"); 260 261 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 262 "reset_remote_device_on_controller0", 263 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, isci, 0, 264 isci_sysctl_reset_remote_device_on_controller0, "IU", 265 "Reset remote device on controller 0"); 266 267 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 268 "reset_remote_device_on_controller1", 269 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 270 isci, 0, isci_sysctl_reset_remote_device_on_controller1, "IU", 271 "Reset remote device on controller 1"); 272 273 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 274 "stop_phy", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, isci, 275 0, isci_sysctl_stop_phy, "IU", "Stop PHY on a controller"); 276 277 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 278 "start_phy", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, isci, 279 0, isci_sysctl_start_phy, "IU", "Start PHY on a controller"); 280 281 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 282 "log_frozen_lun_masks", 283 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, isci, 0, 284 isci_sysctl_log_frozen_lun_masks, "IU", 285 "Log frozen lun masks to kernel log"); 286 287 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 288 "fail_on_task_timeout", 289 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, isci, 0, 290 isci_sysctl_fail_on_task_timeout, "IU", 291 "Fail a command that has encountered a task management timeout"); 292 } 293 294