Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  rsc_dump.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2019 Mellanox Technologies. */

#include "rsc_dump.h"
#include "lib/mlx5.h"

#define MLX5_SGMT_TYPE(SGMT) MLX5_SGMT_TYPE_##SGMT
#define MLX5_SGMT_STR_ASSING(SGMT)[MLX5_SGMT_TYPE(SGMT)] = #SGMT
static const char *const mlx5_rsc_sgmt_name[] = {
 MLX5_SGMT_STR_ASSING(HW_CQPC),
 MLX5_SGMT_STR_ASSING(HW_SQPC),
 MLX5_SGMT_STR_ASSING(HW_RQPC),
 MLX5_SGMT_STR_ASSING(FULL_SRQC),
 MLX5_SGMT_STR_ASSING(FULL_CQC),
 MLX5_SGMT_STR_ASSING(FULL_EQC),
 MLX5_SGMT_STR_ASSING(FULL_QPC),
 MLX5_SGMT_STR_ASSING(SND_BUFF),
 MLX5_SGMT_STR_ASSING(RCV_BUFF),
 MLX5_SGMT_STR_ASSING(SRQ_BUFF),
 MLX5_SGMT_STR_ASSING(CQ_BUFF),
 MLX5_SGMT_STR_ASSING(EQ_BUFF),
 MLX5_SGMT_STR_ASSING(SX_SLICE),
 MLX5_SGMT_STR_ASSING(SX_SLICE_ALL),
 MLX5_SGMT_STR_ASSING(RDB),
 MLX5_SGMT_STR_ASSING(RX_SLICE_ALL),
 MLX5_SGMT_STR_ASSING(PRM_QUERY_QP),
 MLX5_SGMT_STR_ASSING(PRM_QUERY_CQ),
 MLX5_SGMT_STR_ASSING(PRM_QUERY_MKEY),
};

struct mlx5_rsc_dump {
 u32 pdn;
 u32 mkey;
 u32 number_of_menu_items;
 u16 fw_segment_type[MLX5_SGMT_TYPE_NUM];
};

struct mlx5_rsc_dump_cmd {
 u64 mem_size;
 u8 cmd[MLX5_ST_SZ_BYTES(resource_dump)];
};

static int mlx5_rsc_dump_sgmt_get_by_name(char *name)
{
 int i;

 for (i = 0; i < ARRAY_SIZE(mlx5_rsc_sgmt_name); i++)
  if (!strcmp(name, mlx5_rsc_sgmt_name[i]))
   return i;

 return -EINVAL;
}

#define MLX5_RSC_DUMP_MENU_HEADER_SIZE (MLX5_ST_SZ_BYTES(resource_dump_info_segment) + \
     MLX5_ST_SZ_BYTES(resource_dump_command_segment) + \
     MLX5_ST_SZ_BYTES(resource_dump_menu_segment))

static int mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page,
     int read_size, int start_idx)
{
 void *data = page_address(page);
 enum mlx5_sgmt_type sgmt_idx;
 int num_of_items;
 char *sgmt_name;
 void *member;
 int size = 0;
 void *menu;
 int i;

 if (!start_idx) {
  menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu);
  rsc_dump->number_of_menu_items = MLX5_GET(resource_dump_menu_segment, menu,
         num_of_records);
  size = MLX5_RSC_DUMP_MENU_HEADER_SIZE;
  data += size;
 }
 num_of_items = rsc_dump->number_of_menu_items;

 for (i = 0; start_idx + i < num_of_items; i++) {
  size += MLX5_ST_SZ_BYTES(resource_dump_menu_record);
  if (size >= read_size)
   return start_idx + i;

  member = data + MLX5_ST_SZ_BYTES(resource_dump_menu_record) * i;
  sgmt_name =  MLX5_ADDR_OF(resource_dump_menu_record, member, segment_name);
  sgmt_idx = mlx5_rsc_dump_sgmt_get_by_name(sgmt_name);
  if (sgmt_idx == -EINVAL)
   continue;
  rsc_dump->fw_segment_type[sgmt_idx] = MLX5_GET(resource_dump_menu_record,
              member, segment_type);
 }
 return 0;
}

