]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. | |
7c673cae | 3 | * Copyright 2007 Nuova Systems, Inc. All rights reserved. |
7c673cae FG |
4 | */ |
5 | ||
6 | #include "vnic_dev.h" | |
7 | #include "vnic_wq.h" | |
8 | ||
9 | static inline | |
10 | int vnic_wq_get_ctrl(struct vnic_dev *vdev, struct vnic_wq *wq, | |
11 | unsigned int index, enum vnic_res_type res_type) | |
12 | { | |
13 | wq->ctrl = vnic_dev_get_res(vdev, res_type, index); | |
14 | if (!wq->ctrl) | |
15 | return -EINVAL; | |
16 | return 0; | |
17 | } | |
18 | ||
19 | static inline | |
20 | int vnic_wq_alloc_ring(struct vnic_dev *vdev, struct vnic_wq *wq, | |
21 | unsigned int desc_count, unsigned int desc_size) | |
22 | { | |
23 | char res_name[NAME_MAX]; | |
24 | static int instance; | |
25 | ||
9f95a23c | 26 | snprintf(res_name, sizeof(res_name), "%d-wq-%u", instance++, wq->index); |
7c673cae FG |
27 | return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size, |
28 | wq->socket_id, res_name); | |
29 | } | |
30 | ||
31 | static int vnic_wq_alloc_bufs(struct vnic_wq *wq) | |
32 | { | |
33 | unsigned int count = wq->ring.desc_count; | |
34 | /* Allocate the mbuf ring */ | |
9f95a23c TL |
35 | wq->bufs = (struct rte_mbuf **)rte_zmalloc_socket("wq->bufs", |
36 | sizeof(struct rte_mbuf *) * count, | |
7c673cae FG |
37 | RTE_CACHE_LINE_SIZE, wq->socket_id); |
38 | wq->head_idx = 0; | |
39 | wq->tail_idx = 0; | |
40 | if (wq->bufs == NULL) | |
41 | return -ENOMEM; | |
42 | return 0; | |
43 | } | |
44 | ||
45 | void vnic_wq_free(struct vnic_wq *wq) | |
46 | { | |
47 | struct vnic_dev *vdev; | |
48 | ||
49 | vdev = wq->vdev; | |
50 | ||
51 | vnic_dev_free_desc_ring(vdev, &wq->ring); | |
52 | ||
53 | rte_free(wq->bufs); | |
54 | wq->ctrl = NULL; | |
55 | } | |
56 | ||
57 | ||
58 | int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, | |
59 | unsigned int desc_count, unsigned int desc_size) | |
60 | { | |
61 | int err; | |
62 | ||
63 | wq->index = index; | |
64 | wq->vdev = vdev; | |
65 | ||
66 | err = vnic_wq_get_ctrl(vdev, wq, index, RES_TYPE_WQ); | |
67 | if (err) { | |
68 | pr_err("Failed to hook WQ[%d] resource, err %d\n", index, err); | |
69 | return err; | |
70 | } | |
71 | ||
72 | vnic_wq_disable(wq); | |
73 | ||
74 | err = vnic_wq_alloc_ring(vdev, wq, desc_count, desc_size); | |
75 | if (err) | |
76 | return err; | |
77 | ||
78 | err = vnic_wq_alloc_bufs(wq); | |
79 | if (err) { | |
80 | vnic_wq_free(wq); | |
81 | return err; | |
82 | } | |
83 | ||
84 | return 0; | |
85 | } | |
86 | ||
87 | void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, | |
88 | unsigned int fetch_index, unsigned int posted_index, | |
89 | unsigned int error_interrupt_enable, | |
90 | unsigned int error_interrupt_offset) | |
91 | { | |
92 | u64 paddr; | |
93 | unsigned int count = wq->ring.desc_count; | |
94 | ||
95 | paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET; | |
96 | writeq(paddr, &wq->ctrl->ring_base); | |
97 | iowrite32(count, &wq->ctrl->ring_size); | |
98 | iowrite32(fetch_index, &wq->ctrl->fetch_index); | |
99 | iowrite32(posted_index, &wq->ctrl->posted_index); | |
100 | iowrite32(cq_index, &wq->ctrl->cq_index); | |
101 | iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable); | |
102 | iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset); | |
103 | iowrite32(0, &wq->ctrl->error_status); | |
104 | ||
105 | wq->head_idx = fetch_index; | |
106 | wq->tail_idx = wq->head_idx; | |
107 | } | |
108 | ||
109 | void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, | |
110 | unsigned int error_interrupt_enable, | |
111 | unsigned int error_interrupt_offset) | |
112 | { | |
113 | vnic_wq_init_start(wq, cq_index, 0, 0, | |
114 | error_interrupt_enable, | |
115 | error_interrupt_offset); | |
9f95a23c | 116 | wq->cq_pend = 0; |
7c673cae FG |
117 | wq->last_completed_index = 0; |
118 | } | |
119 | ||
7c673cae FG |
120 | unsigned int vnic_wq_error_status(struct vnic_wq *wq) |
121 | { | |
122 | return ioread32(&wq->ctrl->error_status); | |
123 | } | |
124 | ||
125 | void vnic_wq_enable(struct vnic_wq *wq) | |
126 | { | |
127 | iowrite32(1, &wq->ctrl->enable); | |
128 | } | |
129 | ||
130 | int vnic_wq_disable(struct vnic_wq *wq) | |
131 | { | |
132 | unsigned int wait; | |
133 | ||
134 | iowrite32(0, &wq->ctrl->enable); | |
135 | ||
136 | /* Wait for HW to ACK disable request */ | |
137 | for (wait = 0; wait < 1000; wait++) { | |
138 | if (!(ioread32(&wq->ctrl->running))) | |
139 | return 0; | |
140 | udelay(10); | |
141 | } | |
142 | ||
143 | pr_err("Failed to disable WQ[%d]\n", wq->index); | |
144 | ||
145 | return -ETIMEDOUT; | |
146 | } | |
147 | ||
148 | void vnic_wq_clean(struct vnic_wq *wq, | |
9f95a23c | 149 | void (*buf_clean)(struct rte_mbuf **buf)) |
7c673cae | 150 | { |
9f95a23c | 151 | struct rte_mbuf **buf; |
7c673cae FG |
152 | unsigned int to_clean = wq->tail_idx; |
153 | ||
154 | buf = &wq->bufs[to_clean]; | |
155 | ||
156 | while (vnic_wq_desc_used(wq) > 0) { | |
157 | ||
158 | (*buf_clean)(buf); | |
159 | to_clean = buf_idx_incr(wq->ring.desc_count, to_clean); | |
160 | ||
161 | buf = &wq->bufs[to_clean]; | |
162 | wq->ring.desc_avail++; | |
163 | } | |
164 | ||
165 | wq->head_idx = 0; | |
166 | wq->tail_idx = 0; | |
167 | wq->last_completed_index = 0; | |
168 | *((uint32_t *)wq->cqmsg_rz->addr) = 0; | |
169 | ||
170 | iowrite32(0, &wq->ctrl->fetch_index); | |
171 | iowrite32(0, &wq->ctrl->posted_index); | |
172 | iowrite32(0, &wq->ctrl->error_status); | |
173 | ||
174 | vnic_dev_clear_desc_ring(&wq->ring); | |
175 | } |