Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | /********************************************************************** * Author: Cavium, Inc. * * Contact: support@cavium.com * Please include "LiquidIO" in the subject. * * Copyright (c) 2003-2016 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. * * This file is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. See the GNU General Public License for more details. ***********************************************************************/ /*! \file octeon_droq.h * \brief Implementation of Octeon Output queues. "Output" is with * respect to the Octeon device on the NIC. From this driver's point of * view they are ingress queues. */ #ifndef __OCTEON_DROQ_H__ #define __OCTEON_DROQ_H__ /* Default number of packets that will be processed in one iteration. */ #define MAX_PACKET_BUDGET 0xFFFFFFFF /** Octeon descriptor format. * The descriptor ring is made of descriptors which have 2 64-bit values: * -# Physical (bus) address of the data buffer. * -# Physical (bus) address of a octeon_droq_info structure. * The Octeon device DMA's incoming packets and its information at the address * given by these descriptor fields. */ struct octeon_droq_desc { /** The buffer pointer */ u64 buffer_ptr; /** The Info pointer */ u64 info_ptr; }; #define OCT_DROQ_DESC_SIZE (sizeof(struct octeon_droq_desc)) /** Information about packet DMA'ed by Octeon. * The format of the information available at Info Pointer after Octeon * has posted a packet. Not all descriptors have valid information. Only * the Info field of the first descriptor for a packet has information * about the packet. */ struct octeon_droq_info { /** The Length of the packet. */ u64 length; /** The Output Receive Header. */ union octeon_rh rh; }; #define OCT_DROQ_INFO_SIZE (sizeof(struct octeon_droq_info)) struct octeon_skb_page_info { /* DMA address for the page */ dma_addr_t dma; /* Page for the rx dma **/ struct page *page; /** which offset into page */ unsigned int page_offset; }; /** Pointer to data buffer. * Driver keeps a pointer to the data buffer that it made available to * the Octeon device. Since the descriptor ring keeps physical (bus) * addresses, this field is required for the driver to keep track of * the virtual address pointers. */ struct octeon_recv_buffer { /** Packet buffer, including metadata. */ void *buffer; /** Data in the packet buffer. */ u8 *data; /** pg_info **/ struct octeon_skb_page_info pg_info; }; #define OCT_DROQ_RECVBUF_SIZE (sizeof(struct octeon_recv_buffer)) /** Output Queue statistics. Each output queue has four stats fields. */ struct oct_droq_stats { /** Number of packets received in this queue. */ u64 pkts_received; /** Bytes received by this queue. */ u64 bytes_received; /** Packets dropped due to no dispatch function. */ u64 dropped_nodispatch; /** Packets dropped due to no memory available. */ u64 dropped_nomem; /** Packets dropped due to large number of pkts to process. */ u64 dropped_toomany; /** Number of packets sent to stack from this queue. */ u64 rx_pkts_received; /** Number of Bytes sent to stack from this queue. */ u64 rx_bytes_received; /** Num of Packets dropped due to receive path failures. */ u64 rx_dropped; u64 rx_vxlan; /** Num of failures of recv_buffer_alloc() */ u64 rx_alloc_failure; }; #define POLL_EVENT_INTR_ARRIVED 1 #define POLL_EVENT_PROCESS_PKTS 2 #define POLL_EVENT_PENDING_PKTS 3 #define POLL_EVENT_ENABLE_INTR 4 /* The maximum number of buffers that can be dispatched from the * output/dma queue. Set to 64 assuming 1K buffers in DROQ and the fact that * max packet size from DROQ is 64K. */ #define MAX_RECV_BUFS 64 /** Receive Packet format used when dispatching output queue packets * with non-raw opcodes. * The received packet will be sent to the upper layers using this * structure which is passed as a parameter to the dispatch function */ struct octeon_recv_pkt { /** Number of buffers in this received packet */ u16 buffer_count; /** Id of the device that is sending the packet up */ u16 octeon_id; /** Length of data in the packet buffer */ u32 length; /** The receive header */ union octeon_rh rh; /** Pointer to the OS-specific packet buffer */ void *buffer_ptr[MAX_RECV_BUFS]; /** Size of the buffers pointed to by ptr's in buffer_ptr */ u32 buffer_size[MAX_RECV_BUFS]; }; #define OCT_RECV_PKT_SIZE (sizeof(struct octeon_recv_pkt)) /** The first parameter of a dispatch function. * For a raw mode opcode, the driver dispatches with the device * pointer in this structure. * For non-raw mode opcode, the driver dispatches the recv_pkt * created to contain the buffers with data received from Octeon. * --------------------- * | *recv_pkt ----|--- * |-------------------| | * | 0 or more bytes | | * | reserved by driver| | * |-------------------|<-/ * | octeon_recv_pkt | * | | * |___________________| */ struct octeon_recv_info { void *rsvd; struct octeon_recv_pkt *recv_pkt; }; #define OCT_RECV_INFO_SIZE (sizeof(struct octeon_recv_info)) /** Allocate a recv_info structure. The recv_pkt pointer in the recv_info * structure is filled in before this call returns. * @param extra_bytes - extra bytes to be allocated at the end of the recv info * structure. * @return - pointer to a newly allocated recv_info structure. */ static inline struct octeon_recv_info *octeon_alloc_recv_info(int extra_bytes) { struct octeon_recv_info *recv_info; u8 *buf; buf = kmalloc(OCT_RECV_PKT_SIZE + OCT_RECV_INFO_SIZE + extra_bytes, GFP_ATOMIC); if (!buf) return NULL; recv_info = (struct octeon_recv_info *)buf; recv_info->recv_pkt = (struct octeon_recv_pkt *)(buf + OCT_RECV_INFO_SIZE); recv_info->rsvd = NULL; if (extra_bytes) recv_info->rsvd = buf + OCT_RECV_INFO_SIZE + OCT_RECV_PKT_SIZE; return recv_info; } /** Free a recv_info structure. * @param recv_info - Pointer to receive_info to be freed */ static inline void octeon_free_recv_info(struct octeon_recv_info *recv_info) { kfree(recv_info); } typedef int (*octeon_dispatch_fn_t)(struct octeon_recv_info *, void *); /** Used by NIC module to register packet handler and to get device * information for each octeon device. */ struct octeon_droq_ops { /** This registered function will be called by the driver with * the octeon id, pointer to buffer from droq and length of * data in the buffer. The receive header gives the port * number to the caller. Function pointer is set by caller. */ void (*fptr)(u32, void *, u32, union octeon_rh *, void *, void *); void *farg; /* This function will be called by the driver for all NAPI related * events. The first param is the octeon id. The second param is the * output queue number. The third is the NAPI event that occurred. */ void (*napi_fn)(void *); u32 poll_mode; /** Flag indicating if the DROQ handler should drop packets that * it cannot handle in one iteration. Set by caller. */ u32 drop_on_max; }; /** The Descriptor Ring Output Queue structure. * This structure has all the information required to implement a * Octeon DROQ. */ struct octeon_droq { /** A spinlock to protect access to this ring. */ spinlock_t lock; u32 q_no; u32 pkt_count; struct octeon_droq_ops ops; struct octeon_device *oct_dev; /** The 8B aligned descriptor ring starts at this address. */ struct octeon_droq_desc *desc_ring; /** Index in the ring where the driver should read the next packet */ u32 read_idx; /** Index in the ring where Octeon will write the next packet */ u32 write_idx; /** Index in the ring where the driver will refill the descriptor's * buffer */ u32 refill_idx; /** Packets pending to be processed */ atomic_t pkts_pending; /** Number of descriptors in this ring. */ u32 max_count; /** The number of descriptors pending refill. */ u32 refill_count; u32 pkts_per_intr; u32 refill_threshold; /** The max number of descriptors in DROQ without a buffer. * This field is used to keep track of empty space threshold. If the * refill_count reaches this value, the DROQ cannot accept a max-sized * (64K) packet. */ u32 max_empty_descs; /** The receive buffer list. This list has the virtual addresses of the * buffers. */ struct octeon_recv_buffer *recv_buf_list; /** The size of each buffer pointed by the buffer pointer. */ u32 buffer_size; /** Pointer to the mapped packet credit register. * Host writes number of info/buffer ptrs available to this register */ void __iomem *pkts_credit_reg; /** Pointer to the mapped packet sent register. * Octeon writes the number of packets DMA'ed to host memory * in this register. */ void __iomem *pkts_sent_reg; struct list_head dispatch_list; /** Statistics for this DROQ. */ struct oct_droq_stats stats; /** DMA mapped address of the DROQ descriptor ring. */ size_t desc_ring_dma; /** application context */ void *app_ctx; struct napi_struct napi; u32 cpu_id; call_single_data_t csd; }; #define OCT_DROQ_SIZE (sizeof(struct octeon_droq)) /** * Allocates space for the descriptor ring for the droq and sets the * base addr, num desc etc in Octeon registers. * * @param oct_dev - pointer to the octeon device structure * @param q_no - droq no. ranges from 0 - 3. * @param app_ctx - pointer to application context * @return Success: 0 Failure: 1 */ int octeon_init_droq(struct octeon_device *oct_dev, u32 q_no, u32 num_descs, u32 desc_size, void *app_ctx); /** * Frees the space for descriptor ring for the droq. * * @param oct_dev - pointer to the octeon device structure * @param q_no - droq no. ranges from 0 - 3. * @return: Success: 0 Failure: 1 */ int octeon_delete_droq(struct octeon_device *oct_dev, u32 q_no); /** Register a change in droq operations. The ops field has a pointer to a * function which will called by the DROQ handler for all packets arriving * on output queues given by q_no irrespective of the type of packet. * The ops field also has a flag which if set tells the DROQ handler to * drop packets if it receives more than what it can process in one * invocation of the handler. * @param oct - octeon device * @param q_no - octeon output queue number (0 <= q_no <= MAX_OCTEON_DROQ-1 * @param ops - the droq_ops settings for this queue * @return - 0 on success, -ENODEV or -EINVAL on error. */ int octeon_register_droq_ops(struct octeon_device *oct, u32 q_no, struct octeon_droq_ops *ops); /** Resets the function pointer and flag settings made by * octeon_register_droq_ops(). After this routine is called, the DROQ handler * will lookup dispatch function for each arriving packet on the output queue * given by q_no. * @param oct - octeon device * @param q_no - octeon output queue number (0 <= q_no <= MAX_OCTEON_DROQ-1 * @return - 0 on success, -ENODEV or -EINVAL on error. */ int octeon_unregister_droq_ops(struct octeon_device *oct, u32 q_no); /** Register a dispatch function for a opcode/subcode. The driver will call * this dispatch function when it receives a packet with the given * opcode/subcode in its output queues along with the user specified * argument. * @param oct - the octeon device to register with. * @param opcode - the opcode for which the dispatch will be registered. * @param subcode - the subcode for which the dispatch will be registered * @param fn - the dispatch function. * @param fn_arg - user specified that will be passed along with the * dispatch function by the driver. * @return Success: 0; Failure: 1 */ int octeon_register_dispatch_fn(struct octeon_device *oct, u16 opcode, u16 subcode, octeon_dispatch_fn_t fn, void *fn_arg); void octeon_droq_print_stats(void); u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq); int octeon_create_droq(struct octeon_device *oct, u32 q_no, u32 num_descs, u32 desc_size, void *app_ctx); int octeon_droq_process_packets(struct octeon_device *oct, struct octeon_droq *droq, u32 budget); int octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, int cmd, u32 arg); void octeon_droq_check_oom(struct octeon_droq *droq); #endif /*__OCTEON_DROQ_H__ */ |