/* * DirectConnect provides a common interface for the network devices to achieve the full or partial acceleration services from the underlying packet acceleration engine * Copyright (c) 2017, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ #ifndef __DCMODE_SW_COMMON_H__ #define __DCMODE_SW_COMMON_H__ #include #if 0 //------------------------------------------------------------------------------ // Device name, as registered with kernel and accessed in /dev/ //------------------------------------------------------------------------------ #define DEV_NAME "cppp" //------------------------------------------------------------------------------ // Supported commands //------------------------------------------------------------------------------ typedef enum { CPPP_CMD_MIN, CPPP_CMD_ACQUIRE, CPPP_CMD_RELEASE, CPPP_CMD_START, CPPP_CMD_STOP, CPPP_CMD_ATTR_SET, CPPP_CMD_ATTR_GET, CPPP_CMD_XFER_WAIT, CPPP_CMD_XFER_WAKE, CPPP_CMD_MAX, } cppp_cmd_id_t; //------------------------------------------------------------------------------ // Structure describing contiguous block of memory //------------------------------------------------------------------------------ typedef struct { unsigned int phys; void * virt; unsigned int size; uint64_t cookie; } cppp_mem_block_t; //------------------------------------------------------------------------------ // Single communication channel //------------------------------------------------------------------------------ typedef struct { cppp_mem_block_t data; // Memory block for page management cppp_mem_block_t ctrl; // Memory block for shared counters unsigned int id; // Channel ID unsigned int sync; // I/O type unsigned int sram; // SRAM address of write-only counter } cppp_ch_info_t; //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ typedef struct { cppp_flag_t flags; // Configuration options cppp_ch_info_t ch[4]; // Channel info to be populated back cppp_id_t rcli_id; // ID of reference client cppp_mem_block_t ppio; // Packet processor I/O block } cppp_acquire_t; //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ typedef struct { unsigned int id; // Channel ID unsigned int out; // Direction of transfer unsigned int to; // Timeout, nsec } cppp_xfer_t; //------------------------------------------------------------------------------ // Commands container structure //------------------------------------------------------------------------------ typedef struct __attribute__ ((aligned(64))) { cppp_cmd_id_t cmd_id; cppp_id_t cli_id; int fd; union { cppp_acquire_t _acquire; struct { } _release; struct { } _start; struct { } _stop; struct { cppp_attr_t id; void * data; unsigned int size; } _attr; cppp_xfer_t _xfer; } data; } cppp_cmd_t; #endif //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ #define SW_DCMODE_CACHE_LINE_SIZE 32 /* #######################################################################################################*/ /* defines */ #define SW_DCMODE1_MAX_DEV_NUM 32 #define CACHE_LINE_SIZE 32 #define __CH_PRINT(ch, foo) foo(ch, __FUNCTION__) #define SW_DCMODE1_LOCAL_VIRT(ch) ((unsigned int *) ch->lcl_cntr.virt) #define SW_DCMODE1_REMOTE_VIRT(ch) ((unsigned int *) ch->rm_cntr.virt) #define MAX(x, y) (x > y ? x : y) #define MIN(x, y) (x < y ? x : y) /* ######################## */ #define DC_DP_DEFINE_LOCK(lock) DEFINE_MUTEX(lock) #define DC_DP_LOCK mutex_lock #define DC_DP_UNLOCK mutex_unlock /* ######################## */ #define SW_DCMODE1_XFER_IN 0 #define SW_DCMODE1_XFER_OUT 1 typedef enum { SW_DCMODE1_CHAN_SOC2DEV = 0, SW_DCMODE1_CHAN_SOC2DEV_RET = 1, SW_DCMODE1_CHAN_DEV2SOC = 2, SW_DCMODE1_CHAN_DEV2SOC_RET = 3, SW_DCMODE1_CHAN_MAX = 4, } sw_dcmode1_chan_id_t; typedef struct { unsigned int phys; void * virt; unsigned int size; uint32_t desc_dwsz; //uint64_t cookie; } sw_dcmode_mem_block_t; /* * DW0 : * tid - reserved * sid : Subif info (MCF : Bit 13, VAPID : Bit 8-12 and STAID : Bit 0-7) * DW1 : misc - reserved * DW2 : * addr - buffer address * DW3 : * flgs (8 Bit) : Bit OWN(31),SOP(30),EOP(29) * class (Bit 24-27) * size */ typedef struct __attribute__ ((__packed__)) __attribute__ ((aligned(16))) { #if 0 // Little Endian??? uint16_t tid; ///< Buffer tag, set by app CPU, replicated by FW uint16_t sid; ///< Session ID, set by FW uint32_t misc; ///< Misc... uint32_t addr; ///< Physical address of a buffer uint8_t flgs; ///< Buffer control flags uint8_t rsvd; ///< Reserved... uint16_t size; ///< Buffer size #else // Big endian uint32_t tid:16; ///< Buffer tag, set by app CPU, replicated by FW uint32_t sid:16; ///< Session ID, set by FW uint32_t misc; ///< Misc... uint32_t addr; ///< Physical address of a buffer uint32_t flgs:8; ///< Buffer control flags uint32_t rsvd:8; ///< Reserved... uint32_t size:16; ///< Buffer size #endif } sw_dcmode_bd_t; typedef struct { //SW_DCMODE1_SOC_REMOTE_CNTR_LAST_ACCUM(chan,n) ((chan)->lcl_cntr_trck.last_accumulated); // SW_DCMODE1_SOC_REMOTE_CNTR_LAST_ACCUM(chan,n) unsigned int last_accumulated; /* Counter last accumulated value */ unsigned int size; /* Counter max value (wrap-up value) */ } sw_dcmode_cntr_track_t; typedef struct { unsigned int phys; /* Counter physical address */ void * virt; /* Counter virtual address */ unsigned int size; /* Counter size (=4Bytes) */ unsigned int endian; /* Big or little endian */ unsigned int mode; /* Cumulative or Incremental mode */ } sw_dcmode_cntr_t; //------------------------------------------------------------------------------ // Ring state tracker, tailored for modulo type management //------------------------------------------------------------------------------ typedef struct __attribute__ ((__packed__)) { union { uint16_t head; unsigned char head_cache_line[SW_DCMODE_CACHE_LINE_SIZE]; }; union { uint16_t tail; unsigned char tail_cache_line[SW_DCMODE_CACHE_LINE_SIZE]; }; uint32_t mask; uint32_t size; } sw_dcmode_ring_t; typedef struct __attribute__ ((aligned(32))) { union { volatile uint32_t cntr; unsigned char cntr_cache_line[CACHE_LINE_SIZE]; }; } sw_dcmode_cntr_type_t; typedef struct { /* Ring */ sw_dcmode_mem_block_t data; // Descriptor data sw_dcmode_ring_t trck; // Ring pointers and metadata tracker sw_dcmode_bd_t * bufs; // Descriptors local virtual address unsigned int id ; // Channel ID /* Counter */ sw_dcmode_cntr_track_t lcl_cntr_trck; // SoC counter tracker sw_dcmode_cntr_t lcl_cntr; // SoC counter and metadata tracker sw_dcmode_cntr_track_t rm_cntr_trck; // Device counter tracker sw_dcmode_cntr_t rm_cntr; // Device counter and metadata tracker char * name; // User friendly name } sw_dcmode_chan_t; typedef enum { SW_DCMODE_DATA_FROM_BIDIRECTIONAL = DMA_BIDIRECTIONAL, SW_DCMODE_DATA_TO_DEVICE = DMA_TO_DEVICE, SW_DCMODE_DATA_FROM_DEVICE = DMA_FROM_DEVICE } sw_dcmode_data_direction_e; static inline uint32_t sw_dcmode_map_to_phys_addr (void *ctx, void *buffer, uint32_t size, sw_dcmode_data_direction_e direction) { return dma_map_single(ctx, buffer, size, direction); } static inline void sw_dcmode_unmap_phys_addr (void *ctx, uint32_t addr, uint32_t size, sw_dcmode_data_direction_e direction) { dma_unmap_single(ctx, addr, size, direction); } static inline void * get_bd_from_channel(sw_dcmode_chan_t *ch, int32_t index) { void *bdp; printk("Index: %d Track Head: %d\n",index, ch->trck.head); bdp = (void *)((uint32_t *)ch->data.virt + (index * ch->data.desc_dwsz)); // if(index > ch->trck.head) // return NULL; if (ch->trck.head == ch->trck.size) ch->trck.head = 0; return bdp; } //static inline int32_t //__xfer(sw_dcmode_chan_t *ch, sw_dcmode_bd_t *d, unsigned n, int xt, unsigned w); extern int32_t __xfer(sw_dcmode_chan_t *ch, sw_dcmode_bd_t *d, unsigned n, int xt, unsigned w); /*############################################################################################################*/ //------------------------------------------------------------------------------ // Ring metadata is shared with FW which has different endiannes. To address that // ring access calls store values in big-endian but return them for Atom use as // little-endian. //------------------------------------------------------------------------------ //#define SW_DCMODE_SWAP32(x) __builtin_bswap32(x) #define SW_DCMODE_SWAP32(x) x //------------------------------------------------------------------------------ // Emtpy test //------------------------------------------------------------------------------ static inline unsigned int sw_dcmode_ring_empty(sw_dcmode_ring_t * r) { return SW_DCMODE_SWAP32(r->tail) == SW_DCMODE_SWAP32(r->head); } //----------------------------------------------------------------------------- // Full test //------------------------------------------------------------------------------ static inline unsigned int sw_dcmode_ring_full(sw_dcmode_ring_t * r) { return (((SW_DCMODE_SWAP32(r->tail) - SW_DCMODE_SWAP32(r->head) - 1) & r->mask) == 0); } //------------------------------------------------------------------------------ // Number of entries currently inserted in the ring //------------------------------------------------------------------------------ static inline unsigned int sw_dcmode_ring_count_used(sw_dcmode_ring_t * r) { //printk("%s:r->mask:%d r->tail:%d r->head:%d \n ",__FUNCTION__,r->mask,r->tail,r->head); return ((SW_DCMODE_SWAP32(r->head) - SW_DCMODE_SWAP32(r->tail)) & r->mask); } //------------------------------------------------------------------------------ // Number of empty entries available in the list //------------------------------------------------------------------------------ static inline unsigned int sw_dcmode_ring_count_free(sw_dcmode_ring_t * r) { //printk("%s:r->mask:%d r->tail:%d r->head:%d \n ",__FUNCTION__,r->mask,r->tail,r->head); return (r->mask + SW_DCMODE_SWAP32(r->tail) - SW_DCMODE_SWAP32(r->head)); //return (r->mask + SW_DCMODE_SWAP32(r->mask)); } //------------------------------------------------------------------------------ // Number of available entries, depending on the context of usage //------------------------------------------------------------------------------ static inline unsigned int sw_dcmode_ring_count(sw_dcmode_ring_t * r, unsigned int prod) { //printk("print1:%s :%d\n",__FUNCTION__,__LINE__); return prod ? sw_dcmode_ring_count_free(r) : sw_dcmode_ring_count_used(r); } //------------------------------------------------------------------------------ // Counter query, dependent on context of usage //------------------------------------------------------------------------------ static inline unsigned int sw_dcmode_ring_index(sw_dcmode_ring_t * r, unsigned int prod) { //printk("%s:r->mask:%d r->tail:%d r->head:%d \n ",__FUNCTION__,r->mask,r->tail,r->head); //return (SW_DCMODE_SWAP32(prod ? r->head : r->tail) & r->mask); return ((prod ? r->head : r->tail) & r->mask); } //------------------------------------------------------------------------------ // Endianness conversion free, wraparound free counter query //------------------------------------------------------------------------------ //static inline unsigned int sw_dcmode_ring_index_raw(sw_dcmode_ring_t * r, unsigned int prod) static inline uint32_t sw_dcmode_ring_index_raw(sw_dcmode_ring_t * r, unsigned int prod) { //printk("%s: r->tail:%d r->head:%d \n ",__FUNCTION__,r->tail,r->head); return prod ? r->head : r->tail; } //------------------------------------------------------------------------------ // Counter increment, dependent on context of usage //------------------------------------------------------------------------------ static inline void sw_dcmode_ring_index_inc(sw_dcmode_ring_t * r, unsigned int prod, unsigned int n) { //printk("%s: r->tail:%d r->head:%d \n ",__FUNCTION__,r->tail,r->head); if (prod) { r->head = SW_DCMODE_SWAP32(SW_DCMODE_SWAP32(r->head) + n); } else { r->tail = SW_DCMODE_SWAP32(SW_DCMODE_SWAP32(r->tail) + n); } } #endif // __DCMODE_SW_COMMON_H__