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 * Checks a firmware feature status, given bit position. 31 */ 32 static inline boolean_t 33 pqi_is_firmware_feature_supported( 34 struct pqi_config_table_firmware_features *firmware_features, 35 unsigned int bit_position) 36 { 37 unsigned int byte_index; 38 39 byte_index = bit_position / BITS_PER_BYTE; 40 41 if (byte_index >= firmware_features->num_elements) { 42 DBG_ERR_NO_SOFTS("Invalid byte index for bit position %u\n", 43 bit_position); 44 return false; 45 } 46 47 return (firmware_features->features_supported[byte_index] & 48 (1 << (bit_position % BITS_PER_BYTE))) ? true : false; 49 } 50 51 /* 52 * Counts down into the enabled section of firmware 53 * features and reports current enabled status, given 54 * bit position. 55 */ 56 static inline boolean_t 57 pqi_is_firmware_feature_enabled( 58 struct pqi_config_table_firmware_features *firmware_features, 59 uint8_t *firmware_features_iomem_addr, 60 unsigned int bit_position) 61 { 62 unsigned int byte_index; 63 uint8_t *features_enabled_iomem_addr; 64 65 byte_index = (bit_position / BITS_PER_BYTE) + 66 (firmware_features->num_elements * 2); 67 68 features_enabled_iomem_addr = firmware_features_iomem_addr + 69 offsetof(struct pqi_config_table_firmware_features, 70 features_supported) + byte_index; 71 72 return (*features_enabled_iomem_addr & 73 (1 << (bit_position % BITS_PER_BYTE))) ? true : false; 74 } 75 76 /* 77 * Sets the given bit position for the driver to request the indicated 78 * firmware feature be enabled. 79 */ 80 static inline void 81 pqi_request_firmware_feature( 82 struct pqi_config_table_firmware_features *firmware_features, 83 unsigned int bit_position) 84 { 85 unsigned int byte_index; 86 87 /* byte_index adjusted to index into requested start bits */ 88 byte_index = (bit_position / BITS_PER_BYTE) + 89 firmware_features->num_elements; 90 91 /* setting requested bits of local firmware_features */ 92 firmware_features->features_supported[byte_index] |= 93 (1 << (bit_position % BITS_PER_BYTE)); 94 } 95 96 /* 97 * Creates and sends the request for firmware to update the config 98 * table. 99 */ 100 static int 101 pqi_config_table_update(pqisrc_softstate_t *softs, 102 uint16_t first_section, uint16_t last_section) 103 { 104 struct pqi_vendor_general_request request; 105 int ret; 106 107 memset(&request, 0, sizeof(request)); 108 109 request.header.iu_type = PQI_REQUEST_IU_VENDOR_GENERAL; 110 request.header.iu_length = sizeof(request) - PQI_REQUEST_HEADER_LENGTH; 111 request.function_code = PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE; 112 request.data.config_table_update.first_section = first_section; 113 request.data.config_table_update.last_section = last_section; 114 115 ret = pqisrc_build_send_vendor_request(softs, &request); 116 117 if (ret != PQI_STATUS_SUCCESS) { 118 DBG_ERR("Failed to submit vendor general request IU, Ret status: %d\n", ret); 119 } 120 121 return ret; 122 } 123 124 /* 125 * Copies requested features bits into firmware config table, 126 * checks for support, and returns status of updating the config table. 127 */ 128 static int 129 pqi_enable_firmware_features(pqisrc_softstate_t *softs, 130 struct pqi_config_table_firmware_features *firmware_features, 131 uint8_t *firmware_features_abs_addr) 132 { 133 uint8_t *features_requested; 134 uint8_t *features_requested_abs_addr; 135 uint16_t *host_max_known_feature_iomem_addr; 136 uint16_t pqi_max_feature = PQI_FIRMWARE_FEATURE_MAXIMUM; 137 138 features_requested = firmware_features->features_supported + 139 firmware_features->num_elements; 140 141 features_requested_abs_addr = firmware_features_abs_addr + 142 (features_requested - (uint8_t*)firmware_features); 143 /* 144 * NOTE: This memcpy is writing to a BAR-mapped address 145 * which may not be safe for all OSes without proper API 146 */ 147 memcpy(features_requested_abs_addr, features_requested, 148 firmware_features->num_elements); 149 150 if (pqi_is_firmware_feature_supported(firmware_features, 151 PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE)) { 152 host_max_known_feature_iomem_addr = 153 (uint16_t*)(features_requested_abs_addr + 154 (firmware_features->num_elements * 2) + sizeof(uint16_t)); 155 /* 156 * NOTE: This writes to a BAR-mapped address 157 * which may not be safe for all OSes without proper API 158 */ 159 *host_max_known_feature_iomem_addr = pqi_max_feature; 160 } 161 162 return pqi_config_table_update(softs, 163 PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES, 164 PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES); 165 } 166 167 typedef struct pqi_firmware_feature pqi_firmware_feature_t; 168 typedef void (*feature_status_fn)(pqisrc_softstate_t *softs, 169 pqi_firmware_feature_t *firmware_feature); 170 171 struct pqi_firmware_feature { 172 char *feature_name; 173 unsigned int feature_bit; 174 boolean_t supported; 175 boolean_t enabled; 176 feature_status_fn feature_status; 177 }; 178 179 static void 180 pqi_firmware_feature_status(pqisrc_softstate_t *softs, 181 struct pqi_firmware_feature *firmware_feature) 182 { 183 if (!firmware_feature->supported) { 184 DBG_NOTE("%s not supported by controller\n", 185 firmware_feature->feature_name); 186 return; 187 } 188 189 if (firmware_feature->enabled) { 190 DBG_NOTE("%s enabled\n", firmware_feature->feature_name); 191 return; 192 } 193 194 DBG_NOTE("failed to enable %s\n", firmware_feature->feature_name); 195 } 196 197 static void 198 pqi_ctrl_update_feature_flags(pqisrc_softstate_t *softs, 199 struct pqi_firmware_feature *firmware_feature) 200 { 201 switch (firmware_feature->feature_bit) { 202 case PQI_FIRMWARE_FEATURE_RAID_1_WRITE_BYPASS: 203 softs->aio_raid1_write_bypass = firmware_feature->enabled; 204 break; 205 case PQI_FIRMWARE_FEATURE_RAID_5_WRITE_BYPASS: 206 softs->aio_raid5_write_bypass = firmware_feature->enabled; 207 break; 208 case PQI_FIRMWARE_FEATURE_RAID_6_WRITE_BYPASS: 209 softs->aio_raid6_write_bypass = firmware_feature->enabled; 210 break; 211 case PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT: 212 softs->timeout_in_passthrough = true; 213 break; 214 case PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT: 215 softs->timeout_in_tmf = true; 216 break; 217 case PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN: 218 break; 219 case PQI_FIRMWARE_FEATURE_PAGE83_IDENTIFIER_FOR_RPL_WWID: 220 softs->page83id_in_rpl = true; 221 break; 222 default: 223 DBG_NOTE("Nothing to do\n"); 224 return; 225 break; 226 } 227 /* for any valid feature, also go update the feature status. */ 228 pqi_firmware_feature_status(softs, firmware_feature); 229 } 230 231 232 static inline void 233 pqi_firmware_feature_update(pqisrc_softstate_t *softs, 234 struct pqi_firmware_feature *firmware_feature) 235 { 236 if (firmware_feature->feature_status) 237 firmware_feature->feature_status(softs, firmware_feature); 238 } 239 240 /* Defines PQI features that driver wishes to support */ 241 static struct pqi_firmware_feature pqi_firmware_features[] = { 242 #if 0 243 { 244 .feature_name = "Online Firmware Activation", 245 .feature_bit = PQI_FIRMWARE_FEATURE_OFA, 246 .feature_status = pqi_firmware_feature_status, 247 }, 248 { 249 .feature_name = "Serial Management Protocol", 250 .feature_bit = PQI_FIRMWARE_FEATURE_SMP, 251 .feature_status = pqi_firmware_feature_status, 252 }, 253 #endif 254 { 255 .feature_name = "SATA WWN Unique ID", 256 .feature_bit = PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN, 257 .feature_status = pqi_ctrl_update_feature_flags, 258 }, 259 { 260 .feature_name = "RAID IU Timeout", 261 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT, 262 .feature_status = pqi_ctrl_update_feature_flags, 263 }, 264 { 265 .feature_name = "TMF IU Timeout", 266 .feature_bit = PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT, 267 .feature_status = pqi_ctrl_update_feature_flags, 268 }, 269 { 270 .feature_name = "Support for RPL WWID filled by Page83 identifier", 271 .feature_bit = PQI_FIRMWARE_FEATURE_PAGE83_IDENTIFIER_FOR_RPL_WWID, 272 .feature_status = pqi_ctrl_update_feature_flags, 273 }, 274 /* Features independent of Maximum Known Feature should be added 275 before Maximum Known Feature*/ 276 { 277 .feature_name = "Maximum Known Feature", 278 .feature_bit = PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE, 279 .feature_status = pqi_firmware_feature_status, 280 }, 281 { 282 .feature_name = "RAID 0 Read Bypass", 283 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_0_READ_BYPASS, 284 .feature_status = pqi_firmware_feature_status, 285 }, 286 { 287 .feature_name = "RAID 1 Read Bypass", 288 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_1_READ_BYPASS, 289 .feature_status = pqi_firmware_feature_status, 290 }, 291 { 292 .feature_name = "RAID 5 Read Bypass", 293 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_5_READ_BYPASS, 294 .feature_status = pqi_firmware_feature_status, 295 }, 296 { 297 .feature_name = "RAID 6 Read Bypass", 298 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_6_READ_BYPASS, 299 .feature_status = pqi_firmware_feature_status, 300 }, 301 { 302 .feature_name = "RAID 0 Write Bypass", 303 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_0_WRITE_BYPASS, 304 .feature_status = pqi_firmware_feature_status, 305 }, 306 { 307 .feature_name = "RAID 1 Write Bypass", 308 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_1_WRITE_BYPASS, 309 .feature_status = pqi_ctrl_update_feature_flags, 310 }, 311 { 312 .feature_name = "RAID 5 Write Bypass", 313 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_5_WRITE_BYPASS, 314 .feature_status = pqi_ctrl_update_feature_flags, 315 }, 316 { 317 .feature_name = "RAID 6 Write Bypass", 318 .feature_bit = PQI_FIRMWARE_FEATURE_RAID_6_WRITE_BYPASS, 319 .feature_status = pqi_ctrl_update_feature_flags, 320 }, 321 #if 0 322 { 323 .feature_name = "New Soft Reset Handshake", 324 .feature_bit = PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE, 325 .feature_status = pqi_ctrl_update_feature_flags, 326 }, 327 #endif 328 329 }; 330 331 static void 332 pqi_process_firmware_features(pqisrc_softstate_t *softs, 333 void *features, void *firmware_features_abs_addr) 334 { 335 int rc; 336 struct pqi_config_table_firmware_features *firmware_features = features; 337 unsigned int i; 338 unsigned int num_features_supported; 339 340 /* Iterates through local PQI feature support list to 341 see if the controller also supports the feature */ 342 for (i = 0, num_features_supported = 0; 343 i < ARRAY_SIZE(pqi_firmware_features); i++) { 344 /*Check if SATA_WWN_FOR_DEV_UNIQUE_ID feature enabled by setting module 345 parameter if not avoid checking for the feature*/ 346 if ((pqi_firmware_features[i].feature_bit == 347 PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN) && 348 (!softs->sata_unique_wwn)) { 349 continue; 350 } 351 if (pqi_is_firmware_feature_supported(firmware_features, 352 pqi_firmware_features[i].feature_bit)) { 353 pqi_firmware_features[i].supported = true; 354 num_features_supported++; 355 } else { 356 DBG_WARN("Feature %s is not supported by firmware\n", 357 pqi_firmware_features[i].feature_name); 358 pqi_firmware_feature_update(softs, 359 &pqi_firmware_features[i]); 360 361 /* if max known feature bit isn't supported, 362 * then no other feature bits are supported. 363 */ 364 if (pqi_firmware_features[i].feature_bit == 365 PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE) 366 break; 367 } 368 } 369 370 DBG_INFO("Num joint features supported : %u \n", num_features_supported); 371 372 if (num_features_supported == 0) 373 return; 374 375 /* request driver features that are also on firmware-supported list */ 376 for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { 377 if (!pqi_firmware_features[i].supported) 378 continue; 379 #ifdef DEVICE_HINT 380 if (check_device_hint_status(softs, pqi_firmware_features[i].feature_bit)) 381 continue; 382 #endif 383 pqi_request_firmware_feature(firmware_features, 384 pqi_firmware_features[i].feature_bit); 385 } 386 387 /* enable the features that were successfully requested. */ 388 rc = pqi_enable_firmware_features(softs, firmware_features, 389 firmware_features_abs_addr); 390 if (rc) { 391 DBG_ERR("failed to enable firmware features in PQI configuration table\n"); 392 for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { 393 if (!pqi_firmware_features[i].supported) 394 continue; 395 pqi_firmware_feature_update(softs, 396 &pqi_firmware_features[i]); 397 } 398 return; 399 } 400 401 /* report the features that were successfully enabled. */ 402 for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { 403 if (!pqi_firmware_features[i].supported) 404 continue; 405 if (pqi_is_firmware_feature_enabled(firmware_features, 406 firmware_features_abs_addr, 407 pqi_firmware_features[i].feature_bit)) { 408 pqi_firmware_features[i].enabled = true; 409 } else { 410 DBG_WARN("Feature %s could not be enabled.\n", 411 pqi_firmware_features[i].feature_name); 412 } 413 pqi_firmware_feature_update(softs, 414 &pqi_firmware_features[i]); 415 } 416 } 417 418 static void 419 pqi_init_firmware_features(void) 420 { 421 unsigned int i; 422 423 for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { 424 pqi_firmware_features[i].supported = false; 425 pqi_firmware_features[i].enabled = false; 426 } 427 } 428 429 static void 430 pqi_process_firmware_features_section(pqisrc_softstate_t *softs, 431 void *features, void *firmware_features_abs_addr) 432 { 433 pqi_init_firmware_features(); 434 pqi_process_firmware_features(softs, features, firmware_features_abs_addr); 435 } 436 437 438 /* 439 * Get the PQI configuration table parameters. 440 * Currently using for heart-beat counter scratch-pad register. 441 */ 442 int 443 pqisrc_process_config_table(pqisrc_softstate_t *softs) 444 { 445 int ret = PQI_STATUS_FAILURE; 446 uint32_t config_table_size; 447 uint32_t section_off; 448 uint8_t *config_table_abs_addr; 449 struct pqi_conf_table *conf_table; 450 struct pqi_conf_table_section_header *section_hdr; 451 452 config_table_size = softs->pqi_cap.conf_tab_sz; 453 454 if (config_table_size < sizeof(*conf_table) || 455 config_table_size > PQI_CONF_TABLE_MAX_LEN) { 456 DBG_ERR("Invalid PQI conf table length of %u\n", 457 config_table_size); 458 return ret; 459 } 460 461 conf_table = os_mem_alloc(softs, config_table_size); 462 if (!conf_table) { 463 DBG_ERR("Failed to allocate memory for PQI conf table\n"); 464 return ret; 465 } 466 467 config_table_abs_addr = (uint8_t *)(softs->pci_mem_base_vaddr + 468 softs->pqi_cap.conf_tab_off); 469 470 PCI_MEM_GET_BUF(softs, config_table_abs_addr, 471 softs->pqi_cap.conf_tab_off, 472 (uint8_t*)conf_table, config_table_size); 473 474 if (memcmp(conf_table->sign, PQI_CONF_TABLE_SIGNATURE, 475 sizeof(conf_table->sign)) != 0) { 476 DBG_ERR("Invalid PQI config signature\n"); 477 goto out; 478 } 479 480 section_off = LE_32(conf_table->first_section_off); 481 482 while (section_off) { 483 484 if (section_off+ sizeof(*section_hdr) >= config_table_size) { 485 DBG_INFO("Reached end of PQI config table. Breaking off.\n"); 486 break; 487 } 488 489 section_hdr = (struct pqi_conf_table_section_header *)((uint8_t *)conf_table + section_off); 490 491 switch (LE_16(section_hdr->section_id)) { 492 case PQI_CONF_TABLE_SECTION_GENERAL_INFO: 493 break; 494 case PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES: 495 pqi_process_firmware_features_section(softs, section_hdr, (config_table_abs_addr + section_off)); 496 break; 497 case PQI_CONF_TABLE_SECTION_FIRMWARE_ERRATA: 498 case PQI_CONF_TABLE_SECTION_DEBUG: 499 break; 500 case PQI_CONF_TABLE_SECTION_HEARTBEAT: 501 softs->heartbeat_counter_off = softs->pqi_cap.conf_tab_off + 502 section_off + 503 offsetof(struct pqi_conf_table_heartbeat, heartbeat_counter); 504 softs->heartbeat_counter_abs_addr = (uint64_t *)(softs->pci_mem_base_vaddr + 505 softs->heartbeat_counter_off); 506 ret = PQI_STATUS_SUCCESS; 507 break; 508 case PQI_CONF_TABLE_SOFT_RESET: 509 break; 510 default: 511 DBG_NOTE("unrecognized PQI config table section ID: 0x%x\n", 512 LE_16(section_hdr->section_id)); 513 break; 514 } 515 section_off = LE_16(section_hdr->next_section_off); 516 } 517 out: 518 os_mem_free(softs, (void *)conf_table,config_table_size); 519 return ret; 520 } 521