xref: /dpdk/drivers/net/ionic/ionic_main.c (revision 23bf4ddb3aff154b44da764d87d224bf0358748f)
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 
5*23bf4ddbSAlfredo Cardigliano #include <rte_memzone.h>
6*23bf4ddbSAlfredo Cardigliano 
75ef51809SAlfredo Cardigliano #include "ionic.h"
85ef51809SAlfredo Cardigliano 
95ef51809SAlfredo Cardigliano static int
105ef51809SAlfredo Cardigliano ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)
115ef51809SAlfredo Cardigliano {
125ef51809SAlfredo Cardigliano 	unsigned long step_msec = 100;
135ef51809SAlfredo Cardigliano 	unsigned int max_wait_msec = max_wait * 1000;
145ef51809SAlfredo Cardigliano 	unsigned long elapsed_msec = 0;
155ef51809SAlfredo Cardigliano 	int done;
165ef51809SAlfredo Cardigliano 
175ef51809SAlfredo Cardigliano 	/* Wait for dev cmd to complete.. but no more than max_wait sec */
185ef51809SAlfredo Cardigliano 
195ef51809SAlfredo Cardigliano 	do {
205ef51809SAlfredo Cardigliano 		done = ionic_dev_cmd_done(idev);
215ef51809SAlfredo Cardigliano 		if (done) {
225ef51809SAlfredo Cardigliano 			IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs",
235ef51809SAlfredo Cardigliano 				idev->dev_cmd->cmd.cmd.opcode,
245ef51809SAlfredo Cardigliano 				elapsed_msec);
255ef51809SAlfredo Cardigliano 			return 0;
265ef51809SAlfredo Cardigliano 		}
275ef51809SAlfredo Cardigliano 
285ef51809SAlfredo Cardigliano 		msec_delay(step_msec);
295ef51809SAlfredo Cardigliano 
305ef51809SAlfredo Cardigliano 		elapsed_msec += step_msec;
315ef51809SAlfredo Cardigliano 	} while (elapsed_msec < max_wait_msec);
325ef51809SAlfredo Cardigliano 
335ef51809SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs",
345ef51809SAlfredo Cardigliano 		idev->dev_cmd->cmd.cmd.opcode,
355ef51809SAlfredo Cardigliano 		elapsed_msec);
365ef51809SAlfredo Cardigliano 
375ef51809SAlfredo Cardigliano 	return -ETIMEDOUT;
385ef51809SAlfredo Cardigliano }
395ef51809SAlfredo Cardigliano 
405ef51809SAlfredo Cardigliano static int
415ef51809SAlfredo Cardigliano ionic_dev_cmd_check_error(struct ionic_dev *idev)
425ef51809SAlfredo Cardigliano {
435ef51809SAlfredo Cardigliano 	uint8_t status;
445ef51809SAlfredo Cardigliano 
455ef51809SAlfredo Cardigliano 	status = ionic_dev_cmd_status(idev);
465ef51809SAlfredo Cardigliano 	if (status == 0)
475ef51809SAlfredo Cardigliano 		return 0;
485ef51809SAlfredo Cardigliano 
495ef51809SAlfredo Cardigliano 	return -EIO;
505ef51809SAlfredo Cardigliano }
515ef51809SAlfredo Cardigliano 
525ef51809SAlfredo Cardigliano int
535ef51809SAlfredo Cardigliano ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait)
545ef51809SAlfredo Cardigliano {
555ef51809SAlfredo Cardigliano 	int err;
565ef51809SAlfredo Cardigliano 
575ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait(idev, max_wait);
585ef51809SAlfredo Cardigliano 	if (err)
595ef51809SAlfredo Cardigliano 		return err;
605ef51809SAlfredo Cardigliano 
615ef51809SAlfredo Cardigliano 	return ionic_dev_cmd_check_error(idev);
625ef51809SAlfredo Cardigliano }
635ef51809SAlfredo Cardigliano 
645ef51809SAlfredo Cardigliano int
655ef51809SAlfredo Cardigliano ionic_setup(struct ionic_adapter *adapter)
665ef51809SAlfredo Cardigliano {
675ef51809SAlfredo Cardigliano 	return ionic_dev_setup(adapter);
685ef51809SAlfredo Cardigliano }
695ef51809SAlfredo Cardigliano 
705ef51809SAlfredo Cardigliano int
715ef51809SAlfredo Cardigliano ionic_identify(struct ionic_adapter *adapter)
725ef51809SAlfredo Cardigliano {
735ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
745ef51809SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
755ef51809SAlfredo Cardigliano 	int err = 0;
765ef51809SAlfredo Cardigliano 	uint32_t i;
775ef51809SAlfredo Cardigliano 	unsigned int nwords;
785ef51809SAlfredo Cardigliano 	uint32_t drv_size = sizeof(ident->drv.words) /
795ef51809SAlfredo Cardigliano 		sizeof(ident->drv.words[0]);
805ef51809SAlfredo Cardigliano 	uint32_t cmd_size = sizeof(idev->dev_cmd->data) /
815ef51809SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
825ef51809SAlfredo Cardigliano 	uint32_t dev_size = sizeof(ident->dev.words) /
835ef51809SAlfredo Cardigliano 		sizeof(ident->dev.words[0]);
845ef51809SAlfredo Cardigliano 
855ef51809SAlfredo Cardigliano 	memset(ident, 0, sizeof(*ident));
865ef51809SAlfredo Cardigliano 
875ef51809SAlfredo Cardigliano 	ident->drv.os_type = IONIC_OS_TYPE_LINUX;
885ef51809SAlfredo Cardigliano 	ident->drv.os_dist = 0;
895ef51809SAlfredo Cardigliano 	snprintf(ident->drv.os_dist_str,
905ef51809SAlfredo Cardigliano 		sizeof(ident->drv.os_dist_str), "Unknown");
915ef51809SAlfredo Cardigliano 	ident->drv.kernel_ver = 0;
925ef51809SAlfredo Cardigliano 	snprintf(ident->drv.kernel_ver_str,
935ef51809SAlfredo Cardigliano 		sizeof(ident->drv.kernel_ver_str), "DPDK");
945ef51809SAlfredo Cardigliano 	strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION,
955ef51809SAlfredo Cardigliano 		sizeof(ident->drv.driver_ver_str) - 1);
965ef51809SAlfredo Cardigliano 
975ef51809SAlfredo Cardigliano 	nwords = RTE_MIN(drv_size, cmd_size);
985ef51809SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
995ef51809SAlfredo Cardigliano 		iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]);
1005ef51809SAlfredo Cardigliano 
1015ef51809SAlfredo Cardigliano 	ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1);
1025ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1035ef51809SAlfredo Cardigliano 	if (!err) {
1045ef51809SAlfredo Cardigliano 		nwords = RTE_MIN(dev_size, cmd_size);
1055ef51809SAlfredo Cardigliano 		for (i = 0; i < nwords; i++)
1065ef51809SAlfredo Cardigliano 			ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]);
1075ef51809SAlfredo Cardigliano 	}
1085ef51809SAlfredo Cardigliano 
1095ef51809SAlfredo Cardigliano 	return err;
1105ef51809SAlfredo Cardigliano }
1115ef51809SAlfredo Cardigliano 
1125ef51809SAlfredo Cardigliano int
1135ef51809SAlfredo Cardigliano ionic_init(struct ionic_adapter *adapter)
1145ef51809SAlfredo Cardigliano {
1155ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1165ef51809SAlfredo Cardigliano 	int err;
1175ef51809SAlfredo Cardigliano 
1185ef51809SAlfredo Cardigliano 	ionic_dev_cmd_init(idev);
1195ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1205ef51809SAlfredo Cardigliano 	return err;
1215ef51809SAlfredo Cardigliano }
1225ef51809SAlfredo Cardigliano 
1235ef51809SAlfredo Cardigliano int
1245ef51809SAlfredo Cardigliano ionic_reset(struct ionic_adapter *adapter)
1255ef51809SAlfredo Cardigliano {
1265ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1275ef51809SAlfredo Cardigliano 	int err;
1285ef51809SAlfredo Cardigliano 
1295ef51809SAlfredo Cardigliano 	ionic_dev_cmd_reset(idev);
1305ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1315ef51809SAlfredo Cardigliano 	return err;
1325ef51809SAlfredo Cardigliano }
133*23bf4ddbSAlfredo Cardigliano 
134*23bf4ddbSAlfredo Cardigliano int
135*23bf4ddbSAlfredo Cardigliano ionic_port_identify(struct ionic_adapter *adapter)
136*23bf4ddbSAlfredo Cardigliano {
137*23bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
138*23bf4ddbSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
139*23bf4ddbSAlfredo Cardigliano 	unsigned int port_words = sizeof(ident->port.words) /
140*23bf4ddbSAlfredo Cardigliano 		sizeof(ident->port.words[0]);
141*23bf4ddbSAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
142*23bf4ddbSAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
143*23bf4ddbSAlfredo Cardigliano 	unsigned int i;
144*23bf4ddbSAlfredo Cardigliano 	unsigned int nwords;
145*23bf4ddbSAlfredo Cardigliano 	int err;
146*23bf4ddbSAlfredo Cardigliano 
147*23bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_identify(idev);
148*23bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
149*23bf4ddbSAlfredo Cardigliano 	if (!err) {
150*23bf4ddbSAlfredo Cardigliano 		nwords = RTE_MIN(port_words, cmd_words);
151*23bf4ddbSAlfredo Cardigliano 		for (i = 0; i < nwords; i++)
152*23bf4ddbSAlfredo Cardigliano 			ident->port.words[i] =
153*23bf4ddbSAlfredo Cardigliano 				ioread32(&idev->dev_cmd->data[i]);
154*23bf4ddbSAlfredo Cardigliano 	}
155*23bf4ddbSAlfredo Cardigliano 
156*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed);
157*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu);
158*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "state %d ", ident->port.config.state);
159*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable);
160*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type);
161*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type);
162*23bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "loopback_mode %d",
163*23bf4ddbSAlfredo Cardigliano 		ident->port.config.loopback_mode);
164*23bf4ddbSAlfredo Cardigliano 
165*23bf4ddbSAlfredo Cardigliano 	return err;
166*23bf4ddbSAlfredo Cardigliano }
167*23bf4ddbSAlfredo Cardigliano 
168*23bf4ddbSAlfredo Cardigliano static const struct rte_memzone *
169*23bf4ddbSAlfredo Cardigliano ionic_memzone_reserve(const char *name, uint32_t len, int socket_id)
170*23bf4ddbSAlfredo Cardigliano {
171*23bf4ddbSAlfredo Cardigliano 	const struct rte_memzone *mz;
172*23bf4ddbSAlfredo Cardigliano 
173*23bf4ddbSAlfredo Cardigliano 	mz = rte_memzone_lookup(name);
174*23bf4ddbSAlfredo Cardigliano 	if (mz)
175*23bf4ddbSAlfredo Cardigliano 		return mz;
176*23bf4ddbSAlfredo Cardigliano 
177*23bf4ddbSAlfredo Cardigliano 	mz = rte_memzone_reserve_aligned(name, len, socket_id,
178*23bf4ddbSAlfredo Cardigliano 		RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN);
179*23bf4ddbSAlfredo Cardigliano 	return mz;
180*23bf4ddbSAlfredo Cardigliano }
181*23bf4ddbSAlfredo Cardigliano 
182*23bf4ddbSAlfredo Cardigliano int
183*23bf4ddbSAlfredo Cardigliano ionic_port_init(struct ionic_adapter *adapter)
184*23bf4ddbSAlfredo Cardigliano {
185*23bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
186*23bf4ddbSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
187*23bf4ddbSAlfredo Cardigliano 	char z_name[RTE_MEMZONE_NAMESIZE];
188*23bf4ddbSAlfredo Cardigliano 	unsigned int config_words = sizeof(ident->port.config.words) /
189*23bf4ddbSAlfredo Cardigliano 		sizeof(ident->port.config.words[0]);
190*23bf4ddbSAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
191*23bf4ddbSAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
192*23bf4ddbSAlfredo Cardigliano 	unsigned int nwords;
193*23bf4ddbSAlfredo Cardigliano 	unsigned int i;
194*23bf4ddbSAlfredo Cardigliano 	int err;
195*23bf4ddbSAlfredo Cardigliano 
196*23bf4ddbSAlfredo Cardigliano 	if (idev->port_info)
197*23bf4ddbSAlfredo Cardigliano 		return 0;
198*23bf4ddbSAlfredo Cardigliano 
199*23bf4ddbSAlfredo Cardigliano 	idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE);
200*23bf4ddbSAlfredo Cardigliano 
201*23bf4ddbSAlfredo Cardigliano 	snprintf(z_name, sizeof(z_name), "%s_port_%s_info",
202*23bf4ddbSAlfredo Cardigliano 		IONIC_DRV_NAME,
203*23bf4ddbSAlfredo Cardigliano 		adapter->pci_dev->device.name);
204*23bf4ddbSAlfredo Cardigliano 
205*23bf4ddbSAlfredo Cardigliano 	idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz,
206*23bf4ddbSAlfredo Cardigliano 		SOCKET_ID_ANY);
207*23bf4ddbSAlfredo Cardigliano 	if (!idev->port_info_z) {
208*23bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve port info DMA memory");
209*23bf4ddbSAlfredo Cardigliano 		return -ENOMEM;
210*23bf4ddbSAlfredo Cardigliano 	}
211*23bf4ddbSAlfredo Cardigliano 
212*23bf4ddbSAlfredo Cardigliano 	idev->port_info = idev->port_info_z->addr;
213*23bf4ddbSAlfredo Cardigliano 	idev->port_info_pa = idev->port_info_z->iova;
214*23bf4ddbSAlfredo Cardigliano 
215*23bf4ddbSAlfredo Cardigliano 	nwords = RTE_MIN(config_words, cmd_words);
216*23bf4ddbSAlfredo Cardigliano 
217*23bf4ddbSAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
218*23bf4ddbSAlfredo Cardigliano 		iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]);
219*23bf4ddbSAlfredo Cardigliano 
220*23bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_init(idev);
221*23bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
222*23bf4ddbSAlfredo Cardigliano 	if (err) {
223*23bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to init port");
224*23bf4ddbSAlfredo Cardigliano 		return err;
225*23bf4ddbSAlfredo Cardigliano 	}
226*23bf4ddbSAlfredo Cardigliano 
227*23bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
228*23bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
229*23bf4ddbSAlfredo Cardigliano 	if (err) {
230*23bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port UP");
231*23bf4ddbSAlfredo Cardigliano 		return err;
232*23bf4ddbSAlfredo Cardigliano 	}
233*23bf4ddbSAlfredo Cardigliano 
234*23bf4ddbSAlfredo Cardigliano 	return 0;
235*23bf4ddbSAlfredo Cardigliano }
236*23bf4ddbSAlfredo Cardigliano 
237*23bf4ddbSAlfredo Cardigliano int
238*23bf4ddbSAlfredo Cardigliano ionic_port_reset(struct ionic_adapter *adapter)
239*23bf4ddbSAlfredo Cardigliano {
240*23bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
241*23bf4ddbSAlfredo Cardigliano 	int err;
242*23bf4ddbSAlfredo Cardigliano 
243*23bf4ddbSAlfredo Cardigliano 	if (!idev->port_info)
244*23bf4ddbSAlfredo Cardigliano 		return 0;
245*23bf4ddbSAlfredo Cardigliano 
246*23bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_reset(idev);
247*23bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
248*23bf4ddbSAlfredo Cardigliano 	if (err) {
249*23bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to reset port");
250*23bf4ddbSAlfredo Cardigliano 		return err;
251*23bf4ddbSAlfredo Cardigliano 	}
252*23bf4ddbSAlfredo Cardigliano 
253*23bf4ddbSAlfredo Cardigliano 	idev->port_info = NULL;
254*23bf4ddbSAlfredo Cardigliano 	idev->port_info_pa = 0;
255*23bf4ddbSAlfredo Cardigliano 
256*23bf4ddbSAlfredo Cardigliano 	return 0;
257*23bf4ddbSAlfredo Cardigliano }
258