1. insmod log

octeon_drv: module license 'Cavium Networks' taints kernel.
Disabling lock debugging due to kernel taint
-- OCTEON: Loading Octeon PCI driver (base module)
OCTEON: Driver Version: PCI BASE RELEASE 2.3.0 build 84
OCTEON: System is Little endian (1000 ticks/sec)
OCTEON: PCI Driver compile options:  DEBUG 


OCTEON: Found device 177d:92..Initializing...
OCTEON: Setting up Octeon device 0 
Octeon 0000:08:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
Octeon 0000:08:00.0: setting latency timer to 64
OCTEON[0]: CN66XX PASS1.2
OCTEON[0]: Using PCIE Port 0
OCTEON[0]: BIST enabled for soft reset
OCTEON[0]: Reset completed
OCTEON[0] Poll Function (Module Starter arg: 0x0) registered
OCTEON[0]: Enabling PCI-E error reporting..
OCTEON: Initializing droq tasklet
OCTEON: Initializing completion on interrupt tasklet
  alloc irq_desc for 146 on node 0
  alloc kstat_irqs on node 0
alloc irq_2_iommu on node 0
Octeon 0000:08:00.0: irq 146 for MSI/MSI-X
OCTEON[0]: MSI enabled
OCTEON: Octeon device 0 is ready

-- OCTEON: Octeon Poll Thread starting execution now!
-- OCTEON: Octeon PCI driver (base module) is ready!

2. 主结构体octeon_device_t

components/driver/host/driver/osi/octeon_device.c
定义了octeon_device[]数组, 最多支持MAX_OCTEON_DEVICES(4)同时存在

octeon_device_t *octeon_device[MAX_OCTEON_DEVICES];
typedef struct _OCTEON_DEVICE octeon_device_t;

每个octeon device被抽象为一个octeon_device_t结构体, 注意这个主结构是osi的

/** The Octeon device. 
 *  Each Octeon device has this structure to represent all its
 *  components.
 */
