1 /*- 2 * Copyright 2016-2021 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 /* read and modify controller diagnostic option - PQI_PTRAID_UPDATE_ON_RESCAN_LUNS */ 30 void 31 pqisrc_ctrl_diagnostic_options(pqisrc_softstate_t *softs) 32 { 33 int ret = PQI_STATUS_SUCCESS; 34 uint32_t diags_options = 0; 35 pqisrc_raid_req_t request; 36 37 DBG_NOTE("IN\n"); 38 39 memset(&request, 0, sizeof(request)); 40 /* read diags options of controller */ 41 ret = pqisrc_build_send_raid_request(softs, &request, 42 (void*)&diags_options, 43 sizeof(diags_options), 44 BMIC_SENSE_DIAGS_OPTIONS, 45 0, (uint8_t *)RAID_CTLR_LUNID, NULL); 46 if (ret != PQI_STATUS_SUCCESS) { 47 DBG_WARN("Request failed for BMIC Sense Diags Option command." 48 "ret:%d\n",ret); 49 return; 50 } 51 DBG_NOTE("diags options data after read: %#x\n",diags_options); 52 diags_options |= PQI_PTRAID_UPDATE_ON_RESCAN_LUNS; 53 DBG_NOTE("diags options data to write: %#x\n",diags_options); 54 memset(&request, 0, sizeof(request)); 55 /* write specified diags options to controller */ 56 ret = pqisrc_build_send_raid_request(softs, &request, 57 (void*)&diags_options, 58 sizeof(diags_options), 59 BMIC_SET_DIAGS_OPTIONS, 60 0, (uint8_t *)RAID_CTLR_LUNID, NULL); 61 if (ret != PQI_STATUS_SUCCESS) 62 DBG_WARN("Request failed for BMIC Set Diags Option command." 63 "ret:%d\n",ret); 64 #if 0 65 diags_options = 0; 66 memset(&request, 0, sizeof(request)); 67 ret = pqisrc_build_send_raid_request(softs, &request, 68 (void*)&diags_options, 69 sizeof(diags_options), 70 BMIC_SENSE_DIAGS_OPTIONS, 71 0, (uint8_t *)RAID_CTLR_LUNID, NULL); 72 if (ret != PQI_STATUS_SUCCESS) 73 DBG_WARN("Request failed for BMIC Sense Diags Option command." 74 "ret:%d\n",ret); 75 DBG_NOTE("diags options after re-read: %#x\n",diags_options); 76 #endif 77 DBG_NOTE("OUT\n"); 78 } 79 80 /* 81 * Function used to validate the adapter health. 82 */ 83 boolean_t 84 pqisrc_ctrl_offline(pqisrc_softstate_t *softs) 85 { 86 DBG_FUNC("IN\n"); 87 88 DBG_FUNC("OUT\n"); 89 90 return !softs->ctrl_online; 91 } 92 93 /* Function used set/clear legacy INTx bit in Legacy Interrupt INTx 94 * mask clear pqi register 95 */ 96 void 97 pqisrc_configure_legacy_intx(pqisrc_softstate_t *softs, boolean_t enable_intx) 98 { 99 uint32_t intx_mask; 100 uint32_t *reg_addr __unused; 101 102 DBG_FUNC("IN\n"); 103 104 if (enable_intx) 105 reg_addr = &softs->pqi_reg->legacy_intr_mask_clr; 106 else 107 reg_addr = &softs->pqi_reg->legacy_intr_mask_set; 108 109 intx_mask = PCI_MEM_GET32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR); 110 intx_mask |= PQISRC_LEGACY_INTX_MASK; 111 PCI_MEM_PUT32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR ,intx_mask); 112 113 DBG_FUNC("OUT\n"); 114 } 115 116 /* 117 * Function used to take exposed devices to OS as offline. 118 */ 119 void 120 pqisrc_take_devices_offline(pqisrc_softstate_t *softs) 121 { 122 pqi_scsi_dev_t *device = NULL; 123 int i,j; 124 125 DBG_FUNC("IN\n"); 126 for(i = 0; i < PQI_MAX_DEVICES; i++) { 127 for(j = 0; j < PQI_MAX_MULTILUN; j++) { 128 if(softs->device_list[i][j] == NULL) 129 continue; 130 device = softs->device_list[i][j]; 131 pqisrc_remove_device(softs, device); 132 } 133 } 134 135 DBG_FUNC("OUT\n"); 136 } 137 138 /* 139 * Function used to take adapter offline. 140 */ 141 void 142 pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs) 143 { 144 DBG_FUNC("IN\n"); 145 146 softs->ctrl_online = false; 147 148 int lockupcode = 0; 149 150 if (SIS_IS_KERNEL_PANIC(softs)) { 151 lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7); 152 DBG_ERR("Controller FW is not running, Lockup code = %x\n", lockupcode); 153 } 154 else { 155 pqisrc_trigger_nmi_sis(softs); 156 } 157 158 os_complete_outstanding_cmds_nodevice(softs); 159 pqisrc_wait_for_rescan_complete(softs); 160 pqisrc_take_devices_offline(softs); 161 162 DBG_FUNC("OUT\n"); 163 } 164 165 /* 166 * Timer handler for the adapter heart-beat. 167 */ 168 void 169 pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs) 170 { 171 uint8_t take_offline = false; 172 173 DBG_FUNC("IN\n"); 174 175 if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) { 176 take_offline = true; 177 goto take_ctrl_offline; 178 } 179 softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs); 180 DBG_INFO("CTRLR_HEARTBEAT_CNT(softs) = %lx \ 181 softs->prev_heartbeat_count = %lx\n", 182 CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count); 183 184 take_ctrl_offline: 185 if (take_offline){ 186 DBG_ERR("controller is offline\n"); 187 pqisrc_take_ctrl_offline(softs); 188 os_stop_heartbeat_timer(softs); 189 } 190 DBG_FUNC("OUT\n"); 191 } 192 193 /* 194 * Conditional variable management routine for internal commands. 195 */ 196 int 197 pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb, 198 uint32_t timeout_in_msec) 199 { 200 DBG_FUNC("IN\n"); 201 202 int ret = PQI_STATUS_SUCCESS; 203 204 /* 1 msec = 500 usec * 2 */ 205 uint32_t loop_cnt = timeout_in_msec * 2; 206 uint32_t i = 0; 207 208 while (rcb->req_pending == true) { 209 OS_SLEEP(500); /* Micro sec */ 210 /* Polling needed for FreeBSD : since ithread routine is not scheduled 211 * during bootup, we could use polling until interrupts are 212 * enabled (using 'if (cold)'to check for the boot time before 213 * interrupts are enabled). */ 214 IS_POLLING_REQUIRED(softs); 215 216 if ((timeout_in_msec != TIMEOUT_INFINITE) && (i++ == loop_cnt)) { 217 DBG_ERR("ERR: Requested cmd timed out !!!\n"); 218 ret = PQI_STATUS_TIMEOUT; 219 rcb->timedout = true; 220 break; 221 } 222 223 if (pqisrc_ctrl_offline(softs)) { 224 DBG_ERR("Controller is Offline"); 225 ret = PQI_STATUS_FAILURE; 226 break; 227 } 228 229 } 230 rcb->req_pending = true; 231 232 DBG_FUNC("OUT\n"); 233 234 return ret; 235 } 236 237 /* Function used to validate the device wwid. */ 238 boolean_t 239 pqisrc_device_equal(pqi_scsi_dev_t *dev1, 240 pqi_scsi_dev_t *dev2) 241 { 242 return dev1->wwid == dev2->wwid; 243 } 244 245 /* Function used to validate the device scsi3addr. */ 246 boolean_t 247 pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2) 248 { 249 return memcmp(scsi3addr1, scsi3addr2, 8) == 0; 250 } 251 252 /* Function used to validate hba_lunid */ 253 boolean_t 254 pqisrc_is_hba_lunid(uint8_t *scsi3addr) 255 { 256 return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID); 257 } 258 259 /* Function used to validate type of device */ 260 boolean_t 261 pqisrc_is_logical_device(pqi_scsi_dev_t *device) 262 { 263 return !device->is_physical_device; 264 } 265 266 /* Function used to sanitize inquiry string */ 267 void 268 pqisrc_sanitize_inquiry_string(unsigned char *s, int len) 269 { 270 boolean_t terminated = false; 271 272 DBG_FUNC("IN\n"); 273 274 for (; len > 0; (--len, ++s)) { 275 if (*s == 0) 276 terminated = true; 277 if (terminated || *s < 0x20 || *s > 0x7e) 278 *s = ' '; 279 } 280 281 DBG_FUNC("OUT\n"); 282 } 283 284 static char *raid_levels[] = { 285 "RAID 0", 286 "RAID 4", 287 "RAID 1(1+0)", 288 "RAID 5", 289 "RAID 5+1", 290 "RAID ADG", 291 "RAID 1(ADM)", 292 }; 293 294 /* Get the RAID level from the index */ 295 char * 296 pqisrc_raidlevel_to_string(uint8_t raid_level) 297 { 298 DBG_FUNC("IN\n"); 299 if (raid_level < ARRAY_SIZE(raid_levels)) 300 return raid_levels[raid_level]; 301 DBG_FUNC("OUT\n"); 302 303 return " "; 304 } 305 306 /* Debug routine for displaying device info */ 307 void pqisrc_display_device_info(pqisrc_softstate_t *softs, 308 char *action, pqi_scsi_dev_t *device) 309 { 310 if (device->is_physical_device) { 311 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 312 "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 313 action, 314 device->bus, 315 device->target, 316 device->lun, 317 device->vendor, 318 device->model, 319 "Physical", 320 device->offload_config ? '+' : '-', 321 device->offload_enabled_pending ? '+' : '-', 322 device->expose_device ? '+' : '-', 323 device->queue_depth); 324 } else if (device->devtype == RAID_DEVICE) { 325 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 326 "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 327 action, 328 device->bus, 329 device->target, 330 device->lun, 331 device->vendor, 332 device->model, 333 "Controller", 334 device->offload_config ? '+' : '-', 335 device->offload_enabled_pending ? '+' : '-', 336 device->expose_device ? '+' : '-', 337 device->queue_depth); 338 } else if (device->devtype == CONTROLLER_DEVICE) { 339 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 340 "SSDSmartPathCap%c En%c Exp%c qd=%d\n", 341 action, 342 device->bus, 343 device->target, 344 device->lun, 345 device->vendor, 346 device->model, 347 "External", 348 device->offload_config ? '+' : '-', 349 device->offload_enabled_pending ? '+' : '-', 350 device->expose_device ? '+' : '-', 351 device->queue_depth); 352 } else { 353 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " 354 "SSDSmartPathCap%c En%c Exp%c qd=%d devtype=%d\n", 355 action, 356 device->bus, 357 device->target, 358 device->lun, 359 device->vendor, 360 device->model, 361 pqisrc_raidlevel_to_string(device->raid_level), 362 device->offload_config ? '+' : '-', 363 device->offload_enabled_pending ? '+' : '-', 364 device->expose_device ? '+' : '-', 365 device->queue_depth, 366 device->devtype); 367 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */ 368 } 369 } 370 371 /* validate the structure sizes */ 372 void 373 check_struct_sizes(void) 374 { 375 376 ASSERT(sizeof(SCSI3Addr_struct)== 2); 377 ASSERT(sizeof(PhysDevAddr_struct) == 8); 378 ASSERT(sizeof(LogDevAddr_struct)== 8); 379 ASSERT(sizeof(LUNAddr_struct)==8); 380 ASSERT(sizeof(RequestBlock_struct) == 20); 381 ASSERT(sizeof(MoreErrInfo_struct)== 8); 382 ASSERT(sizeof(ErrorInfo_struct)== 48); 383 /* Checking the size of IOCTL_Command_struct for both 384 64 bit and 32 bit system*/ 385 ASSERT(sizeof(IOCTL_Command_struct)== 86 || 386 sizeof(IOCTL_Command_struct)== 82); 387 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42); 388 ASSERT(sizeof(struct bmic_host_wellness_time)== 20); 389 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8); 390 ASSERT(sizeof(struct admin_q_param)== 4); 391 ASSERT(sizeof(struct pqi_registers)== 256); 392 ASSERT(sizeof(struct ioa_registers)== 4128); 393 ASSERT(sizeof(struct pqi_pref_settings)==4); 394 ASSERT(sizeof(struct pqi_cap)== 20); 395 ASSERT(sizeof(iu_header_t)== 4); 396 ASSERT(sizeof(gen_adm_req_iu_t)== 64); 397 ASSERT(sizeof(gen_adm_resp_iu_t)== 64); 398 ASSERT(sizeof(op_q_params) == 9); 399 ASSERT(sizeof(raid_path_error_info_elem_t)== 276); 400 ASSERT(sizeof(aio_path_error_info_elem_t)== 276); 401 ASSERT(sizeof(struct init_base_struct)== 24); 402 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16); 403 ASSERT(sizeof(pqi_dev_cap_t)== 576); 404 ASSERT(sizeof(pqi_aio_req_t)== 128); 405 ASSERT(sizeof(pqisrc_raid_req_t)== 128); 406 ASSERT(sizeof(pqi_raid_tmf_req_t)== 32); 407 ASSERT(sizeof(pqi_aio_tmf_req_t)== 32); 408 ASSERT(sizeof(struct pqi_io_response)== 16); 409 ASSERT(sizeof(struct sense_header_scsi)== 8); 410 ASSERT(sizeof(reportlun_header_t)==8); 411 ASSERT(sizeof(reportlun_ext_entry_t)== 24); 412 ASSERT(sizeof(reportlun_data_ext_t)== 32); 413 ASSERT(sizeof(raidmap_data_t)==8); 414 ASSERT(sizeof(pqisrc_raid_map_t)== 8256); 415 ASSERT(sizeof(bmic_ident_ctrl_t)== 325); 416 ASSERT(sizeof(bmic_ident_physdev_t)==2048); 417 418 } 419 420 uint32_t 421 pqisrc_count_num_scsi_active_requests_on_dev(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 422 { 423 uint32_t i, active_io = 0; 424 rcb_t* rcb; 425 426 for(i = 1; i <= softs->max_outstanding_io; i++) { 427 rcb = &softs->rcb[i]; 428 if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) { 429 active_io++; 430 } 431 } 432 return active_io; 433 } 434 435 void 436 check_device_pending_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 437 { 438 uint32_t tag = softs->max_outstanding_io, active_requests; 439 uint64_t timeout = 0, delay_in_usec = 1000; //In micro Seconds 440 rcb_t* rcb; 441 442 DBG_FUNC("IN\n"); 443 444 active_requests = pqisrc_count_num_scsi_active_requests_on_dev(softs, device); 445 446 DBG_WARN("Device Outstanding IO count = %u\n", active_requests); 447 448 if(!active_requests) 449 return; 450 451 do { 452 rcb = &softs->rcb[tag]; 453 if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) { 454 OS_BUSYWAIT(delay_in_usec); 455 timeout += delay_in_usec; 456 } 457 else 458 tag--; 459 if(timeout >= PQISRC_PENDING_IO_TIMEOUT_USEC) { 460 DBG_WARN("timed out waiting for pending IO\n"); 461 return; 462 } 463 } while(tag); 464 465 } 466 467 inline uint64_t 468 pqisrc_increment_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 469 { 470 #if PQISRC_DEVICE_IO_COUNTER 471 /*Increment device active io count by one*/ 472 return OS_ATOMIC64_INC(&device->active_requests); 473 #endif 474 } 475 476 inline uint64_t 477 pqisrc_decrement_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 478 { 479 #if PQISRC_DEVICE_IO_COUNTER 480 /*Decrement device active io count by one*/ 481 return OS_ATOMIC64_DEC(&device->active_requests); 482 #endif 483 } 484 485 inline void 486 pqisrc_init_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 487 { 488 #if PQISRC_DEVICE_IO_COUNTER 489 /* Reset device count to Zero */ 490 OS_ATOMIC64_INIT(&device->active_requests, 0); 491 #endif 492 } 493 494 inline uint64_t 495 pqisrc_read_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 496 { 497 #if PQISRC_DEVICE_IO_COUNTER 498 /* read device active count*/ 499 return OS_ATOMIC64_READ(&device->active_requests); 500 #endif 501 } 502 503 void 504 pqisrc_wait_for_device_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 505 { 506 uint64_t timeout_in_usec = 0, delay_in_usec = 1000; //In microseconds 507 508 DBG_FUNC("IN\n"); 509 510 if(!softs->ctrl_online) 511 return; 512 513 #if PQISRC_DEVICE_IO_COUNTER 514 DBG_NOTE("Device Outstanding IO count = %ld\n", pqisrc_read_device_active_io(softs, device)); 515 516 while(pqisrc_read_device_active_io(softs, device)) { 517 OS_BUSYWAIT(delay_in_usec); // In microseconds 518 if(!softs->ctrl_online) { 519 DBG_WARN("Controller Offline was detected.\n"); 520 } 521 timeout_in_usec += delay_in_usec; 522 if(timeout_in_usec >= PQISRC_PENDING_IO_TIMEOUT_USEC) { 523 DBG_WARN("timed out waiting for pending IO. DeviceOutStandingIo's=%ld\n", 524 pqisrc_read_device_active_io(softs, device)); 525 return; 526 } 527 } 528 #else 529 check_device_pending_commands_to_complete(softs, device); 530 #endif 531 } 532