1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Netronome Systems, Inc. 3 * All rights reserved. 4 */ 5 6 #include "nfp_resource.h" 7 8 #include "nfp_crc.h" 9 #include "nfp_logs.h" 10 #include "nfp_mutex.h" 11 #include "nfp_target.h" 12 13 #define NFP_RESOURCE_TBL_TARGET NFP_CPP_TARGET_MU 14 #define NFP_RESOURCE_TBL_BASE 0x8100000000ULL 15 16 /* NFP Resource Table self-identifier */ 17 #define NFP_RESOURCE_TBL_NAME "nfp.res" 18 #define NFP_RESOURCE_TBL_KEY 0x00000000 /* Special key for entry 0 */ 19 20 #define NFP_RESOURCE_ENTRY_NAME_SZ 8 21 22 /* Resource table entry */ 23 struct nfp_resource_entry { 24 struct nfp_resource_entry_mutex { 25 uint32_t owner; /**< NFP CPP Lock, interface owner */ 26 uint32_t key; /**< NFP CPP Lock, posix_crc32(name, 8) */ 27 } mutex; 28 /* Memory region descriptor */ 29 struct nfp_resource_entry_region { 30 /** ASCII, zero padded name */ 31 uint8_t name[NFP_RESOURCE_ENTRY_NAME_SZ]; 32 uint8_t reserved[5]; 33 uint8_t cpp_action; /**< CPP Action */ 34 uint8_t cpp_token; /**< CPP Token */ 35 uint8_t cpp_target; /**< CPP Target ID */ 36 /** 256-byte page offset into target's CPP address */ 37 uint32_t page_offset; 38 uint32_t page_size; /**< Size, in 256-byte pages */ 39 } region; 40 }; 41 42 #define NFP_RESOURCE_TBL_SIZE 4096 43 #define NFP_RESOURCE_TBL_ENTRIES (NFP_RESOURCE_TBL_SIZE / \ 44 sizeof(struct nfp_resource_entry)) 45 46 struct nfp_resource { 47 char name[NFP_RESOURCE_ENTRY_NAME_SZ + 1]; 48 uint32_t cpp_id; 49 uint64_t addr; 50 uint64_t size; 51 struct nfp_cpp_mutex *mutex; 52 }; 53 54 static int 55 nfp_cpp_resource_find(struct nfp_cpp *cpp, 56 struct nfp_resource *res) 57 { 58 int ret; 59 uint32_t i; 60 uint32_t key; 61 uint32_t cpp_id; 62 struct nfp_resource_entry entry; 63 char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ + 2]; 64 65 cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0); /* Atomic read */ 66 67 memset(name_pad, 0, sizeof(name_pad)); 68 strlcpy(name_pad, res->name, sizeof(name_pad)); 69 70 /* Search for a matching entry */ 71 if (memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8) == 0) { 72 PMD_DRV_LOG(ERR, "Grabbing device lock not supported."); 73 return -EOPNOTSUPP; 74 } 75 76 key = nfp_crc32_posix(name_pad, NFP_RESOURCE_ENTRY_NAME_SZ); 77 78 for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) { 79 uint64_t addr = NFP_RESOURCE_TBL_BASE + 80 sizeof(struct nfp_resource_entry) * i; 81 82 ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry)); 83 if (ret != sizeof(entry)) 84 return -EIO; 85 86 if (entry.mutex.key != key) 87 continue; 88 89 /* Found key! */ 90 res->mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET, 91 addr, key); 92 res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, 93 entry.region.cpp_action, 94 entry.region.cpp_token); 95 res->addr = ((uint64_t)entry.region.page_offset) << 8; 96 res->size = (uint64_t)entry.region.page_size << 8; 97 98 return 0; 99 } 100 101 return -ENOENT; 102 } 103 104 static int 105 nfp_resource_try_acquire(struct nfp_cpp *cpp, 106 struct nfp_resource *res, 107 struct nfp_cpp_mutex *dev_mutex) 108 { 109 int err; 110 111 if (nfp_cpp_mutex_lock(dev_mutex) != 0) { 112 PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex lock failed."); 113 return -EINVAL; 114 } 115 116 err = nfp_cpp_resource_find(cpp, res); 117 if (err != 0) { 118 PMD_DRV_LOG(ERR, "RESOURCE - CPP resource find failed."); 119 goto err_unlock_dev; 120 } 121 122 err = nfp_cpp_mutex_trylock(res->mutex); 123 if (err != 0) { 124 PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex trylock failed."); 125 goto err_res_mutex_free; 126 } 127 128 nfp_cpp_mutex_unlock(dev_mutex); 129 130 return 0; 131 132 err_res_mutex_free: 133 nfp_cpp_mutex_free(res->mutex); 134 err_unlock_dev: 135 nfp_cpp_mutex_unlock(dev_mutex); 136 137 return err; 138 } 139 140 /** 141 * Acquire a resource handle 142 * 143 * Note: This function locks the acquired resource. 144 * 145 * @param cpp 146 * NFP CPP handle 147 * @param name 148 * Name of the resource 149 * 150 * @return 151 * NFP Resource handle, or NULL 152 */ 153 struct nfp_resource * 154 nfp_resource_acquire(struct nfp_cpp *cpp, 155 const char *name) 156 { 157 int err; 158 uint16_t count = 0; 159 struct timespec wait; 160 struct nfp_resource *res; 161 struct nfp_cpp_mutex *dev_mutex; 162 163 res = malloc(sizeof(*res)); 164 if (res == NULL) { 165 PMD_DRV_LOG(ERR, "RESOURCE - Malloc NSP memory failed."); 166 return NULL; 167 } 168 169 memset(res, 0, sizeof(*res)); 170 171 strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ); 172 173 dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET, 174 NFP_RESOURCE_TBL_BASE, NFP_RESOURCE_TBL_KEY); 175 if (dev_mutex == NULL) { 176 PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex alloc failed."); 177 goto err_free; 178 } 179 180 wait.tv_sec = 0; 181 wait.tv_nsec = 1000000; /* 1ms */ 182 183 for (;;) { 184 err = nfp_resource_try_acquire(cpp, res, dev_mutex); 185 if (err == 0) 186 break; 187 if (err != -EBUSY) { 188 PMD_DRV_LOG(ERR, "RESOURCE - try acquire failed."); 189 goto mutex_free; 190 } 191 192 if (count++ > 1000) { /* 1ms * 1000 = 1s */ 193 PMD_DRV_LOG(ERR, "Error: resource %s timed out.", name); 194 goto mutex_free; 195 } 196 197 nanosleep(&wait, NULL); 198 } 199 200 nfp_cpp_mutex_free(dev_mutex); 201 202 return res; 203 204 mutex_free: 205 nfp_cpp_mutex_free(dev_mutex); 206 err_free: 207 free(res); 208 return NULL; 209 } 210 211 /** 212 * Release a NFP Resource handle 213 * 214 * NOTE: This function implicitly unlocks the resource handle. 215 * 216 * @param res 217 * NFP Resource handle 218 */ 219 void 220 nfp_resource_release(struct nfp_resource *res) 221 { 222 nfp_cpp_mutex_unlock(res->mutex); 223 nfp_cpp_mutex_free(res->mutex); 224 free(res); 225 } 226 227 /** 228 * Return the cpp_id of a resource handle 229 * 230 * @param res 231 * NFP Resource handle 232 * 233 * @return 234 * NFP CPP ID 235 */ 236 uint32_t 237 nfp_resource_cpp_id(const struct nfp_resource *res) 238 { 239 return res->cpp_id; 240 } 241 242 /** 243 * Return the name of a resource handle 244 * 245 * @param res 246 * NFP Resource handle 247 * 248 * @return 249 * Const char pointer to the name of the resource 250 */ 251 const char * 252 nfp_resource_name(const struct nfp_resource *res) 253 { 254 return res->name; 255 } 256 257 /** 258 * Return the address of a resource handle 259 * 260 * @param res 261 * NFP Resource handle 262 * 263 * @return 264 * Address of the resource 265 */ 266 uint64_t 267 nfp_resource_address(const struct nfp_resource *res) 268 { 269 return res->addr; 270 } 271 272 /** 273 * Return the size in bytes of a resource handle 274 * 275 * @param res 276 * NFP Resource handle 277 * 278 * @return 279 * Size of the resource in bytes 280 */ 281 uint64_t 282 nfp_resource_size(const struct nfp_resource *res) 283 { 284 return res->size; 285 } 286