struct _OCTEON_DEVICE {
   /** Lock for this Octeon device */
   cavium_spinlock_t        oct_lock; //实际是spinlock_t
   /** OS dependent PCI device pointer */ 
   cavium_pci_device_t     *pci_dev; //linux下面是struct pci_dev
   /** Chip specific information. */
   void                    *chip;
   /** Octeon Chip type. */
   uint16_t                 chip_id;
   uint16_t                 rev_id;
   /** This device's id - set by the driver. */
   uint16_t                 octeon_id;
   /** This device's PCIe port used for traffic. */
   uint16_t                 pcie_port;
   /** The state of this device */
   cavium_atomic_t          status; //是atomic_t
   /** memory mapped io range */
   octeon_mmio              mmio[OCT_MEM_REGIONS]; //3个, 结构体定义见A
   struct octeon_reg_list   reg_list; //见B
   struct octeon_fn_list    fn_list; //见C
   cavium_atomic_t          interrupts;
   cavium_atomic_t          in_interrupt;
   int                      num_iqs;
   /** The 4 input instruction queues */
   octeon_instr_queue_t     *instr_queue[MAX_OCTEON_INSTR_QUEUES]; //32个, 结构体定义在D,很关键
   int                       pend_list_size;
   octeon_pending_list_t    *plist; //见E
   /** The doubly-linked list of instruction response */
   octeon_response_list_t    response_list[MAX_RESPONSE_LISTS]; //3个, 一个ordered, 一个unordered-blocking, 一个unordered-nonblocking, 结构体见F
   int                        num_oqs;
   /** The 4 output queues  */
   octeon_droq_t            *droq[MAX_OCTEON_OUTPUT_QUEUES]; //32个, droq是Descriptor Ring Output Queue, 结构体见G
#if  !defined(USE_DROQ_THREADS)
   /** Tasklet structures for this device. */
   struct tasklet_struct     droq_tasklet;
#endif
   struct tasklet_struct     comp_tasklet;
   uint32_t                  napi_mask;
   void                     *poll_list;
   cavium_spinlock_t         poll_lock;
   struct tasklet_struct     cntq_tasklet;
   uint32_t                  cntq_ready;
   /* The 2 Octeon DMA Counter Queues */
   void                     *cntq[MAX_OCTEON_DMA_QUEUES]; //2个
   /* The DDOQ lookup table */
   void                     *ddoq_list;
   /** Operations on the DMA queues */
   octeon_dma_ops_t          dma_ops; //见H
   /** A table maintaining maps of core-addr to BAR1 mapped address. */
   octeon_range_table_t      range_table[MAX_OCTEON_MAPS]; //最多32个map, 见I
   /** Total number of core-address ranges mapped (Upto 32). */
   uint32_t                  map_count;
   octeon_io_enable_t        io_qmask; //三个uint32_t, iq, oq, iq64B
   /** List of dispatch functions */
   octeon_dispatch_list_t    dispatch; //驱动收到报文后,会依次调这个链表里面的函数, 注意里面的opcode, 见J
#ifdef USE_BUFFER_POOL //如何打开buffer pool???
   /** The buffer pool implementation */
   cavium_buffer_t           buf[BUF_POOLS]; //6个pool, 分别是32k,16k,8k,4k,2k,1k大小的pool, 见K
   cavium_frag_buf_t         fragments[MAX_BUFFER_CHUNKS]; //1500个, 见L
   uint16_t                  fragment_free_list[MAX_BUFFER_CHUNKS];
   uint16_t                  fragment_free_list_index;
   cavium_spinlock_t         fragment_lock;
#endif
   /** The /proc file entries */
   void                     *proc_root_dir;
   /** Statistics for this octeon device. Does not include IQ, DROQ stats */
   oct_dev_stats_t           stats; //统计信息, 都是64位, interrupts poll_count comp_tasklet_count droq_tasklet_count cntq_tasklet_count
   /** IRQ assigned to this device. */
   int                       irq;
   int                       msi_on;
   /** The core application is running in this mode. See octeon-drv-opcodes.h
       for values. */
   int                       app_mode;
#ifdef CVMCS_DMA_IC
   /* When DMA interrupt raised we have these many packets DMAed by Octeon */
   cavium_atomic_t          dma_cnt_to_process;
#endif
#ifdef USE_DDOQ_THREADS
   cvm_ddoq_thread_t         ddoq_thread[CVM_MAX_DDOQ_THREADS]; //8个或16个, 见M
#endif
   /** The name given to this device. */
   char                      device_name[32];
};

3. A.描述PCIE空间的结构体

/** PCI address space mapping information.
 *  Each of the 3 address spaces given by BAR0, BAR2 and BAR4 of
 *  Octeon gets mapped to different physical address spaces in
 *  the kernel. 
 */
typedef struct  {
  /** PCI address to which the BAR is mapped. */
   unsigned long   start;
  /** Length of this PCI address space. */
   unsigned long   len;
  /** Length that has been mapped to phys. address space. */
   unsigned long   mapped_len;
  /** The physical address to which the PCI address space is mapped. */
   void           *hw_addr;
  /** Flag indicating the mapping was successful. */
   int             done;
}octeon_mmio;

4. B.间接访问寄存器, SLI_WIN*

struct octeon_reg_list {

    uint32_t    *pci_win_wr_addr_hi;
    uint32_t    *pci_win_wr_addr_lo;
    uint64_t    *pci_win_wr_addr;

    uint32_t    *pci_win_rd_addr_hi;
    uint32_t    *pci_win_rd_addr_lo;
    uint64_t    *pci_win_rd_addr;

    uint32_t    *pci_win_wr_data_hi;
    uint32_t    *pci_win_wr_data_lo;
    uint64_t    *pci_win_wr_data;

    uint32_t    *pci_win_rd_data_hi;
    uint32_t    *pci_win_rd_data_lo;
    uint64_t    *pci_win_rd_data;
};

5. C.用来适配不同的octeon型号

最基本的设置寄存器的接口

struct octeon_fn_list {

    void                (* setup_iq_regs)(struct _OCTEON_DEVICE *, int);
    void                (* setup_oq_regs)(struct _OCTEON_DEVICE *, int);

