xref: /dpdk/drivers/net/ionic/ionic_main.c (revision 01a6c311df2fa78928d46eb9bf4f2658a3cc08ee)
15ef51809SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
25ef51809SAlfredo Cardigliano  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
35ef51809SAlfredo Cardigliano  */
45ef51809SAlfredo Cardigliano 
523bf4ddbSAlfredo Cardigliano #include <rte_memzone.h>
623bf4ddbSAlfredo Cardigliano 
75ef51809SAlfredo Cardigliano #include "ionic.h"
8*01a6c311SAlfredo Cardigliano #include "ionic_ethdev.h"
9*01a6c311SAlfredo Cardigliano #include "ionic_lif.h"
10*01a6c311SAlfredo Cardigliano 
11*01a6c311SAlfredo Cardigliano static const char *
12*01a6c311SAlfredo Cardigliano ionic_error_to_str(enum ionic_status_code code)
13*01a6c311SAlfredo Cardigliano {
14*01a6c311SAlfredo Cardigliano 	switch (code) {
15*01a6c311SAlfredo Cardigliano 	case IONIC_RC_SUCCESS:
16*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_SUCCESS";
17*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EVERSION:
18*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EVERSION";
19*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EOPCODE:
20*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EOPCODE";
21*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EIO:
22*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EIO";
23*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EPERM:
24*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EPERM";
25*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EQID:
26*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EQID";
27*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EQTYPE:
28*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EQTYPE";
29*01a6c311SAlfredo Cardigliano 	case IONIC_RC_ENOENT:
30*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_ENOENT";
31*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EINTR:
32*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EINTR";
33*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EAGAIN:
34*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EAGAIN";
35*01a6c311SAlfredo Cardigliano 	case IONIC_RC_ENOMEM:
36*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_ENOMEM";
37*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EFAULT:
38*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EFAULT";
39*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EBUSY:
40*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EBUSY";
41*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EEXIST:
42*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EEXIST";
43*01a6c311SAlfredo Cardigliano 	case IONIC_RC_EINVAL:
44*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_EINVAL";
45*01a6c311SAlfredo Cardigliano 	case IONIC_RC_ENOSPC:
46*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_ENOSPC";
47*01a6c311SAlfredo Cardigliano 	case IONIC_RC_ERANGE:
48*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_ERANGE";
49*01a6c311SAlfredo Cardigliano 	case IONIC_RC_BAD_ADDR:
50*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_BAD_ADDR";
51*01a6c311SAlfredo Cardigliano 	case IONIC_RC_DEV_CMD:
52*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_DEV_CMD";
53*01a6c311SAlfredo Cardigliano 	case IONIC_RC_ERROR:
54*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_ERROR";
55*01a6c311SAlfredo Cardigliano 	case IONIC_RC_ERDMA:
56*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_ERDMA";
57*01a6c311SAlfredo Cardigliano 	default:
58*01a6c311SAlfredo Cardigliano 		return "IONIC_RC_UNKNOWN";
59*01a6c311SAlfredo Cardigliano 	}
60*01a6c311SAlfredo Cardigliano }
61*01a6c311SAlfredo Cardigliano 
62*01a6c311SAlfredo Cardigliano static const char *
63*01a6c311SAlfredo Cardigliano ionic_opcode_to_str(enum ionic_cmd_opcode opcode)
64*01a6c311SAlfredo Cardigliano {
65*01a6c311SAlfredo Cardigliano 	switch (opcode) {
66*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_NOP:
67*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_NOP";
68*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_INIT:
69*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_INIT";
70*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RESET:
71*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RESET";
72*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_IDENTIFY:
73*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_IDENTIFY";
74*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_GETATTR:
75*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_GETATTR";
76*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_SETATTR:
77*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_SETATTR";
78*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_IDENTIFY:
79*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_IDENTIFY";
80*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_INIT:
81*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_INIT";
82*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_RESET:
83*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_RESET";
84*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_GETATTR:
85*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_GETATTR";
86*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_SETATTR:
87*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_SETATTR";
88*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_INIT:
89*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_INIT";
90*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_RESET:
91*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_RESET";
92*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_IDENTIFY:
93*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_IDENTIFY";
94*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_SETATTR:
95*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_SETATTR";
96*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_GETATTR:
97*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_GETATTR";
98*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RX_MODE_SET:
99*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RX_MODE_SET";
100*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RX_FILTER_ADD:
101*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RX_FILTER_ADD";
102*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RX_FILTER_DEL:
103*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RX_FILTER_DEL";
104*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_Q_INIT:
105*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_Q_INIT";
106*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_Q_CONTROL:
107*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_Q_CONTROL";
108*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_RESET_LIF:
109*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_RESET_LIF";
110*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_CREATE_EQ:
111*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_CREATE_EQ";
112*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_CREATE_CQ:
113*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_CREATE_CQ";
114*01a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_CREATE_ADMINQ:
115*01a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_CREATE_ADMINQ";
116*01a6c311SAlfredo Cardigliano 	default:
117*01a6c311SAlfredo Cardigliano 		return "DEVCMD_UNKNOWN";
118*01a6c311SAlfredo Cardigliano 	}
119*01a6c311SAlfredo Cardigliano }
120*01a6c311SAlfredo Cardigliano 
121*01a6c311SAlfredo Cardigliano int
122*01a6c311SAlfredo Cardigliano ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout)
123*01a6c311SAlfredo Cardigliano {
124*01a6c311SAlfredo Cardigliano 	const char *name;
125*01a6c311SAlfredo Cardigliano 	const char *status;
126*01a6c311SAlfredo Cardigliano 
127*01a6c311SAlfredo Cardigliano 	if (ctx->comp.comp.status || timeout) {
128*01a6c311SAlfredo Cardigliano 		name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
129*01a6c311SAlfredo Cardigliano 		status = ionic_error_to_str(ctx->comp.comp.status);
130*01a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "%s (%d) failed: %s (%d)",
131*01a6c311SAlfredo Cardigliano 			name,
132*01a6c311SAlfredo Cardigliano 			ctx->cmd.cmd.opcode,
133*01a6c311SAlfredo Cardigliano 			timeout ? "TIMEOUT" : status,
134*01a6c311SAlfredo Cardigliano 			timeout ? -1 : ctx->comp.comp.status);
135*01a6c311SAlfredo Cardigliano 		return -EIO;
136*01a6c311SAlfredo Cardigliano 	}
137*01a6c311SAlfredo Cardigliano 
138*01a6c311SAlfredo Cardigliano 	return 0;
139*01a6c311SAlfredo Cardigliano }
140*01a6c311SAlfredo Cardigliano 
141*01a6c311SAlfredo Cardigliano static int
142*01a6c311SAlfredo Cardigliano ionic_wait_ctx_for_completion(struct ionic_lif *lif, struct ionic_qcq *qcq,
143*01a6c311SAlfredo Cardigliano 		struct ionic_admin_ctx *ctx, unsigned long max_wait)
144*01a6c311SAlfredo Cardigliano {
145*01a6c311SAlfredo Cardigliano 	unsigned long step_msec = 1;
146*01a6c311SAlfredo Cardigliano 	unsigned int max_wait_msec = max_wait * 1000;
147*01a6c311SAlfredo Cardigliano 	unsigned long elapsed_msec = 0;
148*01a6c311SAlfredo Cardigliano 	int budget = 8;
149*01a6c311SAlfredo Cardigliano 
150*01a6c311SAlfredo Cardigliano 	while (ctx->pending_work && elapsed_msec < max_wait_msec) {
151*01a6c311SAlfredo Cardigliano 		/*
152*01a6c311SAlfredo Cardigliano 		 * Locking here as adminq is served inline (this could be called
153*01a6c311SAlfredo Cardigliano 		 * from multiple places)
154*01a6c311SAlfredo Cardigliano 		 */
155*01a6c311SAlfredo Cardigliano 		rte_spinlock_lock(&lif->adminq_service_lock);
156*01a6c311SAlfredo Cardigliano 
157*01a6c311SAlfredo Cardigliano 		ionic_qcq_service(qcq, budget, ionic_adminq_service, NULL);
158*01a6c311SAlfredo Cardigliano 
159*01a6c311SAlfredo Cardigliano 		rte_spinlock_unlock(&lif->adminq_service_lock);
160*01a6c311SAlfredo Cardigliano 
161*01a6c311SAlfredo Cardigliano 		msec_delay(step_msec);
162*01a6c311SAlfredo Cardigliano 		elapsed_msec += step_msec;
163*01a6c311SAlfredo Cardigliano 	}
164*01a6c311SAlfredo Cardigliano 
165*01a6c311SAlfredo Cardigliano 	return (!ctx->pending_work);
166*01a6c311SAlfredo Cardigliano }
167*01a6c311SAlfredo Cardigliano 
168*01a6c311SAlfredo Cardigliano int
169*01a6c311SAlfredo Cardigliano ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
170*01a6c311SAlfredo Cardigliano {
171*01a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
172*01a6c311SAlfredo Cardigliano 	bool done;
173*01a6c311SAlfredo Cardigliano 	int err;
174*01a6c311SAlfredo Cardigliano 
175*01a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Sending %s to the admin queue",
176*01a6c311SAlfredo Cardigliano 		ionic_opcode_to_str(ctx->cmd.cmd.opcode));
177*01a6c311SAlfredo Cardigliano 
178*01a6c311SAlfredo Cardigliano 	err = ionic_adminq_post(lif, ctx);
179*01a6c311SAlfredo Cardigliano 	if (err) {
180*01a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure posting to the admin queue %d (%d)",
181*01a6c311SAlfredo Cardigliano 			ctx->cmd.cmd.opcode, err);
182*01a6c311SAlfredo Cardigliano 
183*01a6c311SAlfredo Cardigliano 		return err;
184*01a6c311SAlfredo Cardigliano 	}
185*01a6c311SAlfredo Cardigliano 
186*01a6c311SAlfredo Cardigliano 	done = ionic_wait_ctx_for_completion(lif, qcq, ctx,
187*01a6c311SAlfredo Cardigliano 		IONIC_DEVCMD_TIMEOUT);
188*01a6c311SAlfredo Cardigliano 
189*01a6c311SAlfredo Cardigliano 	err = ionic_adminq_check_err(ctx, !done /* timed out */);
190*01a6c311SAlfredo Cardigliano 	return err;
191*01a6c311SAlfredo Cardigliano }
1925ef51809SAlfredo Cardigliano 
1935ef51809SAlfredo Cardigliano static int
1945ef51809SAlfredo Cardigliano ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)
1955ef51809SAlfredo Cardigliano {
1965ef51809SAlfredo Cardigliano 	unsigned long step_msec = 100;
1975ef51809SAlfredo Cardigliano 	unsigned int max_wait_msec = max_wait * 1000;
1985ef51809SAlfredo Cardigliano 	unsigned long elapsed_msec = 0;
1995ef51809SAlfredo Cardigliano 	int done;
2005ef51809SAlfredo Cardigliano 
2015ef51809SAlfredo Cardigliano 	/* Wait for dev cmd to complete.. but no more than max_wait sec */
2025ef51809SAlfredo Cardigliano 
2035ef51809SAlfredo Cardigliano 	do {
2045ef51809SAlfredo Cardigliano 		done = ionic_dev_cmd_done(idev);
2055ef51809SAlfredo Cardigliano 		if (done) {
2065ef51809SAlfredo Cardigliano 			IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs",
2075ef51809SAlfredo Cardigliano 				idev->dev_cmd->cmd.cmd.opcode,
2085ef51809SAlfredo Cardigliano 				elapsed_msec);
2095ef51809SAlfredo Cardigliano 			return 0;
2105ef51809SAlfredo Cardigliano 		}
2115ef51809SAlfredo Cardigliano 
2125ef51809SAlfredo Cardigliano 		msec_delay(step_msec);
2135ef51809SAlfredo Cardigliano 
2145ef51809SAlfredo Cardigliano 		elapsed_msec += step_msec;
2155ef51809SAlfredo Cardigliano 	} while (elapsed_msec < max_wait_msec);
2165ef51809SAlfredo Cardigliano 
2175ef51809SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs",
2185ef51809SAlfredo Cardigliano 		idev->dev_cmd->cmd.cmd.opcode,
2195ef51809SAlfredo Cardigliano 		elapsed_msec);
2205ef51809SAlfredo Cardigliano 
2215ef51809SAlfredo Cardigliano 	return -ETIMEDOUT;
2225ef51809SAlfredo Cardigliano }
2235ef51809SAlfredo Cardigliano 
2245ef51809SAlfredo Cardigliano static int
2255ef51809SAlfredo Cardigliano ionic_dev_cmd_check_error(struct ionic_dev *idev)
2265ef51809SAlfredo Cardigliano {
2275ef51809SAlfredo Cardigliano 	uint8_t status;
2285ef51809SAlfredo Cardigliano 
2295ef51809SAlfredo Cardigliano 	status = ionic_dev_cmd_status(idev);
2305ef51809SAlfredo Cardigliano 	if (status == 0)
2315ef51809SAlfredo Cardigliano 		return 0;
2325ef51809SAlfredo Cardigliano 
2335ef51809SAlfredo Cardigliano 	return -EIO;
2345ef51809SAlfredo Cardigliano }
2355ef51809SAlfredo Cardigliano 
2365ef51809SAlfredo Cardigliano int
2375ef51809SAlfredo Cardigliano ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait)
2385ef51809SAlfredo Cardigliano {
2395ef51809SAlfredo Cardigliano 	int err;
2405ef51809SAlfredo Cardigliano 
2415ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait(idev, max_wait);
2425ef51809SAlfredo Cardigliano 	if (err)
2435ef51809SAlfredo Cardigliano 		return err;
2445ef51809SAlfredo Cardigliano 
2455ef51809SAlfredo Cardigliano 	return ionic_dev_cmd_check_error(idev);
2465ef51809SAlfredo Cardigliano }
2475ef51809SAlfredo Cardigliano 
2485ef51809SAlfredo Cardigliano int
2495ef51809SAlfredo Cardigliano ionic_setup(struct ionic_adapter *adapter)
2505ef51809SAlfredo Cardigliano {
2515ef51809SAlfredo Cardigliano 	return ionic_dev_setup(adapter);
2525ef51809SAlfredo Cardigliano }
2535ef51809SAlfredo Cardigliano 
2545ef51809SAlfredo Cardigliano int
2555ef51809SAlfredo Cardigliano ionic_identify(struct ionic_adapter *adapter)
2565ef51809SAlfredo Cardigliano {
2575ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
2585ef51809SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
2595ef51809SAlfredo Cardigliano 	int err = 0;
2605ef51809SAlfredo Cardigliano 	uint32_t i;
2615ef51809SAlfredo Cardigliano 	unsigned int nwords;
2625ef51809SAlfredo Cardigliano 	uint32_t drv_size = sizeof(ident->drv.words) /
2635ef51809SAlfredo Cardigliano 		sizeof(ident->drv.words[0]);
2645ef51809SAlfredo Cardigliano 	uint32_t cmd_size = sizeof(idev->dev_cmd->data) /
2655ef51809SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
2665ef51809SAlfredo Cardigliano 	uint32_t dev_size = sizeof(ident->dev.words) /
2675ef51809SAlfredo Cardigliano 		sizeof(ident->dev.words[0]);
2685ef51809SAlfredo Cardigliano 
2695ef51809SAlfredo Cardigliano 	memset(ident, 0, sizeof(*ident));
2705ef51809SAlfredo Cardigliano 
2715ef51809SAlfredo Cardigliano 	ident->drv.os_type = IONIC_OS_TYPE_LINUX;
2725ef51809SAlfredo Cardigliano 	ident->drv.os_dist = 0;
2735ef51809SAlfredo Cardigliano 	snprintf(ident->drv.os_dist_str,
2745ef51809SAlfredo Cardigliano 		sizeof(ident->drv.os_dist_str), "Unknown");
2755ef51809SAlfredo Cardigliano 	ident->drv.kernel_ver = 0;
2765ef51809SAlfredo Cardigliano 	snprintf(ident->drv.kernel_ver_str,
2775ef51809SAlfredo Cardigliano 		sizeof(ident->drv.kernel_ver_str), "DPDK");
2785ef51809SAlfredo Cardigliano 	strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION,
2795ef51809SAlfredo Cardigliano 		sizeof(ident->drv.driver_ver_str) - 1);
2805ef51809SAlfredo Cardigliano 
2815ef51809SAlfredo Cardigliano 	nwords = RTE_MIN(drv_size, cmd_size);
2825ef51809SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
2835ef51809SAlfredo Cardigliano 		iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]);
2845ef51809SAlfredo Cardigliano 
2855ef51809SAlfredo Cardigliano 	ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1);
2865ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
2875ef51809SAlfredo Cardigliano 	if (!err) {
2885ef51809SAlfredo Cardigliano 		nwords = RTE_MIN(dev_size, cmd_size);
2895ef51809SAlfredo Cardigliano 		for (i = 0; i < nwords; i++)
2905ef51809SAlfredo Cardigliano 			ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]);
2915ef51809SAlfredo Cardigliano 	}
2925ef51809SAlfredo Cardigliano 
2935ef51809SAlfredo Cardigliano 	return err;
2945ef51809SAlfredo Cardigliano }
2955ef51809SAlfredo Cardigliano 
2965ef51809SAlfredo Cardigliano int
2975ef51809SAlfredo Cardigliano ionic_init(struct ionic_adapter *adapter)
2985ef51809SAlfredo Cardigliano {
2995ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
3005ef51809SAlfredo Cardigliano 	int err;
3015ef51809SAlfredo Cardigliano 
3025ef51809SAlfredo Cardigliano 	ionic_dev_cmd_init(idev);
3035ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
3045ef51809SAlfredo Cardigliano 	return err;
3055ef51809SAlfredo Cardigliano }
3065ef51809SAlfredo Cardigliano 
3075ef51809SAlfredo Cardigliano int
3085ef51809SAlfredo Cardigliano ionic_reset(struct ionic_adapter *adapter)
3095ef51809SAlfredo Cardigliano {
3105ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
3115ef51809SAlfredo Cardigliano 	int err;
3125ef51809SAlfredo Cardigliano 
3135ef51809SAlfredo Cardigliano 	ionic_dev_cmd_reset(idev);
3145ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
3155ef51809SAlfredo Cardigliano 	return err;
3165ef51809SAlfredo Cardigliano }
31723bf4ddbSAlfredo Cardigliano 
31823bf4ddbSAlfredo Cardigliano int
31923bf4ddbSAlfredo Cardigliano ionic_port_identify(struct ionic_adapter *adapter)
32023bf4ddbSAlfredo Cardigliano {
32123bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
32223bf4ddbSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
32323bf4ddbSAlfredo Cardigliano 	unsigned int port_words = sizeof(ident->port.words) /
32423bf4ddbSAlfredo Cardigliano 		sizeof(ident->port.words[0]);
32523bf4ddbSAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
32623bf4ddbSAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
32723bf4ddbSAlfredo Cardigliano 	unsigned int i;
32823bf4ddbSAlfredo Cardigliano 	unsigned int nwords;
32923bf4ddbSAlfredo Cardigliano 	int err;
33023bf4ddbSAlfredo Cardigliano 
33123bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_identify(idev);
33223bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
33323bf4ddbSAlfredo Cardigliano 	if (!err) {
33423bf4ddbSAlfredo Cardigliano 		nwords = RTE_MIN(port_words, cmd_words);
33523bf4ddbSAlfredo Cardigliano 		for (i = 0; i < nwords; i++)
33623bf4ddbSAlfredo Cardigliano 			ident->port.words[i] =
33723bf4ddbSAlfredo Cardigliano 				ioread32(&idev->dev_cmd->data[i]);
33823bf4ddbSAlfredo Cardigliano 	}
33923bf4ddbSAlfredo Cardigliano 
34023bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed);
34123bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu);
34223bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "state %d ", ident->port.config.state);
34323bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable);
34423bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type);
34523bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type);
34623bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "loopback_mode %d",
34723bf4ddbSAlfredo Cardigliano 		ident->port.config.loopback_mode);
34823bf4ddbSAlfredo Cardigliano 
34923bf4ddbSAlfredo Cardigliano 	return err;
35023bf4ddbSAlfredo Cardigliano }
35123bf4ddbSAlfredo Cardigliano 
35223bf4ddbSAlfredo Cardigliano static const struct rte_memzone *
35323bf4ddbSAlfredo Cardigliano ionic_memzone_reserve(const char *name, uint32_t len, int socket_id)
35423bf4ddbSAlfredo Cardigliano {
35523bf4ddbSAlfredo Cardigliano 	const struct rte_memzone *mz;
35623bf4ddbSAlfredo Cardigliano 
35723bf4ddbSAlfredo Cardigliano 	mz = rte_memzone_lookup(name);
35823bf4ddbSAlfredo Cardigliano 	if (mz)
35923bf4ddbSAlfredo Cardigliano 		return mz;
36023bf4ddbSAlfredo Cardigliano 
36123bf4ddbSAlfredo Cardigliano 	mz = rte_memzone_reserve_aligned(name, len, socket_id,
36223bf4ddbSAlfredo Cardigliano 		RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN);
36323bf4ddbSAlfredo Cardigliano 	return mz;
36423bf4ddbSAlfredo Cardigliano }
36523bf4ddbSAlfredo Cardigliano 
36623bf4ddbSAlfredo Cardigliano int
36723bf4ddbSAlfredo Cardigliano ionic_port_init(struct ionic_adapter *adapter)
36823bf4ddbSAlfredo Cardigliano {
36923bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
37023bf4ddbSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
37123bf4ddbSAlfredo Cardigliano 	char z_name[RTE_MEMZONE_NAMESIZE];
37223bf4ddbSAlfredo Cardigliano 	unsigned int config_words = sizeof(ident->port.config.words) /
37323bf4ddbSAlfredo Cardigliano 		sizeof(ident->port.config.words[0]);
37423bf4ddbSAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
37523bf4ddbSAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
37623bf4ddbSAlfredo Cardigliano 	unsigned int nwords;
37723bf4ddbSAlfredo Cardigliano 	unsigned int i;
37823bf4ddbSAlfredo Cardigliano 	int err;
37923bf4ddbSAlfredo Cardigliano 
38023bf4ddbSAlfredo Cardigliano 	if (idev->port_info)
38123bf4ddbSAlfredo Cardigliano 		return 0;
38223bf4ddbSAlfredo Cardigliano 
38323bf4ddbSAlfredo Cardigliano 	idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE);
38423bf4ddbSAlfredo Cardigliano 
38523bf4ddbSAlfredo Cardigliano 	snprintf(z_name, sizeof(z_name), "%s_port_%s_info",
38623bf4ddbSAlfredo Cardigliano 		IONIC_DRV_NAME,
38723bf4ddbSAlfredo Cardigliano 		adapter->pci_dev->device.name);
38823bf4ddbSAlfredo Cardigliano 
38923bf4ddbSAlfredo Cardigliano 	idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz,
39023bf4ddbSAlfredo Cardigliano 		SOCKET_ID_ANY);
39123bf4ddbSAlfredo Cardigliano 	if (!idev->port_info_z) {
39223bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve port info DMA memory");
39323bf4ddbSAlfredo Cardigliano 		return -ENOMEM;
39423bf4ddbSAlfredo Cardigliano 	}
39523bf4ddbSAlfredo Cardigliano 
39623bf4ddbSAlfredo Cardigliano 	idev->port_info = idev->port_info_z->addr;
39723bf4ddbSAlfredo Cardigliano 	idev->port_info_pa = idev->port_info_z->iova;
39823bf4ddbSAlfredo Cardigliano 
39923bf4ddbSAlfredo Cardigliano 	nwords = RTE_MIN(config_words, cmd_words);
40023bf4ddbSAlfredo Cardigliano 
40123bf4ddbSAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
40223bf4ddbSAlfredo Cardigliano 		iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]);
40323bf4ddbSAlfredo Cardigliano 
40423bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_init(idev);
40523bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
40623bf4ddbSAlfredo Cardigliano 	if (err) {
40723bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to init port");
40823bf4ddbSAlfredo Cardigliano 		return err;
40923bf4ddbSAlfredo Cardigliano 	}
41023bf4ddbSAlfredo Cardigliano 
41123bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
41223bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
41323bf4ddbSAlfredo Cardigliano 	if (err) {
41423bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port UP");
41523bf4ddbSAlfredo Cardigliano 		return err;
41623bf4ddbSAlfredo Cardigliano 	}
41723bf4ddbSAlfredo Cardigliano 
41823bf4ddbSAlfredo Cardigliano 	return 0;
41923bf4ddbSAlfredo Cardigliano }
42023bf4ddbSAlfredo Cardigliano 
42123bf4ddbSAlfredo Cardigliano int
42223bf4ddbSAlfredo Cardigliano ionic_port_reset(struct ionic_adapter *adapter)
42323bf4ddbSAlfredo Cardigliano {
42423bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
42523bf4ddbSAlfredo Cardigliano 	int err;
42623bf4ddbSAlfredo Cardigliano 
42723bf4ddbSAlfredo Cardigliano 	if (!idev->port_info)
42823bf4ddbSAlfredo Cardigliano 		return 0;
42923bf4ddbSAlfredo Cardigliano 
43023bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_reset(idev);
43123bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
43223bf4ddbSAlfredo Cardigliano 	if (err) {
43323bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to reset port");
43423bf4ddbSAlfredo Cardigliano 		return err;
43523bf4ddbSAlfredo Cardigliano 	}
43623bf4ddbSAlfredo Cardigliano 
43723bf4ddbSAlfredo Cardigliano 	idev->port_info = NULL;
43823bf4ddbSAlfredo Cardigliano 	idev->port_info_pa = 0;
43923bf4ddbSAlfredo Cardigliano 
44023bf4ddbSAlfredo Cardigliano 	return 0;
44123bf4ddbSAlfredo Cardigliano }
442