1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 /* 3 * Copyright (C) 2018 Netronome Systems, Inc. 4 * 5 * This software is dual licensed under the GNU General License Version 2, 6 * June 1991 as shown in the file COPYING in the top-level directory of this 7 * source tree or the BSD 2-Clause License provided below. You have the 8 * option to license this software under the complete terms of either license. 9 * 10 * The BSD 2-Clause License: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * 1. Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 */ 34 35 #include <linux/kernel.h> 36 #include <net/devlink.h> 37 38 #include "nfpcore/nfp_cpp.h" 39 #include "nfpcore/nfp_nffw.h" 40 #include "nfp_abi.h" 41 #include "nfp_app.h" 42 #include "nfp_main.h" 43 44 static u32 nfp_shared_buf_pool_unit(struct nfp_pf *pf, unsigned int sb) 45 { 46 __le32 sb_id = cpu_to_le32(sb); 47 unsigned int i; 48 49 for (i = 0; i < pf->num_shared_bufs; i++) 50 if (pf->shared_bufs[i].id == sb_id) 51 return le32_to_cpu(pf->shared_bufs[i].pool_size_unit); 52 53 WARN_ON_ONCE(1); 54 return 0; 55 } 56 57 int nfp_shared_buf_pool_get(struct nfp_pf *pf, unsigned int sb, u16 pool_index, 58 struct devlink_sb_pool_info *pool_info) 59 { 60 struct nfp_shared_buf_pool_info_get get_data; 61 struct nfp_shared_buf_pool_id id = { 62 .shared_buf = cpu_to_le32(sb), 63 .pool = cpu_to_le32(pool_index), 64 }; 65 unsigned int unit_size; 66 int n; 67 68 unit_size = nfp_shared_buf_pool_unit(pf, sb); 69 if (!unit_size) 70 return -EINVAL; 71 72 n = nfp_mbox_cmd(pf, NFP_MBOX_POOL_GET, &id, sizeof(id), 73 &get_data, sizeof(get_data)); 74 if (n < 0) 75 return n; 76 if (n < sizeof(get_data)) 77 return -EIO; 78 79 pool_info->pool_type = le32_to_cpu(get_data.pool_type); 80 pool_info->threshold_type = le32_to_cpu(get_data.threshold_type); 81 pool_info->size = le32_to_cpu(get_data.size) * unit_size; 82 83 return 0; 84 } 85 86 int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb, 87 u16 pool_index, u32 size, 88 enum devlink_sb_threshold_type threshold_type) 89 { 90 struct nfp_shared_buf_pool_info_set set_data = { 91 .id = { 92 .shared_buf = cpu_to_le32(sb), 93 .pool = cpu_to_le32(pool_index), 94 }, 95 .threshold_type = cpu_to_le32(threshold_type), 96 }; 97 unsigned int unit_size; 98 99 unit_size = nfp_shared_buf_pool_unit(pf, sb); 100 if (!unit_size || size % unit_size) 101 return -EINVAL; 102 set_data.size = cpu_to_le32(size / unit_size); 103 104 return nfp_mbox_cmd(pf, NFP_MBOX_POOL_SET, &set_data, sizeof(set_data), 105 NULL, 0); 106 } 107 108 int nfp_shared_buf_register(struct nfp_pf *pf) 109 { 110 struct devlink *devlink = priv_to_devlink(pf); 111 unsigned int i, num_entries, entry_sz; 112 struct nfp_cpp_area *sb_desc_area; 113 u8 __iomem *sb_desc; 114 int n, err; 115 116 if (!pf->mbox) 117 return 0; 118 119 n = nfp_pf_rtsym_read_optional(pf, NFP_SHARED_BUF_COUNT_SYM_NAME, 0); 120 if (n <= 0) 121 return n; 122 num_entries = n; 123 124 sb_desc = nfp_pf_map_rtsym(pf, "sb_tbl", NFP_SHARED_BUF_TABLE_SYM_NAME, 125 num_entries * sizeof(pf->shared_bufs[0]), 126 &sb_desc_area); 127 if (IS_ERR(sb_desc)) 128 return PTR_ERR(sb_desc); 129 130 entry_sz = nfp_cpp_area_size(sb_desc_area) / num_entries; 131 132 pf->shared_bufs = kmalloc_array(num_entries, sizeof(pf->shared_bufs[0]), 133 GFP_KERNEL); 134 if (!pf->shared_bufs) { 135 err = -ENOMEM; 136 goto err_release_area; 137 } 138 139 for (i = 0; i < num_entries; i++) { 140 struct nfp_shared_buf *sb = &pf->shared_bufs[i]; 141 142 /* Entries may be larger in future FW */ 143 memcpy_fromio(sb, sb_desc + i * entry_sz, sizeof(*sb)); 144 145 err = devlink_sb_register(devlink, 146 le32_to_cpu(sb->id), 147 le32_to_cpu(sb->size), 148 le16_to_cpu(sb->ingress_pools_count), 149 le16_to_cpu(sb->egress_pools_count), 150 le16_to_cpu(sb->ingress_tc_count), 151 le16_to_cpu(sb->egress_tc_count)); 152 if (err) 153 goto err_unreg_prev; 154 } 155 pf->num_shared_bufs = num_entries; 156 157 nfp_cpp_area_release_free(sb_desc_area); 158 159 return 0; 160 161 err_unreg_prev: 162 while (i--) 163 devlink_sb_unregister(devlink, 164 le32_to_cpu(pf->shared_bufs[i].id)); 165 kfree(pf->shared_bufs); 166 err_release_area: 167 nfp_cpp_area_release_free(sb_desc_area); 168 return err; 169 } 170 171 void nfp_shared_buf_unregister(struct nfp_pf *pf) 172 { 173 struct devlink *devlink = priv_to_devlink(pf); 174 unsigned int i; 175 176 for (i = 0; i < pf->num_shared_bufs; i++) 177 devlink_sb_unregister(devlink, 178 le32_to_cpu(pf->shared_bufs[i].id)); 179 kfree(pf->shared_bufs); 180 } 181