    cvm_intr_return_t   (* interrupt_handler)(void *);
    int                 (* soft_reset)(struct _OCTEON_DEVICE *);
    int                 (* setup_device_regs)(struct _OCTEON_DEVICE *);
    void                (* reinit_regs)(struct _OCTEON_DEVICE *);
    void                (* bar1_idx_setup)(struct _OCTEON_DEVICE *, uint64_t, int, int);
    void                (* bar1_idx_write)(struct _OCTEON_DEVICE *, int, uint32_t);
    uint32_t            (* bar1_idx_read)(struct _OCTEON_DEVICE *, int);
    uint32_t            (* update_iq_read_idx)(octeon_instr_queue_t  *);

    void                (* enable_oq_pkt_time_intr)(octeon_device_t *, int );
    void                (* disable_oq_pkt_time_intr)(octeon_device_t *, int );

    void                (* enable_interrupt)(void  *);
    void                (* disable_interrupt)(void  *);

    void                (* enable_io_queues)(struct _OCTEON_DEVICE  *);
    void                (* disable_io_queues)(struct _OCTEON_DEVICE  *);
};

6. D.表示一个input ring

/** The instruction (input) queue. 
    The input queue is used to post raw (instruction) mode data or packet
    data to Octeon device from the host. Each input queue (upto 4) for
    a Octeon device has one such structure to represent it.
*/
typedef struct   {
  /** A spinlock to protect access to the input ring.  */
   cavium_spinlock_t     lock;
  /** Flag that indicates if the queue uses 64 byte commands. */
  uint32_t               iqcmd_64B:1;
  /** Queue Number. */
  uint32_t               iq_no:5;
  uint32_t               rsvd:18;
  uint32_t               status:8;
  /** Maximum no. of instructions in this queue. */
   uint32_t              max_count;
#if !defined(DISABLE_PCIE14425_ERRATAFIX)
   /** Count of packets that were not sent due to backpressure.  */
   uint32_t              bp_hits;
#endif
  /** Index in input ring where the driver should write the next packet. */
   uint32_t              host_write_index;
  /** Index in input ring where Octeon is expected to read the next packet. */
   uint32_t              octeon_read_index;
  /** This index aids in finding the window in the queue where Octeon 
      has read the commands. */
   uint32_t              flush_index;
  /** This field keeps track of the instructions pending in this queue. */
   cavium_atomic_t       instr_pending;
   uint32_t              reset_instr_cnt;
  /** Pointer to the Virtual Base addr of the input ring. */
   uint8_t              *base_addr;
   octeon_noresponse_list_t    *nrlist; //int buftype, void * buf, 表示NORESPONSE的请求被octeon执行了, 但驱动还没有把资源释放掉
   struct oct_noresp_free_list nr_free; //octeon_noresponse_list_t *q, int put_idx, get_idx;表示需要free的NORESPONSE list?
  /** Octeon doorbell register for the ring. */
   void                 *doorbell_reg;
  /** Octeon instruction count register for this ring. */
   void                 *inst_cnt_reg;
  /** Number of instructions pending to be posted to Octeon. */
   uint32_t              fill_cnt;
  /** The max. number of instructions that can be held pending by the driver. */
   uint32_t              fill_threshold;
  /** The last time that the doorbell was rung. The unit is OS-dependent. */
   unsigned long         last_db_time;
  /** The doorbell timeout. If the doorbell was not rung for this time and 
      fill_cnt is non-zero, ring the doorbell again. */
   unsigned long         db_timeout;
  /** Statistics for this input queue. */
  oct_iq_stats_t         stats;
  /** DMA mapped base address of the input descriptor ring. */
   unsigned long          base_addr_dma;
}  octeon_instr_queue_t;

7. E.对应主结构体的plist域

pending list是用来处理需要response的request的, 和output ring有关吗? --not only, but also input ring

/** Pending list implementation for each Octeon device. */
typedef  struct  {
   /** Pending list for input instructions */
   octeon_pending_entry_t   *list; //见E1
   /** A list which indicates which entry in the pending_list above is free */
   uint32_t                 *free_list; //free_list是个数组, 有count个uint32
   /** The next location in pending_free_list where an index into pending_list
      can be saved */
   uint32_t                  free_index;
   /** Number of pending list entries. */
   uint32_t                  entries;
   /** Count of pending instructions */
   cavium_atomic_t           instr_count;
   /** A lock to control access to the pending list */
   cavium_spinlock_t         lock; 
} octeon_pending_list_t;

