// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) /* Copyright (C) 2015-2018 Netronome Systems, Inc. */ #include <linux/delay.h> #include <linux/device.h> #include <linux/jiffies.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/wait.h> #include "nfp_cpp.h" #include "nfp6000/nfp6000.h" struct nfp_cpp_mutex { … }; static u32 nfp_mutex_locked(u16 interface) { … } static u32 nfp_mutex_unlocked(u16 interface) { … } static u32 nfp_mutex_owner(u32 val) { … } static bool nfp_mutex_is_locked(u32 val) { … } static bool nfp_mutex_is_unlocked(u32 val) { … } /* If you need more than 65536 recursive locks, please rethink your code. */ #define NFP_MUTEX_DEPTH_MAX … static int nfp_cpp_mutex_validate(u16 interface, int *target, unsigned long long address) { … } /** * nfp_cpp_mutex_init() - Initialize a mutex location * @cpp: NFP CPP handle * @target: NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU) * @address: Offset into the address space of the NFP CPP target ID * @key: Unique 32-bit value for this mutex * * The CPP target:address must point to a 64-bit aligned location, and * will initialize 64 bits of data at the location. * * This creates the initial mutex state, as locked by this * nfp_cpp_interface(). * * This function should only be called when setting up * the initial lock state upon boot-up of the system. * * Return: 0 on success, or -errno on failure */ int nfp_cpp_mutex_init(struct nfp_cpp *cpp, int target, unsigned long long address, u32 key) { … } /** * nfp_cpp_mutex_alloc() - Create a mutex handle * @cpp: NFP CPP handle * @target: NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU) * @address: Offset into the address space of the NFP CPP target ID * @key: 32-bit unique key (must match the key at this location) * * The CPP target:address must point to a 64-bit aligned location, and * reserve 64 bits of data at the location for use by the handle. * * Only target/address pairs that point to entities that support the * MU Atomic Engine's CmpAndSwap32 command are supported. * * Return: A non-NULL struct nfp_cpp_mutex * on success, NULL on failure. */ struct nfp_cpp_mutex *nfp_cpp_mutex_alloc(struct nfp_cpp *cpp, int target, unsigned long long address, u32 key) { … } /** * nfp_cpp_mutex_free() - Free a mutex handle - does not alter the lock state * @mutex: NFP CPP Mutex handle */ void nfp_cpp_mutex_free(struct nfp_cpp_mutex *mutex) { … } /** * nfp_cpp_mutex_lock() - Lock a mutex handle, using the NFP MU Atomic Engine * @mutex: NFP CPP Mutex handle * * Return: 0 on success, or -errno on failure */ int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex) { … } /** * nfp_cpp_mutex_unlock() - Unlock a mutex handle, using the MU Atomic Engine * @mutex: NFP CPP Mutex handle * * Return: 0 on success, or -errno on failure */ int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex) { … } /** * nfp_cpp_mutex_trylock() - Attempt to lock a mutex handle * @mutex: NFP CPP Mutex handle * * Return: 0 if the lock succeeded, -errno on failure */ int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex) { … } /** * nfp_cpp_mutex_reclaim() - Unlock mutex if held by local endpoint * @cpp: NFP CPP handle * @target: NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU) * @address: Offset into the address space of the NFP CPP target ID * * Release lock if held by local system. Extreme care is advised, call only * when no local lock users can exist. * * Return: 0 if the lock was OK, 1 if locked by us, -errno on invalid mutex */ int nfp_cpp_mutex_reclaim(struct nfp_cpp *cpp, int target, unsigned long long address) { … }