101f2e4eaSScott Feldman /* 229046f9bSVasanthy Kolluri * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. 301f2e4eaSScott Feldman * Copyright 2007 Nuova Systems, Inc. All rights reserved. 401f2e4eaSScott Feldman * 501f2e4eaSScott Feldman * This program is free software; you may redistribute it and/or modify 601f2e4eaSScott Feldman * it under the terms of the GNU General Public License as published by 701f2e4eaSScott Feldman * the Free Software Foundation; version 2 of the License. 801f2e4eaSScott Feldman * 901f2e4eaSScott Feldman * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1001f2e4eaSScott Feldman * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1101f2e4eaSScott Feldman * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1201f2e4eaSScott Feldman * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1301f2e4eaSScott Feldman * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1401f2e4eaSScott Feldman * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1501f2e4eaSScott Feldman * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1601f2e4eaSScott Feldman * SOFTWARE. 1701f2e4eaSScott Feldman * 1801f2e4eaSScott Feldman */ 1901f2e4eaSScott Feldman 2001f2e4eaSScott Feldman #ifndef _VNIC_CQ_H_ 2101f2e4eaSScott Feldman #define _VNIC_CQ_H_ 2201f2e4eaSScott Feldman 2301f2e4eaSScott Feldman #include "cq_desc.h" 2401f2e4eaSScott Feldman #include "vnic_dev.h" 2501f2e4eaSScott Feldman 2601f2e4eaSScott Feldman /* Completion queue control */ 2701f2e4eaSScott Feldman struct vnic_cq_ctrl { 2801f2e4eaSScott Feldman u64 ring_base; /* 0x00 */ 2901f2e4eaSScott Feldman u32 ring_size; /* 0x08 */ 3001f2e4eaSScott Feldman u32 pad0; 3101f2e4eaSScott Feldman u32 flow_control_enable; /* 0x10 */ 3201f2e4eaSScott Feldman u32 pad1; 3301f2e4eaSScott Feldman u32 color_enable; /* 0x18 */ 3401f2e4eaSScott Feldman u32 pad2; 3501f2e4eaSScott Feldman u32 cq_head; /* 0x20 */ 3601f2e4eaSScott Feldman u32 pad3; 3701f2e4eaSScott Feldman u32 cq_tail; /* 0x28 */ 3801f2e4eaSScott Feldman u32 pad4; 3901f2e4eaSScott Feldman u32 cq_tail_color; /* 0x30 */ 4001f2e4eaSScott Feldman u32 pad5; 4101f2e4eaSScott Feldman u32 interrupt_enable; /* 0x38 */ 4201f2e4eaSScott Feldman u32 pad6; 4301f2e4eaSScott Feldman u32 cq_entry_enable; /* 0x40 */ 4401f2e4eaSScott Feldman u32 pad7; 4501f2e4eaSScott Feldman u32 cq_message_enable; /* 0x48 */ 4601f2e4eaSScott Feldman u32 pad8; 4701f2e4eaSScott Feldman u32 interrupt_offset; /* 0x50 */ 4801f2e4eaSScott Feldman u32 pad9; 4901f2e4eaSScott Feldman u64 cq_message_addr; /* 0x58 */ 5001f2e4eaSScott Feldman u32 pad10; 5101f2e4eaSScott Feldman }; 5201f2e4eaSScott Feldman 53*7c2ce6e6SSujith Sankar struct vnic_rx_bytes_counter { 54*7c2ce6e6SSujith Sankar unsigned int small_pkt_bytes_cnt; 55*7c2ce6e6SSujith Sankar unsigned int large_pkt_bytes_cnt; 56*7c2ce6e6SSujith Sankar }; 57*7c2ce6e6SSujith Sankar 5801f2e4eaSScott Feldman struct vnic_cq { 5901f2e4eaSScott Feldman unsigned int index; 6001f2e4eaSScott Feldman struct vnic_dev *vdev; 6101f2e4eaSScott Feldman struct vnic_cq_ctrl __iomem *ctrl; /* memory-mapped */ 6201f2e4eaSScott Feldman struct vnic_dev_ring ring; 6301f2e4eaSScott Feldman unsigned int to_clean; 6401f2e4eaSScott Feldman unsigned int last_color; 657d260ec2SVasanthy Kolluri unsigned int interrupt_offset; 66*7c2ce6e6SSujith Sankar struct vnic_rx_bytes_counter pkt_size_counter; 67*7c2ce6e6SSujith Sankar unsigned int cur_rx_coal_timeval; 68*7c2ce6e6SSujith Sankar unsigned int tobe_rx_coal_timeval; 69*7c2ce6e6SSujith Sankar ktime_t prev_ts; 7001f2e4eaSScott Feldman }; 7101f2e4eaSScott Feldman 7201f2e4eaSScott Feldman static inline unsigned int vnic_cq_service(struct vnic_cq *cq, 7301f2e4eaSScott Feldman unsigned int work_to_do, 7401f2e4eaSScott Feldman int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc, 7501f2e4eaSScott Feldman u8 type, u16 q_number, u16 completed_index, void *opaque), 7601f2e4eaSScott Feldman void *opaque) 7701f2e4eaSScott Feldman { 7801f2e4eaSScott Feldman struct cq_desc *cq_desc; 7901f2e4eaSScott Feldman unsigned int work_done = 0; 8001f2e4eaSScott Feldman u16 q_number, completed_index; 8101f2e4eaSScott Feldman u8 type, color; 8201f2e4eaSScott Feldman 8301f2e4eaSScott Feldman cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + 8401f2e4eaSScott Feldman cq->ring.desc_size * cq->to_clean); 8501f2e4eaSScott Feldman cq_desc_dec(cq_desc, &type, &color, 8601f2e4eaSScott Feldman &q_number, &completed_index); 8701f2e4eaSScott Feldman 8801f2e4eaSScott Feldman while (color != cq->last_color) { 8901f2e4eaSScott Feldman 9001f2e4eaSScott Feldman if ((*q_service)(cq->vdev, cq_desc, type, 9101f2e4eaSScott Feldman q_number, completed_index, opaque)) 9201f2e4eaSScott Feldman break; 9301f2e4eaSScott Feldman 9401f2e4eaSScott Feldman cq->to_clean++; 9501f2e4eaSScott Feldman if (cq->to_clean == cq->ring.desc_count) { 9601f2e4eaSScott Feldman cq->to_clean = 0; 9701f2e4eaSScott Feldman cq->last_color = cq->last_color ? 0 : 1; 9801f2e4eaSScott Feldman } 9901f2e4eaSScott Feldman 10001f2e4eaSScott Feldman cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + 10101f2e4eaSScott Feldman cq->ring.desc_size * cq->to_clean); 10201f2e4eaSScott Feldman cq_desc_dec(cq_desc, &type, &color, 10301f2e4eaSScott Feldman &q_number, &completed_index); 10401f2e4eaSScott Feldman 10501f2e4eaSScott Feldman work_done++; 10601f2e4eaSScott Feldman if (work_done >= work_to_do) 10701f2e4eaSScott Feldman break; 10801f2e4eaSScott Feldman } 10901f2e4eaSScott Feldman 11001f2e4eaSScott Feldman return work_done; 11101f2e4eaSScott Feldman } 11201f2e4eaSScott Feldman 11301f2e4eaSScott Feldman void vnic_cq_free(struct vnic_cq *cq); 11401f2e4eaSScott Feldman int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, 11501f2e4eaSScott Feldman unsigned int desc_count, unsigned int desc_size); 11601f2e4eaSScott Feldman void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, 11701f2e4eaSScott Feldman unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, 11801f2e4eaSScott Feldman unsigned int cq_tail_color, unsigned int interrupt_enable, 11901f2e4eaSScott Feldman unsigned int cq_entry_enable, unsigned int message_enable, 12001f2e4eaSScott Feldman unsigned int interrupt_offset, u64 message_addr); 12101f2e4eaSScott Feldman void vnic_cq_clean(struct vnic_cq *cq); 12201f2e4eaSScott Feldman 12301f2e4eaSScott Feldman #endif /* _VNIC_CQ_H_ */ 124