0001
0002
0003
0004 #include <linux/errno.h>
0005 #include <linux/types.h>
0006 #include <linux/pci.h>
0007 #include <linux/delay.h>
0008 #include <linux/slab.h>
0009 #include "vnic_dev.h"
0010 #include "vnic_wq.h"
0011
0012 static inline int vnic_wq_get_ctrl(struct vnic_dev *vdev, struct vnic_wq *wq,
0013 unsigned int index, enum vnic_res_type res_type)
0014 {
0015 wq->ctrl = svnic_dev_get_res(vdev, res_type, index);
0016 if (!wq->ctrl)
0017 return -EINVAL;
0018
0019 return 0;
0020 }
0021
0022 static inline int vnic_wq_alloc_ring(struct vnic_dev *vdev, struct vnic_wq *wq,
0023 unsigned int index, unsigned int desc_count, unsigned int desc_size)
0024 {
0025 return svnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count,
0026 desc_size);
0027 }
0028
0029 static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
0030 {
0031 struct vnic_wq_buf *buf;
0032 unsigned int i, j, count = wq->ring.desc_count;
0033 unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
0034
0035 for (i = 0; i < blks; i++) {
0036 wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ, GFP_ATOMIC);
0037 if (!wq->bufs[i]) {
0038 pr_err("Failed to alloc wq_bufs\n");
0039
0040 return -ENOMEM;
0041 }
0042 }
0043
0044 for (i = 0; i < blks; i++) {
0045 buf = wq->bufs[i];
0046 for (j = 0; j < VNIC_WQ_BUF_DFLT_BLK_ENTRIES; j++) {
0047 buf->index = i * VNIC_WQ_BUF_DFLT_BLK_ENTRIES + j;
0048 buf->desc = (u8 *)wq->ring.descs +
0049 wq->ring.desc_size * buf->index;
0050 if (buf->index + 1 == count) {
0051 buf->next = wq->bufs[0];
0052 break;
0053 } else if (j + 1 == VNIC_WQ_BUF_DFLT_BLK_ENTRIES) {
0054 buf->next = wq->bufs[i + 1];
0055 } else {
0056 buf->next = buf + 1;
0057 buf++;
0058 }
0059 }
0060 }
0061
0062 wq->to_use = wq->to_clean = wq->bufs[0];
0063
0064 return 0;
0065 }
0066
0067 void svnic_wq_free(struct vnic_wq *wq)
0068 {
0069 struct vnic_dev *vdev;
0070 unsigned int i;
0071
0072 vdev = wq->vdev;
0073
0074 svnic_dev_free_desc_ring(vdev, &wq->ring);
0075
0076 for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) {
0077 kfree(wq->bufs[i]);
0078 wq->bufs[i] = NULL;
0079 }
0080
0081 wq->ctrl = NULL;
0082
0083 }
0084
0085 int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
0086 unsigned int desc_count, unsigned int desc_size)
0087 {
0088 int err;
0089
0090 wq->index = 0;
0091 wq->vdev = vdev;
0092
0093 err = vnic_wq_get_ctrl(vdev, wq, 0, RES_TYPE_DEVCMD2);
0094 if (err) {
0095 pr_err("Failed to get devcmd2 resource\n");
0096
0097 return err;
0098 }
0099
0100 svnic_wq_disable(wq);
0101
0102 err = vnic_wq_alloc_ring(vdev, wq, 0, desc_count, desc_size);
0103 if (err)
0104 return err;
0105
0106 return 0;
0107 }
0108
0109 int svnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
0110 unsigned int index, unsigned int desc_count, unsigned int desc_size)
0111 {
0112 int err;
0113
0114 wq->index = index;
0115 wq->vdev = vdev;
0116
0117 err = vnic_wq_get_ctrl(vdev, wq, index, RES_TYPE_WQ);
0118 if (err) {
0119 pr_err("Failed to hook WQ[%d] resource\n", index);
0120
0121 return err;
0122 }
0123
0124 svnic_wq_disable(wq);
0125
0126 err = vnic_wq_alloc_ring(vdev, wq, index, desc_count, desc_size);
0127 if (err)
0128 return err;
0129
0130 err = vnic_wq_alloc_bufs(wq);
0131 if (err) {
0132 svnic_wq_free(wq);
0133
0134 return err;
0135 }
0136
0137 return 0;
0138 }
0139
0140 void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
0141 unsigned int fetch_index, unsigned int posted_index,
0142 unsigned int error_interrupt_enable,
0143 unsigned int error_interrupt_offset)
0144 {
0145 u64 paddr;
0146 unsigned int count = wq->ring.desc_count;
0147
0148 paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;
0149 writeq(paddr, &wq->ctrl->ring_base);
0150 iowrite32(count, &wq->ctrl->ring_size);
0151 iowrite32(fetch_index, &wq->ctrl->fetch_index);
0152 iowrite32(posted_index, &wq->ctrl->posted_index);
0153 iowrite32(cq_index, &wq->ctrl->cq_index);
0154 iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);
0155 iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);
0156 iowrite32(0, &wq->ctrl->error_status);
0157
0158 wq->to_use = wq->to_clean =
0159 &wq->bufs[fetch_index / VNIC_WQ_BUF_BLK_ENTRIES(count)]
0160 [fetch_index % VNIC_WQ_BUF_BLK_ENTRIES(count)];
0161 }
0162
0163 void svnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
0164 unsigned int error_interrupt_enable,
0165 unsigned int error_interrupt_offset)
0166 {
0167 vnic_wq_init_start(wq, cq_index, 0, 0, error_interrupt_enable,
0168 error_interrupt_offset);
0169 }
0170
0171 unsigned int svnic_wq_error_status(struct vnic_wq *wq)
0172 {
0173 return ioread32(&wq->ctrl->error_status);
0174 }
0175
0176 void svnic_wq_enable(struct vnic_wq *wq)
0177 {
0178 iowrite32(1, &wq->ctrl->enable);
0179 }
0180
0181 int svnic_wq_disable(struct vnic_wq *wq)
0182 {
0183 unsigned int wait;
0184
0185 iowrite32(0, &wq->ctrl->enable);
0186
0187
0188 for (wait = 0; wait < 100; wait++) {
0189 if (!(ioread32(&wq->ctrl->running)))
0190 return 0;
0191 udelay(1);
0192 }
0193
0194 pr_err("Failed to disable WQ[%d]\n", wq->index);
0195
0196 return -ETIMEDOUT;
0197 }
0198
0199 void svnic_wq_clean(struct vnic_wq *wq,
0200 void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf))
0201 {
0202 struct vnic_wq_buf *buf;
0203
0204 BUG_ON(ioread32(&wq->ctrl->enable));
0205
0206 buf = wq->to_clean;
0207
0208 while (svnic_wq_desc_used(wq) > 0) {
0209
0210 (*buf_clean)(wq, buf);
0211
0212 buf = wq->to_clean = buf->next;
0213 wq->ring.desc_avail++;
0214 }
0215
0216 wq->to_use = wq->to_clean = wq->bufs[0];
0217
0218 iowrite32(0, &wq->ctrl->fetch_index);
0219 iowrite32(0, &wq->ctrl->posted_index);
0220 iowrite32(0, &wq->ctrl->error_status);
0221
0222 svnic_dev_clear_desc_ring(&wq->ring);
0223 }