0001
0002
0003
0004 #include <linux/kernel.h>
0005 #include <net/devlink.h>
0006
0007 #include "nfpcore/nfp_cpp.h"
0008 #include "nfpcore/nfp_nffw.h"
0009 #include "nfp_abi.h"
0010 #include "nfp_app.h"
0011 #include "nfp_main.h"
0012
0013 static u32 nfp_shared_buf_pool_unit(struct nfp_pf *pf, unsigned int sb)
0014 {
0015 __le32 sb_id = cpu_to_le32(sb);
0016 unsigned int i;
0017
0018 for (i = 0; i < pf->num_shared_bufs; i++)
0019 if (pf->shared_bufs[i].id == sb_id)
0020 return le32_to_cpu(pf->shared_bufs[i].pool_size_unit);
0021
0022 WARN_ON_ONCE(1);
0023 return 0;
0024 }
0025
0026 int nfp_shared_buf_pool_get(struct nfp_pf *pf, unsigned int sb, u16 pool_index,
0027 struct devlink_sb_pool_info *pool_info)
0028 {
0029 struct nfp_shared_buf_pool_info_get get_data;
0030 struct nfp_shared_buf_pool_id id = {
0031 .shared_buf = cpu_to_le32(sb),
0032 .pool = cpu_to_le32(pool_index),
0033 };
0034 unsigned int unit_size;
0035 int n;
0036
0037 unit_size = nfp_shared_buf_pool_unit(pf, sb);
0038 if (!unit_size)
0039 return -EINVAL;
0040
0041 n = nfp_mbox_cmd(pf, NFP_MBOX_POOL_GET, &id, sizeof(id),
0042 &get_data, sizeof(get_data));
0043 if (n < 0)
0044 return n;
0045 if (n < sizeof(get_data))
0046 return -EIO;
0047
0048 pool_info->pool_type = le32_to_cpu(get_data.pool_type);
0049 pool_info->threshold_type = le32_to_cpu(get_data.threshold_type);
0050 pool_info->size = le32_to_cpu(get_data.size) * unit_size;
0051 pool_info->cell_size = unit_size;
0052
0053 return 0;
0054 }
0055
0056 int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb,
0057 u16 pool_index, u32 size,
0058 enum devlink_sb_threshold_type threshold_type)
0059 {
0060 struct nfp_shared_buf_pool_info_set set_data = {
0061 .id = {
0062 .shared_buf = cpu_to_le32(sb),
0063 .pool = cpu_to_le32(pool_index),
0064 },
0065 .threshold_type = cpu_to_le32(threshold_type),
0066 };
0067 unsigned int unit_size;
0068
0069 unit_size = nfp_shared_buf_pool_unit(pf, sb);
0070 if (!unit_size || size % unit_size)
0071 return -EINVAL;
0072 set_data.size = cpu_to_le32(size / unit_size);
0073
0074 return nfp_mbox_cmd(pf, NFP_MBOX_POOL_SET, &set_data, sizeof(set_data),
0075 NULL, 0);
0076 }
0077
0078 int nfp_shared_buf_register(struct nfp_pf *pf)
0079 {
0080 struct devlink *devlink = priv_to_devlink(pf);
0081 unsigned int i, num_entries, entry_sz;
0082 struct nfp_cpp_area *sb_desc_area;
0083 u8 __iomem *sb_desc;
0084 int n, err;
0085
0086 if (!pf->mbox)
0087 return 0;
0088
0089 n = nfp_pf_rtsym_read_optional(pf, NFP_SHARED_BUF_COUNT_SYM_NAME, 0);
0090 if (n <= 0)
0091 return n;
0092 num_entries = n;
0093
0094 sb_desc = nfp_pf_map_rtsym(pf, "sb_tbl", NFP_SHARED_BUF_TABLE_SYM_NAME,
0095 num_entries * sizeof(pf->shared_bufs[0]),
0096 &sb_desc_area);
0097 if (IS_ERR(sb_desc))
0098 return PTR_ERR(sb_desc);
0099
0100 entry_sz = nfp_cpp_area_size(sb_desc_area) / num_entries;
0101
0102 pf->shared_bufs = kmalloc_array(num_entries, sizeof(pf->shared_bufs[0]),
0103 GFP_KERNEL);
0104 if (!pf->shared_bufs) {
0105 err = -ENOMEM;
0106 goto err_release_area;
0107 }
0108
0109 for (i = 0; i < num_entries; i++) {
0110 struct nfp_shared_buf *sb = &pf->shared_bufs[i];
0111
0112
0113 memcpy_fromio(sb, sb_desc + i * entry_sz, sizeof(*sb));
0114
0115 err = devlink_sb_register(devlink,
0116 le32_to_cpu(sb->id),
0117 le32_to_cpu(sb->size),
0118 le16_to_cpu(sb->ingress_pools_count),
0119 le16_to_cpu(sb->egress_pools_count),
0120 le16_to_cpu(sb->ingress_tc_count),
0121 le16_to_cpu(sb->egress_tc_count));
0122 if (err)
0123 goto err_unreg_prev;
0124 }
0125 pf->num_shared_bufs = num_entries;
0126
0127 nfp_cpp_area_release_free(sb_desc_area);
0128
0129 return 0;
0130
0131 err_unreg_prev:
0132 while (i--)
0133 devlink_sb_unregister(devlink,
0134 le32_to_cpu(pf->shared_bufs[i].id));
0135 kfree(pf->shared_bufs);
0136 err_release_area:
0137 nfp_cpp_area_release_free(sb_desc_area);
0138 return err;
0139 }
0140
0141 void nfp_shared_buf_unregister(struct nfp_pf *pf)
0142 {
0143 struct devlink *devlink = priv_to_devlink(pf);
0144 unsigned int i;
0145
0146 for (i = 0; i < pf->num_shared_bufs; i++)
0147 devlink_sb_unregister(devlink,
0148 le32_to_cpu(pf->shared_bufs[i].id));
0149 kfree(pf->shared_bufs);
0150 }