0001
0002
0003
0004 #ifndef _VNIC_CQ_H_
0005 #define _VNIC_CQ_H_
0006
0007 #include "cq_desc.h"
0008 #include "vnic_dev.h"
0009
0010
0011 struct vnic_cq_ctrl {
0012 u64 ring_base;
0013 u32 ring_size;
0014 u32 pad0;
0015 u32 flow_control_enable;
0016 u32 pad1;
0017 u32 color_enable;
0018 u32 pad2;
0019 u32 cq_head;
0020 u32 pad3;
0021 u32 cq_tail;
0022 u32 pad4;
0023 u32 cq_tail_color;
0024 u32 pad5;
0025 u32 interrupt_enable;
0026 u32 pad6;
0027 u32 cq_entry_enable;
0028 u32 pad7;
0029 u32 cq_message_enable;
0030 u32 pad8;
0031 u32 interrupt_offset;
0032 u32 pad9;
0033 u64 cq_message_addr;
0034 u32 pad10;
0035 };
0036
0037 struct vnic_cq {
0038 unsigned int index;
0039 struct vnic_dev *vdev;
0040 struct vnic_cq_ctrl __iomem *ctrl;
0041 struct vnic_dev_ring ring;
0042 unsigned int to_clean;
0043 unsigned int last_color;
0044 };
0045
0046 static inline unsigned int svnic_cq_service(struct vnic_cq *cq,
0047 unsigned int work_to_do,
0048 int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc,
0049 u8 type, u16 q_number, u16 completed_index, void *opaque),
0050 void *opaque)
0051 {
0052 struct cq_desc *cq_desc;
0053 unsigned int work_done = 0;
0054 u16 q_number, completed_index;
0055 u8 type, color;
0056
0057 cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
0058 cq->ring.desc_size * cq->to_clean);
0059 cq_desc_dec(cq_desc, &type, &color,
0060 &q_number, &completed_index);
0061
0062 while (color != cq->last_color) {
0063
0064 if ((*q_service)(cq->vdev, cq_desc, type,
0065 q_number, completed_index, opaque))
0066 break;
0067
0068 cq->to_clean++;
0069 if (cq->to_clean == cq->ring.desc_count) {
0070 cq->to_clean = 0;
0071 cq->last_color = cq->last_color ? 0 : 1;
0072 }
0073
0074 cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
0075 cq->ring.desc_size * cq->to_clean);
0076 cq_desc_dec(cq_desc, &type, &color,
0077 &q_number, &completed_index);
0078
0079 work_done++;
0080 if (work_done >= work_to_do)
0081 break;
0082 }
0083
0084 return work_done;
0085 }
0086
0087 void svnic_cq_free(struct vnic_cq *cq);
0088 int svnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq,
0089 unsigned int index, unsigned int desc_count, unsigned int desc_size);
0090 void svnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
0091 unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail,
0092 unsigned int cq_tail_color, unsigned int interrupt_enable,
0093 unsigned int cq_entry_enable, unsigned int message_enable,
0094 unsigned int interrupt_offset, u64 message_addr);
0095 void svnic_cq_clean(struct vnic_cq *cq);
0096 #endif