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 64b6c8db9SChaoyong He #include "nfp_mutex.h" 74b6c8db9SChaoyong He 8c7e9729dSAlejandro Lucero #include <sched.h> 9c7e9729dSAlejandro Lucero 1052d810dcSJames Hershaw #include "nfp_logs.h" 11055ccb33SChaoyong He #include "nfp_target.h" 12c7e9729dSAlejandro Lucero 13c7e9729dSAlejandro Lucero /* 14c7e9729dSAlejandro Lucero * If you need more than 65536 recursive locks, please 15c7e9729dSAlejandro Lucero * rethink your code. 16c7e9729dSAlejandro Lucero */ 17c7e9729dSAlejandro Lucero #define MUTEX_DEPTH_MAX 0xffff 18c7e9729dSAlejandro Lucero 19c7e9729dSAlejandro Lucero struct nfp_cpp_mutex { 20c7e9729dSAlejandro Lucero struct nfp_cpp *cpp; 21c7e9729dSAlejandro Lucero uint8_t target; 22c7e9729dSAlejandro Lucero uint16_t depth; 23c69debceSChaoyong He uint64_t address; 24c7e9729dSAlejandro Lucero uint32_t key; 25c69debceSChaoyong He uint32_t usage; 26c7e9729dSAlejandro Lucero struct nfp_cpp_mutex *prev, *next; 27c7e9729dSAlejandro Lucero }; 28c7e9729dSAlejandro Lucero 294b6c8db9SChaoyong He static inline uint32_t 304b6c8db9SChaoyong He nfp_mutex_locked(uint16_t interface) 314b6c8db9SChaoyong He { 324b6c8db9SChaoyong He return (uint32_t)interface << 16 | 0x000f; 334b6c8db9SChaoyong He } 344b6c8db9SChaoyong He 354b6c8db9SChaoyong He static inline uint32_t 364b6c8db9SChaoyong He nfp_mutex_unlocked(uint16_t interface) 374b6c8db9SChaoyong He { 384b6c8db9SChaoyong He return (uint32_t)interface << 16 | 0x0000; 394b6c8db9SChaoyong He } 404b6c8db9SChaoyong He 414b6c8db9SChaoyong He static inline uint16_t 424b6c8db9SChaoyong He nfp_mutex_owner(uint32_t val) 434b6c8db9SChaoyong He { 444b6c8db9SChaoyong He return (val >> 16) & 0xffff; 454b6c8db9SChaoyong He } 464b6c8db9SChaoyong He 474b6c8db9SChaoyong He static inline bool 484b6c8db9SChaoyong He nfp_mutex_is_locked(uint32_t val) 494b6c8db9SChaoyong He { 504b6c8db9SChaoyong He return (val & 0xffff) == 0x000f; 514b6c8db9SChaoyong He } 524b6c8db9SChaoyong He 534b6c8db9SChaoyong He static inline bool 544b6c8db9SChaoyong He nfp_mutex_is_unlocked(uint32_t val) 554b6c8db9SChaoyong He { 564b6c8db9SChaoyong He return (val & 0xffff) == 0; 574b6c8db9SChaoyong He } 584b6c8db9SChaoyong He 59c7e9729dSAlejandro Lucero static int 604b6c8db9SChaoyong He nfp_cpp_mutex_validate(uint16_t interface, 61d108b9e9SChaoyong He int *target, 62c69debceSChaoyong He uint64_t address) 63c7e9729dSAlejandro Lucero { 644b6c8db9SChaoyong He /* Not permitted on invalid interfaces */ 654b6c8db9SChaoyong He if (NFP_CPP_INTERFACE_TYPE_of(interface) == NFP_CPP_INTERFACE_TYPE_INVALID) 664b6c8db9SChaoyong He return -EINVAL; 674b6c8db9SChaoyong He 68c7e9729dSAlejandro Lucero /* Address must be 64-bit aligned */ 694aa75cadSChaoyong He if ((address & 7) != 0) 70b29d5df4SChaoyong He return -EINVAL; 71c7e9729dSAlejandro Lucero 72c7e9729dSAlejandro Lucero if (*target != NFP_CPP_TARGET_MU) 73b29d5df4SChaoyong He return -EINVAL; 74c7e9729dSAlejandro Lucero 75c7e9729dSAlejandro Lucero return 0; 76c7e9729dSAlejandro Lucero } 77c7e9729dSAlejandro Lucero 786d03aa61SChaoyong He /** 79c7e9729dSAlejandro Lucero * Initialize a mutex location 80c7e9729dSAlejandro Lucero * 81c7e9729dSAlejandro Lucero * The CPP target:address must point to a 64-bit aligned location, and 82c7e9729dSAlejandro Lucero * will initialize 64 bits of data at the location. 83c7e9729dSAlejandro Lucero * 84c7e9729dSAlejandro Lucero * This creates the initial mutex state, as locked by this 85c7e9729dSAlejandro Lucero * nfp_cpp_interface(). 86c7e9729dSAlejandro Lucero * 87c7e9729dSAlejandro Lucero * This function should only be called when setting up 88c7e9729dSAlejandro Lucero * the initial lock state upon boot-up of the system. 89c7e9729dSAlejandro Lucero * 906d03aa61SChaoyong He * @param cpp 916d03aa61SChaoyong He * NFP CPP handle 926d03aa61SChaoyong He * @param target 936d03aa61SChaoyong He * NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU) 946d03aa61SChaoyong He * @param address 956d03aa61SChaoyong He * Offset into the address space of the NFP CPP target ID 966d03aa61SChaoyong He * @param key 976d03aa61SChaoyong He * Unique 32-bit value for this mutex 98c7e9729dSAlejandro Lucero * 996d03aa61SChaoyong He * @return 1006d03aa61SChaoyong He * 0 on success, or negative value on failure 101c7e9729dSAlejandro Lucero */ 102c7e9729dSAlejandro Lucero int 103d108b9e9SChaoyong He nfp_cpp_mutex_init(struct nfp_cpp *cpp, 104d108b9e9SChaoyong He int target, 105c69debceSChaoyong He uint64_t address, 106c7e9729dSAlejandro Lucero uint32_t key) 107c7e9729dSAlejandro Lucero { 108610bf14bSChaoyong He int err; 109c7e9729dSAlejandro Lucero uint32_t muw = NFP_CPP_ID(target, 4, 0); /* atomic_write */ 1104b6c8db9SChaoyong He uint16_t interface = nfp_cpp_interface(cpp); 111c7e9729dSAlejandro Lucero 1124b6c8db9SChaoyong He err = nfp_cpp_mutex_validate(interface, &target, address); 113c7e9729dSAlejandro Lucero if (err < 0) 114c7e9729dSAlejandro Lucero return err; 115c7e9729dSAlejandro Lucero 116c7e9729dSAlejandro Lucero err = nfp_cpp_writel(cpp, muw, address + 4, key); 117c7e9729dSAlejandro Lucero if (err < 0) 118c7e9729dSAlejandro Lucero return err; 119c7e9729dSAlejandro Lucero 1204b6c8db9SChaoyong He err = nfp_cpp_writel(cpp, muw, address, nfp_mutex_locked(interface)); 121c7e9729dSAlejandro Lucero if (err < 0) 122c7e9729dSAlejandro Lucero return err; 123c7e9729dSAlejandro Lucero 124c7e9729dSAlejandro Lucero return 0; 125c7e9729dSAlejandro Lucero } 126c7e9729dSAlejandro Lucero 1276d03aa61SChaoyong He /** 128c7e9729dSAlejandro Lucero * Create a mutex handle from an address controlled by a MU Atomic engine 129c7e9729dSAlejandro Lucero * 130c7e9729dSAlejandro Lucero * The CPP target:address must point to a 64-bit aligned location, and 131c7e9729dSAlejandro Lucero * reserve 64 bits of data at the location for use by the handle. 132c7e9729dSAlejandro Lucero * 133c7e9729dSAlejandro Lucero * Only target/address pairs that point to entities that support the 134c7e9729dSAlejandro Lucero * MU Atomic Engine are supported. 135c7e9729dSAlejandro Lucero * 1366d03aa61SChaoyong He * @param cpp 1376d03aa61SChaoyong He * NFP CPP handle 1386d03aa61SChaoyong He * @param target 1396d03aa61SChaoyong He * NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU) 1406d03aa61SChaoyong He * @param address 1416d03aa61SChaoyong He * Offset into the address space of the NFP CPP target ID 1426d03aa61SChaoyong He * @param key 1436d03aa61SChaoyong He * 32-bit unique key (must match the key at this location) 144c7e9729dSAlejandro Lucero * 1456d03aa61SChaoyong He * @return 1466d03aa61SChaoyong He * A non-NULL struct nfp_cpp_mutex * on success, NULL on failure. 147c7e9729dSAlejandro Lucero */ 148c7e9729dSAlejandro Lucero struct nfp_cpp_mutex * 149d108b9e9SChaoyong He nfp_cpp_mutex_alloc(struct nfp_cpp *cpp, 150d108b9e9SChaoyong He int target, 151c69debceSChaoyong He uint64_t address, 152d108b9e9SChaoyong He uint32_t key) 153c7e9729dSAlejandro Lucero { 154c7e9729dSAlejandro Lucero int err; 155c7e9729dSAlejandro Lucero uint32_t tmp; 156610bf14bSChaoyong He struct nfp_cpp_mutex *mutex; 157610bf14bSChaoyong He uint32_t mur = NFP_CPP_ID(target, 3, 0); /* atomic_read */ 1584b6c8db9SChaoyong He uint16_t interface = nfp_cpp_interface(cpp); 159c7e9729dSAlejandro Lucero 1604b6c8db9SChaoyong He err = nfp_cpp_mutex_validate(interface, &target, address); 161c7e9729dSAlejandro Lucero if (err < 0) 162c7e9729dSAlejandro Lucero return NULL; 163c7e9729dSAlejandro Lucero 164c7e9729dSAlejandro Lucero err = nfp_cpp_readl(cpp, mur, address + 4, &tmp); 165c7e9729dSAlejandro Lucero if (err < 0) 166c7e9729dSAlejandro Lucero return NULL; 167c7e9729dSAlejandro Lucero 168c7e9729dSAlejandro Lucero if (tmp != key) 169b29d5df4SChaoyong He return NULL; 170c7e9729dSAlejandro Lucero 1710352f47aSFerruh Yigit mutex = calloc(1, sizeof(*mutex)); 172cbcbfd73SJames Hershaw if (mutex == NULL) 173b29d5df4SChaoyong He return NULL; 174c7e9729dSAlejandro Lucero 175c7e9729dSAlejandro Lucero mutex->cpp = cpp; 176c7e9729dSAlejandro Lucero mutex->target = target; 177c7e9729dSAlejandro Lucero mutex->address = address; 178c7e9729dSAlejandro Lucero mutex->key = key; 179c7e9729dSAlejandro Lucero mutex->depth = 0; 180c7e9729dSAlejandro Lucero 181c7e9729dSAlejandro Lucero return mutex; 182c7e9729dSAlejandro Lucero } 183c7e9729dSAlejandro Lucero 1846d03aa61SChaoyong He /** 185c7e9729dSAlejandro Lucero * Free a mutex handle - does not alter the lock state 186c7e9729dSAlejandro Lucero * 1876d03aa61SChaoyong He * @param mutex 1886d03aa61SChaoyong He * NFP CPP Mutex handle 189c7e9729dSAlejandro Lucero */ 190c7e9729dSAlejandro Lucero void 191c7e9729dSAlejandro Lucero nfp_cpp_mutex_free(struct nfp_cpp_mutex *mutex) 192c7e9729dSAlejandro Lucero { 193c7e9729dSAlejandro Lucero free(mutex); 194c7e9729dSAlejandro Lucero } 195c7e9729dSAlejandro Lucero 1966d03aa61SChaoyong He /** 197c7e9729dSAlejandro Lucero * Lock a mutex handle, using the NFP MU Atomic Engine 198c7e9729dSAlejandro Lucero * 1996d03aa61SChaoyong He * @param mutex 2006d03aa61SChaoyong He * NFP CPP Mutex handle 201c7e9729dSAlejandro Lucero * 2026d03aa61SChaoyong He * @return 2036d03aa61SChaoyong He * 0 on success, or negative value on failure. 204c7e9729dSAlejandro Lucero */ 205c7e9729dSAlejandro Lucero int 206c7e9729dSAlejandro Lucero nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex) 207c7e9729dSAlejandro Lucero { 208c7e9729dSAlejandro Lucero int err; 209c7e9729dSAlejandro Lucero time_t warn_at = time(NULL) + 15; 210c7e9729dSAlejandro Lucero 211c7e9729dSAlejandro Lucero while ((err = nfp_cpp_mutex_trylock(mutex)) != 0) { 212b29d5df4SChaoyong He /* If err != -EBUSY, then the lock was damaged */ 213b29d5df4SChaoyong He if (err < 0 && err != -EBUSY) 214c7e9729dSAlejandro Lucero return err; 215f842b01aSChaoyong He 216c7e9729dSAlejandro Lucero if (time(NULL) >= warn_at) { 217efa766e1SChaoyong He PMD_DRV_LOG(WARNING, "Waiting for NFP mutex..."); 218c7e9729dSAlejandro Lucero warn_at = time(NULL) + 60; 219c7e9729dSAlejandro Lucero } 220f842b01aSChaoyong He 221c7e9729dSAlejandro Lucero sched_yield(); 222c7e9729dSAlejandro Lucero } 223f842b01aSChaoyong He 224c7e9729dSAlejandro Lucero return 0; 225c7e9729dSAlejandro Lucero } 226c7e9729dSAlejandro Lucero 2276d03aa61SChaoyong He /** 228c7e9729dSAlejandro Lucero * Unlock a mutex handle, using the NFP MU Atomic Engine 229c7e9729dSAlejandro Lucero * 2306d03aa61SChaoyong He * @param mutex 2316d03aa61SChaoyong He * NFP CPP Mutex handle 232c7e9729dSAlejandro Lucero * 2336d03aa61SChaoyong He * @return 2346d03aa61SChaoyong He * 0 on success, or negative value on failure 235c7e9729dSAlejandro Lucero */ 236c7e9729dSAlejandro Lucero int 237c7e9729dSAlejandro Lucero nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex) 238c7e9729dSAlejandro Lucero { 239610bf14bSChaoyong He int err; 240610bf14bSChaoyong He uint32_t key; 241610bf14bSChaoyong He uint32_t value; 242610bf14bSChaoyong He struct nfp_cpp *cpp = mutex->cpp; 243610bf14bSChaoyong He uint16_t interface = nfp_cpp_interface(cpp); 244c7e9729dSAlejandro Lucero uint32_t muw = NFP_CPP_ID(mutex->target, 4, 0); /* atomic_write */ 245c7e9729dSAlejandro Lucero uint32_t mur = NFP_CPP_ID(mutex->target, 3, 0); /* atomic_read */ 246c7e9729dSAlejandro Lucero 247c7e9729dSAlejandro Lucero if (mutex->depth > 1) { 248c7e9729dSAlejandro Lucero mutex->depth--; 249c7e9729dSAlejandro Lucero return 0; 250c7e9729dSAlejandro Lucero } 251c7e9729dSAlejandro Lucero 252c7e9729dSAlejandro Lucero err = nfp_cpp_readl(mutex->cpp, mur, mutex->address + 4, &key); 253c7e9729dSAlejandro Lucero if (err < 0) 2544b6c8db9SChaoyong He return err; 255c7e9729dSAlejandro Lucero 2564b6c8db9SChaoyong He if (key != mutex->key) 2574b6c8db9SChaoyong He return -EPERM; 258c7e9729dSAlejandro Lucero 2594b6c8db9SChaoyong He err = nfp_cpp_readl(mutex->cpp, mur, mutex->address, &value); 260c7e9729dSAlejandro Lucero if (err < 0) 2614b6c8db9SChaoyong He return err; 2624b6c8db9SChaoyong He 2634b6c8db9SChaoyong He if (value != nfp_mutex_locked(interface)) 2644b6c8db9SChaoyong He return -EACCES; 2654b6c8db9SChaoyong He 2664b6c8db9SChaoyong He err = nfp_cpp_writel(cpp, muw, mutex->address, 2674b6c8db9SChaoyong He nfp_mutex_unlocked(interface)); 2684b6c8db9SChaoyong He if (err < 0) 2694b6c8db9SChaoyong He return err; 270c7e9729dSAlejandro Lucero 271c7e9729dSAlejandro Lucero mutex->depth = 0; 272c7e9729dSAlejandro Lucero 2734b6c8db9SChaoyong He return 0; 274c7e9729dSAlejandro Lucero } 275c7e9729dSAlejandro Lucero 2766d03aa61SChaoyong He /** 277c7e9729dSAlejandro Lucero * Attempt to lock a mutex handle, using the NFP MU Atomic Engine 278c7e9729dSAlejandro Lucero * 279c7e9729dSAlejandro Lucero * Valid lock states: 280c7e9729dSAlejandro Lucero * 0x....0000 - Unlocked 281c7e9729dSAlejandro Lucero * 0x....000f - Locked 282c7e9729dSAlejandro Lucero * 2836d03aa61SChaoyong He * @param mutex 2846d03aa61SChaoyong He * NFP CPP Mutex handle 2856d03aa61SChaoyong He * 2866d03aa61SChaoyong He * @return 2876d03aa61SChaoyong He * 0 if the lock succeeded, negative value on failure. 288c7e9729dSAlejandro Lucero */ 289c7e9729dSAlejandro Lucero int 290c7e9729dSAlejandro Lucero nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex) 291c7e9729dSAlejandro Lucero { 292610bf14bSChaoyong He int err; 293610bf14bSChaoyong He uint32_t key; 294610bf14bSChaoyong He uint32_t tmp; 295610bf14bSChaoyong He uint32_t value; 296610bf14bSChaoyong He struct nfp_cpp *cpp = mutex->cpp; 297c7e9729dSAlejandro Lucero uint32_t mur = NFP_CPP_ID(mutex->target, 3, 0); /* atomic_read */ 298c7e9729dSAlejandro Lucero uint32_t muw = NFP_CPP_ID(mutex->target, 4, 0); /* atomic_write */ 299c7e9729dSAlejandro Lucero uint32_t mus = NFP_CPP_ID(mutex->target, 5, 3); /* test_set_imm */ 300c7e9729dSAlejandro Lucero 301c7e9729dSAlejandro Lucero if (mutex->depth > 0) { 302c7e9729dSAlejandro Lucero if (mutex->depth == MUTEX_DEPTH_MAX) 303b29d5df4SChaoyong He return -E2BIG; 304c7e9729dSAlejandro Lucero 305c7e9729dSAlejandro Lucero mutex->depth++; 306c7e9729dSAlejandro Lucero return 0; 307c7e9729dSAlejandro Lucero } 308c7e9729dSAlejandro Lucero 309c7e9729dSAlejandro Lucero /* Verify that the lock marker is not damaged */ 310c7e9729dSAlejandro Lucero err = nfp_cpp_readl(cpp, mur, mutex->address + 4, &key); 311*aa6b4a80SHuaxing Zhu if (err < 0) { 312*aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "Failed to read key."); 3134b6c8db9SChaoyong He return err; 314*aa6b4a80SHuaxing Zhu } 315c7e9729dSAlejandro Lucero 316*aa6b4a80SHuaxing Zhu if (key != mutex->key) { 317*aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "Key: %x is not same with the mutex: %x.", 318*aa6b4a80SHuaxing Zhu key, mutex->key); 3194b6c8db9SChaoyong He return -EPERM; 320*aa6b4a80SHuaxing Zhu } 321c7e9729dSAlejandro Lucero 322c7e9729dSAlejandro Lucero /* 323c7e9729dSAlejandro Lucero * Compare against the unlocked state, and if true, 324c7e9729dSAlejandro Lucero * write the interface id into the top 16 bits, and 325c7e9729dSAlejandro Lucero * mark as locked. 326c7e9729dSAlejandro Lucero */ 3274b6c8db9SChaoyong He value = nfp_mutex_locked(nfp_cpp_interface(cpp)); 328c7e9729dSAlejandro Lucero 329c7e9729dSAlejandro Lucero /* 330c7e9729dSAlejandro Lucero * We use test_set_imm here, as it implies a read 331c7e9729dSAlejandro Lucero * of the current state, and sets the bits in the 332c7e9729dSAlejandro Lucero * bytemask of the command to 1s. Since the mutex 333c7e9729dSAlejandro Lucero * is guaranteed to be 64-bit aligned, the bytemask 334c7e9729dSAlejandro Lucero * of this 32-bit command is ensured to be 8'b00001111, 335c7e9729dSAlejandro Lucero * which implies that the lower 4 bits will be set to 336c7e9729dSAlejandro Lucero * ones regardless of the initial state. 337c7e9729dSAlejandro Lucero * 338c7e9729dSAlejandro Lucero * Since this is a 'Readback' operation, with no Pull 339c7e9729dSAlejandro Lucero * data, we can treat this as a normal Push (read) 340c7e9729dSAlejandro Lucero * atomic, which returns the original value. 341c7e9729dSAlejandro Lucero */ 342c7e9729dSAlejandro Lucero err = nfp_cpp_readl(cpp, mus, mutex->address, &tmp); 343*aa6b4a80SHuaxing Zhu if (err < 0) { 344*aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "Failed to read tmp."); 3454b6c8db9SChaoyong He return err; 346*aa6b4a80SHuaxing Zhu } 347c7e9729dSAlejandro Lucero 348c7e9729dSAlejandro Lucero /* Was it unlocked? */ 3494b6c8db9SChaoyong He if (nfp_mutex_is_unlocked(tmp)) { 350c7e9729dSAlejandro Lucero /* 351c7e9729dSAlejandro Lucero * The read value can only be 0x....0000 in the unlocked state. 352c7e9729dSAlejandro Lucero * If there was another contending for this lock, then 353c7e9729dSAlejandro Lucero * the lock state would be 0x....000f 354c7e9729dSAlejandro Lucero * 3556d03aa61SChaoyong He * Write our owner ID into the lock. 356c7e9729dSAlejandro Lucero * While not strictly necessary, this helps with 357c7e9729dSAlejandro Lucero * debug and bookkeeping. 358c7e9729dSAlejandro Lucero */ 359c7e9729dSAlejandro Lucero err = nfp_cpp_writel(cpp, muw, mutex->address, value); 360*aa6b4a80SHuaxing Zhu if (err < 0) { 361*aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "Failed to write value."); 3624b6c8db9SChaoyong He return err; 363*aa6b4a80SHuaxing Zhu } 364c7e9729dSAlejandro Lucero 365c7e9729dSAlejandro Lucero mutex->depth = 1; 3664b6c8db9SChaoyong He return 0; 367c7e9729dSAlejandro Lucero } 368c7e9729dSAlejandro Lucero 369c7e9729dSAlejandro Lucero /* Already locked by us? Success! */ 370c7e9729dSAlejandro Lucero if (tmp == value) { 371c7e9729dSAlejandro Lucero mutex->depth = 1; 3724b6c8db9SChaoyong He return 0; 373c7e9729dSAlejandro Lucero } 374c7e9729dSAlejandro Lucero 3754b6c8db9SChaoyong He return nfp_mutex_is_locked(tmp) ? -EBUSY : -EINVAL; 3764b6c8db9SChaoyong He } 377c7e9729dSAlejandro Lucero 3784b6c8db9SChaoyong He /** 3794b6c8db9SChaoyong He * Release lock if held by local system. 3804b6c8db9SChaoyong He * Extreme care is advised, call only when no local lock users can exist. 3814b6c8db9SChaoyong He * 3824b6c8db9SChaoyong He * @param cpp 3834b6c8db9SChaoyong He * NFP CPP handle 3844b6c8db9SChaoyong He * @param target 3854b6c8db9SChaoyong He * NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU) 3864b6c8db9SChaoyong He * @param address 3874b6c8db9SChaoyong He * Offset into the address space of the NFP CPP target ID 3884b6c8db9SChaoyong He * 3894b6c8db9SChaoyong He * @return 3904b6c8db9SChaoyong He * - (0) if the lock was OK 3914b6c8db9SChaoyong He * - (1) if locked by us 3924b6c8db9SChaoyong He * - (-errno) on invalid mutex 3934b6c8db9SChaoyong He */ 3944b6c8db9SChaoyong He int 3954b6c8db9SChaoyong He nfp_cpp_mutex_reclaim(struct nfp_cpp *cpp, 3964b6c8db9SChaoyong He int target, 3974b6c8db9SChaoyong He uint64_t address) 3984b6c8db9SChaoyong He { 3994b6c8db9SChaoyong He int err; 4004b6c8db9SChaoyong He uint32_t tmp; 4014b6c8db9SChaoyong He uint16_t interface = nfp_cpp_interface(cpp); 4024b6c8db9SChaoyong He const uint32_t mur = NFP_CPP_ID(target, 3, 0); /* atomic_read */ 4034b6c8db9SChaoyong He const uint32_t muw = NFP_CPP_ID(target, 4, 0); /* atomic_write */ 4044b6c8db9SChaoyong He 4054b6c8db9SChaoyong He err = nfp_cpp_mutex_validate(interface, &target, address); 4064b6c8db9SChaoyong He if (err != 0) 407c7e9729dSAlejandro Lucero return err; 4084b6c8db9SChaoyong He 4094b6c8db9SChaoyong He /* Check lock */ 4104b6c8db9SChaoyong He err = nfp_cpp_readl(cpp, mur, address, &tmp); 4114b6c8db9SChaoyong He if (err < 0) 4124b6c8db9SChaoyong He return err; 4134b6c8db9SChaoyong He 4144b6c8db9SChaoyong He if (nfp_mutex_is_unlocked(tmp) || nfp_mutex_owner(tmp) != interface) 4154b6c8db9SChaoyong He return 0; 4164b6c8db9SChaoyong He 4174b6c8db9SChaoyong He /* Bust the lock */ 4184b6c8db9SChaoyong He err = nfp_cpp_writel(cpp, muw, address, nfp_mutex_unlocked(interface)); 4194b6c8db9SChaoyong He if (err < 0) 4204b6c8db9SChaoyong He return err; 4214b6c8db9SChaoyong He 4224b6c8db9SChaoyong He return 1; 423c7e9729dSAlejandro Lucero } 424