blob: d2d089b668c038111b3f611d53ee28e7b378d746 [file] [log] [blame]
/**
* rwnx_ipc_utils.h
*
* IPC utility function declarations
*
* Copyright (C) RivieraWaves 2012-2021
*/
#ifndef _RWNX_IPC_UTILS_H_
#define _RWNX_IPC_UTILS_H_
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/skbuff.h>
#include "aicwf_debug.h"
#include "lmac_msg.h"
#if 0
#ifdef CONFIG_RWNX_DBG
/* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */
#define RWNX_DBG printk
#else
#define RWNX_DBG(a...) do {} while (0)
#endif
#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__
#endif
#ifdef ANDROID_PLATFORM
#define HIGH_KERNEL_VERSION KERNEL_VERSION(5, 15, 41)
#else
#define HIGH_KERNEL_VERSION KERNEL_VERSION(6, 0, 0)
#endif
enum rwnx_dev_flag {
RWNX_DEV_RESTARTING,
RWNX_DEV_STACK_RESTARTING,
RWNX_DEV_STARTED,
RWNX_DEV_ADDING_STA,
};
struct rwnx_hw;
struct rwnx_sta;
struct rwnx_sw_txhdr;
/**
* struct rwnx_ipc_buf - Generic IPC buffer
* An IPC buffer is a buffer allocated in host memory and "DMA mapped" to be
* accessible by the firmware.
*
* @addr: Host address of the buffer. If NULL other field are invalid
* @dma_addr: DMA address of the buffer.
* @size: Size, in bytes, of the buffer
*/
struct rwnx_ipc_buf
{
void *addr;
dma_addr_t dma_addr;
size_t size;
};
/**
* struct rwnx_ipc_buf_pool - Generic pool of IPC buffers
*
* @nb: Number of buffers currently allocated in the pool
* @buffers: Array of buffers (size of array is @nb)
* @pool: DMA pool in which buffers have been allocated
*/
struct rwnx_ipc_buf_pool {
int nb;
struct rwnx_ipc_buf *buffers;
struct dma_pool *pool;
};
/**
* struct rwnx_ipc_dbgdump - IPC buffer for debug dump
*
* @mutex: Mutex to protect access to debug dump
* @buf: IPC buffer
*/
struct rwnx_ipc_dbgdump {
struct mutex mutex;
struct rwnx_ipc_buf buf;
};
static const u32 rwnx_tx_pattern = 0xCAFEFADE;
/*
* Maximum Length of Radiotap header vendor specific data(in bytes)
*/
#define RADIOTAP_HDR_VEND_MAX_LEN 16
/*
* Maximum Radiotap Header Length without vendor specific data (in bytes)
*/
#define RADIOTAP_HDR_MAX_LEN 80
/*
* Unsupported HT Frame data length (in bytes)
*/
#define UNSUP_RX_VEC_DATA_LEN 2
/**
* IPC environment control
*/
int rwnx_ipc_init(struct rwnx_hw *rwnx_hw, u8 *shared_ram);
void rwnx_ipc_deinit(struct rwnx_hw *rwnx_hw);
void rwnx_ipc_start(struct rwnx_hw *rwnx_hw);
void rwnx_ipc_stop(struct rwnx_hw *rwnx_hw);
void rwnx_ipc_msg_push(struct rwnx_hw *rwnx_hw, void *msg_buf, uint16_t len);
/**
* IPC buffer management
*/
int rwnx_ipc_buf_alloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf,
size_t buf_size, enum dma_data_direction dir, const void *init);
/**
* rwnx_ipc_buf_e2a_alloc() - Allocate an Embedded To Application Input IPC buffer
*
* @rwnx_hw: Main driver data
* @buf: IPC buffer structure to store I{PC buffer information
* @buf_size: Size of the Buffer to allocate
* @return: 0 on success and != 0 otherwise
*/
static inline int rwnx_ipc_buf_e2a_alloc(struct rwnx_hw *rwnx_hw,
struct rwnx_ipc_buf *buf,
size_t buf_size)
{
return rwnx_ipc_buf_alloc(rwnx_hw, buf, buf_size, DMA_FROM_DEVICE, NULL);
}
/**
* rwnx_ipc_buf_a2e_alloc() - Allocate an Application to Embedded Output IPC buffer
*
* @rwnx_hw: Main driver data
* @buf: IPC buffer structure to store I{PC buffer information
* @buf_size: Size of the Buffer to allocate
* @buf_data: Initialization data for the buffer. Must be at least
* @buf_size long
* @return: 0 on success and != 0 otherwise
*/
static inline int rwnx_ipc_buf_a2e_alloc(struct rwnx_hw *rwnx_hw,
struct rwnx_ipc_buf *buf,
size_t buf_size, const void *buf_data)
{
return rwnx_ipc_buf_alloc(rwnx_hw, buf, buf_size, DMA_TO_DEVICE, buf_data);
}
void rwnx_ipc_buf_dealloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf);
int rwnx_ipc_buf_a2e_init(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf,
void *data, size_t buf_size);
void rwnx_ipc_buf_release(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf,
enum dma_data_direction dir);
/**
* rwnx_ipc_buf_e2a_release() - Release DMA mapping for an Application to Embedded IPC buffer
*
* @rwnx_hw: Main driver structure
* @buf: IPC buffer to release
*
* An A2E buffer is realeased when it has been read by the embbeded side. This is
* used before giving back a buffer to upper layer, or before deleting a buffer
* when rwnx_ipc_buf_dealloc() cannot be used.
*/
static inline void rwnx_ipc_buf_a2e_release(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf)
{
rwnx_ipc_buf_release(rwnx_hw, buf, DMA_TO_DEVICE);
}
/**
* rwnx_ipc_buf_e2a_release() - Release DMA mapping for an Embedded to Application IPC buffer
*
* @rwnx_hw: Main driver structure
* @buf: IPC buffer to release
*
* An E2A buffer is released when it has been updated by the embedded and it's ready
* to be forwarded to upper layer (i.e. out of the driver) or to be deleted and
* rwnx_ipc_buf_dealloc() cannot be used.
*
* Note: This function has the side effect to synchronize the buffer for the host so no need to
* call rwnx_ipc_buf_e2a_sync().
*/
static inline void rwnx_ipc_buf_e2a_release(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf)
{
rwnx_ipc_buf_release(rwnx_hw, buf, DMA_FROM_DEVICE);
}
void rwnx_ipc_buf_e2a_sync(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, size_t len);
void rwnx_ipc_buf_e2a_sync_back(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, size_t len);
/**
* IPC rx buffer management
*/
int rwnx_ipc_rxbuf_init(struct rwnx_hw *rwnx_hw, uint32_t rx_bufsz);
int rwnx_ipc_rxbuf_alloc(struct rwnx_hw *rwnx_hw);
void rwnx_ipc_rxbuf_dealloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf);
void rwnx_ipc_rxbuf_repush(struct rwnx_hw *rwnx_hw,
struct rwnx_ipc_buf *buf);
#ifdef CONFIG_RWNX_FULLMAC
void rwnx_ipc_rxdesc_repush(struct rwnx_hw *rwnx_hw,
struct rwnx_ipc_buf *buf);
struct rwnx_ipc_buf *rwnx_ipc_rxbuf_from_hostid(struct rwnx_hw *rwnx_hw, u32 hostid);
#endif /* CONFIG_RWNX_FULLMAC */
int rwnx_ipc_unsuprxvec_alloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf);
void rwnx_ipc_unsuprxvec_repush(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf);
/**
* IPC TX specific functions
*/
#if 0
void rwnx_ipc_txdesc_push(struct rwnx_hw *rwnx_hw, struct rwnx_sw_txhdr *sw_txhdr,
struct sk_buff *hostid, int hw_queue);
#endif
struct sk_buff *rwnx_ipc_get_skb_from_cfm(struct rwnx_hw *rwnx_hw,
struct rwnx_ipc_buf *buf);
void rwnx_ipc_sta_buffer_init(struct rwnx_hw *rwnx_hw, int sta_idx);
void rwnx_ipc_sta_buffer(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, int tid, int size);
void rwnx_ipc_tx_drain(struct rwnx_hw *rwnx_hw);
bool rwnx_ipc_tx_pending(struct rwnx_hw *rwnx_hw);
/**
* FW dump handler / trace
*/
void rwnx_error_ind(struct rwnx_hw *rwnx_hw);
void rwnx_umh_done(struct rwnx_hw *rwnx_hw);
void *rwnx_ipc_fw_trace_desc_get(struct rwnx_hw *rwnx_hw);
#endif /* _RWNX_IPC_UTILS_H_ */