b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /** |
| 2 | * rwnx_ipc_utils.h |
| 3 | * |
| 4 | * IPC utility function declarations |
| 5 | * |
| 6 | * Copyright (C) RivieraWaves 2012-2021 |
| 7 | */ |
| 8 | #ifndef _RWNX_IPC_UTILS_H_ |
| 9 | #define _RWNX_IPC_UTILS_H_ |
| 10 | |
| 11 | #include <linux/dma-mapping.h> |
| 12 | #include <linux/dmapool.h> |
| 13 | #include <linux/skbuff.h> |
| 14 | #include "aicwf_debug.h" |
| 15 | #include "lmac_msg.h" |
| 16 | #if 0 |
| 17 | #ifdef CONFIG_RWNX_DBG |
| 18 | /* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */ |
| 19 | #define RWNX_DBG printk |
| 20 | #else |
| 21 | #define RWNX_DBG(a...) do {} while (0) |
| 22 | #endif |
| 23 | |
| 24 | #define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ |
| 25 | #endif |
| 26 | |
| 27 | #ifdef ANDROID_PLATFORM |
| 28 | #define HIGH_KERNEL_VERSION KERNEL_VERSION(5, 15, 41) |
| 29 | #else |
| 30 | #define HIGH_KERNEL_VERSION KERNEL_VERSION(6, 0, 0) |
| 31 | #endif |
| 32 | |
| 33 | enum rwnx_dev_flag { |
| 34 | RWNX_DEV_RESTARTING, |
| 35 | RWNX_DEV_STACK_RESTARTING, |
| 36 | RWNX_DEV_STARTED, |
| 37 | RWNX_DEV_ADDING_STA, |
| 38 | }; |
| 39 | |
| 40 | struct rwnx_hw; |
| 41 | struct rwnx_sta; |
| 42 | struct rwnx_sw_txhdr; |
| 43 | |
| 44 | /** |
| 45 | * struct rwnx_ipc_buf - Generic IPC buffer |
| 46 | * An IPC buffer is a buffer allocated in host memory and "DMA mapped" to be |
| 47 | * accessible by the firmware. |
| 48 | * |
| 49 | * @addr: Host address of the buffer. If NULL other field are invalid |
| 50 | * @dma_addr: DMA address of the buffer. |
| 51 | * @size: Size, in bytes, of the buffer |
| 52 | */ |
| 53 | struct rwnx_ipc_buf |
| 54 | { |
| 55 | void *addr; |
| 56 | dma_addr_t dma_addr; |
| 57 | size_t size; |
| 58 | }; |
| 59 | |
| 60 | /** |
| 61 | * struct rwnx_ipc_buf_pool - Generic pool of IPC buffers |
| 62 | * |
| 63 | * @nb: Number of buffers currently allocated in the pool |
| 64 | * @buffers: Array of buffers (size of array is @nb) |
| 65 | * @pool: DMA pool in which buffers have been allocated |
| 66 | */ |
| 67 | struct rwnx_ipc_buf_pool { |
| 68 | int nb; |
| 69 | struct rwnx_ipc_buf *buffers; |
| 70 | struct dma_pool *pool; |
| 71 | }; |
| 72 | |
| 73 | /** |
| 74 | * struct rwnx_ipc_dbgdump - IPC buffer for debug dump |
| 75 | * |
| 76 | * @mutex: Mutex to protect access to debug dump |
| 77 | * @buf: IPC buffer |
| 78 | */ |
| 79 | struct rwnx_ipc_dbgdump { |
| 80 | struct mutex mutex; |
| 81 | struct rwnx_ipc_buf buf; |
| 82 | }; |
| 83 | |
| 84 | static const u32 rwnx_tx_pattern = 0xCAFEFADE; |
| 85 | |
| 86 | /* |
| 87 | * Maximum Length of Radiotap header vendor specific data(in bytes) |
| 88 | */ |
| 89 | #define RADIOTAP_HDR_VEND_MAX_LEN 16 |
| 90 | |
| 91 | /* |
| 92 | * Maximum Radiotap Header Length without vendor specific data (in bytes) |
| 93 | */ |
| 94 | #define RADIOTAP_HDR_MAX_LEN 80 |
| 95 | |
| 96 | /* |
| 97 | * Unsupported HT Frame data length (in bytes) |
| 98 | */ |
| 99 | #define UNSUP_RX_VEC_DATA_LEN 2 |
| 100 | |
| 101 | |
| 102 | /** |
| 103 | * IPC environment control |
| 104 | */ |
| 105 | int rwnx_ipc_init(struct rwnx_hw *rwnx_hw, u8 *shared_ram); |
| 106 | void rwnx_ipc_deinit(struct rwnx_hw *rwnx_hw); |
| 107 | void rwnx_ipc_start(struct rwnx_hw *rwnx_hw); |
| 108 | void rwnx_ipc_stop(struct rwnx_hw *rwnx_hw); |
| 109 | void rwnx_ipc_msg_push(struct rwnx_hw *rwnx_hw, void *msg_buf, uint16_t len); |
| 110 | |
| 111 | /** |
| 112 | * IPC buffer management |
| 113 | */ |
| 114 | int rwnx_ipc_buf_alloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, |
| 115 | size_t buf_size, enum dma_data_direction dir, const void *init); |
| 116 | /** |
| 117 | * rwnx_ipc_buf_e2a_alloc() - Allocate an Embedded To Application Input IPC buffer |
| 118 | * |
| 119 | * @rwnx_hw: Main driver data |
| 120 | * @buf: IPC buffer structure to store I{PC buffer information |
| 121 | * @buf_size: Size of the Buffer to allocate |
| 122 | * @return: 0 on success and != 0 otherwise |
| 123 | */ |
| 124 | static inline int rwnx_ipc_buf_e2a_alloc(struct rwnx_hw *rwnx_hw, |
| 125 | struct rwnx_ipc_buf *buf, |
| 126 | size_t buf_size) |
| 127 | { |
| 128 | return rwnx_ipc_buf_alloc(rwnx_hw, buf, buf_size, DMA_FROM_DEVICE, NULL); |
| 129 | } |
| 130 | |
| 131 | /** |
| 132 | * rwnx_ipc_buf_a2e_alloc() - Allocate an Application to Embedded Output IPC buffer |
| 133 | * |
| 134 | * @rwnx_hw: Main driver data |
| 135 | * @buf: IPC buffer structure to store I{PC buffer information |
| 136 | * @buf_size: Size of the Buffer to allocate |
| 137 | * @buf_data: Initialization data for the buffer. Must be at least |
| 138 | * @buf_size long |
| 139 | * @return: 0 on success and != 0 otherwise |
| 140 | */ |
| 141 | static inline int rwnx_ipc_buf_a2e_alloc(struct rwnx_hw *rwnx_hw, |
| 142 | struct rwnx_ipc_buf *buf, |
| 143 | size_t buf_size, const void *buf_data) |
| 144 | { |
| 145 | return rwnx_ipc_buf_alloc(rwnx_hw, buf, buf_size, DMA_TO_DEVICE, buf_data); |
| 146 | } |
| 147 | void rwnx_ipc_buf_dealloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf); |
| 148 | int rwnx_ipc_buf_a2e_init(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, |
| 149 | void *data, size_t buf_size); |
| 150 | |
| 151 | void rwnx_ipc_buf_release(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, |
| 152 | enum dma_data_direction dir); |
| 153 | |
| 154 | /** |
| 155 | * rwnx_ipc_buf_e2a_release() - Release DMA mapping for an Application to Embedded IPC buffer |
| 156 | * |
| 157 | * @rwnx_hw: Main driver structure |
| 158 | * @buf: IPC buffer to release |
| 159 | * |
| 160 | * An A2E buffer is realeased when it has been read by the embbeded side. This is |
| 161 | * used before giving back a buffer to upper layer, or before deleting a buffer |
| 162 | * when rwnx_ipc_buf_dealloc() cannot be used. |
| 163 | */ |
| 164 | static inline void rwnx_ipc_buf_a2e_release(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf) |
| 165 | { |
| 166 | rwnx_ipc_buf_release(rwnx_hw, buf, DMA_TO_DEVICE); |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * rwnx_ipc_buf_e2a_release() - Release DMA mapping for an Embedded to Application IPC buffer |
| 171 | * |
| 172 | * @rwnx_hw: Main driver structure |
| 173 | * @buf: IPC buffer to release |
| 174 | * |
| 175 | * An E2A buffer is released when it has been updated by the embedded and it's ready |
| 176 | * to be forwarded to upper layer (i.e. out of the driver) or to be deleted and |
| 177 | * rwnx_ipc_buf_dealloc() cannot be used. |
| 178 | * |
| 179 | * Note: This function has the side effect to synchronize the buffer for the host so no need to |
| 180 | * call rwnx_ipc_buf_e2a_sync(). |
| 181 | */ |
| 182 | static inline void rwnx_ipc_buf_e2a_release(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf) |
| 183 | { |
| 184 | rwnx_ipc_buf_release(rwnx_hw, buf, DMA_FROM_DEVICE); |
| 185 | } |
| 186 | |
| 187 | void rwnx_ipc_buf_e2a_sync(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, size_t len); |
| 188 | void rwnx_ipc_buf_e2a_sync_back(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf, size_t len); |
| 189 | |
| 190 | /** |
| 191 | * IPC rx buffer management |
| 192 | */ |
| 193 | int rwnx_ipc_rxbuf_init(struct rwnx_hw *rwnx_hw, uint32_t rx_bufsz); |
| 194 | int rwnx_ipc_rxbuf_alloc(struct rwnx_hw *rwnx_hw); |
| 195 | void rwnx_ipc_rxbuf_dealloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf); |
| 196 | void rwnx_ipc_rxbuf_repush(struct rwnx_hw *rwnx_hw, |
| 197 | struct rwnx_ipc_buf *buf); |
| 198 | #ifdef CONFIG_RWNX_FULLMAC |
| 199 | void rwnx_ipc_rxdesc_repush(struct rwnx_hw *rwnx_hw, |
| 200 | struct rwnx_ipc_buf *buf); |
| 201 | struct rwnx_ipc_buf *rwnx_ipc_rxbuf_from_hostid(struct rwnx_hw *rwnx_hw, u32 hostid); |
| 202 | #endif /* CONFIG_RWNX_FULLMAC */ |
| 203 | |
| 204 | int rwnx_ipc_unsuprxvec_alloc(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf); |
| 205 | void rwnx_ipc_unsuprxvec_repush(struct rwnx_hw *rwnx_hw, struct rwnx_ipc_buf *buf); |
| 206 | |
| 207 | /** |
| 208 | * IPC TX specific functions |
| 209 | */ |
| 210 | #if 0 |
| 211 | void rwnx_ipc_txdesc_push(struct rwnx_hw *rwnx_hw, struct rwnx_sw_txhdr *sw_txhdr, |
| 212 | struct sk_buff *hostid, int hw_queue); |
| 213 | #endif |
| 214 | struct sk_buff *rwnx_ipc_get_skb_from_cfm(struct rwnx_hw *rwnx_hw, |
| 215 | struct rwnx_ipc_buf *buf); |
| 216 | void rwnx_ipc_sta_buffer_init(struct rwnx_hw *rwnx_hw, int sta_idx); |
| 217 | void rwnx_ipc_sta_buffer(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, int tid, int size); |
| 218 | void rwnx_ipc_tx_drain(struct rwnx_hw *rwnx_hw); |
| 219 | bool rwnx_ipc_tx_pending(struct rwnx_hw *rwnx_hw); |
| 220 | |
| 221 | /** |
| 222 | * FW dump handler / trace |
| 223 | */ |
| 224 | void rwnx_error_ind(struct rwnx_hw *rwnx_hw); |
| 225 | void rwnx_umh_done(struct rwnx_hw *rwnx_hw); |
| 226 | void *rwnx_ipc_fw_trace_desc_get(struct rwnx_hw *rwnx_hw); |
| 227 | |
| 228 | #endif /* _RWNX_IPC_UTILS_H_ */ |
| 229 | |