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 #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     /* Wait for HW to ACK disable request */
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 }