]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / dpdk / drivers / raw / ifpga_rawdev / base / ifpga_feature_dev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
3 */
4
5 #include <sys/ioctl.h>
6
7 #include "ifpga_feature_dev.h"
8
9 /*
10 * Enable Port by clear the port soft reset bit, which is set by default.
11 * The AFU is unable to respond to any MMIO access while in reset.
12 * __fpga_port_enable function should only be used after __fpga_port_disable
13 * function.
14 */
15 void __fpga_port_enable(struct ifpga_port_hw *port)
16 {
17 struct feature_port_header *port_hdr;
18 struct feature_port_control control;
19
20 WARN_ON(!port->disable_count);
21
22 if (--port->disable_count != 0)
23 return;
24
25 port_hdr = get_port_feature_ioaddr_by_index(port,
26 PORT_FEATURE_ID_HEADER);
27 WARN_ON(!port_hdr);
28
29 control.csr = readq(&port_hdr->control);
30 control.port_sftrst = 0x0;
31 writeq(control.csr, &port_hdr->control);
32 }
33
34 int __fpga_port_disable(struct ifpga_port_hw *port)
35 {
36 struct feature_port_header *port_hdr;
37 struct feature_port_control control;
38
39 if (port->disable_count++ != 0)
40 return 0;
41
42 port_hdr = get_port_feature_ioaddr_by_index(port,
43 PORT_FEATURE_ID_HEADER);
44 WARN_ON(!port_hdr);
45
46 /* Set port soft reset */
47 control.csr = readq(&port_hdr->control);
48 control.port_sftrst = 0x1;
49 writeq(control.csr, &port_hdr->control);
50
51 /*
52 * HW sets ack bit to 1 when all outstanding requests have been drained
53 * on this port and minimum soft reset pulse width has elapsed.
54 * Driver polls port_soft_reset_ack to determine if reset done by HW.
55 */
56 control.port_sftrst_ack = 1;
57
58 if (fpga_wait_register_field(port_sftrst_ack, control,
59 &port_hdr->control, RST_POLL_TIMEOUT,
60 RST_POLL_INVL)) {
61 dev_err(port, "timeout, fail to reset device\n");
62 return -ETIMEDOUT;
63 }
64
65 return 0;
66 }
67
68 int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid)
69 {
70 struct feature_port_header *port_hdr;
71 u64 guidl, guidh;
72
73 port_hdr = get_port_feature_ioaddr_by_index(port, PORT_FEATURE_ID_UAFU);
74
75 spinlock_lock(&port->lock);
76 guidl = readq(&port_hdr->afu_header.guid.b[0]);
77 guidh = readq(&port_hdr->afu_header.guid.b[8]);
78 spinlock_unlock(&port->lock);
79
80 memcpy(uuid->b, &guidl, sizeof(u64));
81 memcpy(uuid->b + 8, &guidh, sizeof(u64));
82
83 return 0;
84 }
85
86 /* Mask / Unmask Port Errors by the Error Mask register. */
87 void port_err_mask(struct ifpga_port_hw *port, bool mask)
88 {
89 struct feature_port_error *port_err;
90 struct feature_port_err_key err_mask;
91
92 port_err = get_port_feature_ioaddr_by_index(port,
93 PORT_FEATURE_ID_ERROR);
94
95 if (mask)
96 err_mask.csr = PORT_ERR_MASK;
97 else
98 err_mask.csr = 0;
99
100 writeq(err_mask.csr, &port_err->error_mask);
101 }
102
103 /* Clear All Port Errors. */
104 int port_err_clear(struct ifpga_port_hw *port, u64 err)
105 {
106 struct feature_port_header *port_hdr;
107 struct feature_port_error *port_err;
108 struct feature_port_err_key mask;
109 struct feature_port_first_err_key first;
110 struct feature_port_status status;
111 int ret = 0;
112
113 port_err = get_port_feature_ioaddr_by_index(port,
114 PORT_FEATURE_ID_ERROR);
115 port_hdr = get_port_feature_ioaddr_by_index(port,
116 PORT_FEATURE_ID_HEADER);
117
118 /*
119 * Clear All Port Errors
120 *
121 * - Check for AP6 State
122 * - Halt Port by keeping Port in reset
123 * - Set PORT Error mask to all 1 to mask errors
124 * - Clear all errors
125 * - Set Port mask to all 0 to enable errors
126 * - All errors start capturing new errors
127 * - Enable Port by pulling the port out of reset
128 */
129
130 /* If device is still in AP6 state, can not clear any error.*/
131 status.csr = readq(&port_hdr->status);
132 if (status.power_state == PORT_POWER_STATE_AP6) {
133 dev_err(dev, "Could not clear errors, device in AP6 state.\n");
134 return -EBUSY;
135 }
136
137 /* Halt Port by keeping Port in reset */
138 ret = __fpga_port_disable(port);
139 if (ret)
140 return ret;
141
142 /* Mask all errors */
143 port_err_mask(port, true);
144
145 /* Clear errors if err input matches with current port errors.*/
146 mask.csr = readq(&port_err->port_error);
147
148 if (mask.csr == err) {
149 writeq(mask.csr, &port_err->port_error);
150
151 first.csr = readq(&port_err->port_first_error);
152 writeq(first.csr, &port_err->port_first_error);
153 } else {
154 ret = -EBUSY;
155 }
156
157 /* Clear mask */
158 port_err_mask(port, false);
159
160 /* Enable the Port by clear the reset */
161 __fpga_port_enable(port);
162
163 return ret;
164 }
165
166 int port_clear_error(struct ifpga_port_hw *port)
167 {
168 struct feature_port_error *port_err;
169 struct feature_port_err_key error;
170
171 port_err = get_port_feature_ioaddr_by_index(port,
172 PORT_FEATURE_ID_ERROR);
173 error.csr = readq(&port_err->port_error);
174
175 dev_info(port, "read port error: 0x%lx\n", (unsigned long)error.csr);
176
177 return port_err_clear(port, error.csr);
178 }
179
180 void fme_hw_uinit(struct ifpga_fme_hw *fme)
181 {
182 struct feature *feature;
183 int i;
184
185 if (fme->state != IFPGA_FME_IMPLEMENTED)
186 return;
187
188 for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
189 feature = &fme->sub_feature[i];
190 if (feature->state == IFPGA_FEATURE_ATTACHED &&
191 feature->ops && feature->ops->uinit)
192 feature->ops->uinit(feature);
193 }
194 }
195
196 int fme_hw_init(struct ifpga_fme_hw *fme)
197 {
198 struct feature *feature;
199 int i, ret;
200
201 if (fme->state != IFPGA_FME_IMPLEMENTED)
202 return -EINVAL;
203
204 for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
205 feature = &fme->sub_feature[i];
206 if (feature->state == IFPGA_FEATURE_ATTACHED &&
207 feature->ops && feature->ops->init) {
208 ret = feature->ops->init(feature);
209 if (ret) {
210 fme_hw_uinit(fme);
211 return ret;
212 }
213 }
214 }
215
216 return 0;
217 }
218
219 void port_hw_uinit(struct ifpga_port_hw *port)
220 {
221 struct feature *feature;
222 int i;
223
224 for (i = 0; i < PORT_FEATURE_ID_MAX; i++) {
225 feature = &port->sub_feature[i];
226 if (feature->state == IFPGA_FEATURE_ATTACHED &&
227 feature->ops && feature->ops->uinit)
228 feature->ops->uinit(feature);
229 }
230 }
231
232 int port_hw_init(struct ifpga_port_hw *port)
233 {
234 struct feature *feature;
235 int i, ret;
236
237 if (port->state == IFPGA_PORT_UNUSED)
238 return 0;
239
240 for (i = 0; i < PORT_FEATURE_ID_MAX; i++) {
241 feature = &port->sub_feature[i];
242 if (feature->ops && feature->ops->init) {
243 ret = feature->ops->init(feature);
244 if (ret) {
245 port_hw_uinit(port);
246 return ret;
247 }
248 }
249 }
250
251 return 0;
252 }
253