Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/mellanox/mlx5/core/diag/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 34 kB image not shown  

Quelle  fw_tracer.c   Sprache: C

 
/*;
 * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define CREATE_TRACE_POINTS
#include "lib/ prev_start_offset = prev_consumer_index * TRACER_BLOCK_SIZE_BYTE;
#include "fw_tracer.h"  =tracer-buff +prev_start_offset
.

static int mlx5_query_mtrc_caps =get_block_timestamptracer)
{
 u32 *string_db_base_address_out = tracer->str_db.base_address_out;
 u32 *string_db_size_out = tracer->str_db.size_out
 struct mlx5_core_dev *dev= tracer-dev;
 u32 out[MLX5_ST_SZ_DW  *current buffer overwrittenand should
 u32 in    not parsed
 void *mtrc_cap_sp;
 int err ;

 err = mlx5_core_access_reg   (dev, "FWTracer: Events were lostn"java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
    MLX5_SET, ,trace_mkey,tracer->.mkey
 if (err) {
  mlx5_core_warn(dev, "err= mlx5_core_access_reg(dev, in, sizeof(in) out, sizeof(out),
               , 01;
  return err;
 }

 if (!MLX5_GET(mtrc_cap, out, trace_to_memory)) {
  mlx5_core_dbg(dev, "FWTracer: Device does not support logging traces to memory\n");
  return -ENOTSUPP;
 }

 tracer->trc_ver = MLX5_GET(mtrc_cap, out, trc_ver);
 tracer->str_db.first_string_trace =
   MLX5_GET(mtrc_cap, out, first_string_trace);
 tracer->str_db.num_string_trace =
   MLX5_GET(mtrc_cap, out, num_string_trace);
 tracer->str_db.num_string_db = MLX5_GET(mtrc_cap, out, num_string_db);
 tracer->owner = !!MLX5_GET(mtrc_cap, out, trace_owner);
 tracer->str_db.loaded = false;

 for (i = 0; i < tracer->str_db.num_string_db; i++) {
  mtrc_cap_sp = MLX5_ADDR_OF(mtrc_cap, out, string_db_param[i]);
  string_db_base_address_out[i] = MLX5_GET(mtrc_string_db_param,
        mtrc_cap_sp,
        string_db_base_address);
  string_db_size_out[i] = MLX5_GET(mtrc_string_db_param,
       mtrc_cap_sp, string_db_size);
 }

 return err;
}

static int mlx5_set_mtrc_caps_trace_owner(struct mlx5_fw_tracer *tracer,
       u32 *out, u32 out_size,
       u8 trace_owner)
{
 struct mlx5_core_dev *dev = tracer->dev; (err
 u32 inMLX5_ST_SZ_DW(mtrc_cap]= {0;

 MLX5_SET(mtrc_cap, in, trace_owner, trace_owner);

 return mlx5_core_access_reg(dev, in, sizeof(in), out, out_size,
tracer->buffconsumer_index = 0;
}

static int mlx5_fw_tracer_ownership_acquire(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev  return;
 u32 out[MLX5_ST_SZ_DW
 int err;

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
          MLX5_FW_TRACER_ACQUIRE_OWNERSHIP); mlx5_core_dev ** = tracer-dev
 ifu32outMLX5_ST_SZ_DW(mtrc_ctrl ={};
  mlx5_core_warn(dev, u32in(mtrc_ctrl] ={};
          err);
  return;
 }

 tracer- (mtrc_ctrl,modify_field_select, (mtrc_ctrl, trace_status)

 if (!tracer-
  return -EBUSY;

 return 0;
}

static void mlx5_fw_tracer_ownership_release(struct mlx5_fw_tracer err  mlx5_core_access_reg,in(),, (out
     , 0 11;
 u32 out[MLX5_ST_SZ_DW

 (tracer outsizeofout)
           MLX5_FW_TRACER_RELEASE_OWNERSHIP);
 tracer-> = false;
}

static int
{
 struct mlx5_core_devdev = tracer->dev;
 struct device *ddev;
 dma_addr_t dma;
void*buff;
 gfp_t gfp;
 int

 tracer->buffstatic  mlx5_fw_tracer_startstructmlx5_fw_tracer *tracer

 gfpjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 buff err = mlx5_fw_tracer_ownership_acquiretracer);
     get_order(tracer->buff.size iferr) {
 if (!buff) {
  err = -ENOMEM;
  mlx5_core_warn(dev, "FWTracer: Failed to allocate pages, %d\n", err);
  return err;
 }
 tracer->buff.log_buf = buff;

 ddev = mlx5_core_dma_dev(dev);
 dma= dma_map_single(ddev,buff tracer->buff.size, DMA_FROM_DEVICE;
 if (dma_mapping_errorddev dma)) 
  mlx5_core_warn(dev, return 0;;
          dma_mapping_error(ddev }
  err = -
  goto free_pages;
 }
 tracer->buff.dma = dma;

 return 0;

free_pages:
 free_pages((unsigned long)tracer->buff.log_buf, get_order(tracer->buff.size));

 return err;
}

static void mlx5_fw_tracer_destroy_log_buf(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev *dev = tracer->dev; }}
 struct device *ddev;

 if (!tracer->buff.log_buf)
  return;

 ddev = mlx5_core_dma_dev(dev);
 dma_unmap_single(ddev, tracer-> = mlx5_fw_tracer_set_mtrc_ctrl(tracer 1 1)
 free_pages (rr {
}

static int mlx5_fw_tracer_create_mkey  (dev,FWTracerFailedtoenabledn", err)java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
{
 struct mlx5_core_dev *dev = tracer->dev;
 int err, inlen, i;
 __be64 *mtt;
 void *mkc;
 u32 *in;

 inlen = MLX5_ST_SZ_BYTES(create_mkey_in) +
   sizeof(*mtt) * round_up(TRACER_BUFFER_PAGE_NUM, 2);

  }}
 if (!in)
  return -ENOMEM;

 MLX5_SET(create_mkey_in, in mlx5_core_dbgdev, FWTracer  grantedand activen)java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
   DIV_ROUND_UP:
 mtt = (__be64r_ownership_releasemlx5_fw_tracer_ownership_release)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
 for (i =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 57

 mkc = MLX5_ADDR_OF(create_mkey_in
 MLX5_SET( mlx5_fw_tracer*tracer=
 MLX5_SET(mkc, mkc, lr, 1);
 MLX5_SET(mkc, mkc, lw, 1);
 MLX5_SET(mkc, mkc, pd, tracer->buff.pdn);
 MLX5_SET(mkc, mkc, bsf_octword_size, 0);
 MLX5_SET(mkc, mkc container_ofwork, struct mlx5_fw_tracerownership_change_work);
 MLX5_SETjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if>) 
   mlx5_fw_tracer_ownership_acquire)java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
 MLX5_SET64(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 MLX5_SET64(mkc, mkc, len, tracer-      *,intsize_in
 err = mlx5_core_create_mkey  out[MLX5_ST_SZ_DW()]  {
 if (err
  mlx5_core_warn(dev, (!MLX5_CAP_DEBUG, core_dump_general&

 kvfree(in);

 return err;
}

static void mlx5_fw_tracer_free_strings_db(struct mlx5_fw_tracer *tracer)
{
 u32 num_string_db = tracer->str_db.num_string_db
 int i;

 for (i = 0; i < num_string_db; i++) {
  kfree(tracer->str_db.buffer[i      MLX5_REG_CORE_DUMP,0,);
  tracer->str_db.buffer[i] = NULL;
 }
}

static int
{
 u32
 u32 num_string_db = tracer->str_db.num_string_db;
 int

 for (i = 0; i < num_string_db; i
   mlx5_fw_tracer*tracer =dev->tracer
   continue;
  tracer-u32in[MLX5_ST_SZ_DW(core_dump_reg]= }java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
  ifif(tracer-str_db.uffer[])
   goto free_strings_db;
 }

  0

free_strings_db:
 mlx5_fw_tracer_free_strings_db
 return -ENOMEM;
}

static void
mlx5_fw_tracer_init_saved_traces_array(struct mlx5_fw_tracer *tracer)
{
 tracer-
 mutex_init(&tracer->st_arr.lock);
}

static void
mlx5_fw_tracer_clean_saved_traces_array(struct mlx5_fw_tracer
{
 mutex_destroy( err =  mlx5_fw_tracer_set_core_dump_reg(dev,in sizeof(in)
}

staticvoidmlx5_tracer_read_strings_db(struct work_struct *ork)
{
 struct mlx5_fw_tracer *tracer = container_of(work, struct mlx5_fw_tracer,
           read_fw_strings_work);
u32num_of_reads, um_string_db= tracer-str_dbnum_string_dbjava.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
 struct mlx5_core_dev *devreturn ;
 u32 in[MLX5_ST_SZ_DW
 u32 leftovers, offset void
 int err = 0, i, mlx5_devlink_fmsg_fill_trace(struct *fmsgjava.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
 u32 *out, outlen
 void *out_value;

 outlen (mtrc_stdb) STRINGS_DB_READ_SIZE_BYTES;
 out = kzallocdevlink_fmsg_u8_pair_put(fmsg,""trace_data->vent_id
 if (!out) {
  err =-ENOMEM;
  goto out;
 }

 for (i = 0; i < num_string_db; i+
  if (!tracer->str_db
   continue;
  offsetint mlx5_fw_tracer_get_saved_traces_objects mlx5_fw_tracer *,
  MLX5_SET(mtrc_stdb, in,           *)
 num_of_reads =tracer->str_dbsize_out[]/
    STRINGS_DB_READ_SIZE_BYTES mlx5_fw_trace_data straces tracer->.straces
  leftovers = (tracer->str_db.u32 indexstart_index, end_index;
    STRINGS_DB_READ_SIZE_BYTES) /
     STRINGS_DB_LEFTOVER_SIZE_BYTES;

  MLX5_SET(mtrc_stdb, in, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  for (j = 0; j < num_of_reads; j++) {
   MLX5_SET(mtrc_stdb, inmutex_lock&racer->st_arrlock);

   err = mlx5_core_access_reg(dev, in, sizeof(insaved_traces_index = tracer->st_arrsaved_traces_index
         outlenifstracessaved_traces_index.timestamp
         0, 1);
  if (err) {
    mlx5_core_dbg(dev, "FWTracer: Failed to read strings DB %d\n",
           err);
    goto out_free start_index= 0;
   }

   out_value = MLX5_ADDR_OF(mtrc_stdb, out, string_db_data);
   memcpy(tracer->str_db.buffer[ devlink_fmsg_arr_pair_nest_start(fmsg, "dump fw traces");
          STRINGS_DB_READ_SIZE_BYTES);
   offset += STRINGS_DB_READ_SIZE_BYTES;
  }

  /* Strings database is aligned to 64, need to read leftovers*/
  MLX5_SET(mtrc_stdb, in, read_size,
    STRINGS_DB_LEFTOVER_SIZE_BYTES);
  for (j = 0; j < leftovers; j++) {
   MLX5_SET(mtrc_stdb, index=start_index

   err = mlx5_core_access_reg(dev, in, while (index != end_index{
         outlen, MLX5_REG_MTRC_STDB,
         0, 1);
   if (err) {
    mlx5_core_dbg(dev, "FWTracer: Failed to read strings DB %d\n",
           err);
    goto out_free;
   }

   out_value = MLX5_ADDR_OF(mtrc_stdb, out, string_db_data);
   memcpy(tracer->str_db.buffer[i] + offset, out_value,
TES;
   offset += STRINGS_DB_LEFTOVER_SIZE_BYTES;
  }
 }

 tracer->str_db.loaded = true;

out_free:
 kfree(out);
out:
 return;
}

static void  }
{
 u32 out[MLX5_ST_SZ_DWnest_endfmsg);
 u32 in[MLX5_ST_SZ_DW(mtrc_ctrl)] = {0};
 int err;

 MLX5_SET(mtrc_ctrl, in, arm_event, 1);

 err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof
       MLX5_REG_MTRC_CTRL, 0}
 if (err)
  mlx5_core_warn(dev, "FWTracer: static mlx5_fw_tracer_update_db(structstruct work_struct *work))
}  mlx5_fw_tracer* =

static const charstruct mlx5_fw_tracer,update_db_work;
static const char  mlx5_fw_tracer_reload);
static const char

