1c7e9729dSAlejandro Lucero /* SPDX-License-Identifier: BSD-3-Clause 2c7e9729dSAlejandro Lucero * Copyright(c) 2018 Netronome Systems, Inc. 3c7e9729dSAlejandro Lucero * All rights reserved. 4c7e9729dSAlejandro Lucero */ 5c7e9729dSAlejandro Lucero 602236d46SChaoyong He #include "nfp_resource.h" 7c7e9729dSAlejandro Lucero 802236d46SChaoyong He #include "nfp_crc.h" 952d810dcSJames Hershaw #include "nfp_logs.h" 104b6c8db9SChaoyong He #include "nfp_mutex.h" 11055ccb33SChaoyong He #include "nfp_target.h" 12c7e9729dSAlejandro Lucero 13c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_TARGET NFP_CPP_TARGET_MU 14c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_BASE 0x8100000000ULL 15c7e9729dSAlejandro Lucero 16c7e9729dSAlejandro Lucero /* NFP Resource Table self-identifier */ 17c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_NAME "nfp.res" 18c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_KEY 0x00000000 /* Special key for entry 0 */ 19c7e9729dSAlejandro Lucero 20c7e9729dSAlejandro Lucero #define NFP_RESOURCE_ENTRY_NAME_SZ 8 21c7e9729dSAlejandro Lucero 226d03aa61SChaoyong He /* Resource table entry */ 23c7e9729dSAlejandro Lucero struct nfp_resource_entry { 24c7e9729dSAlejandro Lucero struct nfp_resource_entry_mutex { 256d03aa61SChaoyong He uint32_t owner; /**< NFP CPP Lock, interface owner */ 266d03aa61SChaoyong He uint32_t key; /**< NFP CPP Lock, posix_crc32(name, 8) */ 27c7e9729dSAlejandro Lucero } mutex; 286d03aa61SChaoyong He /* Memory region descriptor */ 29c7e9729dSAlejandro Lucero struct nfp_resource_entry_region { 306d03aa61SChaoyong He /** ASCII, zero padded name */ 31c7e9729dSAlejandro Lucero uint8_t name[NFP_RESOURCE_ENTRY_NAME_SZ]; 32c7e9729dSAlejandro Lucero uint8_t reserved[5]; 336d03aa61SChaoyong He uint8_t cpp_action; /**< CPP Action */ 346d03aa61SChaoyong He uint8_t cpp_token; /**< CPP Token */ 356d03aa61SChaoyong He uint8_t cpp_target; /**< CPP Target ID */ 366d03aa61SChaoyong He /** 256-byte page offset into target's CPP address */ 37c7e9729dSAlejandro Lucero uint32_t page_offset; 386d03aa61SChaoyong He uint32_t page_size; /**< Size, in 256-byte pages */ 39c7e9729dSAlejandro Lucero } region; 40c7e9729dSAlejandro Lucero }; 41c7e9729dSAlejandro Lucero 42c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_SIZE 4096 4302236d46SChaoyong He #define NFP_RESOURCE_TBL_ENTRIES (NFP_RESOURCE_TBL_SIZE / \ 44c7e9729dSAlejandro Lucero sizeof(struct nfp_resource_entry)) 45c7e9729dSAlejandro Lucero 46c7e9729dSAlejandro Lucero struct nfp_resource { 47c7e9729dSAlejandro Lucero char name[NFP_RESOURCE_ENTRY_NAME_SZ + 1]; 48c7e9729dSAlejandro Lucero uint32_t cpp_id; 49c7e9729dSAlejandro Lucero uint64_t addr; 50c7e9729dSAlejandro Lucero uint64_t size; 51c7e9729dSAlejandro Lucero struct nfp_cpp_mutex *mutex; 52c7e9729dSAlejandro Lucero }; 53c7e9729dSAlejandro Lucero 54c7e9729dSAlejandro Lucero static int 55d108b9e9SChaoyong He nfp_cpp_resource_find(struct nfp_cpp *cpp, 56d108b9e9SChaoyong He struct nfp_resource *res) 57c7e9729dSAlejandro Lucero { 58610bf14bSChaoyong He int ret; 59610bf14bSChaoyong He uint32_t i; 60610bf14bSChaoyong He uint32_t key; 61610bf14bSChaoyong He uint32_t cpp_id; 62c7e9729dSAlejandro Lucero struct nfp_resource_entry entry; 63610bf14bSChaoyong He char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ + 2]; 64c7e9729dSAlejandro Lucero 65c7e9729dSAlejandro Lucero cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0); /* Atomic read */ 66c7e9729dSAlejandro Lucero 6762280b78SAndy Green memset(name_pad, 0, sizeof(name_pad)); 6862280b78SAndy Green strlcpy(name_pad, res->name, sizeof(name_pad)); 69c7e9729dSAlejandro Lucero 70c7e9729dSAlejandro Lucero /* Search for a matching entry */ 71cbcbfd73SJames Hershaw if (memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8) == 0) { 72*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Grabbing device lock not supported."); 73c7e9729dSAlejandro Lucero return -EOPNOTSUPP; 74c7e9729dSAlejandro Lucero } 75f842b01aSChaoyong He 7662280b78SAndy Green key = nfp_crc32_posix(name_pad, NFP_RESOURCE_ENTRY_NAME_SZ); 77c7e9729dSAlejandro Lucero 78c7e9729dSAlejandro Lucero for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) { 79c7e9729dSAlejandro Lucero uint64_t addr = NFP_RESOURCE_TBL_BASE + 80c7e9729dSAlejandro Lucero sizeof(struct nfp_resource_entry) * i; 81c7e9729dSAlejandro Lucero 82c7e9729dSAlejandro Lucero ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry)); 83c7e9729dSAlejandro Lucero if (ret != sizeof(entry)) 84c7e9729dSAlejandro Lucero return -EIO; 85c7e9729dSAlejandro Lucero 86c7e9729dSAlejandro Lucero if (entry.mutex.key != key) 87c7e9729dSAlejandro Lucero continue; 88c7e9729dSAlejandro Lucero 89c7e9729dSAlejandro Lucero /* Found key! */ 90d108b9e9SChaoyong He res->mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET, 91d108b9e9SChaoyong He addr, key); 92c7e9729dSAlejandro Lucero res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, 93c7e9729dSAlejandro Lucero entry.region.cpp_action, 94c7e9729dSAlejandro Lucero entry.region.cpp_token); 95c7e9729dSAlejandro Lucero res->addr = ((uint64_t)entry.region.page_offset) << 8; 96c7e9729dSAlejandro Lucero res->size = (uint64_t)entry.region.page_size << 8; 97f842b01aSChaoyong He 98c7e9729dSAlejandro Lucero return 0; 99c7e9729dSAlejandro Lucero } 100c7e9729dSAlejandro Lucero 101c7e9729dSAlejandro Lucero return -ENOENT; 102c7e9729dSAlejandro Lucero } 103c7e9729dSAlejandro Lucero 104c7e9729dSAlejandro Lucero static int 105d108b9e9SChaoyong He nfp_resource_try_acquire(struct nfp_cpp *cpp, 106d108b9e9SChaoyong He struct nfp_resource *res, 107c7e9729dSAlejandro Lucero struct nfp_cpp_mutex *dev_mutex) 108c7e9729dSAlejandro Lucero { 109c7e9729dSAlejandro Lucero int err; 110c7e9729dSAlejandro Lucero 111efa766e1SChaoyong He if (nfp_cpp_mutex_lock(dev_mutex) != 0) { 112*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex lock failed."); 113c7e9729dSAlejandro Lucero return -EINVAL; 114efa766e1SChaoyong He } 115c7e9729dSAlejandro Lucero 116c7e9729dSAlejandro Lucero err = nfp_cpp_resource_find(cpp, res); 117efa766e1SChaoyong He if (err != 0) { 118*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RESOURCE - CPP resource find failed."); 119c7e9729dSAlejandro Lucero goto err_unlock_dev; 120efa766e1SChaoyong He } 121c7e9729dSAlejandro Lucero 122c7e9729dSAlejandro Lucero err = nfp_cpp_mutex_trylock(res->mutex); 123efa766e1SChaoyong He if (err != 0) { 124*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex trylock failed."); 125c7e9729dSAlejandro Lucero goto err_res_mutex_free; 126efa766e1SChaoyong He } 127c7e9729dSAlejandro Lucero 128c7e9729dSAlejandro Lucero nfp_cpp_mutex_unlock(dev_mutex); 129c7e9729dSAlejandro Lucero 130c7e9729dSAlejandro Lucero return 0; 131c7e9729dSAlejandro Lucero 132c7e9729dSAlejandro Lucero err_res_mutex_free: 133c7e9729dSAlejandro Lucero nfp_cpp_mutex_free(res->mutex); 134c7e9729dSAlejandro Lucero err_unlock_dev: 135c7e9729dSAlejandro Lucero nfp_cpp_mutex_unlock(dev_mutex); 136c7e9729dSAlejandro Lucero 137c7e9729dSAlejandro Lucero return err; 138c7e9729dSAlejandro Lucero } 139c7e9729dSAlejandro Lucero 1406d03aa61SChaoyong He /** 1416d03aa61SChaoyong He * Acquire a resource handle 142c7e9729dSAlejandro Lucero * 1436d03aa61SChaoyong He * Note: This function locks the acquired resource. 144c7e9729dSAlejandro Lucero * 1456d03aa61SChaoyong He * @param cpp 1466d03aa61SChaoyong He * NFP CPP handle 1476d03aa61SChaoyong He * @param name 1486d03aa61SChaoyong He * Name of the resource 1496d03aa61SChaoyong He * 1506d03aa61SChaoyong He * @return 1516d03aa61SChaoyong He * NFP Resource handle, or NULL 152c7e9729dSAlejandro Lucero */ 153c7e9729dSAlejandro Lucero struct nfp_resource * 154d108b9e9SChaoyong He nfp_resource_acquire(struct nfp_cpp *cpp, 155d108b9e9SChaoyong He const char *name) 156c7e9729dSAlejandro Lucero { 157c7e9729dSAlejandro Lucero int err; 158610bf14bSChaoyong He uint16_t count = 0; 159c7e9729dSAlejandro Lucero struct timespec wait; 160610bf14bSChaoyong He struct nfp_resource *res; 161610bf14bSChaoyong He struct nfp_cpp_mutex *dev_mutex; 162c7e9729dSAlejandro Lucero 163c7e9729dSAlejandro Lucero res = malloc(sizeof(*res)); 164aa6b4a80SHuaxing Zhu if (res == NULL) { 165aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "RESOURCE - Malloc NSP memory failed."); 166c7e9729dSAlejandro Lucero return NULL; 167aa6b4a80SHuaxing Zhu } 168c7e9729dSAlejandro Lucero 169c7e9729dSAlejandro Lucero memset(res, 0, sizeof(*res)); 170c7e9729dSAlejandro Lucero 171c7e9729dSAlejandro Lucero strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ); 172c7e9729dSAlejandro Lucero 173c7e9729dSAlejandro Lucero dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET, 174d108b9e9SChaoyong He NFP_RESOURCE_TBL_BASE, NFP_RESOURCE_TBL_KEY); 175cbcbfd73SJames Hershaw if (dev_mutex == NULL) { 176*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex alloc failed."); 17702236d46SChaoyong He goto err_free; 178c7e9729dSAlejandro Lucero } 179c7e9729dSAlejandro Lucero 180c7e9729dSAlejandro Lucero wait.tv_sec = 0; 1816d03aa61SChaoyong He wait.tv_nsec = 1000000; /* 1ms */ 182c7e9729dSAlejandro Lucero 183c7e9729dSAlejandro Lucero for (;;) { 184c7e9729dSAlejandro Lucero err = nfp_resource_try_acquire(cpp, res, dev_mutex); 185cbcbfd73SJames Hershaw if (err == 0) 186c7e9729dSAlejandro Lucero break; 187efa766e1SChaoyong He if (err != -EBUSY) { 188*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "RESOURCE - try acquire failed."); 18902236d46SChaoyong He goto mutex_free; 190efa766e1SChaoyong He } 191c7e9729dSAlejandro Lucero 1926d03aa61SChaoyong He if (count++ > 1000) { /* 1ms * 1000 = 1s */ 193*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Error: resource %s timed out.", name); 19402236d46SChaoyong He goto mutex_free; 195c7e9729dSAlejandro Lucero } 196c7e9729dSAlejandro Lucero 197c7e9729dSAlejandro Lucero nanosleep(&wait, NULL); 198c7e9729dSAlejandro Lucero } 199c7e9729dSAlejandro Lucero 200c7e9729dSAlejandro Lucero nfp_cpp_mutex_free(dev_mutex); 201c7e9729dSAlejandro Lucero 202c7e9729dSAlejandro Lucero return res; 203c7e9729dSAlejandro Lucero 20402236d46SChaoyong He mutex_free: 205c7e9729dSAlejandro Lucero nfp_cpp_mutex_free(dev_mutex); 20602236d46SChaoyong He err_free: 207c7e9729dSAlejandro Lucero free(res); 208c7e9729dSAlejandro Lucero return NULL; 209c7e9729dSAlejandro Lucero } 210c7e9729dSAlejandro Lucero 2116d03aa61SChaoyong He /** 2126d03aa61SChaoyong He * Release a NFP Resource handle 213c7e9729dSAlejandro Lucero * 2146d03aa61SChaoyong He * NOTE: This function implicitly unlocks the resource handle. 2156d03aa61SChaoyong He * 2166d03aa61SChaoyong He * @param res 2176d03aa61SChaoyong He * NFP Resource handle 218c7e9729dSAlejandro Lucero */ 219c7e9729dSAlejandro Lucero void 220c7e9729dSAlejandro Lucero nfp_resource_release(struct nfp_resource *res) 221c7e9729dSAlejandro Lucero { 222c7e9729dSAlejandro Lucero nfp_cpp_mutex_unlock(res->mutex); 223c7e9729dSAlejandro Lucero nfp_cpp_mutex_free(res->mutex); 224c7e9729dSAlejandro Lucero free(res); 225c7e9729dSAlejandro Lucero } 226c7e9729dSAlejandro Lucero 2276d03aa61SChaoyong He /** 2286d03aa61SChaoyong He * Return the cpp_id of a resource handle 229c7e9729dSAlejandro Lucero * 2306d03aa61SChaoyong He * @param res 2316d03aa61SChaoyong He * NFP Resource handle 2326d03aa61SChaoyong He * 2336d03aa61SChaoyong He * @return 2346d03aa61SChaoyong He * NFP CPP ID 235c7e9729dSAlejandro Lucero */ 236c7e9729dSAlejandro Lucero uint32_t 237c7e9729dSAlejandro Lucero nfp_resource_cpp_id(const struct nfp_resource *res) 238c7e9729dSAlejandro Lucero { 239c7e9729dSAlejandro Lucero return res->cpp_id; 240c7e9729dSAlejandro Lucero } 241c7e9729dSAlejandro Lucero 2426d03aa61SChaoyong He /** 2436d03aa61SChaoyong He * Return the name of a resource handle 244c7e9729dSAlejandro Lucero * 2456d03aa61SChaoyong He * @param res 2466d03aa61SChaoyong He * NFP Resource handle 2476d03aa61SChaoyong He * 2486d03aa61SChaoyong He * @return 2496d03aa61SChaoyong He * Const char pointer to the name of the resource 250c7e9729dSAlejandro Lucero */ 251d108b9e9SChaoyong He const char * 252d108b9e9SChaoyong He nfp_resource_name(const struct nfp_resource *res) 253c7e9729dSAlejandro Lucero { 254c7e9729dSAlejandro Lucero return res->name; 255c7e9729dSAlejandro Lucero } 256c7e9729dSAlejandro Lucero 2576d03aa61SChaoyong He /** 2586d03aa61SChaoyong He * Return the address of a resource handle 259c7e9729dSAlejandro Lucero * 2606d03aa61SChaoyong He * @param res 2616d03aa61SChaoyong He * NFP Resource handle 2626d03aa61SChaoyong He * 2636d03aa61SChaoyong He * @return 2646d03aa61SChaoyong He * Address of the resource 265c7e9729dSAlejandro Lucero */ 266c7e9729dSAlejandro Lucero uint64_t 267c7e9729dSAlejandro Lucero nfp_resource_address(const struct nfp_resource *res) 268c7e9729dSAlejandro Lucero { 269c7e9729dSAlejandro Lucero return res->addr; 270c7e9729dSAlejandro Lucero } 271c7e9729dSAlejandro Lucero 2726d03aa61SChaoyong He /** 2736d03aa61SChaoyong He * Return the size in bytes of a resource handle 274c7e9729dSAlejandro Lucero * 2756d03aa61SChaoyong He * @param res 2766d03aa61SChaoyong He * NFP Resource handle 2776d03aa61SChaoyong He * 2786d03aa61SChaoyong He * @return 2796d03aa61SChaoyong He * Size of the resource in bytes 280c7e9729dSAlejandro Lucero */ 281c7e9729dSAlejandro Lucero uint64_t 282c7e9729dSAlejandro Lucero nfp_resource_size(const struct nfp_resource *res) 283c7e9729dSAlejandro Lucero { 284c7e9729dSAlejandro Lucero return res->size; 285c7e9729dSAlejandro Lucero } 286