1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2*2d9fd380Sjfb8856606 * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3*2d9fd380Sjfb8856606 */
4*2d9fd380Sjfb8856606
5*2d9fd380Sjfb8856606 #include <stdbool.h>
6*2d9fd380Sjfb8856606
7*2d9fd380Sjfb8856606 #include <rte_memzone.h>
8*2d9fd380Sjfb8856606
9*2d9fd380Sjfb8856606 #include "ionic.h"
10*2d9fd380Sjfb8856606 #include "ionic_ethdev.h"
11*2d9fd380Sjfb8856606 #include "ionic_lif.h"
12*2d9fd380Sjfb8856606
13*2d9fd380Sjfb8856606 static const char *
ionic_error_to_str(enum ionic_status_code code)14*2d9fd380Sjfb8856606 ionic_error_to_str(enum ionic_status_code code)
15*2d9fd380Sjfb8856606 {
16*2d9fd380Sjfb8856606 switch (code) {
17*2d9fd380Sjfb8856606 case IONIC_RC_SUCCESS:
18*2d9fd380Sjfb8856606 return "IONIC_RC_SUCCESS";
19*2d9fd380Sjfb8856606 case IONIC_RC_EVERSION:
20*2d9fd380Sjfb8856606 return "IONIC_RC_EVERSION";
21*2d9fd380Sjfb8856606 case IONIC_RC_EOPCODE:
22*2d9fd380Sjfb8856606 return "IONIC_RC_EOPCODE";
23*2d9fd380Sjfb8856606 case IONIC_RC_EIO:
24*2d9fd380Sjfb8856606 return "IONIC_RC_EIO";
25*2d9fd380Sjfb8856606 case IONIC_RC_EPERM:
26*2d9fd380Sjfb8856606 return "IONIC_RC_EPERM";
27*2d9fd380Sjfb8856606 case IONIC_RC_EQID:
28*2d9fd380Sjfb8856606 return "IONIC_RC_EQID";
29*2d9fd380Sjfb8856606 case IONIC_RC_EQTYPE:
30*2d9fd380Sjfb8856606 return "IONIC_RC_EQTYPE";
31*2d9fd380Sjfb8856606 case IONIC_RC_ENOENT:
32*2d9fd380Sjfb8856606 return "IONIC_RC_ENOENT";
33*2d9fd380Sjfb8856606 case IONIC_RC_EINTR:
34*2d9fd380Sjfb8856606 return "IONIC_RC_EINTR";
35*2d9fd380Sjfb8856606 case IONIC_RC_EAGAIN:
36*2d9fd380Sjfb8856606 return "IONIC_RC_EAGAIN";
37*2d9fd380Sjfb8856606 case IONIC_RC_ENOMEM:
38*2d9fd380Sjfb8856606 return "IONIC_RC_ENOMEM";
39*2d9fd380Sjfb8856606 case IONIC_RC_EFAULT:
40*2d9fd380Sjfb8856606 return "IONIC_RC_EFAULT";
41*2d9fd380Sjfb8856606 case IONIC_RC_EBUSY:
42*2d9fd380Sjfb8856606 return "IONIC_RC_EBUSY";
43*2d9fd380Sjfb8856606 case IONIC_RC_EEXIST:
44*2d9fd380Sjfb8856606 return "IONIC_RC_EEXIST";
45*2d9fd380Sjfb8856606 case IONIC_RC_EINVAL:
46*2d9fd380Sjfb8856606 return "IONIC_RC_EINVAL";
47*2d9fd380Sjfb8856606 case IONIC_RC_ENOSPC:
48*2d9fd380Sjfb8856606 return "IONIC_RC_ENOSPC";
49*2d9fd380Sjfb8856606 case IONIC_RC_ERANGE:
50*2d9fd380Sjfb8856606 return "IONIC_RC_ERANGE";
51*2d9fd380Sjfb8856606 case IONIC_RC_BAD_ADDR:
52*2d9fd380Sjfb8856606 return "IONIC_RC_BAD_ADDR";
53*2d9fd380Sjfb8856606 case IONIC_RC_DEV_CMD:
54*2d9fd380Sjfb8856606 return "IONIC_RC_DEV_CMD";
55*2d9fd380Sjfb8856606 case IONIC_RC_ERROR:
56*2d9fd380Sjfb8856606 return "IONIC_RC_ERROR";
57*2d9fd380Sjfb8856606 case IONIC_RC_ERDMA:
58*2d9fd380Sjfb8856606 return "IONIC_RC_ERDMA";
59*2d9fd380Sjfb8856606 default:
60*2d9fd380Sjfb8856606 return "IONIC_RC_UNKNOWN";
61*2d9fd380Sjfb8856606 }
62*2d9fd380Sjfb8856606 }
63*2d9fd380Sjfb8856606
64*2d9fd380Sjfb8856606 static const char *
ionic_opcode_to_str(enum ionic_cmd_opcode opcode)65*2d9fd380Sjfb8856606 ionic_opcode_to_str(enum ionic_cmd_opcode opcode)
66*2d9fd380Sjfb8856606 {
67*2d9fd380Sjfb8856606 switch (opcode) {
68*2d9fd380Sjfb8856606 case IONIC_CMD_NOP:
69*2d9fd380Sjfb8856606 return "IONIC_CMD_NOP";
70*2d9fd380Sjfb8856606 case IONIC_CMD_INIT:
71*2d9fd380Sjfb8856606 return "IONIC_CMD_INIT";
72*2d9fd380Sjfb8856606 case IONIC_CMD_RESET:
73*2d9fd380Sjfb8856606 return "IONIC_CMD_RESET";
74*2d9fd380Sjfb8856606 case IONIC_CMD_IDENTIFY:
75*2d9fd380Sjfb8856606 return "IONIC_CMD_IDENTIFY";
76*2d9fd380Sjfb8856606 case IONIC_CMD_GETATTR:
77*2d9fd380Sjfb8856606 return "IONIC_CMD_GETATTR";
78*2d9fd380Sjfb8856606 case IONIC_CMD_SETATTR:
79*2d9fd380Sjfb8856606 return "IONIC_CMD_SETATTR";
80*2d9fd380Sjfb8856606 case IONIC_CMD_PORT_IDENTIFY:
81*2d9fd380Sjfb8856606 return "IONIC_CMD_PORT_IDENTIFY";
82*2d9fd380Sjfb8856606 case IONIC_CMD_PORT_INIT:
83*2d9fd380Sjfb8856606 return "IONIC_CMD_PORT_INIT";
84*2d9fd380Sjfb8856606 case IONIC_CMD_PORT_RESET:
85*2d9fd380Sjfb8856606 return "IONIC_CMD_PORT_RESET";
86*2d9fd380Sjfb8856606 case IONIC_CMD_PORT_GETATTR:
87*2d9fd380Sjfb8856606 return "IONIC_CMD_PORT_GETATTR";
88*2d9fd380Sjfb8856606 case IONIC_CMD_PORT_SETATTR:
89*2d9fd380Sjfb8856606 return "IONIC_CMD_PORT_SETATTR";
90*2d9fd380Sjfb8856606 case IONIC_CMD_LIF_INIT:
91*2d9fd380Sjfb8856606 return "IONIC_CMD_LIF_INIT";
92*2d9fd380Sjfb8856606 case IONIC_CMD_LIF_RESET:
93*2d9fd380Sjfb8856606 return "IONIC_CMD_LIF_RESET";
94*2d9fd380Sjfb8856606 case IONIC_CMD_LIF_IDENTIFY:
95*2d9fd380Sjfb8856606 return "IONIC_CMD_LIF_IDENTIFY";
96*2d9fd380Sjfb8856606 case IONIC_CMD_LIF_SETATTR:
97*2d9fd380Sjfb8856606 return "IONIC_CMD_LIF_SETATTR";
98*2d9fd380Sjfb8856606 case IONIC_CMD_LIF_GETATTR:
99*2d9fd380Sjfb8856606 return "IONIC_CMD_LIF_GETATTR";
100*2d9fd380Sjfb8856606 case IONIC_CMD_RX_MODE_SET:
101*2d9fd380Sjfb8856606 return "IONIC_CMD_RX_MODE_SET";
102*2d9fd380Sjfb8856606 case IONIC_CMD_RX_FILTER_ADD:
103*2d9fd380Sjfb8856606 return "IONIC_CMD_RX_FILTER_ADD";
104*2d9fd380Sjfb8856606 case IONIC_CMD_RX_FILTER_DEL:
105*2d9fd380Sjfb8856606 return "IONIC_CMD_RX_FILTER_DEL";
106*2d9fd380Sjfb8856606 case IONIC_CMD_Q_INIT:
107*2d9fd380Sjfb8856606 return "IONIC_CMD_Q_INIT";
108*2d9fd380Sjfb8856606 case IONIC_CMD_Q_CONTROL:
109*2d9fd380Sjfb8856606 return "IONIC_CMD_Q_CONTROL";
110*2d9fd380Sjfb8856606 case IONIC_CMD_RDMA_RESET_LIF:
111*2d9fd380Sjfb8856606 return "IONIC_CMD_RDMA_RESET_LIF";
112*2d9fd380Sjfb8856606 case IONIC_CMD_RDMA_CREATE_EQ:
113*2d9fd380Sjfb8856606 return "IONIC_CMD_RDMA_CREATE_EQ";
114*2d9fd380Sjfb8856606 case IONIC_CMD_RDMA_CREATE_CQ:
115*2d9fd380Sjfb8856606 return "IONIC_CMD_RDMA_CREATE_CQ";
116*2d9fd380Sjfb8856606 case IONIC_CMD_RDMA_CREATE_ADMINQ:
117*2d9fd380Sjfb8856606 return "IONIC_CMD_RDMA_CREATE_ADMINQ";
118*2d9fd380Sjfb8856606 default:
119*2d9fd380Sjfb8856606 return "DEVCMD_UNKNOWN";
120*2d9fd380Sjfb8856606 }
121*2d9fd380Sjfb8856606 }
122*2d9fd380Sjfb8856606
123*2d9fd380Sjfb8856606 int
ionic_adminq_check_err(struct ionic_admin_ctx * ctx,bool timeout)124*2d9fd380Sjfb8856606 ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout)
125*2d9fd380Sjfb8856606 {
126*2d9fd380Sjfb8856606 const char *name;
127*2d9fd380Sjfb8856606 const char *status;
128*2d9fd380Sjfb8856606
129*2d9fd380Sjfb8856606 if (ctx->comp.comp.status || timeout) {
130*2d9fd380Sjfb8856606 name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
131*2d9fd380Sjfb8856606 status = ionic_error_to_str(ctx->comp.comp.status);
132*2d9fd380Sjfb8856606 IONIC_PRINT(ERR, "%s (%d) failed: %s (%d)",
133*2d9fd380Sjfb8856606 name,
134*2d9fd380Sjfb8856606 ctx->cmd.cmd.opcode,
135*2d9fd380Sjfb8856606 timeout ? "TIMEOUT" : status,
136*2d9fd380Sjfb8856606 timeout ? -1 : ctx->comp.comp.status);
137*2d9fd380Sjfb8856606 return -EIO;
138*2d9fd380Sjfb8856606 }
139*2d9fd380Sjfb8856606
140*2d9fd380Sjfb8856606 return 0;
141*2d9fd380Sjfb8856606 }
142*2d9fd380Sjfb8856606
143*2d9fd380Sjfb8856606 static int
ionic_wait_ctx_for_completion(struct ionic_lif * lif,struct ionic_qcq * qcq,struct ionic_admin_ctx * ctx,unsigned long max_wait)144*2d9fd380Sjfb8856606 ionic_wait_ctx_for_completion(struct ionic_lif *lif, struct ionic_qcq *qcq,
145*2d9fd380Sjfb8856606 struct ionic_admin_ctx *ctx, unsigned long max_wait)
146*2d9fd380Sjfb8856606 {
147*2d9fd380Sjfb8856606 unsigned long step_msec = 1;
148*2d9fd380Sjfb8856606 unsigned int max_wait_msec = max_wait * 1000;
149*2d9fd380Sjfb8856606 unsigned long elapsed_msec = 0;
150*2d9fd380Sjfb8856606 int budget = 8;
151*2d9fd380Sjfb8856606
152*2d9fd380Sjfb8856606 while (ctx->pending_work && elapsed_msec < max_wait_msec) {
153*2d9fd380Sjfb8856606 /*
154*2d9fd380Sjfb8856606 * Locking here as adminq is served inline (this could be called
155*2d9fd380Sjfb8856606 * from multiple places)
156*2d9fd380Sjfb8856606 */
157*2d9fd380Sjfb8856606 rte_spinlock_lock(&lif->adminq_service_lock);
158*2d9fd380Sjfb8856606
159*2d9fd380Sjfb8856606 ionic_qcq_service(qcq, budget, ionic_adminq_service, NULL);
160*2d9fd380Sjfb8856606
161*2d9fd380Sjfb8856606 rte_spinlock_unlock(&lif->adminq_service_lock);
162*2d9fd380Sjfb8856606
163*2d9fd380Sjfb8856606 msec_delay(step_msec);
164*2d9fd380Sjfb8856606 elapsed_msec += step_msec;
165*2d9fd380Sjfb8856606 }
166*2d9fd380Sjfb8856606
167*2d9fd380Sjfb8856606 return (!ctx->pending_work);
168*2d9fd380Sjfb8856606 }
169*2d9fd380Sjfb8856606
170*2d9fd380Sjfb8856606 int
ionic_adminq_post_wait(struct ionic_lif * lif,struct ionic_admin_ctx * ctx)171*2d9fd380Sjfb8856606 ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
172*2d9fd380Sjfb8856606 {
173*2d9fd380Sjfb8856606 struct ionic_qcq *qcq = lif->adminqcq;
174*2d9fd380Sjfb8856606 bool done;
175*2d9fd380Sjfb8856606 int err;
176*2d9fd380Sjfb8856606
177*2d9fd380Sjfb8856606 IONIC_PRINT(DEBUG, "Sending %s to the admin queue",
178*2d9fd380Sjfb8856606 ionic_opcode_to_str(ctx->cmd.cmd.opcode));
179*2d9fd380Sjfb8856606
180*2d9fd380Sjfb8856606 err = ionic_adminq_post(lif, ctx);
181*2d9fd380Sjfb8856606 if (err) {
182*2d9fd380Sjfb8856606 IONIC_PRINT(ERR, "Failure posting to the admin queue %d (%d)",
183*2d9fd380Sjfb8856606 ctx->cmd.cmd.opcode, err);
184*2d9fd380Sjfb8856606
185*2d9fd380Sjfb8856606 return err;
186*2d9fd380Sjfb8856606 }
187*2d9fd380Sjfb8856606
188*2d9fd380Sjfb8856606 done = ionic_wait_ctx_for_completion(lif, qcq, ctx,
189*2d9fd380Sjfb8856606 IONIC_DEVCMD_TIMEOUT);
190*2d9fd380Sjfb8856606
191*2d9fd380Sjfb8856606 err = ionic_adminq_check_err(ctx, !done /* timed out */);
192*2d9fd380Sjfb8856606 return err;
193*2d9fd380Sjfb8856606 }
194*2d9fd380Sjfb8856606
195*2d9fd380Sjfb8856606 static int
ionic_dev_cmd_wait(struct ionic_dev * idev,unsigned long max_wait)196*2d9fd380Sjfb8856606 ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)
197*2d9fd380Sjfb8856606 {
198*2d9fd380Sjfb8856606 unsigned long step_msec = 100;
199*2d9fd380Sjfb8856606 unsigned int max_wait_msec = max_wait * 1000;
200*2d9fd380Sjfb8856606 unsigned long elapsed_msec = 0;
201*2d9fd380Sjfb8856606 int done;
202*2d9fd380Sjfb8856606
203*2d9fd380Sjfb8856606 /* Wait for dev cmd to complete.. but no more than max_wait sec */
204*2d9fd380Sjfb8856606
205*2d9fd380Sjfb8856606 do {
206*2d9fd380Sjfb8856606 done = ionic_dev_cmd_done(idev);
207*2d9fd380Sjfb8856606 if (done) {
208*2d9fd380Sjfb8856606 IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs",
209*2d9fd380Sjfb8856606 idev->dev_cmd->cmd.cmd.opcode,
210*2d9fd380Sjfb8856606 elapsed_msec);
211*2d9fd380Sjfb8856606 return 0;
212*2d9fd380Sjfb8856606 }
213*2d9fd380Sjfb8856606
214*2d9fd380Sjfb8856606 msec_delay(step_msec);
215*2d9fd380Sjfb8856606
216*2d9fd380Sjfb8856606 elapsed_msec += step_msec;
217*2d9fd380Sjfb8856606 } while (elapsed_msec < max_wait_msec);
218*2d9fd380Sjfb8856606
219*2d9fd380Sjfb8856606 IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs",
220*2d9fd380Sjfb8856606 idev->dev_cmd->cmd.cmd.opcode,
221*2d9fd380Sjfb8856606 elapsed_msec);
222*2d9fd380Sjfb8856606
223*2d9fd380Sjfb8856606 return -ETIMEDOUT;
224*2d9fd380Sjfb8856606 }
225*2d9fd380Sjfb8856606
226*2d9fd380Sjfb8856606 static int
ionic_dev_cmd_check_error(struct ionic_dev * idev)227*2d9fd380Sjfb8856606 ionic_dev_cmd_check_error(struct ionic_dev *idev)
228*2d9fd380Sjfb8856606 {
229*2d9fd380Sjfb8856606 uint8_t status;
230*2d9fd380Sjfb8856606
231*2d9fd380Sjfb8856606 status = ionic_dev_cmd_status(idev);
232*2d9fd380Sjfb8856606 if (status == 0)
233*2d9fd380Sjfb8856606 return 0;
234*2d9fd380Sjfb8856606
235*2d9fd380Sjfb8856606 return -EIO;
236*2d9fd380Sjfb8856606 }
237*2d9fd380Sjfb8856606
238*2d9fd380Sjfb8856606 int
ionic_dev_cmd_wait_check(struct ionic_dev * idev,unsigned long max_wait)239*2d9fd380Sjfb8856606 ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait)
240*2d9fd380Sjfb8856606 {
241*2d9fd380Sjfb8856606 int err;
242*2d9fd380Sjfb8856606
243*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait(idev, max_wait);
244*2d9fd380Sjfb8856606 if (err)
245*2d9fd380Sjfb8856606 return err;
246*2d9fd380Sjfb8856606
247*2d9fd380Sjfb8856606 return ionic_dev_cmd_check_error(idev);
248*2d9fd380Sjfb8856606 }
249*2d9fd380Sjfb8856606
250*2d9fd380Sjfb8856606 int
ionic_setup(struct ionic_adapter * adapter)251*2d9fd380Sjfb8856606 ionic_setup(struct ionic_adapter *adapter)
252*2d9fd380Sjfb8856606 {
253*2d9fd380Sjfb8856606 return ionic_dev_setup(adapter);
254*2d9fd380Sjfb8856606 }
255*2d9fd380Sjfb8856606
256*2d9fd380Sjfb8856606 int
ionic_identify(struct ionic_adapter * adapter)257*2d9fd380Sjfb8856606 ionic_identify(struct ionic_adapter *adapter)
258*2d9fd380Sjfb8856606 {
259*2d9fd380Sjfb8856606 struct ionic_dev *idev = &adapter->idev;
260*2d9fd380Sjfb8856606 struct ionic_identity *ident = &adapter->ident;
261*2d9fd380Sjfb8856606 int err = 0;
262*2d9fd380Sjfb8856606 uint32_t i;
263*2d9fd380Sjfb8856606 unsigned int nwords;
264*2d9fd380Sjfb8856606 uint32_t drv_size = sizeof(ident->drv.words) /
265*2d9fd380Sjfb8856606 sizeof(ident->drv.words[0]);
266*2d9fd380Sjfb8856606 uint32_t cmd_size = sizeof(idev->dev_cmd->data) /
267*2d9fd380Sjfb8856606 sizeof(idev->dev_cmd->data[0]);
268*2d9fd380Sjfb8856606 uint32_t dev_size = sizeof(ident->dev.words) /
269*2d9fd380Sjfb8856606 sizeof(ident->dev.words[0]);
270*2d9fd380Sjfb8856606
271*2d9fd380Sjfb8856606 memset(ident, 0, sizeof(*ident));
272*2d9fd380Sjfb8856606
273*2d9fd380Sjfb8856606 ident->drv.os_type = IONIC_OS_TYPE_LINUX;
274*2d9fd380Sjfb8856606 ident->drv.os_dist = 0;
275*2d9fd380Sjfb8856606 snprintf(ident->drv.os_dist_str,
276*2d9fd380Sjfb8856606 sizeof(ident->drv.os_dist_str), "Unknown");
277*2d9fd380Sjfb8856606 ident->drv.kernel_ver = 0;
278*2d9fd380Sjfb8856606 snprintf(ident->drv.kernel_ver_str,
279*2d9fd380Sjfb8856606 sizeof(ident->drv.kernel_ver_str), "DPDK");
280*2d9fd380Sjfb8856606 strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION,
281*2d9fd380Sjfb8856606 sizeof(ident->drv.driver_ver_str) - 1);
282*2d9fd380Sjfb8856606
283*2d9fd380Sjfb8856606 nwords = RTE_MIN(drv_size, cmd_size);
284*2d9fd380Sjfb8856606 for (i = 0; i < nwords; i++)
285*2d9fd380Sjfb8856606 iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]);
286*2d9fd380Sjfb8856606
287*2d9fd380Sjfb8856606 ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1);
288*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
289*2d9fd380Sjfb8856606 if (!err) {
290*2d9fd380Sjfb8856606 nwords = RTE_MIN(dev_size, cmd_size);
291*2d9fd380Sjfb8856606 for (i = 0; i < nwords; i++)
292*2d9fd380Sjfb8856606 ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]);
293*2d9fd380Sjfb8856606 }
294*2d9fd380Sjfb8856606
295*2d9fd380Sjfb8856606 return err;
296*2d9fd380Sjfb8856606 }
297*2d9fd380Sjfb8856606
298*2d9fd380Sjfb8856606 int
ionic_init(struct ionic_adapter * adapter)299*2d9fd380Sjfb8856606 ionic_init(struct ionic_adapter *adapter)
300*2d9fd380Sjfb8856606 {
301*2d9fd380Sjfb8856606 struct ionic_dev *idev = &adapter->idev;
302*2d9fd380Sjfb8856606 int err;
303*2d9fd380Sjfb8856606
304*2d9fd380Sjfb8856606 ionic_dev_cmd_init(idev);
305*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
306*2d9fd380Sjfb8856606 return err;
307*2d9fd380Sjfb8856606 }
308*2d9fd380Sjfb8856606
309*2d9fd380Sjfb8856606 int
ionic_reset(struct ionic_adapter * adapter)310*2d9fd380Sjfb8856606 ionic_reset(struct ionic_adapter *adapter)
311*2d9fd380Sjfb8856606 {
312*2d9fd380Sjfb8856606 struct ionic_dev *idev = &adapter->idev;
313*2d9fd380Sjfb8856606 int err;
314*2d9fd380Sjfb8856606
315*2d9fd380Sjfb8856606 ionic_dev_cmd_reset(idev);
316*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
317*2d9fd380Sjfb8856606 return err;
318*2d9fd380Sjfb8856606 }
319*2d9fd380Sjfb8856606
320*2d9fd380Sjfb8856606 int
ionic_port_identify(struct ionic_adapter * adapter)321*2d9fd380Sjfb8856606 ionic_port_identify(struct ionic_adapter *adapter)
322*2d9fd380Sjfb8856606 {
323*2d9fd380Sjfb8856606 struct ionic_dev *idev = &adapter->idev;
324*2d9fd380Sjfb8856606 struct ionic_identity *ident = &adapter->ident;
325*2d9fd380Sjfb8856606 unsigned int port_words = sizeof(ident->port.words) /
326*2d9fd380Sjfb8856606 sizeof(ident->port.words[0]);
327*2d9fd380Sjfb8856606 unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
328*2d9fd380Sjfb8856606 sizeof(idev->dev_cmd->data[0]);
329*2d9fd380Sjfb8856606 unsigned int i;
330*2d9fd380Sjfb8856606 unsigned int nwords;
331*2d9fd380Sjfb8856606 int err;
332*2d9fd380Sjfb8856606
333*2d9fd380Sjfb8856606 ionic_dev_cmd_port_identify(idev);
334*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
335*2d9fd380Sjfb8856606 if (!err) {
336*2d9fd380Sjfb8856606 nwords = RTE_MIN(port_words, cmd_words);
337*2d9fd380Sjfb8856606 for (i = 0; i < nwords; i++)
338*2d9fd380Sjfb8856606 ident->port.words[i] =
339*2d9fd380Sjfb8856606 ioread32(&idev->dev_cmd->data[i]);
340*2d9fd380Sjfb8856606 }
341*2d9fd380Sjfb8856606
342*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed);
343*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu);
344*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "state %d ", ident->port.config.state);
345*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable);
346*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type);
347*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type);
348*2d9fd380Sjfb8856606 IONIC_PRINT(INFO, "loopback_mode %d",
349*2d9fd380Sjfb8856606 ident->port.config.loopback_mode);
350*2d9fd380Sjfb8856606
351*2d9fd380Sjfb8856606 return err;
352*2d9fd380Sjfb8856606 }
353*2d9fd380Sjfb8856606
354*2d9fd380Sjfb8856606 static const struct rte_memzone *
ionic_memzone_reserve(const char * name,uint32_t len,int socket_id)355*2d9fd380Sjfb8856606 ionic_memzone_reserve(const char *name, uint32_t len, int socket_id)
356*2d9fd380Sjfb8856606 {
357*2d9fd380Sjfb8856606 const struct rte_memzone *mz;
358*2d9fd380Sjfb8856606
359*2d9fd380Sjfb8856606 mz = rte_memzone_lookup(name);
360*2d9fd380Sjfb8856606 if (mz)
361*2d9fd380Sjfb8856606 return mz;
362*2d9fd380Sjfb8856606
363*2d9fd380Sjfb8856606 mz = rte_memzone_reserve_aligned(name, len, socket_id,
364*2d9fd380Sjfb8856606 RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN);
365*2d9fd380Sjfb8856606 return mz;
366*2d9fd380Sjfb8856606 }
367*2d9fd380Sjfb8856606
368*2d9fd380Sjfb8856606 int
ionic_port_init(struct ionic_adapter * adapter)369*2d9fd380Sjfb8856606 ionic_port_init(struct ionic_adapter *adapter)
370*2d9fd380Sjfb8856606 {
371*2d9fd380Sjfb8856606 struct ionic_dev *idev = &adapter->idev;
372*2d9fd380Sjfb8856606 struct ionic_identity *ident = &adapter->ident;
373*2d9fd380Sjfb8856606 char z_name[RTE_MEMZONE_NAMESIZE];
374*2d9fd380Sjfb8856606 unsigned int config_words = sizeof(ident->port.config.words) /
375*2d9fd380Sjfb8856606 sizeof(ident->port.config.words[0]);
376*2d9fd380Sjfb8856606 unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
377*2d9fd380Sjfb8856606 sizeof(idev->dev_cmd->data[0]);
378*2d9fd380Sjfb8856606 unsigned int nwords;
379*2d9fd380Sjfb8856606 unsigned int i;
380*2d9fd380Sjfb8856606 int err;
381*2d9fd380Sjfb8856606
382*2d9fd380Sjfb8856606 if (idev->port_info)
383*2d9fd380Sjfb8856606 return 0;
384*2d9fd380Sjfb8856606
385*2d9fd380Sjfb8856606 idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE);
386*2d9fd380Sjfb8856606
387*2d9fd380Sjfb8856606 snprintf(z_name, sizeof(z_name), "%s_port_%s_info",
388*2d9fd380Sjfb8856606 IONIC_DRV_NAME,
389*2d9fd380Sjfb8856606 adapter->pci_dev->device.name);
390*2d9fd380Sjfb8856606
391*2d9fd380Sjfb8856606 idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz,
392*2d9fd380Sjfb8856606 SOCKET_ID_ANY);
393*2d9fd380Sjfb8856606 if (!idev->port_info_z) {
394*2d9fd380Sjfb8856606 IONIC_PRINT(ERR, "Cannot reserve port info DMA memory");
395*2d9fd380Sjfb8856606 return -ENOMEM;
396*2d9fd380Sjfb8856606 }
397*2d9fd380Sjfb8856606
398*2d9fd380Sjfb8856606 idev->port_info = idev->port_info_z->addr;
399*2d9fd380Sjfb8856606 idev->port_info_pa = idev->port_info_z->iova;
400*2d9fd380Sjfb8856606
401*2d9fd380Sjfb8856606 nwords = RTE_MIN(config_words, cmd_words);
402*2d9fd380Sjfb8856606
403*2d9fd380Sjfb8856606 for (i = 0; i < nwords; i++)
404*2d9fd380Sjfb8856606 iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]);
405*2d9fd380Sjfb8856606
406*2d9fd380Sjfb8856606 ionic_dev_cmd_port_init(idev);
407*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
408*2d9fd380Sjfb8856606 if (err) {
409*2d9fd380Sjfb8856606 IONIC_PRINT(ERR, "Failed to init port");
410*2d9fd380Sjfb8856606 return err;
411*2d9fd380Sjfb8856606 }
412*2d9fd380Sjfb8856606
413*2d9fd380Sjfb8856606 ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
414*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
415*2d9fd380Sjfb8856606 if (err) {
416*2d9fd380Sjfb8856606 IONIC_PRINT(WARNING, "Failed to bring port UP");
417*2d9fd380Sjfb8856606 return err;
418*2d9fd380Sjfb8856606 }
419*2d9fd380Sjfb8856606
420*2d9fd380Sjfb8856606 return 0;
421*2d9fd380Sjfb8856606 }
422*2d9fd380Sjfb8856606
423*2d9fd380Sjfb8856606 int
ionic_port_reset(struct ionic_adapter * adapter)424*2d9fd380Sjfb8856606 ionic_port_reset(struct ionic_adapter *adapter)
425*2d9fd380Sjfb8856606 {
426*2d9fd380Sjfb8856606 struct ionic_dev *idev = &adapter->idev;
427*2d9fd380Sjfb8856606 int err;
428*2d9fd380Sjfb8856606
429*2d9fd380Sjfb8856606 if (!idev->port_info)
430*2d9fd380Sjfb8856606 return 0;
431*2d9fd380Sjfb8856606
432*2d9fd380Sjfb8856606 ionic_dev_cmd_port_reset(idev);
433*2d9fd380Sjfb8856606 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
434*2d9fd380Sjfb8856606 if (err) {
435*2d9fd380Sjfb8856606 IONIC_PRINT(ERR, "Failed to reset port");
436*2d9fd380Sjfb8856606 return err;
437*2d9fd380Sjfb8856606 }
438*2d9fd380Sjfb8856606
439*2d9fd380Sjfb8856606 idev->port_info = NULL;
440*2d9fd380Sjfb8856606 idev->port_info_pa = 0;
441*2d9fd380Sjfb8856606
442*2d9fd380Sjfb8856606 return 0;
443*2d9fd380Sjfb8856606 }
444