diff options
author | Hieu Tran <hieu.t.tran@intel.com> | 2018-08-09 09:29:55 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2018-08-28 14:04:04 -0400 |
commit | 8b97ceb1dc0f29d6af0cd85983041a9fbac8e14c (patch) | |
tree | a091d9a3a62f3b0fd7c90721ca967dae29c11e27 /drivers/net/ethernet/intel/ice/ice_common.c | |
parent | b1edc14a3fbfe0154a2aecb8bb9775c3012cb6e2 (diff) |
ice: Enable firmware logging during device initialization.
To enable FW logging, the "cq_en" and "uart_en" enable bits of the
"fw_log" element in struct ice_hw need to set accordingly based on
some user-provided parameters during driver loading. To select which
FW log events to be emitted, the "cfg" elements of corresponding FW
modules in the "evnts" array member of "fw_log" need to be configured.
Signed-off-by: Hieu Tran <hieu.t.tran@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_common.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_common.c | 182 |
1 files changed, 180 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 52c2bf4f108e..0847dbf9d42f 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c | |||
@@ -427,6 +427,176 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw) | |||
427 | devm_kfree(ice_hw_to_dev(hw), sw); | 427 | devm_kfree(ice_hw_to_dev(hw), sw); |
428 | } | 428 | } |
429 | 429 | ||
430 | #define ICE_FW_LOG_DESC_SIZE(n) (sizeof(struct ice_aqc_fw_logging_data) + \ | ||
431 | (((n) - 1) * sizeof(((struct ice_aqc_fw_logging_data *)0)->entry))) | ||
432 | #define ICE_FW_LOG_DESC_SIZE_MAX \ | ||
433 | ICE_FW_LOG_DESC_SIZE(ICE_AQC_FW_LOG_ID_MAX) | ||
434 | |||
435 | /** | ||
436 | * ice_cfg_fw_log - configure FW logging | ||
437 | * @hw: pointer to the hw struct | ||
438 | * @enable: enable certain FW logging events if true, disable all if false | ||
439 | * | ||
440 | * This function enables/disables the FW logging via Rx CQ events and a UART | ||
441 | * port based on predetermined configurations. FW logging via the Rx CQ can be | ||
442 | * enabled/disabled for individual PF's. However, FW logging via the UART can | ||
443 | * only be enabled/disabled for all PFs on the same device. | ||
444 | * | ||
445 | * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in | ||
446 | * hw->fw_log need to be set accordingly, e.g. based on user-provided input, | ||
447 | * before initializing the device. | ||
448 | * | ||
449 | * When re/configuring FW logging, callers need to update the "cfg" elements of | ||
450 | * the hw->fw_log.evnts array with the desired logging event configurations for | ||
451 | * modules of interest. When disabling FW logging completely, the callers can | ||
452 | * just pass false in the "enable" parameter. On completion, the function will | ||
453 | * update the "cur" element of the hw->fw_log.evnts array with the resulting | ||
454 | * logging event configurations of the modules that are being re/configured. FW | ||
455 | * logging modules that are not part of a reconfiguration operation retain their | ||
456 | * previous states. | ||
457 | * | ||
458 | * Before resetting the device, it is recommended that the driver disables FW | ||
459 | * logging before shutting down the control queue. When disabling FW logging | ||
460 | * ("enable" = false), the latest configurations of FW logging events stored in | ||
461 | * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after | ||
462 | * a device reset. | ||
463 | * | ||
464 | * When enabling FW logging to emit log messages via the Rx CQ during the | ||
465 | * device's initialization phase, a mechanism alternative to interrupt handlers | ||
466 | * needs to be used to extract FW log messages from the Rx CQ periodically and | ||
467 | * to prevent the Rx CQ from being full and stalling other types of control | ||
468 | * messages from FW to SW. Interrupts are typically disabled during the device's | ||
469 | * initialization phase. | ||
470 | */ | ||
471 | static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable) | ||
472 | { | ||
473 | struct ice_aqc_fw_logging_data *data = NULL; | ||
474 | struct ice_aqc_fw_logging *cmd; | ||
475 | enum ice_status status = 0; | ||
476 | u16 i, chgs = 0, len = 0; | ||
477 | struct ice_aq_desc desc; | ||
478 | u8 actv_evnts = 0; | ||
479 | void *buf = NULL; | ||
480 | |||
481 | if (!hw->fw_log.cq_en && !hw->fw_log.uart_en) | ||
482 | return 0; | ||
483 | |||
484 | /* Disable FW logging only when the control queue is still responsive */ | ||
485 | if (!enable && | ||
486 | (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq))) | ||
487 | return 0; | ||
488 | |||
489 | ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging); | ||
490 | cmd = &desc.params.fw_logging; | ||
491 | |||
492 | /* Indicate which controls are valid */ | ||
493 | if (hw->fw_log.cq_en) | ||
494 | cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID; | ||
495 | |||
496 | if (hw->fw_log.uart_en) | ||
497 | cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID; | ||
498 | |||
499 | if (enable) { | ||
500 | /* Fill in an array of entries with FW logging modules and | ||
501 | * logging events being reconfigured. | ||
502 | */ | ||
503 | for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { | ||
504 | u16 val; | ||
505 | |||
506 | /* Keep track of enabled event types */ | ||
507 | actv_evnts |= hw->fw_log.evnts[i].cfg; | ||
508 | |||
509 | if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur) | ||
510 | continue; | ||
511 | |||
512 | if (!data) { | ||
513 | data = devm_kzalloc(ice_hw_to_dev(hw), | ||
514 | ICE_FW_LOG_DESC_SIZE_MAX, | ||
515 | GFP_KERNEL); | ||
516 | if (!data) | ||
517 | return ICE_ERR_NO_MEMORY; | ||
518 | } | ||
519 | |||
520 | val = i << ICE_AQC_FW_LOG_ID_S; | ||
521 | val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S; | ||
522 | data->entry[chgs++] = cpu_to_le16(val); | ||
523 | } | ||
524 | |||
525 | /* Only enable FW logging if at least one module is specified. | ||
526 | * If FW logging is currently enabled but all modules are not | ||
527 | * enabled to emit log messages, disable FW logging altogether. | ||
528 | */ | ||
529 | if (actv_evnts) { | ||
530 | /* Leave if there is effectively no change */ | ||
531 | if (!chgs) | ||
532 | goto out; | ||
533 | |||
534 | if (hw->fw_log.cq_en) | ||
535 | cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN; | ||
536 | |||
537 | if (hw->fw_log.uart_en) | ||
538 | cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN; | ||
539 | |||
540 | buf = data; | ||
541 | len = ICE_FW_LOG_DESC_SIZE(chgs); | ||
542 | desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | status = ice_aq_send_cmd(hw, &desc, buf, len, NULL); | ||
547 | if (!status) { | ||
548 | /* Update the current configuration to reflect events enabled. | ||
549 | * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW | ||
550 | * logging mode is enabled for the device. They do not reflect | ||
551 | * actual modules being enabled to emit log messages. So, their | ||
552 | * values remain unchanged even when all modules are disabled. | ||
553 | */ | ||
554 | u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX; | ||
555 | |||
556 | hw->fw_log.actv_evnts = actv_evnts; | ||
557 | for (i = 0; i < cnt; i++) { | ||
558 | u16 v, m; | ||
559 | |||
560 | if (!enable) { | ||
561 | /* When disabling all FW logging events as part | ||
562 | * of device's de-initialization, the original | ||
563 | * configurations are retained, and can be used | ||
564 | * to reconfigure FW logging later if the device | ||
565 | * is re-initialized. | ||
566 | */ | ||
567 | hw->fw_log.evnts[i].cur = 0; | ||
568 | continue; | ||
569 | } | ||
570 | |||
571 | v = le16_to_cpu(data->entry[i]); | ||
572 | m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; | ||
573 | hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | out: | ||
578 | if (data) | ||
579 | devm_kfree(ice_hw_to_dev(hw), data); | ||
580 | |||
581 | return status; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * ice_output_fw_log | ||
586 | * @hw: pointer to the hw struct | ||
587 | * @desc: pointer to the AQ message descriptor | ||
588 | * @buf: pointer to the buffer accompanying the AQ message | ||
589 | * | ||
590 | * Formats a FW Log message and outputs it via the standard driver logs. | ||
591 | */ | ||
592 | void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf) | ||
593 | { | ||
594 | ice_debug(hw, ICE_DBG_AQ_MSG, "[ FW Log Msg Start ]\n"); | ||
595 | ice_debug_array(hw, ICE_DBG_AQ_MSG, 16, 1, (u8 *)buf, | ||
596 | le16_to_cpu(desc->datalen)); | ||
597 | ice_debug(hw, ICE_DBG_AQ_MSG, "[ FW Log Msg End ]\n"); | ||
598 | } | ||
599 | |||
430 | /** | 600 | /** |
431 | * ice_init_hw - main hardware initialization routine | 601 | * ice_init_hw - main hardware initialization routine |
432 | * @hw: pointer to the hardware structure | 602 | * @hw: pointer to the hardware structure |
@@ -461,6 +631,11 @@ enum ice_status ice_init_hw(struct ice_hw *hw) | |||
461 | if (status) | 631 | if (status) |
462 | goto err_unroll_cqinit; | 632 | goto err_unroll_cqinit; |
463 | 633 | ||
634 | /* Enable FW logging. Not fatal if this fails. */ | ||
635 | status = ice_cfg_fw_log(hw, true); | ||
636 | if (status) | ||
637 | ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n"); | ||
638 | |||
464 | status = ice_clear_pf_cfg(hw); | 639 | status = ice_clear_pf_cfg(hw); |
465 | if (status) | 640 | if (status) |
466 | goto err_unroll_cqinit; | 641 | goto err_unroll_cqinit; |
@@ -574,15 +749,18 @@ err_unroll_cqinit: | |||
574 | */ | 749 | */ |
575 | void ice_deinit_hw(struct ice_hw *hw) | 750 | void ice_deinit_hw(struct ice_hw *hw) |
576 | { | 751 | { |
752 | ice_cleanup_fltr_mgmt_struct(hw); | ||
753 | |||
577 | ice_sched_cleanup_all(hw); | 754 | ice_sched_cleanup_all(hw); |
578 | ice_shutdown_all_ctrlq(hw); | ||
579 | 755 | ||
580 | if (hw->port_info) { | 756 | if (hw->port_info) { |
581 | devm_kfree(ice_hw_to_dev(hw), hw->port_info); | 757 | devm_kfree(ice_hw_to_dev(hw), hw->port_info); |
582 | hw->port_info = NULL; | 758 | hw->port_info = NULL; |
583 | } | 759 | } |
584 | 760 | ||
585 | ice_cleanup_fltr_mgmt_struct(hw); | 761 | /* Attempt to disable FW logging before shutting down control queues */ |
762 | ice_cfg_fw_log(hw, false); | ||
763 | ice_shutdown_all_ctrlq(hw); | ||
586 | } | 764 | } |
587 | 765 | ||
588 | /** | 766 | /** |