Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: mpi3mr: Trigger support

Add functions to process automatic diag triggers. If a condition defined in
the triggers is met, the driver will call appropriate controller functions
to save the diagnostic information.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202405151955.BiAWI1SY-lkp@intel.com/
Co-developed-by: Sathya Prakash <sathya.prakash@broadcom.com>
Signed-off-by: Sathya Prakash <sathya.prakash@broadcom.com>
Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
Link: https://lore.kernel.org/r/20240626102646.14298-3-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Ranjan Kumar and committed by
Martin K. Petersen
d8d08d16 fc444494

+564 -8
+43
drivers/scsi/mpi3mr/mpi3mr.h
··· 193 193 #define MPI3MR_DEFAULT_HDB_MIN_SZ (2 * 1024 * 1024) 194 194 #define MPI3MR_MAX_NUM_HDB 2 195 195 196 + #define MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN 0 197 + #define MPI3MR_HDB_TRIGGER_TYPE_FAULT 1 198 + #define MPI3MR_HDB_TRIGGER_TYPE_ELEMENT 2 196 199 #define MPI3MR_HDB_TRIGGER_TYPE_GLOBAL 3 200 + #define MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET 4 201 + #define MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED 5 197 202 198 203 /* SGE Flag definition */ 199 204 #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ ··· 223 218 #define MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS 256 224 219 #define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048 225 220 221 + #define MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER (0xFFFD) 226 222 227 223 /** 228 224 * struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe ··· 309 303 MPI3MR_RESET_FROM_FIRMWARE = 27, 310 304 MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29, 311 305 MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30, 306 + MPI3MR_RESET_FROM_TRIGGER = 31, 312 307 }; 313 308 314 309 #define MPI3MR_RESET_REASON_OSTYPE_LINUX 1 ··· 886 879 }; 887 880 888 881 /** 882 + * struct trigger_event_data - store trigger related 883 + * information. 884 + * 885 + * @trace_hdb: Trace diag buffer descriptor reference 886 + * @fw_hdb: FW diag buffer descriptor reference 887 + * @trigger_type: Trigger type 888 + * @trigger_specific_data: Trigger specific data 889 + * @snapdump: Snapdump enable or disable flag 890 + */ 891 + struct trigger_event_data { 892 + struct diag_buffer_desc *trace_hdb; 893 + struct diag_buffer_desc *fw_hdb; 894 + u8 trigger_type; 895 + union mpi3mr_trigger_data trigger_specific_data; 896 + bool snapdump; 897 + }; 898 + 899 + /** 889 900 * struct diag_buffer_desc - memory descriptor structure to 890 901 * store virtual, dma addresses, size, buffer status for host 891 902 * diagnostic buffers. ··· 1138 1113 * @ioctl_chain_sge: DMA buffer descriptor for IOCTL chain 1139 1114 * @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response 1140 1115 * @ioctl_sges_allocated: Flag for IOCTL SGEs allocated or not 1116 + * @trace_release_trigger_active: Trace trigger active flag 1117 + * @fw_release_trigger_active: Fw release trigger active flag 1118 + * @snapdump_trigger_active: Snapdump trigger active flag 1141 1119 */ 1142 1120 struct mpi3mr_ioc { 1143 1121 struct list_head list; ··· 1338 1310 struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB]; 1339 1311 struct mpi3_driver_page2 *driver_pg2; 1340 1312 spinlock_t trigger_lock; 1313 + bool snapdump_trigger_active; 1314 + bool trace_release_trigger_active; 1315 + bool fw_release_trigger_active; 1341 1316 }; 1342 1317 1343 1318 /** ··· 1544 1513 u8 buf_type); 1545 1514 int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc, 1546 1515 struct diag_buffer_desc *diag_buffer); 1516 + void mpi3mr_set_trigger_data_in_all_hdb(struct mpi3mr_ioc *mrioc, 1517 + u8 type, union mpi3mr_trigger_data *trigger_data, bool force); 1518 + void mpi3mr_reply_trigger(struct mpi3mr_ioc *mrioc, u16 iocstatus, 1519 + u32 iocloginfo); 1520 + void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc, 1521 + struct trigger_event_data *event_data); 1522 + void mpi3mr_scsisense_trigger(struct mpi3mr_ioc *mrioc, u8 senseky, u8 asc, 1523 + u8 ascq); 1524 + void mpi3mr_event_trigger(struct mpi3mr_ioc *mrioc, u8 event); 1525 + void mpi3mr_global_trigger(struct mpi3mr_ioc *mrioc, u64 trigger_data); 1526 + void mpi3mr_hdbstatuschg_evt_th(struct mpi3mr_ioc *mrioc, 1527 + struct mpi3_event_notification_reply *event_reply); 1547 1528 #endif /*MPI3MR_H_INCLUDED*/
+336 -1
drivers/scsi/mpi3mr/mpi3mr_app.c
··· 317 317 } 318 318 319 319 /** 320 + * mpi3mr_process_trigger - Generic HDB Trigger handler 321 + * @mrioc: Adapter instance reference 322 + * @trigger_type: Trigger type 323 + * @trigger_data: Trigger data 324 + * @trigger_flags: Trigger flags 325 + * 326 + * This function checks validity of HDB, triggers and based on 327 + * trigger information, creates an event to be processed in the 328 + * firmware event worker thread . 329 + * 330 + * This function should be called with trigger spinlock held 331 + * 332 + * Return: Nothing 333 + */ 334 + static void mpi3mr_process_trigger(struct mpi3mr_ioc *mrioc, u8 trigger_type, 335 + union mpi3mr_trigger_data *trigger_data, u8 trigger_flags) 336 + { 337 + struct trigger_event_data event_data; 338 + struct diag_buffer_desc *trace_hdb = NULL; 339 + struct diag_buffer_desc *fw_hdb = NULL; 340 + u64 global_trigger; 341 + 342 + trace_hdb = mpi3mr_diag_buffer_for_type(mrioc, 343 + MPI3_DIAG_BUFFER_TYPE_TRACE); 344 + if (trace_hdb && 345 + (trace_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && 346 + (trace_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) 347 + trace_hdb = NULL; 348 + 349 + fw_hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW); 350 + 351 + if (fw_hdb && 352 + (fw_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && 353 + (fw_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) 354 + fw_hdb = NULL; 355 + 356 + if (mrioc->snapdump_trigger_active || (mrioc->fw_release_trigger_active 357 + && mrioc->trace_release_trigger_active) || 358 + (!trace_hdb && !fw_hdb) || (!mrioc->driver_pg2) || 359 + ((trigger_type == MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) 360 + && (!mrioc->driver_pg2->num_triggers))) 361 + return; 362 + 363 + memset(&event_data, 0, sizeof(event_data)); 364 + event_data.trigger_type = trigger_type; 365 + memcpy(&event_data.trigger_specific_data, trigger_data, 366 + sizeof(*trigger_data)); 367 + global_trigger = le64_to_cpu(mrioc->driver_pg2->global_trigger); 368 + 369 + if (global_trigger & MPI3_DRIVER2_GLOBALTRIGGER_SNAPDUMP_ENABLED) { 370 + event_data.snapdump = true; 371 + event_data.trace_hdb = trace_hdb; 372 + event_data.fw_hdb = fw_hdb; 373 + mrioc->snapdump_trigger_active = true; 374 + } else if (trigger_type == MPI3MR_HDB_TRIGGER_TYPE_GLOBAL) { 375 + if ((trace_hdb) && (global_trigger & 376 + MPI3_DRIVER2_GLOBALTRIGGER_DIAG_TRACE_RELEASE) && 377 + (!mrioc->trace_release_trigger_active)) { 378 + event_data.trace_hdb = trace_hdb; 379 + mrioc->trace_release_trigger_active = true; 380 + } 381 + if ((fw_hdb) && (global_trigger & 382 + MPI3_DRIVER2_GLOBALTRIGGER_DIAG_FW_RELEASE) && 383 + (!mrioc->fw_release_trigger_active)) { 384 + event_data.fw_hdb = fw_hdb; 385 + mrioc->fw_release_trigger_active = true; 386 + } 387 + } else if (trigger_type == MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) { 388 + if ((trace_hdb) && (trigger_flags & 389 + MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_TRACE_RELEASE) && 390 + (!mrioc->trace_release_trigger_active)) { 391 + event_data.trace_hdb = trace_hdb; 392 + mrioc->trace_release_trigger_active = true; 393 + } 394 + if ((fw_hdb) && (trigger_flags & 395 + MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_FW_RELEASE) && 396 + (!mrioc->fw_release_trigger_active)) { 397 + event_data.fw_hdb = fw_hdb; 398 + mrioc->fw_release_trigger_active = true; 399 + } 400 + } 401 + 402 + if (event_data.trace_hdb || event_data.fw_hdb) 403 + mpi3mr_hdb_trigger_data_event(mrioc, &event_data); 404 + } 405 + 406 + /** 407 + * mpi3mr_global_trigger - Global HDB trigger handler 408 + * @mrioc: Adapter instance reference 409 + * @trigger_data: Trigger data 410 + * 411 + * This function checks whether the given global trigger is 412 + * enabled in the driver page 2 and if so calls generic trigger 413 + * handler to queue event for HDB release. 414 + * 415 + * Return: Nothing 416 + */ 417 + void mpi3mr_global_trigger(struct mpi3mr_ioc *mrioc, u64 trigger_data) 418 + { 419 + unsigned long flags; 420 + union mpi3mr_trigger_data trigger_specific_data; 421 + 422 + spin_lock_irqsave(&mrioc->trigger_lock, flags); 423 + if (le64_to_cpu(mrioc->driver_pg2->global_trigger) & trigger_data) { 424 + memset(&trigger_specific_data, 0, 425 + sizeof(trigger_specific_data)); 426 + trigger_specific_data.global = trigger_data; 427 + mpi3mr_process_trigger(mrioc, MPI3MR_HDB_TRIGGER_TYPE_GLOBAL, 428 + &trigger_specific_data, 0); 429 + } 430 + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); 431 + } 432 + 433 + /** 434 + * mpi3mr_scsisense_trigger - SCSI sense HDB trigger handler 435 + * @mrioc: Adapter instance reference 436 + * @sensekey: Sense Key 437 + * @asc: Additional Sense Code 438 + * @ascq: Additional Sense Code Qualifier 439 + * 440 + * This function compares SCSI sense trigger values with driver 441 + * page 2 values and calls generic trigger handler to release 442 + * HDBs if match found 443 + * 444 + * Return: Nothing 445 + */ 446 + void mpi3mr_scsisense_trigger(struct mpi3mr_ioc *mrioc, u8 sensekey, u8 asc, 447 + u8 ascq) 448 + { 449 + struct mpi3_driver2_trigger_scsi_sense *scsi_sense_trigger = NULL; 450 + u64 i = 0; 451 + unsigned long flags; 452 + u8 num_triggers, trigger_flags; 453 + 454 + if (mrioc->scsisense_trigger_present) { 455 + spin_lock_irqsave(&mrioc->trigger_lock, flags); 456 + scsi_sense_trigger = (struct mpi3_driver2_trigger_scsi_sense *) 457 + mrioc->driver_pg2->trigger; 458 + num_triggers = mrioc->driver_pg2->num_triggers; 459 + for (i = 0; i < num_triggers; i++, scsi_sense_trigger++) { 460 + if (scsi_sense_trigger->type != 461 + MPI3_DRIVER2_TRIGGER_TYPE_SCSI_SENSE) 462 + continue; 463 + if (!(scsi_sense_trigger->sense_key == 464 + MPI3_DRIVER2_TRIGGER_SCSI_SENSE_SENSE_KEY_MATCH_ALL 465 + || scsi_sense_trigger->sense_key == sensekey)) 466 + continue; 467 + if (!(scsi_sense_trigger->asc == 468 + MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASC_MATCH_ALL || 469 + scsi_sense_trigger->asc == asc)) 470 + continue; 471 + if (!(scsi_sense_trigger->ascq == 472 + MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASCQ_MATCH_ALL || 473 + scsi_sense_trigger->ascq == ascq)) 474 + continue; 475 + trigger_flags = scsi_sense_trigger->flags; 476 + mpi3mr_process_trigger(mrioc, 477 + MPI3MR_HDB_TRIGGER_TYPE_ELEMENT, 478 + (union mpi3mr_trigger_data *)scsi_sense_trigger, 479 + trigger_flags); 480 + break; 481 + } 482 + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); 483 + } 484 + } 485 + 486 + /** 487 + * mpi3mr_event_trigger - MPI event HDB trigger handler 488 + * @mrioc: Adapter instance reference 489 + * @event: MPI Event 490 + * 491 + * This function compares event trigger values with driver page 492 + * 2 values and calls generic trigger handler to release 493 + * HDBs if match found. 494 + * 495 + * Return: Nothing 496 + */ 497 + void mpi3mr_event_trigger(struct mpi3mr_ioc *mrioc, u8 event) 498 + { 499 + struct mpi3_driver2_trigger_event *event_trigger = NULL; 500 + u64 i = 0; 501 + unsigned long flags; 502 + u8 num_triggers, trigger_flags; 503 + 504 + if (mrioc->event_trigger_present) { 505 + spin_lock_irqsave(&mrioc->trigger_lock, flags); 506 + event_trigger = (struct mpi3_driver2_trigger_event *) 507 + mrioc->driver_pg2->trigger; 508 + num_triggers = mrioc->driver_pg2->num_triggers; 509 + 510 + for (i = 0; i < num_triggers; i++, event_trigger++) { 511 + if (event_trigger->type != 512 + MPI3_DRIVER2_TRIGGER_TYPE_EVENT) 513 + continue; 514 + if (event_trigger->event != event) 515 + continue; 516 + trigger_flags = event_trigger->flags; 517 + mpi3mr_process_trigger(mrioc, 518 + MPI3MR_HDB_TRIGGER_TYPE_ELEMENT, 519 + (union mpi3mr_trigger_data *)event_trigger, 520 + trigger_flags); 521 + break; 522 + } 523 + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); 524 + } 525 + } 526 + 527 + /** 528 + * mpi3mr_reply_trigger - MPI Reply HDB trigger handler 529 + * @mrioc: Adapter instance reference 530 + * @ioc_status: Masked value of IOC Status from MPI Reply 531 + * @ioc_loginfo: IOC Log Info from MPI Reply 532 + * 533 + * This function compares IOC status and IOC log info trigger 534 + * values with driver page 2 values and calls generic trigger 535 + * handler to release HDBs if match found. 536 + * 537 + * Return: Nothing 538 + */ 539 + void mpi3mr_reply_trigger(struct mpi3mr_ioc *mrioc, u16 ioc_status, 540 + u32 ioc_loginfo) 541 + { 542 + struct mpi3_driver2_trigger_reply *reply_trigger = NULL; 543 + u64 i = 0; 544 + unsigned long flags; 545 + u8 num_triggers, trigger_flags; 546 + 547 + if (mrioc->reply_trigger_present) { 548 + spin_lock_irqsave(&mrioc->trigger_lock, flags); 549 + reply_trigger = (struct mpi3_driver2_trigger_reply *) 550 + mrioc->driver_pg2->trigger; 551 + num_triggers = mrioc->driver_pg2->num_triggers; 552 + for (i = 0; i < num_triggers; i++, reply_trigger++) { 553 + if (reply_trigger->type != 554 + MPI3_DRIVER2_TRIGGER_TYPE_REPLY) 555 + continue; 556 + if ((le16_to_cpu(reply_trigger->ioc_status) != 557 + ioc_status) 558 + && (le16_to_cpu(reply_trigger->ioc_status) != 559 + MPI3_DRIVER2_TRIGGER_REPLY_IOCSTATUS_MATCH_ALL)) 560 + continue; 561 + if ((le32_to_cpu(reply_trigger->ioc_log_info) != 562 + (le32_to_cpu(reply_trigger->ioc_log_info_mask) & 563 + ioc_loginfo))) 564 + continue; 565 + trigger_flags = reply_trigger->flags; 566 + mpi3mr_process_trigger(mrioc, 567 + MPI3MR_HDB_TRIGGER_TYPE_ELEMENT, 568 + (union mpi3mr_trigger_data *)reply_trigger, 569 + trigger_flags); 570 + break; 571 + } 572 + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); 573 + } 574 + } 575 + 576 + /** 320 577 * mpi3mr_get_num_trigger - Gets number of HDB triggers 321 578 * @mrioc: Adapter instance reference 322 579 * @num_triggers: Number of triggers ··· 706 449 * @type: Trigger type 707 450 * @data: Trigger data 708 451 * @force: Trigger overwrite flag 709 - * @trigger_data: pointer to trigger data information 452 + * @trigger_data: Pointer to trigger data information 710 453 * 711 454 * Updates trigger type and trigger data based on parameter 712 455 * passed to this function ··· 723 466 memset(&hdb->trigger_data, 0, sizeof(*trigger_data)); 724 467 else 725 468 memcpy(&hdb->trigger_data, trigger_data, sizeof(*trigger_data)); 469 + } 470 + 471 + /** 472 + * mpi3mr_set_trigger_data_in_all_hdb - Updates HDB trigger type 473 + * and trigger data for all HDB 474 + * 475 + * @mrioc: Adapter instance reference 476 + * @type: Trigger type 477 + * @data: Trigger data 478 + * @force: Trigger overwrite flag 479 + * @trigger_data: Pointer to trigger data information 480 + * 481 + * Updates trigger type and trigger data based on parameter 482 + * passed to this function 483 + * 484 + * Return: Nothing 485 + */ 486 + void mpi3mr_set_trigger_data_in_all_hdb(struct mpi3mr_ioc *mrioc, 487 + u8 type, union mpi3mr_trigger_data *trigger_data, bool force) 488 + { 489 + struct diag_buffer_desc *hdb = NULL; 490 + 491 + hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_TRACE); 492 + if (hdb) 493 + mpi3mr_set_trigger_data_in_hdb(hdb, type, trigger_data, force); 494 + hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW); 495 + if (hdb) 496 + mpi3mr_set_trigger_data_in_hdb(hdb, type, trigger_data, force); 497 + } 498 + 499 + /** 500 + * mpi3mr_hdbstatuschg_evt_th - HDB status change evt tophalf 501 + * @mrioc: Adapter instance reference 502 + * @event_reply: event data 503 + * 504 + * Modifies the status of the applicable diag buffer descriptors 505 + * 506 + * Return: Nothing 507 + */ 508 + void mpi3mr_hdbstatuschg_evt_th(struct mpi3mr_ioc *mrioc, 509 + struct mpi3_event_notification_reply *event_reply) 510 + { 511 + struct mpi3_event_data_diag_buffer_status_change *evtdata; 512 + struct diag_buffer_desc *diag_buffer; 513 + 514 + evtdata = (struct mpi3_event_data_diag_buffer_status_change *) 515 + event_reply->event_data; 516 + 517 + diag_buffer = mpi3mr_diag_buffer_for_type(mrioc, evtdata->type); 518 + if (!diag_buffer) 519 + return; 520 + if ((diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && 521 + (diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) 522 + return; 523 + switch (evtdata->reason_code) { 524 + case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED: 525 + { 526 + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_RELEASED; 527 + mpi3mr_set_trigger_data_in_hdb(diag_buffer, 528 + MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0); 529 + atomic64_inc(&event_counter); 530 + break; 531 + } 532 + case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED: 533 + { 534 + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED; 535 + break; 536 + } 537 + case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED: 538 + { 539 + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED; 540 + break; 541 + } 542 + default: 543 + dprint_event_th(mrioc, "%s: unknown reason_code(%d)\n", 544 + __func__, evtdata->reason_code); 545 + break; 546 + } 726 547 } 727 548 728 549 /**
+72 -7
drivers/scsi/mpi3mr/mpi3mr_fw.c
··· 274 274 case MPI3_EVENT_PREPARE_FOR_RESET: 275 275 desc = "Prepare For Reset"; 276 276 break; 277 + case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE: 278 + desc = "Diagnostic Buffer Status Change"; 279 + break; 277 280 } 278 281 279 282 if (!desc) ··· 345 342 { 346 343 u16 reply_desc_type, host_tag = 0; 347 344 u16 ioc_status = MPI3_IOCSTATUS_SUCCESS; 348 - u32 ioc_loginfo = 0; 345 + u32 ioc_loginfo = 0, sense_count = 0; 349 346 struct mpi3_status_reply_descriptor *status_desc; 350 347 struct mpi3_address_reply_descriptor *addr_desc; 351 348 struct mpi3_success_reply_descriptor *success_desc; 352 349 struct mpi3_default_reply *def_reply = NULL; 353 350 struct mpi3mr_drv_cmd *cmdptr = NULL; 354 351 struct mpi3_scsi_io_reply *scsi_reply; 352 + struct scsi_sense_hdr sshdr; 355 353 u8 *sense_buf = NULL; 356 354 357 355 *reply_dma = 0; ··· 367 363 MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) 368 364 ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info); 369 365 ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; 366 + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); 370 367 break; 371 368 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: 372 369 addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc; ··· 385 380 scsi_reply = (struct mpi3_scsi_io_reply *)def_reply; 386 381 sense_buf = mpi3mr_get_sensebuf_virt_addr(mrioc, 387 382 le64_to_cpu(scsi_reply->sense_data_buffer_address)); 383 + sense_count = le32_to_cpu(scsi_reply->sense_count); 384 + if (sense_buf) { 385 + scsi_normalize_sense(sense_buf, sense_count, 386 + &sshdr); 387 + mpi3mr_scsisense_trigger(mrioc, sshdr.sense_key, 388 + sshdr.asc, sshdr.ascq); 389 + } 388 390 } 391 + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); 389 392 break; 390 393 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: 391 394 success_desc = (struct mpi3_success_reply_descriptor *)reply_desc; ··· 951 938 }, 952 939 { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" }, 953 940 { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" }, 941 + { 942 + MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT, 943 + "diagnostic buffer post timeout" 944 + }, 945 + { 946 + MPI3MR_RESET_FROM_DIAG_BUFFER_RELEASE_TIMEOUT, 947 + "diagnostic buffer release timeout" 948 + }, 954 949 { MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronous reset" }, 955 950 { MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout"}, 956 951 { MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT, "timeout of a SAS transport layer request" }, ··· 2408 2387 void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code) 2409 2388 { 2410 2389 u32 ioc_status, host_diagnostic, timeout; 2390 + union mpi3mr_trigger_data trigger_data; 2411 2391 2412 2392 if (mrioc->unrecoverable) { 2413 2393 ioc_err(mrioc, "controller is unrecoverable\n"); ··· 2420 2398 ioc_err(mrioc, "controller is not present\n"); 2421 2399 return; 2422 2400 } 2423 - 2401 + memset(&trigger_data, 0, sizeof(trigger_data)); 2424 2402 ioc_status = readl(&mrioc->sysif_regs->ioc_status); 2425 - if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) || 2426 - (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) { 2403 + 2404 + if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { 2405 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 2406 + MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0); 2407 + return; 2408 + } else if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) { 2409 + trigger_data.fault = (readl(&mrioc->sysif_regs->fault) & 2410 + MPI3_SYSIF_FAULT_CODE_MASK); 2411 + 2412 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 2413 + MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); 2427 2414 mpi3mr_print_fault_info(mrioc); 2428 2415 return; 2429 2416 } 2417 + 2430 2418 mpi3mr_set_diagsave(mrioc); 2431 2419 mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, 2432 2420 reason_code); 2421 + trigger_data.fault = (readl(&mrioc->sysif_regs->fault) & 2422 + MPI3_SYSIF_FAULT_CODE_MASK); 2423 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, MPI3MR_HDB_TRIGGER_TYPE_FAULT, 2424 + &trigger_data, 0); 2433 2425 timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; 2434 2426 do { 2435 2427 host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic); ··· 2623 2587 container_of(work, struct mpi3mr_ioc, watchdog_work.work); 2624 2588 unsigned long flags; 2625 2589 enum mpi3mr_iocstate ioc_state; 2626 - u32 fault, host_diagnostic, ioc_status; 2590 + u32 host_diagnostic, ioc_status; 2591 + union mpi3mr_trigger_data trigger_data; 2627 2592 u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH; 2628 2593 2629 2594 if (mrioc->reset_in_progress) ··· 2655 2618 return; 2656 2619 } 2657 2620 2621 + memset(&trigger_data, 0, sizeof(trigger_data)); 2658 2622 ioc_status = readl(&mrioc->sysif_regs->ioc_status); 2659 2623 if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { 2624 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 2625 + MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0); 2660 2626 mpi3mr_soft_reset_handler(mrioc, MPI3MR_RESET_FROM_FIRMWARE, 0); 2661 2627 return; 2662 2628 } ··· 2669 2629 if (ioc_state != MRIOC_STATE_FAULT) 2670 2630 goto schedule_work; 2671 2631 2672 - fault = readl(&mrioc->sysif_regs->fault) & MPI3_SYSIF_FAULT_CODE_MASK; 2632 + trigger_data.fault = readl(&mrioc->sysif_regs->fault) & MPI3_SYSIF_FAULT_CODE_MASK; 2633 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 2634 + MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); 2673 2635 host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic); 2674 2636 if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) { 2675 2637 if (!mrioc->diagsave_timeout) { ··· 2685 2643 mpi3mr_print_fault_info(mrioc); 2686 2644 mrioc->diagsave_timeout = 0; 2687 2645 2688 - switch (fault) { 2646 + switch (trigger_data.fault) { 2689 2647 case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED: 2690 2648 case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED: 2691 2649 ioc_warn(mrioc, ··· 4032 3990 mpi3mr_unmask_events(mrioc, MPI3_EVENT_PREPARE_FOR_RESET); 4033 3991 mpi3mr_unmask_events(mrioc, MPI3_EVENT_CABLE_MGMT); 4034 3992 mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENERGY_PACK_CHANGE); 3993 + mpi3mr_unmask_events(mrioc, MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE); 4035 3994 4036 3995 retval = mpi3mr_issue_event_notification(mrioc); 4037 3996 if (retval) ··· 4208 4165 if (retval) { 4209 4166 ioc_err(mrioc, "failed to enable events %d\n", 4210 4167 retval); 4168 + goto out_failed; 4169 + } 4170 + 4171 + retval = mpi3mr_refresh_trigger(mrioc, MPI3_CONFIG_ACTION_READ_CURRENT); 4172 + if (retval) { 4173 + ioc_err(mrioc, "failed to refresh triggers\n"); 4211 4174 goto out_failed; 4212 4175 } 4213 4176 ··· 5155 5106 int retval = 0, i; 5156 5107 unsigned long flags; 5157 5108 u32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; 5109 + union mpi3mr_trigger_data trigger_data; 5158 5110 5159 5111 /* Block the reset handler until diag save in progress*/ 5160 5112 dprint_reset(mrioc, ··· 5188 5138 mrioc->reset_in_progress = 1; 5189 5139 mrioc->stop_bsgs = 1; 5190 5140 mrioc->prev_reset_result = -1; 5141 + memset(&trigger_data, 0, sizeof(trigger_data)); 5191 5142 5192 5143 if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && 5193 5144 (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) && 5194 5145 (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { 5146 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 5147 + MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET, NULL, 0); 5195 5148 dprint_reset(mrioc, 5196 5149 "soft_reset_handler: releasing host diagnostic buffers\n"); 5197 5150 mpi3mr_release_diag_bufs(mrioc, 0); ··· 5214 5161 retval = mpi3mr_issue_reset(mrioc, 5215 5162 MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); 5216 5163 if (!retval) { 5164 + trigger_data.fault = (readl(&mrioc->sysif_regs->fault) & 5165 + MPI3_SYSIF_FAULT_CODE_MASK); 5217 5166 do { 5218 5167 host_diagnostic = 5219 5168 readl(&mrioc->sysif_regs->host_diagnostic); ··· 5224 5169 break; 5225 5170 msleep(100); 5226 5171 } while (--timeout); 5172 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 5173 + MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); 5227 5174 } 5228 5175 } 5229 5176 ··· 5262 5205 } 5263 5206 mpi3mr_memset_buffers(mrioc); 5264 5207 mpi3mr_release_diag_bufs(mrioc, 1); 5208 + mrioc->fw_release_trigger_active = false; 5209 + mrioc->trace_release_trigger_active = false; 5210 + mrioc->snapdump_trigger_active = false; 5211 + mpi3mr_set_trigger_data_in_all_hdb(mrioc, 5212 + MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET, NULL, 0); 5213 + 5214 + dprint_reset(mrioc, 5215 + "soft_reset_handler: reinitializing the controller\n"); 5265 5216 retval = mpi3mr_reinit_ioc(mrioc, 0); 5266 5217 if (retval) { 5267 5218 pr_err(IOCNAME "reinit after soft reset failed: reason %d\n",
+113
drivers/scsi/mpi3mr/mpi3mr_os.c
··· 242 242 } 243 243 244 244 /** 245 + * mpi3mr_hdb_trigger_data_event - Add hdb trigger data event to 246 + * the list 247 + * @mrioc: Adapter instance reference 248 + * @event_data: Event data 249 + * 250 + * Add the given hdb trigger data event to the firmware event 251 + * list. 252 + * 253 + * Return: Nothing. 254 + */ 255 + void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc, 256 + struct trigger_event_data *event_data) 257 + { 258 + struct mpi3mr_fwevt *fwevt; 259 + u16 sz = sizeof(*event_data); 260 + 261 + fwevt = mpi3mr_alloc_fwevt(sz); 262 + if (!fwevt) { 263 + ioc_warn(mrioc, "failed to queue hdb trigger data event\n"); 264 + return; 265 + } 266 + 267 + fwevt->mrioc = mrioc; 268 + fwevt->event_id = MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER; 269 + fwevt->send_ack = 0; 270 + fwevt->process_evt = 1; 271 + fwevt->evt_ctx = 0; 272 + fwevt->event_data_size = sz; 273 + memcpy(fwevt->event_data, event_data, sz); 274 + 275 + mpi3mr_fwevt_add_to_list(mrioc, fwevt); 276 + } 277 + 278 + /** 245 279 * mpi3mr_fwevt_del_from_list - Delete firmware event from list 246 280 * @mrioc: Adapter instance reference 247 281 * @fwevt: Firmware event reference ··· 932 898 } 933 899 } else 934 900 mpi3mr_remove_tgtdev_from_sas_transport(mrioc, tgtdev); 901 + mpi3mr_global_trigger(mrioc, 902 + MPI3_DRIVER2_GLOBALTRIGGER_DEVICE_REMOVAL_ENABLED); 935 903 936 904 ioc_info(mrioc, "%s :Removed handle(0x%04x), wwid(0x%016llx)\n", 937 905 __func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid); ··· 1467 1431 } 1468 1432 out: 1469 1433 return r; 1434 + } 1435 + 1436 + /** 1437 + * mpi3mr_process_trigger_data_event_bh - Process trigger event 1438 + * data 1439 + * @mrioc: Adapter instance reference 1440 + * @event_data: Event data 1441 + * 1442 + * This function releases diage buffers or issues diag fault 1443 + * based on trigger conditions 1444 + * 1445 + * Return: Nothing 1446 + */ 1447 + static void mpi3mr_process_trigger_data_event_bh(struct mpi3mr_ioc *mrioc, 1448 + struct trigger_event_data *event_data) 1449 + { 1450 + struct diag_buffer_desc *trace_hdb = event_data->trace_hdb; 1451 + struct diag_buffer_desc *fw_hdb = event_data->fw_hdb; 1452 + unsigned long flags; 1453 + int retval = 0; 1454 + u8 trigger_type = event_data->trigger_type; 1455 + union mpi3mr_trigger_data *trigger_data = 1456 + &event_data->trigger_specific_data; 1457 + 1458 + if (event_data->snapdump) { 1459 + if (trace_hdb) 1460 + mpi3mr_set_trigger_data_in_hdb(trace_hdb, trigger_type, 1461 + trigger_data, 1); 1462 + if (fw_hdb) 1463 + mpi3mr_set_trigger_data_in_hdb(fw_hdb, trigger_type, 1464 + trigger_data, 1); 1465 + mpi3mr_soft_reset_handler(mrioc, 1466 + MPI3MR_RESET_FROM_TRIGGER, 1); 1467 + return; 1468 + } 1469 + 1470 + if (trace_hdb) { 1471 + retval = mpi3mr_issue_diag_buf_release(mrioc, trace_hdb); 1472 + if (!retval) { 1473 + mpi3mr_set_trigger_data_in_hdb(trace_hdb, trigger_type, 1474 + trigger_data, 1); 1475 + } 1476 + spin_lock_irqsave(&mrioc->trigger_lock, flags); 1477 + mrioc->trace_release_trigger_active = false; 1478 + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); 1479 + } 1480 + if (fw_hdb) { 1481 + retval = mpi3mr_issue_diag_buf_release(mrioc, fw_hdb); 1482 + if (!retval) { 1483 + mpi3mr_set_trigger_data_in_hdb(fw_hdb, trigger_type, 1484 + trigger_data, 1); 1485 + } 1486 + spin_lock_irqsave(&mrioc->trigger_lock, flags); 1487 + mrioc->fw_release_trigger_active = false; 1488 + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); 1489 + } 1470 1490 } 1471 1491 1472 1492 /** ··· 2109 2017 mpi3mr_refresh_tgtdevs(mrioc); 2110 2018 ioc_info(mrioc, 2111 2019 "scan for non responding and newly added devices after soft reset completed\n"); 2020 + break; 2021 + } 2022 + case MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER: 2023 + { 2024 + mpi3mr_process_trigger_data_event_bh(mrioc, 2025 + (struct trigger_event_data *)fwevt->event_data); 2112 2026 break; 2113 2027 } 2114 2028 default: ··· 2955 2857 ack_req = 1; 2956 2858 2957 2859 evt_type = event_reply->event; 2860 + mpi3mr_event_trigger(mrioc, event_reply->event); 2958 2861 2959 2862 switch (evt_type) { 2960 2863 case MPI3_EVENT_DEVICE_ADDED: ··· 2992 2893 { 2993 2894 mpi3mr_preparereset_evt_th(mrioc, event_reply); 2994 2895 ack_req = 0; 2896 + break; 2897 + } 2898 + case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE: 2899 + { 2900 + mpi3mr_hdbstatuschg_evt_th(mrioc, event_reply); 2995 2901 break; 2996 2902 } 2997 2903 case MPI3_EVENT_DEVICE_INFO_CHANGED: ··· 3262 3158 MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) 3263 3159 ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info); 3264 3160 ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; 3161 + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); 3265 3162 break; 3266 3163 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: 3267 3164 addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc; ··· 3291 3186 ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; 3292 3187 if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY) 3293 3188 panic("%s: Ran out of sense buffers\n", mrioc->name); 3189 + if (sense_buf) { 3190 + scsi_normalize_sense(sense_buf, sense_count, &sshdr); 3191 + mpi3mr_scsisense_trigger(mrioc, sshdr.sense_key, 3192 + sshdr.asc, sshdr.ascq); 3193 + } 3194 + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); 3294 3195 break; 3295 3196 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: 3296 3197 success_desc = (struct mpi3_success_reply_descriptor *)reply_desc; ··· 3922 3811 default: 3923 3812 break; 3924 3813 } 3814 + mpi3mr_global_trigger(mrioc, 3815 + MPI3_DRIVER2_GLOBALTRIGGER_TASK_MANAGEMENT_ENABLED); 3925 3816 3926 3817 out_unlock: 3927 3818 drv_cmd->state = MPI3MR_CMD_NOTUSED;