1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. 3 * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4 */ 5 6 #ifndef _VNIC_CQ_H_ 7 #define _VNIC_CQ_H_ 8 9 #include "cq_desc.h" 10 #include "vnic_dev.h" 11 12 /* Completion queue control */ 13 struct vnic_cq_ctrl { 14 u64 ring_base; /* 0x00 */ 15 #define CQ_RING_BASE 0x00 16 u32 ring_size; /* 0x08 */ 17 #define CQ_RING_SIZE 0x08 18 u32 pad0; 19 u32 flow_control_enable; /* 0x10 */ 20 #define CQ_FLOW_CONTROL_ENABLE 0x10 21 u32 pad1; 22 u32 color_enable; /* 0x18 */ 23 #define CQ_COLOR_ENABLE 0x18 24 u32 pad2; 25 u32 cq_head; /* 0x20 */ 26 #define CQ_HEAD 0x20 27 u32 pad3; 28 u32 cq_tail; /* 0x28 */ 29 #define CQ_TAIL 0x28 30 u32 pad4; 31 u32 cq_tail_color; /* 0x30 */ 32 #define CQ_TAIL_COLOR 0x30 33 u32 pad5; 34 u32 interrupt_enable; /* 0x38 */ 35 #define CQ_INTR_ENABLE 0x38 36 u32 pad6; 37 u32 cq_entry_enable; /* 0x40 */ 38 #define CQ_ENTRY_ENABLE 0x40 39 u32 pad7; 40 u32 cq_message_enable; /* 0x48 */ 41 #define CQ_MESSAGE_ENABLE 0x48 42 u32 pad8; 43 u32 interrupt_offset; /* 0x50 */ 44 #define CQ_INTR_OFFSET 0x50 45 u32 pad9; 46 u64 cq_message_addr; /* 0x58 */ 47 #define CQ_MESSAGE_ADDR 0x58 48 u32 pad10; 49 }; 50 51 #ifdef ENIC_AIC 52 struct vnic_rx_bytes_counter { 53 unsigned int small_pkt_bytes_cnt; 54 unsigned int large_pkt_bytes_cnt; 55 }; 56 #endif 57 58 struct vnic_cq { 59 unsigned int index; 60 struct vnic_dev *vdev; 61 struct vnic_res *ctrl; 62 struct vnic_dev_ring ring; 63 unsigned int to_clean; 64 unsigned int last_color; 65 unsigned int interrupt_offset; 66 #ifdef ENIC_AIC 67 struct vnic_rx_bytes_counter pkt_size_counter; 68 unsigned int cur_rx_coal_timeval; 69 unsigned int tobe_rx_coal_timeval; 70 ktime_t prev_ts; 71 #endif 72 int ntxqsets; 73 int nrxqsets; 74 int ntxqsets_start; 75 int nrxqsets_start; 76 }; 77 78 void vnic_cq_free(struct vnic_cq *cq); 79 void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, 80 unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, 81 unsigned int cq_tail_color, unsigned int interrupt_enable, 82 unsigned int cq_entry_enable, unsigned int message_enable, 83 unsigned int interrupt_offset, u64 message_addr); 84 void vnic_cq_clean(struct vnic_cq *cq); 85 int vnic_cq_mem_size(struct vnic_cq *cq, unsigned int desc_count, 86 unsigned int desc_size); 87 88 static inline unsigned int vnic_cq_service(struct vnic_cq *cq, 89 unsigned int work_to_do, 90 int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc, 91 u8 type, u16 q_number, u16 completed_index, void *opaque), 92 void *opaque) 93 { 94 struct cq_desc *cq_desc; 95 unsigned int work_done = 0; 96 u16 q_number, completed_index; 97 u8 type, color; 98 99 cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + 100 cq->ring.desc_size * cq->to_clean); 101 cq_desc_dec(cq_desc, &type, &color, 102 &q_number, &completed_index); 103 104 while (color != cq->last_color) { 105 if ((*q_service)(cq->vdev, cq_desc, type, 106 q_number, completed_index, opaque)) 107 break; 108 109 cq->to_clean++; 110 if (cq->to_clean == cq->ring.desc_count) { 111 cq->to_clean = 0; 112 cq->last_color = cq->last_color ? 0 : 1; 113 } 114 115 cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + 116 cq->ring.desc_size * cq->to_clean); 117 cq_desc_dec(cq_desc, &type, &color, 118 &q_number, &completed_index); 119 120 work_done++; 121 if (work_done >= work_to_do) 122 break; 123 } 124 125 return work_done; 126 } 127 128 static inline unsigned int vnic_cq_work(struct vnic_cq *cq, 129 unsigned int work_to_do) 130 { 131 struct cq_desc *cq_desc; 132 unsigned int work_avail = 0; 133 u16 q_number, completed_index; 134 u8 type, color; 135 u32 to_clean, last_color; 136 137 to_clean = cq->to_clean; 138 last_color = cq->last_color; 139 cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + 140 cq->ring.desc_size * to_clean); 141 cq_desc_dec(cq_desc, &type, &color, 142 &q_number, &completed_index); 143 144 while (color != last_color) { 145 to_clean++; 146 if (to_clean == cq->ring.desc_count) { 147 to_clean = 0; 148 last_color = last_color ? 0 : 1; 149 } 150 151 cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + 152 cq->ring.desc_size * to_clean); 153 cq_desc_dec(cq_desc, &type, &color, 154 &q_number, &completed_index); 155 156 work_avail++; 157 if (work_avail >= work_to_do) 158 break; 159 } 160 161 return work_avail; 162 } 163 164 #endif /* _VNIC_CQ_H_ */ 165