7.1. E1.octeon_pending_entry_t

/** Structure of an entry in pending list.
 */
typedef struct  {
  /** Used to add/delete this entry to one of the 3 response lists. */
   cavium_list_t                    list; //双向链表
  /** Index in the input queue where this request was posted */
   uint16_t                         queue_index;
  /** Queue into which request was posted. */
   uint16_t                         iq_no;
  /** Index into pending_list that is returned to the user (for polling) */
   uint32_t                         request_id;
  /** Status of this entry */
   OCTEON_PENDING_ENTRY_STATUS      status; //有4种状态, FREE USED TIMEOUT REMOVE
  /** The instruction itself (not in the format that Octeon sees it)*/
   octeon_soft_instruction_t       *instr; //见E11, 非常重要
}octeon_pending_entry_t;

7.1.1. E11.这个就是和硬件最接近的结构?

--no, 还只是个开始

/** Format of a instruction presented to the driver. This structure has the
    values that get posted to Octeon in addition to other fields that are
    used by the driver to keep track of the instruction's progress.
*/
typedef struct {
    cavium_list_t                    list;
#define COMPLETION_WORD_INIT    0xffffffffffffffffULL
    /** Pointer to the completion status word */
    volatile uint64_t               *status_word;
    /** The timestamp (in ticks) till we wait for a response for this
        instruction. */
    unsigned long                    timeout;
    /**How the response for the instruction should be handled.*/
    octeon_request_info_t            req_info; //见E111
    /** Input data pointer. It is either pointing directly to input data
        or to a gather list which is a list of addresses where data is present. */
    void                            *dptr; //可以是直接一个指针地址, 也可以是octeon_sg_entry_t 的链表
    /** Response from Octeon comes at this address. It is either pointing to 
        output data buffer directly or to a scatter list which in turn points 
        to output data buffers. */
    void                            *rptr; //可以是soft_instr->rptr = SOFT_REQ_OUTBUF(soft_req, 0), 也可以是octeon_sg_entry_t 的链表
    /** The instruction header. All input commands have this field. */
    octeon_instr_ih_t                ih; //见E112
    /** Input request header. */
    octeon_instr_irh_t               irh; //见E113
    /** The PCI instruction to be sent to Octeon. This is stored in the instr
        to retrieve the physical address of buffers when instr is freed. */
    octeon_instr_64B_t               command; //见E114, 重要! input ring 的64字节命令字
    /** These headers are used to create a 64-byte instruction  */
    uint64_t                         exhdr[4];
    /** Information about the extra headers. */
    octeon_exhdr_info_t              exhdr_info; //见E115
    /** Flags to indicate memory allocated for this instruction. Used by driver
        when freeing the soft instruction.  */
    uint32_t                         alloc_flags;
    /** If a gather list was allocated, this ptr points to the buffer used for
        the gather list. The gather list has to be 8B aligned, so this value
        may be different from dptr.
    */
    void                            *gather_ptr;
    /** Total data bytes transferred in the gather mode request. */
    uint32_t                         gather_bytes;
    /** If a scatter list was allocated, this ptr points to the buffer used for
        the scatter list. The scatter list has to be 8B aligned, so this value
        may be different from rptr.
    */
    void                            *scatter_ptr;
    /** Total data bytes to be received in the scatter mode request. */
    uint32_t                         scatter_bytes;
}octeon_soft_instruction_t;

E111.octeon_request_info_t

/** Information about the request sent to driver by kernel mode applications. */
typedef struct  {
  /** The Octeon device to use for this request */
   uint32_t                  octeon_id;
  /** The request mask */
   octeon_request_mask_t     req_mask; //一共32bit, resp_mode:2,dma_mode:2,resp_order:2,ignore_signal:2,iq_no:5,rsvd:19
  /** timeout for this request */
   uint32_t                  timeout;
  /** Status of this request */
   octeon_req_status_t       status; //一个u32
  /** The request id assigned by driver to this request */
   uint32_t                  request_id;
  /** The callback function to call after request completion */
   instr_callback_t          callback; //原型是void(* instr_callback_t)(octeon_req_status_t, void *); 
  /** Argument passed to callback */
   void                     *callback_arg;
} octeon_request_info_t;

