/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2018 Netronome Systems, Inc. * All rights reserved. */ #ifndef __NFP_CPP_H__ #define __NFP_CPP_H__ #include #include "nfp-common/nfp_platform.h" #include "nfp-common/nfp_resid.h" struct nfp_cpp_mutex; /* * NFP CPP handle */ struct nfp_cpp { uint32_t model; uint32_t interface; uint8_t *serial; int serial_len; void *priv; /* Mutex cache */ struct nfp_cpp_mutex *mutex_cache; const struct nfp_cpp_operations *op; /* * NFP-6xxx originating island IMB CPP Address Translation. CPP Target * ID is index into array. Values are obtained at runtime from local * island XPB CSRs. */ uint32_t imb_cat_table[16]; int driver_lock_needed; }; /* * NFP CPP device area handle */ struct nfp_cpp_area { struct nfp_cpp *cpp; char *name; unsigned long long offset; unsigned long size; /* Here follows the 'priv' part of nfp_cpp_area. */ }; /* * NFP CPP operations structure */ struct nfp_cpp_operations { /* Size of priv area in struct nfp_cpp_area */ size_t area_priv_size; /* Instance an NFP CPP */ int (*init)(struct nfp_cpp *cpp, struct rte_pci_device *dev); /* * Free the bus. * Called only once, during nfp_cpp_unregister() */ void (*free)(struct nfp_cpp *cpp); /* * Initialize a new NFP CPP area * NOTE: This is _not_ serialized */ int (*area_init)(struct nfp_cpp_area *area, uint32_t dest, unsigned long long address, unsigned long size); /* * Clean up a NFP CPP area before it is freed * NOTE: This is _not_ serialized */ void (*area_cleanup)(struct nfp_cpp_area *area); /* * Acquire resources for a NFP CPP area * Serialized */ int (*area_acquire)(struct nfp_cpp_area *area); /* * Release resources for a NFP CPP area * Serialized */ void (*area_release)(struct nfp_cpp_area *area); /* * Return a void IO pointer to a NFP CPP area * NOTE: This is _not_ serialized */ void *(*area_iomem)(struct nfp_cpp_area *area); void *(*area_mapped)(struct nfp_cpp_area *area); /* * Perform a read from a NFP CPP area * Serialized */ int (*area_read)(struct nfp_cpp_area *area, void *kernel_vaddr, unsigned long offset, unsigned int length); /* * Perform a write to a NFP CPP area * Serialized */ int (*area_write)(struct nfp_cpp_area *area, const void *kernel_vaddr, unsigned long offset, unsigned int length); }; /* * This should be the only external function the transport * module supplies */ const struct nfp_cpp_operations *nfp_cpp_transport_operations(void); /* * Set the model id * * @param cpp NFP CPP operations structure * @param model Model ID */ void nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model); /* * Set the private instance owned data of a nfp_cpp struct * * @param cpp NFP CPP operations structure * @param interface Interface ID */ void nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface); /* * Set the private instance owned data of a nfp_cpp struct * * @param cpp NFP CPP operations structure * @param serial NFP serial byte array * @param len Length of the serial byte array */ int nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial, size_t serial_len); /* * Set the private data of the nfp_cpp instance * * @param cpp NFP CPP operations structure * @return Opaque device pointer */ void nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv); /* * Return the private data of the nfp_cpp instance * * @param cpp NFP CPP operations structure * @return Opaque device pointer */ void *nfp_cpp_priv(struct nfp_cpp *cpp); /* * Get the privately allocated portion of a NFP CPP area handle * * @param cpp_area NFP CPP area handle * @return Pointer to the private area, or NULL on failure */ void *nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area); uint32_t __nfp_cpp_model_autodetect(struct nfp_cpp *cpp); /* * NFP CPP core interface for CPP clients. */ /* * Open a NFP CPP handle to a CPP device * * @param[in] id 0-based ID for the CPP interface to use * * @return NFP CPP handle, or NULL on failure (and set errno accordingly). */ struct nfp_cpp *nfp_cpp_from_device_name(struct rte_pci_device *dev, int driver_lock_needed); /* * Free a NFP CPP handle * * @param[in] cpp NFP CPP handle */ void nfp_cpp_free(struct nfp_cpp *cpp); #define NFP_CPP_MODEL_INVALID 0xffffffff /* * NFP_CPP_MODEL_CHIP_of - retrieve the chip ID from the model ID * * The chip ID is a 16-bit BCD+A-F encoding for the chip type. * * @param[in] model NFP CPP model id * @return NFP CPP chip id */ #define NFP_CPP_MODEL_CHIP_of(model) (((model) >> 16) & 0xffff) /* * NFP_CPP_MODEL_IS_6000 - Check for the NFP6000 family of devices * * NOTE: The NFP4000 series is considered as a NFP6000 series variant. * * @param[in] model NFP CPP model id * @return true if model is in the NFP6000 family, false otherwise. */ #define NFP_CPP_MODEL_IS_6000(model) \ ((NFP_CPP_MODEL_CHIP_of(model) >= 0x4000) && \ (NFP_CPP_MODEL_CHIP_of(model) < 0x7000)) /* * nfp_cpp_model - Retrieve the Model ID of the NFP * * @param[in] cpp NFP CPP handle * @return NFP CPP Model ID */ uint32_t nfp_cpp_model(struct nfp_cpp *cpp); /* * NFP Interface types - logical interface for this CPP connection 4 bits are * reserved for interface type. */ #define NFP_CPP_INTERFACE_TYPE_INVALID 0x0 #define NFP_CPP_INTERFACE_TYPE_PCI 0x1 #define NFP_CPP_INTERFACE_TYPE_ARM 0x2 #define NFP_CPP_INTERFACE_TYPE_RPC 0x3 #define NFP_CPP_INTERFACE_TYPE_ILA 0x4 /* * Construct a 16-bit NFP Interface ID * * Interface IDs consists of 4 bits of interface type, 4 bits of unit * identifier, and 8 bits of channel identifier. * * The NFP Interface ID is used in the implementation of NFP CPP API mutexes, * which use the MU Atomic CompareAndWrite operation - hence the limit to 16 * bits to be able to use the NFP Interface ID as a lock owner. * * @param[in] type NFP Interface Type * @param[in] unit Unit identifier for the interface type * @param[in] channel Channel identifier for the interface unit * @return Interface ID */ #define NFP_CPP_INTERFACE(type, unit, channel) \ ((((type) & 0xf) << 12) | \ (((unit) & 0xf) << 8) | \ (((channel) & 0xff) << 0)) /* * Get the interface type of a NFP Interface ID * @param[in] interface NFP Interface ID * @return NFP Interface ID's type */ #define NFP_CPP_INTERFACE_TYPE_of(interface) (((interface) >> 12) & 0xf) /* * Get the interface unit of a NFP Interface ID * @param[in] interface NFP Interface ID * @return NFP Interface ID's unit */ #define NFP_CPP_INTERFACE_UNIT_of(interface) (((interface) >> 8) & 0xf) /* * Get the interface channel of a NFP Interface ID * @param[in] interface NFP Interface ID * @return NFP Interface ID's channel */ #define NFP_CPP_INTERFACE_CHANNEL_of(interface) (((interface) >> 0) & 0xff) /* * Retrieve the Interface ID of the NFP * @param[in] cpp NFP CPP handle * @return NFP CPP Interface ID */ uint16_t nfp_cpp_interface(struct nfp_cpp *cpp); /* * Retrieve the NFP Serial Number (unique per NFP) * @param[in] cpp NFP CPP handle * @param[out] serial Pointer to reference the serial number array * * @return size of the NFP6000 serial number, in bytes */ int nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial); /* * Allocate a NFP CPP area handle, as an offset into a CPP ID * @param[in] cpp NFP CPP handle * @param[in] cpp_id NFP CPP ID * @param[in] address Offset into the NFP CPP ID address space * @param[in] size Size of the area to reserve * * @return NFP CPP handle, or NULL on failure (and set errno accordingly). */ struct nfp_cpp_area *nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, unsigned long size); /* * Allocate a NFP CPP area handle, as an offset into a CPP ID, by a named owner * @param[in] cpp NFP CPP handle * @param[in] cpp_id NFP CPP ID * @param[in] name Name of owner of the area * @param[in] address Offset into the NFP CPP ID address space * @param[in] size Size of the area to reserve * * @return NFP CPP handle, or NULL on failure (and set errno accordingly). */ struct nfp_cpp_area *nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, uint32_t cpp_id, const char *name, unsigned long long address, unsigned long size); /* * Free an allocated NFP CPP area handle * @param[in] area NFP CPP area handle */ void nfp_cpp_area_free(struct nfp_cpp_area *area); /* * Acquire the resources needed to access the NFP CPP area handle * * @param[in] area NFP CPP area handle * * @return 0 on success, -1 on failure (and set errno accordingly). */ int nfp_cpp_area_acquire(struct nfp_cpp_area *area); /* * Release the resources needed to access the NFP CPP area handle * * @param[in] area NFP CPP area handle */ void nfp_cpp_area_release(struct nfp_cpp_area *area); /* * Allocate, then acquire the resources needed to access the NFP CPP area handle * @param[in] cpp NFP CPP handle * @param[in] cpp_id NFP CPP ID * @param[in] address Offset into the NFP CPP ID address space * @param[in] size Size of the area to reserve * * @return NFP CPP handle, or NULL on failure (and set errno accordingly). */ struct nfp_cpp_area *nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, unsigned long size); /* * Release the resources, then free the NFP CPP area handle * @param[in] area NFP CPP area handle */ void nfp_cpp_area_release_free(struct nfp_cpp_area *area); uint8_t *nfp_cpp_map_area(struct nfp_cpp *cpp, int domain, int target, uint64_t addr, unsigned long size, struct nfp_cpp_area **area); /* * Return an IO pointer to the beginning of the NFP CPP area handle. The area * must be acquired with 'nfp_cpp_area_acquire()' before calling this operation. * * @param[in] area NFP CPP area handle * * @return Pointer to IO memory, or NULL on failure (and set errno accordingly). */ void *nfp_cpp_area_mapped(struct nfp_cpp_area *area); /* * Read from a NFP CPP area handle into a buffer. The area must be acquired with * 'nfp_cpp_area_acquire()' before calling this operation. * * @param[in] area NFP CPP area handle * @param[in] offset Offset into the area * @param[in] buffer Location of buffer to receive the data * @param[in] length Length of the data to read * * @return bytes read on success, -1 on failure (and set errno accordingly). * */ int nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset, void *buffer, size_t length); /* * Write to a NFP CPP area handle from a buffer. The area must be acquired with * 'nfp_cpp_area_acquire()' before calling this operation. * * @param[in] area NFP CPP area handle * @param[in] offset Offset into the area * @param[in] buffer Location of buffer that holds the data * @param[in] length Length of the data to read * * @return bytes written on success, -1 on failure (and set errno accordingly). */ int nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset, const void *buffer, size_t length); /* * nfp_cpp_area_iomem() - get IOMEM region for CPP area * @area: CPP area handle * * Returns an iomem pointer for use with readl()/writel() style operations. * * NOTE: Area must have been locked down with an 'acquire'. * * Return: pointer to the area, or NULL */ void *nfp_cpp_area_iomem(struct nfp_cpp_area *area); /* * Verify that IO can be performed on an offset in an area * * @param[in] area NFP CPP area handle * @param[in] offset Offset into the area * @param[in] size Size of region to validate * * @return 0 on success, -1 on failure (and set errno accordingly). */ int nfp_cpp_area_check_range(struct nfp_cpp_area *area, unsigned long long offset, unsigned long size); /* * Get the NFP CPP handle that is the parent of a NFP CPP area handle * * @param cpp_area NFP CPP area handle * @return NFP CPP handle */ struct nfp_cpp *nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area); /* * Get the name passed during allocation of the NFP CPP area handle * * @param cpp_area NFP CPP area handle * @return Pointer to the area's name */ const char *nfp_cpp_area_name(struct nfp_cpp_area *cpp_area); /* * Read a block of data from a NFP CPP ID * * @param[in] cpp NFP CPP handle * @param[in] cpp_id NFP CPP ID * @param[in] address Offset into the NFP CPP ID address space * @param[in] kernel_vaddr Buffer to copy read data to * @param[in] length Size of the area to reserve * * @return bytes read on success, -1 on failure (and set errno accordingly). */ int nfp_cpp_read(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, void *kernel_vaddr, size_t length); /* * Write a block of data to a NFP CPP ID * * @param[in] cpp NFP CPP handle * @param[in] cpp_id NFP CPP ID * @param[in] address Offset into the NFP CPP ID address space * @param[in] kernel_vaddr Buffer to copy write data from * @param[in] length Size of the area to reserve * * @return bytes written on success, -1 on failure (and set errno accordingly). */ int nfp_cpp_write(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, const void *kernel_vaddr, size_t length); /* * Fill a NFP CPP area handle and offset with a value * * @param[in] area NFP CPP area handle * @param[in] offset Offset into the NFP CPP ID address space * @param[in] value 32-bit value to fill area with * @param[in] length Size of the area to reserve * * @return bytes written on success, -1 on failure (and set errno accordingly). */ int nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset, uint32_t value, size_t length); /* * Read a single 32-bit value from a NFP CPP area handle * * @param area NFP CPP area handle * @param offset offset into NFP CPP area handle * @param value output value * * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this * operation. * * NOTE: offset must be 32-bit aligned. * * @return 0 on success, or -1 on error (and set errno accordingly). */ int nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset, uint32_t *value); /* * Write a single 32-bit value to a NFP CPP area handle * * @param area NFP CPP area handle * @param offset offset into NFP CPP area handle * @param value value to write * * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this * operation. * * NOTE: offset must be 32-bit aligned. * * @return 0 on success, or -1 on error (and set errno accordingly). */ int nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset, uint32_t value); /* * Read a single 64-bit value from a NFP CPP area handle * * @param area NFP CPP area handle * @param offset offset into NFP CPP area handle * @param value output value * * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this * operation. * * NOTE: offset must be 64-bit aligned. * * @return 0 on success, or -1 on error (and set errno accordingly). */ int nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset, uint64_t *value); /* * Write a single 64-bit value to a NFP CPP area handle * * @param area NFP CPP area handle * @param offset offset into NFP CPP area handle * @param value value to write * * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this * operation. * * NOTE: offset must be 64-bit aligned. * * @return 0 on success, or -1 on error (and set errno accordingly). */ int nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset, uint64_t value); /* * Write a single 32-bit value on the XPB bus * * @param cpp NFP CPP device handle * @param xpb_tgt XPB target and address * @param value value to write * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t value); /* * Read a single 32-bit value from the XPB bus * * @param cpp NFP CPP device handle * @param xpb_tgt XPB target and address * @param value output value * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t *value); /* * Modify bits of a 32-bit value from the XPB bus * * @param cpp NFP CPP device handle * @param xpb_tgt XPB target and address * @param mask mask of bits to alter * @param value value to modify * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask, uint32_t value); /* * Modify bits of a 32-bit value from the XPB bus * * @param cpp NFP CPP device handle * @param xpb_tgt XPB target and address * @param mask mask of bits to alter * @param value value to monitor for * @param timeout_us maximum number of us to wait (-1 for forever) * * @return >= 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask, uint32_t value, int timeout_us); /* * Read a 32-bit word from a NFP CPP ID * * @param cpp NFP CPP handle * @param cpp_id NFP CPP ID * @param address offset into the NFP CPP ID address space * @param value output value * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, uint32_t *value); /* * Write a 32-bit value to a NFP CPP ID * * @param cpp NFP CPP handle * @param cpp_id NFP CPP ID * @param address offset into the NFP CPP ID address space * @param value value to write * * @return 0 on success, or -1 on failure (and set errno accordingly). * */ int nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, uint32_t value); /* * Read a 64-bit work from a NFP CPP ID * * @param cpp NFP CPP handle * @param cpp_id NFP CPP ID * @param address offset into the NFP CPP ID address space * @param value output value * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, uint64_t *value); /* * Write a 64-bit value to a NFP CPP ID * * @param cpp NFP CPP handle * @param cpp_id NFP CPP ID * @param address offset into the NFP CPP ID address space * @param value value to write * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, uint64_t value); /* * Initialize a mutex location * 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. * * @param cpp NFP CPP handle * @param target NFP CPP target ID * @param address Offset into the address space of the NFP CPP target ID * @param key_id Unique 32-bit value for this mutex * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_cpp_mutex_init(struct nfp_cpp *cpp, int target, unsigned long long address, uint32_t key_id); /* * Create a mutex handle from an address controlled by a MU Atomic engine * * 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. * * @param cpp NFP CPP handle * @param target NFP CPP target ID * @param address Offset into the address space of the NFP CPP target ID * @param key_id 32-bit unique key (must match the key at this location) * * @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, uint32_t key_id); /* * Get the NFP CPP handle the mutex was created with * * @param mutex NFP mutex handle * @return NFP CPP handle */ struct nfp_cpp *nfp_cpp_mutex_cpp(struct nfp_cpp_mutex *mutex); /* * Get the mutex key * * @param mutex NFP mutex handle * @return Mutex key */ uint32_t nfp_cpp_mutex_key(struct nfp_cpp_mutex *mutex); /* * Get the mutex owner * * @param mutex NFP mutex handle * @return Interface ID of the mutex owner * * NOTE: This is for debug purposes ONLY - the owner may change at any time, * unless it has been locked by this NFP CPP handle. */ uint16_t nfp_cpp_mutex_owner(struct nfp_cpp_mutex *mutex); /* * Get the mutex target * * @param mutex NFP mutex handle * @return Mutex CPP target (ie NFP_CPP_TARGET_MU) */ int nfp_cpp_mutex_target(struct nfp_cpp_mutex *mutex); /* * Get the mutex address * * @param mutex NFP mutex handle * @return Mutex CPP address */ uint64_t nfp_cpp_mutex_address(struct nfp_cpp_mutex *mutex); /* * Free a mutex handle - does not alter the lock state * * @param mutex NFP CPP Mutex handle */ void nfp_cpp_mutex_free(struct nfp_cpp_mutex *mutex); /* * Lock a mutex handle, using the NFP MU Atomic Engine * * @param mutex NFP CPP Mutex handle * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex); /* * Unlock a mutex handle, using the NFP MU Atomic Engine * * @param mutex NFP CPP Mutex handle * * @return 0 on success, or -1 on failure (and set errno accordingly). */ int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex); /* * Attempt to lock a mutex handle, using the NFP MU Atomic Engine * * @param mutex NFP CPP Mutex handle * @return 0 if the lock succeeded, -1 on failure (and errno set * appropriately). */ int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex); #endif /* !__NFP_CPP_H__ */