11e66f787SSean Bruno /*- 29fac68fcSPAPANI SRIKANTH * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries. 31e66f787SSean Bruno * 41e66f787SSean Bruno * Redistribution and use in source and binary forms, with or without 51e66f787SSean Bruno * modification, are permitted provided that the following conditions 61e66f787SSean Bruno * are met: 71e66f787SSean Bruno * 1. Redistributions of source code must retain the above copyright 81e66f787SSean Bruno * notice, this list of conditions and the following disclaimer. 91e66f787SSean Bruno * 2. Redistributions in binary form must reproduce the above copyright 101e66f787SSean Bruno * notice, this list of conditions and the following disclaimer in the 111e66f787SSean Bruno * documentation and/or other materials provided with the distribution. 121e66f787SSean Bruno * 131e66f787SSean Bruno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 141e66f787SSean Bruno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 151e66f787SSean Bruno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 161e66f787SSean Bruno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 171e66f787SSean Bruno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 181e66f787SSean Bruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 191e66f787SSean Bruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 201e66f787SSean Bruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 211e66f787SSean Bruno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 221e66f787SSean Bruno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 231e66f787SSean Bruno * SUCH DAMAGE. 241e66f787SSean Bruno */ 251e66f787SSean Bruno 261e66f787SSean Bruno /* $FreeBSD$ */ 271e66f787SSean Bruno 281e66f787SSean Bruno #include "smartpqi_includes.h" 291e66f787SSean Bruno 309fac68fcSPAPANI SRIKANTH /* read and modify controller diagnostic option - PQI_PTRAID_UPDATE_ON_RESCAN_LUNS */ 319fac68fcSPAPANI SRIKANTH void 329fac68fcSPAPANI SRIKANTH pqisrc_ctrl_diagnostic_options(pqisrc_softstate_t *softs) 339fac68fcSPAPANI SRIKANTH { 349fac68fcSPAPANI SRIKANTH int ret = PQI_STATUS_SUCCESS; 359fac68fcSPAPANI SRIKANTH uint32_t diags_options = 0; 369fac68fcSPAPANI SRIKANTH pqisrc_raid_req_t request; 379fac68fcSPAPANI SRIKANTH 389fac68fcSPAPANI SRIKANTH DBG_NOTE("IN\n"); 399fac68fcSPAPANI SRIKANTH 409fac68fcSPAPANI SRIKANTH memset(&request, 0, sizeof(request)); 419fac68fcSPAPANI SRIKANTH /* read diags options of controller */ 429fac68fcSPAPANI SRIKANTH ret = pqisrc_build_send_raid_request(softs, &request, 439fac68fcSPAPANI SRIKANTH (void*)&diags_options, 449fac68fcSPAPANI SRIKANTH sizeof(diags_options), 459fac68fcSPAPANI SRIKANTH BMIC_SENSE_DIAGS_OPTIONS, 469fac68fcSPAPANI SRIKANTH 0, (uint8_t *)RAID_CTLR_LUNID, NULL); 479fac68fcSPAPANI SRIKANTH if (ret != PQI_STATUS_SUCCESS) { 489fac68fcSPAPANI SRIKANTH DBG_WARN("Request failed for BMIC Sense Diags Option command." 499fac68fcSPAPANI SRIKANTH "ret:%d\n",ret); 509fac68fcSPAPANI SRIKANTH return; 519fac68fcSPAPANI SRIKANTH } 529fac68fcSPAPANI SRIKANTH DBG_NOTE("diags options data after read: %#x\n",diags_options); 539fac68fcSPAPANI SRIKANTH diags_options |= PQI_PTRAID_UPDATE_ON_RESCAN_LUNS; 549fac68fcSPAPANI SRIKANTH DBG_NOTE("diags options data to write: %#x\n",diags_options); 559fac68fcSPAPANI SRIKANTH memset(&request, 0, sizeof(request)); 569fac68fcSPAPANI SRIKANTH /* write specified diags options to controller */ 579fac68fcSPAPANI SRIKANTH ret = pqisrc_build_send_raid_request(softs, &request, 589fac68fcSPAPANI SRIKANTH (void*)&diags_options, 599fac68fcSPAPANI SRIKANTH sizeof(diags_options), 609fac68fcSPAPANI SRIKANTH BMIC_SET_DIAGS_OPTIONS, 619fac68fcSPAPANI SRIKANTH 0, (uint8_t *)RAID_CTLR_LUNID, NULL); 629fac68fcSPAPANI SRIKANTH if (ret != PQI_STATUS_SUCCESS) 639fac68fcSPAPANI SRIKANTH DBG_WARN("Request failed for BMIC Set Diags Option command." 649fac68fcSPAPANI SRIKANTH "ret:%d\n",ret); 659fac68fcSPAPANI SRIKANTH #if 0 669fac68fcSPAPANI SRIKANTH diags_options = 0; 679fac68fcSPAPANI SRIKANTH memset(&request, 0, sizeof(request)); 689fac68fcSPAPANI SRIKANTH ret = pqisrc_build_send_raid_request(softs, &request, 699fac68fcSPAPANI SRIKANTH (void*)&diags_options, 709fac68fcSPAPANI SRIKANTH sizeof(diags_options), 719fac68fcSPAPANI SRIKANTH BMIC_SENSE_DIAGS_OPTIONS, 729fac68fcSPAPANI SRIKANTH 0, (uint8_t *)RAID_CTLR_LUNID, NULL); 739fac68fcSPAPANI SRIKANTH if (ret != PQI_STATUS_SUCCESS) 749fac68fcSPAPANI SRIKANTH DBG_WARN("Request failed for BMIC Sense Diags Option command." 759fac68fcSPAPANI SRIKANTH "ret:%d\n",ret); 769fac68fcSPAPANI SRIKANTH DBG_NOTE("diags options after re-read: %#x\n",diags_options); 779fac68fcSPAPANI SRIKANTH #endif 789fac68fcSPAPANI SRIKANTH DBG_NOTE("OUT\n"); 799fac68fcSPAPANI SRIKANTH } 809fac68fcSPAPANI SRIKANTH 811e66f787SSean Bruno /* 821e66f787SSean Bruno * Function used to validate the adapter health. 831e66f787SSean Bruno */ 849fac68fcSPAPANI SRIKANTH boolean_t 859fac68fcSPAPANI SRIKANTH pqisrc_ctrl_offline(pqisrc_softstate_t *softs) 861e66f787SSean Bruno { 871e66f787SSean Bruno DBG_FUNC("IN\n"); 881e66f787SSean Bruno 891e66f787SSean Bruno DBG_FUNC("OUT\n"); 901e66f787SSean Bruno 911e66f787SSean Bruno return !softs->ctrl_online; 921e66f787SSean Bruno } 931e66f787SSean Bruno 94b17f4335SSean Bruno /* Function used set/clear legacy INTx bit in Legacy Interrupt INTx 95b17f4335SSean Bruno * mask clear pqi register 96b17f4335SSean Bruno */ 979fac68fcSPAPANI SRIKANTH void 989fac68fcSPAPANI SRIKANTH pqisrc_configure_legacy_intx(pqisrc_softstate_t *softs, boolean_t enable_intx) 99b17f4335SSean Bruno { 100b17f4335SSean Bruno uint32_t intx_mask; 101e28289caSScott Long uint32_t *reg_addr __unused; 102b17f4335SSean Bruno 103b17f4335SSean Bruno DBG_FUNC("IN\n"); 104b17f4335SSean Bruno 105b17f4335SSean Bruno if (enable_intx) 106b17f4335SSean Bruno reg_addr = &softs->pqi_reg->legacy_intr_mask_clr; 107b17f4335SSean Bruno else 108b17f4335SSean Bruno reg_addr = &softs->pqi_reg->legacy_intr_mask_set; 109b17f4335SSean Bruno 110b17f4335SSean Bruno intx_mask = PCI_MEM_GET32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR); 111b17f4335SSean Bruno intx_mask |= PQISRC_LEGACY_INTX_MASK; 112b17f4335SSean Bruno PCI_MEM_PUT32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR ,intx_mask); 113b17f4335SSean Bruno 114b17f4335SSean Bruno DBG_FUNC("OUT\n"); 115b17f4335SSean Bruno } 116b17f4335SSean Bruno 1171e66f787SSean Bruno /* 1181e66f787SSean Bruno * Function used to take exposed devices to OS as offline. 1191e66f787SSean Bruno */ 1209fac68fcSPAPANI SRIKANTH void 1219fac68fcSPAPANI SRIKANTH pqisrc_take_devices_offline(pqisrc_softstate_t *softs) 1221e66f787SSean Bruno { 1231e66f787SSean Bruno pqi_scsi_dev_t *device = NULL; 1241e66f787SSean Bruno int i,j; 1251e66f787SSean Bruno 1261e66f787SSean Bruno DBG_FUNC("IN\n"); 1271e66f787SSean Bruno for(i = 0; i < PQI_MAX_DEVICES; i++) { 1281e66f787SSean Bruno for(j = 0; j < PQI_MAX_MULTILUN; j++) { 1291e66f787SSean Bruno if(softs->device_list[i][j] == NULL) 1301e66f787SSean Bruno continue; 1311e66f787SSean Bruno device = softs->device_list[i][j]; 1321e66f787SSean Bruno pqisrc_remove_device(softs, device); 1331e66f787SSean Bruno } 1341e66f787SSean Bruno } 1351e66f787SSean Bruno 1361e66f787SSean Bruno DBG_FUNC("OUT\n"); 1371e66f787SSean Bruno } 1381e66f787SSean Bruno 1391e66f787SSean Bruno /* 1401e66f787SSean Bruno * Function used to take adapter offline. 1411e66f787SSean Bruno */ 1429fac68fcSPAPANI SRIKANTH void 1439fac68fcSPAPANI SRIKANTH pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs) 1441e66f787SSean Bruno { 1451e66f787SSean Bruno DBG_FUNC("IN\n"); 1461e66f787SSean Bruno 1471e66f787SSean Bruno softs->ctrl_online = false; 1489fac68fcSPAPANI SRIKANTH 1499fac68fcSPAPANI SRIKANTH int lockupcode = 0; 1509fac68fcSPAPANI SRIKANTH 1519fac68fcSPAPANI SRIKANTH if (SIS_IS_KERNEL_PANIC(softs)) { 1529fac68fcSPAPANI SRIKANTH lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7); 153*d53e97bbSGordon Bergling DBG_ERR("Controller FW is not running, Lockup code = %x\n", lockupcode); 1549fac68fcSPAPANI SRIKANTH } 1559fac68fcSPAPANI SRIKANTH else { 1561e66f787SSean Bruno pqisrc_trigger_nmi_sis(softs); 1579fac68fcSPAPANI SRIKANTH } 1589fac68fcSPAPANI SRIKANTH 1591e66f787SSean Bruno os_complete_outstanding_cmds_nodevice(softs); 1609fac68fcSPAPANI SRIKANTH pqisrc_wait_for_rescan_complete(softs); 1611e66f787SSean Bruno pqisrc_take_devices_offline(softs); 1621e66f787SSean Bruno 1631e66f787SSean Bruno DBG_FUNC("OUT\n"); 1641e66f787SSean Bruno } 1651e66f787SSean Bruno 1661e66f787SSean Bruno /* 1671e66f787SSean Bruno * Timer handler for the adapter heart-beat. 1681e66f787SSean Bruno */ 1699fac68fcSPAPANI SRIKANTH void 1709fac68fcSPAPANI SRIKANTH pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs) 1711e66f787SSean Bruno { 1721e66f787SSean Bruno uint8_t take_offline = false; 1731e66f787SSean Bruno 1741e66f787SSean Bruno DBG_FUNC("IN\n"); 1751e66f787SSean Bruno 1761e66f787SSean Bruno if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) { 1771e66f787SSean Bruno take_offline = true; 1781e66f787SSean Bruno goto take_ctrl_offline; 1791e66f787SSean Bruno } 1801e66f787SSean Bruno softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs); 1811e66f787SSean Bruno DBG_INFO("CTRLR_HEARTBEAT_CNT(softs) = %lx \ 1821e66f787SSean Bruno softs->prev_heartbeat_count = %lx\n", 1831e66f787SSean Bruno CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count); 1841e66f787SSean Bruno 1851e66f787SSean Bruno take_ctrl_offline: 1861e66f787SSean Bruno if (take_offline){ 1871e66f787SSean Bruno DBG_ERR("controller is offline\n"); 1881e66f787SSean Bruno pqisrc_take_ctrl_offline(softs); 1891e66f787SSean Bruno os_stop_heartbeat_timer(softs); 1901e66f787SSean Bruno } 1911e66f787SSean Bruno DBG_FUNC("OUT\n"); 1921e66f787SSean Bruno } 1931e66f787SSean Bruno 1941e66f787SSean Bruno /* 1951e66f787SSean Bruno * Conditional variable management routine for internal commands. 1961e66f787SSean Bruno */ 1979fac68fcSPAPANI SRIKANTH int 1989fac68fcSPAPANI SRIKANTH pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb, 1999fac68fcSPAPANI SRIKANTH uint32_t timeout_in_msec) 2009fac68fcSPAPANI SRIKANTH { 2011e66f787SSean Bruno DBG_FUNC("IN\n"); 2021e66f787SSean Bruno 2031e66f787SSean Bruno int ret = PQI_STATUS_SUCCESS; 2049fac68fcSPAPANI SRIKANTH 2059fac68fcSPAPANI SRIKANTH /* 1 msec = 500 usec * 2 */ 2069fac68fcSPAPANI SRIKANTH uint32_t loop_cnt = timeout_in_msec * 2; 2079fac68fcSPAPANI SRIKANTH uint32_t i = 0; 2081e66f787SSean Bruno 2091e66f787SSean Bruno while (rcb->req_pending == true) { 2101e66f787SSean Bruno OS_SLEEP(500); /* Micro sec */ 2111e66f787SSean Bruno /* Polling needed for FreeBSD : since ithread routine is not scheduled 2129fac68fcSPAPANI SRIKANTH * during bootup, we could use polling until interrupts are 2139fac68fcSPAPANI SRIKANTH * enabled (using 'if (cold)'to check for the boot time before 2149fac68fcSPAPANI SRIKANTH * interrupts are enabled). */ 2151e66f787SSean Bruno IS_POLLING_REQUIRED(softs); 2161e66f787SSean Bruno 2179fac68fcSPAPANI SRIKANTH if ((timeout_in_msec != TIMEOUT_INFINITE) && (i++ == loop_cnt)) { 2181e66f787SSean Bruno DBG_ERR("ERR: Requested cmd timed out !!!\n"); 2191e66f787SSean Bruno ret = PQI_STATUS_TIMEOUT; 2209fac68fcSPAPANI SRIKANTH rcb->timedout = true; 2211e66f787SSean Bruno break; 2221e66f787SSean Bruno } 2231e66f787SSean Bruno 2241e66f787SSean Bruno if (pqisrc_ctrl_offline(softs)) { 2251e66f787SSean Bruno DBG_ERR("Controller is Offline"); 2261e66f787SSean Bruno ret = PQI_STATUS_FAILURE; 2271e66f787SSean Bruno break; 2281e66f787SSean Bruno } 2299fac68fcSPAPANI SRIKANTH 2301e66f787SSean Bruno } 2311e66f787SSean Bruno rcb->req_pending = true; 2321e66f787SSean Bruno 2331e66f787SSean Bruno DBG_FUNC("OUT\n"); 2341e66f787SSean Bruno 2351e66f787SSean Bruno return ret; 2361e66f787SSean Bruno } 2371e66f787SSean Bruno 2381e66f787SSean Bruno /* Function used to validate the device wwid. */ 2399fac68fcSPAPANI SRIKANTH boolean_t 2409fac68fcSPAPANI SRIKANTH pqisrc_device_equal(pqi_scsi_dev_t *dev1, 2411e66f787SSean Bruno pqi_scsi_dev_t *dev2) 2421e66f787SSean Bruno { 2431e66f787SSean Bruno return dev1->wwid == dev2->wwid; 2441e66f787SSean Bruno } 2451e66f787SSean Bruno 2461e66f787SSean Bruno /* Function used to validate the device scsi3addr. */ 2479fac68fcSPAPANI SRIKANTH boolean_t 2489fac68fcSPAPANI SRIKANTH pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2) 2491e66f787SSean Bruno { 2501e66f787SSean Bruno return memcmp(scsi3addr1, scsi3addr2, 8) == 0; 2511e66f787SSean Bruno } 2521e66f787SSean Bruno 2531e66f787SSean Bruno /* Function used to validate hba_lunid */ 2549fac68fcSPAPANI SRIKANTH boolean_t 2559fac68fcSPAPANI SRIKANTH pqisrc_is_hba_lunid(uint8_t *scsi3addr) 2561e66f787SSean Bruno { 2571e66f787SSean Bruno return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID); 2581e66f787SSean Bruno } 2591e66f787SSean Bruno 2601e66f787SSean Bruno /* Function used to validate type of device */ 2619fac68fcSPAPANI SRIKANTH boolean_t 2629fac68fcSPAPANI SRIKANTH pqisrc_is_logical_device(pqi_scsi_dev_t *device) 2631e66f787SSean Bruno { 2641e66f787SSean Bruno return !device->is_physical_device; 2651e66f787SSean Bruno } 2661e66f787SSean Bruno 2671e66f787SSean Bruno /* Function used to sanitize inquiry string */ 2689fac68fcSPAPANI SRIKANTH void 2699fac68fcSPAPANI SRIKANTH pqisrc_sanitize_inquiry_string(unsigned char *s, int len) 2701e66f787SSean Bruno { 2711e66f787SSean Bruno boolean_t terminated = false; 2721e66f787SSean Bruno 2731e66f787SSean Bruno DBG_FUNC("IN\n"); 2741e66f787SSean Bruno 2751e66f787SSean Bruno for (; len > 0; (--len, ++s)) { 2761e66f787SSean Bruno if (*s == 0) 2771e66f787SSean Bruno terminated = true; 2781e66f787SSean Bruno if (terminated || *s < 0x20 || *s > 0x7e) 2791e66f787SSean Bruno *s = ' '; 2801e66f787SSean Bruno } 2811e66f787SSean Bruno 2821e66f787SSean Bruno DBG_FUNC("OUT\n"); 2831e66f787SSean Bruno } 2841e66f787SSean Bruno 2851e66f787SSean Bruno static char *raid_levels[] = { 2861e66f787SSean Bruno "RAID 0", 2871e66f787SSean Bruno "RAID 4", 2881e66f787SSean Bruno "RAID 1(1+0)", 2891e66f787SSean Bruno "RAID 5", 2901e66f787SSean Bruno "RAID 5+1", 2911e66f787SSean Bruno "RAID ADG", 2921e66f787SSean Bruno "RAID 1(ADM)", 2931e66f787SSean Bruno }; 2941e66f787SSean Bruno 2951e66f787SSean Bruno /* Get the RAID level from the index */ 2969fac68fcSPAPANI SRIKANTH char * 2979fac68fcSPAPANI SRIKANTH pqisrc_raidlevel_to_string(uint8_t raid_level) 2981e66f787SSean Bruno { 2991e66f787SSean Bruno DBG_FUNC("IN\n"); 3001e66f787SSean Bruno if (raid_level < ARRAY_SIZE(raid_levels)) 3011e66f787SSean Bruno return raid_levels[raid_level]; 3021e66f787SSean Bruno DBG_FUNC("OUT\n"); 3031e66f787SSean Bruno 3041e66f787SSean Bruno return " "; 3051e66f787SSean Bruno } 3061e66f787SSean Bruno 3071e66f787SSean Bruno /* Debug routine for displaying device info */ 3084f77349dSWarner Losh void pqisrc_display_device_info(pqisrc_softstate_t *softs, 3091e66f787SSean Bruno char *action, pqi_scsi_dev_t *device) 3101e66f787SSean Bruno { 3114f77349dSWarner Losh if (device->is_physical_device) { 3124f77349dSWarner Losh DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 3134f77349dSWarner Losh "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 3144f77349dSWarner Losh action, 3154f77349dSWarner Losh device->bus, 3164f77349dSWarner Losh device->target, 3174f77349dSWarner Losh device->lun, 3184f77349dSWarner Losh device->vendor, 3194f77349dSWarner Losh device->model, 3204f77349dSWarner Losh "Physical", 3214f77349dSWarner Losh device->offload_config ? '+' : '-', 3224f77349dSWarner Losh device->offload_enabled_pending ? '+' : '-', 3234f77349dSWarner Losh device->expose_device ? '+' : '-', 3244f77349dSWarner Losh device->queue_depth); 3254f77349dSWarner Losh } else if (device->devtype == RAID_DEVICE) { 3264f77349dSWarner Losh DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 3274f77349dSWarner Losh "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 3284f77349dSWarner Losh action, 3294f77349dSWarner Losh device->bus, 3304f77349dSWarner Losh device->target, 3314f77349dSWarner Losh device->lun, 3324f77349dSWarner Losh device->vendor, 3334f77349dSWarner Losh device->model, 3344f77349dSWarner Losh "Controller", 3354f77349dSWarner Losh device->offload_config ? '+' : '-', 3364f77349dSWarner Losh device->offload_enabled_pending ? '+' : '-', 3374f77349dSWarner Losh device->expose_device ? '+' : '-', 3384f77349dSWarner Losh device->queue_depth); 3394f77349dSWarner Losh } else if (device->devtype == CONTROLLER_DEVICE) { 3404f77349dSWarner Losh DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 3414f77349dSWarner Losh "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 3424f77349dSWarner Losh action, 3434f77349dSWarner Losh device->bus, 3444f77349dSWarner Losh device->target, 3454f77349dSWarner Losh device->lun, 3464f77349dSWarner Losh device->vendor, 3474f77349dSWarner Losh device->model, 3484f77349dSWarner Losh "External", 3494f77349dSWarner Losh device->offload_config ? '+' : '-', 3504f77349dSWarner Losh device->offload_enabled_pending ? '+' : '-', 3514f77349dSWarner Losh device->expose_device ? '+' : '-', 3524f77349dSWarner Losh device->queue_depth); 3534f77349dSWarner Losh } else { 3544f77349dSWarner Losh DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 3554f77349dSWarner Losh "SSDSmartPathCap%c En%c Exp%c qd=%d devtype=%d\n", 3561e66f787SSean Bruno action, 3571e66f787SSean Bruno device->bus, 3581e66f787SSean Bruno device->target, 3591e66f787SSean Bruno device->lun, 3601e66f787SSean Bruno device->vendor, 3611e66f787SSean Bruno device->model, 3621e66f787SSean Bruno pqisrc_raidlevel_to_string(device->raid_level), 3631e66f787SSean Bruno device->offload_config ? '+' : '-', 3641e66f787SSean Bruno device->offload_enabled_pending ? '+' : '-', 3651e66f787SSean Bruno device->expose_device ? '+' : '-', 3664f77349dSWarner Losh device->queue_depth, 3674f77349dSWarner Losh device->devtype); 3681e66f787SSean Bruno pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */ 3691e66f787SSean Bruno } 3704f77349dSWarner Losh } 3711e66f787SSean Bruno 3721e66f787SSean Bruno /* validate the structure sizes */ 3739fac68fcSPAPANI SRIKANTH void 374fb1c2168SDimitry Andric check_struct_sizes(void) 3751e66f787SSean Bruno { 3761e66f787SSean Bruno 3771e66f787SSean Bruno ASSERT(sizeof(SCSI3Addr_struct)== 2); 3781e66f787SSean Bruno ASSERT(sizeof(PhysDevAddr_struct) == 8); 3791e66f787SSean Bruno ASSERT(sizeof(LogDevAddr_struct)== 8); 3801e66f787SSean Bruno ASSERT(sizeof(LUNAddr_struct)==8); 3811e66f787SSean Bruno ASSERT(sizeof(RequestBlock_struct) == 20); 3821e66f787SSean Bruno ASSERT(sizeof(MoreErrInfo_struct)== 8); 3831e66f787SSean Bruno ASSERT(sizeof(ErrorInfo_struct)== 48); 3849fac68fcSPAPANI SRIKANTH /* Checking the size of IOCTL_Command_struct for both 3859fac68fcSPAPANI SRIKANTH 64 bit and 32 bit system*/ 3869fac68fcSPAPANI SRIKANTH ASSERT(sizeof(IOCTL_Command_struct)== 86 || 3879fac68fcSPAPANI SRIKANTH sizeof(IOCTL_Command_struct)== 82); 3881e66f787SSean Bruno ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42); 3891e66f787SSean Bruno ASSERT(sizeof(struct bmic_host_wellness_time)== 20); 3901e66f787SSean Bruno ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8); 3911e66f787SSean Bruno ASSERT(sizeof(struct admin_q_param)== 4); 3921e66f787SSean Bruno ASSERT(sizeof(struct pqi_registers)== 256); 3931e66f787SSean Bruno ASSERT(sizeof(struct ioa_registers)== 4128); 3941e66f787SSean Bruno ASSERT(sizeof(struct pqi_pref_settings)==4); 3951e66f787SSean Bruno ASSERT(sizeof(struct pqi_cap)== 20); 3961e66f787SSean Bruno ASSERT(sizeof(iu_header_t)== 4); 3971e66f787SSean Bruno ASSERT(sizeof(gen_adm_req_iu_t)== 64); 3981e66f787SSean Bruno ASSERT(sizeof(gen_adm_resp_iu_t)== 64); 3991e66f787SSean Bruno ASSERT(sizeof(op_q_params) == 9); 4001e66f787SSean Bruno ASSERT(sizeof(raid_path_error_info_elem_t)== 276); 4011e66f787SSean Bruno ASSERT(sizeof(aio_path_error_info_elem_t)== 276); 4021e66f787SSean Bruno ASSERT(sizeof(struct init_base_struct)== 24); 4031e66f787SSean Bruno ASSERT(sizeof(pqi_iu_layer_desc_t)== 16); 4041e66f787SSean Bruno ASSERT(sizeof(pqi_dev_cap_t)== 576); 4051e66f787SSean Bruno ASSERT(sizeof(pqi_aio_req_t)== 128); 4061e66f787SSean Bruno ASSERT(sizeof(pqisrc_raid_req_t)== 128); 4079fac68fcSPAPANI SRIKANTH ASSERT(sizeof(pqi_raid_tmf_req_t)== 32); 4089fac68fcSPAPANI SRIKANTH ASSERT(sizeof(pqi_aio_tmf_req_t)== 32); 4091e66f787SSean Bruno ASSERT(sizeof(struct pqi_io_response)== 16); 4101e66f787SSean Bruno ASSERT(sizeof(struct sense_header_scsi)== 8); 4111e66f787SSean Bruno ASSERT(sizeof(reportlun_header_t)==8); 4121e66f787SSean Bruno ASSERT(sizeof(reportlun_ext_entry_t)== 24); 4131e66f787SSean Bruno ASSERT(sizeof(reportlun_data_ext_t)== 32); 4141e66f787SSean Bruno ASSERT(sizeof(raidmap_data_t)==8); 4151e66f787SSean Bruno ASSERT(sizeof(pqisrc_raid_map_t)== 8256); 4161e66f787SSean Bruno ASSERT(sizeof(bmic_ident_ctrl_t)== 325); 4171e66f787SSean Bruno ASSERT(sizeof(bmic_ident_physdev_t)==2048); 4181e66f787SSean Bruno 4191e66f787SSean Bruno } 4209fac68fcSPAPANI SRIKANTH 4219fac68fcSPAPANI SRIKANTH uint32_t 4229fac68fcSPAPANI SRIKANTH pqisrc_count_num_scsi_active_requests_on_dev(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 4239fac68fcSPAPANI SRIKANTH { 4249fac68fcSPAPANI SRIKANTH uint32_t i, active_io = 0; 4259fac68fcSPAPANI SRIKANTH rcb_t* rcb; 4269fac68fcSPAPANI SRIKANTH 4279fac68fcSPAPANI SRIKANTH for(i = 1; i <= softs->max_outstanding_io; i++) { 4289fac68fcSPAPANI SRIKANTH rcb = &softs->rcb[i]; 4299fac68fcSPAPANI SRIKANTH if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) { 4309fac68fcSPAPANI SRIKANTH active_io++; 4319fac68fcSPAPANI SRIKANTH } 4329fac68fcSPAPANI SRIKANTH } 4339fac68fcSPAPANI SRIKANTH return active_io; 4349fac68fcSPAPANI SRIKANTH } 4359fac68fcSPAPANI SRIKANTH 4369fac68fcSPAPANI SRIKANTH void 4379fac68fcSPAPANI SRIKANTH check_device_pending_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 4389fac68fcSPAPANI SRIKANTH { 4399fac68fcSPAPANI SRIKANTH uint32_t tag = softs->max_outstanding_io, active_requests; 4409fac68fcSPAPANI SRIKANTH uint64_t timeout = 0, delay_in_usec = 1000; //In micro Seconds 4419fac68fcSPAPANI SRIKANTH rcb_t* rcb; 4429fac68fcSPAPANI SRIKANTH 4439fac68fcSPAPANI SRIKANTH DBG_FUNC("IN\n"); 4449fac68fcSPAPANI SRIKANTH 4459fac68fcSPAPANI SRIKANTH active_requests = pqisrc_count_num_scsi_active_requests_on_dev(softs, device); 4469fac68fcSPAPANI SRIKANTH 4479fac68fcSPAPANI SRIKANTH DBG_WARN("Device Outstanding IO count = %u\n", active_requests); 4489fac68fcSPAPANI SRIKANTH 4499fac68fcSPAPANI SRIKANTH if(!active_requests) 4509fac68fcSPAPANI SRIKANTH return; 4519fac68fcSPAPANI SRIKANTH 4529fac68fcSPAPANI SRIKANTH do { 4539fac68fcSPAPANI SRIKANTH rcb = &softs->rcb[tag]; 4549fac68fcSPAPANI SRIKANTH if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) { 4559fac68fcSPAPANI SRIKANTH OS_BUSYWAIT(delay_in_usec); 4569fac68fcSPAPANI SRIKANTH timeout += delay_in_usec; 4579fac68fcSPAPANI SRIKANTH } 4589fac68fcSPAPANI SRIKANTH else 4599fac68fcSPAPANI SRIKANTH tag--; 4609fac68fcSPAPANI SRIKANTH if(timeout >= PQISRC_PENDING_IO_TIMEOUT_USEC) { 4619fac68fcSPAPANI SRIKANTH DBG_WARN("timed out waiting for pending IO\n"); 4629fac68fcSPAPANI SRIKANTH return; 4639fac68fcSPAPANI SRIKANTH } 4649fac68fcSPAPANI SRIKANTH } while(tag); 4659fac68fcSPAPANI SRIKANTH 4669fac68fcSPAPANI SRIKANTH } 4679fac68fcSPAPANI SRIKANTH 4689fac68fcSPAPANI SRIKANTH inline uint64_t 4699fac68fcSPAPANI SRIKANTH pqisrc_increment_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 4709fac68fcSPAPANI SRIKANTH { 4719fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER 4729fac68fcSPAPANI SRIKANTH /*Increment device active io count by one*/ 4739fac68fcSPAPANI SRIKANTH return OS_ATOMIC64_INC(&device->active_requests); 4749fac68fcSPAPANI SRIKANTH #endif 4759fac68fcSPAPANI SRIKANTH } 4769fac68fcSPAPANI SRIKANTH 4779fac68fcSPAPANI SRIKANTH inline uint64_t 4789fac68fcSPAPANI SRIKANTH pqisrc_decrement_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 4799fac68fcSPAPANI SRIKANTH { 4809fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER 4819fac68fcSPAPANI SRIKANTH /*Decrement device active io count by one*/ 4829fac68fcSPAPANI SRIKANTH return OS_ATOMIC64_DEC(&device->active_requests); 4839fac68fcSPAPANI SRIKANTH #endif 4849fac68fcSPAPANI SRIKANTH } 4859fac68fcSPAPANI SRIKANTH 4869fac68fcSPAPANI SRIKANTH inline void 4879fac68fcSPAPANI SRIKANTH pqisrc_init_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 4889fac68fcSPAPANI SRIKANTH { 4899fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER 4909fac68fcSPAPANI SRIKANTH /* Reset device count to Zero */ 4919fac68fcSPAPANI SRIKANTH OS_ATOMIC64_INIT(&device->active_requests, 0); 4929fac68fcSPAPANI SRIKANTH #endif 4939fac68fcSPAPANI SRIKANTH } 4949fac68fcSPAPANI SRIKANTH 4959fac68fcSPAPANI SRIKANTH inline uint64_t 4969fac68fcSPAPANI SRIKANTH pqisrc_read_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 4979fac68fcSPAPANI SRIKANTH { 4989fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER 4999fac68fcSPAPANI SRIKANTH /* read device active count*/ 5009fac68fcSPAPANI SRIKANTH return OS_ATOMIC64_READ(&device->active_requests); 5019fac68fcSPAPANI SRIKANTH #endif 5029fac68fcSPAPANI SRIKANTH } 5039fac68fcSPAPANI SRIKANTH 5049fac68fcSPAPANI SRIKANTH void 5059fac68fcSPAPANI SRIKANTH pqisrc_wait_for_device_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 5069fac68fcSPAPANI SRIKANTH { 5079fac68fcSPAPANI SRIKANTH uint64_t timeout_in_usec = 0, delay_in_usec = 1000; //In microseconds 5089fac68fcSPAPANI SRIKANTH 5099fac68fcSPAPANI SRIKANTH DBG_FUNC("IN\n"); 5109fac68fcSPAPANI SRIKANTH 5119fac68fcSPAPANI SRIKANTH if(!softs->ctrl_online) 5129fac68fcSPAPANI SRIKANTH return; 5139fac68fcSPAPANI SRIKANTH 5149fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER 5159fac68fcSPAPANI SRIKANTH DBG_NOTE("Device Outstanding IO count = %ld\n", pqisrc_read_device_active_io(softs, device)); 5169fac68fcSPAPANI SRIKANTH 5179fac68fcSPAPANI SRIKANTH while(pqisrc_read_device_active_io(softs, device)) { 5189fac68fcSPAPANI SRIKANTH OS_BUSYWAIT(delay_in_usec); // In microseconds 5199fac68fcSPAPANI SRIKANTH if(!softs->ctrl_online) { 5209fac68fcSPAPANI SRIKANTH DBG_WARN("Controller Offline was detected.\n"); 5219fac68fcSPAPANI SRIKANTH } 5229fac68fcSPAPANI SRIKANTH timeout_in_usec += delay_in_usec; 5239fac68fcSPAPANI SRIKANTH if(timeout_in_usec >= PQISRC_PENDING_IO_TIMEOUT_USEC) { 5249fac68fcSPAPANI SRIKANTH DBG_WARN("timed out waiting for pending IO. DeviceOutStandingIo's=%ld\n", 5259fac68fcSPAPANI SRIKANTH pqisrc_read_device_active_io(softs, device)); 5269fac68fcSPAPANI SRIKANTH return; 5279fac68fcSPAPANI SRIKANTH } 5289fac68fcSPAPANI SRIKANTH } 5299fac68fcSPAPANI SRIKANTH #else 5309fac68fcSPAPANI SRIKANTH check_device_pending_commands_to_complete(softs, device); 5319fac68fcSPAPANI SRIKANTH #endif 5329fac68fcSPAPANI SRIKANTH } 533