E112.对应到硬件寄存器DPI_INST_HDR

好像是小端模式

typedef struct  {
  /** Tag Value */
  uint64_t     tag:32;
  /** Tag type */
  uint64_t     tagtype:2;
  /** Short Raw Packet Indicator 1=short raw pkt */
  uint64_t     rs:1;
  /** Core group selection (1 of 16) */
  uint64_t     grp:4;
  /** Packet Order / Work Unit selection (1 of 8)*/
  uint64_t     qos:3;
  /** Front Data size */
  uint64_t     fsz:6;
  /** Data length OR no. of entries in gather list */
  uint64_t     dlengsz:14;
  /** Gather indicator 1=gather*/
  uint64_t     gather:1;
  /** Raw mode indicator 1 = RAW */ 
  uint64_t     raw:1;
}octeon_instr_ih_t;

E113.Input Request Header

/** Input Request Header in LITTLE ENDIAN format */

typedef struct  {
  /** Request ID  */
  uint64_t     rid:16;
  /** PCIe port to use for response */
  uint64_t     pcie_port:3;
  /** Scatter indicator  1=scatter */
  uint64_t     scatter:1;
  /** Size of Expected result OR no. of entries in scatter list */
  uint64_t     rlenssz:14;
  /** Desired destination port for result */
  uint64_t     dport:6;
  /** Opcode Specific parameters */
  uint64_t     param:8;
  /** Opcode for the return packet  */
  uint64_t     opcode:16;
} octeon_instr_irh_t;

E114.这个就是input ring的一个instruction

/** 64-byte instruction format.
    Format of instruction for a 64-byte mode input queue.
*/
typedef struct  {
  /** Pointer where the input data is available. */
  uint64_t             dptr;
  /** Instruction Header. */
  uint64_t             ih;
  /** Pointer where the response for a RAW mode packet will be written
      by Octeon. */
  uint64_t             rptr;
  /** Input Request Header. */
  uint64_t             irh;
  /** Additional headers available in a 64-byte instruction. */
  uint64_t             exhdr[4];
}octeon_instr_64B_t;

E115.extra header

/** Information about each of the extra headers added for a 64-byte
    instruction. */
typedef struct {
   /** The number of 64-bit extra header words in this request. */
   uint64_t    exhdr_count:4;
   /** Use a value of type OCTEON_EXHDR_FMT */
   uint64_t    exhdr1_op:2;
   uint64_t    exhdr2_op:2;
   uint64_t    exhdr3_op:2;
   uint64_t    exhdr4_op:2;
   uint64_t    rsvd:52;
} octeon_exhdr_info_t;

8. F.头指针, 表示一个response链表

typedef struct {
  /** List structure to add delete pending entries to */
   cavium_list_t head;
  /** A lock for this response list */
   cavium_spinlock_t lock;
} octeon_response_list_t;

9. G.表示output ring描述符

/** The Descriptor Ring Output Queue structure.
    This structure has all the information required to implement a 
    Octeon DROQ.
*/
typedef struct  {
  /** A spinlock to protect access to this ring. */
   cavium_spinlock_t        lock;
   uint32_t                 q_no;
   uint32_t                 fastpath_on;
   octeon_droq_ops_t        ops; //见G1
   octeon_device_t         *oct_dev; //指向主结构体的指针
#ifdef  USE_DROQ_THREADS
   cvm_kthread_t            thread; //见G2
   cavium_wait_channel      wc; //就是wait_queue_head_t
   int                      stop_thread;
   cavium_atomic_t          thread_active;
#endif
  /** The 8B aligned descriptor ring starts at this address. */
   octeon_droq_desc_t      *desc_ring; //见G3, 这个才是硬件寄存器
  /** Index in the ring where the driver should read the next packet */
   uint32_t                 host_read_index;
  /** Index in the ring where Octeon will write the next packet */
   uint32_t                 octeon_write_index;
  /** Index in the ring where the driver will refill the descriptor's buffer */
   uint32_t                 host_refill_index;
  /** Packets pending to be processed - tasklet implementation */
   cavium_atomic_t          pkts_pending;
  /** Number of  descriptors in this ring. */
   uint32_t                 max_count;
  /** The number of descriptors pending refill. */
   uint32_t                 refill_count;
   uint32_t                 pkts_per_intr;
   uint32_t                 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. */
   uint32_t                 max_empty_descs;
   /** The 8B aligned info ptrs begin from this address. */
   octeon_droq_info_t      *info_list; //见G4
  /** The receive buffer list. This list has the virtual addresses of the
      buffers.  */
   octeon_recv_buffer_t    *recv_buf_list; //见G5, 驱动用来保存虚拟buffer地址
  /** The size of each buffer pointed by the buffer pointer. */
   uint32_t                 buffer_size;
  /** Pointer to the mapped packet credit register.
       Host writes number of info/buffer ptrs available to this register */
   void                    *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                    *pkts_sent_reg;
#if  defined(ENABLE_PCIE_2G4G_FIX)
   void                    *buffer_block;
#endif
   cavium_list_t            dispatch_list; //双向链表
  /** Statistics for this DROQ. */
   oct_droq_stats_t         stats; //见G6
  /** DMA mapped address of the DROQ descriptor ring. */
   unsigned long            desc_ring_dma;
  /** Info ptr list are allocated at this virtual address. */
   unsigned long            info_base_addr;
  /** Allocated size of info list. */
   uint32_t                 info_alloc_size;
}octeon_droq_t;

