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