16d935bddSGowrishankar Muthukrishnan /* SPDX-License-Identifier: BSD-3-Clause
26d935bddSGowrishankar Muthukrishnan * Copyright(C) 2024 Marvell.
36d935bddSGowrishankar Muthukrishnan */
46d935bddSGowrishankar Muthukrishnan
56d935bddSGowrishankar Muthukrishnan #include <stdint.h>
66d935bddSGowrishankar Muthukrishnan
76d935bddSGowrishankar Muthukrishnan #include <bus_pci_driver.h>
86d935bddSGowrishankar Muthukrishnan
96d935bddSGowrishankar Muthukrishnan #include <rte_io.h>
10*f317dc96SGowrishankar Muthukrishnan #include <rte_malloc.h>
116d935bddSGowrishankar Muthukrishnan
126d935bddSGowrishankar Muthukrishnan #include "odm.h"
136d935bddSGowrishankar Muthukrishnan #include "odm_priv.h"
146d935bddSGowrishankar Muthukrishnan
156d935bddSGowrishankar Muthukrishnan static void
odm_vchan_resc_free(struct odm_dev * odm,int qno)166d935bddSGowrishankar Muthukrishnan odm_vchan_resc_free(struct odm_dev *odm, int qno)
176d935bddSGowrishankar Muthukrishnan {
18*f317dc96SGowrishankar Muthukrishnan struct odm_queue *vq = &odm->vq[qno];
19*f317dc96SGowrishankar Muthukrishnan
20*f317dc96SGowrishankar Muthukrishnan rte_memzone_free(vq->iring_mz);
21*f317dc96SGowrishankar Muthukrishnan rte_memzone_free(vq->cring_mz);
22*f317dc96SGowrishankar Muthukrishnan rte_free(vq->extra_ins_sz);
23*f317dc96SGowrishankar Muthukrishnan
24*f317dc96SGowrishankar Muthukrishnan vq->iring_mz = NULL;
25*f317dc96SGowrishankar Muthukrishnan vq->cring_mz = NULL;
26*f317dc96SGowrishankar Muthukrishnan vq->extra_ins_sz = NULL;
276d935bddSGowrishankar Muthukrishnan }
286d935bddSGowrishankar Muthukrishnan
296d935bddSGowrishankar Muthukrishnan static int
send_mbox_to_pf(struct odm_dev * odm,union odm_mbox_msg * msg,union odm_mbox_msg * rsp)306d935bddSGowrishankar Muthukrishnan send_mbox_to_pf(struct odm_dev *odm, union odm_mbox_msg *msg, union odm_mbox_msg *rsp)
316d935bddSGowrishankar Muthukrishnan {
326d935bddSGowrishankar Muthukrishnan int retry_cnt = ODM_MBOX_RETRY_CNT;
336d935bddSGowrishankar Muthukrishnan union odm_mbox_msg pf_msg;
346d935bddSGowrishankar Muthukrishnan
356d935bddSGowrishankar Muthukrishnan msg->d.err = ODM_MBOX_ERR_CODE_MAX;
366d935bddSGowrishankar Muthukrishnan odm_write64(msg->u[0], odm->rbase + ODM_MBOX_VF_PF_DATA(0));
376d935bddSGowrishankar Muthukrishnan odm_write64(msg->u[1], odm->rbase + ODM_MBOX_VF_PF_DATA(1));
386d935bddSGowrishankar Muthukrishnan
396d935bddSGowrishankar Muthukrishnan pf_msg.u[0] = 0;
406d935bddSGowrishankar Muthukrishnan pf_msg.u[1] = 0;
416d935bddSGowrishankar Muthukrishnan pf_msg.u[0] = odm_read64(odm->rbase + ODM_MBOX_VF_PF_DATA(0));
426d935bddSGowrishankar Muthukrishnan
436d935bddSGowrishankar Muthukrishnan while (pf_msg.d.rsp == 0 && retry_cnt > 0) {
446d935bddSGowrishankar Muthukrishnan pf_msg.u[0] = odm_read64(odm->rbase + ODM_MBOX_VF_PF_DATA(0));
456d935bddSGowrishankar Muthukrishnan --retry_cnt;
466d935bddSGowrishankar Muthukrishnan }
476d935bddSGowrishankar Muthukrishnan
486d935bddSGowrishankar Muthukrishnan if (retry_cnt <= 0)
496d935bddSGowrishankar Muthukrishnan return -EBADE;
506d935bddSGowrishankar Muthukrishnan
516d935bddSGowrishankar Muthukrishnan pf_msg.u[1] = odm_read64(odm->rbase + ODM_MBOX_VF_PF_DATA(1));
526d935bddSGowrishankar Muthukrishnan
536d935bddSGowrishankar Muthukrishnan if (rsp) {
546d935bddSGowrishankar Muthukrishnan rsp->u[0] = pf_msg.u[0];
556d935bddSGowrishankar Muthukrishnan rsp->u[1] = pf_msg.u[1];
566d935bddSGowrishankar Muthukrishnan }
576d935bddSGowrishankar Muthukrishnan
586d935bddSGowrishankar Muthukrishnan if (pf_msg.d.rsp == msg->d.err && pf_msg.d.err != 0)
596d935bddSGowrishankar Muthukrishnan return -EBADE;
606d935bddSGowrishankar Muthukrishnan
616d935bddSGowrishankar Muthukrishnan return 0;
626d935bddSGowrishankar Muthukrishnan }
636d935bddSGowrishankar Muthukrishnan
64*f317dc96SGowrishankar Muthukrishnan static int
odm_queue_ring_config(struct odm_dev * odm,int vchan,int isize,int csize)65*f317dc96SGowrishankar Muthukrishnan odm_queue_ring_config(struct odm_dev *odm, int vchan, int isize, int csize)
66*f317dc96SGowrishankar Muthukrishnan {
67*f317dc96SGowrishankar Muthukrishnan union odm_vdma_ring_cfg_s ring_cfg = {0};
68*f317dc96SGowrishankar Muthukrishnan struct odm_queue *vq = &odm->vq[vchan];
69*f317dc96SGowrishankar Muthukrishnan
70*f317dc96SGowrishankar Muthukrishnan if (vq->iring_mz == NULL || vq->cring_mz == NULL)
71*f317dc96SGowrishankar Muthukrishnan return -EINVAL;
72*f317dc96SGowrishankar Muthukrishnan
73*f317dc96SGowrishankar Muthukrishnan ring_cfg.s.isize = (isize / 1024) - 1;
74*f317dc96SGowrishankar Muthukrishnan ring_cfg.s.csize = (csize / 1024) - 1;
75*f317dc96SGowrishankar Muthukrishnan
76*f317dc96SGowrishankar Muthukrishnan odm_write64(ring_cfg.u, odm->rbase + ODM_VDMA_RING_CFG(vchan));
77*f317dc96SGowrishankar Muthukrishnan odm_write64(vq->iring_mz->iova, odm->rbase + ODM_VDMA_IRING_BADDR(vchan));
78*f317dc96SGowrishankar Muthukrishnan odm_write64(vq->cring_mz->iova, odm->rbase + ODM_VDMA_CRING_BADDR(vchan));
79*f317dc96SGowrishankar Muthukrishnan
80*f317dc96SGowrishankar Muthukrishnan return 0;
81*f317dc96SGowrishankar Muthukrishnan }
82*f317dc96SGowrishankar Muthukrishnan
83*f317dc96SGowrishankar Muthukrishnan int
odm_enable(struct odm_dev * odm)84*f317dc96SGowrishankar Muthukrishnan odm_enable(struct odm_dev *odm)
85*f317dc96SGowrishankar Muthukrishnan {
86*f317dc96SGowrishankar Muthukrishnan struct odm_queue *vq;
87*f317dc96SGowrishankar Muthukrishnan int qno, rc = 0;
88*f317dc96SGowrishankar Muthukrishnan
89*f317dc96SGowrishankar Muthukrishnan for (qno = 0; qno < odm->num_qs; qno++) {
90*f317dc96SGowrishankar Muthukrishnan vq = &odm->vq[qno];
91*f317dc96SGowrishankar Muthukrishnan
92*f317dc96SGowrishankar Muthukrishnan vq->desc_idx = vq->stats.completed_offset;
93*f317dc96SGowrishankar Muthukrishnan vq->pending_submit_len = 0;
94*f317dc96SGowrishankar Muthukrishnan vq->pending_submit_cnt = 0;
95*f317dc96SGowrishankar Muthukrishnan vq->iring_head = 0;
96*f317dc96SGowrishankar Muthukrishnan vq->cring_head = 0;
97*f317dc96SGowrishankar Muthukrishnan vq->ins_ring_head = 0;
98*f317dc96SGowrishankar Muthukrishnan vq->iring_sz_available = vq->iring_max_words;
99*f317dc96SGowrishankar Muthukrishnan
100*f317dc96SGowrishankar Muthukrishnan rc = odm_queue_ring_config(odm, qno, vq->iring_max_words * 8,
101*f317dc96SGowrishankar Muthukrishnan vq->cring_max_entry * 4);
102*f317dc96SGowrishankar Muthukrishnan if (rc < 0)
103*f317dc96SGowrishankar Muthukrishnan break;
104*f317dc96SGowrishankar Muthukrishnan
105*f317dc96SGowrishankar Muthukrishnan odm_write64(0x1, odm->rbase + ODM_VDMA_EN(qno));
106*f317dc96SGowrishankar Muthukrishnan }
107*f317dc96SGowrishankar Muthukrishnan
108*f317dc96SGowrishankar Muthukrishnan return rc;
109*f317dc96SGowrishankar Muthukrishnan }
110*f317dc96SGowrishankar Muthukrishnan
111*f317dc96SGowrishankar Muthukrishnan int
odm_disable(struct odm_dev * odm)112*f317dc96SGowrishankar Muthukrishnan odm_disable(struct odm_dev *odm)
113*f317dc96SGowrishankar Muthukrishnan {
114*f317dc96SGowrishankar Muthukrishnan int qno, wait_cnt = ODM_IRING_IDLE_WAIT_CNT;
115*f317dc96SGowrishankar Muthukrishnan uint64_t val;
116*f317dc96SGowrishankar Muthukrishnan
117*f317dc96SGowrishankar Muthukrishnan /* Disable the queue and wait for the queue to became idle */
118*f317dc96SGowrishankar Muthukrishnan for (qno = 0; qno < odm->num_qs; qno++) {
119*f317dc96SGowrishankar Muthukrishnan odm_write64(0x0, odm->rbase + ODM_VDMA_EN(qno));
120*f317dc96SGowrishankar Muthukrishnan do {
121*f317dc96SGowrishankar Muthukrishnan val = odm_read64(odm->rbase + ODM_VDMA_IRING_BADDR(qno));
122*f317dc96SGowrishankar Muthukrishnan } while ((!(val & 1ULL << 63)) && (--wait_cnt > 0));
123*f317dc96SGowrishankar Muthukrishnan }
124*f317dc96SGowrishankar Muthukrishnan
125*f317dc96SGowrishankar Muthukrishnan return 0;
126*f317dc96SGowrishankar Muthukrishnan }
127*f317dc96SGowrishankar Muthukrishnan
128*f317dc96SGowrishankar Muthukrishnan int
odm_vchan_setup(struct odm_dev * odm,int vchan,int nb_desc)129*f317dc96SGowrishankar Muthukrishnan odm_vchan_setup(struct odm_dev *odm, int vchan, int nb_desc)
130*f317dc96SGowrishankar Muthukrishnan {
131*f317dc96SGowrishankar Muthukrishnan struct odm_queue *vq = &odm->vq[vchan];
132*f317dc96SGowrishankar Muthukrishnan int isize, csize, max_nb_desc, rc = 0;
133*f317dc96SGowrishankar Muthukrishnan union odm_mbox_msg mbox_msg;
134*f317dc96SGowrishankar Muthukrishnan const struct rte_memzone *mz;
135*f317dc96SGowrishankar Muthukrishnan char name[32];
136*f317dc96SGowrishankar Muthukrishnan
137*f317dc96SGowrishankar Muthukrishnan if (vq->iring_mz != NULL)
138*f317dc96SGowrishankar Muthukrishnan odm_vchan_resc_free(odm, vchan);
139*f317dc96SGowrishankar Muthukrishnan
140*f317dc96SGowrishankar Muthukrishnan mbox_msg.u[0] = 0;
141*f317dc96SGowrishankar Muthukrishnan mbox_msg.u[1] = 0;
142*f317dc96SGowrishankar Muthukrishnan
143*f317dc96SGowrishankar Muthukrishnan /* ODM PF driver expects vfid starts from index 0 */
144*f317dc96SGowrishankar Muthukrishnan mbox_msg.q.vfid = odm->vfid;
145*f317dc96SGowrishankar Muthukrishnan mbox_msg.q.cmd = ODM_QUEUE_OPEN;
146*f317dc96SGowrishankar Muthukrishnan mbox_msg.q.qidx = vchan;
147*f317dc96SGowrishankar Muthukrishnan rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
148*f317dc96SGowrishankar Muthukrishnan if (rc < 0)
149*f317dc96SGowrishankar Muthukrishnan return rc;
150*f317dc96SGowrishankar Muthukrishnan
151*f317dc96SGowrishankar Muthukrishnan /* Determine instruction & completion ring sizes. */
152*f317dc96SGowrishankar Muthukrishnan
153*f317dc96SGowrishankar Muthukrishnan /* Create iring that can support nb_desc. Round up to a multiple of 1024. */
154*f317dc96SGowrishankar Muthukrishnan isize = RTE_ALIGN_CEIL(nb_desc * ODM_IRING_ENTRY_SIZE_MAX * 8, 1024);
155*f317dc96SGowrishankar Muthukrishnan isize = RTE_MIN(isize, ODM_IRING_MAX_SIZE);
156*f317dc96SGowrishankar Muthukrishnan snprintf(name, sizeof(name), "vq%d_iring%d", odm->vfid, vchan);
157*f317dc96SGowrishankar Muthukrishnan mz = rte_memzone_reserve_aligned(name, isize, SOCKET_ID_ANY, 0, 1024);
158*f317dc96SGowrishankar Muthukrishnan if (mz == NULL)
159*f317dc96SGowrishankar Muthukrishnan return -ENOMEM;
160*f317dc96SGowrishankar Muthukrishnan vq->iring_mz = mz;
161*f317dc96SGowrishankar Muthukrishnan vq->iring_max_words = isize / 8;
162*f317dc96SGowrishankar Muthukrishnan
163*f317dc96SGowrishankar Muthukrishnan /* Create cring that can support max instructions that can be inflight in hw. */
164*f317dc96SGowrishankar Muthukrishnan max_nb_desc = (isize / (ODM_IRING_ENTRY_SIZE_MIN * 8));
165*f317dc96SGowrishankar Muthukrishnan csize = RTE_ALIGN_CEIL(max_nb_desc * sizeof(union odm_cmpl_ent_s), 1024);
166*f317dc96SGowrishankar Muthukrishnan snprintf(name, sizeof(name), "vq%d_cring%d", odm->vfid, vchan);
167*f317dc96SGowrishankar Muthukrishnan mz = rte_memzone_reserve_aligned(name, csize, SOCKET_ID_ANY, 0, 1024);
168*f317dc96SGowrishankar Muthukrishnan if (mz == NULL) {
169*f317dc96SGowrishankar Muthukrishnan rc = -ENOMEM;
170*f317dc96SGowrishankar Muthukrishnan goto iring_free;
171*f317dc96SGowrishankar Muthukrishnan }
172*f317dc96SGowrishankar Muthukrishnan vq->cring_mz = mz;
173*f317dc96SGowrishankar Muthukrishnan vq->cring_max_entry = csize / 4;
174*f317dc96SGowrishankar Muthukrishnan
175*f317dc96SGowrishankar Muthukrishnan /* Allocate memory to track the size of each instruction. */
176*f317dc96SGowrishankar Muthukrishnan snprintf(name, sizeof(name), "vq%d_extra%d", odm->vfid, vchan);
177*f317dc96SGowrishankar Muthukrishnan vq->extra_ins_sz = rte_zmalloc(name, vq->cring_max_entry, 0);
178*f317dc96SGowrishankar Muthukrishnan if (vq->extra_ins_sz == NULL) {
179*f317dc96SGowrishankar Muthukrishnan rc = -ENOMEM;
180*f317dc96SGowrishankar Muthukrishnan goto cring_free;
181*f317dc96SGowrishankar Muthukrishnan }
182*f317dc96SGowrishankar Muthukrishnan
183*f317dc96SGowrishankar Muthukrishnan vq->stats = (struct vq_stats){0};
184*f317dc96SGowrishankar Muthukrishnan return rc;
185*f317dc96SGowrishankar Muthukrishnan
186*f317dc96SGowrishankar Muthukrishnan cring_free:
187*f317dc96SGowrishankar Muthukrishnan rte_memzone_free(odm->vq[vchan].cring_mz);
188*f317dc96SGowrishankar Muthukrishnan vq->cring_mz = NULL;
189*f317dc96SGowrishankar Muthukrishnan iring_free:
190*f317dc96SGowrishankar Muthukrishnan rte_memzone_free(odm->vq[vchan].iring_mz);
191*f317dc96SGowrishankar Muthukrishnan vq->iring_mz = NULL;
192*f317dc96SGowrishankar Muthukrishnan
193*f317dc96SGowrishankar Muthukrishnan return rc;
194*f317dc96SGowrishankar Muthukrishnan }
195*f317dc96SGowrishankar Muthukrishnan
1966d935bddSGowrishankar Muthukrishnan int
odm_dev_init(struct odm_dev * odm)1976d935bddSGowrishankar Muthukrishnan odm_dev_init(struct odm_dev *odm)
1986d935bddSGowrishankar Muthukrishnan {
1996d935bddSGowrishankar Muthukrishnan struct rte_pci_device *pci_dev = odm->pci_dev;
2006d935bddSGowrishankar Muthukrishnan union odm_mbox_msg mbox_msg;
2016d935bddSGowrishankar Muthukrishnan uint16_t vfid;
2026d935bddSGowrishankar Muthukrishnan int rc;
2036d935bddSGowrishankar Muthukrishnan
2046d935bddSGowrishankar Muthukrishnan odm->rbase = pci_dev->mem_resource[0].addr;
2056d935bddSGowrishankar Muthukrishnan vfid = ((pci_dev->addr.devid & 0x1F) << 3) | (pci_dev->addr.function & 0x7);
2066d935bddSGowrishankar Muthukrishnan vfid -= 1;
2076d935bddSGowrishankar Muthukrishnan odm->vfid = vfid;
2086d935bddSGowrishankar Muthukrishnan odm->num_qs = 0;
2096d935bddSGowrishankar Muthukrishnan
2106d935bddSGowrishankar Muthukrishnan mbox_msg.u[0] = 0;
2116d935bddSGowrishankar Muthukrishnan mbox_msg.u[1] = 0;
2126d935bddSGowrishankar Muthukrishnan mbox_msg.q.vfid = odm->vfid;
2136d935bddSGowrishankar Muthukrishnan mbox_msg.q.cmd = ODM_DEV_INIT;
2146d935bddSGowrishankar Muthukrishnan rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
2156d935bddSGowrishankar Muthukrishnan if (!rc)
2166d935bddSGowrishankar Muthukrishnan odm->max_qs = 1 << (4 - mbox_msg.d.nvfs);
2176d935bddSGowrishankar Muthukrishnan
2186d935bddSGowrishankar Muthukrishnan return rc;
2196d935bddSGowrishankar Muthukrishnan }
2206d935bddSGowrishankar Muthukrishnan
2216d935bddSGowrishankar Muthukrishnan int
odm_dev_fini(struct odm_dev * odm)2226d935bddSGowrishankar Muthukrishnan odm_dev_fini(struct odm_dev *odm)
2236d935bddSGowrishankar Muthukrishnan {
2246d935bddSGowrishankar Muthukrishnan union odm_mbox_msg mbox_msg;
2256d935bddSGowrishankar Muthukrishnan int qno, rc = 0;
2266d935bddSGowrishankar Muthukrishnan
2276d935bddSGowrishankar Muthukrishnan mbox_msg.u[0] = 0;
2286d935bddSGowrishankar Muthukrishnan mbox_msg.u[1] = 0;
2296d935bddSGowrishankar Muthukrishnan mbox_msg.q.vfid = odm->vfid;
2306d935bddSGowrishankar Muthukrishnan mbox_msg.q.cmd = ODM_DEV_CLOSE;
2316d935bddSGowrishankar Muthukrishnan rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
2326d935bddSGowrishankar Muthukrishnan
2336d935bddSGowrishankar Muthukrishnan for (qno = 0; qno < odm->num_qs; qno++)
2346d935bddSGowrishankar Muthukrishnan odm_vchan_resc_free(odm, qno);
2356d935bddSGowrishankar Muthukrishnan
2366d935bddSGowrishankar Muthukrishnan return rc;
2376d935bddSGowrishankar Muthukrishnan }
238