9.1. G1.octeon_droq_ops_t

/** Used by NIC module to register packet handler and to get device
  * information for each octeon device.
  */
typedef struct {
    /** 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 response header gives the port 
        number to the caller.  Function pointer is set by caller.  */
    void       (*fptr)(int, void *, uint32_t, octeon_resp_hdr_t *);
    /* 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)(int, int, int );
    int        poll_mode;
    /** Flag indicating if the DROQ handler should drop packets that
        it cannot handle in one iteration. Set by caller. */
    int        drop_on_max;
    uint16_t   op_mask;
    uint16_t   op_major;
} octeon_droq_ops_t;

9.2. G2.cvm_kthread_t

typedef  struct {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
    cavium_pid_t      id; //就是pid_t               
#else
    cavium_ostask_t  *id; //就是struct task_struct
#endif
    int               (*fn)(void *);
    void              *fn_arg;
    char               fn_string[80];
    int                exec_on_create;
} cvm_kthread_t;

9.3. G3.真正的符合硬件的定义的结构体

/** 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_t structure.
    The Octeon device DMA's incoming packets and its information at the address
    given by these descriptor fields.
 */
typedef struct  {
  /** The buffer pointer */
   uint64_t        buffer_ptr;
  /** The Info pointer */
   uint64_t        info_ptr; //octeon_droq_info_t的地址, 见G4
}octeon_droq_desc_t;

9.4. G4.octeon_droq_info_t

/** 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. */
typedef struct {
  /** The Output Response Header. */
   octeon_resp_hdr_t    resp_hdr; //见G41
  /** The Length of the packet. */
   uint64_t             length;
}octeon_droq_info_t;

9.4.1. G41.octeon_resp_hdr_t

/** Response Header in LITTLE ENDIAN format */
typedef struct {
  /** The request id for a packet thats in response to pkt sent by host. */
   uint64_t        request_id:16;
  /** Reserved. */
   uint64_t        reserved:4;
  /** The destination Queue port. */
   uint64_t        dest_qport:22;
  /** The source port for a packet thats in response to pkt sent by host. */
   uint64_t        src_port:6;
  /** Opcode for this packet. */
   uint64_t        opcode:16;
} octeon_resp_hdr_t;

9.5. G5.驱动用这个来表示buffer, 用的是虚拟地址

/** 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. The fields are operated by
    OS-dependent routines.
*/
typedef struct  {
  /** Pointer to the packet buffer. Hidden by void * to make it OS independent.
         */
     void        *buffer;
  /** Pointer to the data in the packet buffer.
      This could be different or same as the buffer pointer depending
      on the OS for which the code is compiled. */
     uint8_t        *data;
} octeon_recv_buffer_t;

9.6. G6. oct_droq_stats_t

