Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /* Copyright (c) 2019 Mellanox Technologies */
0003 
0004 #include <linux/mlx5/driver.h>
0005 #include "mlx5_core.h"
0006 #include "lib/pci_vsc.h"
0007 #include "lib/mlx5.h"
0008 
0009 #define BAD_ACCESS          0xBADACCE5
0010 #define MLX5_PROTECTED_CR_SCAN_CRSPACE  0x7
0011 
0012 static bool mlx5_crdump_enabled(struct mlx5_core_dev *dev)
0013 {
0014     return !!dev->priv.health.crdump_size;
0015 }
0016 
0017 static int mlx5_crdump_fill(struct mlx5_core_dev *dev, u32 *cr_data)
0018 {
0019     u32 crdump_size = dev->priv.health.crdump_size;
0020     int i, ret;
0021 
0022     for (i = 0; i < (crdump_size / 4); i++)
0023         cr_data[i] = BAD_ACCESS;
0024 
0025     ret = mlx5_vsc_gw_read_block_fast(dev, cr_data, crdump_size);
0026     if (ret <= 0) {
0027         if (ret == 0)
0028             return -EIO;
0029         return ret;
0030     }
0031 
0032     if (crdump_size != ret) {
0033         mlx5_core_warn(dev, "failed to read full dump, read %d out of %u\n",
0034                    ret, crdump_size);
0035         return -EINVAL;
0036     }
0037 
0038     return 0;
0039 }
0040 
0041 int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data)
0042 {
0043     int ret;
0044 
0045     if (!mlx5_crdump_enabled(dev))
0046         return -ENODEV;
0047 
0048     ret = mlx5_vsc_gw_lock(dev);
0049     if (ret) {
0050         mlx5_core_warn(dev, "crdump: failed to lock vsc gw err %d\n",
0051                    ret);
0052         return ret;
0053     }
0054     /* Verify no other PF is running cr-dump or sw reset */
0055     ret = mlx5_vsc_sem_set_space(dev, MLX5_SEMAPHORE_SW_RESET,
0056                      MLX5_VSC_LOCK);
0057     if (ret) {
0058         mlx5_core_warn(dev, "Failed to lock SW reset semaphore\n");
0059         goto unlock_gw;
0060     }
0061 
0062     ret = mlx5_vsc_gw_set_space(dev, MLX5_VSC_SPACE_SCAN_CRSPACE, NULL);
0063     if (ret)
0064         goto unlock_sem;
0065 
0066     ret = mlx5_crdump_fill(dev, cr_data);
0067 
0068 unlock_sem:
0069     mlx5_vsc_sem_set_space(dev, MLX5_SEMAPHORE_SW_RESET, MLX5_VSC_UNLOCK);
0070 unlock_gw:
0071     mlx5_vsc_gw_unlock(dev);
0072     return ret;
0073 }
0074 
0075 int mlx5_crdump_enable(struct mlx5_core_dev *dev)
0076 {
0077     struct mlx5_priv *priv = &dev->priv;
0078     u32 space_size;
0079     int ret;
0080 
0081     if (!mlx5_core_is_pf(dev) || !mlx5_vsc_accessible(dev) ||
0082         mlx5_crdump_enabled(dev))
0083         return 0;
0084 
0085     ret = mlx5_vsc_gw_lock(dev);
0086     if (ret)
0087         return ret;
0088 
0089     /* Check if space is supported and get space size */
0090     ret = mlx5_vsc_gw_set_space(dev, MLX5_VSC_SPACE_SCAN_CRSPACE,
0091                     &space_size);
0092     if (ret) {
0093         /* Unlock and mask error since space is not supported */
0094         mlx5_vsc_gw_unlock(dev);
0095         return 0;
0096     }
0097 
0098     if (!space_size) {
0099         mlx5_core_warn(dev, "Invalid Crspace size, zero\n");
0100         mlx5_vsc_gw_unlock(dev);
0101         return -EINVAL;
0102     }
0103 
0104     ret = mlx5_vsc_gw_unlock(dev);
0105     if (ret)
0106         return ret;
0107 
0108     priv->health.crdump_size = space_size;
0109     return 0;
0110 }
0111 
0112 void mlx5_crdump_disable(struct mlx5_core_dev *dev)
0113 {
0114     dev->priv.health.crdump_size = 0;
0115 }