static int mlx5_rsc_dump_trigger(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd,
     struct page *page)
{
 struct mlx5_rsc_dump *rsc_dump = dev->rsc_dump;
 struct device *ddev = mlx5_core_dma_dev(dev);
 u32 out_seq_num;
 u32 in_seq_num;
 dma_addr_t dma;
 int err;

 dma = dma_map_page(ddev, page, 0, cmd->mem_size, DMA_FROM_DEVICE);
 if (unlikely(dma_mapping_error(ddev, dma)))
  return -ENOMEM;

 in_seq_num = MLX5_GET(resource_dump, cmd->cmd, seq_num);
 MLX5_SET(resource_dump, cmd->cmd, mkey, rsc_dump->mkey);
 MLX5_SET64(resource_dump, cmd->cmd, address, dma);

 err = mlx5_core_access_reg(dev, cmd->cmd, sizeof(cmd->cmd), cmd->cmd,
       sizeof(cmd->cmd), MLX5_REG_RESOURCE_DUMP, 0, 1);
 if (err) {
  mlx5_core_err(dev, "Resource dump: Failed to access err %d\n", err);
  goto out;
 }
 out_seq_num = MLX5_GET(resource_dump, cmd->cmd, seq_num);
 if (out_seq_num && (in_seq_num + 1 != out_seq_num))
  err = -EIO;
out:
 dma_unmap_page(ddev, dma, cmd->mem_size, DMA_FROM_DEVICE);
 return err;
}

struct mlx5_rsc_dump_cmd *mlx5_rsc_dump_cmd_create(struct mlx5_core_dev *dev,
         struct mlx5_rsc_key *key)
{
 struct mlx5_rsc_dump_cmd *cmd;
 int sgmt_type;

 if (IS_ERR_OR_NULL(dev->rsc_dump))
  return ERR_PTR(-EOPNOTSUPP);

 sgmt_type = dev->rsc_dump->fw_segment_type[key->rsc];
 if (!sgmt_type && key->rsc != MLX5_SGMT_TYPE_MENU)
  return ERR_PTR(-EOPNOTSUPP);

 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 if (!cmd) {
  mlx5_core_err(dev, "Resource dump: Failed to allocate command\n");
  return ERR_PTR(-ENOMEM);
 }
 MLX5_SET(resource_dump, cmd->cmd, segment_type, sgmt_type);
 MLX5_SET(resource_dump, cmd->cmd, index1, key->index1);
 MLX5_SET(resource_dump, cmd->cmd, index2, key->index2);
 MLX5_SET(resource_dump, cmd->cmd, num_of_obj1, key->num_of_obj1);
 MLX5_SET(resource_dump, cmd->cmd, num_of_obj2, key->num_of_obj2);
 MLX5_SET(resource_dump, cmd->cmd, size, key->size);
 cmd->mem_size = key->size;
 return cmd;
}
EXPORT_SYMBOL(mlx5_rsc_dump_cmd_create);

void mlx5_rsc_dump_cmd_destroy(struct mlx5_rsc_dump_cmd *cmd)
{
 kfree(cmd);
}
EXPORT_SYMBOL(mlx5_rsc_dump_cmd_destroy);

int mlx5_rsc_dump_next(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd,
         struct page *page, int *size)
{
 bool more_dump;
 int err;

 if (IS_ERR_OR_NULL(dev->rsc_dump))
  return -EOPNOTSUPP;

 err = mlx5_rsc_dump_trigger(dev, cmd, page);
 if (err) {
  mlx5_core_err(dev, "Resource dump: Failed to trigger dump, %d\n", err);
  return err;
 }
 *size = MLX5_GET(resource_dump, cmd->cmd, size);
 more_dump = MLX5_GET(resource_dump, cmd->cmd, more_dump);

 return more_dump;
}
EXPORT_SYMBOL(mlx5_rsc_dump_next);

