1 /*- 2 * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 27 #include "smartpqi_includes.h" 28 29 /* 30 * Function used to validate the adapter health. 31 */ 32 boolean_t 33 pqisrc_ctrl_offline(pqisrc_softstate_t *softs) 34 { 35 DBG_FUNC("IN\n"); 36 37 DBG_FUNC("OUT\n"); 38 39 return !softs->ctrl_online; 40 } 41 /* Function used set/clear legacy INTx bit in Legacy Interrupt INTx 42 * mask clear pqi register 43 */ 44 void 45 pqisrc_configure_legacy_intx(pqisrc_softstate_t *softs, boolean_t enable_intx) 46 { 47 uint32_t intx_mask; 48 49 DBG_FUNC("IN\n"); 50 51 intx_mask = PCI_MEM_GET32(softs, 0, PQI_LEGACY_INTR_MASK_CLR); 52 intx_mask |= PQISRC_LEGACY_INTX_MASK; 53 PCI_MEM_PUT32(softs, 0, PQI_LEGACY_INTR_MASK_CLR ,intx_mask); 54 55 DBG_FUNC("OUT\n"); 56 } 57 58 /* 59 * Function used to take exposed devices to OS as offline. 60 */ 61 void 62 pqisrc_take_devices_offline(pqisrc_softstate_t *softs) 63 { 64 pqi_scsi_dev_t *device = NULL; 65 int i; 66 67 DBG_FUNC("IN\n"); 68 for(i = 0; i < PQI_MAX_DEVICES; i++) { 69 device = softs->dev_list[i]; 70 if(device == NULL) 71 continue; 72 pqisrc_remove_device(softs, device); 73 } 74 75 DBG_FUNC("OUT\n"); 76 } 77 78 /* 79 * Function used to take adapter offline. 80 */ 81 void 82 pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs) 83 { 84 DBG_FUNC("IN\n"); 85 86 int lockupcode = 0; 87 88 softs->ctrl_online = false; 89 90 if (SIS_IS_KERNEL_PANIC(softs)) { 91 lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7); 92 DBG_ERR("Controller FW is not running, Lockup code = %x\n", lockupcode); 93 } 94 else { 95 pqisrc_trigger_nmi_sis(softs); 96 } 97 98 os_complete_outstanding_cmds_nodevice(softs); 99 pqisrc_wait_for_rescan_complete(softs); 100 pqisrc_take_devices_offline(softs); 101 102 DBG_FUNC("OUT\n"); 103 } 104 105 /* 106 * Timer handler for the adapter heart-beat. 107 */ 108 void 109 pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs) 110 { 111 uint8_t take_offline = false; 112 uint64_t new_heartbeat; 113 static uint32_t running_ping_cnt = 0; 114 115 DBG_FUNC("IN\n"); 116 117 new_heartbeat = CTRLR_HEARTBEAT_CNT(softs); 118 DBG_IO("heartbeat old=%lx new=%lx\n", softs->prev_heartbeat_count, new_heartbeat); 119 120 if (new_heartbeat == softs->prev_heartbeat_count) { 121 take_offline = true; 122 goto take_ctrl_offline; 123 } 124 125 #if 1 126 /* print every 30 calls (should print once/minute) */ 127 running_ping_cnt++; 128 129 if ((running_ping_cnt % 30) == 0) 130 print_all_counters(softs, COUNTER_FLAG_ONLY_NON_ZERO); 131 #endif 132 133 softs->prev_heartbeat_count = new_heartbeat; 134 135 take_ctrl_offline: 136 if (take_offline){ 137 DBG_ERR("controller is offline\n"); 138 os_stop_heartbeat_timer(softs); 139 pqisrc_take_ctrl_offline(softs); 140 } 141 DBG_FUNC("OUT\n"); 142 } 143 144 /* 145 * Conditional variable management routine for internal commands. 146 */ 147 int 148 pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb, 149 uint32_t timeout_in_msec) 150 { 151 DBG_FUNC("IN\n"); 152 153 int ret = PQI_STATUS_SUCCESS; 154 155 /* 1 msec = 500 usec * 2 */ 156 uint32_t loop_cnt = timeout_in_msec * 2; 157 uint32_t i = 0; 158 159 while (rcb->req_pending == true) { 160 OS_SLEEP(500); /* Micro sec */ 161 /* Polling needed for FreeBSD : since ithread routine is not scheduled 162 * during bootup, we could use polling until interrupts are 163 * enabled (using 'if (cold)'to check for the boot time before 164 * interrupts are enabled). */ 165 IS_POLLING_REQUIRED(softs); 166 167 if ((timeout_in_msec != TIMEOUT_INFINITE) && (i++ == loop_cnt)) { 168 DBG_ERR("ERR: Requested cmd timed out !!!\n"); 169 ret = PQI_STATUS_TIMEOUT; 170 rcb->timedout = true; 171 break; 172 } 173 174 if (pqisrc_ctrl_offline(softs)) { 175 DBG_ERR("Controller is Offline"); 176 ret = PQI_STATUS_FAILURE; 177 break; 178 } 179 180 } 181 rcb->req_pending = true; 182 183 DBG_FUNC("OUT\n"); 184 185 return ret; 186 } 187 188 /* Function used to validate the device wwid. */ 189 boolean_t 190 pqisrc_device_equal(pqi_scsi_dev_t *dev1, 191 pqi_scsi_dev_t *dev2) 192 { 193 return dev1->wwid == dev2->wwid; 194 } 195 196 /* Function used to validate the device scsi3addr. */ 197 boolean_t 198 pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2) 199 { 200 return memcmp(scsi3addr1, scsi3addr2, 8) == 0; 201 } 202 203 /* Function used to validate hba_lunid */ 204 boolean_t 205 pqisrc_is_hba_lunid(uint8_t *scsi3addr) 206 { 207 return pqisrc_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID); 208 } 209 210 /* Function used to validate type of device */ 211 boolean_t 212 pqisrc_is_logical_device(pqi_scsi_dev_t *device) 213 { 214 return !device->is_physical_device; 215 } 216 217 /* Function used to sanitize inquiry string */ 218 void 219 pqisrc_sanitize_inquiry_string(unsigned char *s, int len) 220 { 221 boolean_t terminated = false; 222 223 DBG_FUNC("IN\n"); 224 225 for (; len > 0; (--len, ++s)) { 226 if (*s == 0) 227 terminated = true; 228 if (terminated || *s < 0x20 || *s > 0x7e) 229 *s = ' '; 230 } 231 232 DBG_FUNC("OUT\n"); 233 } 234 235 static char *raid_levels[] = { 236 "RAID 0", 237 "RAID 4", 238 "RAID 1(1+0)", 239 "RAID 5", 240 "RAID 5+1", 241 "RAID 6", 242 "RAID 1(Triple)", 243 }; 244 245 /* Get the RAID level from the index */ 246 char * 247 pqisrc_raidlevel_to_string(uint8_t raid_level) 248 { 249 DBG_FUNC("IN\n"); 250 if (raid_level < ARRAY_SIZE(raid_levels)) 251 return raid_levels[raid_level]; 252 DBG_FUNC("OUT\n"); 253 254 return " "; 255 } 256 257 /* Debug routine for displaying device info */ 258 void pqisrc_display_device_info(pqisrc_softstate_t *softs, 259 char *action, pqi_scsi_dev_t *device) 260 { 261 if (device->is_physical_device) { 262 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 263 "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 264 action, 265 device->bus, 266 device->target, 267 device->lun, 268 device->vendor, 269 device->model, 270 "Physical", 271 device->offload_config ? '+' : '-', 272 device->offload_enabled_pending ? '+' : '-', 273 device->expose_device ? '+' : '-', 274 device->queue_depth); 275 } else if (device->devtype == RAID_DEVICE) { 276 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 277 "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 278 action, 279 device->bus, 280 device->target, 281 device->lun, 282 device->vendor, 283 device->model, 284 "Controller", 285 device->offload_config ? '+' : '-', 286 device->offload_enabled_pending ? '+' : '-', 287 device->expose_device ? '+' : '-', 288 device->queue_depth); 289 } else if (device->devtype == CONTROLLER_DEVICE) { 290 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 291 "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 292 action, 293 device->bus, 294 device->target, 295 device->lun, 296 device->vendor, 297 device->model, 298 "External", 299 device->offload_config ? '+' : '-', 300 device->offload_enabled_pending ? '+' : '-', 301 device->expose_device ? '+' : '-', 302 device->queue_depth); 303 } else { 304 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 305 "SSDSmartPathCap%c En%c Exp%c qd=%d devtype=%d\n", 306 action, 307 device->bus, 308 device->target, 309 device->lun, 310 device->vendor, 311 device->model, 312 pqisrc_raidlevel_to_string(device->raid_level), 313 device->offload_config ? '+' : '-', 314 device->offload_enabled_pending ? '+' : '-', 315 device->expose_device ? '+' : '-', 316 device->queue_depth, 317 device->devtype); 318 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */ 319 } 320 } 321 322 /* validate the structure sizes */ 323 void 324 check_struct_sizes(void) 325 { 326 327 ASSERT(sizeof(SCSI3Addr_struct)== 2); 328 ASSERT(sizeof(PhysDevAddr_struct) == 8); 329 ASSERT(sizeof(LogDevAddr_struct)== 8); 330 ASSERT(sizeof(LUNAddr_struct)==8); 331 ASSERT(sizeof(RequestBlock_struct) == 20); 332 ASSERT(sizeof(MoreErrInfo_struct)== 8); 333 ASSERT(sizeof(ErrorInfo_struct)== 48); 334 /* Checking the size of IOCTL_Command_struct for both 335 64 bit and 32 bit system*/ 336 ASSERT(sizeof(IOCTL_Command_struct)== 86 || 337 sizeof(IOCTL_Command_struct)== 82); 338 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42); 339 ASSERT(sizeof(struct bmic_host_wellness_time)== 20); 340 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8); 341 ASSERT(sizeof(struct admin_q_param)== 4); 342 ASSERT(sizeof(struct pqi_registers)== 256); 343 ASSERT(sizeof(struct ioa_registers)== 4128); 344 ASSERT(sizeof(struct pqi_pref_settings)==4); 345 ASSERT(sizeof(struct pqi_cap)== 20); 346 ASSERT(sizeof(iu_header_t)== 4); 347 ASSERT(sizeof(gen_adm_req_iu_t)== 64); 348 ASSERT(sizeof(gen_adm_resp_iu_t)== 64); 349 ASSERT(sizeof(op_q_params) == 9); 350 ASSERT(sizeof(raid_path_error_info_elem_t)== 276); 351 ASSERT(sizeof(aio_path_error_info_elem_t)== 276); 352 ASSERT(sizeof(struct init_base_struct)== 24); 353 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16); 354 ASSERT(sizeof(pqi_dev_cap_t)== 576); 355 ASSERT(sizeof(pqi_aio_req_t)== 128); 356 ASSERT(sizeof(pqisrc_raid_req_t)== 128); 357 ASSERT(sizeof(pqi_raid_tmf_req_t)== 32); 358 ASSERT(sizeof(pqi_aio_tmf_req_t)== 32); 359 ASSERT(sizeof(struct pqi_io_response)== 16); 360 ASSERT(sizeof(struct sense_header_scsi)== 8); 361 ASSERT(sizeof(reportlun_header_t)==8); 362 ASSERT(sizeof(reportlun_ext_entry_t)== 24); 363 ASSERT(sizeof(reportlun_data_ext_t)== 32); 364 ASSERT(sizeof(raidmap_data_t)==8); 365 ASSERT(sizeof(pqisrc_raid_map_t)== 8256); 366 ASSERT(sizeof(bmic_ident_ctrl_t)== 325); 367 ASSERT(sizeof(bmic_ident_physdev_t)==2048); 368 369 } 370 371 #if 0 372 uint32_t 373 pqisrc_count_num_scsi_active_requests_on_dev(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 374 { 375 uint32_t i, active_io = 0; 376 rcb_t* rcb; 377 378 for(i = 1; i <= softs->max_outstanding_io; i++) { 379 rcb = &softs->rcb[i]; 380 if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) { 381 active_io++; 382 } 383 } 384 return active_io; 385 } 386 387 void 388 check_device_pending_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 389 { 390 uint32_t tag = softs->max_outstanding_io, active_requests; 391 uint64_t timeout = 0, delay_in_usec = 1000; /* In micro Seconds */ 392 rcb_t* rcb; 393 394 DBG_FUNC("IN\n"); 395 396 active_requests = pqisrc_count_num_scsi_active_requests_on_dev(softs, device); 397 398 DBG_WARN("Device Outstanding IO count = %u\n", active_requests); 399 400 if(!active_requests) 401 return; 402 403 do { 404 rcb = &softs->rcb[tag]; 405 if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) { 406 OS_SLEEP(delay_in_usec); 407 timeout += delay_in_usec; 408 } 409 else 410 tag--; 411 if(timeout >= PQISRC_PENDING_IO_TIMEOUT_USEC) { 412 DBG_WARN("timed out waiting for pending IO\n"); 413 return; 414 } 415 } while(tag); 416 } 417 #endif 418 419 void 420 pqisrc_wait_for_device_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 421 { 422 uint64_t timeout_in_usec = 0, delay_in_usec = 1000; /* In microseconds */ 423 424 DBG_FUNC("IN\n"); 425 426 if(!softs->ctrl_online) 427 return; 428 429 #if PQISRC_DEVICE_IO_COUNTER 430 DBG_WARN_BTL(device,"Device Outstanding IO count = %lu\n", pqisrc_read_device_active_io(softs, device)); 431 432 while(pqisrc_read_device_active_io(softs, device)) { 433 OS_BUSYWAIT(delay_in_usec); /* In microseconds */ 434 if(!softs->ctrl_online) { 435 DBG_WARN("Controller Offline was detected.\n"); 436 } 437 timeout_in_usec += delay_in_usec; 438 if(timeout_in_usec >= PQISRC_PENDING_IO_TIMEOUT_USEC) { 439 DBG_WARN_BTL(device,"timed out waiting for pending IO. DeviceOutStandingIo's=%lu\n", 440 pqisrc_read_device_active_io(softs, device)); 441 return; 442 } 443 } 444 #else 445 check_device_pending_commands_to_complete(softs, device); 446 #endif 447 } 448