1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 3 #ifndef _FDMA_API_H_ 4 #define _FDMA_API_H_ 5 6 #include <linux/bits.h> 7 #include <linux/etherdevice.h> 8 #include <linux/types.h> 9 10 #include "fdma_pci.h" 11 12 /* This provides a common set of functions and data structures for interacting 13 * with the Frame DMA engine on multiple Microchip switchcores. 14 * 15 * Frame DMA DCB format: 16 * 17 * +---------------------------+ 18 * | Next Ptr | 19 * +---------------------------+ 20 * | Reserved | Info | 21 * +---------------------------+ 22 * | Data0 Ptr | 23 * +---------------------------+ 24 * | Reserved | Status0 | 25 * +---------------------------+ 26 * | Data1 Ptr | 27 * +---------------------------+ 28 * | Reserved | Status1 | 29 * +---------------------------+ 30 * | Data2 Ptr | 31 * +---------------------------+ 32 * | Reserved | Status2 | 33 * |-------------|-------------| 34 * | | 35 * | | 36 * | | 37 * | | 38 * | | 39 * |---------------------------| 40 * | Data14 Ptr | 41 * +-------------|-------------+ 42 * | Reserved | Status14 | 43 * +-------------|-------------+ 44 * 45 * The data pointers points to the actual frame data to be received or sent. The 46 * addresses of the data pointers can, as of writing, be either a: DMA address, 47 * physical address or mapped address. 48 * 49 */ 50 51 #define FDMA_DCB_INFO_DATAL(x) ((x) & GENMASK(15, 0)) 52 #define FDMA_DCB_INFO_TOKEN BIT(17) 53 #define FDMA_DCB_INFO_INTR BIT(18) 54 #define FDMA_DCB_INFO_SW(x) (((x) << 24) & GENMASK(31, 24)) 55 56 #define FDMA_DCB_STATUS_BLOCKL(x) ((x) & GENMASK(15, 0)) 57 #define FDMA_DCB_STATUS_SOF BIT(16) 58 #define FDMA_DCB_STATUS_EOF BIT(17) 59 #define FDMA_DCB_STATUS_INTR BIT(18) 60 #define FDMA_DCB_STATUS_DONE BIT(19) 61 #define FDMA_DCB_STATUS_BLOCKO(x) (((x) << 20) & GENMASK(31, 20)) 62 #define FDMA_DCB_INVALID_DATA 0x1 63 64 #define FDMA_DB_MAX 15 /* Max number of DB's on Sparx5 */ 65 66 struct fdma; 67 68 struct fdma_db { 69 __le64 dataptr; 70 __le64 status; 71 }; 72 73 struct fdma_dcb { 74 __le64 nextptr; 75 __le64 info; 76 struct fdma_db db[FDMA_DB_MAX]; 77 }; 78 79 struct fdma_ops { 80 /* User-provided callback to set the dataptr */ 81 int (*dataptr_cb)(struct fdma *fdma, int dcb_idx, int db_idx, u64 *ptr); 82 /* User-provided callback to set the nextptr */ 83 int (*nextptr_cb)(struct fdma *fdma, int dcb_idx, u64 *ptr); 84 }; 85 86 struct fdma { 87 void *priv; 88 89 /* Virtual addresses */ 90 struct fdma_dcb *dcbs; 91 struct fdma_dcb *last_dcb; 92 93 /* DMA address */ 94 dma_addr_t dma; 95 96 /* Size of DCB + DB memory */ 97 int size; 98 99 /* Indexes used to access the next-to-be-used DCB or DB */ 100 int db_index; 101 int dcb_index; 102 103 /* Number of DCB's and DB's */ 104 u32 n_dcbs; 105 u32 n_dbs; 106 107 /* Size of DB's */ 108 u32 db_size; 109 110 /* Channel id this FDMA object operates on */ 111 u32 channel_id; 112 113 struct fdma_ops ops; 114 115 #if IS_ENABLED(CONFIG_MCHP_LAN966X_PCI) 116 /* PCI ATU region for this FDMA instance. */ 117 struct fdma_pci_atu_region *atu_region; 118 #endif 119 }; 120 121 /* Advance the DCB index and wrap if required. */ 122 static inline void fdma_dcb_advance(struct fdma *fdma) 123 { 124 fdma->dcb_index++; 125 if (fdma->dcb_index >= fdma->n_dcbs) 126 fdma->dcb_index = 0; 127 } 128 129 /* Advance the DB index. */ 130 static inline void fdma_db_advance(struct fdma *fdma) 131 { 132 fdma->db_index++; 133 } 134 135 /* Reset the db index to zero. */ 136 static inline void fdma_db_reset(struct fdma *fdma) 137 { 138 fdma->db_index = 0; 139 } 140 141 /* Check if a DCB can be reused in case of multiple DB's per DCB. */ 142 static inline bool fdma_dcb_is_reusable(struct fdma *fdma) 143 { 144 return fdma->db_index != fdma->n_dbs; 145 } 146 147 /* Check if the FDMA has marked this DB as done. */ 148 static inline bool fdma_db_is_done(struct fdma_db *db) 149 { 150 return le64_to_cpu(db->status) & FDMA_DCB_STATUS_DONE; 151 } 152 153 /* Get the length of a DB. */ 154 static inline int fdma_db_len_get(struct fdma_db *db) 155 { 156 return FDMA_DCB_STATUS_BLOCKL(le64_to_cpu(db->status)); 157 } 158 159 /* Get the dataptr of a DB. */ 160 static inline u64 fdma_db_dataptr_get(struct fdma_db *db) 161 { 162 return le64_to_cpu(db->dataptr); 163 } 164 165 /* Set the length of a DB. */ 166 static inline void fdma_dcb_len_set(struct fdma_dcb *dcb, u32 len) 167 { 168 dcb->info = cpu_to_le64(FDMA_DCB_INFO_DATAL(len)); 169 } 170 171 /* Get a DB by index. */ 172 static inline struct fdma_db *fdma_db_get(struct fdma *fdma, int dcb_idx, 173 int db_idx) 174 { 175 return &fdma->dcbs[dcb_idx].db[db_idx]; 176 } 177 178 /* Get the next DB. */ 179 static inline struct fdma_db *fdma_db_next_get(struct fdma *fdma) 180 { 181 return fdma_db_get(fdma, fdma->dcb_index, fdma->db_index); 182 } 183 184 /* Get a DCB by index. */ 185 static inline struct fdma_dcb *fdma_dcb_get(struct fdma *fdma, int dcb_idx) 186 { 187 return &fdma->dcbs[dcb_idx]; 188 } 189 190 /* Get the next DCB. */ 191 static inline struct fdma_dcb *fdma_dcb_next_get(struct fdma *fdma) 192 { 193 return fdma_dcb_get(fdma, fdma->dcb_index); 194 } 195 196 /* Check if the FDMA has frames ready for extraction. */ 197 static inline bool fdma_has_frames(struct fdma *fdma) 198 { 199 return fdma_db_is_done(fdma_db_next_get(fdma)); 200 } 201 202 /* Get a nextptr by index */ 203 static inline int fdma_nextptr_cb(struct fdma *fdma, int dcb_idx, u64 *nextptr) 204 { 205 *nextptr = fdma->dma + (sizeof(struct fdma_dcb) * dcb_idx); 206 return 0; 207 } 208 209 /* Get the DMA address of a dataptr, by index. This function is only applicable 210 * if the dataptr addresses and DCB's are in contiguous memory and the driver 211 * supports XDP. 212 */ 213 static inline u64 fdma_dataptr_dma_addr_contiguous(struct fdma *fdma, 214 int dcb_idx, int db_idx) 215 { 216 return fdma->dma + (sizeof(struct fdma_dcb) * fdma->n_dcbs) + 217 (dcb_idx * fdma->n_dbs + db_idx) * fdma->db_size + 218 XDP_PACKET_HEADROOM; 219 } 220 221 /* Get the virtual address of a dataptr, by index. This function is only 222 * applicable if the dataptr addresses and DCB's are in contiguous memory and 223 * the driver supports XDP. 224 */ 225 static inline void *fdma_dataptr_virt_addr_contiguous(struct fdma *fdma, 226 int dcb_idx, int db_idx) 227 { 228 return (u8 *)fdma->dcbs + (sizeof(struct fdma_dcb) * fdma->n_dcbs) + 229 (dcb_idx * fdma->n_dbs + db_idx) * fdma->db_size + 230 XDP_PACKET_HEADROOM; 231 } 232 233 /* Check if this DCB is the last used DCB. */ 234 static inline bool fdma_is_last(struct fdma *fdma, struct fdma_dcb *dcb) 235 { 236 return dcb == fdma->last_dcb; 237 } 238 239 int fdma_dcbs_init(struct fdma *fdma, u64 info, u64 status); 240 int fdma_db_add(struct fdma *fdma, int dcb_idx, int db_idx, u64 status); 241 int fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status); 242 int __fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status, 243 int (*dcb_cb)(struct fdma *fdma, int dcb_idx, u64 *nextptr), 244 int (*db_cb)(struct fdma *fdma, int dcb_idx, int db_idx, 245 u64 *dataptr)); 246 247 int fdma_alloc_coherent(struct device *dev, struct fdma *fdma); 248 int fdma_alloc_phys(struct fdma *fdma); 249 #if IS_ENABLED(CONFIG_MCHP_LAN966X_PCI) 250 int fdma_alloc_coherent_and_map(struct device *dev, struct fdma *fdma, 251 struct fdma_pci_atu *atu); 252 #endif 253 254 void fdma_free_coherent(struct device *dev, struct fdma *fdma); 255 void fdma_free_phys(struct fdma *fdma); 256 #if IS_ENABLED(CONFIG_MCHP_LAN966X_PCI) 257 void fdma_free_coherent_and_unmap(struct device *dev, struct fdma *fdma); 258 #endif 259 260 u32 fdma_get_size(struct fdma *fdma); 261 u32 fdma_get_size_contiguous(struct fdma *fdma); 262 263 #endif 264