/** Output Queue statistics. Each output queue has four stats fields. */
typedef struct {
  uint64_t   pkts_received; /**< Number of packets received in this queue. */
  uint64_t   bytes_received;/**< Bytes received by this queue. */
  uint64_t   dropped_nodispatch; /**< Packets dropped due to no dispatch function. */
  uint64_t   dropped_nomem; /**< Packets dropped due to no memory available. */
  uint64_t   dropped_toomany; /**< Packets dropped due to large number of pkts to process. */
} oct_droq_stats_t;

10. H. octeon_dma_ops_t

/** Used by CNTQ module to register DMA queue interrupt handler, tasklets
  * and statistics routines for each octeon device.
  */
typedef struct {
    /** Tasklet to be scheduled for CNTQ bottom half processing. */
    void      (*bh)(unsigned long);
    /** Interrupt Handler for DMA Queue interrupts. */
    int       (*intr_handler)(void  *, uint64_t);
    /** Read DMA Counter Queue and DDOQ list statistics into a structure */
    int       (* read_statsb)(int, oct_stats_t *);
    /** Format and print DMA Counter Queue and DDOQ list statistics into a buffer */
    int       (* read_stats)(int, char *);
} octeon_dma_ops_t;

11. I. octeon_range_table_t

/** Map of Octeon core memory address to Octeon BAR1 indexed space. */
typedef  struct  {
  /** Starting Core address mapped */
  uint64_t      core_addr;
  /** Physical address (of the BAR1 mapped space) 
      corressponding to core_addr. */
  void       *mapped_addr;
  /** Indicator that the mapping is valid. */
  int         valid;
} octeon_range_table_t;

12. J.收到报文后按opcode分发

/** The dispatch list entry.
 *  The driver keeps a record of functions registered for each 
 *  response header opcode in this structure. Since the opcode is
 *  hashed to index into the driver's list, more than one opcode
 *  can hash to the same entry, in which case the list field points
 *  to a linked list with the other entries.
 */
typedef struct {
  /** List head for this entry */
    cavium_list_t             list;
  /** The opcode for which the above dispatch function & arg should be
      used */
    octeon_opcode_t           opcode;
  /** The function to be called for a packet received by the driver */
    octeon_dispatch_fn_t      dispatch_fn;
  /** The application specified argument to be passed to the above
      function along with the received packet */
    void                      *arg;
} octeon_dispatch_t;


/** The dispatch list structure. */
typedef struct {
    cavium_spinlock_t      lock;
    /** Count of dispatch functions currently registered */
    uint32_t               count;
    /** The list of dispatch functions */
    octeon_dispatch_t     *dlist;
} octeon_dispatch_list_t;

13. K. buffer pool

/** Each buffer pool is represented by this structure.
 */
typedef struct {
  /** Lock for this pool. */
   cavium_spinlock_t buffer_lock;
  /** Number of chunks in this pool. */
   int chunks;
  /** Size of each chunk available for use after allocation. */
   int chunk_size;
  /** Actual size of each chunk. (includes size of buffer tag)*/
   int real_size;
   uint8_t *base;
  /** Address of each chunk. */
   uint8_t *address[MAX_BUFFER_CHUNKS];
  /** Address of usable space in chunk ( chunk - buffer tag) */
   uint8_t *address_trans[MAX_BUFFER_CHUNKS];
  /** Free list for this pool. */
   uint16_t free_list[MAX_BUFFER_CHUNKS];
  /** The next location in free list where a buffer is available. */
   int free_list_index;
  /** Start of head for this pool's fragment list.  */
   cavium_list_t frags_list;
} cavium_buffer_t;

14. L. buffer pool的fragment

/** List to keep track of fragmented buffers in the buffer pool. */
typedef struct {
    cavium_list_t list;
    cavium_list_t alloc_list;
    uint8_t *big_buf;
    int frags_count;
    int index;
    OCTEON_BUFPOOL p;
    uint16_t free_list[MAX_FRAGMENTS];
    uint8_t *address[MAX_FRAGMENTS];
    int free_list_index;
    int not_allocated;
} cavium_frag_buf_t;

15. M.USE_DDOQ_THREADS

typedef struct cvm_ddoq_thread_info {
    int ddoq_id;
    int req_id;
    int num_pkts;
} octeon_ddoq_thread_info_t;

