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