aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/ice/ice_common.c
diff options
context:
space:
mode:
authorHieu Tran <hieu.t.tran@intel.com>2018-08-09 09:29:55 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-08-28 14:04:04 -0400
commit8b97ceb1dc0f29d6af0cd85983041a9fbac8e14c (patch)
treea091d9a3a62f3b0fd7c90721ca967dae29c11e27 /drivers/net/ethernet/intel/ice/ice_common.c
parentb1edc14a3fbfe0154a2aecb8bb9775c3012cb6e2 (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.c182
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 */
471static 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
577out:
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 */
592void 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 */
575void ice_deinit_hw(struct ice_hw *hw) 750void 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/**