#define MLX5_RSC_DUMP_MENU_SEGMENT 0xffff
static int mlx5_rsc_dump_menu(struct mlx5_core_dev *dev)
{
 struct mlx5_rsc_dump_cmd *cmd = NULL;
 struct mlx5_rsc_key key = {};
 struct page *page;
 int start_idx = 0;
 int size;
 int err;

 page = alloc_page(GFP_KERNEL);
 if (!page)
  return -ENOMEM;

 key.rsc = MLX5_SGMT_TYPE_MENU;
 key.size = PAGE_SIZE;
 cmd  = mlx5_rsc_dump_cmd_create(dev, &key);
 if (IS_ERR(cmd)) {
  err = PTR_ERR(cmd);
  goto free_page;
 }
 MLX5_SET(resource_dump, cmd->cmd, segment_type, MLX5_RSC_DUMP_MENU_SEGMENT);

 do {
  err = mlx5_rsc_dump_next(dev, cmd, page, &size);
  if (err < 0)
   goto destroy_cmd;

  start_idx = mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page, size, start_idx);

 } while (err > 0);

destroy_cmd:
 mlx5_rsc_dump_cmd_destroy(cmd);
free_page:
 __free_page(page);

 return err;
}

static int mlx5_rsc_dump_create_mkey(struct mlx5_core_dev *mdev, u32 pdn,
         u32 *mkey)
{
 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
 void *mkc;
 u32 *in;
 int err;

 in = kvzalloc(inlen, GFP_KERNEL);
 if (!in)
  return -ENOMEM;

 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
 MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA);
 MLX5_SET(mkc, mkc, lw, 1);
 MLX5_SET(mkc, mkc, lr, 1);

 MLX5_SET(mkc, mkc, pd, pdn);
 MLX5_SET(mkc, mkc, length64, 1);
 MLX5_SET(mkc, mkc, qpn, 0xffffff);

 err = mlx5_core_create_mkey(mdev, mkey, in, inlen);

 kvfree(in);
 return err;
}

struct mlx5_rsc_dump *mlx5_rsc_dump_create(struct mlx5_core_dev *dev)
{
 struct mlx5_rsc_dump *rsc_dump;

 if (!MLX5_CAP_DEBUG(dev, resource_dump)) {
  mlx5_core_dbg(dev, "Resource dump: capability not present\n");
  return NULL;
 }
 rsc_dump = kzalloc(sizeof(*rsc_dump), GFP_KERNEL);
 if (!rsc_dump)
  return ERR_PTR(-ENOMEM);

 return rsc_dump;
}

void mlx5_rsc_dump_destroy(struct mlx5_core_dev *dev)
{
 if (IS_ERR_OR_NULL(dev->rsc_dump))
  return;
 kfree(dev->rsc_dump);
}

int mlx5_rsc_dump_init(struct mlx5_core_dev *dev)
{
 struct mlx5_rsc_dump *rsc_dump = dev->rsc_dump;
 int err;

 if (IS_ERR_OR_NULL(dev->rsc_dump))
  return 0;

 err = mlx5_core_alloc_pd(dev, &rsc_dump->pdn);
 if (err) {
  mlx5_core_warn(dev, "Resource dump: Failed to allocate PD %d\n", err);
  return err;
 }
 err = mlx5_rsc_dump_create_mkey(dev, rsc_dump->pdn, &rsc_dump->mkey);
 if (err) {
  mlx5_core_err(dev, "Resource dump: Failed to create mkey, %d\n", err);
  goto free_pd;
 }
 err = mlx5_rsc_dump_menu(dev);
 if (err) {
  mlx5_core_err(dev, "Resource dump: Failed to read menu, %d\n", err);
  goto destroy_mkey;
 }
 return err;

destroy_mkey:
 mlx5_core_destroy_mkey(dev, rsc_dump->mkey);
free_pd:
 mlx5_core_dealloc_pd(dev, rsc_dump->pdn);
 return err;
}

void mlx5_rsc_dump_cleanup(struct mlx5_core_dev *dev)
{
 if (IS_ERR_OR_NULL(dev->rsc_dump))
  return;

 mlx5_core_destroy_mkey(dev, dev->rsc_dump->mkey);
 mlx5_core_dealloc_pd(dev, dev->rsc_dump->pdn);
}

Messung V0.5
C=98 H=93 G=95

¤ Dauer der Verarbeitung: 0.13 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge