1 /* 2 * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 /** 29 * DOC: i_qdf_mem.h 30 * Linux-specific definitions for QDF memory API's 31 */ 32 33 #ifndef __I_QDF_MEM_H 34 #define __I_QDF_MEM_H 35 36 #ifdef __KERNEL__ 37 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17) 38 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) 39 #include <linux/autoconf.h> 40 #else 41 #include <generated/autoconf.h> 42 #endif 43 #endif 44 #include <linux/slab.h> 45 #include <linux/hardirq.h> 46 #include <linux/vmalloc.h> 47 #include <linux/pci.h> /* pci_alloc_consistent */ 48 #include <linux/cache.h> /* L1_CACHE_BYTES */ 49 50 #define __qdf_cache_line_sz L1_CACHE_BYTES 51 #if CONFIG_MCL 52 #include <cds_queue.h> 53 #else 54 #include <sys/queue.h> 55 #endif 56 #else 57 /* 58 * Provide dummy defs for kernel data types, functions, and enums 59 * used in this header file. 60 */ 61 #define GFP_KERNEL 0 62 #define GFP_ATOMIC 0 63 #define kzalloc(size, flags) NULL 64 #define vmalloc(size) NULL 65 #define kfree(buf) 66 #define vfree(buf) 67 #define pci_alloc_consistent(dev, size, paddr) NULL 68 #define __qdf_mempool_t void* 69 #define QDF_RET_IP NULL 70 #endif /* __KERNEL__ */ 71 #include <qdf_status.h> 72 73 #ifdef CONFIG_ARM_SMMU 74 #include <pld_common.h> 75 #include <asm/dma-iommu.h> 76 #include <linux/iommu.h> 77 #endif 78 79 #ifdef __KERNEL__ 80 typedef struct mempool_elem { 81 STAILQ_ENTRY(mempool_elem) mempool_entry; 82 } mempool_elem_t; 83 84 /** 85 * typedef __qdf_mempool_ctxt_t - Memory pool context 86 * @pool_id: pool identifier 87 * @flags: flags 88 * @elem_size: size of each pool element in bytes 89 * @pool_mem: pool_addr address of the pool created 90 * @mem_size: Total size of the pool in bytes 91 * @free_list: free pool list 92 * @lock: spinlock object 93 * @max_elem: Maximum number of elements in tha pool 94 * @free_cnt: Number of free elements available 95 */ 96 typedef struct __qdf_mempool_ctxt { 97 int pool_id; 98 u_int32_t flags; 99 size_t elem_size; 100 void *pool_mem; 101 u_int32_t mem_size; 102 103 STAILQ_HEAD(, mempool_elem) free_list; 104 spinlock_t lock; 105 u_int32_t max_elem; 106 u_int32_t free_cnt; 107 } __qdf_mempool_ctxt_t; 108 109 #endif /* __KERNEL__ */ 110 111 #define __qdf_align(a, mask) ALIGN(a, mask) 112 113 /* typedef for dma_data_direction */ 114 typedef enum dma_data_direction __dma_data_direction; 115 116 /** 117 * __qdf_dma_dir_to_os() - Convert DMA data direction to OS specific enum 118 * @dir: QDF DMA data direction 119 * 120 * Return: 121 * enum dma_data_direction 122 */ 123 static inline 124 enum dma_data_direction __qdf_dma_dir_to_os(qdf_dma_dir_t qdf_dir) 125 { 126 switch (qdf_dir) { 127 case QDF_DMA_BIDIRECTIONAL: 128 return DMA_BIDIRECTIONAL; 129 case QDF_DMA_TO_DEVICE: 130 return DMA_TO_DEVICE; 131 case QDF_DMA_FROM_DEVICE: 132 return DMA_FROM_DEVICE; 133 default: 134 return DMA_NONE; 135 } 136 } 137 138 139 /** 140 * __qdf_mem_map_nbytes_single - Map memory for DMA 141 * @osdev: pomter OS device context 142 * @buf: pointer to memory to be dma mapped 143 * @dir: DMA map direction 144 * @nbytes: number of bytes to be mapped. 145 * @phy_addr: ponter to recive physical address. 146 * 147 * Return: success/failure 148 */ 149 static inline uint32_t __qdf_mem_map_nbytes_single(qdf_device_t osdev, 150 void *buf, qdf_dma_dir_t dir, 151 int nbytes, 152 qdf_dma_addr_t *phy_addr) 153 { 154 /* assume that the OS only provides a single fragment */ 155 *phy_addr = dma_map_single(osdev->dev, buf, nbytes, 156 __qdf_dma_dir_to_os(dir)); 157 return dma_mapping_error(osdev->dev, *phy_addr) ? 158 QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; 159 } 160 161 /** 162 * __qdf_mem_unmap_nbytes_single() - un_map memory for DMA 163 * 164 * @osdev: pomter OS device context 165 * @phy_addr: physical address of memory to be dma unmapped 166 * @dir: DMA unmap direction 167 * @nbytes: number of bytes to be unmapped. 168 * 169 * Return - none 170 */ 171 static inline void __qdf_mem_unmap_nbytes_single(qdf_device_t osdev, 172 qdf_dma_addr_t phy_addr, 173 qdf_dma_dir_t dir, int nbytes) 174 { 175 dma_unmap_single(osdev->dev, phy_addr, nbytes, 176 __qdf_dma_dir_to_os(dir)); 177 } 178 #ifdef __KERNEL__ 179 180 typedef __qdf_mempool_ctxt_t *__qdf_mempool_t; 181 182 int __qdf_mempool_init(qdf_device_t osdev, __qdf_mempool_t *pool, int pool_cnt, 183 size_t pool_entry_size, u_int32_t flags); 184 void __qdf_mempool_destroy(qdf_device_t osdev, __qdf_mempool_t pool); 185 void *__qdf_mempool_alloc(qdf_device_t osdev, __qdf_mempool_t pool); 186 void __qdf_mempool_free(qdf_device_t osdev, __qdf_mempool_t pool, void *buf); 187 #define QDF_RET_IP ((void *)_RET_IP_) 188 189 #define __qdf_mempool_elem_size(_pool) ((_pool)->elem_size) 190 #endif 191 192 /** 193 * __qdf_mem_cmp() - memory compare 194 * @memory1: pointer to one location in memory to compare. 195 * @memory2: pointer to second location in memory to compare. 196 * @num_bytes: the number of bytes to compare. 197 * 198 * Function to compare two pieces of memory, similar to memcmp function 199 * in standard C. 200 * Return: 201 * int32_t - returns an int value that tells if the memory 202 * locations are equal or not equal. 203 * 0 -- equal 204 * < 0 -- *memory1 is less than *memory2 205 * > 0 -- *memory1 is bigger than *memory2 206 */ 207 static inline int32_t __qdf_mem_cmp(const void *memory1, const void *memory2, 208 uint32_t num_bytes) 209 { 210 return (int32_t) memcmp(memory1, memory2, num_bytes); 211 } 212 213 /** 214 * __qdf_mem_smmu_s1_enabled() - Return SMMU stage 1 translation enable status 215 * @osdev parent device instance 216 * 217 * Return: true if smmu s1 enabled, false if smmu s1 is bypassed 218 */ 219 static inline bool __qdf_mem_smmu_s1_enabled(qdf_device_t osdev) 220 { 221 return osdev->smmu_s1_enabled; 222 } 223 224 #ifdef CONFIG_ARM_SMMU 225 /** 226 * __qdf_mem_paddr_from_dmaaddr() - get actual physical address from dma_addr 227 * @osdev: parent device instance 228 * @dma_addr: dma_addr 229 * 230 * Get actual physical address from dma_addr based on SMMU enablement status. 231 * IF SMMU Stage 1 tranlation is enabled, DMA APIs return IO virtual address 232 * (IOVA) otherwise returns physical address. So get SMMU physical address 233 * mapping from IOVA. 234 * 235 * Return: dmaable physical address 236 */ 237 static inline unsigned long 238 __qdf_mem_paddr_from_dmaaddr(qdf_device_t osdev, 239 qdf_dma_addr_t dma_addr) 240 { 241 struct dma_iommu_mapping *mapping; 242 243 if (__qdf_mem_smmu_s1_enabled(osdev)) { 244 mapping = osdev->iommu_mapping; 245 if (mapping) 246 return iommu_iova_to_phys(mapping->domain, dma_addr); 247 } 248 249 return dma_addr; 250 } 251 #else 252 static inline unsigned long 253 __qdf_mem_paddr_from_dmaaddr(qdf_device_t osdev, 254 qdf_dma_addr_t dma_addr) 255 { 256 return dma_addr; 257 } 258 #endif 259 260 /** 261 * __qdf_os_mem_dma_get_sgtable() - Returns DMA memory scatter gather table 262 * @dev: device instace 263 * @sgt: scatter gather table pointer 264 * @cpu_addr: HLOS virtual address 265 * @dma_addr: dma/iova 266 * @size: allocated memory size 267 * 268 * Return: physical address 269 */ 270 static inline int 271 __qdf_os_mem_dma_get_sgtable(struct device *dev, void *sgt, void *cpu_addr, 272 qdf_dma_addr_t dma_addr, size_t size) 273 { 274 return dma_get_sgtable(dev, (struct sg_table *)sgt, cpu_addr, dma_addr, 275 size); 276 } 277 278 /** 279 * __qdf_mem_get_dma_addr() - Return dma addr based on SMMU translation status 280 * @osdev: parent device instance 281 * @mem_info: Pointer to allocated memory information 282 * 283 * Based on smmu stage 1 translation enablement status, return corresponding dma 284 * address from qdf_mem_info_t. If stage 1 translation enabled, return 285 * IO virtual address otherwise return physical address. 286 * 287 * Return: dma address 288 */ 289 static inline qdf_dma_addr_t __qdf_mem_get_dma_addr(qdf_device_t osdev, 290 qdf_mem_info_t *mem_info) 291 { 292 if (__qdf_mem_smmu_s1_enabled(osdev)) 293 return (qdf_dma_addr_t)mem_info->iova; 294 else 295 return (qdf_dma_addr_t)mem_info->pa; 296 } 297 298 /** 299 * __qdf_mem_get_dma_addr_ptr() - Return DMA address storage pointer 300 * @osdev: parent device instance 301 * @mem_info: Pointer to allocated memory information 302 * 303 * Based on smmu stage 1 translation enablement status, return corresponding 304 * dma address pointer from qdf_mem_info_t structure. If stage 1 translation 305 * enabled, return pointer to IO virtual address otherwise return pointer to 306 * physical address 307 * 308 * Return: dma address storage pointer 309 */ 310 static inline qdf_dma_addr_t * 311 __qdf_mem_get_dma_addr_ptr(qdf_device_t osdev, 312 qdf_mem_info_t *mem_info) 313 { 314 if (__qdf_mem_smmu_s1_enabled(osdev)) 315 return (qdf_dma_addr_t *)(&mem_info->iova); 316 else 317 return (qdf_dma_addr_t *)(&mem_info->pa); 318 } 319 320 /** 321 * __qdf_update_mem_map_table() - Update DMA memory map info 322 * @osdev: Parent device instance 323 * @mem_info: Pointer to shared memory information 324 * @dma_addr: dma address 325 * @mem_size: memory size allocated 326 * 327 * Store DMA shared memory information 328 * 329 * Return: none 330 */ 331 static inline void __qdf_update_mem_map_table(qdf_device_t osdev, 332 qdf_mem_info_t *mem_info, 333 qdf_dma_addr_t dma_addr, 334 uint32_t mem_size) 335 { 336 mem_info->pa = __qdf_mem_paddr_from_dmaaddr(osdev, dma_addr); 337 mem_info->iova = dma_addr; 338 mem_info->size = mem_size; 339 } 340 341 /** 342 * __qdf_mem_get_dma_size() - Return DMA memory size 343 * @osdev: parent device instance 344 * @mem_info: Pointer to allocated memory information 345 * 346 * Return: DMA memory size 347 */ 348 static inline uint32_t 349 __qdf_mem_get_dma_size(qdf_device_t osdev, 350 qdf_mem_info_t *mem_info) 351 { 352 return mem_info->size; 353 } 354 355 /** 356 * __qdf_mem_set_dma_size() - Set DMA memory size 357 * @osdev: parent device instance 358 * @mem_info: Pointer to allocated memory information 359 * @mem_size: memory size allocated 360 * 361 * Return: none 362 */ 363 static inline void 364 __qdf_mem_set_dma_size(qdf_device_t osdev, 365 qdf_mem_info_t *mem_info, 366 uint32_t mem_size) 367 { 368 mem_info->size = mem_size; 369 } 370 371 /** 372 * __qdf_mem_get_dma_size() - Return DMA physical address 373 * @osdev: parent device instance 374 * @mem_info: Pointer to allocated memory information 375 * 376 * Return: DMA physical address 377 */ 378 static inline qdf_dma_addr_t 379 __qdf_mem_get_dma_pa(qdf_device_t osdev, 380 qdf_mem_info_t *mem_info) 381 { 382 return mem_info->pa; 383 } 384 385 /** 386 * __qdf_mem_set_dma_size() - Set DMA physical address 387 * @osdev: parent device instance 388 * @mem_info: Pointer to allocated memory information 389 * @dma_pa: DMA phsical address 390 * 391 * Return: none 392 */ 393 static inline void 394 __qdf_mem_set_dma_pa(qdf_device_t osdev, 395 qdf_mem_info_t *mem_info, 396 qdf_dma_addr_t dma_pa) 397 { 398 mem_info->pa = dma_pa; 399 } 400 #endif /* __I_QDF_MEM_H */ 401