Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /* Copyright 2014 Cisco Systems, Inc.  All rights reserved. */
0003 
0004 #ifndef _VNIC_CQ_H_
0005 #define _VNIC_CQ_H_
0006 
0007 #include "cq_desc.h"
0008 #include "vnic_dev.h"
0009 
0010 /* Completion queue control */
0011 struct vnic_cq_ctrl {
0012     u64 ring_base;          /* 0x00 */
0013     u32 ring_size;          /* 0x08 */
0014     u32 pad0;
0015     u32 flow_control_enable;    /* 0x10 */
0016     u32 pad1;
0017     u32 color_enable;       /* 0x18 */
0018     u32 pad2;
0019     u32 cq_head;            /* 0x20 */
0020     u32 pad3;
0021     u32 cq_tail;            /* 0x28 */
0022     u32 pad4;
0023     u32 cq_tail_color;      /* 0x30 */
0024     u32 pad5;
0025     u32 interrupt_enable;       /* 0x38 */
0026     u32 pad6;
0027     u32 cq_entry_enable;        /* 0x40 */
0028     u32 pad7;
0029     u32 cq_message_enable;      /* 0x48 */
0030     u32 pad8;
0031     u32 interrupt_offset;       /* 0x50 */
0032     u32 pad9;
0033     u64 cq_message_addr;        /* 0x58 */
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;  /* memory-mapped */
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 /* _VNIC_CQ_H_ */