typedef struct cvm_ddoq_thread {
   octeon_device_t         *oct_dev; //主结构体的指针
   cvm_kthread_t         thread; //见G2
   cavium_wait_channel     wc; //还是wait_queue_head_t
   int                  stop_thread;
   cavium_atomic_t         thread_active;
   cavium_atomic_t      ddoq_pkts_queued;

   cavium_spinlock_t    th_lock;
   int                  th_read_idx;
   int                  th_write_idx;

   /* On each interrupt we can handle at most */
   octeon_ddoq_thread_info_t th_info[CVM_DDOQ_MAX_THREAD_PKTS];
} cvm_ddoq_thread_t;

16. octeon_module_handler_t

当octeon device被初始化 被复位 被停止时调用的附加函数

/** Structure passed by kernel application when registering a module with
    the driver. */
typedef struct {

    /* Application type for which handler is being registered. */
    uint32_t   app_type;

    /* Call this routine to perform add-on module related setup activities
       when a octeon device is being initialized.
     */
    int   (*startptr)(int, void *);

    /* Call this routine to perform add-on module related reset activities
       when a octeon device is being reset.
     */
    int   (*resetptr)(int, void *);

    /* Call this routine to perform add-on module related shutdown 
       activities when a octeon device is being removed or the driver is 
       being unloaded.
         */
    int   (*stopptr)(int, void *);

} octeon_module_handler_t;

17. octeon_cn6xxx_t

/* Register address and configuration for a CN6XXX devices. */
/* If device specific changes need to be made then add a struct to include
   device specific fields as shown in the commented section */
typedef struct {

    /** PCI interrupt summary register */
    uint8_t            *intr_sum_reg64;

    /** PCI interrupt enable register */
    uint8_t            *intr_enb_reg64;

    /** The PCI interrupt mask used by interrupt handler */
    uint64_t            intr_mask64;

    cn6xxx_config_t    *conf; //见2A

    /* Example additional fields - not used currently
    struct {
    }cn6xyz;
    */

} octeon_cn6xxx_t;

17.1. 2A.cn6xxx_config_t

/** Structure to define the configuration for CN61XX,CN63XX,CN66XX & CN68XX Octeon processors. */
typedef  struct {
    /** Common attributes. */
    octeon_common_config_t  c; //num_iqs num_oqs pending_list_size
    /** Input Queue attributes. */
    /*num_descs: 每个ring有多少个命令
    **instr_type: 是32bit还是64bit格式的
    **db_min: 发doorbell之前需要准备好多少个command
    **db_timeout: 在查询pending的command之前的超时时间
    */
    octeon_iq_config_t      iq[CN6XXX_MAX_INPUT_QUEUES];

    /** Some of the Output Queue attributes. */
    /*num_descs: 每个ring多少个描述符
    **info_ptr: 默认是1, 表示使用info指针模式
    **buf_size: buffer大小
    **pkts_per_intr: 每次调用driver的tasklet要处理多少个packets
    **refill_threshold: 小于此值, 驱动需要充填(replenish)
    */
    cn6xxx_oq_config_t      oq[CN6XXX_MAX_OUTPUT_QUEUES];
    /** Interrupt Coalescing (Packet Count). Octeon will interrupt the host
        only if it sent as many packets as specified by this field. The driver
        usually does not use packet count interrupt coalescing. 
        All output queues have the same packet count setting. */
    //两种中断机制之一, 时间间隔
    uint32_t                oq_intr_pkt;
    /** Interrupt Coalescing (Time Interval). Octeon will interrupt the host
        if atleast one packet was sent in the time interval specified by this
        field. The driver uses time interval interrupt coalescing by default.
        The time is specified in microseconds.
        All output queues have the same time interval setting. */
    uint32_t                oq_intr_time;
#ifdef CVMCS_DMA_IC
    /** Interrupt Coalescing (Packet Count). Octeon will interrupt the host
        only if it DMAed as many packets as specified by this field. */
    //两种中断机制之二, 已经DMA的报文数
    uint32_t                dma_intr_pkt;
    /** Interrupt Coalescing (Time Interval). Octeon will interrupt the host
        if atleast one packet was DMAed in the time interval specified by this
        field. */ 
    uint32_t                dma_intr_time;
#endif
} cn6xxx_config_t;

results matching ""

    No results matching ""