| .. | .. |
|---|
| 30 | 30 | * SOFTWARE. |
|---|
| 31 | 31 | */ |
|---|
| 32 | 32 | #define CREATE_TRACE_POINTS |
|---|
| 33 | +#include "lib/eq.h" |
|---|
| 33 | 34 | #include "fw_tracer.h" |
|---|
| 34 | 35 | #include "fw_tracer_tracepoint.h" |
|---|
| 35 | 36 | |
|---|
| .. | .. |
|---|
| 63 | 64 | MLX5_GET(mtrc_cap, out, num_string_trace); |
|---|
| 64 | 65 | tracer->str_db.num_string_db = MLX5_GET(mtrc_cap, out, num_string_db); |
|---|
| 65 | 66 | tracer->owner = !!MLX5_GET(mtrc_cap, out, trace_owner); |
|---|
| 67 | + tracer->str_db.loaded = false; |
|---|
| 66 | 68 | |
|---|
| 67 | 69 | for (i = 0; i < tracer->str_db.num_string_db; i++) { |
|---|
| 68 | 70 | mtrc_cap_sp = MLX5_ADDR_OF(mtrc_cap, out, string_db_param[i]); |
|---|
| .. | .. |
|---|
| 123 | 125 | static int mlx5_fw_tracer_create_log_buf(struct mlx5_fw_tracer *tracer) |
|---|
| 124 | 126 | { |
|---|
| 125 | 127 | struct mlx5_core_dev *dev = tracer->dev; |
|---|
| 126 | | - struct device *ddev = &dev->pdev->dev; |
|---|
| 128 | + struct device *ddev; |
|---|
| 127 | 129 | dma_addr_t dma; |
|---|
| 128 | 130 | void *buff; |
|---|
| 129 | 131 | gfp_t gfp; |
|---|
| .. | .. |
|---|
| 141 | 143 | } |
|---|
| 142 | 144 | tracer->buff.log_buf = buff; |
|---|
| 143 | 145 | |
|---|
| 146 | + ddev = mlx5_core_dma_dev(dev); |
|---|
| 144 | 147 | dma = dma_map_single(ddev, buff, tracer->buff.size, DMA_FROM_DEVICE); |
|---|
| 145 | 148 | if (dma_mapping_error(ddev, dma)) { |
|---|
| 146 | 149 | mlx5_core_warn(dev, "FWTracer: Unable to map DMA: %d\n", |
|---|
| .. | .. |
|---|
| 161 | 164 | static void mlx5_fw_tracer_destroy_log_buf(struct mlx5_fw_tracer *tracer) |
|---|
| 162 | 165 | { |
|---|
| 163 | 166 | struct mlx5_core_dev *dev = tracer->dev; |
|---|
| 164 | | - struct device *ddev = &dev->pdev->dev; |
|---|
| 167 | + struct device *ddev; |
|---|
| 165 | 168 | |
|---|
| 166 | 169 | if (!tracer->buff.log_buf) |
|---|
| 167 | 170 | return; |
|---|
| 168 | 171 | |
|---|
| 172 | + ddev = mlx5_core_dma_dev(dev); |
|---|
| 169 | 173 | dma_unmap_single(ddev, tracer->buff.dma, tracer->buff.size, DMA_FROM_DEVICE); |
|---|
| 170 | 174 | free_pages((unsigned long)tracer->buff.log_buf, get_order(tracer->buff.size)); |
|---|
| 171 | 175 | } |
|---|
| .. | .. |
|---|
| 187 | 191 | |
|---|
| 188 | 192 | MLX5_SET(create_mkey_in, in, translations_octword_actual_size, |
|---|
| 189 | 193 | DIV_ROUND_UP(TRACER_BUFFER_PAGE_NUM, 2)); |
|---|
| 190 | | - mtt = (u64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt); |
|---|
| 194 | + mtt = (__be64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt); |
|---|
| 191 | 195 | for (i = 0 ; i < TRACER_BUFFER_PAGE_NUM ; i++) |
|---|
| 192 | 196 | mtt[i] = cpu_to_be64(tracer->buff.dma + i * PAGE_SIZE); |
|---|
| 193 | 197 | |
|---|
| .. | .. |
|---|
| 240 | 244 | free_strings_db: |
|---|
| 241 | 245 | mlx5_fw_tracer_free_strings_db(tracer); |
|---|
| 242 | 246 | return -ENOMEM; |
|---|
| 247 | +} |
|---|
| 248 | + |
|---|
| 249 | +static void |
|---|
| 250 | +mlx5_fw_tracer_init_saved_traces_array(struct mlx5_fw_tracer *tracer) |
|---|
| 251 | +{ |
|---|
| 252 | + tracer->st_arr.saved_traces_index = 0; |
|---|
| 253 | + mutex_init(&tracer->st_arr.lock); |
|---|
| 254 | +} |
|---|
| 255 | + |
|---|
| 256 | +static void |
|---|
| 257 | +mlx5_fw_tracer_clean_saved_traces_array(struct mlx5_fw_tracer *tracer) |
|---|
| 258 | +{ |
|---|
| 259 | + mutex_destroy(&tracer->st_arr.lock); |
|---|
| 243 | 260 | } |
|---|
| 244 | 261 | |
|---|
| 245 | 262 | static void mlx5_tracer_read_strings_db(struct work_struct *work) |
|---|
| .. | .. |
|---|
| 466 | 483 | (u64)timestamp_low; |
|---|
| 467 | 484 | break; |
|---|
| 468 | 485 | default: |
|---|
| 469 | | - if (tracer_event->event_id >= tracer->str_db.first_string_trace || |
|---|
| 486 | + if (tracer_event->event_id >= tracer->str_db.first_string_trace && |
|---|
| 470 | 487 | tracer_event->event_id <= tracer->str_db.first_string_trace + |
|---|
| 471 | 488 | tracer->str_db.num_string_trace) { |
|---|
| 472 | 489 | tracer_event->type = TRACER_EVENT_TYPE_STRING; |
|---|
| .. | .. |
|---|
| 521 | 538 | list_del(&str_frmt->list); |
|---|
| 522 | 539 | } |
|---|
| 523 | 540 | |
|---|
| 524 | | -static void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, |
|---|
| 525 | | - struct mlx5_core_dev *dev, |
|---|
| 526 | | - u64 trace_timestamp) |
|---|
| 541 | +static void mlx5_fw_tracer_save_trace(struct mlx5_fw_tracer *tracer, |
|---|
| 542 | + u64 timestamp, bool lost, |
|---|
| 543 | + u8 event_id, char *msg) |
|---|
| 544 | +{ |
|---|
| 545 | + struct mlx5_fw_trace_data *trace_data; |
|---|
| 546 | + |
|---|
| 547 | + mutex_lock(&tracer->st_arr.lock); |
|---|
| 548 | + trace_data = &tracer->st_arr.straces[tracer->st_arr.saved_traces_index]; |
|---|
| 549 | + trace_data->timestamp = timestamp; |
|---|
| 550 | + trace_data->lost = lost; |
|---|
| 551 | + trace_data->event_id = event_id; |
|---|
| 552 | + strscpy_pad(trace_data->msg, msg, TRACE_STR_MSG); |
|---|
| 553 | + |
|---|
| 554 | + tracer->st_arr.saved_traces_index = |
|---|
| 555 | + (tracer->st_arr.saved_traces_index + 1) & (SAVED_TRACES_NUM - 1); |
|---|
| 556 | + mutex_unlock(&tracer->st_arr.lock); |
|---|
| 557 | +} |
|---|
| 558 | + |
|---|
| 559 | +static noinline |
|---|
| 560 | +void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt, |
|---|
| 561 | + struct mlx5_core_dev *dev, |
|---|
| 562 | + u64 trace_timestamp) |
|---|
| 527 | 563 | { |
|---|
| 528 | 564 | char tmp[512]; |
|---|
| 529 | 565 | |
|---|
| .. | .. |
|---|
| 538 | 574 | |
|---|
| 539 | 575 | trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost, |
|---|
| 540 | 576 | str_frmt->event_id, tmp); |
|---|
| 577 | + |
|---|
| 578 | + mlx5_fw_tracer_save_trace(dev->tracer, trace_timestamp, |
|---|
| 579 | + str_frmt->lost, str_frmt->event_id, tmp); |
|---|
| 541 | 580 | |
|---|
| 542 | 581 | /* remove it from hash */ |
|---|
| 543 | 582 | mlx5_tracer_clean_message(str_frmt); |
|---|
| .. | .. |
|---|
| 564 | 603 | } else { |
|---|
| 565 | 604 | cur_string = mlx5_tracer_message_get(tracer, tracer_event); |
|---|
| 566 | 605 | if (!cur_string) { |
|---|
| 567 | | - pr_debug("%s Got string event for unknown string tdsm: %d\n", |
|---|
| 606 | + pr_debug("%s Got string event for unknown string tmsn: %d\n", |
|---|
| 568 | 607 | __func__, tracer_event->string_event.tmsn); |
|---|
| 569 | 608 | return -1; |
|---|
| 570 | 609 | } |
|---|
| .. | .. |
|---|
| 600 | 639 | trace_timestamp = (timestamp_event.timestamp & MASK_52_7) | |
|---|
| 601 | 640 | (str_frmt->timestamp & MASK_6_0); |
|---|
| 602 | 641 | else |
|---|
| 603 | | - trace_timestamp = ((timestamp_event.timestamp & MASK_52_7) - 1) | |
|---|
| 642 | + trace_timestamp = ((timestamp_event.timestamp - 1) & MASK_52_7) | |
|---|
| 604 | 643 | (str_frmt->timestamp & MASK_6_0); |
|---|
| 605 | 644 | |
|---|
| 606 | 645 | mlx5_tracer_print_trace(str_frmt, dev, trace_timestamp); |
|---|
| .. | .. |
|---|
| 637 | 676 | if (!tracer->owner) |
|---|
| 638 | 677 | return; |
|---|
| 639 | 678 | |
|---|
| 679 | + if (unlikely(!tracer->str_db.loaded)) |
|---|
| 680 | + goto arm; |
|---|
| 681 | + |
|---|
| 640 | 682 | block_count = tracer->buff.size / TRACER_BLOCK_SIZE_BYTE; |
|---|
| 641 | 683 | start_offset = tracer->buff.consumer_index * TRACER_BLOCK_SIZE_BYTE; |
|---|
| 642 | 684 | |
|---|
| 643 | | - /* Copy the block to local buffer to avoid HW override while being processed*/ |
|---|
| 685 | + /* Copy the block to local buffer to avoid HW override while being processed */ |
|---|
| 644 | 686 | memcpy(tmp_trace_block, tracer->buff.log_buf + start_offset, |
|---|
| 645 | 687 | TRACER_BLOCK_SIZE_BYTE); |
|---|
| 646 | 688 | |
|---|
| .. | .. |
|---|
| 648 | 690 | get_block_timestamp(tracer, &tmp_trace_block[TRACES_PER_BLOCK - 1]); |
|---|
| 649 | 691 | |
|---|
| 650 | 692 | while (block_timestamp > tracer->last_timestamp) { |
|---|
| 651 | | - /* Check block override if its not the first block */ |
|---|
| 693 | + /* Check block override if it's not the first block */ |
|---|
| 652 | 694 | if (!tracer->last_timestamp) { |
|---|
| 653 | 695 | u64 *ts_event; |
|---|
| 654 | 696 | /* To avoid block override be the HW in case of buffer |
|---|
| .. | .. |
|---|
| 694 | 736 | &tmp_trace_block[TRACES_PER_BLOCK - 1]); |
|---|
| 695 | 737 | } |
|---|
| 696 | 738 | |
|---|
| 739 | +arm: |
|---|
| 697 | 740 | mlx5_fw_tracer_arm(dev); |
|---|
| 698 | 741 | } |
|---|
| 699 | 742 | |
|---|
| .. | .. |
|---|
| 714 | 757 | if (err) |
|---|
| 715 | 758 | mlx5_core_warn(dev, "FWTracer: Failed to set tracer configurations %d\n", err); |
|---|
| 716 | 759 | |
|---|
| 760 | + tracer->buff.consumer_index = 0; |
|---|
| 717 | 761 | return err; |
|---|
| 718 | 762 | } |
|---|
| 719 | 763 | |
|---|
| .. | .. |
|---|
| 778 | 822 | mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner); |
|---|
| 779 | 823 | if (tracer->owner) { |
|---|
| 780 | 824 | tracer->owner = false; |
|---|
| 781 | | - tracer->buff.consumer_index = 0; |
|---|
| 782 | 825 | return; |
|---|
| 783 | 826 | } |
|---|
| 784 | 827 | |
|---|
| 785 | 828 | mlx5_fw_tracer_start(tracer); |
|---|
| 829 | +} |
|---|
| 830 | + |
|---|
| 831 | +static int mlx5_fw_tracer_set_core_dump_reg(struct mlx5_core_dev *dev, |
|---|
| 832 | + u32 *in, int size_in) |
|---|
| 833 | +{ |
|---|
| 834 | + u32 out[MLX5_ST_SZ_DW(core_dump_reg)] = {}; |
|---|
| 835 | + |
|---|
| 836 | + if (!MLX5_CAP_DEBUG(dev, core_dump_general) && |
|---|
| 837 | + !MLX5_CAP_DEBUG(dev, core_dump_qp)) |
|---|
| 838 | + return -EOPNOTSUPP; |
|---|
| 839 | + |
|---|
| 840 | + return mlx5_core_access_reg(dev, in, size_in, out, sizeof(out), |
|---|
| 841 | + MLX5_REG_CORE_DUMP, 0, 1); |
|---|
| 842 | +} |
|---|
| 843 | + |
|---|
| 844 | +int mlx5_fw_tracer_trigger_core_dump_general(struct mlx5_core_dev *dev) |
|---|
| 845 | +{ |
|---|
| 846 | + struct mlx5_fw_tracer *tracer = dev->tracer; |
|---|
| 847 | + u32 in[MLX5_ST_SZ_DW(core_dump_reg)] = {}; |
|---|
| 848 | + int err; |
|---|
| 849 | + |
|---|
| 850 | + if (!MLX5_CAP_DEBUG(dev, core_dump_general) || !tracer) |
|---|
| 851 | + return -EOPNOTSUPP; |
|---|
| 852 | + if (!tracer->owner) |
|---|
| 853 | + return -EPERM; |
|---|
| 854 | + |
|---|
| 855 | + MLX5_SET(core_dump_reg, in, core_dump_type, 0x0); |
|---|
| 856 | + |
|---|
| 857 | + err = mlx5_fw_tracer_set_core_dump_reg(dev, in, sizeof(in)); |
|---|
| 858 | + if (err) |
|---|
| 859 | + return err; |
|---|
| 860 | + queue_work(tracer->work_queue, &tracer->handle_traces_work); |
|---|
| 861 | + flush_workqueue(tracer->work_queue); |
|---|
| 862 | + return 0; |
|---|
| 863 | +} |
|---|
| 864 | + |
|---|
| 865 | +static int |
|---|
| 866 | +mlx5_devlink_fmsg_fill_trace(struct devlink_fmsg *fmsg, |
|---|
| 867 | + struct mlx5_fw_trace_data *trace_data) |
|---|
| 868 | +{ |
|---|
| 869 | + int err; |
|---|
| 870 | + |
|---|
| 871 | + err = devlink_fmsg_obj_nest_start(fmsg); |
|---|
| 872 | + if (err) |
|---|
| 873 | + return err; |
|---|
| 874 | + |
|---|
| 875 | + err = devlink_fmsg_u64_pair_put(fmsg, "timestamp", trace_data->timestamp); |
|---|
| 876 | + if (err) |
|---|
| 877 | + return err; |
|---|
| 878 | + |
|---|
| 879 | + err = devlink_fmsg_bool_pair_put(fmsg, "lost", trace_data->lost); |
|---|
| 880 | + if (err) |
|---|
| 881 | + return err; |
|---|
| 882 | + |
|---|
| 883 | + err = devlink_fmsg_u8_pair_put(fmsg, "event_id", trace_data->event_id); |
|---|
| 884 | + if (err) |
|---|
| 885 | + return err; |
|---|
| 886 | + |
|---|
| 887 | + err = devlink_fmsg_string_pair_put(fmsg, "msg", trace_data->msg); |
|---|
| 888 | + if (err) |
|---|
| 889 | + return err; |
|---|
| 890 | + |
|---|
| 891 | + err = devlink_fmsg_obj_nest_end(fmsg); |
|---|
| 892 | + if (err) |
|---|
| 893 | + return err; |
|---|
| 894 | + return 0; |
|---|
| 895 | +} |
|---|
| 896 | + |
|---|
| 897 | +int mlx5_fw_tracer_get_saved_traces_objects(struct mlx5_fw_tracer *tracer, |
|---|
| 898 | + struct devlink_fmsg *fmsg) |
|---|
| 899 | +{ |
|---|
| 900 | + struct mlx5_fw_trace_data *straces = tracer->st_arr.straces; |
|---|
| 901 | + u32 index, start_index, end_index; |
|---|
| 902 | + u32 saved_traces_index; |
|---|
| 903 | + int err; |
|---|
| 904 | + |
|---|
| 905 | + if (!straces[0].timestamp) |
|---|
| 906 | + return -ENOMSG; |
|---|
| 907 | + |
|---|
| 908 | + mutex_lock(&tracer->st_arr.lock); |
|---|
| 909 | + saved_traces_index = tracer->st_arr.saved_traces_index; |
|---|
| 910 | + if (straces[saved_traces_index].timestamp) |
|---|
| 911 | + start_index = saved_traces_index; |
|---|
| 912 | + else |
|---|
| 913 | + start_index = 0; |
|---|
| 914 | + end_index = (saved_traces_index - 1) & (SAVED_TRACES_NUM - 1); |
|---|
| 915 | + |
|---|
| 916 | + err = devlink_fmsg_arr_pair_nest_start(fmsg, "dump fw traces"); |
|---|
| 917 | + if (err) |
|---|
| 918 | + goto unlock; |
|---|
| 919 | + index = start_index; |
|---|
| 920 | + while (index != end_index) { |
|---|
| 921 | + err = mlx5_devlink_fmsg_fill_trace(fmsg, &straces[index]); |
|---|
| 922 | + if (err) |
|---|
| 923 | + goto unlock; |
|---|
| 924 | + |
|---|
| 925 | + index = (index + 1) & (SAVED_TRACES_NUM - 1); |
|---|
| 926 | + } |
|---|
| 927 | + |
|---|
| 928 | + err = devlink_fmsg_arr_pair_nest_end(fmsg); |
|---|
| 929 | +unlock: |
|---|
| 930 | + mutex_unlock(&tracer->st_arr.lock); |
|---|
| 931 | + return err; |
|---|
| 786 | 932 | } |
|---|
| 787 | 933 | |
|---|
| 788 | 934 | /* Create software resources (Buffers, etc ..) */ |
|---|
| .. | .. |
|---|
| 832 | 978 | goto free_log_buf; |
|---|
| 833 | 979 | } |
|---|
| 834 | 980 | |
|---|
| 981 | + mlx5_fw_tracer_init_saved_traces_array(tracer); |
|---|
| 835 | 982 | mlx5_core_dbg(dev, "FWTracer: Tracer created\n"); |
|---|
| 836 | 983 | |
|---|
| 837 | 984 | return tracer; |
|---|
| .. | .. |
|---|
| 846 | 993 | return ERR_PTR(err); |
|---|
| 847 | 994 | } |
|---|
| 848 | 995 | |
|---|
| 849 | | -/* Create HW resources + start tracer |
|---|
| 850 | | - * must be called before Async EQ is created |
|---|
| 851 | | - */ |
|---|
| 996 | +static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data); |
|---|
| 997 | + |
|---|
| 998 | +/* Create HW resources + start tracer */ |
|---|
| 852 | 999 | int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer) |
|---|
| 853 | 1000 | { |
|---|
| 854 | 1001 | struct mlx5_core_dev *dev; |
|---|
| .. | .. |
|---|
| 865 | 1012 | err = mlx5_core_alloc_pd(dev, &tracer->buff.pdn); |
|---|
| 866 | 1013 | if (err) { |
|---|
| 867 | 1014 | mlx5_core_warn(dev, "FWTracer: Failed to allocate PD %d\n", err); |
|---|
| 868 | | - return err; |
|---|
| 1015 | + goto err_cancel_work; |
|---|
| 869 | 1016 | } |
|---|
| 870 | 1017 | |
|---|
| 871 | 1018 | err = mlx5_fw_tracer_create_mkey(tracer); |
|---|
| .. | .. |
|---|
| 874 | 1021 | goto err_dealloc_pd; |
|---|
| 875 | 1022 | } |
|---|
| 876 | 1023 | |
|---|
| 877 | | - mlx5_fw_tracer_start(tracer); |
|---|
| 1024 | + MLX5_NB_INIT(&tracer->nb, fw_tracer_event, DEVICE_TRACER); |
|---|
| 1025 | + mlx5_eq_notifier_register(dev, &tracer->nb); |
|---|
| 878 | 1026 | |
|---|
| 1027 | + err = mlx5_fw_tracer_start(tracer); |
|---|
| 1028 | + if (err) { |
|---|
| 1029 | + mlx5_core_warn(dev, "FWTracer: Failed to start tracer %d\n", err); |
|---|
| 1030 | + goto err_notifier_unregister; |
|---|
| 1031 | + } |
|---|
| 879 | 1032 | return 0; |
|---|
| 880 | 1033 | |
|---|
| 1034 | +err_notifier_unregister: |
|---|
| 1035 | + mlx5_eq_notifier_unregister(dev, &tracer->nb); |
|---|
| 1036 | + mlx5_core_destroy_mkey(dev, &tracer->buff.mkey); |
|---|
| 881 | 1037 | err_dealloc_pd: |
|---|
| 882 | 1038 | mlx5_core_dealloc_pd(dev, tracer->buff.pdn); |
|---|
| 1039 | +err_cancel_work: |
|---|
| 1040 | + cancel_work_sync(&tracer->read_fw_strings_work); |
|---|
| 883 | 1041 | return err; |
|---|
| 884 | 1042 | } |
|---|
| 885 | 1043 | |
|---|
| 886 | | -/* Stop tracer + Cleanup HW resources |
|---|
| 887 | | - * must be called after Async EQ is destroyed |
|---|
| 888 | | - */ |
|---|
| 1044 | +/* Stop tracer + Cleanup HW resources */ |
|---|
| 889 | 1045 | void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer) |
|---|
| 890 | 1046 | { |
|---|
| 891 | 1047 | if (IS_ERR_OR_NULL(tracer)) |
|---|
| .. | .. |
|---|
| 893 | 1049 | |
|---|
| 894 | 1050 | mlx5_core_dbg(tracer->dev, "FWTracer: Cleanup, is owner ? (%d)\n", |
|---|
| 895 | 1051 | tracer->owner); |
|---|
| 896 | | - |
|---|
| 1052 | + mlx5_eq_notifier_unregister(tracer->dev, &tracer->nb); |
|---|
| 897 | 1053 | cancel_work_sync(&tracer->ownership_change_work); |
|---|
| 898 | 1054 | cancel_work_sync(&tracer->handle_traces_work); |
|---|
| 899 | 1055 | |
|---|
| .. | .. |
|---|
| 915 | 1071 | cancel_work_sync(&tracer->read_fw_strings_work); |
|---|
| 916 | 1072 | mlx5_fw_tracer_clean_ready_list(tracer); |
|---|
| 917 | 1073 | mlx5_fw_tracer_clean_print_hash(tracer); |
|---|
| 1074 | + mlx5_fw_tracer_clean_saved_traces_array(tracer); |
|---|
| 918 | 1075 | mlx5_fw_tracer_free_strings_db(tracer); |
|---|
| 919 | 1076 | mlx5_fw_tracer_destroy_log_buf(tracer); |
|---|
| 920 | 1077 | flush_workqueue(tracer->work_queue); |
|---|
| .. | .. |
|---|
| 922 | 1079 | kvfree(tracer); |
|---|
| 923 | 1080 | } |
|---|
| 924 | 1081 | |
|---|
| 925 | | -void mlx5_fw_tracer_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe) |
|---|
| 1082 | +static int mlx5_fw_tracer_recreate_strings_db(struct mlx5_fw_tracer *tracer) |
|---|
| 926 | 1083 | { |
|---|
| 927 | | - struct mlx5_fw_tracer *tracer = dev->tracer; |
|---|
| 1084 | + struct mlx5_core_dev *dev; |
|---|
| 1085 | + int err; |
|---|
| 928 | 1086 | |
|---|
| 929 | | - if (!tracer) |
|---|
| 930 | | - return; |
|---|
| 1087 | + cancel_work_sync(&tracer->read_fw_strings_work); |
|---|
| 1088 | + mlx5_fw_tracer_clean_ready_list(tracer); |
|---|
| 1089 | + mlx5_fw_tracer_clean_print_hash(tracer); |
|---|
| 1090 | + mlx5_fw_tracer_clean_saved_traces_array(tracer); |
|---|
| 1091 | + mlx5_fw_tracer_free_strings_db(tracer); |
|---|
| 1092 | + |
|---|
| 1093 | + dev = tracer->dev; |
|---|
| 1094 | + err = mlx5_query_mtrc_caps(tracer); |
|---|
| 1095 | + if (err) { |
|---|
| 1096 | + mlx5_core_dbg(dev, "FWTracer: Failed to query capabilities %d\n", err); |
|---|
| 1097 | + return err; |
|---|
| 1098 | + } |
|---|
| 1099 | + |
|---|
| 1100 | + err = mlx5_fw_tracer_allocate_strings_db(tracer); |
|---|
| 1101 | + if (err) { |
|---|
| 1102 | + mlx5_core_warn(dev, "FWTracer: Allocate strings DB failed %d\n", err); |
|---|
| 1103 | + return err; |
|---|
| 1104 | + } |
|---|
| 1105 | + mlx5_fw_tracer_init_saved_traces_array(tracer); |
|---|
| 1106 | + |
|---|
| 1107 | + return 0; |
|---|
| 1108 | +} |
|---|
| 1109 | + |
|---|
| 1110 | +int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer) |
|---|
| 1111 | +{ |
|---|
| 1112 | + struct mlx5_core_dev *dev; |
|---|
| 1113 | + int err; |
|---|
| 1114 | + |
|---|
| 1115 | + if (IS_ERR_OR_NULL(tracer)) |
|---|
| 1116 | + return -EINVAL; |
|---|
| 1117 | + |
|---|
| 1118 | + dev = tracer->dev; |
|---|
| 1119 | + mlx5_fw_tracer_cleanup(tracer); |
|---|
| 1120 | + err = mlx5_fw_tracer_recreate_strings_db(tracer); |
|---|
| 1121 | + if (err) { |
|---|
| 1122 | + mlx5_core_warn(dev, "Failed to recreate FW tracer strings DB\n"); |
|---|
| 1123 | + return err; |
|---|
| 1124 | + } |
|---|
| 1125 | + err = mlx5_fw_tracer_init(tracer); |
|---|
| 1126 | + if (err) { |
|---|
| 1127 | + mlx5_core_warn(dev, "Failed to re-initialize FW tracer\n"); |
|---|
| 1128 | + return err; |
|---|
| 1129 | + } |
|---|
| 1130 | + |
|---|
| 1131 | + return 0; |
|---|
| 1132 | +} |
|---|
| 1133 | + |
|---|
| 1134 | +static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data) |
|---|
| 1135 | +{ |
|---|
| 1136 | + struct mlx5_fw_tracer *tracer = mlx5_nb_cof(nb, struct mlx5_fw_tracer, nb); |
|---|
| 1137 | + struct mlx5_core_dev *dev = tracer->dev; |
|---|
| 1138 | + struct mlx5_eqe *eqe = data; |
|---|
| 931 | 1139 | |
|---|
| 932 | 1140 | switch (eqe->sub_type) { |
|---|
| 933 | 1141 | case MLX5_TRACER_SUBTYPE_OWNERSHIP_CHANGE: |
|---|
| .. | .. |
|---|
| 935 | 1143 | queue_work(tracer->work_queue, &tracer->ownership_change_work); |
|---|
| 936 | 1144 | break; |
|---|
| 937 | 1145 | case MLX5_TRACER_SUBTYPE_TRACES_AVAILABLE: |
|---|
| 938 | | - if (likely(tracer->str_db.loaded)) |
|---|
| 939 | | - queue_work(tracer->work_queue, &tracer->handle_traces_work); |
|---|
| 1146 | + queue_work(tracer->work_queue, &tracer->handle_traces_work); |
|---|
| 940 | 1147 | break; |
|---|
| 941 | 1148 | default: |
|---|
| 942 | 1149 | mlx5_core_dbg(dev, "FWTracer: Event with unrecognized subtype: sub_type %d\n", |
|---|
| 943 | 1150 | eqe->sub_type); |
|---|
| 944 | 1151 | } |
|---|
| 1152 | + |
|---|
| 1153 | + return NOTIFY_OK; |
|---|
| 945 | 1154 | } |
|---|
| 946 | 1155 | |
|---|
| 947 | 1156 | EXPORT_TRACEPOINT_SYMBOL(mlx5_fw); |
|---|