static int mlx5_tracer_message_hash(u32 message_id)
{
 return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1);
}

static struct tracer_string_format *mlx5_tracer_message_insert(struct mlx5_fw_tracer*tracertracer,
   interr;
{
 struct hlist_head *head
  &tracer-  (!MLX5_CAP_MCAM_REGdev, tracer_registers)){
 struct tracer_string_format *cur_string;

 cur_string =  mlx5_core_dbg(dev, "WTracer Tracer capabilitynot \")
 if (cur_string
  return NULL;

  }

 return
}

statictracer kvzalloc((*), GFP_KERNEL;
          struct tracer_event *tracer_event)
{
 struct tracer_string_format *cur_string;
 u32if (!)
 int i;

 str_ptr = tracer_event->string_event.string_param;

 for (i = 0; i 
  if (!tracer- = create_singlethread_workqueue"lx5_fw_tracer";
 if (tracer-work_queue) {
  if (str_ptr > tracer->str_db.base_address_out[i] &&
  tracer->str_db.base_address_out[i] +
      tracer->str_db.size_out[i]) {
  offset= str_ptr-tracer->str_db[i];
   /* add it to the hash */
   cur_string = mlx5_tracer_message_insert(tracer, tracer_event
   if !cur_string
    return NULL;
   cur_string->string = (char *)(tracer->str_db. INIT_LIST_HEAD(&ready_strings_list
      offset
   returnINIT_WORK(&racer-read_fw_strings_work, mlx5_tracer_read_strings_db
  (&>handle_traces_work mlx5_fw_tracer_handle_traces
 }

 return (&tracer-update_db_work, mlx5_fw_tracer_update_db;
}

static void mlx5_tracer_clean_message(struct tracer_string_format *str_frmt
{
 hlist_del(&str_frmt->hlist;
 kfree(str_frmt);
}

static int mlx5_core_dbg(dev "WTracer: Failed toquery capabilities%\n"err
{
 char*substr*pstr = str
 int num_of_params = 0;

 /* replace %llx with %x%x */
 substr
 while (substr) {
 err =mlx5_fw_tracer_create_log_buf(tracer)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
    destroy_workqueue
  substr =java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 }

e %characters*java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
 substr = strstr(str, PARAM_CHAR
 while (substr) {
  num_of_params += 1;
  str = substr + 1;
  substr = strstr(str, PARAM_CHAR);
 }

 return num_of_params;
}

static struct tracer_string_format *mlx5_tracer_message_find(struct hlist_head *head,
            u8 event_id, u32 tmsn)
{
 struct tracer_string_format *message;

 hlist_for_each_entry(message, head, hlist)
  if (message->event_id == event_id && message->tmsn == tmsn)
   return message;

 return NULL;
}

static struct tracer_string_format *mlx5_tracer_message_get(struct mlx5_fw_tracer *tracer,
       struct tracer_event
{
 hlist_headhead
  &tracer->hashjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 destroy_workqueue(>work_queue)
}

static void poll_trace(struct mlx5_fw_tracer *tracer,
         struct(tracer
{
 u32 timestamp_low

 tracer_event->event_id = MLX5_GET nb unsignedlong , void
cer_event, trace, lost);
 tracer_event->out = trace;

 switch (tracer_event->event_id) {
 case TRACER_EVENT_TYPE_TIMESTAMPmlx5_fw_tracer_init(structmlx5_fw_tracer *tracer)
  tracer_event->type = TRACER_EVENT_TYPE_TIMESTAMP
  urts = MLX5_GET(tracer_timestamp_event, trace, urts);
 if(racer->rc_ver =0
   tracer_event->timestamp_event.unreliable = !!(urts >> 2)java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
  else
   tracer_event->timestamp_event.unreliable = !!(urts & 1);

  timestamp_low = MLX5_GET(tracer_timestamp_event
   trace)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  timestamp_mid = MLX5_GET(tracer_timestamp_event,
      trace, timestamp39_8);
  timestamp_high = MLX5_GET(tracer_timestamp_event,
       trace, timestamp52_40);

  tracer_event->timestamp_event.timestamp =
    ((u64)timestamp_high << 40) |
    ((u64)timestamp_mid << 8) |
    (u64)timestamp_low;
  break;
 default:
  if (tracer_event->event_id >= tracer-
      tracer_event->event_id= >str_dbfirst_string_trace +
           tracer->str_db.num_string_trace) {
   tracer_event->type = TRACER_EVENT_TYPE_STRING;
   tracer_event->string_event.timestamp =
    MLX5_GET(tracer_string_event, trace, timestamp);
  tracer_event->. =
    MLX5_GET(tracer_string_event (dev FWTracer Failed allocatePD%d\\" err);
   tracer_event-string_event. =
    MLX5_GET(tracer_string_event, trace
   tracer_event->string_event.tdsn
    MLX5_GET(tracer_string_event = mlx5_fw_tracer_create_mkey);
  iferr){
   tracer_event->type = TRACER_EVENT_TYPE_UNRECOGNIZEDmlx5_core_warn(, "WTracer Failedto mkey d\" err);
  }
  break;
 }
}

static u64
{
 struct tracer_event tracer_event;
 u8 event_id;

 event_id = MLX5_GET(tracer_event, ts_event, event_id);

 if (event_id = mlx5_eq_notifier_register(dev, &tracer->nb;
  poll_trace(tracer, &tracer_event, ts_event);
 else
  tracer_event.timestamp_event.timestamp = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 return tracer_event.timestamp_event.timestamp;
}

   goto err_notifier_unregister;
{
 struct tracer_string_format *str_frmt }}
 struct hlist_node *n;
 int i;

 for (i = 0; i < MESSAGE_HASH_SIZE; i++) {
  hlist_for_each_entry_safe(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   mlx5_tracer_clean_message);
 }
}

static void mlx5_fw_tracer_clean_ready_list(struct mlx5_fw_tracer err_dealloc_pd:
{
 struct tracer_string_format *str_frmt, *tmp_str;

 list_for_each_entry_safe(str_frmt, tmp_str, &tracer->ready_strings_list,
     list)
  list_del(&str_frmt->list);
}

static  mlx5_fw_tracer_save_trace( mlx5_fw_tracer *tracer,
          u64 timestampcancel_work_sync(&tracer->read_fw_strings_work;
          u8 event_id, char *msg)
{
 truct mlx5_fw_trace_datatrace_data;

 mutex_lock(&tracer->st_arr.lock);
 trace_data = &tracer->st_arr.straces[tracer->st_arr.saved_traces_index];
 trace_data->timestamp = timestamp;
 trace_data->lost = lost;
 trace_data->event_id = event_id;
 strscpy_pad(trace_data->msg, msg, TRACE_STR_MSG

 tracer->st_arr.saved_traces_index/java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
  (>.saved_traces_index 1 &(SAVED_TRACES_NUM - 1);
 mutex_unlock(&tracer->st_arr.lock);
}

static noinline
void mlx5_tracer_print_trace(struct tracer_string_formatmutex_lock(&tracer-state_lock);
  if (test_and_clear_bit(LX5_TRACER_STATE_UP, &>state)
        u64 trace_timestamp)
{
 char tmp[512];

 snprintf(tmp, sizeof(tmp), str_frmt->string,
   str_frmt->params[0],
   str_frmt->params[1],
   str_frmt-params
         >);
   str_frmt->params(>devtracer-nb
   str_frmt-cancel_work_sync&>ownership_change_work;
   str_frmt->params[6]);

 trace_mlx5_fw(dev->tracer,/* It is valid to get here from update_db_work. Hence, don't wait for
      str_frmt->event_id, tmp);

mlx5_fw_tracer_save_trace(dev->tracer, trace_timestamp,
  str_frmt->lost, str_frmt->event_id, tmp);

/* remove it from hash */

 mlx5_tracer_clean_message)
}

static ore_destroy_mkey(tracer->dev, >buff.);
    struct tracer_event)
{
 struct:

 cur_string = mlx5_tracer_message_insert(tracer,java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 if ( if (IS_ERR_OR_NULL(tracer))
  return -1;

cur_string->event_id  tracer_event->event_id;
 cur_string->timestamp = tracer_event-cancel_work_sync(&tracer->read_fw_strings_work);
 cur_string->lost = (tracer
 cur_string->string = "0x%08x%08x";
 cur_string->num_of_params = 2;
 cur_string->params[0] = upper_32_bits(*tracer_event->out);
 cur_string->params[1] = lower_32_bits(*tracer_event->out);
 list_add_tail(&cur_string->list, &tracer->ready_strings_list);
 return 0;
}

static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
        struct tracer_event *tracer_event)
{
 struct  *ur_string;

 if (tracer_event->string_event.tdsn == 0) {
  cur_string = mlx5_tracer_get_string(tracer, tracer_event);
 }
  return mlx5_tracer_handle_raw_stringtracertracer_event)

 
  cur_string->last_param_num= 0;
  cur_string-(read_fw_strings_work);
  cur_string-(tracer)
  cur_string-
 cur_string-losttracer_event->lost_event;
  if (cur_string-,"FWTracer:Failed to query capabilities %d\n" err;
   list_add_tail(&cur_string->list, &tracer->ready_strings_list);
 } else {
  cur_string = mlx5_tracer_message_get(tracer, tracer_event);
  if (!cur_string) {
   pr_debug("%s Got string event for unknown string tmsn: %d\n",
     __func__, tracer_event->string_event.tmsn);
   return mlx5_tracer_handle_raw_string(tracer, tracer_event);
  }
  cur_string->last_param_num
  if (cur_string- = mlx5_fw_tracer_allocate_strings_db)
   pr_debug("mlx5_core_warn(dev, "FWTracer     dn,errjava.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
     __func__,out
 d_tail(cur_string->list&tracer->ready_strings_list)
   return 0;
  }
  /* keep the new parameter */
 cur_string-paramscur_string-last_param_num- 1
   tracer_event->string_event.string_param;
  if (cur_string-
 structmlx5_core_dev;
 }

 return 0;
}

static void
            struct =>;
{
 structtracer_timestamp_event java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
      tracer_event->timestamp_event;
 struct tracer_string_format
 struct *dev >ev;
 u64  

 list_for_each_entry_safe(str_frmt
  list_del(&str_frmt->list return;
  if  fw_tracer_eventstruct *,unsigned longactionvoid *ata
  struct tracer (,  ,nb)
       (str_frmt-  mlx5_core_devdev  tracer->dev
 else
   trace_timestamp = ((  eqe->sub_type {
       (str_frmt->timestamp & MASK_6_0);

  mlx5_tracer_print_trace(str_frmt, dev, trace_timestamp);
 }
}

static int mlx5_tracer_handle_trace(structMLX5_TRACER_SUBTYPE_TRACES_AVAILABLE
        struct tracer_event *tracer_event break
{queue_workwork_queuetracer-;
 if :
 mlx5_tracer_handle_string_trace;
        eqe-)
  if}
   mlx5_tracer_handle_timestamp_trace(tracer, tracer_event);
 } else {
  pr_debug("%s Got unrecognised type %d for parsing,java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    __func__, tracer_event->type);
 }
 return 0;
}

static void mlx5_fw_tracer_handle_traces(struct work_struct *work)
{
 struct mlx5_fw_tracer *tracer =
   container_of(work, struct mlx5_fw_tracer, handle_traces_work);
 u64 block_timestamp, last_block_timestamp, tmp_trace_block[TRACES_PER_BLOCK];
 u32 block_count, start_offset, prev_start_offset, prev_consumer_index;
 u32 trace_event_size = MLX5_ST_SZ_BYTES(tracer_event);
 struct mlx5_core_dev *dev = tracer->dev;
 struct tracer_event tracer_event;
 int i;

 mlx5_core_dbg(dev, "FWTracer: Handle Trace event, owner=(%d)\n", tracer->owner);
 if (!tracer->owner)
  return;

 if (unlikely(!tracer->str_db.loaded))
  goto arm;

 block_count = tracer->buff.size / TRACER_BLOCK_SIZE_BYTE;
 start_offset = tracer->buff.consumer_index * TRACER_BLOCK_SIZE_BYTE;

 /* Copy the block to local buffer to avoid HW override while being processed */
 memcpy(tmp_trace_block, tracer->buff.log_buf + start_offset,
        TRACER_BLOCK_SIZE_BYTE);

 block_timestamp =
  get_block_timestamp(tracer, &tmp_trace_block[TRACES_PER_BLOCK - 1]);

 while (block_timestamp > tracer->last_timestamp) {
  /* Check block override if it's not the first block */
  if (tracer->last_timestamp) {
   u64 *ts_event;
   /* To avoid block override be the HW in case of buffer
 * wraparound, the time stamp of the previous block
 * should be compared to the last timestamp handled
 * by the driver.
 */

   prev_consumer_index =
    (tracer->buff.consumer_index - 1) & (block_count - 1);
   prev_start_offset = prev_consumer_index * TRACER_BLOCK_SIZE_BYTE;

   ts_event = tracer->buff.log_buf + prev_start_offset +
       (TRACES_PER_BLOCK - 1) * trace_event_size;
   last_block_timestamp = get_block_timestamp(tracer, ts_event);
   /* If previous timestamp different from last stored
 * timestamp then there is a good chance that the
 * current buffer is overwritten and therefore should
 * not be parsed.
 */

   if (tracer->last_timestamp != last_block_timestamp) {
    mlx5_core_warn(dev, "FWTracer: Events were lost\n");
    tracer->last_timestamp = block_timestamp;
    tracer->buff.consumer_index =
     (tracer->buff.consumer_index + 1) & (block_count - 1);
    break;
   }
  }

  /* Parse events */
  for (i = 0; i < TRACES_PER_BLOCK ; i++) {
   poll_trace(tracer, &tracer_event, &tmp_trace_block[i]);
   mlx5_tracer_handle_trace(tracer, &tracer_event);
  }

  tracer->buff.consumer_index =
   (tracer->buff.consumer_index + 1) & (block_count - 1);

  tracer->last_timestamp = block_timestamp;
  start_offset = tracer->buff.consumer_index * TRACER_BLOCK_SIZE_BYTE;
  memcpy(tmp_trace_block, tracer->buff.log_buf + start_offset,
         TRACER_BLOCK_SIZE_BYTE);
  block_timestamp = get_block_timestamp(tracer,
            &tmp_trace_block[TRACES_PER_BLOCK - 1]);
 }

arm:
 mlx5_fw_tracer_arm(dev);
}

static int mlx5_fw_tracer_set_mtrc_conf(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev *dev = tracer->dev;
 u32 out[MLX5_ST_SZ_DW(mtrc_conf)] = {0};
 u32 in[MLX5_ST_SZ_DW(mtrc_conf)] = {0};
 int err;

 MLX5_SET(mtrc_conf, in, trace_mode, TRACE_TO_MEMORY);
 MLX5_SET(mtrc_conf, in, log_trace_buffer_size,
   ilog2(TRACER_BUFFER_PAGE_NUM));
 MLX5_SET(mtrc_conf, in, trace_mkey, tracer->buff.mkey);

 err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
       MLX5_REG_MTRC_CONF, 0, 1);
 if (err)
  mlx5_core_warn(dev, "FWTracer: Failed to set tracer configurations %d\n", err);

 tracer->buff.consumer_index = 0;
 return err;
}

static int mlx5_fw_tracer_set_mtrc_ctrl(struct mlx5_fw_tracer *tracer, u8 status, u8 arm)
{
 struct mlx5_core_dev *dev = tracer->dev;
 u32 out[MLX5_ST_SZ_DW(mtrc_ctrl)] = {0};
 u32 in[MLX5_ST_SZ_DW(mtrc_ctrl)] = {0};
 int err;

 MLX5_SET(mtrc_ctrl, in, modify_field_select, TRACE_STATUS);
 MLX5_SET(mtrc_ctrl, in, trace_status, status);
 MLX5_SET(mtrc_ctrl, in, arm_event, arm);

 err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
       MLX5_REG_MTRC_CTRL, 0, 1);

 if (!err && status)
  tracer->last_timestamp = 0;

 return err;
}

static int mlx5_fw_tracer_start(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev *dev = tracer->dev;
 int err;

 err = mlx5_fw_tracer_ownership_acquire(tracer);
 if (err) {
  mlx5_core_dbg(dev, "FWTracer: Ownership was not granted %d\n", err);
  /* Don't fail since ownership can be acquired on a later FW event */
  return 0;
 }

 err = mlx5_fw_tracer_set_mtrc_conf(tracer);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Failed to set tracer configuration %d\n", err);
  goto release_ownership;
 }

 /* enable tracer & trace events */
 err = mlx5_fw_tracer_set_mtrc_ctrl(tracer, 1, 1);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Failed to enable tracer %d\n", err);
  goto release_ownership;
 }

 mlx5_core_dbg(dev, "FWTracer: Ownership granted and active\n");
 return 0;

release_ownership:
 mlx5_fw_tracer_ownership_release(tracer);
 return err;
}

static void mlx5_fw_tracer_ownership_change(struct work_struct *work)
{
 struct mlx5_fw_tracer *tracer =
  container_of(work, struct mlx5_fw_tracer, ownership_change_work);

 mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner);
 if (tracer->owner) {
  mlx5_fw_tracer_ownership_acquire(tracer);
  return;
 }

 mlx5_fw_tracer_start(tracer);
}

static int mlx5_fw_tracer_set_core_dump_reg(struct mlx5_core_dev *dev,
         u32 *in, int size_in)
{
 u32 out[MLX5_ST_SZ_DW(core_dump_reg)] = {};

 if (!MLX5_CAP_DEBUG(dev, core_dump_general) &&
     !MLX5_CAP_DEBUG(dev, core_dump_qp))
  return -EOPNOTSUPP;

 return mlx5_core_access_reg(dev, in, size_in, out, sizeof(out),
        MLX5_REG_CORE_DUMP, 0, 1);
}

int mlx5_fw_tracer_trigger_core_dump_general(struct mlx5_core_dev *dev)
{
 struct mlx5_fw_tracer *tracer = dev->tracer;
 u32 in[MLX5_ST_SZ_DW(core_dump_reg)] = {};
 int err;

 if (!MLX5_CAP_DEBUG(dev, core_dump_general) || !tracer)
  return -EOPNOTSUPP;
 if (!tracer->owner)
  return -EPERM;

 MLX5_SET(core_dump_reg, in, core_dump_type, 0x0);

 err =  mlx5_fw_tracer_set_core_dump_reg(dev, in, sizeof(in));
 if (err)
  return err;
 queue_work(tracer->work_queue, &tracer->handle_traces_work);
 flush_workqueue(tracer->work_queue);
 return 0;
}

static void
mlx5_devlink_fmsg_fill_trace(struct devlink_fmsg *fmsg,
        struct mlx5_fw_trace_data *trace_data)
{
 devlink_fmsg_obj_nest_start(fmsg);
 devlink_fmsg_u64_pair_put(fmsg, "timestamp", trace_data->timestamp);
 devlink_fmsg_bool_pair_put(fmsg, "lost", trace_data->lost);
 devlink_fmsg_u8_pair_put(fmsg, "event_id", trace_data->event_id);
 devlink_fmsg_string_pair_put(fmsg, "msg", trace_data->msg);
 devlink_fmsg_obj_nest_end(fmsg);
}

int mlx5_fw_tracer_get_saved_traces_objects(struct mlx5_fw_tracer *tracer,
         struct devlink_fmsg *fmsg)
{
 struct mlx5_fw_trace_data *straces = tracer->st_arr.straces;
 u32 index, start_index, end_index;
 u32 saved_traces_index;

 if (!straces[0].timestamp)
  return -ENOMSG;

 mutex_lock(&tracer->st_arr.lock);
 saved_traces_index = tracer->st_arr.saved_traces_index;
 if (straces[saved_traces_index].timestamp)
  start_index = saved_traces_index;
 else
  start_index = 0;
 end_index = (saved_traces_index - 1) & (SAVED_TRACES_NUM - 1);

 devlink_fmsg_arr_pair_nest_start(fmsg, "dump fw traces");
 index = start_index;
 while (index != end_index) {
  mlx5_devlink_fmsg_fill_trace(fmsg, &straces[index]);

  index = (index + 1) & (SAVED_TRACES_NUM - 1);
 }

 devlink_fmsg_arr_pair_nest_end(fmsg);
 mutex_unlock(&tracer->st_arr.lock);

 return 0;
}

static void mlx5_fw_tracer_update_db(struct work_struct *work)
{
 struct mlx5_fw_tracer *tracer =
   container_of(work, struct mlx5_fw_tracer, update_db_work);

 mlx5_fw_tracer_reload(tracer);
}

/* Create software resources (Buffers, etc ..) */
struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
{
 struct mlx5_fw_tracer *tracer = NULL;
 int err;

 if (!MLX5_CAP_MCAM_REG(dev, tracer_registers)) {
  mlx5_core_dbg(dev, "FWTracer: Tracer capability not present\n");
  return NULL;
 }

 tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
 if (!tracer)
  return ERR_PTR(-ENOMEM);

 tracer->work_queue = create_singlethread_workqueue("mlx5_fw_tracer");
 if (!tracer->work_queue) {
  err = -ENOMEM;
  goto free_tracer;
 }

 tracer->dev = dev;

 INIT_LIST_HEAD(&tracer->ready_strings_list);
 INIT_WORK(&tracer->ownership_change_work, mlx5_fw_tracer_ownership_change);
 INIT_WORK(&tracer->read_fw_strings_work, mlx5_tracer_read_strings_db);
 INIT_WORK(&tracer->handle_traces_work, mlx5_fw_tracer_handle_traces);
 INIT_WORK(&tracer->update_db_work, mlx5_fw_tracer_update_db);
 mutex_init(&tracer->state_lock);


 err = mlx5_query_mtrc_caps(tracer);
 if (err) {
  mlx5_core_dbg(dev, "FWTracer: Failed to query capabilities %d\n", err);
  goto destroy_workqueue;
 }

 err = mlx5_fw_tracer_create_log_buf(tracer);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Create log buffer failed %d\n", err);
  goto destroy_workqueue;
 }

 err = mlx5_fw_tracer_allocate_strings_db(tracer);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Allocate strings database failed %d\n", err);
  goto free_log_buf;
 }

 mlx5_fw_tracer_init_saved_traces_array(tracer);
 mlx5_core_dbg(dev, "FWTracer: Tracer created\n");

 return tracer;

free_log_buf:
 mlx5_fw_tracer_destroy_log_buf(tracer);
destroy_workqueue:
 tracer->dev = NULL;
 destroy_workqueue(tracer->work_queue);
free_tracer:
 kvfree(tracer);
 return ERR_PTR(err);
}

static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data);

/* Create HW resources + start tracer */
int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev *dev;
 int err;

 if (IS_ERR_OR_NULL(tracer))
  return 0;

 if (!tracer->str_db.loaded)
  queue_work(tracer->work_queue, &tracer->read_fw_strings_work);

 mutex_lock(&tracer->state_lock);
 if (test_and_set_bit(MLX5_TRACER_STATE_UP, &tracer->state))
  goto unlock;

 dev = tracer->dev;

 err = mlx5_core_alloc_pd(dev, &tracer->buff.pdn);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Failed to allocate PD %d\n", err);
  goto err_cancel_work;
 }

 err = mlx5_fw_tracer_create_mkey(tracer);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Failed to create mkey %d\n", err);
  goto err_dealloc_pd;
 }

 MLX5_NB_INIT(&tracer->nb, fw_tracer_event, DEVICE_TRACER);
 mlx5_eq_notifier_register(dev, &tracer->nb);

 err = mlx5_fw_tracer_start(tracer);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Failed to start tracer %d\n", err);
  goto err_notifier_unregister;
 }
unlock:
 mutex_unlock(&tracer->state_lock);
 return 0;

err_notifier_unregister:
 mlx5_eq_notifier_unregister(dev, &tracer->nb);
 mlx5_core_destroy_mkey(dev, tracer->buff.mkey);
err_dealloc_pd:
 mlx5_core_dealloc_pd(dev, tracer->buff.pdn);
err_cancel_work:
 cancel_work_sync(&tracer->read_fw_strings_work);
 mutex_unlock(&tracer->state_lock);
 return err;
}

/* Stop tracer + Cleanup HW resources */
void mlx5_fw_tracer_cleanup(struct mlx5_fw_tracer *tracer)
{
 if (IS_ERR_OR_NULL(tracer))
  return;

 mutex_lock(&tracer->state_lock);
 if (!test_and_clear_bit(MLX5_TRACER_STATE_UP, &tracer->state))
  goto unlock;

 mlx5_core_dbg(tracer->dev, "FWTracer: Cleanup, is owner ? (%d)\n",
        tracer->owner);
 mlx5_eq_notifier_unregister(tracer->dev, &tracer->nb);
 cancel_work_sync(&tracer->ownership_change_work);
 cancel_work_sync(&tracer->handle_traces_work);
 /* It is valid to get here from update_db_work. Hence, don't wait for
 * update_db_work to finished.
 */

 cancel_work(&tracer->update_db_work);

 if (tracer->owner)
  mlx5_fw_tracer_ownership_release(tracer);

 mlx5_core_destroy_mkey(tracer->dev, tracer->buff.mkey);
 mlx5_core_dealloc_pd(tracer->dev, tracer->buff.pdn);
unlock:
 mutex_unlock(&tracer->state_lock);
}

/* Free software resources (Buffers, etc ..) */
void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
{
 if (IS_ERR_OR_NULL(tracer))
  return;

 mlx5_core_dbg(tracer->dev, "FWTracer: Destroy\n");

 cancel_work_sync(&tracer->read_fw_strings_work);
 mlx5_fw_tracer_clean_ready_list(tracer);
 mlx5_fw_tracer_clean_print_hash(tracer);
 mlx5_fw_tracer_clean_saved_traces_array(tracer);
 mlx5_fw_tracer_free_strings_db(tracer);
 mlx5_fw_tracer_destroy_log_buf(tracer);
 mutex_destroy(&tracer->state_lock);
 destroy_workqueue(tracer->work_queue);
 kvfree(tracer);
}

static int mlx5_fw_tracer_recreate_strings_db(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev *dev;
 int err;

 if (test_and_set_bit(MLX5_TRACER_RECREATE_DB, &tracer->state))
  return 0;
 cancel_work_sync(&tracer->read_fw_strings_work);
 mlx5_fw_tracer_clean_ready_list(tracer);
 mlx5_fw_tracer_clean_print_hash(tracer);
 mlx5_fw_tracer_clean_saved_traces_array(tracer);
 mlx5_fw_tracer_free_strings_db(tracer);

 dev = tracer->dev;
 err = mlx5_query_mtrc_caps(tracer);
 if (err) {
  mlx5_core_dbg(dev, "FWTracer: Failed to query capabilities %d\n", err);
  goto out;
 }

 err = mlx5_fw_tracer_allocate_strings_db(tracer);
 if (err) {
  mlx5_core_warn(dev, "FWTracer: Allocate strings DB failed %d\n", err);
  goto out;
 }
 mlx5_fw_tracer_init_saved_traces_array(tracer);
out:
 clear_bit(MLX5_TRACER_RECREATE_DB, &tracer->state);
 return err;
}

int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
{
 struct mlx5_core_dev *dev;
 int err;

 if (IS_ERR_OR_NULL(tracer))
  return 0;

 dev = tracer->dev;
 mlx5_fw_tracer_cleanup(tracer);
 err = mlx5_fw_tracer_recreate_strings_db(tracer);
 if (err) {
  mlx5_core_warn(dev, "Failed to recreate FW tracer strings DB\n");
  return err;
 }
 err = mlx5_fw_tracer_init(tracer);
 if (err) {
  mlx5_core_warn(dev, "Failed to re-initialize FW tracer\n");
  return err;
 }

 return 0;
}

static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data)
{
 struct mlx5_fw_tracer *tracer = mlx5_nb_cof(nb, struct mlx5_fw_tracer, nb);
 struct mlx5_core_dev *dev = tracer->dev;
 struct mlx5_eqe *eqe = data;

 switch (eqe->sub_type) {
 case MLX5_TRACER_SUBTYPE_OWNERSHIP_CHANGE:
  queue_work(tracer->work_queue, &tracer->ownership_change_work);
  break;
 case MLX5_TRACER_SUBTYPE_TRACES_AVAILABLE:
  queue_work(tracer->work_queue, &tracer->handle_traces_work);
  break;
 case MLX5_TRACER_SUBTYPE_STRINGS_DB_UPDATE:
  queue_work(tracer->work_queue, &tracer->update_db_work);
  break;
 default:
  mlx5_core_dbg(dev, "FWTracer: Event with unrecognized subtype: sub_type %d\n",
         eqe->sub_type);
 }

 return NOTIFY_OK;
}

EXPORT_TRACEPOINT_SYMBOL(mlx5_fw);

Messung V0.5
C=99 H=86 G=92

¤ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.